diff mbox series

[09/22] mtd: nand: automate NAND timings selection

Message ID 1511285912-12452-10-git-send-email-yamada.masahiro@socionext.com
State Accepted
Commit 27c4792cd233ba68fa15aaa885d0f53db7b5728a
Headers show
Series mtd: nand: imports NAND core updates from Linux 4.15-rc1 and sync Denali driver | expand

Commit Message

Masahiro Yamada Nov. 21, 2017, 5:38 p.m. UTC
From: Boris Brezillon <boris.brezillon@free-electrons.com>

The NAND framework provides several helpers to query timing modes supported
by a NAND chip, but this implies that all NAND controller drivers have
to implement the same timings selection dance. Also currently NAND
devices can be resetted at arbitrary places which also resets the timing
for ONFI chips to timing mode 0.

Provide a common logic to select the best timings based on ONFI or
->onfi_timing_mode_default information. Hook this into nand_reset()
to make sure the new timing is applied each time during a reset.

NAND controller willing to support timings adjustment should just
implement the ->setup_data_interface() method.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
[Linux commit: d8e725dd831186a3595036b2b1df9f68cbc6efa3]
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>

---

 drivers/mtd/nand/nand_base.c | 155 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h     |  14 ++--
 2 files changed, 165 insertions(+), 4 deletions(-)

Comments

York Sun Dec. 4, 2017, 10:37 p.m. UTC | #1
On 11/21/2017 09:47 AM, Masahiro Yamada wrote:
> From: Boris Brezillon <boris.brezillon@free-electrons.com>
> 
> The NAND framework provides several helpers to query timing modes supported
> by a NAND chip, but this implies that all NAND controller drivers have
> to implement the same timings selection dance. Also currently NAND
> devices can be resetted at arbitrary places which also resets the timing
> for ONFI chips to timing mode 0.
> 
> Provide a common logic to select the best timings based on ONFI or
> ->onfi_timing_mode_default information. Hook this into nand_reset()
> to make sure the new timing is applied each time during a reset.
> 
> NAND controller willing to support timings adjustment should just
> implement the ->setup_data_interface() method.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> [Linux commit: d8e725dd831186a3595036b2b1df9f68cbc6efa3]
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> 
> ---
> 
>  drivers/mtd/nand/nand_base.c | 155 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/nand.h     |  14 ++--
>  2 files changed, 165 insertions(+), 4 deletions(-)
> 

I am having a weird problem with this patch. My board is T2080QDS,
powerpc-based. Booting from SD, if the environmental variable sectors
are invalid, the default variables are loaded. U-Boot crashes after
hitting a key to stop the autoboot. However, if the environmental
variables are valid (even with the default values), U-Boot is fine. Git
bisect points to this patch. I don't see a direct connection between
this patch and the failure. Any suggestion?

Please see the log with this commit (27c4792cd23) and one commit before
this (b893e83330662).

York


Log 1, failing case with invalid environment

SD boot...
Initializing....using SPD
WARNING: Calling __hwconfig without a buffer and before environment is ready
WARNING: Calling __hwconfig without a buffer and before environment is ready
WARNING: Calling __hwconfig without a buffer and before environment is ready
WARNING: Calling __hwconfig without a buffer and before environment is ready
6 GiB left unmapped


U-Boot 2017.11-00208-g27c4792 (Dec 04 2017 - 14:18:57 -0800)

CPU0:  T2080E, Version: 1.1, (0x85380011)
Core:  e6500, Version: 2.0, (0x80400120)
Clock Configuration:
       CPU0:1200 MHz, CPU1:1200 MHz, CPU2:1200 MHz, CPU3:1200 MHz,
       CCB:400  MHz,
       DDR:933.333 MHz (1866.667 MT/s data rate) (Asynchronous), IFC:400
 MHz
       FMAN1: 466.667 MHz
       QMAN:  200 MHz
       PME:   400 MHz
L1:    D-cache 32 KiB enabled
       I-cache 32 KiB enabled
Reset Configuration Word (RCW):
       00000000: 0c070012 0e000000 00000000 00000000
       00000010: 66150002 00000000 68104000 c1000000
       00000020: 00000000 00000000 00000000 000307fc
       00000030: 00000000 00000000 00000000 00000004
Board: T2080QDS, Sys ID: 0x28, Board Arch: V1, Board Version: A, boot
from SD/MMC
FPGA: v11 (T1040QDS_2014_0318_1724), build 317 on Tue Mar 18 21:24:26 2014
SERDES Reference Clocks:
SD1_CLK1=156.25MHZ, SD1_CLK2=100.00MHz
SD2_CLK1=100.00MHz, SD2_CLK2=100.00MHz
I2C:   ready
SPI:   ready
DRAM:  Detected UDIMM
6 GiB left unmapped
8 GiB (DDR3, 64-bit, CL=13, ECC on)
Flash: 128 MiB
L2:    2 MiB enabled
Corenet Platform Cache: 512 KiB enabled
Using SERDES1 Protocol: 102 (0x66)
Using SERDES2 Protocol: 21 (0x15)
SRIO1: disabled
SRIO2: disabled
RNG: Instantiation failed with error 2000025b
SEC0: RNG instantiated
NAND:  512 MiB
MMC:   FSL_SDHC: 0
*** Warning - bad CRC, using default environment

EEPROM: NXID v1
PCIe1: Root Complex, x1 gen1, regs @ 0xfe240000
  01:00.0     - 8086:107d - Network controller
PCIe1: Bus 00 - 01
PCIe2: Root Complex, no link, regs @ 0xfe250000
PCIe2: Bus 02 - 02
PCIe3: disabled
PCIe4: Root Complex, no link, regs @ 0xfe270000
PCIe4: Bus 03 - 03
In:    serial
Out:   serial
Err:   serial
Net:
MMC read: dev # 0, block # 2080, count 128 ...
Fman1: Data at 7faf67d0 is not a firmware
e1000#0: Out of Memory!
No ethernet found.
Hit any key to stop autoboot:  0
(York: Hit a key to stop the counting down here)
ERROR : memory not allocated

(Hanging here)


Log 2, passing case with invalid environment

SD boot...
Initializing....using SPD
WARNING: Calling __hwconfig without a buffer and before environment is ready
WARNING: Calling __hwconfig without a buffer and before environment is ready
WARNING: Calling __hwconfig without a buffer and before environment is ready
WARNING: Calling __hwconfig without a buffer and before environment is ready
6 GiB left unmapped


U-Boot 2017.11-00207-gb893e83 (Dec 04 2017 - 14:17:47 -0800)

CPU0:  T2080E, Version: 1.1, (0x85380011)
Core:  e6500, Version: 2.0, (0x80400120)
Clock Configuration:
       CPU0:1200 MHz, CPU1:1200 MHz, CPU2:1200 MHz, CPU3:1200 MHz,
       CCB:400  MHz,
       DDR:933.333 MHz (1866.667 MT/s data rate) (Asynchronous), IFC:400
 MHz
       FMAN1: 466.667 MHz
       QMAN:  200 MHz
       PME:   400 MHz
L1:    D-cache 32 KiB enabled
       I-cache 32 KiB enabled
Reset Configuration Word (RCW):
       00000000: 0c070012 0e000000 00000000 00000000
       00000010: 66150002 00000000 68104000 c1000000
       00000020: 00000000 00000000 00000000 000307fc
       00000030: 00000000 00000000 00000000 00000004
Board: T2080QDS, Sys ID: 0x28, Board Arch: V1, Board Version: A, boot
from SD/MMC
FPGA: v11 (T1040QDS_2014_0318_1724), build 317 on Tue Mar 18 21:24:26 2014
SERDES Reference Clocks:
SD1_CLK1=156.25MHZ, SD1_CLK2=100.00MHz
SD2_CLK1=100.00MHz, SD2_CLK2=100.00MHz
I2C:   ready
SPI:   ready
DRAM:  Detected UDIMM
6 GiB left unmapped
8 GiB (DDR3, 64-bit, CL=13, ECC on)
Flash: 128 MiB
L2:    2 MiB enabled
Corenet Platform Cache: 512 KiB enabled
Using SERDES1 Protocol: 102 (0x66)
Using SERDES2 Protocol: 21 (0x15)
SRIO1: disabled
SRIO2: disabled
RNG: Instantiation failed with error 2000025b
SEC0: RNG instantiated
NAND:  512 MiB
MMC:   FSL_SDHC: 0
*** Warning - bad CRC, using default environment

EEPROM: NXID v1
PCIe1: Root Complex, x1 gen1, regs @ 0xfe240000
  01:00.0     - 8086:107d - Network controller
PCIe1: Bus 00 - 01
PCIe2: Root Complex, no link, regs @ 0xfe250000
PCIe2: Bus 02 - 02
PCIe3: disabled
PCIe4: Root Complex, no link, regs @ 0xfe270000
PCIe4: Bus 03 - 03
In:    serial
Out:   serial
Err:   serial
Net:
MMC read: dev # 0, block # 2080, count 128 ...
Fman1: Data at 7faf67c0 is not a firmware
e1000: 00:15:17:bf:ed:40
       e1000#0
Warning: e1000#0 MAC addresses don't match:
Address in SROM is         00:15:17:bf:ed:40
Address in environment is  00:04:9f:03:0a:24

Hit any key to stop autoboot:  0
(York: hit a key to stop the counting down here)
=>
=>
=> saveenv
Saving Environment to MMC...
Writing to MMC(0)... done


Log 3, with valid environment, the failing case passes.

SD boot...
Initializing....using SPD
6 GiB left unmapped


U-Boot 2017.11-00208-g27c4792 (Dec 04 2017 - 14:33:34 -0800)

CPU0:  T2080E, Version: 1.1, (0x85380011)
Core:  e6500, Version: 2.0, (0x80400120)
Clock Configuration:
       CPU0:1200 MHz, CPU1:1200 MHz, CPU2:1200 MHz, CPU3:1200 MHz,
       CCB:400  MHz,
       DDR:933.333 MHz (1866.667 MT/s data rate) (Asynchronous), IFC:400
 MHz
       FMAN1: 466.667 MHz
       QMAN:  200 MHz
       PME:   400 MHz
L1:    D-cache 32 KiB enabled
       I-cache 32 KiB enabled
Reset Configuration Word (RCW):
       00000000: 0c070012 0e000000 00000000 00000000
       00000010: 66150002 00000000 68104000 c1000000
       00000020: 00000000 00000000 00000000 000307fc
       00000030: 00000000 00000000 00000000 00000004
Board: T2080QDS, Sys ID: 0x28, Board Arch: V1, Board Version: A, boot
from SD/MMC
FPGA: v11 (T1040QDS_2014_0318_1724), build 317 on Tue Mar 18 21:24:26 2014
SERDES Reference Clocks:
SD1_CLK1=156.25MHZ, SD1_CLK2=100.00MHz
SD2_CLK1=100.00MHz, SD2_CLK2=100.00MHz
I2C:   ready
SPI:   ready
DRAM:  Detected UDIMM
6 GiB left unmapped
8 GiB (DDR3, 64-bit, CL=13, ECC on)
       DDR Chip-Select Interleaving Mode: CS0+CS1
Flash: 128 MiB
L2:    2 MiB enabled
Corenet Platform Cache: 512 KiB enabled
Using SERDES1 Protocol: 102 (0x66)
Using SERDES2 Protocol: 21 (0x15)
SRIO1: disabled
SRIO2: disabled
RNG: Instantiation failed with error 2000025b
SEC0: RNG instantiated
NAND:  512 MiB
MMC:   FSL_SDHC: 0
EEPROM: NXID v1
PCIe1: Root Complex, x1 gen1, regs @ 0xfe240000
  01:00.0     - 8086:107d - Network controller
PCIe1: Bus 00 - 01
PCIe2: Root Complex, no link, regs @ 0xfe250000
PCIe2: Bus 02 - 02
PCIe3: disabled
PCIe4: Root Complex, no link, regs @ 0xfe270000
PCIe4: Bus 03 - 03
In:    serial
Out:   serial
Err:   serial
Net:
MMC read: dev # 0, block # 2080, count 128 ...
Fman1: Data at 7faf8f48 is not a firmware
e1000: 00:15:17:bf:ed:40
       e1000#0
Warning: e1000#0 MAC addresses don't match:
Address in SROM is         00:15:17:bf:ed:40
Address in environment is  00:04:9f:03:0a:24

Hit any key to stop autoboot:  0
=>
=>
=>
=>
Masahiro Yamada Dec. 5, 2017, 12:30 a.m. UTC | #2
2017-12-05 7:37 GMT+09:00 York Sun <york.sun@nxp.com>:
> On 11/21/2017 09:47 AM, Masahiro Yamada wrote:
>> From: Boris Brezillon <boris.brezillon@free-electrons.com>
>>
>> The NAND framework provides several helpers to query timing modes supported
>> by a NAND chip, but this implies that all NAND controller drivers have
>> to implement the same timings selection dance. Also currently NAND
>> devices can be resetted at arbitrary places which also resets the timing
>> for ONFI chips to timing mode 0.
>>
>> Provide a common logic to select the best timings based on ONFI or
>> ->onfi_timing_mode_default information. Hook this into nand_reset()
>> to make sure the new timing is applied each time during a reset.
>>
>> NAND controller willing to support timings adjustment should just
>> implement the ->setup_data_interface() method.
>>
>> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
>> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>> [Linux commit: d8e725dd831186a3595036b2b1df9f68cbc6efa3]
>> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>>
>> ---
>>
>>  drivers/mtd/nand/nand_base.c | 155 +++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/mtd/nand.h     |  14 ++--
>>  2 files changed, 165 insertions(+), 4 deletions(-)
>>
>
> I am having a weird problem with this patch. My board is T2080QDS,
> powerpc-based. Booting from SD, if the environmental variable sectors
> are invalid, the default variables are loaded. U-Boot crashes after
> hitting a key to stop the autoboot. However, if the environmental
> variables are valid (even with the default values), U-Boot is fine. Git
> bisect points to this patch. I don't see a direct connection between
> this patch and the failure. Any suggestion?
>
> Please see the log with this commit (27c4792cd23) and one commit before
> this (b893e83330662).
>
> York
>
>
> Log 1, failing case with invalid environment
>
> SD boot...
> Initializing....using SPD
> WARNING: Calling __hwconfig without a buffer and before environment is ready
> WARNING: Calling __hwconfig without a buffer and before environment is ready
> WARNING: Calling __hwconfig without a buffer and before environment is ready
> WARNING: Calling __hwconfig without a buffer and before environment is ready
> 6 GiB left unmapped
>
>
> U-Boot 2017.11-00208-g27c4792 (Dec 04 2017 - 14:18:57 -0800)
>
> CPU0:  T2080E, Version: 1.1, (0x85380011)
> Core:  e6500, Version: 2.0, (0x80400120)
> Clock Configuration:
>        CPU0:1200 MHz, CPU1:1200 MHz, CPU2:1200 MHz, CPU3:1200 MHz,
>        CCB:400  MHz,
>        DDR:933.333 MHz (1866.667 MT/s data rate) (Asynchronous), IFC:400
>  MHz
>        FMAN1: 466.667 MHz
>        QMAN:  200 MHz
>        PME:   400 MHz
> L1:    D-cache 32 KiB enabled
>        I-cache 32 KiB enabled
> Reset Configuration Word (RCW):
>        00000000: 0c070012 0e000000 00000000 00000000
>        00000010: 66150002 00000000 68104000 c1000000
>        00000020: 00000000 00000000 00000000 000307fc
>        00000030: 00000000 00000000 00000000 00000004
> Board: T2080QDS, Sys ID: 0x28, Board Arch: V1, Board Version: A, boot
> from SD/MMC
> FPGA: v11 (T1040QDS_2014_0318_1724), build 317 on Tue Mar 18 21:24:26 2014
> SERDES Reference Clocks:
> SD1_CLK1=156.25MHZ, SD1_CLK2=100.00MHz
> SD2_CLK1=100.00MHz, SD2_CLK2=100.00MHz
> I2C:   ready
> SPI:   ready
> DRAM:  Detected UDIMM
> 6 GiB left unmapped
> 8 GiB (DDR3, 64-bit, CL=13, ECC on)
> Flash: 128 MiB
> L2:    2 MiB enabled
> Corenet Platform Cache: 512 KiB enabled
> Using SERDES1 Protocol: 102 (0x66)
> Using SERDES2 Protocol: 21 (0x15)
> SRIO1: disabled
> SRIO2: disabled
> RNG: Instantiation failed with error 2000025b
> SEC0: RNG instantiated
> NAND:  512 MiB
> MMC:   FSL_SDHC: 0
> *** Warning - bad CRC, using default environment
>
> EEPROM: NXID v1
> PCIe1: Root Complex, x1 gen1, regs @ 0xfe240000
>   01:00.0     - 8086:107d - Network controller
> PCIe1: Bus 00 - 01
> PCIe2: Root Complex, no link, regs @ 0xfe250000
> PCIe2: Bus 02 - 02
> PCIe3: disabled
> PCIe4: Root Complex, no link, regs @ 0xfe270000
> PCIe4: Bus 03 - 03
> In:    serial
> Out:   serial
> Err:   serial
> Net:
> MMC read: dev # 0, block # 2080, count 128 ...
> Fman1: Data at 7faf67d0 is not a firmware
> e1000#0: Out of Memory!


Looks like malloc() failed.


> No ethernet found.
> Hit any key to stop autoboot:  0
> (York: Hit a key to stop the counting down here)
> ERROR : memory not allocated


This error message comes from xmalloc() or xrealloc().



I think your board grew in size by my commit.


Does disabling some features solve your problem?
York Sun Dec. 5, 2017, 12:34 a.m. UTC | #3
On 12/04/2017 04:31 PM, Masahiro Yamada wrote:
> 2017-12-05 7:37 GMT+09:00 York Sun <york.sun@nxp.com>:
>> On 11/21/2017 09:47 AM, Masahiro Yamada wrote:
>>> From: Boris Brezillon <boris.brezillon@free-electrons.com>
>>>
>>> The NAND framework provides several helpers to query timing modes supported
>>> by a NAND chip, but this implies that all NAND controller drivers have
>>> to implement the same timings selection dance. Also currently NAND
>>> devices can be resetted at arbitrary places which also resets the timing
>>> for ONFI chips to timing mode 0.
>>>
>>> Provide a common logic to select the best timings based on ONFI or
>>> ->onfi_timing_mode_default information. Hook this into nand_reset()
>>> to make sure the new timing is applied each time during a reset.
>>>
>>> NAND controller willing to support timings adjustment should just
>>> implement the ->setup_data_interface() method.
>>>
>>> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
>>> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>>> [Linux commit: d8e725dd831186a3595036b2b1df9f68cbc6efa3]
>>> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>>>
>>> ---
>>>
>>>  drivers/mtd/nand/nand_base.c | 155 +++++++++++++++++++++++++++++++++++++++++++
>>>  include/linux/mtd/nand.h     |  14 ++--
>>>  2 files changed, 165 insertions(+), 4 deletions(-)
>>>
>>
>> I am having a weird problem with this patch. My board is T2080QDS,
>> powerpc-based. Booting from SD, if the environmental variable sectors
>> are invalid, the default variables are loaded. U-Boot crashes after
>> hitting a key to stop the autoboot. However, if the environmental
>> variables are valid (even with the default values), U-Boot is fine. Git
>> bisect points to this patch. I don't see a direct connection between
>> this patch and the failure. Any suggestion?
>>
>> Please see the log with this commit (27c4792cd23) and one commit before
>> this (b893e83330662).
>>
>> York
>>
>>
>> Log 1, failing case with invalid environment
>>
>> SD boot...
>> Initializing....using SPD
>> WARNING: Calling __hwconfig without a buffer and before environment is ready
>> WARNING: Calling __hwconfig without a buffer and before environment is ready
>> WARNING: Calling __hwconfig without a buffer and before environment is ready
>> WARNING: Calling __hwconfig without a buffer and before environment is ready
>> 6 GiB left unmapped
>>
>>
>> U-Boot 2017.11-00208-g27c4792 (Dec 04 2017 - 14:18:57 -0800)
>>
>> CPU0:  T2080E, Version: 1.1, (0x85380011)
>> Core:  e6500, Version: 2.0, (0x80400120)
>> Clock Configuration:
>>        CPU0:1200 MHz, CPU1:1200 MHz, CPU2:1200 MHz, CPU3:1200 MHz,
>>        CCB:400  MHz,
>>        DDR:933.333 MHz (1866.667 MT/s data rate) (Asynchronous), IFC:400
>>  MHz
>>        FMAN1: 466.667 MHz
>>        QMAN:  200 MHz
>>        PME:   400 MHz
>> L1:    D-cache 32 KiB enabled
>>        I-cache 32 KiB enabled
>> Reset Configuration Word (RCW):
>>        00000000: 0c070012 0e000000 00000000 00000000
>>        00000010: 66150002 00000000 68104000 c1000000
>>        00000020: 00000000 00000000 00000000 000307fc
>>        00000030: 00000000 00000000 00000000 00000004
>> Board: T2080QDS, Sys ID: 0x28, Board Arch: V1, Board Version: A, boot
>> from SD/MMC
>> FPGA: v11 (T1040QDS_2014_0318_1724), build 317 on Tue Mar 18 21:24:26 2014
>> SERDES Reference Clocks:
>> SD1_CLK1=156.25MHZ, SD1_CLK2=100.00MHz
>> SD2_CLK1=100.00MHz, SD2_CLK2=100.00MHz
>> I2C:   ready
>> SPI:   ready
>> DRAM:  Detected UDIMM
>> 6 GiB left unmapped
>> 8 GiB (DDR3, 64-bit, CL=13, ECC on)
>> Flash: 128 MiB
>> L2:    2 MiB enabled
>> Corenet Platform Cache: 512 KiB enabled
>> Using SERDES1 Protocol: 102 (0x66)
>> Using SERDES2 Protocol: 21 (0x15)
>> SRIO1: disabled
>> SRIO2: disabled
>> RNG: Instantiation failed with error 2000025b
>> SEC0: RNG instantiated
>> NAND:  512 MiB
>> MMC:   FSL_SDHC: 0
>> *** Warning - bad CRC, using default environment
>>
>> EEPROM: NXID v1
>> PCIe1: Root Complex, x1 gen1, regs @ 0xfe240000
>>   01:00.0     - 8086:107d - Network controller
>> PCIe1: Bus 00 - 01
>> PCIe2: Root Complex, no link, regs @ 0xfe250000
>> PCIe2: Bus 02 - 02
>> PCIe3: disabled
>> PCIe4: Root Complex, no link, regs @ 0xfe270000
>> PCIe4: Bus 03 - 03
>> In:    serial
>> Out:   serial
>> Err:   serial
>> Net:
>> MMC read: dev # 0, block # 2080, count 128 ...
>> Fman1: Data at 7faf67d0 is not a firmware
>> e1000#0: Out of Memory!
> 
> 
> Looks like malloc() failed.
> 
> 
>> No ethernet found.
>> Hit any key to stop autoboot:  0
>> (York: Hit a key to stop the counting down here)
>> ERROR : memory not allocated
> 
> 
> This error message comes from xmalloc() or xrealloc().
> 
> 
> 
> I think your board grew in size by my commit.
> 
> 
> Does disabling some features solve your problem?
> 

Hmm, _this_ patch doesn't add much. I will try again with some features
removed.

York
York Sun Dec. 5, 2017, 4:38 p.m. UTC | #4
On 12/04/2017 04:31 PM, Masahiro Yamada wrote:
>> Err:   serial
>> Net:
>> MMC read: dev # 0, block # 2080, count 128 ...
>> Fman1: Data at 7faf67d0 is not a firmware
>> e1000#0: Out of Memory!
> 
> 
> Looks like malloc() failed.
> 
> 
>> No ethernet found.
>> Hit any key to stop autoboot:  0
>> (York: Hit a key to stop the counting down here)
>> ERROR : memory not allocated
> 
> 
> This error message comes from xmalloc() or xrealloc().
> 
> 
> 
> I think your board grew in size by my commit.
> 
> 
> Does disabling some features solve your problem?
> 
I tried to disable USB feature and reduced the image size, but that
didn't fix this issue. I don't believe NAND driver has anything to do
with this issue though. I will keep debugging.

York
York Sun Dec. 5, 2017, 7:48 p.m. UTC | #5
On 12/05/2017 08:38 AM, York Sun wrote:
> On 12/04/2017 04:31 PM, Masahiro Yamada wrote:
>>> Err:   serial
>>> Net:
>>> MMC read: dev # 0, block # 2080, count 128 ...
>>> Fman1: Data at 7faf67d0 is not a firmware
>>> e1000#0: Out of Memory!
>>
>>
>> Looks like malloc() failed.
>>
>>
>>> No ethernet found.
>>> Hit any key to stop autoboot:  0
>>> (York: Hit a key to stop the counting down here)
>>> ERROR : memory not allocated
>>
>>
>> This error message comes from xmalloc() or xrealloc().
>>
>>
>>
>> I think your board grew in size by my commit.
>>
>>
>> Does disabling some features solve your problem?
>>
> I tried to disable USB feature and reduced the image size, but that
> didn't fix this issue. I don't believe NAND driver has anything to do
> with this issue though. I will keep debugging.
> 

I think I found the root cause. It is dcache related. I am testing on
more platform before sending out a patch.

Sorry for the noise.

York
diff mbox series

Patch

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 77da6fa..f452f59 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -902,6 +902,148 @@  static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 }
 
 /**
+ * nand_reset_data_interface - Reset data interface and timings
+ * @chip: The NAND chip
+ *
+ * Reset the Data interface and timings to ONFI mode 0.
+ *
+ * Returns 0 for success or negative error code otherwise.
+ */
+static int nand_reset_data_interface(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	const struct nand_data_interface *conf;
+	int ret;
+
+	if (!chip->setup_data_interface)
+		return 0;
+
+	/*
+	 * The ONFI specification says:
+	 * "
+	 * To transition from NV-DDR or NV-DDR2 to the SDR data
+	 * interface, the host shall use the Reset (FFh) command
+	 * using SDR timing mode 0. A device in any timing mode is
+	 * required to recognize Reset (FFh) command issued in SDR
+	 * timing mode 0.
+	 * "
+	 *
+	 * Configure the data interface in SDR mode and set the
+	 * timings to timing mode 0.
+	 */
+
+	conf = nand_get_default_data_interface();
+	ret = chip->setup_data_interface(mtd, conf, false);
+	if (ret)
+		pr_err("Failed to configure data interface to SDR timing mode 0\n");
+
+	return ret;
+}
+
+/**
+ * nand_setup_data_interface - Setup the best data interface and timings
+ * @chip: The NAND chip
+ *
+ * Find and configure the best data interface and NAND timings supported by
+ * the chip and the driver.
+ * First tries to retrieve supported timing modes from ONFI information,
+ * and if the NAND chip does not support ONFI, relies on the
+ * ->onfi_timing_mode_default specified in the nand_ids table.
+ *
+ * Returns 0 for success or negative error code otherwise.
+ */
+static int nand_setup_data_interface(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int ret;
+
+	if (!chip->setup_data_interface || !chip->data_interface)
+		return 0;
+
+	/*
+	 * Ensure the timing mode has been changed on the chip side
+	 * before changing timings on the controller side.
+	 */
+	if (chip->onfi_version) {
+		u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
+			chip->onfi_timing_mode_default,
+		};
+
+		ret = chip->onfi_set_features(mtd, chip,
+				ONFI_FEATURE_ADDR_TIMING_MODE,
+				tmode_param);
+		if (ret)
+			goto err;
+	}
+
+	ret = chip->setup_data_interface(mtd, chip->data_interface, false);
+err:
+	return ret;
+}
+
+/**
+ * nand_init_data_interface - find the best data interface and timings
+ * @chip: The NAND chip
+ *
+ * Find the best data interface and NAND timings supported by the chip
+ * and the driver.
+ * First tries to retrieve supported timing modes from ONFI information,
+ * and if the NAND chip does not support ONFI, relies on the
+ * ->onfi_timing_mode_default specified in the nand_ids table. After this
+ * function nand_chip->data_interface is initialized with the best timing mode
+ * available.
+ *
+ * Returns 0 for success or negative error code otherwise.
+ */
+static int nand_init_data_interface(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int modes, mode, ret;
+
+	if (!chip->setup_data_interface)
+		return 0;
+
+	/*
+	 * First try to identify the best timings from ONFI parameters and
+	 * if the NAND does not support ONFI, fallback to the default ONFI
+	 * timing mode.
+	 */
+	modes = onfi_get_async_timing_mode(chip);
+	if (modes == ONFI_TIMING_MODE_UNKNOWN) {
+		if (!chip->onfi_timing_mode_default)
+			return 0;
+
+		modes = GENMASK(chip->onfi_timing_mode_default, 0);
+	}
+
+	chip->data_interface = kzalloc(sizeof(*chip->data_interface),
+				       GFP_KERNEL);
+	if (!chip->data_interface)
+		return -ENOMEM;
+
+	for (mode = fls(modes) - 1; mode >= 0; mode--) {
+		ret = onfi_init_data_interface(chip, chip->data_interface,
+					       NAND_SDR_IFACE, mode);
+		if (ret)
+			continue;
+
+		ret = chip->setup_data_interface(mtd, chip->data_interface,
+						 true);
+		if (!ret) {
+			chip->onfi_timing_mode_default = mode;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void __maybe_unused nand_release_data_interface(struct nand_chip *chip)
+{
+	kfree(chip->data_interface);
+}
+
+/**
  * nand_reset - Reset and initialize a NAND device
  * @chip: The NAND chip
  *
@@ -910,9 +1052,18 @@  static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 int nand_reset(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	int ret;
+
+	ret = nand_reset_data_interface(chip);
+	if (ret)
+		return ret;
 
 	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
+	ret = nand_setup_data_interface(chip);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -3882,6 +4033,10 @@  int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 		return PTR_ERR(type);
 	}
 
+	ret = nand_init_data_interface(chip);
+	if (ret)
+		return ret;
+
 	chip->select_chip(mtd, -1);
 
 	/* Check for a chip array */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 0b9fe3f..274bd8d 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -764,10 +764,9 @@  nand_get_sdr_timings(const struct nand_data_interface *conf)
  *                      also from the datasheet. It is the recommended ECC step
  *			size, if known; if unknown, set to zero.
  * @onfi_timing_mode_default: [INTERN] default ONFI timing mode. This field is
- *			      either deduced from the datasheet if the NAND
- *			      chip is not ONFI compliant or set to 0 if it is
- *			      (an ONFI chip is always configured in mode 0
- *			      after a NAND reset)
+ *			      set to the actually used ONFI mode if the chip is
+ *			      ONFI compliant or deduced from the datasheet if
+ *			      the NAND chip is not ONFI compliant.
  * @numchips:		[INTERN] number of physical chips
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
@@ -787,6 +786,7 @@  nand_get_sdr_timings(const struct nand_data_interface *conf)
  * @read_retries:	[INTERN] the number of read retry modes supported
  * @onfi_set_features:	[REPLACEABLE] set the features for ONFI nand
  * @onfi_get_features:	[REPLACEABLE] get the features for ONFI nand
+ * @setup_data_interface: [OPTIONAL] setup the data interface and timing
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
  *			lookup.
@@ -835,6 +835,10 @@  struct nand_chip {
 	int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
 			int feature_addr, uint8_t *subfeature_para);
 	int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);
+	int (*setup_data_interface)(struct mtd_info *mtd,
+				    const struct nand_data_interface *conf,
+				    bool check_only);
+
 
 	int chip_delay;
 	unsigned int options;
@@ -862,6 +866,8 @@  struct nand_chip {
 	struct nand_onfi_params	onfi_params;
 	struct nand_jedec_params jedec_params;
  
+	struct nand_data_interface *data_interface;
+
 	int read_retries;
 
 	flstate_t state;