diff mbox

[01/14] mtd: Flex-OneNAND support

Message ID 2AF67696C6634054B7CFDF7A9C19865D@sisodomain.com
State New, archived
Headers show

Commit Message

Amul Saha June 12, 2009, 10:26 a.m. UTC
This patch now adds support for Flex-OneNAND to be used as a module,
it also supports Boundary setting at module insertion time

Signed-off-by: Amul Kumar Saha <amul.saha at samsung.com>
Signed-off-by: Vishak G <vishak.g at samsung.com>
---
 onenand_base.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

Comments

Artem Bityutskiy June 12, 2009, 10:42 a.m. UTC | #1
On Fri, 2009-06-12 at 15:56 +0530, Amul Saha wrote:
> This patch now adds support for Flex-OneNAND to be used as a module,
> it also supports Boundary setting at module insertion time
> 
> Signed-off-by: Amul Kumar Saha <amul.saha at samsung.com>
> Signed-off-by: Vishak G <vishak.g at samsung.com>
> ---
>  onenand_base.c |   15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
> index 8d4c9c2..6d2086f 100644
> --- a/drivers/mtd/onenand/onenand_base.c
> +++ b/drivers/mtd/onenand/onenand_base.c
> @@ -20,6 +20,7 @@
> 
>  #include <linux/kernel.h>
>  #include <linux/module.h>
> +#include <linux/moduleparam.h>
>  #include <linux/init.h>
>  #include <linux/sched.h>
>  #include <linux/delay.h>
> @@ -31,6 +32,16 @@
> 
>  #include <asm/io.h>
> 
> +static char *flex_bdry_info;
> +
> +module_param(flex_bdry_info, charp, 0400);
> +MODULE_PARM_DESC(flex_bdry_info, "SLC Boundary information for Flex-OneNAND"
> +				 "Syntax:flex_bdry_info=DIE_BDRY,LOCK,..."
> +				 "DIE_BDRY: SLC boundary of the die"
> +				 "LOCK: Locking information for SLC boundary"
> +				 "    : 0->Set boundary in unlocked status"
> +				 "    : 1->Set boundary in locked status");
> +
>  /* Default Flex-OneNAND boundary and lock respectively */
>  static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };
> 
> @@ -3456,6 +3467,10 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
>  	if (onenand_probe(mtd))
>  		return -ENXIO;
> 
> +#ifdef MODULE
> +	flexonenand_setup(flex_bdry_info);
> +#endif

Why do you need this ifdef? What is the fundamental difference between
onenand.ko as a module and onenand compiled-in?
Amul Saha June 12, 2009, 11:57 a.m. UTC | #2
Hi Artem,

>> +#ifdef MODULE
>> + flexonenand_setup(flex_bdry_info);
>> +#endif
>
> Why do you need this ifdef? What is the fundamental difference between
> onenand.ko as a module and onenand compiled-in?
>

flexonenand_setup( ) need not be called, when OneNAND is built-in.
This function-call will cause overhead unwantedly on every boot, during OneNAND scan.

flexonenand_setup( ) call is needed only when it has been built as a module.

Regards,
Amul Kumar Saha
Artem Bityutskiy June 12, 2009, 12:03 p.m. UTC | #3
On Fri, 2009-06-12 at 17:27 +0530, Amul Saha wrote:
> Hi Artem,
> 
> >> +#ifdef MODULE
> >> + flexonenand_setup(flex_bdry_info);
> >> +#endif
> >
> > Why do you need this ifdef? What is the fundamental difference between
> > onenand.ko as a module and onenand compiled-in?
> >
> 
> flexonenand_setup( ) need not be called, when OneNAND is built-in.
> This function-call will cause overhead unwantedly on every boot, during OneNAND scan.
> 
> flexonenand_setup( ) call is needed only when it has been built as a module.

Why?
David Woodhouse June 12, 2009, 12:52 p.m. UTC | #4
On Fri, 2009-06-12 at 15:03 +0300, Artem Bityutskiy wrote:
> 
> > flexonenand_setup( ) call is needed only when it has been built as a
> module.
> 
> Why?

Because they're adding a 'flex_bdry_info' module parameter which is a
string, that they then process just the same way as the original command
line option.

I think that's the wrong approach -- please use module_param_array()
instead, so it sets the contents of the flex_bdry[] array directly and
you can remove the flexonenand_setup() function completely.

Please ensure that your email addresses in the Signed-off-by: line are
correct, too. None of this 'user at domain' nonsense.
Amul Saha June 12, 2009, 1:16 p.m. UTC | #5
>> >> +#ifdef MODULE
>> >> + flexonenand_setup(flex_bdry_info);
>> >> +#endif
>> >
>> > Why do you need this ifdef? What is the fundamental difference between
>> > onenand.ko as a module and onenand compiled-in?
>> >
>>
>> flexonenand_setup( ) need not be called, when OneNAND is built-in.
>> This function-call will cause overhead unwantedly on every boot, during OneNAND scan.
>>
>> flexonenand_setup( ) call is needed only when it has been built as a module.
>
> Why?
>

When Flex-OneNAND is built-in, the SLC boundary can be set by kernel command line.
During the boot up time, flexonenand_setup() gets invoked by kernel, on parsing the kernel
command line.

But when Flex-OneNAND is built as a module, SLC boundary information is passed as module
parameter.
So in this case flexonenand_setup() has to be called explicitly during insomd time
(module_init),  to set the desired boundary.
So without a compilation macro (#ifdef MODULE) flexonenand_setup() is invoked in onenand_scan,
even when it is built-in which is not needed.

I am not getting your point, could you please clarify?

Regards,
Amul Kumar Saha
David Woodhouse June 12, 2009, 1:32 p.m. UTC | #6
On Fri, 2009-06-12 at 18:46 +0530, Amul Saha wrote:
> >> >> +#ifdef MODULE
> >> >> + flexonenand_setup(flex_bdry_info);
> >> >> +#endif
> >> >
> >> > Why do you need this ifdef? What is the fundamental difference between
> >> > onenand.ko as a module and onenand compiled-in?
> >> >
> >>
> >> flexonenand_setup( ) need not be called, when OneNAND is built-in.
> >> This function-call will cause overhead unwantedly on every boot, during OneNAND scan.
> >>
> >> flexonenand_setup( ) call is needed only when it has been built as a module.
> >
> > Why?
> >
> 
> When Flex-OneNAND is built-in, the SLC boundary can be set by kernel command line.
> During the boot up time, flexonenand_setup() gets invoked by kernel, on parsing the kernel
> command line.
> 
> But when Flex-OneNAND is built as a module, SLC boundary information is passed as module
> parameter.
> So in this case flexonenand_setup() has to be called explicitly during insomd time
> (module_init),  to set the desired boundary.
> So without a compilation macro (#ifdef MODULE) flexonenand_setup() is invoked in onenand_scan,
> even when it is built-in which is not needed.
> 
> I am not getting your point, could you please clarify?

You can remove flexonenand_setup() and the __setup("onenand_brdy=")
completely, and use _only_ "module_param_array()". That will work both
for modules and for the built-in case.
Amul Saha June 12, 2009, 1:49 p.m. UTC | #7
Hi David,

>
> You can remove flexonenand_setup() and the __setup("onenand_brdy=")
> completely, and use _only_ "module_param_array()". That will work both
> for modules and for the built-in case.
>

OK , Got your point.
Working towards it, will come up with the updated patch.

Regards
Amul Kumar Saha
David Woodhouse June 22, 2009, 7:15 p.m. UTC | #8
On Fri, 2009-06-19 at 12:20 +0530, apgmoorthy wrote:
> Hi David,
> 
> Currenlty , Is there a way to use JFFS2 with MLC Memories ( NOP == 1 )?
> 
> If not , Felt that any one of the following patch can be of use
> 
> 1. http://lists.infradead.org/pipermail/linux-mtd/2007-December/020047.html
>           - Which removes the Clean Marker.

There was a reason for the cleanmarker -- it saved us from using
partly-erased blocks for data. Do you have some other way to guarantee
that this won't happen?

(Sorry, I think we may have had this discussion before, but I've
forgotten the conclusion, if there was one. It was academic at the time,
since we didn't have any solution for the paired-page insanity anyway. I
was mostly just burying my head in the sand and hoping this stupid 'MLC'
crap would go away.)
AYYANARPONNUSAMY GANGHEYAMOORTHY June 23, 2009, 12:52 p.m. UTC | #9
Hi David,  

On Tuesday, June 23, 2009 12:45 AM David Woodhouse wrote :
 
>> If not , Felt that any one of the following patch can be of use
>> 
>> 1. http://lists.infradead.org/pipermail/linux-mtd/2007-December/020047.html
>>           - Which removes the Clean Marker.

>There was a reason for the cleanmarker -- it saved us from using partly-erased blocks for data. Do you have some other way to
guarantee that this won't 
>happen?
- How about the second One (Refer Below Links), which leaves 1page/block for Cleanmarker.
   http://lists.infradead.org/pipermail/linux-mtd/2008-September/023101.html
   http://lists.infradead.org/pipermail/linux-mtd/2008-September/023044.html 
  
>(Sorry, I think we may have had this discussion before, but I've forgotten the conclusion, if there was one. It was academic at the
time, since we didn't >have any solution for the paired-page insanity anyway. 
- Right , I dont see any detailed discussion on this regard in the list.
  

With Regards
 Moorthy
David Woodhouse June 23, 2009, 1:19 p.m. UTC | #10
Your mail program is behaving very strangely -- your quotes are quite
hard to read. Is there any chance you could use a better one? I've tried
to clean it up, but it tends to make your replies hard to read. Some of
your replies are lacking correct References: headers too, so the
threading is broken.

On Tue, 2009-06-23 at 18:22 +0530, apgmoorthy wrote:
> >There was a reason for the cleanmarker -- it saved us from using 
> > partly-erased blocks for data. Do you have some other way to
> > guarantee that this won't happen?
>
> - How about the second One (Refer Below Links), which leaves
> 1page/block for Cleanmarker.
> 
> http://lists.infradead.org/pipermail/linux-mtd/2008-September/023101.html   http://lists.infradead.org/pipermail/linux-mtd/2008-September/023044.html 

Using one page per block for the cleanmarker would work, but seems
wasteful. I can think of one more approach which we might take -- erase
blocks only as we need them.

So instead of erasing blocks without cleanmarker _immediately_ on
startup, we just put them on a 'to be erased' list. Whenever the
empty_list is getting short of blocks, we erase another block from the
'to be erased' list and move it to the empty list.

It does mean that if you keep rebooting over and over again, you're
probably going to increase your erase count. But with a long-lived
system, it's likely to be more efficient than the large cleanmarker?

What do you think?
AYYANARPONNUSAMY GANGHEYAMOORTHY June 24, 2009, 6:50 a.m. UTC | #11
On Tuesday, June 23, 2009 6:50 PM David Woodhouse wrote:
 
> Your mail program is behaving very strangely -- your quotes are quite
> hard to read. Is there any chance you could use a better one? 

- Earlier Mailer had some issues , Now using a different one.
   
> So instead of erasing blocks without cleanmarker _immediately_ on
> startup, we just put them on a 'to be erased' list. Whenever the
> empty_list is getting short of blocks, we erase another block from the
> 'to be erased' list and move it to the empty list.
> 
> It does mean that if you keep rebooting over and over again, you're
> probably going to increase your erase count. But with a long-lived
> system, it's likely to be more efficient than the large cleanmarker?
> 
> What do you think?
> 

- Yes , the solution looks a better tradeoff.
  Will work in that direction and get a pacth.
  Later we can look into a way to optimize erase count. 

With Regards
 Moorthy
Amul Saha March 31, 2010, 9:53 a.m. UTC | #12
Hi David,

We have come up with an alternate solution to support MLC devices on JFFS2.

>>
>> Currenlty , Is there a way to use JFFS2 with MLC Memories ( NOP == 1 )?
>>
>> If not , Felt that any one of the following patch can be of use
>>
>> 1. http://lists.infradead.org/pipermail/linux-mtd/2007-December/020047.html
>>           - Which removes the Clean Marker.
>
> There was a reason for the cleanmarker -- it saved us from using
> partly-erased blocks for data. Do you have some other way to guarantee
> that this won't happen?
>
> (Sorry, I think we may have had this discussion before, but I've
> forgotten the conclusion, if there was one. It was academic at the time,
> since we didn't have any solution for the paired-page insanity anyway. I
> was mostly just burying my head in the sand and hoping this stupid 'MLC'
> crap would go away.)

New approach:-

We will have something known as the TOKEN_BLOCK.

TOKEN_BLOCK: A block used to store all the ready_to_use blocks related info.

ready_to_use blocks: These are blocks which are erased and ready to use,
 but don't have a usual CLEANMARKER on them. To save NOP for
 the 1st page of each block.

How it works:
1. Ask GC to provide a block, and use it as TOKEN_BLOCK on need basis.
2. In the provided block, we store all ready_to_use block info.
3. On remount; this info needs to be retreived.
    So, we shall make use of MAGIC_NUMBER signifying TOKEN_BLOCK,
    to identify the block containing the info.

Scan has to be modified, to identify the TOKEN_BLOCK and act accordingly.

Handling TOKEN_BLOCK
1. Make request for a block to be used as TOKEN_BLOCK.
2. List all the ready_to_use block info on the TOKEN_BLOCK contiguously.
3. Write the TOKEN_BLOCK's MAGIC_NUMBER in the OOB Area alongwith the
 ready_to_use info, in the Main Area.
4. On next update, ask GC to provide a fresh block.
5. Update this block accordingly as TOKEN_BLOCK.
6. Discard the previous TOKEN_BLOCK, and put it on dirty_list.

Let me know, about the feasibility of this design from your perspective.

This is just a base plan, and obvisouly there are a lot of things that have to be looked
into, before getting into the real imlpementation.

Regards,
Amul Kumar Saha
massimo cirillo March 31, 2010, 1:07 p.m. UTC | #13
Hi Amul,

> 3. Write the TOKEN_BLOCK's MAGIC_NUMBER in the OOB Area alongwith the
>  ready_to_use info, in the Main Area.
I think you should protect each ready_to_use block info in the TOKEN_BLOCK
with a CRC - as it was a node of JFFS2 - against power loss corruption.

> 4. On next update, ask GC to provide a fresh block.
What do you mean ? Each time a block is erased do you
update the TOKEN_BLOCK by using a new one ?
Amul Saha April 5, 2010, 11:10 a.m. UTC | #14
Hi,

>> 3. Write the TOKEN_BLOCK's MAGIC_NUMBER in the OOB Area alongwith the
>>  ready_to_use info, in the Main Area.
> I think you should protect each ready_to_use block info in the TOKEN_BLOCK
> with a CRC - as it was a node of JFFS2 - against power loss corruption.
>

Sure, I'll take that into account.

>> 4. On next update, ask GC to provide a fresh block.
> What do you mean ? Each time a block is erased do you
> update the TOKEN_BLOCK by using a new one ?
>

No.
That would be done only during a proper unmount or idle time.
As this block just contains ready_to_use block info,
that can be reconstructed, on remount.
Because any updation on fixed intervals will not be of use.
Neither will it be feasbale to update the TOKEN_BLOCK on every erase.
Please do comment.

Regards,
Amul
massimo cirillo April 5, 2010, 11:52 a.m. UTC | #15
Ok,
but at the remount how do you verify if the TOKEN_BLOCK
is updated or not (in case of power loss) ? I suggest using
a commit mark (one page wasted) at the end of the update
procedure.
So you'll have in the TOKEN_BLOCK the following layout:

MAGIC_NUMBER of the TOKEN_BLOCK
ready_to_use info
commit mark

What do you think ?

2010/4/5 Amul Kumar Saha <amul.saha@samsung.com>:
> Hi,
>
>>> 3. Write the TOKEN_BLOCK's MAGIC_NUMBER in the OOB Area alongwith the
>>>  ready_to_use info, in the Main Area.
>> I think you should protect each ready_to_use block info in the TOKEN_BLOCK
>> with a CRC - as it was a node of JFFS2 - against power loss corruption.
>>
>
> Sure, I'll take that into account.
>
>>> 4. On next update, ask GC to provide a fresh block.
>> What do you mean ? Each time a block is erased do you
>> update the TOKEN_BLOCK by using a new one ?
>>
>
> No.
> That would be done only during a proper unmount or idle time.
> As this block just contains ready_to_use block info,
> that can be reconstructed, on remount.
> Because any updation on fixed intervals will not be of use.
> Neither will it be feasbale to update the TOKEN_BLOCK on every erase.
> Please do comment.
>
> Regards,
> Amul
>
>
>
Amul Saha April 9, 2010, 9:21 a.m. UTC | #16
Hi,


>Ok,
>but at the remount how do you verify if the TOKEN_BLOCK
>is updated or not (in case of power loss) ? I suggest using
>a commit mark (one page wasted) at the end of the update
>procedure.
>So you'll have in the TOKEN_BLOCK the following layout:
>
>MAGIC_NUMBER of the TOKEN_BLOCK
>ready_to_use info
>commit mark
>
>What do you think ?
>

Yes.
However, the TOKEN_BLOCK update would then
only be limited to mount and unmount.
As writing a commit mark while the system is still running,
would validate an invalid block on abrupt power-off.

Regards,
Amul
massimo cirillo April 13, 2010, 9:45 a.m. UTC | #17
Hi,
I agree with you, and the following is my thinking.
Let's suppose we have a flash with 2KB page, 128KB block,
4096 blocks (512MB as size of the flash).
The cleanmarker would take one page for every block, so the
wasted space is 2KB*4096=8MB. Instead if we put the erased
info in a single block (TOKEN_BLOCK) we waste only 128KB.
But we need to consider the overhead in the management of
such a block. We need to store information for 4096 blocks,
for example an array of 4096 bit (1=erased, 0=not erased),
protected by ECC (against read error) and CRC (against
power loss in writing the array on the block). We need 2 pages
for each instance of the array. The question is: how often do we
need to update this array? If we choose to update each time it is
needed (that is when a block is  just erased and just before a block
is taken from the free list), at the 32nd update we should erase the
TOKEN_BLOCK and allocate a new one. IMO this overhead is
unacceptable in terms of time performance. So we update the info
only at the unmount and when the system is idle.
Moreover, there is the problem of power loss between two updates:
how to recognize at the mount that the array info is updated? In my
opinion the solution is to write an invalidation mark (one page with
all zeros) just after the instance of the array when the instance
becomes invalid.

Bye

2010/4/9 Amul Kumar Saha <amul.saha@samsung.com>:
> Hi,
>
>
>>Ok,
>>but at the remount how do you verify if the TOKEN_BLOCK
>>is updated or not (in case of power loss) ? I suggest using
>>a commit mark (one page wasted) at the end of the update
>>procedure.
>>So you'll have in the TOKEN_BLOCK the following layout:
>>
>>MAGIC_NUMBER of the TOKEN_BLOCK
>>ready_to_use info
>>commit mark
>>
>>What do you think ?
>>
>
> Yes.
> However, the TOKEN_BLOCK update would then
> only be limited to mount and unmount.
> As writing a commit mark while the system is still running,
> would validate an invalid block on abrupt power-off.
>
> Regards,
> Amul
>
>
>
massimo cirillo April 15, 2010, 9:03 p.m. UTC | #18
yes,
the update only at the unmount and the usage of the commit
mark are ok for me.

2010/4/15 Raghav Gupta <raghav.gupta@partner.samsung.com>:
> Resending it due to formatting issues. My bad.
>
> Hi,
>
>> I agree with you, and the following is my thinking.
>> Let's suppose we have a flash with 2KB page, 128KB block,
>> 4096 blocks (512MB as size of the flash).
>> The cleanmarker would take one page for every block, so the
>> wasted space is 2KB*4096=8MB. Instead if we put the erased
>> info in a single block (TOKEN_BLOCK) we waste only 128KB.
>> But we need to consider the overhead in the management of
>> such a block. We need to store information for 4096 blocks,
>> for example an array of 4096 bit (1=erased, 0=not erased),
>> protected by ECC (against read error) and CRC (against
>> power loss in writing the array on the block). We need 2 pages
>> for each instance of the array. The question is: how often do we
>> need to update this array? If we choose to update each time it is
>> needed (that is when a block is  just erased and just before a block
>> is taken from the free list), at the 32nd update we should erase the
>> TOKEN_BLOCK and allocate a new one. IMO this overhead is
>> unacceptable in terms of time performance. So we update the info
>> only at the unmount and when the system is idle.
>> Moreover, there is the problem of power loss between two updates:
>> how to recognize at the mount that the array info is updated? In my
>> opinion the solution is to write an invalidation mark (one page with
>> all zeros) just after the instance of the array when the instance
>> becomes invalid.
>
>
> Yes, I agree with you. The overhead involved in updating the token block
> on every change in the "ready_to_use" list is unacceptable.
> So, we can update the TOKEN_BLOCK only at unmount.
>
> Also we can authenticate that the TOKEN_BLOCK as valid
> by using a "valid/invalid flag"(commit mark)
>
> And to guard against reading of an older version of
> a TOKEN_BLOCK (on power failure) as valid by immediately
> deleting the block on retrieval of the 'ready_to_use' list.
>
> Regards,
> Raghav Gupta
>
>
>
massimo cirillo April 15, 2010, 9:26 p.m. UTC | #19
Resending the message due to a Mail Delivery
error returned by raghav.gupta@partner.samsung.com.

2010/4/15 massimo cirillo <maxcir@gmail.com>:
> yes,
> the update only at the unmount and the usage of the commit
> mark are ok for me.
>
> 2010/4/15 Raghav Gupta <raghav.gupta@partner.samsung.com>:
>> Resending it due to formatting issues. My bad.
>>
>> Hi,
>>
>>> I agree with you, and the following is my thinking.
>>> Let's suppose we have a flash with 2KB page, 128KB block,
>>> 4096 blocks (512MB as size of the flash).
>>> The cleanmarker would take one page for every block, so the
>>> wasted space is 2KB*4096=8MB. Instead if we put the erased
>>> info in a single block (TOKEN_BLOCK) we waste only 128KB.
>>> But we need to consider the overhead in the management of
>>> such a block. We need to store information for 4096 blocks,
>>> for example an array of 4096 bit (1=erased, 0=not erased),
>>> protected by ECC (against read error) and CRC (against
>>> power loss in writing the array on the block). We need 2 pages
>>> for each instance of the array. The question is: how often do we
>>> need to update this array? If we choose to update each time it is
>>> needed (that is when a block is  just erased and just before a block
>>> is taken from the free list), at the 32nd update we should erase the
>>> TOKEN_BLOCK and allocate a new one. IMO this overhead is
>>> unacceptable in terms of time performance. So we update the info
>>> only at the unmount and when the system is idle.
>>> Moreover, there is the problem of power loss between two updates:
>>> how to recognize at the mount that the array info is updated? In my
>>> opinion the solution is to write an invalidation mark (one page with
>>> all zeros) just after the instance of the array when the instance
>>> becomes invalid.
>>
>>
>> Yes, I agree with you. The overhead involved in updating the token block
>> on every change in the "ready_to_use" list is unacceptable.
>> So, we can update the TOKEN_BLOCK only at unmount.
>>
>> Also we can authenticate that the TOKEN_BLOCK as valid
>> by using a "valid/invalid flag"(commit mark)
>>
>> And to guard against reading of an older version of
>> a TOKEN_BLOCK (on power failure) as valid by immediately
>> deleting the block on retrieval of the 'ready_to_use' list.
>>
>> Regards,
>> Raghav Gupta
>>
>>
>>
>
diff mbox

Patch

diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 8d4c9c2..6d2086f 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -20,6 +20,7 @@ 

 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
@@ -31,6 +32,16 @@ 

 #include <asm/io.h>

+static char *flex_bdry_info;
+
+module_param(flex_bdry_info, charp, 0400);
+MODULE_PARM_DESC(flex_bdry_info, "SLC Boundary information for Flex-OneNAND"
+				 "Syntax:flex_bdry_info=DIE_BDRY,LOCK,..."
+				 "DIE_BDRY: SLC boundary of the die"
+				 "LOCK: Locking information for SLC boundary"
+				 "    : 0->Set boundary in unlocked status"
+				 "    : 1->Set boundary in locked status");
+
 /* Default Flex-OneNAND boundary and lock respectively */
 static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };

@@ -3456,6 +3467,10 @@  int onenand_scan(struct mtd_info *mtd, int maxchips)
 	if (onenand_probe(mtd))
 		return -ENXIO;

+#ifdef MODULE
+	flexonenand_setup(flex_bdry_info);
+#endif
+
 	/* Set Sync. Burst Read after probing */
 	if (this->mmcontrol) {
 		printk(KERN_INFO "OneNAND Sync. Burst Read support\n");