Patchwork [U-Boot,v2,10/15] sf: Enable FDT-based configuration and memory mapping

login
register
mail settings
Submitter Simon Glass
Date March 11, 2013, 4:08 p.m.
Message ID <1363018093-28979-11-git-send-email-sjg@chromium.org>
Download mbox | patch
Permalink /patch/226589/
State Accepted, archived
Delegated to: Tom Rini
Headers show

Comments

Simon Glass - March 11, 2013, 4:08 p.m.
Enable device tree control of SPI flash, and use this to implement
memory-mapped SPI flash, which is supported on Intel chips.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 drivers/mtd/spi/spi_flash.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
 include/fdtdec.h            |  1 +
 include/spi_flash.h         |  1 +
 lib/fdtdec.c                |  1 +
 4 files changed, 48 insertions(+), 1 deletion(-)
Jagannadha Sutradharudu Teki - April 23, 2013, 8:49 p.m.
Hi Simon,

On Mon, Mar 11, 2013 at 9:38 PM, Simon Glass <sjg@chromium.org> wrote:
> Enable device tree control of SPI flash, and use this to implement
> memory-mapped SPI flash, which is supported on Intel chips.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> Changes in v2: None
>
>  drivers/mtd/spi/spi_flash.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
>  include/fdtdec.h            |  1 +
>  include/spi_flash.h         |  1 +
>  lib/fdtdec.c                |  1 +
>  4 files changed, 48 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
> index b82011d..111185a 100644
> --- a/drivers/mtd/spi/spi_flash.c
> +++ b/drivers/mtd/spi/spi_flash.c
> @@ -8,6 +8,7 @@
>   */
>
>  #include <common.h>
> +#include <fdtdec.h>
>  #include <malloc.h>
>  #include <spi.h>
>  #include <spi_flash.h>
> @@ -15,6 +16,8 @@
>
>  #include "spi_flash_internal.h"
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
>  static void spi_flash_addr(u32 addr, u8 *cmd)
>  {
>         /* cmd[0] is actual command */
> @@ -146,6 +149,10 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
>  {
>         u8 cmd[5];
>
> +       /* Handle memory-mapped SPI */
> +       if (flash->memory_map)
> +               memcpy(data, flash->memory_map + offset, len);
> +

What is this change implies, does this means for memory mapped
flashes, read can do directly through memcpy()
and no need for spi_flash_read_common().

I am thinking what exactly this req' is for as you read the
flash->memory_map + offset onto data and again your reading
FAST_READ on data using spi_flash_read_common().

Can you please explain.

Thanks,
Jagan.

>         cmd[0] = CMD_READ_ARRAY_FAST;
>         spi_flash_addr(offset, cmd);
>         cmd[4] = 0x00;
> @@ -275,6 +282,34 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
>         return 0;
>  }
>
> +#ifdef CONFIG_OF_CONTROL
> +int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
> +{
> +       fdt_addr_t addr;
> +       fdt_size_t size;
> +       int node;
> +
> +       /* If there is no node, do nothing */
> +       node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
> +       if (node < 0)
> +               return 0;
> +
> +       addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
> +       if (addr == FDT_ADDR_T_NONE) {
> +               debug("%s: Cannot decode address\n", __func__);
> +               return 0;
> +       }
> +
> +       if (flash->size != size) {
> +               debug("%s: Memory map must cover entire device\n", __func__);
> +               return -1;
> +       }
> +       flash->memory_map = (void *)addr;
> +
> +       return 0;
> +}
> +#endif /* CONFIG_OF_CONTROL */
> +
>  /*
>   * The following table holds all device probe functions
>   *
> @@ -391,9 +426,18 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
>                 goto err_manufacturer_probe;
>         }
>
> +#ifdef CONFIG_OF_CONTROL
> +       if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
> +               debug("SF: FDT decode error\n");
> +               goto err_manufacturer_probe;
> +       }
> +#endif
>         printf("SF: Detected %s with page size ", flash->name);
>         print_size(flash->sector_size, ", total ");
> -       print_size(flash->size, "\n");
> +       print_size(flash->size, "");
> +       if (flash->memory_map)
> +               printf(", mapped at %p", flash->memory_map);
> +       puts("\n");
>
>         spi_release_bus(spi);
>
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index d86dbe2..a46e51c 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -83,6 +83,7 @@ enum fdt_compat_id {
>         COMPAT_SAMSUNG_EXYNOS_EHCI,     /* Exynos EHCI controller */
>         COMPAT_SAMSUNG_EXYNOS_USB_PHY,  /* Exynos phy controller for usb2.0 */
>         COMPAT_MAXIM_MAX77686_PMIC,     /* MAX77686 PMIC */
> +       COMPAT_GENERIC_SPI_FLASH,       /* Generic SPI Flash chip */
>
>         COMPAT_COUNT,
>  };
> diff --git a/include/spi_flash.h b/include/spi_flash.h
> index 030d49c..3b6a44e 100644
> --- a/include/spi_flash.h
> +++ b/include/spi_flash.h
> @@ -39,6 +39,7 @@ struct spi_flash {
>         /* Erase (sector) size */
>         u32             sector_size;
>
> +       void *memory_map;       /* Address of read-only SPI flash access */
>         int             (*read)(struct spi_flash *flash, u32 offset,
>                                 size_t len, void *buf);
>         int             (*write)(struct spi_flash *flash, u32 offset,
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index e99a4b9..2145354 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -56,6 +56,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>         COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
>         COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
>         COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
> +       COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
>  };
>
>  const char *fdtdec_get_compatible(enum fdt_compat_id id)
> --
> 1.8.1.3
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
Simon Glass - April 23, 2013, 8:52 p.m.
Hi Jagan,

On Tue, Apr 23, 2013 at 1:49 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> Hi Simon,
>
> On Mon, Mar 11, 2013 at 9:38 PM, Simon Glass <sjg@chromium.org> wrote:
>> Enable device tree control of SPI flash, and use this to implement
>> memory-mapped SPI flash, which is supported on Intel chips.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>> Changes in v2: None
>>
>>  drivers/mtd/spi/spi_flash.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
>>  include/fdtdec.h            |  1 +
>>  include/spi_flash.h         |  1 +
>>  lib/fdtdec.c                |  1 +
>>  4 files changed, 48 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
>> index b82011d..111185a 100644
>> --- a/drivers/mtd/spi/spi_flash.c
>> +++ b/drivers/mtd/spi/spi_flash.c
>> @@ -8,6 +8,7 @@
>>   */
>>
>>  #include <common.h>
>> +#include <fdtdec.h>
>>  #include <malloc.h>
>>  #include <spi.h>
>>  #include <spi_flash.h>
>> @@ -15,6 +16,8 @@
>>
>>  #include "spi_flash_internal.h"
>>
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>>  static void spi_flash_addr(u32 addr, u8 *cmd)
>>  {
>>         /* cmd[0] is actual command */
>> @@ -146,6 +149,10 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
>>  {
>>         u8 cmd[5];
>>
>> +       /* Handle memory-mapped SPI */
>> +       if (flash->memory_map)
>> +               memcpy(data, flash->memory_map + offset, len);
>> +
>
> What is this change implies, does this means for memory mapped
> flashes, read can do directly through memcpy()
> and no need for spi_flash_read_common().
>
> I am thinking what exactly this req' is for as you read the
> flash->memory_map + offset onto data and again your reading
> FAST_READ on data using spi_flash_read_common().
>
> Can you please explain.

Yes you are right, this should exit at this point - at present it is
reading twice. I will prepare a patch.

Regards,
Simon

>
> Thanks,
> Jagan.
>
>>         cmd[0] = CMD_READ_ARRAY_FAST;
>>         spi_flash_addr(offset, cmd);
>>         cmd[4] = 0x00;
>> @@ -275,6 +282,34 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
>>         return 0;
>>  }
>>
>> +#ifdef CONFIG_OF_CONTROL
>> +int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
>> +{
>> +       fdt_addr_t addr;
>> +       fdt_size_t size;
>> +       int node;
>> +
>> +       /* If there is no node, do nothing */
>> +       node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
>> +       if (node < 0)
>> +               return 0;
>> +
>> +       addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
>> +       if (addr == FDT_ADDR_T_NONE) {
>> +               debug("%s: Cannot decode address\n", __func__);
>> +               return 0;
>> +       }
>> +
>> +       if (flash->size != size) {
>> +               debug("%s: Memory map must cover entire device\n", __func__);
>> +               return -1;
>> +       }
>> +       flash->memory_map = (void *)addr;
>> +
>> +       return 0;
>> +}
>> +#endif /* CONFIG_OF_CONTROL */
>> +
>>  /*
>>   * The following table holds all device probe functions
>>   *
>> @@ -391,9 +426,18 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
>>                 goto err_manufacturer_probe;
>>         }
>>
>> +#ifdef CONFIG_OF_CONTROL
>> +       if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
>> +               debug("SF: FDT decode error\n");
>> +               goto err_manufacturer_probe;
>> +       }
>> +#endif
>>         printf("SF: Detected %s with page size ", flash->name);
>>         print_size(flash->sector_size, ", total ");
>> -       print_size(flash->size, "\n");
>> +       print_size(flash->size, "");
>> +       if (flash->memory_map)
>> +               printf(", mapped at %p", flash->memory_map);
>> +       puts("\n");
>>
>>         spi_release_bus(spi);
>>
>> diff --git a/include/fdtdec.h b/include/fdtdec.h
>> index d86dbe2..a46e51c 100644
>> --- a/include/fdtdec.h
>> +++ b/include/fdtdec.h
>> @@ -83,6 +83,7 @@ enum fdt_compat_id {
>>         COMPAT_SAMSUNG_EXYNOS_EHCI,     /* Exynos EHCI controller */
>>         COMPAT_SAMSUNG_EXYNOS_USB_PHY,  /* Exynos phy controller for usb2.0 */
>>         COMPAT_MAXIM_MAX77686_PMIC,     /* MAX77686 PMIC */
>> +       COMPAT_GENERIC_SPI_FLASH,       /* Generic SPI Flash chip */
>>
>>         COMPAT_COUNT,
>>  };
>> diff --git a/include/spi_flash.h b/include/spi_flash.h
>> index 030d49c..3b6a44e 100644
>> --- a/include/spi_flash.h
>> +++ b/include/spi_flash.h
>> @@ -39,6 +39,7 @@ struct spi_flash {
>>         /* Erase (sector) size */
>>         u32             sector_size;
>>
>> +       void *memory_map;       /* Address of read-only SPI flash access */
>>         int             (*read)(struct spi_flash *flash, u32 offset,
>>                                 size_t len, void *buf);
>>         int             (*write)(struct spi_flash *flash, u32 offset,
>> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
>> index e99a4b9..2145354 100644
>> --- a/lib/fdtdec.c
>> +++ b/lib/fdtdec.c
>> @@ -56,6 +56,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>>         COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
>>         COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
>>         COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
>> +       COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
>>  };
>>
>>  const char *fdtdec_get_compatible(enum fdt_compat_id id)
>> --
>> 1.8.1.3
>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot@lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot

Patch

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index b82011d..111185a 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -8,6 +8,7 @@ 
  */
 
 #include <common.h>
+#include <fdtdec.h>
 #include <malloc.h>
 #include <spi.h>
 #include <spi_flash.h>
@@ -15,6 +16,8 @@ 
 
 #include "spi_flash_internal.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 static void spi_flash_addr(u32 addr, u8 *cmd)
 {
 	/* cmd[0] is actual command */
@@ -146,6 +149,10 @@  int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 {
 	u8 cmd[5];
 
+	/* Handle memory-mapped SPI */
+	if (flash->memory_map)
+		memcpy(data, flash->memory_map + offset, len);
+
 	cmd[0] = CMD_READ_ARRAY_FAST;
 	spi_flash_addr(offset, cmd);
 	cmd[4] = 0x00;
@@ -275,6 +282,34 @@  int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
 	return 0;
 }
 
+#ifdef CONFIG_OF_CONTROL
+int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
+{
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int node;
+
+	/* If there is no node, do nothing */
+	node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
+	if (node < 0)
+		return 0;
+
+	addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
+	if (addr == FDT_ADDR_T_NONE) {
+		debug("%s: Cannot decode address\n", __func__);
+		return 0;
+	}
+
+	if (flash->size != size) {
+		debug("%s: Memory map must cover entire device\n", __func__);
+		return -1;
+	}
+	flash->memory_map = (void *)addr;
+
+	return 0;
+}
+#endif /* CONFIG_OF_CONTROL */
+
 /*
  * The following table holds all device probe functions
  *
@@ -391,9 +426,18 @@  struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 		goto err_manufacturer_probe;
 	}
 
+#ifdef CONFIG_OF_CONTROL
+	if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
+		debug("SF: FDT decode error\n");
+		goto err_manufacturer_probe;
+	}
+#endif
 	printf("SF: Detected %s with page size ", flash->name);
 	print_size(flash->sector_size, ", total ");
-	print_size(flash->size, "\n");
+	print_size(flash->size, "");
+	if (flash->memory_map)
+		printf(", mapped at %p", flash->memory_map);
+	puts("\n");
 
 	spi_release_bus(spi);
 
diff --git a/include/fdtdec.h b/include/fdtdec.h
index d86dbe2..a46e51c 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -83,6 +83,7 @@  enum fdt_compat_id {
 	COMPAT_SAMSUNG_EXYNOS_EHCI,	/* Exynos EHCI controller */
 	COMPAT_SAMSUNG_EXYNOS_USB_PHY,	/* Exynos phy controller for usb2.0 */
 	COMPAT_MAXIM_MAX77686_PMIC,	/* MAX77686 PMIC */
+	COMPAT_GENERIC_SPI_FLASH,	/* Generic SPI Flash chip */
 
 	COMPAT_COUNT,
 };
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 030d49c..3b6a44e 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -39,6 +39,7 @@  struct spi_flash {
 	/* Erase (sector) size */
 	u32		sector_size;
 
+	void *memory_map;	/* Address of read-only SPI flash access */
 	int		(*read)(struct spi_flash *flash, u32 offset,
 				size_t len, void *buf);
 	int		(*write)(struct spi_flash *flash, u32 offset,
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index e99a4b9..2145354 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -56,6 +56,7 @@  static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
 	COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
 	COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
+	COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)