Message ID | 20171012202915.nokylct55mwg244b@lenoch (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi, Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki On 12/10/17 23:29, Ladislav Michl wrote: > Hi Roger, > > On Thu, Oct 12, 2017 at 06:05:31PM +0300, Roger Quadros wrote: > [snip] >> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki >> >> On 12/10/17 15:27, Ladislav Michl wrote: >>> Not being Tony, I try to answer anyway... >>> >>> I've done patchset which removes gpmc_probe_onenand_child and uses >>> gpmc_probe_generic_child (renamed to gpmc_probe_child) to setup OneNAND >>> async timings. Sync timings is setup from mtd/onenand/omap2.c after >>> chip frequency is known. >>> >>> I've not sent it yet as device datasheet is available under NDA only, >>> I do not have it and thus I'm left with equivalent source modifications >>> without really understanding what should be done and why. >>> >>> That said, I sent this patch to fix OneNAND support (for IGEPv2 board >>> at least) and leave discussion about making things nice for later. >>> >>> I'm proposing killing gpmc_onenand_data first and teaching OneNAND >>> to get its configuration from DT. Later I'll cleanup sync/async >>> patchset and send it for review unless someone is willing to take >>> it over to speed things up a bit - then I'll send it as it is :-) >> >> sounds fine to me. >>> >>> Side question: in tree OneNAND DT nodes are providing timing information. >>> I have no clue where this timing information is coming from and driver >>> completely ignores it and computes timings on its own. Any hints here? >> >> My guess is nobody has access to the datasheet and we're relying on bootloader >> set timings or timings that were already hardcoded in the kernel. >> >> You can use CONFIG_OMAP_GPMC_DEBUG to dump the timings set by the bootloader >> in DT format. >> >> You can also compare the timings before and after gpmc driver loads. > > That will not help a lot, as these questions will remain unanswered using > above method: > - why SYNC_WRITE cannot be used on 24xx? No idea. This is there right from the first commit. > - why are we letting gpio line settle only on 34xx? From commit 782b7a367d81da005d93b28cb00f9ae086773c24 "On OMAP3, the driver was occasionally not seeing the GPIO interrupt. Adding a small delay of one register read eliminates the problem." I guess this was a quick workaround to the problem faced by the early users of OneNand on OMAP3. > - why we are not using SYNC_WRITE with 54 MHz freq? I'm not sure. Seems to be in there from the first commit. > - how should be omap_onenand_platform_data flags set by default? > probably few more I do not remember, but will show up once I start > polishing patchset :) > > Anyway, here's first untested version, just to show, that we need > to touch arch/arm/mach-omap2/gpmc-onenand.c anyway, just to make > gpmc_onenand_setup directly callable without global > omap_onenand_platform_data (and later move it into omap-gpmc) Best to start a fresh thread with new patches. Patch looks in the right direction. > > So unless someone comes with better idea, I'll drop all global > variables from arch/arm/mach-omap2/gpmc-onenand.c and export > gpmc_onenand_setup to get rid of omap_onenand_platform_data. > After that patch gets merged, we can make additional patch on > top of following one, which will drop use of omap_onenand_platform_data > from omap2 onenand mtd driver. There are simply too many trees to > get things merged to make it easy task :-/ I understand it is a bit challenging. but we'll work it out. Main thing to keep in mind is to not break build in the different trees. So you might have to still keep some code around (especially platform data) but just mark it deprecated. > > Also note that no DT only kernel sets flags, regulator, gpio and yet > noone complained, so we could leave it for later - and use more recent > APIs (gpiolib, etc). At least nobody seems to be setting regulator and gpio in arch/arm/gpmc-onenand.c so probably things work without it for everyone. > > diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c > index 29cc0c21138c..85fac7aed2dc 100644 > --- a/drivers/mtd/onenand/omap2.c > +++ b/drivers/mtd/onenand/omap2.c > @@ -28,12 +28,15 @@ > #include <linux/mtd/mtd.h> > #include <linux/mtd/onenand.h> > #include <linux/mtd/partitions.h> > +#include <linux/of.h> > +#include <linux/of_device.h> > #include <linux/platform_device.h> > #include <linux/interrupt.h> > #include <linux/delay.h> > #include <linux/dma-mapping.h> > #include <linux/io.h> > #include <linux/slab.h> > +#include <linux/sys_soc.h> > #include <linux/regulator/consumer.h> > #include <linux/gpio.h> > > @@ -59,7 +62,7 @@ struct omap2_onenand { > int dma_channel; > int freq; > struct regulator *regulator; > - u8 flags; > + bool gpio_settle; > }; > > static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) > @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) > if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { > syscfg |= ONENAND_SYS_CFG1_IOBE; > write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); > - if (c->flags & ONENAND_IN_OMAP34XX) > + if (c->gpio_settle) > /* Add a delay to let GPIO settle */ > syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); > } > @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) > return ret; > } > > +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) > +{ > + struct device_node *child = dev->of_node; > + u32 cs, val; > + > + if (of_property_read_u32(child, "reg", &cs) < 0) { > + dev_err(dev, "reg not found in DT\n"); > + return -EINVAL; > + } > + c->gpmc_cs = cs; > + > + if (!of_property_read_u32(child, "dma-channel", &val)) > + c->dma_channel = val; > + else > + c->dma_channel = -1; > + > + /* TODO: gpio, regulator, unlocking */ > + > + return 0; > +} > + > +static const struct soc_device_attribute omap2_soc_devices[] = { > + { .family = "OMAP2*" }, > + { /* sentinel */ } > +}; > + Is this the preferred way of doing things? Tony? I was thinking that we could use separate compatible ids for omap2 vs omap3+ e.g. for omap2, compatible = "ti,omap2-onenand"; for omap3 onwards, compatible = "ti,omap3-onenand"; and use of_device_is_compatible() to do omap2 vs omap3 specific stuff. > static int omap2_onenand_probe(struct platform_device *pdev) > { > struct omap_onenand_platform_data *pdata; > @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) > if (!c) > return -ENOMEM; > > + r = omap2_onenand_get_dt(&pdev->dev, c); > + if (r) > + goto err_kfree; > + > init_completion(&c->irq_done); > init_completion(&c->dma_done); > - c->flags = pdata->flags; > - c->gpmc_cs = pdata->cs; > - c->gpio_irq = pdata->gpio_irq; > - c->dma_channel = pdata->dma_channel; > if (c->dma_channel < 0) { > /* if -1, don't use DMA */ > c->gpio_irq = 0; > @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) > c->mtd.priv = &c->onenand; > > c->mtd.dev.parent = &pdev->dev; > - mtd_set_of_node(&c->mtd, pdata->of_node); > + mtd_set_of_node(&c->mtd, pdev->dev.of_node); > > this = &c->onenand; > if (c->dma_channel >= 0) { > this->wait = omap2_onenand_wait; > - if (c->flags & ONENAND_IN_OMAP34XX) { > - this->read_bufferram = omap3_onenand_read_bufferram; > - this->write_bufferram = omap3_onenand_write_bufferram; > - } else { > + if (soc_device_match(omap2_soc_devices)) { > this->read_bufferram = omap2_onenand_read_bufferram; > this->write_bufferram = omap2_onenand_write_bufferram; > + } else { > + c->gpio_settle = true; > + this->read_bufferram = omap3_onenand_read_bufferram; > + this->write_bufferram = omap3_onenand_write_bufferram; > } > } > > - if (pdata->regulator_can_sleep) { > + if (0 /* TODO: pdata->regulator_can_sleep */) { > c->regulator = regulator_get(&pdev->dev, "vonenand"); > if (IS_ERR(c->regulator)) { > dev_err(&pdev->dev, "Failed to get regulator\n"); > @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) > c->onenand.disable = omap2_onenand_disable; > } > > - if (pdata->skip_initial_unlocking) > + if (0 /* TODO: pdata->skip_initial_unlocking */) > this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; This should be a standard onenand binding. Maybe Boris can recommend what to do here. > > if ((r = onenand_scan(&c->mtd, 1)) < 0) > goto err_release_regulator; > > - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, > - pdata ? pdata->nr_parts : 0); > + r = mtd_device_register(&c->mtd, NULL, 0); > if (r) > goto err_release_onenand; > > @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) > return 0; > } > > +static const struct of_device_id omap2_onenand_ids[] = { > + { .compatible = "ti,omap2-onenand", }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); > + > static struct platform_driver omap2_onenand_driver = { > .probe = omap2_onenand_probe, > .remove = omap2_onenand_remove, > .shutdown = omap2_onenand_shutdown, > .driver = { > .name = DRIVER_NAME, > + .of_match_table = of_match_ptr(omap2_onenand_ids), > }, > }; > >
Hi Roger! On Fri, Oct 13, 2017 at 11:52:44AM +0300, Roger Quadros wrote: > Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > > On 12/10/17 23:29, Ladislav Michl wrote: > > Hi Roger, > > > > On Thu, Oct 12, 2017 at 06:05:31PM +0300, Roger Quadros wrote: > > [snip] > >> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > >> > >> On 12/10/17 15:27, Ladislav Michl wrote: > >>> Not being Tony, I try to answer anyway... > >>> > >>> I've done patchset which removes gpmc_probe_onenand_child and uses > >>> gpmc_probe_generic_child (renamed to gpmc_probe_child) to setup OneNAND > >>> async timings. Sync timings is setup from mtd/onenand/omap2.c after > >>> chip frequency is known. > >>> > >>> I've not sent it yet as device datasheet is available under NDA only, > >>> I do not have it and thus I'm left with equivalent source modifications > >>> without really understanding what should be done and why. > >>> > >>> That said, I sent this patch to fix OneNAND support (for IGEPv2 board > >>> at least) and leave discussion about making things nice for later. > >>> > >>> I'm proposing killing gpmc_onenand_data first and teaching OneNAND > >>> to get its configuration from DT. Later I'll cleanup sync/async > >>> patchset and send it for review unless someone is willing to take > >>> it over to speed things up a bit - then I'll send it as it is :-) > >> > >> sounds fine to me. > >>> > >>> Side question: in tree OneNAND DT nodes are providing timing information. > >>> I have no clue where this timing information is coming from and driver > >>> completely ignores it and computes timings on its own. Any hints here? > >> > >> My guess is nobody has access to the datasheet and we're relying on bootloader > >> set timings or timings that were already hardcoded in the kernel. > >> > >> You can use CONFIG_OMAP_GPMC_DEBUG to dump the timings set by the bootloader > >> in DT format. > >> > >> You can also compare the timings before and after gpmc driver loads. > > > > That will not help a lot, as these questions will remain unanswered using > > above method: > > - why SYNC_WRITE cannot be used on 24xx? > > No idea. This is there right from the first commit. Okay. Lets leave this on DT and remove it from code. That code path is not currently used anyway. > > - why are we letting gpio line settle only on 34xx? > > >From commit 782b7a367d81da005d93b28cb00f9ae086773c24 > > "On OMAP3, the driver was occasionally not seeing the GPIO > interrupt. Adding a small delay of one register read > eliminates the problem." > > I guess this was a quick workaround to the problem faced by the early users > of OneNand on OMAP3. > > > - why we are not using SYNC_WRITE with 54 MHz freq? > > I'm not sure. Seems to be in there from the first commit. > > > - how should be omap_onenand_platform_data flags set by default? > > probably few more I do not remember, but will show up once I start > > polishing patchset :) > > > > Anyway, here's first untested version, just to show, that we need > > to touch arch/arm/mach-omap2/gpmc-onenand.c anyway, just to make > > gpmc_onenand_setup directly callable without global > > omap_onenand_platform_data (and later move it into omap-gpmc) > > Best to start a fresh thread with new patches. Patch looks in the right direction. > > > > > So unless someone comes with better idea, I'll drop all global > > variables from arch/arm/mach-omap2/gpmc-onenand.c and export > > gpmc_onenand_setup to get rid of omap_onenand_platform_data. > > After that patch gets merged, we can make additional patch on > > top of following one, which will drop use of omap_onenand_platform_data > > from omap2 onenand mtd driver. There are simply too many trees to > > get things merged to make it easy task :-/ > > I understand it is a bit challenging. but we'll work it out. Main thing to > keep in mind is to not break build in the different trees. So you might have to > still keep some code around (especially platform data) but just mark it deprecated. Okay, lets start separate thread with patchset. It seems it's doable after all :-) > > Also note that no DT only kernel sets flags, regulator, gpio and yet > > noone complained, so we could leave it for later - and use more recent > > APIs (gpiolib, etc). > > At least nobody seems to be setting regulator and gpio in arch/arm/gpmc-onenand.c > so probably things work without it for everyone. > > > > > diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c > > index 29cc0c21138c..85fac7aed2dc 100644 > > --- a/drivers/mtd/onenand/omap2.c > > +++ b/drivers/mtd/onenand/omap2.c > > @@ -28,12 +28,15 @@ > > #include <linux/mtd/mtd.h> > > #include <linux/mtd/onenand.h> > > #include <linux/mtd/partitions.h> > > +#include <linux/of.h> > > +#include <linux/of_device.h> > > #include <linux/platform_device.h> > > #include <linux/interrupt.h> > > #include <linux/delay.h> > > #include <linux/dma-mapping.h> > > #include <linux/io.h> > > #include <linux/slab.h> > > +#include <linux/sys_soc.h> > > #include <linux/regulator/consumer.h> > > #include <linux/gpio.h> > > > > @@ -59,7 +62,7 @@ struct omap2_onenand { > > int dma_channel; > > int freq; > > struct regulator *regulator; > > - u8 flags; > > + bool gpio_settle; > > }; > > > > static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) > > @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) > > if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { > > syscfg |= ONENAND_SYS_CFG1_IOBE; > > write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); > > - if (c->flags & ONENAND_IN_OMAP34XX) > > + if (c->gpio_settle) > > /* Add a delay to let GPIO settle */ > > syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); > > } > > @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) > > return ret; > > } > > > > +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) > > +{ > > + struct device_node *child = dev->of_node; > > + u32 cs, val; > > + > > + if (of_property_read_u32(child, "reg", &cs) < 0) { > > + dev_err(dev, "reg not found in DT\n"); > > + return -EINVAL; > > + } > > + c->gpmc_cs = cs; > > + > > + if (!of_property_read_u32(child, "dma-channel", &val)) > > + c->dma_channel = val; > > + else > > + c->dma_channel = -1; > > + > > + /* TODO: gpio, regulator, unlocking */ > > + > > + return 0; > > +} > > + > > +static const struct soc_device_attribute omap2_soc_devices[] = { > > + { .family = "OMAP2*" }, > > + { /* sentinel */ } > > +}; > > + > > Is this the preferred way of doing things? Tony? > I was thinking that we could use separate compatible ids for omap2 vs omap3+ > e.g. > > for omap2, compatible = "ti,omap2-onenand"; > for omap3 onwards, compatible = "ti,omap3-onenand"; > > and use of_device_is_compatible() to do omap2 vs omap3 specific stuff. Well, the problem is that there are 'compatible = "ti,omap2-onenand"' DTs around for OMAP3 devices such as Nokia 8x0 AFAIR. Anyway, I'm also interested what preferred solution is. Once revealed I'll send proper patch. > > static int omap2_onenand_probe(struct platform_device *pdev) > > { > > struct omap_onenand_platform_data *pdata; > > @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) > > if (!c) > > return -ENOMEM; > > > > + r = omap2_onenand_get_dt(&pdev->dev, c); > > + if (r) > > + goto err_kfree; > > + > > init_completion(&c->irq_done); > > init_completion(&c->dma_done); > > - c->flags = pdata->flags; > > - c->gpmc_cs = pdata->cs; > > - c->gpio_irq = pdata->gpio_irq; > > - c->dma_channel = pdata->dma_channel; > > if (c->dma_channel < 0) { > > /* if -1, don't use DMA */ > > c->gpio_irq = 0; > > @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) > > c->mtd.priv = &c->onenand; > > > > c->mtd.dev.parent = &pdev->dev; > > - mtd_set_of_node(&c->mtd, pdata->of_node); > > + mtd_set_of_node(&c->mtd, pdev->dev.of_node); > > > > this = &c->onenand; > > if (c->dma_channel >= 0) { > > this->wait = omap2_onenand_wait; > > - if (c->flags & ONENAND_IN_OMAP34XX) { > > - this->read_bufferram = omap3_onenand_read_bufferram; > > - this->write_bufferram = omap3_onenand_write_bufferram; > > - } else { > > + if (soc_device_match(omap2_soc_devices)) { > > this->read_bufferram = omap2_onenand_read_bufferram; > > this->write_bufferram = omap2_onenand_write_bufferram; > > + } else { > > + c->gpio_settle = true; > > + this->read_bufferram = omap3_onenand_read_bufferram; > > + this->write_bufferram = omap3_onenand_write_bufferram; > > } > > } > > > > - if (pdata->regulator_can_sleep) { > > + if (0 /* TODO: pdata->regulator_can_sleep */) { > > c->regulator = regulator_get(&pdev->dev, "vonenand"); > > if (IS_ERR(c->regulator)) { > > dev_err(&pdev->dev, "Failed to get regulator\n"); > > @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) > > c->onenand.disable = omap2_onenand_disable; > > } > > > > - if (pdata->skip_initial_unlocking) > > + if (0 /* TODO: pdata->skip_initial_unlocking */) > > this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; > > This should be a standard onenand binding. Maybe Boris can recommend what to do here. > > > > > if ((r = onenand_scan(&c->mtd, 1)) < 0) > > goto err_release_regulator; > > > > - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, > > - pdata ? pdata->nr_parts : 0); > > + r = mtd_device_register(&c->mtd, NULL, 0); > > if (r) > > goto err_release_onenand; > > > > @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) > > return 0; > > } > > > > +static const struct of_device_id omap2_onenand_ids[] = { > > + { .compatible = "ti,omap2-onenand", }, > > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); > > + > > static struct platform_driver omap2_onenand_driver = { > > .probe = omap2_onenand_probe, > > .remove = omap2_onenand_remove, > > .shutdown = omap2_onenand_shutdown, > > .driver = { > > .name = DRIVER_NAME, > > + .of_match_table = of_match_ptr(omap2_onenand_ids), > > }, > > }; > > > > > > -- > cheers, > -roger -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Ladislav, Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki On 13/10/17 15:05, Ladislav Michl wrote: > Hi Roger! > > On Fri, Oct 13, 2017 at 11:52:44AM +0300, Roger Quadros wrote: >> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki >> >> On 12/10/17 23:29, Ladislav Michl wrote: >>> Hi Roger, >>> >>> On Thu, Oct 12, 2017 at 06:05:31PM +0300, Roger Quadros wrote: >>> [snip] >>>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki >>>> >>>> On 12/10/17 15:27, Ladislav Michl wrote: >>>>> Not being Tony, I try to answer anyway... >>>>> >>>>> I've done patchset which removes gpmc_probe_onenand_child and uses >>>>> gpmc_probe_generic_child (renamed to gpmc_probe_child) to setup OneNAND >>>>> async timings. Sync timings is setup from mtd/onenand/omap2.c after >>>>> chip frequency is known. >>>>> >>>>> I've not sent it yet as device datasheet is available under NDA only, >>>>> I do not have it and thus I'm left with equivalent source modifications >>>>> without really understanding what should be done and why. >>>>> >>>>> That said, I sent this patch to fix OneNAND support (for IGEPv2 board >>>>> at least) and leave discussion about making things nice for later. >>>>> >>>>> I'm proposing killing gpmc_onenand_data first and teaching OneNAND >>>>> to get its configuration from DT. Later I'll cleanup sync/async >>>>> patchset and send it for review unless someone is willing to take >>>>> it over to speed things up a bit - then I'll send it as it is :-) >>>> >>>> sounds fine to me. >>>>> >>>>> Side question: in tree OneNAND DT nodes are providing timing information. >>>>> I have no clue where this timing information is coming from and driver >>>>> completely ignores it and computes timings on its own. Any hints here? >>>> >>>> My guess is nobody has access to the datasheet and we're relying on bootloader >>>> set timings or timings that were already hardcoded in the kernel. >>>> >>>> You can use CONFIG_OMAP_GPMC_DEBUG to dump the timings set by the bootloader >>>> in DT format. >>>> >>>> You can also compare the timings before and after gpmc driver loads. >>> >>> That will not help a lot, as these questions will remain unanswered using >>> above method: >>> - why SYNC_WRITE cannot be used on 24xx? >> >> No idea. This is there right from the first commit. > > Okay. Lets leave this on DT and remove it from code. That code > path is not currently used anyway. > >>> - why are we letting gpio line settle only on 34xx? >> >> >From commit 782b7a367d81da005d93b28cb00f9ae086773c24 >> >> "On OMAP3, the driver was occasionally not seeing the GPIO >> interrupt. Adding a small delay of one register read >> eliminates the problem." >> >> I guess this was a quick workaround to the problem faced by the early users >> of OneNand on OMAP3. >> >>> - why we are not using SYNC_WRITE with 54 MHz freq? >> >> I'm not sure. Seems to be in there from the first commit. >> >>> - how should be omap_onenand_platform_data flags set by default? >>> probably few more I do not remember, but will show up once I start >>> polishing patchset :) >>> >>> Anyway, here's first untested version, just to show, that we need >>> to touch arch/arm/mach-omap2/gpmc-onenand.c anyway, just to make >>> gpmc_onenand_setup directly callable without global >>> omap_onenand_platform_data (and later move it into omap-gpmc) >> >> Best to start a fresh thread with new patches. Patch looks in the right direction. >> >>> >>> So unless someone comes with better idea, I'll drop all global >>> variables from arch/arm/mach-omap2/gpmc-onenand.c and export >>> gpmc_onenand_setup to get rid of omap_onenand_platform_data. >>> After that patch gets merged, we can make additional patch on >>> top of following one, which will drop use of omap_onenand_platform_data >>> from omap2 onenand mtd driver. There are simply too many trees to >>> get things merged to make it easy task :-/ >> >> I understand it is a bit challenging. but we'll work it out. Main thing to >> keep in mind is to not break build in the different trees. So you might have to >> still keep some code around (especially platform data) but just mark it deprecated. > > Okay, lets start separate thread with patchset. It seems it's doable after > all :-) > >>> Also note that no DT only kernel sets flags, regulator, gpio and yet >>> noone complained, so we could leave it for later - and use more recent >>> APIs (gpiolib, etc). >> >> At least nobody seems to be setting regulator and gpio in arch/arm/gpmc-onenand.c >> so probably things work without it for everyone. >> >>> >>> diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c >>> index 29cc0c21138c..85fac7aed2dc 100644 >>> --- a/drivers/mtd/onenand/omap2.c >>> +++ b/drivers/mtd/onenand/omap2.c >>> @@ -28,12 +28,15 @@ >>> #include <linux/mtd/mtd.h> >>> #include <linux/mtd/onenand.h> >>> #include <linux/mtd/partitions.h> >>> +#include <linux/of.h> >>> +#include <linux/of_device.h> >>> #include <linux/platform_device.h> >>> #include <linux/interrupt.h> >>> #include <linux/delay.h> >>> #include <linux/dma-mapping.h> >>> #include <linux/io.h> >>> #include <linux/slab.h> >>> +#include <linux/sys_soc.h> >>> #include <linux/regulator/consumer.h> >>> #include <linux/gpio.h> >>> >>> @@ -59,7 +62,7 @@ struct omap2_onenand { >>> int dma_channel; >>> int freq; >>> struct regulator *regulator; >>> - u8 flags; >>> + bool gpio_settle; >>> }; >>> >>> static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) >>> @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) >>> if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { >>> syscfg |= ONENAND_SYS_CFG1_IOBE; >>> write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); >>> - if (c->flags & ONENAND_IN_OMAP34XX) >>> + if (c->gpio_settle) >>> /* Add a delay to let GPIO settle */ >>> syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); >>> } >>> @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) >>> return ret; >>> } >>> >>> +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) >>> +{ >>> + struct device_node *child = dev->of_node; >>> + u32 cs, val; >>> + >>> + if (of_property_read_u32(child, "reg", &cs) < 0) { >>> + dev_err(dev, "reg not found in DT\n"); >>> + return -EINVAL; >>> + } >>> + c->gpmc_cs = cs; >>> + >>> + if (!of_property_read_u32(child, "dma-channel", &val)) >>> + c->dma_channel = val; >>> + else >>> + c->dma_channel = -1; >>> + >>> + /* TODO: gpio, regulator, unlocking */ >>> + >>> + return 0; >>> +} >>> + >>> +static const struct soc_device_attribute omap2_soc_devices[] = { >>> + { .family = "OMAP2*" }, >>> + { /* sentinel */ } >>> +}; >>> + >> >> Is this the preferred way of doing things? Tony? >> I was thinking that we could use separate compatible ids for omap2 vs omap3+ >> e.g. >> >> for omap2, compatible = "ti,omap2-onenand"; >> for omap3 onwards, compatible = "ti,omap3-onenand"; >> >> and use of_device_is_compatible() to do omap2 vs omap3 specific stuff. > > Well, the problem is that there are 'compatible = "ti,omap2-onenand"' DTs > around for OMAP3 devices such as Nokia 8x0 AFAIR. Nokia n8xx devices are all OMAP2 based and can continu use ti,omap2-onenand. Nokia n9xx devices are all OMAP3 based so need to use ti,omap3-onenand. It shouldn't be a big problem to add a new binding. > > Anyway, I'm also interested what preferred solution is. Once revealed I'll send > proper patch. > >>> static int omap2_onenand_probe(struct platform_device *pdev) >>> { >>> struct omap_onenand_platform_data *pdata; >>> @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) >>> if (!c) >>> return -ENOMEM; >>> >>> + r = omap2_onenand_get_dt(&pdev->dev, c); >>> + if (r) >>> + goto err_kfree; >>> + >>> init_completion(&c->irq_done); >>> init_completion(&c->dma_done); >>> - c->flags = pdata->flags; >>> - c->gpmc_cs = pdata->cs; >>> - c->gpio_irq = pdata->gpio_irq; >>> - c->dma_channel = pdata->dma_channel; >>> if (c->dma_channel < 0) { >>> /* if -1, don't use DMA */ >>> c->gpio_irq = 0; >>> @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) >>> c->mtd.priv = &c->onenand; >>> >>> c->mtd.dev.parent = &pdev->dev; >>> - mtd_set_of_node(&c->mtd, pdata->of_node); >>> + mtd_set_of_node(&c->mtd, pdev->dev.of_node); >>> >>> this = &c->onenand; >>> if (c->dma_channel >= 0) { >>> this->wait = omap2_onenand_wait; >>> - if (c->flags & ONENAND_IN_OMAP34XX) { >>> - this->read_bufferram = omap3_onenand_read_bufferram; >>> - this->write_bufferram = omap3_onenand_write_bufferram; >>> - } else { >>> + if (soc_device_match(omap2_soc_devices)) { >>> this->read_bufferram = omap2_onenand_read_bufferram; >>> this->write_bufferram = omap2_onenand_write_bufferram; >>> + } else { >>> + c->gpio_settle = true; >>> + this->read_bufferram = omap3_onenand_read_bufferram; >>> + this->write_bufferram = omap3_onenand_write_bufferram; >>> } >>> } >>> >>> - if (pdata->regulator_can_sleep) { >>> + if (0 /* TODO: pdata->regulator_can_sleep */) { >>> c->regulator = regulator_get(&pdev->dev, "vonenand"); >>> if (IS_ERR(c->regulator)) { >>> dev_err(&pdev->dev, "Failed to get regulator\n"); >>> @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) >>> c->onenand.disable = omap2_onenand_disable; >>> } >>> >>> - if (pdata->skip_initial_unlocking) >>> + if (0 /* TODO: pdata->skip_initial_unlocking */) >>> this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; >> >> This should be a standard onenand binding. Maybe Boris can recommend what to do here. >> >>> >>> if ((r = onenand_scan(&c->mtd, 1)) < 0) >>> goto err_release_regulator; >>> >>> - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, >>> - pdata ? pdata->nr_parts : 0); >>> + r = mtd_device_register(&c->mtd, NULL, 0); >>> if (r) >>> goto err_release_onenand; >>> >>> @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) >>> return 0; >>> } >>> >>> +static const struct of_device_id omap2_onenand_ids[] = { >>> + { .compatible = "ti,omap2-onenand", }, >>> + {}, >>> +}; >>> +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); >>> + >>> static struct platform_driver omap2_onenand_driver = { >>> .probe = omap2_onenand_probe, >>> .remove = omap2_onenand_remove, >>> .shutdown = omap2_onenand_shutdown, >>> .driver = { >>> .name = DRIVER_NAME, >>> + .of_match_table = of_match_ptr(omap2_onenand_ids), >>> }, >>> }; >>> >>> >> >> -- >> cheers, >> -roger > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >
Hi Roger, On Fri, Oct 13, 2017 at 03:11:37PM +0300, Roger Quadros wrote: > Ladislav, > > Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > > On 13/10/17 15:05, Ladislav Michl wrote: > > Hi Roger! > > > > On Fri, Oct 13, 2017 at 11:52:44AM +0300, Roger Quadros wrote: > >> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > >> > >> On 12/10/17 23:29, Ladislav Michl wrote: > >>> Hi Roger, > >>> > >>> On Thu, Oct 12, 2017 at 06:05:31PM +0300, Roger Quadros wrote: > >>> [snip] > >>>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > >>>> > >>>> On 12/10/17 15:27, Ladislav Michl wrote: > >>>>> Not being Tony, I try to answer anyway... > >>>>> > >>>>> I've done patchset which removes gpmc_probe_onenand_child and uses > >>>>> gpmc_probe_generic_child (renamed to gpmc_probe_child) to setup OneNAND > >>>>> async timings. Sync timings is setup from mtd/onenand/omap2.c after > >>>>> chip frequency is known. > >>>>> > >>>>> I've not sent it yet as device datasheet is available under NDA only, > >>>>> I do not have it and thus I'm left with equivalent source modifications > >>>>> without really understanding what should be done and why. > >>>>> > >>>>> That said, I sent this patch to fix OneNAND support (for IGEPv2 board > >>>>> at least) and leave discussion about making things nice for later. > >>>>> > >>>>> I'm proposing killing gpmc_onenand_data first and teaching OneNAND > >>>>> to get its configuration from DT. Later I'll cleanup sync/async > >>>>> patchset and send it for review unless someone is willing to take > >>>>> it over to speed things up a bit - then I'll send it as it is :-) > >>>> > >>>> sounds fine to me. > >>>>> > >>>>> Side question: in tree OneNAND DT nodes are providing timing information. > >>>>> I have no clue where this timing information is coming from and driver > >>>>> completely ignores it and computes timings on its own. Any hints here? > >>>> > >>>> My guess is nobody has access to the datasheet and we're relying on bootloader > >>>> set timings or timings that were already hardcoded in the kernel. > >>>> > >>>> You can use CONFIG_OMAP_GPMC_DEBUG to dump the timings set by the bootloader > >>>> in DT format. > >>>> > >>>> You can also compare the timings before and after gpmc driver loads. > >>> > >>> That will not help a lot, as these questions will remain unanswered using > >>> above method: > >>> - why SYNC_WRITE cannot be used on 24xx? > >> > >> No idea. This is there right from the first commit. > > > > Okay. Lets leave this on DT and remove it from code. That code > > path is not currently used anyway. > > > >>> - why are we letting gpio line settle only on 34xx? > >> > >> >From commit 782b7a367d81da005d93b28cb00f9ae086773c24 > >> > >> "On OMAP3, the driver was occasionally not seeing the GPIO > >> interrupt. Adding a small delay of one register read > >> eliminates the problem." > >> > >> I guess this was a quick workaround to the problem faced by the early users > >> of OneNand on OMAP3. > >> > >>> - why we are not using SYNC_WRITE with 54 MHz freq? > >> > >> I'm not sure. Seems to be in there from the first commit. > >> > >>> - how should be omap_onenand_platform_data flags set by default? > >>> probably few more I do not remember, but will show up once I start > >>> polishing patchset :) > >>> > >>> Anyway, here's first untested version, just to show, that we need > >>> to touch arch/arm/mach-omap2/gpmc-onenand.c anyway, just to make > >>> gpmc_onenand_setup directly callable without global > >>> omap_onenand_platform_data (and later move it into omap-gpmc) > >> > >> Best to start a fresh thread with new patches. Patch looks in the right direction. > >> > >>> > >>> So unless someone comes with better idea, I'll drop all global > >>> variables from arch/arm/mach-omap2/gpmc-onenand.c and export > >>> gpmc_onenand_setup to get rid of omap_onenand_platform_data. > >>> After that patch gets merged, we can make additional patch on > >>> top of following one, which will drop use of omap_onenand_platform_data > >>> from omap2 onenand mtd driver. There are simply too many trees to > >>> get things merged to make it easy task :-/ > >> > >> I understand it is a bit challenging. but we'll work it out. Main thing to > >> keep in mind is to not break build in the different trees. So you might have to > >> still keep some code around (especially platform data) but just mark it deprecated. > > > > Okay, lets start separate thread with patchset. It seems it's doable after > > all :-) > > > >>> Also note that no DT only kernel sets flags, regulator, gpio and yet > >>> noone complained, so we could leave it for later - and use more recent > >>> APIs (gpiolib, etc). > >> > >> At least nobody seems to be setting regulator and gpio in arch/arm/gpmc-onenand.c > >> so probably things work without it for everyone. > >> > >>> > >>> diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c > >>> index 29cc0c21138c..85fac7aed2dc 100644 > >>> --- a/drivers/mtd/onenand/omap2.c > >>> +++ b/drivers/mtd/onenand/omap2.c > >>> @@ -28,12 +28,15 @@ > >>> #include <linux/mtd/mtd.h> > >>> #include <linux/mtd/onenand.h> > >>> #include <linux/mtd/partitions.h> > >>> +#include <linux/of.h> > >>> +#include <linux/of_device.h> > >>> #include <linux/platform_device.h> > >>> #include <linux/interrupt.h> > >>> #include <linux/delay.h> > >>> #include <linux/dma-mapping.h> > >>> #include <linux/io.h> > >>> #include <linux/slab.h> > >>> +#include <linux/sys_soc.h> > >>> #include <linux/regulator/consumer.h> > >>> #include <linux/gpio.h> > >>> > >>> @@ -59,7 +62,7 @@ struct omap2_onenand { > >>> int dma_channel; > >>> int freq; > >>> struct regulator *regulator; > >>> - u8 flags; > >>> + bool gpio_settle; > >>> }; > >>> > >>> static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) > >>> @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) > >>> if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { > >>> syscfg |= ONENAND_SYS_CFG1_IOBE; > >>> write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); > >>> - if (c->flags & ONENAND_IN_OMAP34XX) > >>> + if (c->gpio_settle) > >>> /* Add a delay to let GPIO settle */ > >>> syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); > >>> } > >>> @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) > >>> return ret; > >>> } > >>> > >>> +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) > >>> +{ > >>> + struct device_node *child = dev->of_node; > >>> + u32 cs, val; > >>> + > >>> + if (of_property_read_u32(child, "reg", &cs) < 0) { > >>> + dev_err(dev, "reg not found in DT\n"); > >>> + return -EINVAL; > >>> + } > >>> + c->gpmc_cs = cs; > >>> + > >>> + if (!of_property_read_u32(child, "dma-channel", &val)) > >>> + c->dma_channel = val; > >>> + else > >>> + c->dma_channel = -1; > >>> + > >>> + /* TODO: gpio, regulator, unlocking */ > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +static const struct soc_device_attribute omap2_soc_devices[] = { > >>> + { .family = "OMAP2*" }, > >>> + { /* sentinel */ } > >>> +}; > >>> + > >> > >> Is this the preferred way of doing things? Tony? > >> I was thinking that we could use separate compatible ids for omap2 vs omap3+ > >> e.g. > >> > >> for omap2, compatible = "ti,omap2-onenand"; > >> for omap3 onwards, compatible = "ti,omap3-onenand"; > >> > >> and use of_device_is_compatible() to do omap2 vs omap3 specific stuff. > > > > Well, the problem is that there are 'compatible = "ti,omap2-onenand"' DTs > > around for OMAP3 devices such as Nokia 8x0 AFAIR. > > Nokia n8xx devices are all OMAP2 based and can continu use ti,omap2-onenand. > Nokia n9xx devices are all OMAP3 based so need to use ti,omap3-onenand. It shouldn't > be a big problem to add a new binding. Quick grep arch/arm/boot/dts finds omap3-n950-n9.dtsi, but there is no compatible property as well as there is not any in omap2420-n8x0-common.dtsi. We could probably warn and bail out as we do in NAND case, but it would break backward compatibility. Pavel? Another user is IGEP board, but as it is broken in mainline anyway and I'm probably the only mainline user, it is not a big deal ;-) > > Anyway, I'm also interested what preferred solution is. Once revealed I'll send > > proper patch. > > > >>> static int omap2_onenand_probe(struct platform_device *pdev) > >>> { > >>> struct omap_onenand_platform_data *pdata; > >>> @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) > >>> if (!c) > >>> return -ENOMEM; > >>> > >>> + r = omap2_onenand_get_dt(&pdev->dev, c); > >>> + if (r) > >>> + goto err_kfree; > >>> + > >>> init_completion(&c->irq_done); > >>> init_completion(&c->dma_done); > >>> - c->flags = pdata->flags; > >>> - c->gpmc_cs = pdata->cs; > >>> - c->gpio_irq = pdata->gpio_irq; > >>> - c->dma_channel = pdata->dma_channel; > >>> if (c->dma_channel < 0) { > >>> /* if -1, don't use DMA */ > >>> c->gpio_irq = 0; > >>> @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) > >>> c->mtd.priv = &c->onenand; > >>> > >>> c->mtd.dev.parent = &pdev->dev; > >>> - mtd_set_of_node(&c->mtd, pdata->of_node); > >>> + mtd_set_of_node(&c->mtd, pdev->dev.of_node); > >>> > >>> this = &c->onenand; > >>> if (c->dma_channel >= 0) { > >>> this->wait = omap2_onenand_wait; > >>> - if (c->flags & ONENAND_IN_OMAP34XX) { > >>> - this->read_bufferram = omap3_onenand_read_bufferram; > >>> - this->write_bufferram = omap3_onenand_write_bufferram; > >>> - } else { > >>> + if (soc_device_match(omap2_soc_devices)) { > >>> this->read_bufferram = omap2_onenand_read_bufferram; > >>> this->write_bufferram = omap2_onenand_write_bufferram; > >>> + } else { > >>> + c->gpio_settle = true; > >>> + this->read_bufferram = omap3_onenand_read_bufferram; > >>> + this->write_bufferram = omap3_onenand_write_bufferram; > >>> } > >>> } > >>> > >>> - if (pdata->regulator_can_sleep) { > >>> + if (0 /* TODO: pdata->regulator_can_sleep */) { > >>> c->regulator = regulator_get(&pdev->dev, "vonenand"); > >>> if (IS_ERR(c->regulator)) { > >>> dev_err(&pdev->dev, "Failed to get regulator\n"); > >>> @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) > >>> c->onenand.disable = omap2_onenand_disable; > >>> } > >>> > >>> - if (pdata->skip_initial_unlocking) > >>> + if (0 /* TODO: pdata->skip_initial_unlocking */) > >>> this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; > >> > >> This should be a standard onenand binding. Maybe Boris can recommend what to do here. > >> > >>> > >>> if ((r = onenand_scan(&c->mtd, 1)) < 0) > >>> goto err_release_regulator; > >>> > >>> - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, > >>> - pdata ? pdata->nr_parts : 0); > >>> + r = mtd_device_register(&c->mtd, NULL, 0); > >>> if (r) > >>> goto err_release_onenand; > >>> > >>> @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) > >>> return 0; > >>> } > >>> > >>> +static const struct of_device_id omap2_onenand_ids[] = { > >>> + { .compatible = "ti,omap2-onenand", }, > >>> + {}, > >>> +}; > >>> +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); > >>> + > >>> static struct platform_driver omap2_onenand_driver = { > >>> .probe = omap2_onenand_probe, > >>> .remove = omap2_onenand_remove, > >>> .shutdown = omap2_onenand_shutdown, > >>> .driver = { > >>> .name = DRIVER_NAME, > >>> + .of_match_table = of_match_ptr(omap2_onenand_ids), > >>> }, > >>> }; > >>> > >>> > >> > >> -- > >> cheers, > >> -roger > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > -- > cheers, > -roger -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi, On Fri, Oct 13, 2017 at 02:25:18PM +0200, Ladislav Michl wrote: > Hi Roger, > > On Fri, Oct 13, 2017 at 03:11:37PM +0300, Roger Quadros wrote: > > Ladislav, > > > > Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > > > > On 13/10/17 15:05, Ladislav Michl wrote: > > > Hi Roger! > > > > > > On Fri, Oct 13, 2017 at 11:52:44AM +0300, Roger Quadros wrote: > > >> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > > >> > > >> On 12/10/17 23:29, Ladislav Michl wrote: > > >>> Hi Roger, > > >>> > > >>> On Thu, Oct 12, 2017 at 06:05:31PM +0300, Roger Quadros wrote: > > >>> [snip] > > >>>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > > >>>> > > >>>> On 12/10/17 15:27, Ladislav Michl wrote: > > >>>>> Not being Tony, I try to answer anyway... > > >>>>> > > >>>>> I've done patchset which removes gpmc_probe_onenand_child and uses > > >>>>> gpmc_probe_generic_child (renamed to gpmc_probe_child) to setup OneNAND > > >>>>> async timings. Sync timings is setup from mtd/onenand/omap2.c after > > >>>>> chip frequency is known. > > >>>>> > > >>>>> I've not sent it yet as device datasheet is available under NDA only, > > >>>>> I do not have it and thus I'm left with equivalent source modifications > > >>>>> without really understanding what should be done and why. > > >>>>> > > >>>>> That said, I sent this patch to fix OneNAND support (for IGEPv2 board > > >>>>> at least) and leave discussion about making things nice for later. > > >>>>> > > >>>>> I'm proposing killing gpmc_onenand_data first and teaching OneNAND > > >>>>> to get its configuration from DT. Later I'll cleanup sync/async > > >>>>> patchset and send it for review unless someone is willing to take > > >>>>> it over to speed things up a bit - then I'll send it as it is :-) > > >>>> > > >>>> sounds fine to me. > > >>>>> > > >>>>> Side question: in tree OneNAND DT nodes are providing timing information. > > >>>>> I have no clue where this timing information is coming from and driver > > >>>>> completely ignores it and computes timings on its own. Any hints here? > > >>>> > > >>>> My guess is nobody has access to the datasheet and we're relying on bootloader > > >>>> set timings or timings that were already hardcoded in the kernel. > > >>>> > > >>>> You can use CONFIG_OMAP_GPMC_DEBUG to dump the timings set by the bootloader > > >>>> in DT format. > > >>>> > > >>>> You can also compare the timings before and after gpmc driver loads. > > >>> > > >>> That will not help a lot, as these questions will remain unanswered using > > >>> above method: > > >>> - why SYNC_WRITE cannot be used on 24xx? > > >> > > >> No idea. This is there right from the first commit. > > > > > > Okay. Lets leave this on DT and remove it from code. That code > > > path is not currently used anyway. > > > > > >>> - why are we letting gpio line settle only on 34xx? > > >> > > >> >From commit 782b7a367d81da005d93b28cb00f9ae086773c24 > > >> > > >> "On OMAP3, the driver was occasionally not seeing the GPIO > > >> interrupt. Adding a small delay of one register read > > >> eliminates the problem." > > >> > > >> I guess this was a quick workaround to the problem faced by the early users > > >> of OneNand on OMAP3. > > >> > > >>> - why we are not using SYNC_WRITE with 54 MHz freq? > > >> > > >> I'm not sure. Seems to be in there from the first commit. > > >> > > >>> - how should be omap_onenand_platform_data flags set by default? > > >>> probably few more I do not remember, but will show up once I start > > >>> polishing patchset :) > > >>> > > >>> Anyway, here's first untested version, just to show, that we need > > >>> to touch arch/arm/mach-omap2/gpmc-onenand.c anyway, just to make > > >>> gpmc_onenand_setup directly callable without global > > >>> omap_onenand_platform_data (and later move it into omap-gpmc) > > >> > > >> Best to start a fresh thread with new patches. Patch looks in the right direction. > > >> > > >>> > > >>> So unless someone comes with better idea, I'll drop all global > > >>> variables from arch/arm/mach-omap2/gpmc-onenand.c and export > > >>> gpmc_onenand_setup to get rid of omap_onenand_platform_data. > > >>> After that patch gets merged, we can make additional patch on > > >>> top of following one, which will drop use of omap_onenand_platform_data > > >>> from omap2 onenand mtd driver. There are simply too many trees to > > >>> get things merged to make it easy task :-/ > > >> > > >> I understand it is a bit challenging. but we'll work it out. Main thing to > > >> keep in mind is to not break build in the different trees. So you might have to > > >> still keep some code around (especially platform data) but just mark it deprecated. > > > > > > Okay, lets start separate thread with patchset. It seems it's doable after > > > all :-) > > > > > >>> Also note that no DT only kernel sets flags, regulator, gpio and yet > > >>> noone complained, so we could leave it for later - and use more recent > > >>> APIs (gpiolib, etc). > > >> > > >> At least nobody seems to be setting regulator and gpio in arch/arm/gpmc-onenand.c > > >> so probably things work without it for everyone. > > >> > > >>> > > >>> diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c > > >>> index 29cc0c21138c..85fac7aed2dc 100644 > > >>> --- a/drivers/mtd/onenand/omap2.c > > >>> +++ b/drivers/mtd/onenand/omap2.c > > >>> @@ -28,12 +28,15 @@ > > >>> #include <linux/mtd/mtd.h> > > >>> #include <linux/mtd/onenand.h> > > >>> #include <linux/mtd/partitions.h> > > >>> +#include <linux/of.h> > > >>> +#include <linux/of_device.h> > > >>> #include <linux/platform_device.h> > > >>> #include <linux/interrupt.h> > > >>> #include <linux/delay.h> > > >>> #include <linux/dma-mapping.h> > > >>> #include <linux/io.h> > > >>> #include <linux/slab.h> > > >>> +#include <linux/sys_soc.h> > > >>> #include <linux/regulator/consumer.h> > > >>> #include <linux/gpio.h> > > >>> > > >>> @@ -59,7 +62,7 @@ struct omap2_onenand { > > >>> int dma_channel; > > >>> int freq; > > >>> struct regulator *regulator; > > >>> - u8 flags; > > >>> + bool gpio_settle; > > >>> }; > > >>> > > >>> static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) > > >>> @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) > > >>> if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { > > >>> syscfg |= ONENAND_SYS_CFG1_IOBE; > > >>> write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); > > >>> - if (c->flags & ONENAND_IN_OMAP34XX) > > >>> + if (c->gpio_settle) > > >>> /* Add a delay to let GPIO settle */ > > >>> syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); > > >>> } > > >>> @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) > > >>> return ret; > > >>> } > > >>> > > >>> +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) > > >>> +{ > > >>> + struct device_node *child = dev->of_node; > > >>> + u32 cs, val; > > >>> + > > >>> + if (of_property_read_u32(child, "reg", &cs) < 0) { > > >>> + dev_err(dev, "reg not found in DT\n"); > > >>> + return -EINVAL; > > >>> + } > > >>> + c->gpmc_cs = cs; > > >>> + > > >>> + if (!of_property_read_u32(child, "dma-channel", &val)) > > >>> + c->dma_channel = val; > > >>> + else > > >>> + c->dma_channel = -1; > > >>> + > > >>> + /* TODO: gpio, regulator, unlocking */ > > >>> + > > >>> + return 0; > > >>> +} > > >>> + > > >>> +static const struct soc_device_attribute omap2_soc_devices[] = { > > >>> + { .family = "OMAP2*" }, > > >>> + { /* sentinel */ } > > >>> +}; > > >>> + > > >> > > >> Is this the preferred way of doing things? Tony? > > >> I was thinking that we could use separate compatible ids for omap2 vs omap3+ > > >> e.g. > > >> > > >> for omap2, compatible = "ti,omap2-onenand"; > > >> for omap3 onwards, compatible = "ti,omap3-onenand"; > > >> > > >> and use of_device_is_compatible() to do omap2 vs omap3 specific stuff. > > > > > > Well, the problem is that there are 'compatible = "ti,omap2-onenand"' DTs > > > around for OMAP3 devices such as Nokia 8x0 AFAIR. > > > > Nokia n8xx devices are all OMAP2 based and can continu use ti,omap2-onenand. > > Nokia n9xx devices are all OMAP3 based so need to use ti,omap3-onenand. It shouldn't > > be a big problem to add a new binding. > > Quick grep arch/arm/boot/dts finds omap3-n950-n9.dtsi, but there is no > compatible property as well as there is not any in omap2420-n8x0-common.dtsi. > We could probably warn and bail out as we do in NAND case, but it would break > backward compatibility. Pavel? > > Another user is IGEP board, but as it is broken in mainline anyway and > I'm probably the only mainline user, it is not a big deal ;-) $ git grep onenand arch/arm/boot/dts/omap*dts* | grep -v "label" arch/arm/boot/dts/omap2420-n8x0-common.dtsi: onenand@0,0 { arch/arm/boot/dts/omap3-igep.dtsi: onenand@0,0 { arch/arm/boot/dts/omap3-igep.dtsi: compatible = "ti,omap2-onenand"; arch/arm/boot/dts/omap3-n900.dts: onenand@0,0 { arch/arm/boot/dts/omap3-n950-n9.dtsi: onenand@0,0 { arch/arm/boot/dts/omap3430-sdp.dts: onenand@2,0 { Mainline n950/n9 support is still missing display support (WIP) and n950 was a developers only device. I don't think having to update the DT is a big issue there. N900 is another story, though. It's supported fairly well in mainline and definitely has users. But if we want to make sure, that old DT keeps booting it should be possible to add some early code, which modifies the DT tree on the fly (like omapdrm does). It could add the compatible to any "onenand@XXX" node, if it's missing and print a warning. Then that code could be removed after a few kernels releases. > > > Anyway, I'm also interested what preferred solution is. Once revealed I'll send > > > proper patch. > > > > > >>> static int omap2_onenand_probe(struct platform_device *pdev) > > >>> { > > >>> struct omap_onenand_platform_data *pdata; > > >>> @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) > > >>> if (!c) > > >>> return -ENOMEM; > > >>> > > >>> + r = omap2_onenand_get_dt(&pdev->dev, c); > > >>> + if (r) > > >>> + goto err_kfree; > > >>> + > > >>> init_completion(&c->irq_done); > > >>> init_completion(&c->dma_done); > > >>> - c->flags = pdata->flags; > > >>> - c->gpmc_cs = pdata->cs; > > >>> - c->gpio_irq = pdata->gpio_irq; > > >>> - c->dma_channel = pdata->dma_channel; > > >>> if (c->dma_channel < 0) { > > >>> /* if -1, don't use DMA */ > > >>> c->gpio_irq = 0; > > >>> @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) > > >>> c->mtd.priv = &c->onenand; > > >>> > > >>> c->mtd.dev.parent = &pdev->dev; > > >>> - mtd_set_of_node(&c->mtd, pdata->of_node); > > >>> + mtd_set_of_node(&c->mtd, pdev->dev.of_node); > > >>> > > >>> this = &c->onenand; > > >>> if (c->dma_channel >= 0) { > > >>> this->wait = omap2_onenand_wait; > > >>> - if (c->flags & ONENAND_IN_OMAP34XX) { > > >>> - this->read_bufferram = omap3_onenand_read_bufferram; > > >>> - this->write_bufferram = omap3_onenand_write_bufferram; > > >>> - } else { > > >>> + if (soc_device_match(omap2_soc_devices)) { > > >>> this->read_bufferram = omap2_onenand_read_bufferram; > > >>> this->write_bufferram = omap2_onenand_write_bufferram; > > >>> + } else { > > >>> + c->gpio_settle = true; > > >>> + this->read_bufferram = omap3_onenand_read_bufferram; > > >>> + this->write_bufferram = omap3_onenand_write_bufferram; > > >>> } > > >>> } > > >>> > > >>> - if (pdata->regulator_can_sleep) { > > >>> + if (0 /* TODO: pdata->regulator_can_sleep */) { > > >>> c->regulator = regulator_get(&pdev->dev, "vonenand"); > > >>> if (IS_ERR(c->regulator)) { > > >>> dev_err(&pdev->dev, "Failed to get regulator\n"); > > >>> @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) > > >>> c->onenand.disable = omap2_onenand_disable; > > >>> } > > >>> > > >>> - if (pdata->skip_initial_unlocking) > > >>> + if (0 /* TODO: pdata->skip_initial_unlocking */) > > >>> this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; > > >> > > >> This should be a standard onenand binding. Maybe Boris can recommend what to do here. > > >> > > >>> > > >>> if ((r = onenand_scan(&c->mtd, 1)) < 0) > > >>> goto err_release_regulator; > > >>> > > >>> - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, > > >>> - pdata ? pdata->nr_parts : 0); > > >>> + r = mtd_device_register(&c->mtd, NULL, 0); > > >>> if (r) > > >>> goto err_release_onenand; > > >>> > > >>> @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) > > >>> return 0; > > >>> } > > >>> > > >>> +static const struct of_device_id omap2_onenand_ids[] = { > > >>> + { .compatible = "ti,omap2-onenand", }, > > >>> + {}, > > >>> +}; > > >>> +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); > > >>> + > > >>> static struct platform_driver omap2_onenand_driver = { > > >>> .probe = omap2_onenand_probe, > > >>> .remove = omap2_onenand_remove, > > >>> .shutdown = omap2_onenand_shutdown, > > >>> .driver = { > > >>> .name = DRIVER_NAME, > > >>> + .of_match_table = of_match_ptr(omap2_onenand_ids), > > >>> }, > > >>> }; > > >>> > > >>> > > >> > > >> -- > > >> cheers, > > >> -roger > > > -- > > > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > > > the body of a message to majordomo@vger.kernel.org > > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > > > > -- > > cheers, > > -roger > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi, Sorry about the annoying signature that is being auto inserted by our mail servers. We are working to get it fixed ASAP. Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki On 13/10/17 15:56, Sebastian Reichel wrote: > Hi, > > On Fri, Oct 13, 2017 at 02:25:18PM +0200, Ladislav Michl wrote: >> Hi Roger, >> >> On Fri, Oct 13, 2017 at 03:11:37PM +0300, Roger Quadros wrote: >>> Ladislav, >>> >>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki >>> >>> On 13/10/17 15:05, Ladislav Michl wrote: >>>> Hi Roger! >>>> >>>> On Fri, Oct 13, 2017 at 11:52:44AM +0300, Roger Quadros wrote: >>>>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki >>>>> >>>>> On 12/10/17 23:29, Ladislav Michl wrote: >>>>>> Hi Roger, >>>>>> >>>>>> On Thu, Oct 12, 2017 at 06:05:31PM +0300, Roger Quadros wrote: >>>>>> [snip] >>>>>>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki >>>>>>> >>>>>>> On 12/10/17 15:27, Ladislav Michl wrote: >>>>>>>> Not being Tony, I try to answer anyway... >>>>>>>> >>>>>>>> I've done patchset which removes gpmc_probe_onenand_child and uses >>>>>>>> gpmc_probe_generic_child (renamed to gpmc_probe_child) to setup OneNAND >>>>>>>> async timings. Sync timings is setup from mtd/onenand/omap2.c after >>>>>>>> chip frequency is known. >>>>>>>> >>>>>>>> I've not sent it yet as device datasheet is available under NDA only, >>>>>>>> I do not have it and thus I'm left with equivalent source modifications >>>>>>>> without really understanding what should be done and why. >>>>>>>> >>>>>>>> That said, I sent this patch to fix OneNAND support (for IGEPv2 board >>>>>>>> at least) and leave discussion about making things nice for later. >>>>>>>> >>>>>>>> I'm proposing killing gpmc_onenand_data first and teaching OneNAND >>>>>>>> to get its configuration from DT. Later I'll cleanup sync/async >>>>>>>> patchset and send it for review unless someone is willing to take >>>>>>>> it over to speed things up a bit - then I'll send it as it is :-) >>>>>>> >>>>>>> sounds fine to me. >>>>>>>> >>>>>>>> Side question: in tree OneNAND DT nodes are providing timing information. >>>>>>>> I have no clue where this timing information is coming from and driver >>>>>>>> completely ignores it and computes timings on its own. Any hints here? >>>>>>> >>>>>>> My guess is nobody has access to the datasheet and we're relying on bootloader >>>>>>> set timings or timings that were already hardcoded in the kernel. >>>>>>> >>>>>>> You can use CONFIG_OMAP_GPMC_DEBUG to dump the timings set by the bootloader >>>>>>> in DT format. >>>>>>> >>>>>>> You can also compare the timings before and after gpmc driver loads. >>>>>> >>>>>> That will not help a lot, as these questions will remain unanswered using >>>>>> above method: >>>>>> - why SYNC_WRITE cannot be used on 24xx? >>>>> >>>>> No idea. This is there right from the first commit. >>>> >>>> Okay. Lets leave this on DT and remove it from code. That code >>>> path is not currently used anyway. >>>> >>>>>> - why are we letting gpio line settle only on 34xx? >>>>> >>>>> >From commit 782b7a367d81da005d93b28cb00f9ae086773c24 >>>>> >>>>> "On OMAP3, the driver was occasionally not seeing the GPIO >>>>> interrupt. Adding a small delay of one register read >>>>> eliminates the problem." >>>>> >>>>> I guess this was a quick workaround to the problem faced by the early users >>>>> of OneNand on OMAP3. >>>>> >>>>>> - why we are not using SYNC_WRITE with 54 MHz freq? >>>>> >>>>> I'm not sure. Seems to be in there from the first commit. >>>>> >>>>>> - how should be omap_onenand_platform_data flags set by default? >>>>>> probably few more I do not remember, but will show up once I start >>>>>> polishing patchset :) >>>>>> >>>>>> Anyway, here's first untested version, just to show, that we need >>>>>> to touch arch/arm/mach-omap2/gpmc-onenand.c anyway, just to make >>>>>> gpmc_onenand_setup directly callable without global >>>>>> omap_onenand_platform_data (and later move it into omap-gpmc) >>>>> >>>>> Best to start a fresh thread with new patches. Patch looks in the right direction. >>>>> >>>>>> >>>>>> So unless someone comes with better idea, I'll drop all global >>>>>> variables from arch/arm/mach-omap2/gpmc-onenand.c and export >>>>>> gpmc_onenand_setup to get rid of omap_onenand_platform_data. >>>>>> After that patch gets merged, we can make additional patch on >>>>>> top of following one, which will drop use of omap_onenand_platform_data >>>>>> from omap2 onenand mtd driver. There are simply too many trees to >>>>>> get things merged to make it easy task :-/ >>>>> >>>>> I understand it is a bit challenging. but we'll work it out. Main thing to >>>>> keep in mind is to not break build in the different trees. So you might have to >>>>> still keep some code around (especially platform data) but just mark it deprecated. >>>> >>>> Okay, lets start separate thread with patchset. It seems it's doable after >>>> all :-) >>>> >>>>>> Also note that no DT only kernel sets flags, regulator, gpio and yet >>>>>> noone complained, so we could leave it for later - and use more recent >>>>>> APIs (gpiolib, etc). >>>>> >>>>> At least nobody seems to be setting regulator and gpio in arch/arm/gpmc-onenand.c >>>>> so probably things work without it for everyone. >>>>> >>>>>> >>>>>> diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c >>>>>> index 29cc0c21138c..85fac7aed2dc 100644 >>>>>> --- a/drivers/mtd/onenand/omap2.c >>>>>> +++ b/drivers/mtd/onenand/omap2.c >>>>>> @@ -28,12 +28,15 @@ >>>>>> #include <linux/mtd/mtd.h> >>>>>> #include <linux/mtd/onenand.h> >>>>>> #include <linux/mtd/partitions.h> >>>>>> +#include <linux/of.h> >>>>>> +#include <linux/of_device.h> >>>>>> #include <linux/platform_device.h> >>>>>> #include <linux/interrupt.h> >>>>>> #include <linux/delay.h> >>>>>> #include <linux/dma-mapping.h> >>>>>> #include <linux/io.h> >>>>>> #include <linux/slab.h> >>>>>> +#include <linux/sys_soc.h> >>>>>> #include <linux/regulator/consumer.h> >>>>>> #include <linux/gpio.h> >>>>>> >>>>>> @@ -59,7 +62,7 @@ struct omap2_onenand { >>>>>> int dma_channel; >>>>>> int freq; >>>>>> struct regulator *regulator; >>>>>> - u8 flags; >>>>>> + bool gpio_settle; >>>>>> }; >>>>>> >>>>>> static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) >>>>>> @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) >>>>>> if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { >>>>>> syscfg |= ONENAND_SYS_CFG1_IOBE; >>>>>> write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); >>>>>> - if (c->flags & ONENAND_IN_OMAP34XX) >>>>>> + if (c->gpio_settle) >>>>>> /* Add a delay to let GPIO settle */ >>>>>> syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); >>>>>> } >>>>>> @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) >>>>>> return ret; >>>>>> } >>>>>> >>>>>> +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) >>>>>> +{ >>>>>> + struct device_node *child = dev->of_node; >>>>>> + u32 cs, val; >>>>>> + >>>>>> + if (of_property_read_u32(child, "reg", &cs) < 0) { >>>>>> + dev_err(dev, "reg not found in DT\n"); >>>>>> + return -EINVAL; >>>>>> + } >>>>>> + c->gpmc_cs = cs; >>>>>> + >>>>>> + if (!of_property_read_u32(child, "dma-channel", &val)) >>>>>> + c->dma_channel = val; >>>>>> + else >>>>>> + c->dma_channel = -1; >>>>>> + >>>>>> + /* TODO: gpio, regulator, unlocking */ >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> +static const struct soc_device_attribute omap2_soc_devices[] = { >>>>>> + { .family = "OMAP2*" }, >>>>>> + { /* sentinel */ } >>>>>> +}; >>>>>> + >>>>> >>>>> Is this the preferred way of doing things? Tony? >>>>> I was thinking that we could use separate compatible ids for omap2 vs omap3+ >>>>> e.g. >>>>> >>>>> for omap2, compatible = "ti,omap2-onenand"; >>>>> for omap3 onwards, compatible = "ti,omap3-onenand"; >>>>> >>>>> and use of_device_is_compatible() to do omap2 vs omap3 specific stuff. >>>> >>>> Well, the problem is that there are 'compatible = "ti,omap2-onenand"' DTs >>>> around for OMAP3 devices such as Nokia 8x0 AFAIR. >>> >>> Nokia n8xx devices are all OMAP2 based and can continu use ti,omap2-onenand. >>> Nokia n9xx devices are all OMAP3 based so need to use ti,omap3-onenand. It shouldn't >>> be a big problem to add a new binding. >> >> Quick grep arch/arm/boot/dts finds omap3-n950-n9.dtsi, but there is no >> compatible property as well as there is not any in omap2420-n8x0-common.dtsi. >> We could probably warn and bail out as we do in NAND case, but it would break >> backward compatibility. Pavel? >> >> Another user is IGEP board, but as it is broken in mainline anyway and >> I'm probably the only mainline user, it is not a big deal ;-) > > $ git grep onenand arch/arm/boot/dts/omap*dts* | grep -v "label" > arch/arm/boot/dts/omap2420-n8x0-common.dtsi: onenand@0,0 { > arch/arm/boot/dts/omap3-igep.dtsi: onenand@0,0 { > arch/arm/boot/dts/omap3-igep.dtsi: compatible = "ti,omap2-onenand"; > arch/arm/boot/dts/omap3-n900.dts: onenand@0,0 { > arch/arm/boot/dts/omap3-n950-n9.dtsi: onenand@0,0 { > arch/arm/boot/dts/omap3430-sdp.dts: onenand@2,0 { > > Mainline n950/n9 support is still missing display support (WIP) and n950 > was a developers only device. I don't think having to update the DT is a > big issue there. N900 is another story, though. It's supported fairly well > in mainline and definitely has users. > > But if we want to make sure, that old DT keeps booting it should be > possible to add some early code, which modifies the DT tree on > the fly (like omapdrm does). It could add the compatible to any > "onenand@XXX" node, if it's missing and print a warning. Then that > code could be removed after a few kernels releases. As current driver doesn't expect a compatible property, a simpler approach would be to fix all compatibles in the next kernel release and add proper driver support that depends on the compatible ids in the release after that. This shouldn't break any users. I'm not a big fan of on the fly DT modification :P > >>>> Anyway, I'm also interested what preferred solution is. Once revealed I'll send >>>> proper patch. >>>> >>>>>> static int omap2_onenand_probe(struct platform_device *pdev) >>>>>> { >>>>>> struct omap_onenand_platform_data *pdata; >>>>>> @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) >>>>>> if (!c) >>>>>> return -ENOMEM; >>>>>> >>>>>> + r = omap2_onenand_get_dt(&pdev->dev, c); >>>>>> + if (r) >>>>>> + goto err_kfree; >>>>>> + >>>>>> init_completion(&c->irq_done); >>>>>> init_completion(&c->dma_done); >>>>>> - c->flags = pdata->flags; >>>>>> - c->gpmc_cs = pdata->cs; >>>>>> - c->gpio_irq = pdata->gpio_irq; >>>>>> - c->dma_channel = pdata->dma_channel; >>>>>> if (c->dma_channel < 0) { >>>>>> /* if -1, don't use DMA */ >>>>>> c->gpio_irq = 0; >>>>>> @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) >>>>>> c->mtd.priv = &c->onenand; >>>>>> >>>>>> c->mtd.dev.parent = &pdev->dev; >>>>>> - mtd_set_of_node(&c->mtd, pdata->of_node); >>>>>> + mtd_set_of_node(&c->mtd, pdev->dev.of_node); >>>>>> >>>>>> this = &c->onenand; >>>>>> if (c->dma_channel >= 0) { >>>>>> this->wait = omap2_onenand_wait; >>>>>> - if (c->flags & ONENAND_IN_OMAP34XX) { >>>>>> - this->read_bufferram = omap3_onenand_read_bufferram; >>>>>> - this->write_bufferram = omap3_onenand_write_bufferram; >>>>>> - } else { >>>>>> + if (soc_device_match(omap2_soc_devices)) { >>>>>> this->read_bufferram = omap2_onenand_read_bufferram; >>>>>> this->write_bufferram = omap2_onenand_write_bufferram; >>>>>> + } else { >>>>>> + c->gpio_settle = true; >>>>>> + this->read_bufferram = omap3_onenand_read_bufferram; >>>>>> + this->write_bufferram = omap3_onenand_write_bufferram; >>>>>> } >>>>>> } >>>>>> >>>>>> - if (pdata->regulator_can_sleep) { >>>>>> + if (0 /* TODO: pdata->regulator_can_sleep */) { >>>>>> c->regulator = regulator_get(&pdev->dev, "vonenand"); >>>>>> if (IS_ERR(c->regulator)) { >>>>>> dev_err(&pdev->dev, "Failed to get regulator\n"); >>>>>> @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) >>>>>> c->onenand.disable = omap2_onenand_disable; >>>>>> } >>>>>> >>>>>> - if (pdata->skip_initial_unlocking) >>>>>> + if (0 /* TODO: pdata->skip_initial_unlocking */) >>>>>> this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; >>>>> >>>>> This should be a standard onenand binding. Maybe Boris can recommend what to do here. >>>>> >>>>>> >>>>>> if ((r = onenand_scan(&c->mtd, 1)) < 0) >>>>>> goto err_release_regulator; >>>>>> >>>>>> - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, >>>>>> - pdata ? pdata->nr_parts : 0); >>>>>> + r = mtd_device_register(&c->mtd, NULL, 0); >>>>>> if (r) >>>>>> goto err_release_onenand; >>>>>> >>>>>> @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) >>>>>> return 0; >>>>>> } >>>>>> >>>>>> +static const struct of_device_id omap2_onenand_ids[] = { >>>>>> + { .compatible = "ti,omap2-onenand", }, >>>>>> + {}, >>>>>> +}; >>>>>> +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); >>>>>> + >>>>>> static struct platform_driver omap2_onenand_driver = { >>>>>> .probe = omap2_onenand_probe, >>>>>> .remove = omap2_onenand_remove, >>>>>> .shutdown = omap2_onenand_shutdown, >>>>>> .driver = { >>>>>> .name = DRIVER_NAME, >>>>>> + .of_match_table = of_match_ptr(omap2_onenand_ids), >>>>>> }, >>>>>> }; >>>>>> >>>>>> >>>>> >>>>> -- >>>>> cheers, >>>>> -roger >>>> -- >>>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in >>>> the body of a message to majordomo@vger.kernel.org >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>>> >>> >>> -- >>> cheers, >>> -roger >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-omap" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Oct 17, 2017 at 10:49:54AM +0300, Roger Quadros wrote: > Hi, > > Sorry about the annoying signature that is being auto inserted by our mail servers. > We are working to get it fixed ASAP. No problem. As this is probably handled by IT department, where simple things take incredible amount of time, I do not expect this signature gone till next polar day ;-) > Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > > On 13/10/17 15:56, Sebastian Reichel wrote: > > Hi, > > > > On Fri, Oct 13, 2017 at 02:25:18PM +0200, Ladislav Michl wrote: > >> Hi Roger, > >> > >> On Fri, Oct 13, 2017 at 03:11:37PM +0300, Roger Quadros wrote: > >>> Ladislav, > >>> > >>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > >>> > >>> On 13/10/17 15:05, Ladislav Michl wrote: > >>>> Hi Roger! > >>>> > >>>> On Fri, Oct 13, 2017 at 11:52:44AM +0300, Roger Quadros wrote: > >>>>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > >>>>> > >>>>> On 12/10/17 23:29, Ladislav Michl wrote: > >>>>>> Hi Roger, > >>>>>> > >>>>>> On Thu, Oct 12, 2017 at 06:05:31PM +0300, Roger Quadros wrote: > >>>>>> [snip] > >>>>>>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki > >>>>>>> > >>>>>>> On 12/10/17 15:27, Ladislav Michl wrote: > >>>>>>>> Not being Tony, I try to answer anyway... > >>>>>>>> > >>>>>>>> I've done patchset which removes gpmc_probe_onenand_child and uses > >>>>>>>> gpmc_probe_generic_child (renamed to gpmc_probe_child) to setup OneNAND > >>>>>>>> async timings. Sync timings is setup from mtd/onenand/omap2.c after > >>>>>>>> chip frequency is known. > >>>>>>>> > >>>>>>>> I've not sent it yet as device datasheet is available under NDA only, > >>>>>>>> I do not have it and thus I'm left with equivalent source modifications > >>>>>>>> without really understanding what should be done and why. > >>>>>>>> > >>>>>>>> That said, I sent this patch to fix OneNAND support (for IGEPv2 board > >>>>>>>> at least) and leave discussion about making things nice for later. > >>>>>>>> > >>>>>>>> I'm proposing killing gpmc_onenand_data first and teaching OneNAND > >>>>>>>> to get its configuration from DT. Later I'll cleanup sync/async > >>>>>>>> patchset and send it for review unless someone is willing to take > >>>>>>>> it over to speed things up a bit - then I'll send it as it is :-) > >>>>>>> > >>>>>>> sounds fine to me. > >>>>>>>> > >>>>>>>> Side question: in tree OneNAND DT nodes are providing timing information. > >>>>>>>> I have no clue where this timing information is coming from and driver > >>>>>>>> completely ignores it and computes timings on its own. Any hints here? > >>>>>>> > >>>>>>> My guess is nobody has access to the datasheet and we're relying on bootloader > >>>>>>> set timings or timings that were already hardcoded in the kernel. > >>>>>>> > >>>>>>> You can use CONFIG_OMAP_GPMC_DEBUG to dump the timings set by the bootloader > >>>>>>> in DT format. > >>>>>>> > >>>>>>> You can also compare the timings before and after gpmc driver loads. > >>>>>> > >>>>>> That will not help a lot, as these questions will remain unanswered using > >>>>>> above method: > >>>>>> - why SYNC_WRITE cannot be used on 24xx? > >>>>> > >>>>> No idea. This is there right from the first commit. > >>>> > >>>> Okay. Lets leave this on DT and remove it from code. That code > >>>> path is not currently used anyway. > >>>> > >>>>>> - why are we letting gpio line settle only on 34xx? > >>>>> > >>>>> >From commit 782b7a367d81da005d93b28cb00f9ae086773c24 > >>>>> > >>>>> "On OMAP3, the driver was occasionally not seeing the GPIO > >>>>> interrupt. Adding a small delay of one register read > >>>>> eliminates the problem." > >>>>> > >>>>> I guess this was a quick workaround to the problem faced by the early users > >>>>> of OneNand on OMAP3. > >>>>> > >>>>>> - why we are not using SYNC_WRITE with 54 MHz freq? > >>>>> > >>>>> I'm not sure. Seems to be in there from the first commit. > >>>>> > >>>>>> - how should be omap_onenand_platform_data flags set by default? > >>>>>> probably few more I do not remember, but will show up once I start > >>>>>> polishing patchset :) > >>>>>> > >>>>>> Anyway, here's first untested version, just to show, that we need > >>>>>> to touch arch/arm/mach-omap2/gpmc-onenand.c anyway, just to make > >>>>>> gpmc_onenand_setup directly callable without global > >>>>>> omap_onenand_platform_data (and later move it into omap-gpmc) > >>>>> > >>>>> Best to start a fresh thread with new patches. Patch looks in the right direction. > >>>>> > >>>>>> > >>>>>> So unless someone comes with better idea, I'll drop all global > >>>>>> variables from arch/arm/mach-omap2/gpmc-onenand.c and export > >>>>>> gpmc_onenand_setup to get rid of omap_onenand_platform_data. > >>>>>> After that patch gets merged, we can make additional patch on > >>>>>> top of following one, which will drop use of omap_onenand_platform_data > >>>>>> from omap2 onenand mtd driver. There are simply too many trees to > >>>>>> get things merged to make it easy task :-/ > >>>>> > >>>>> I understand it is a bit challenging. but we'll work it out. Main thing to > >>>>> keep in mind is to not break build in the different trees. So you might have to > >>>>> still keep some code around (especially platform data) but just mark it deprecated. > >>>> > >>>> Okay, lets start separate thread with patchset. It seems it's doable after > >>>> all :-) > >>>> > >>>>>> Also note that no DT only kernel sets flags, regulator, gpio and yet > >>>>>> noone complained, so we could leave it for later - and use more recent > >>>>>> APIs (gpiolib, etc). > >>>>> > >>>>> At least nobody seems to be setting regulator and gpio in arch/arm/gpmc-onenand.c > >>>>> so probably things work without it for everyone. > >>>>> > >>>>>> > >>>>>> diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c > >>>>>> index 29cc0c21138c..85fac7aed2dc 100644 > >>>>>> --- a/drivers/mtd/onenand/omap2.c > >>>>>> +++ b/drivers/mtd/onenand/omap2.c > >>>>>> @@ -28,12 +28,15 @@ > >>>>>> #include <linux/mtd/mtd.h> > >>>>>> #include <linux/mtd/onenand.h> > >>>>>> #include <linux/mtd/partitions.h> > >>>>>> +#include <linux/of.h> > >>>>>> +#include <linux/of_device.h> > >>>>>> #include <linux/platform_device.h> > >>>>>> #include <linux/interrupt.h> > >>>>>> #include <linux/delay.h> > >>>>>> #include <linux/dma-mapping.h> > >>>>>> #include <linux/io.h> > >>>>>> #include <linux/slab.h> > >>>>>> +#include <linux/sys_soc.h> > >>>>>> #include <linux/regulator/consumer.h> > >>>>>> #include <linux/gpio.h> > >>>>>> > >>>>>> @@ -59,7 +62,7 @@ struct omap2_onenand { > >>>>>> int dma_channel; > >>>>>> int freq; > >>>>>> struct regulator *regulator; > >>>>>> - u8 flags; > >>>>>> + bool gpio_settle; > >>>>>> }; > >>>>>> > >>>>>> static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) > >>>>>> @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) > >>>>>> if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { > >>>>>> syscfg |= ONENAND_SYS_CFG1_IOBE; > >>>>>> write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); > >>>>>> - if (c->flags & ONENAND_IN_OMAP34XX) > >>>>>> + if (c->gpio_settle) > >>>>>> /* Add a delay to let GPIO settle */ > >>>>>> syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); > >>>>>> } > >>>>>> @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) > >>>>>> return ret; > >>>>>> } > >>>>>> > >>>>>> +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) > >>>>>> +{ > >>>>>> + struct device_node *child = dev->of_node; > >>>>>> + u32 cs, val; > >>>>>> + > >>>>>> + if (of_property_read_u32(child, "reg", &cs) < 0) { > >>>>>> + dev_err(dev, "reg not found in DT\n"); > >>>>>> + return -EINVAL; > >>>>>> + } > >>>>>> + c->gpmc_cs = cs; > >>>>>> + > >>>>>> + if (!of_property_read_u32(child, "dma-channel", &val)) > >>>>>> + c->dma_channel = val; > >>>>>> + else > >>>>>> + c->dma_channel = -1; > >>>>>> + > >>>>>> + /* TODO: gpio, regulator, unlocking */ > >>>>>> + > >>>>>> + return 0; > >>>>>> +} > >>>>>> + > >>>>>> +static const struct soc_device_attribute omap2_soc_devices[] = { > >>>>>> + { .family = "OMAP2*" }, > >>>>>> + { /* sentinel */ } > >>>>>> +}; > >>>>>> + > >>>>> > >>>>> Is this the preferred way of doing things? Tony? > >>>>> I was thinking that we could use separate compatible ids for omap2 vs omap3+ > >>>>> e.g. > >>>>> > >>>>> for omap2, compatible = "ti,omap2-onenand"; > >>>>> for omap3 onwards, compatible = "ti,omap3-onenand"; > >>>>> > >>>>> and use of_device_is_compatible() to do omap2 vs omap3 specific stuff. > >>>> > >>>> Well, the problem is that there are 'compatible = "ti,omap2-onenand"' DTs > >>>> around for OMAP3 devices such as Nokia 8x0 AFAIR. > >>> > >>> Nokia n8xx devices are all OMAP2 based and can continu use ti,omap2-onenand. > >>> Nokia n9xx devices are all OMAP3 based so need to use ti,omap3-onenand. It shouldn't > >>> be a big problem to add a new binding. > >> > >> Quick grep arch/arm/boot/dts finds omap3-n950-n9.dtsi, but there is no > >> compatible property as well as there is not any in omap2420-n8x0-common.dtsi. > >> We could probably warn and bail out as we do in NAND case, but it would break > >> backward compatibility. Pavel? > >> > >> Another user is IGEP board, but as it is broken in mainline anyway and > >> I'm probably the only mainline user, it is not a big deal ;-) > > > > $ git grep onenand arch/arm/boot/dts/omap*dts* | grep -v "label" > > arch/arm/boot/dts/omap2420-n8x0-common.dtsi: onenand@0,0 { > > arch/arm/boot/dts/omap3-igep.dtsi: onenand@0,0 { > > arch/arm/boot/dts/omap3-igep.dtsi: compatible = "ti,omap2-onenand"; > > arch/arm/boot/dts/omap3-n900.dts: onenand@0,0 { > > arch/arm/boot/dts/omap3-n950-n9.dtsi: onenand@0,0 { > > arch/arm/boot/dts/omap3430-sdp.dts: onenand@2,0 { > > > > Mainline n950/n9 support is still missing display support (WIP) and n950 > > was a developers only device. I don't think having to update the DT is a > > big issue there. N900 is another story, though. It's supported fairly well > > in mainline and definitely has users. > > > > But if we want to make sure, that old DT keeps booting it should be > > possible to add some early code, which modifies the DT tree on > > the fly (like omapdrm does). It could add the compatible to any > > "onenand@XXX" node, if it's missing and print a warning. Then that > > code could be removed after a few kernels releases. > > As current driver doesn't expect a compatible property, a simpler approach would be > to fix all compatibles in the next kernel release and add proper driver support that > depends on the compatible ids in the release after that. This shouldn't break any users. I'm probably missing something... Current driver does not expect a compatible property, but it gets information from outside (arm/mach-omap2). Once we switch to DT only approach, we will need this information, but all those N9x0 users would have to update DT as well... Oh wait... This is only needed to setup DMA and that GPIO wait hack and none of them seems to be in use. So we are probably safe anyway. In theory, only some out of tree users would be affected. Sebastian, is the above right? > I'm not a big fan of on the fly DT modification :P Already done in patchset... > >>>> Anyway, I'm also interested what preferred solution is. Once revealed I'll send > >>>> proper patch. > >>>> > >>>>>> static int omap2_onenand_probe(struct platform_device *pdev) > >>>>>> { > >>>>>> struct omap_onenand_platform_data *pdata; > >>>>>> @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) > >>>>>> if (!c) > >>>>>> return -ENOMEM; > >>>>>> > >>>>>> + r = omap2_onenand_get_dt(&pdev->dev, c); > >>>>>> + if (r) > >>>>>> + goto err_kfree; > >>>>>> + > >>>>>> init_completion(&c->irq_done); > >>>>>> init_completion(&c->dma_done); > >>>>>> - c->flags = pdata->flags; > >>>>>> - c->gpmc_cs = pdata->cs; > >>>>>> - c->gpio_irq = pdata->gpio_irq; > >>>>>> - c->dma_channel = pdata->dma_channel; > >>>>>> if (c->dma_channel < 0) { > >>>>>> /* if -1, don't use DMA */ > >>>>>> c->gpio_irq = 0; > >>>>>> @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) > >>>>>> c->mtd.priv = &c->onenand; > >>>>>> > >>>>>> c->mtd.dev.parent = &pdev->dev; > >>>>>> - mtd_set_of_node(&c->mtd, pdata->of_node); > >>>>>> + mtd_set_of_node(&c->mtd, pdev->dev.of_node); > >>>>>> > >>>>>> this = &c->onenand; > >>>>>> if (c->dma_channel >= 0) { > >>>>>> this->wait = omap2_onenand_wait; > >>>>>> - if (c->flags & ONENAND_IN_OMAP34XX) { > >>>>>> - this->read_bufferram = omap3_onenand_read_bufferram; > >>>>>> - this->write_bufferram = omap3_onenand_write_bufferram; > >>>>>> - } else { > >>>>>> + if (soc_device_match(omap2_soc_devices)) { > >>>>>> this->read_bufferram = omap2_onenand_read_bufferram; > >>>>>> this->write_bufferram = omap2_onenand_write_bufferram; > >>>>>> + } else { > >>>>>> + c->gpio_settle = true; > >>>>>> + this->read_bufferram = omap3_onenand_read_bufferram; > >>>>>> + this->write_bufferram = omap3_onenand_write_bufferram; > >>>>>> } > >>>>>> } > >>>>>> > >>>>>> - if (pdata->regulator_can_sleep) { > >>>>>> + if (0 /* TODO: pdata->regulator_can_sleep */) { > >>>>>> c->regulator = regulator_get(&pdev->dev, "vonenand"); > >>>>>> if (IS_ERR(c->regulator)) { > >>>>>> dev_err(&pdev->dev, "Failed to get regulator\n"); > >>>>>> @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) > >>>>>> c->onenand.disable = omap2_onenand_disable; > >>>>>> } > >>>>>> > >>>>>> - if (pdata->skip_initial_unlocking) > >>>>>> + if (0 /* TODO: pdata->skip_initial_unlocking */) > >>>>>> this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; > >>>>> > >>>>> This should be a standard onenand binding. Maybe Boris can recommend what to do here. > >>>>> > >>>>>> > >>>>>> if ((r = onenand_scan(&c->mtd, 1)) < 0) > >>>>>> goto err_release_regulator; > >>>>>> > >>>>>> - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, > >>>>>> - pdata ? pdata->nr_parts : 0); > >>>>>> + r = mtd_device_register(&c->mtd, NULL, 0); > >>>>>> if (r) > >>>>>> goto err_release_onenand; > >>>>>> > >>>>>> @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) > >>>>>> return 0; > >>>>>> } > >>>>>> > >>>>>> +static const struct of_device_id omap2_onenand_ids[] = { > >>>>>> + { .compatible = "ti,omap2-onenand", }, > >>>>>> + {}, > >>>>>> +}; > >>>>>> +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); > >>>>>> + > >>>>>> static struct platform_driver omap2_onenand_driver = { > >>>>>> .probe = omap2_onenand_probe, > >>>>>> .remove = omap2_onenand_remove, > >>>>>> .shutdown = omap2_onenand_shutdown, > >>>>>> .driver = { > >>>>>> .name = DRIVER_NAME, > >>>>>> + .of_match_table = of_match_ptr(omap2_onenand_ids), > >>>>>> }, > >>>>>> }; > >>>>>> > >>>>>> > >>>>> > >>>>> -- > >>>>> cheers, > >>>>> -roger > >>>> -- > >>>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in > >>>> the body of a message to majordomo@vger.kernel.org > >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html > >>>> > >>> > >>> -- > >>> cheers, > >>> -roger > >> -- > >> To unsubscribe from this list: send the line "unsubscribe linux-omap" in > >> the body of a message to majordomo@vger.kernel.org > >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- > cheers, > -roger -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 29cc0c21138c..85fac7aed2dc 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -28,12 +28,15 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/onenand.h> #include <linux/mtd/partitions.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/sys_soc.h> #include <linux/regulator/consumer.h> #include <linux/gpio.h> @@ -59,7 +62,7 @@ struct omap2_onenand { int dma_channel; int freq; struct regulator *regulator; - u8 flags; + bool gpio_settle; }; static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) @@ -152,7 +155,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { syscfg |= ONENAND_SYS_CFG1_IOBE; write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); - if (c->flags & ONENAND_IN_OMAP34XX) + if (c->gpio_settle) /* Add a delay to let GPIO settle */ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); } @@ -606,6 +609,32 @@ static int omap2_onenand_disable(struct mtd_info *mtd) return ret; } +static int omap2_onenand_get_dt(struct device *dev, struct omap2_onenand *c) +{ + struct device_node *child = dev->of_node; + u32 cs, val; + + if (of_property_read_u32(child, "reg", &cs) < 0) { + dev_err(dev, "reg not found in DT\n"); + return -EINVAL; + } + c->gpmc_cs = cs; + + if (!of_property_read_u32(child, "dma-channel", &val)) + c->dma_channel = val; + else + c->dma_channel = -1; + + /* TODO: gpio, regulator, unlocking */ + + return 0; +} + +static const struct soc_device_attribute omap2_soc_devices[] = { + { .family = "OMAP2*" }, + { /* sentinel */ } +}; + static int omap2_onenand_probe(struct platform_device *pdev) { struct omap_onenand_platform_data *pdata; @@ -624,12 +653,12 @@ static int omap2_onenand_probe(struct platform_device *pdev) if (!c) return -ENOMEM; + r = omap2_onenand_get_dt(&pdev->dev, c); + if (r) + goto err_kfree; + init_completion(&c->irq_done); init_completion(&c->dma_done); - c->flags = pdata->flags; - c->gpmc_cs = pdata->cs; - c->gpio_irq = pdata->gpio_irq; - c->dma_channel = pdata->dma_channel; if (c->dma_channel < 0) { /* if -1, don't use DMA */ c->gpio_irq = 0; @@ -710,21 +739,22 @@ static int omap2_onenand_probe(struct platform_device *pdev) c->mtd.priv = &c->onenand; c->mtd.dev.parent = &pdev->dev; - mtd_set_of_node(&c->mtd, pdata->of_node); + mtd_set_of_node(&c->mtd, pdev->dev.of_node); this = &c->onenand; if (c->dma_channel >= 0) { this->wait = omap2_onenand_wait; - if (c->flags & ONENAND_IN_OMAP34XX) { - this->read_bufferram = omap3_onenand_read_bufferram; - this->write_bufferram = omap3_onenand_write_bufferram; - } else { + if (soc_device_match(omap2_soc_devices)) { this->read_bufferram = omap2_onenand_read_bufferram; this->write_bufferram = omap2_onenand_write_bufferram; + } else { + c->gpio_settle = true; + this->read_bufferram = omap3_onenand_read_bufferram; + this->write_bufferram = omap3_onenand_write_bufferram; } } - if (pdata->regulator_can_sleep) { + if (0 /* TODO: pdata->regulator_can_sleep */) { c->regulator = regulator_get(&pdev->dev, "vonenand"); if (IS_ERR(c->regulator)) { dev_err(&pdev->dev, "Failed to get regulator\n"); @@ -735,14 +765,13 @@ static int omap2_onenand_probe(struct platform_device *pdev) c->onenand.disable = omap2_onenand_disable; } - if (pdata->skip_initial_unlocking) + if (0 /* TODO: pdata->skip_initial_unlocking */) this->options |= ONENAND_SKIP_INITIAL_UNLOCKING; if ((r = onenand_scan(&c->mtd, 1)) < 0) goto err_release_regulator; - r = mtd_device_register(&c->mtd, pdata ? pdata->parts : NULL, - pdata ? pdata->nr_parts : 0); + r = mtd_device_register(&c->mtd, NULL, 0); if (r) goto err_release_onenand; @@ -792,12 +821,19 @@ static int omap2_onenand_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id omap2_onenand_ids[] = { + { .compatible = "ti,omap2-onenand", }, + {}, +}; +MODULE_DEVICE_TABLE(of, omap2_onenand_ids); + static struct platform_driver omap2_onenand_driver = { .probe = omap2_onenand_probe, .remove = omap2_onenand_remove, .shutdown = omap2_onenand_shutdown, .driver = { .name = DRIVER_NAME, + .of_match_table = of_match_ptr(omap2_onenand_ids), }, };