diff mbox

[U-Boot,v2] dm: implement a cfi flash uclass

Message ID 1444548628-10119-1-git-send-email-thomas@wytron.com.tw
State Changes Requested
Delegated to: Simon Glass
Headers show

Commit Message

Thomas Chou Oct. 11, 2015, 7:30 a.m. UTC
Implement a cfi flash uclass to work with drivers/mtd/cfi-flash.c.
The flash base address is extracted from device tree, and passed
to cfi_flash_bank_addr().

The current code supports only one bank. It should be extended to
support multiple banks by decoding multiple "reg" tuples, eg,
	reg = <0 0x00000000 0x02000000
	       0 0x02000000 0x02000000>;

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
v2
  add dts binding.
  add more help to Kconfig.
  move struct platdata to top of file as Simon suggested.

 common/board_r.c                             |  3 +
 configs/nios2-generic_defconfig              |  1 +
 doc/device-tree-bindings/mtd/mtd-physmap.txt | 88 ++++++++++++++++++++++++++++
 drivers/mtd/Kconfig                          | 16 +++++
 drivers/mtd/Makefile                         |  1 +
 drivers/mtd/cfi-flash-uclass.c               | 70 ++++++++++++++++++++++
 drivers/mtd/cfi_flash.c                      | 18 ++++++
 include/cfi-flash.h                          | 27 +++++++++
 include/dm/uclass-id.h                       |  1 +
 9 files changed, 225 insertions(+)
 create mode 100644 doc/device-tree-bindings/mtd/mtd-physmap.txt
 create mode 100644 drivers/mtd/cfi-flash-uclass.c
 create mode 100644 include/cfi-flash.h

Comments

Bin Meng Oct. 11, 2015, 7:54 a.m. UTC | #1
+Simon,

Hi Thomas,

On Sun, Oct 11, 2015 at 3:30 PM, Thomas Chou <thomas@wytron.com.tw> wrote:
> Implement a cfi flash uclass to work with drivers/mtd/cfi-flash.c.
> The flash base address is extracted from device tree, and passed
> to cfi_flash_bank_addr().
>
> The current code supports only one bank. It should be extended to
> support multiple banks by decoding multiple "reg" tuples, eg,
>         reg = <0 0x00000000 0x02000000
>                0 0x02000000 0x02000000>;
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
> v2
>   add dts binding.
>   add more help to Kconfig.
>   move struct platdata to top of file as Simon suggested.
>
>  common/board_r.c                             |  3 +
>  configs/nios2-generic_defconfig              |  1 +
>  doc/device-tree-bindings/mtd/mtd-physmap.txt | 88 ++++++++++++++++++++++++++++
>  drivers/mtd/Kconfig                          | 16 +++++
>  drivers/mtd/Makefile                         |  1 +
>  drivers/mtd/cfi-flash-uclass.c               | 70 ++++++++++++++++++++++
>  drivers/mtd/cfi_flash.c                      | 18 ++++++
>  include/cfi-flash.h                          | 27 +++++++++
>  include/dm/uclass-id.h                       |  1 +
>  9 files changed, 225 insertions(+)
>  create mode 100644 doc/device-tree-bindings/mtd/mtd-physmap.txt
>  create mode 100644 drivers/mtd/cfi-flash-uclass.c
>  create mode 100644 include/cfi-flash.h
>
> diff --git a/common/board_r.c b/common/board_r.c
> index a4facf8..fceaea6 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -38,6 +38,7 @@
>  #include <miiphy.h>
>  #endif
>  #include <mmc.h>
> +#include <mtd/cfi_flash.h>
>  #include <nand.h>
>  #include <onenand_uboot.h>
>  #include <scsi.h>
> @@ -348,6 +349,8 @@ static int initr_flash(void)
>         /* update start of FLASH memory    */
>  #ifdef CONFIG_SYS_FLASH_BASE
>         bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
> +#else
> +       bd->bi_flashstart = cfi_flash_bank_addr(0);
>  #endif
>         /* size of FLASH memory (final value) */
>         bd->bi_flashsize = flash_size;
> diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
> index 3d404b2..7b504ba 100644
> --- a/configs/nios2-generic_defconfig
> +++ b/configs/nios2-generic_defconfig
> @@ -18,6 +18,7 @@ CONFIG_NET_RANDOM_ETHADDR=y
>  CONFIG_ALTERA_PIO=y
>  CONFIG_MISC=y
>  CONFIG_ALTERA_SYSID=y
> +CONFIG_CFI_FLASH=y
>  CONFIG_ALTERA_JTAG_UART=y
>  CONFIG_ALTERA_JTAG_UART_BYPASS=y
>  CONFIG_TIMER=y
> diff --git a/doc/device-tree-bindings/mtd/mtd-physmap.txt b/doc/device-tree-bindings/mtd/mtd-physmap.txt
> new file mode 100644
> index 0000000..a04d6e8
> --- /dev/null
> +++ b/doc/device-tree-bindings/mtd/mtd-physmap.txt
> @@ -0,0 +1,88 @@
> +CFI or JEDEC memory-mapped NOR flash, MTD-RAM (NVRAM...)
> +
> +Flash chips (Memory Technology Devices) are often used for solid state
> +file systems on embedded devices.
> +
> + - compatible : should contain the specific model of mtd chip(s)
> +   used, if known, followed by either "cfi-flash", "jedec-flash",
> +   "mtd-ram" or "mtd-rom".
> + - reg : Address range(s) of the mtd chip(s)
> +   It's possible to (optionally) define multiple "reg" tuples so that
> +   non-identical chips can be described in one node.
> + - bank-width : Width (in bytes) of the bank.  Equal to the
> +   device width times the number of interleaved chips.
> + - device-width : (optional) Width of a single mtd chip.  If
> +   omitted, assumed to be equal to 'bank-width'.
> + - #address-cells, #size-cells : Must be present if the device has
> +   sub-nodes representing partitions (see below).  In this case
> +   both #address-cells and #size-cells must be equal to 1.
> + - no-unaligned-direct-access: boolean to disable the default direct
> +   mapping of the flash.
> +   On some platforms (e.g. MPC5200) a direct 1:1 mapping may cause
> +   problems with JFFS2 usage, as the local bus (LPB) doesn't support
> +   unaligned accesses as implemented in the JFFS2 code via memcpy().
> +   By defining "no-unaligned-direct-access", the flash will not be
> +   exposed directly to the MTD users (e.g. JFFS2) any more.
> + - linux,mtd-name: allow to specify the mtd name for retro capability with
> +   physmap-flash drivers as boot loader pass the mtd partition via the old
> +   device name physmap-flash.
> + - use-advanced-sector-protection: boolean to enable support for the
> +   advanced sector protection (Spansion: PPB - Persistent Protection
> +   Bits) locking.
> +
> +For JEDEC compatible devices, the following additional properties
> +are defined:
> +
> + - vendor-id : Contains the flash chip's vendor id (1 byte).
> + - device-id : Contains the flash chip's device id (1 byte).
> +
> +For ROM compatible devices (and ROM fallback from cfi-flash), the following
> +additional (optional) property is defined:
> +
> + - erase-size : The chip's physical erase block size in bytes.
> +
> +The device tree may optionally contain sub-nodes describing partitions of the
> +address space. See partition.txt for more detail.
> +
> +Example:
> +
> +       flash@ff000000 {
> +               compatible = "amd,am29lv128ml", "cfi-flash";
> +               reg = <ff000000 01000000>;
> +               bank-width = <4>;
> +               device-width = <1>;
> +               #address-cells = <1>;
> +               #size-cells = <1>;
> +               fs@0 {
> +                       label = "fs";
> +                       reg = <0 f80000>;
> +               };
> +               firmware@f80000 {
> +                       label ="firmware";
> +                       reg = <f80000 80000>;
> +                       read-only;
> +               };
> +       };
> +
> +Here an example with multiple "reg" tuples:
> +
> +       flash@f0000000,0 {
> +               #address-cells = <1>;
> +               #size-cells = <1>;
> +               compatible = "intel,PC48F4400P0VB", "cfi-flash";

PC48F4400P0VB should be lower cases

> +               reg = <0 0x00000000 0x02000000
> +                      0 0x02000000 0x02000000>;
> +               bank-width = <2>;
> +               partition@0 {
> +                       label = "test-part1";
> +                       reg = <0 0x04000000>;
> +               };
> +       };
> +
> +An example using SRAM:
> +
> +       sram@2,0 {
> +               compatible = "samsung,k6f1616u6a", "mtd-ram";
> +               reg = <2 0 0x00200000>;
> +               bank-width = <2>;
> +       };

By looking at the implementation, is it really necessary to add a new
uclass for cfi-flash, given we only need get the flash base address?
There are no cfi-flash specific ops defined.
Why not just read its base address from device tree?

[snip]

Regards,
Bin
Thomas Chou Oct. 11, 2015, 8:54 a.m. UTC | #2
Hi Bin,

On 10/11/2015 03:54 PM, Bin Meng wrote:
> By looking at the implementation, is it really necessary to add a new
> uclass for cfi-flash, given we only need get the flash base address?
> There are no cfi-flash specific ops defined.
> Why not just read its base address from device tree?

Yes, there is not flash ops involved at the moment.

I have tried to minimize the change to existing cfi_flash driver, and 
got it just works when I am converting all nios2 related devices to 
driver model and device tree control.

Yet it is just the beginning to convert cfi flash to driver model. It 
will include per device flash_info and flash related operations in the 
full extent.

Best regards,
Thomas
Bin Meng Oct. 11, 2015, 9:10 a.m. UTC | #3
Hi Thomas,

On Sun, Oct 11, 2015 at 4:54 PM, Thomas Chou <thomas@wytron.com.tw> wrote:
> Hi Bin,
>
> On 10/11/2015 03:54 PM, Bin Meng wrote:
>>
>> By looking at the implementation, is it really necessary to add a new
>> uclass for cfi-flash, given we only need get the flash base address?
>> There are no cfi-flash specific ops defined.
>> Why not just read its base address from device tree?
>
>
> Yes, there is not flash ops involved at the moment.
>
> I have tried to minimize the change to existing cfi_flash driver, and got it
> just works when I am converting all nios2 related devices to driver model
> and device tree control.
>
> Yet it is just the beginning to convert cfi flash to driver model. It will
> include per device flash_info and flash related operations in the full
> extent.
>

It's unlikely we are going to create another instance of cfi-flash
driver, isn't it? Then it's just a single driver which does not make
cfi-flash a "class". We can just update the cfi-flash driver to read
its flash base address directly from device tree, without the need to
go through driver model.

Regards,
Bin
Thomas Chou Oct. 11, 2015, 9:35 a.m. UTC | #4
Hi Bin,

On 10/11/2015 03:54 PM, Bin Meng wrote:
>> +       flash@f0000000,0 {
>> +               #address-cells = <1>;
>> +               #size-cells = <1>;
>> +               compatible = "intel,PC48F4400P0VB", "cfi-flash";
>
> PC48F4400P0VB should be lower cases

Thanks for your review. I will change it to lower cases.

Best regards,
Thomas
Thomas Chou Oct. 11, 2015, 12:24 p.m. UTC | #5
Hi Bin,

On 10/11/2015 05:10 PM, Bin Meng wrote:
> It's unlikely we are going to create another instance of cfi-flash
> driver, isn't it? Then it's just a single driver which does not make
> cfi-flash a "class". We can just update the cfi-flash driver to read
> its flash base address directly from device tree, without the need to
> go through driver model.

It is an on-going process to convert existing drivers to driver model. 
The spi-flash has driver model now. How do you think it is unlikely that 
cfi-flash should be converted to driver-model?

It is not just base address. There is device binding with compatible 
ids. There will be resources allocation, too. Please don't limit your 
imagination by my poor coding skill.

There are three good things to u-boot in recent years, the Kconfig, 
device tree control and driver model. Together, they provide more 
flexibility to processors on FPGA, like nios2. Here almost everything is 
programmable, and it is difficult to hard code driver setup in the old way.

Huge thanks to all the contributors. Thank you too, Bin.

Best regards,
Thomas
Bin Meng Oct. 11, 2015, 12:43 p.m. UTC | #6
Hi Thomas,

On Sun, Oct 11, 2015 at 8:24 PM, Thomas Chou <thomas@wytron.com.tw> wrote:
> Hi Bin,
>
> On 10/11/2015 05:10 PM, Bin Meng wrote:
>>
>> It's unlikely we are going to create another instance of cfi-flash
>> driver, isn't it? Then it's just a single driver which does not make
>> cfi-flash a "class". We can just update the cfi-flash driver to read
>> its flash base address directly from device tree, without the need to
>> go through driver model.
>
>
> It is an on-going process to convert existing drivers to driver model. The
> spi-flash has driver model now. How do you think it is unlikely that
> cfi-flash should be converted to driver-model?

The spi-flash is converted to driver model, which is good, as there
are spi flashes from different vendors which have different op codes
thus need different drivers to handle. But for cfi-flash, almost every
cfi-flash we see in the market conforms to the same CFI spec, thus we
only need one driver (drivers/mtd/cfi_flash.c) to work with all these
flashes, right? Unless I am missing something recently, eg: some
vendors started to created flashes which are not 100% compatible with
the CFI spec? If this is the only single driver, I don't see the need
to create a special driver model uclass for it. Just an open
discussion. I am not saying we should, or we should not :)

>
> It is not just base address. There is device binding with compatible ids.
> There will be resources allocation, too. Please don't limit your imagination
> by my poor coding skill.

All there can be obtained from device tree. Being a non-DM driver does
not prevent you from using device tree.

>
> There are three good things to u-boot in recent years, the Kconfig, device
> tree control and driver model. Together, they provide more flexibility to
> processors on FPGA, like nios2. Here almost everything is programmable, and
> it is difficult to hard code driver setup in the old way.
>
> Huge thanks to all the contributors. Thank you too, Bin.
>

Agreed!

Regards,
Bin
Thomas Chou Oct. 11, 2015, 1:29 p.m. UTC | #7
Hi Bin,

On 10/11/2015 08:43 PM, Bin Meng wrote:
> The spi-flash is converted to driver model, which is good, as there
> are spi flashes from different vendors which have different op codes
> thus need different drivers to handle. But for cfi-flash, almost every
> cfi-flash we see in the market conforms to the same CFI spec, thus we
> only need one driver (drivers/mtd/cfi_flash.c) to work with all these
> flashes, right? Unless I am missing something recently, eg: some
> vendors started to created flashes which are not 100% compatible with
> the CFI spec? If this is the only single driver, I don't see the need
> to create a special driver model uclass for it. Just an open
> discussion. I am not saying we should, or we should not :)

I had the same question myself. But I found that there are several 
uclasses which has only one driver. No worries. :)

>> It is not just base address. There is device binding with compatible ids.
>> There will be resources allocation, too. Please don't limit your imagination
>> by my poor coding skill.
>
> All there can be obtained from device tree. Being a non-DM driver does
> not prevent you from using device tree.

It is true. Yet using driver model does have some advantages over 
non-DM. It is more unified and dynamic. So I chose the DM way when I 
have to add device tree binding. You may find my patch quite trivial. 
Thanks to the DM framework.

Best regards,
Thomas
Simon Glass Oct. 11, 2015, 9:47 p.m. UTC | #8
Hi,

On 11 October 2015 at 07:29, Thomas Chou <thomas@wytron.com.tw> wrote:
> Hi Bin,
>
> On 10/11/2015 08:43 PM, Bin Meng wrote:
>>
>> The spi-flash is converted to driver model, which is good, as there
>> are spi flashes from different vendors which have different op codes
>> thus need different drivers to handle. But for cfi-flash, almost every
>> cfi-flash we see in the market conforms to the same CFI spec, thus we
>> only need one driver (drivers/mtd/cfi_flash.c) to work with all these
>> flashes, right? Unless I am missing something recently, eg: some
>> vendors started to created flashes which are not 100% compatible with
>> the CFI spec? If this is the only single driver, I don't see the need
>> to create a special driver model uclass for it. Just an open
>> discussion. I am not saying we should, or we should not :)
>
>
> I had the same question myself. But I found that there are several uclasses
> which has only one driver. No worries. :)

I don't see any problem with this in general, although the point with
CFI is that you are really implementing the uclass, as there will not
going to be any drivers (as I understand it).

Looking at SPI flash, it does have an API (read, write, erase). Could
CFI use the same API? That might mean that we could unify the two and
share a uclass.

One approach may be to use a name like UCLASS_FLASH, and add some
operations to it. Then we can say that we have a real uclass. The
operations could come in a separate flash perhaps.

>
>>> It is not just base address. There is device binding with compatible ids.
>>> There will be resources allocation, too. Please don't limit your
>>> imagination
>>> by my poor coding skill.
>>
>>
>> All there can be obtained from device tree. Being a non-DM driver does
>> not prevent you from using device tree.
>
>
> It is true. Yet using driver model does have some advantages over non-DM. It
> is more unified and dynamic. So I chose the DM way when I have to add device
> tree binding. You may find my patch quite trivial. Thanks to the DM
> framework.

Regards,
Simon
Thomas Chou Oct. 12, 2015, 12:07 a.m. UTC | #9
Hi Simon,

On 10/12/2015 05:47 AM, Simon Glass wrote:
> I don't see any problem with this in general, although the point with
> CFI is that you are really implementing the uclass, as there will not
> going to be any drivers (as I understand it).
>
> Looking at SPI flash, it does have an API (read, write, erase). Could
> CFI use the same API? That might mean that we could unify the two and
> share a uclass.
>
> One approach may be to use a name like UCLASS_FLASH, and add some
> operations to it. Then we can say that we have a real uclass. The
> operations could come in a separate flash perhaps.

Great. It has been my first choice to have a unified flash uclass.

Best regards,
Thomas
Bin Meng Oct. 12, 2015, 3:07 a.m. UTC | #10
Hi,

On Mon, Oct 12, 2015 at 5:47 AM, Simon Glass <sjg@chromium.org> wrote:
> Hi,
>
> On 11 October 2015 at 07:29, Thomas Chou <thomas@wytron.com.tw> wrote:
>> Hi Bin,
>>
>> On 10/11/2015 08:43 PM, Bin Meng wrote:
>>>
>>> The spi-flash is converted to driver model, which is good, as there
>>> are spi flashes from different vendors which have different op codes
>>> thus need different drivers to handle. But for cfi-flash, almost every
>>> cfi-flash we see in the market conforms to the same CFI spec, thus we
>>> only need one driver (drivers/mtd/cfi_flash.c) to work with all these
>>> flashes, right? Unless I am missing something recently, eg: some
>>> vendors started to created flashes which are not 100% compatible with
>>> the CFI spec? If this is the only single driver, I don't see the need
>>> to create a special driver model uclass for it. Just an open
>>> discussion. I am not saying we should, or we should not :)
>>
>>
>> I had the same question myself. But I found that there are several uclasses
>> which has only one driver. No worries. :)

These single drivers under a uclass is probably due to we have not
converted all other drivers to driver model yet.

>
> I don't see any problem with this in general, although the point with
> CFI is that you are really implementing the uclass, as there will not
> going to be any drivers (as I understand it).

Yep, that's really my concern regarding to a new 'class' to be created
but actually no additional driver will use that 'class'.

>
> Looking at SPI flash, it does have an API (read, write, erase). Could
> CFI use the same API? That might mean that we could unify the two and
> share a uclass.

Yep, I believe this is a better approach.

>
> One approach may be to use a name like UCLASS_FLASH, and add some
> operations to it. Then we can say that we have a real uclass. The
> operations could come in a separate flash perhaps.
>
>>
>>>> It is not just base address. There is device binding with compatible ids.
>>>> There will be resources allocation, too. Please don't limit your
>>>> imagination
>>>> by my poor coding skill.
>>>
>>>
>>> All there can be obtained from device tree. Being a non-DM driver does
>>> not prevent you from using device tree.
>>
>>
>> It is true. Yet using driver model does have some advantages over non-DM. It
>> is more unified and dynamic. So I chose the DM way when I have to add device
>> tree binding. You may find my patch quite trivial. Thanks to the DM
>> framework.
>
> Regards,
> Simon

Regards,
Bin
diff mbox

Patch

diff --git a/common/board_r.c b/common/board_r.c
index a4facf8..fceaea6 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -38,6 +38,7 @@ 
 #include <miiphy.h>
 #endif
 #include <mmc.h>
+#include <mtd/cfi_flash.h>
 #include <nand.h>
 #include <onenand_uboot.h>
 #include <scsi.h>
@@ -348,6 +349,8 @@  static int initr_flash(void)
 	/* update start of FLASH memory    */
 #ifdef CONFIG_SYS_FLASH_BASE
 	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+#else
+	bd->bi_flashstart = cfi_flash_bank_addr(0);
 #endif
 	/* size of FLASH memory (final value) */
 	bd->bi_flashsize = flash_size;
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig
index 3d404b2..7b504ba 100644
--- a/configs/nios2-generic_defconfig
+++ b/configs/nios2-generic_defconfig
@@ -18,6 +18,7 @@  CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ALTERA_PIO=y
 CONFIG_MISC=y
 CONFIG_ALTERA_SYSID=y
+CONFIG_CFI_FLASH=y
 CONFIG_ALTERA_JTAG_UART=y
 CONFIG_ALTERA_JTAG_UART_BYPASS=y
 CONFIG_TIMER=y
diff --git a/doc/device-tree-bindings/mtd/mtd-physmap.txt b/doc/device-tree-bindings/mtd/mtd-physmap.txt
new file mode 100644
index 0000000..a04d6e8
--- /dev/null
+++ b/doc/device-tree-bindings/mtd/mtd-physmap.txt
@@ -0,0 +1,88 @@ 
+CFI or JEDEC memory-mapped NOR flash, MTD-RAM (NVRAM...)
+
+Flash chips (Memory Technology Devices) are often used for solid state
+file systems on embedded devices.
+
+ - compatible : should contain the specific model of mtd chip(s)
+   used, if known, followed by either "cfi-flash", "jedec-flash",
+   "mtd-ram" or "mtd-rom".
+ - reg : Address range(s) of the mtd chip(s)
+   It's possible to (optionally) define multiple "reg" tuples so that
+   non-identical chips can be described in one node.
+ - bank-width : Width (in bytes) of the bank.  Equal to the
+   device width times the number of interleaved chips.
+ - device-width : (optional) Width of a single mtd chip.  If
+   omitted, assumed to be equal to 'bank-width'.
+ - #address-cells, #size-cells : Must be present if the device has
+   sub-nodes representing partitions (see below).  In this case
+   both #address-cells and #size-cells must be equal to 1.
+ - no-unaligned-direct-access: boolean to disable the default direct
+   mapping of the flash.
+   On some platforms (e.g. MPC5200) a direct 1:1 mapping may cause
+   problems with JFFS2 usage, as the local bus (LPB) doesn't support
+   unaligned accesses as implemented in the JFFS2 code via memcpy().
+   By defining "no-unaligned-direct-access", the flash will not be
+   exposed directly to the MTD users (e.g. JFFS2) any more.
+ - linux,mtd-name: allow to specify the mtd name for retro capability with
+   physmap-flash drivers as boot loader pass the mtd partition via the old
+   device name physmap-flash.
+ - use-advanced-sector-protection: boolean to enable support for the
+   advanced sector protection (Spansion: PPB - Persistent Protection
+   Bits) locking.
+
+For JEDEC compatible devices, the following additional properties
+are defined:
+
+ - vendor-id : Contains the flash chip's vendor id (1 byte).
+ - device-id : Contains the flash chip's device id (1 byte).
+
+For ROM compatible devices (and ROM fallback from cfi-flash), the following
+additional (optional) property is defined:
+
+ - erase-size : The chip's physical erase block size in bytes.
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Example:
+
+	flash@ff000000 {
+		compatible = "amd,am29lv128ml", "cfi-flash";
+		reg = <ff000000 01000000>;
+		bank-width = <4>;
+		device-width = <1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		fs@0 {
+			label = "fs";
+			reg = <0 f80000>;
+		};
+		firmware@f80000 {
+			label ="firmware";
+			reg = <f80000 80000>;
+			read-only;
+		};
+	};
+
+Here an example with multiple "reg" tuples:
+
+	flash@f0000000,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "intel,PC48F4400P0VB", "cfi-flash";
+		reg = <0 0x00000000 0x02000000
+		       0 0x02000000 0x02000000>;
+		bank-width = <2>;
+		partition@0 {
+			label = "test-part1";
+			reg = <0 0x04000000>;
+		};
+	};
+
+An example using SRAM:
+
+	sram@2,0 {
+		compatible = "samsung,k6f1616u6a", "mtd-ram";
+		reg = <2 0 0x00200000>;
+		bank-width = <2>;
+	};
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 59278d1..b1addb5 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -1,3 +1,19 @@ 
+menu "CFI Flash Support"
+
+config CFI_FLASH
+	bool "Enable Driver Model for CFI Flash driver"
+	depends on DM
+	help
+	  The Common Flash Interface specification was developed by Intel,
+	  AMD and other flash manufactures that provides a universal method
+	  for probing the capabilities of flash devices. If you wish to
+	  support any device that is CFI-compliant, you need to enable this
+	  option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
+	  for more information on CFI. This driver uses the same API as
+	  drivers/mtd/cfi_flash.c. But now implemented by the uclass.
+
+endmenu
+
 source "drivers/mtd/nand/Kconfig"
 
 source "drivers/mtd/spi/Kconfig"
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index a623f4c..0bcc76c 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -11,6 +11,7 @@  endif
 obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
 obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
 obj-$(CONFIG_HAS_DATAFLASH) += at45.o
+obj-$(CONFIG_CFI_FLASH) += cfi-flash-uclass.o
 obj-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o
 obj-$(CONFIG_FLASH_CFI_MTD) += cfi_mtd.o
 obj-$(CONFIG_HAS_DATAFLASH) += dataflash.o
diff --git a/drivers/mtd/cfi-flash-uclass.c b/drivers/mtd/cfi-flash-uclass.c
new file mode 100644
index 0000000..62c914b
--- /dev/null
+++ b/drivers/mtd/cfi-flash-uclass.c
@@ -0,0 +1,70 @@ 
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <cfi-flash.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct cfi_flash_platdata {
+	phys_addr_t base;
+};
+
+/*
+ * Implement a cfi flash uclass to work with drivers/mtd/cfi-flash.c.
+ */
+
+phys_addr_t cfi_flash_get_base(struct udevice *dev)
+{
+	struct cfi_flash_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	return uc_priv->base;
+}
+
+UCLASS_DRIVER(cfi_flash) = {
+	.id		= UCLASS_CFI_FLASH,
+	.name		= "cfi_flash",
+	.per_device_auto_alloc_size = sizeof(struct cfi_flash_dev_priv),
+};
+
+static int cfi_flash_probe(struct udevice *dev)
+{
+	struct cfi_flash_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct cfi_flash_platdata *plat = dev->platdata;
+
+	uc_priv->base = plat->base;
+
+	return 0;
+}
+
+static int cfi_flash_ofdata_to_platdata(struct udevice *dev)
+{
+	struct cfi_flash_platdata *plat = dev_get_platdata(dev);
+	fdt_size_t size;
+
+	fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+	plat->base = (phys_addr_t)ioremap(dev_get_addr(dev), size);
+
+	return 0;
+}
+
+static const struct udevice_id cfi_flash_ids[] = {
+	{ .compatible = "cfi-flash", },
+	{ }
+};
+
+U_BOOT_DRIVER(cfi_flash) = {
+	.name	= "cfi_flash",
+	.id	= UCLASS_CFI_FLASH,
+	.of_match = cfi_flash_ids,
+	.ofdata_to_platdata = cfi_flash_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct cfi_flash_platdata),
+	.probe = cfi_flash_probe,
+};
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 50983b8..9204596 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -18,6 +18,9 @@ 
 /* #define DEBUG	*/
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <cfi-flash.h>
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
@@ -87,10 +90,25 @@  static u16 cfi_flash_config_reg(int i)
 int cfi_flash_num_flash_banks = CONFIG_SYS_MAX_FLASH_BANKS_DETECT;
 #endif
 
+#ifdef CONFIG_CFI_FLASH
+phys_addr_t cfi_flash_bank_addr(int i)
+{
+	struct udevice *dev;
+	int ret;
+
+	/* FIXME: the current code supports only one bank */
+	ret = uclass_get_device(UCLASS_CFI_FLASH, i, &dev);
+	if (ret)
+		return ret;
+
+	return cfi_flash_get_base(dev);
+}
+#else
 __weak phys_addr_t cfi_flash_bank_addr(int i)
 {
 	return ((phys_addr_t [])CONFIG_SYS_FLASH_BANKS_LIST)[i];
 }
+#endif
 
 __weak unsigned long cfi_flash_bank_size(int i)
 {
diff --git a/include/cfi-flash.h b/include/cfi-flash.h
new file mode 100644
index 0000000..192df97
--- /dev/null
+++ b/include/cfi-flash.h
@@ -0,0 +1,27 @@ 
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _CFI_FLASH_H_
+#define _CFI_FLASH_H_
+
+/*
+ * Get the cfi flash base address
+ *
+ * @dev: The cfi flash device
+ * @return: the cfi flash base address
+ */
+phys_addr_t cfi_flash_get_base(struct udevice *dev);
+
+/*
+ * struct cfi_flash_dev_priv - information about a device used by the uclass
+ *
+ * @base: the cfi flash base address
+ */
+struct cfi_flash_dev_priv {
+	phys_addr_t base;
+};
+
+#endif	/* _CFI_FLASH_H_ */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a6982ab..09e370c 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -25,6 +25,7 @@  enum uclass_id {
 	UCLASS_SIMPLE_BUS,	/* bus with child devices */
 
 	/* U-Boot uclasses start here - in alphabetical order */
+	UCLASS_CFI_FLASH,	/* cfi flash */
 	UCLASS_CLK,		/* Clock source, e.g. used by peripherals */
 	UCLASS_CPU,		/* CPU, typically part of an SoC */
 	UCLASS_CROS_EC,		/* Chrome OS EC */