@@ -2891,10 +2891,11 @@ static void spi_nor_init_params_deprecated(struct spi_nor *nor)
spi_nor_manufacturer_init_params(nor);
- if (nor->info->no_sfdp_flags & (SPI_NOR_DUAL_READ |
- SPI_NOR_QUAD_READ |
- SPI_NOR_OCTAL_READ |
- SPI_NOR_OCTAL_DTR_READ))
+ if ((nor->info->no_sfdp_flags & (SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ |
+ SPI_NOR_OCTAL_READ |
+ SPI_NOR_OCTAL_DTR_READ)) ||
+ nor->manufacturer->flags & SPI_NOR_MANUFACT_TRY_SFDP)
spi_nor_sfdp_init_params_deprecated(nor);
}
@@ -2911,7 +2912,32 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
struct device_node *np = spi_nor_get_flash_node(nor);
params->quad_enable = spi_nor_sr2_bit1_quad_enable;
- params->otp.org = info->otp;
+ memset(¶ms->otp.org, 0, sizeof(struct spi_nor_otp_organization));
+ if (info->otp) {
+ memcpy(¶ms->otp.org, info->otp, sizeof(struct spi_nor_otp_organization));
+ } else if (nor->manufacturer->flags & SPI_NOR_MANUFACT_DT_OTP) {
+ /* Check for OTP information on device tree */
+ u32 n_regions, len;
+
+ if (!of_property_read_u32(np, "opt_n_regions", &n_regions) &&
+ n_regions > 0 &&
+ !of_property_read_u32(np, "otp_len", &len) &&
+ len > 0) {
+ u32 base, offset = 0;
+
+ if (n_regions > 1) {
+ /* If offset is not defined use length as offset */
+ if (of_property_read_u32(np, "otp_offset", &offset))
+ offset = len;
+ }
+ if (of_property_read_u32(np, "otp_base", &base))
+ base = 0;
+ params->otp.org.n_regions = n_regions;
+ params->otp.org.offset = offset;
+ params->otp.org.base = base;
+ params->otp.org.len = len;
+ }
+ }
/* Default to 16-bit Write Status (01h) Command */
nor->flags |= SNOR_F_HAS_16BIT_SR;
@@ -326,7 +326,7 @@ struct spi_nor_otp_ops {
* @ops: OTP access ops
*/
struct spi_nor_otp {
- const struct spi_nor_otp_organization *org;
+ struct spi_nor_otp_organization org;
const struct spi_nor_otp_ops *ops;
};
@@ -560,12 +560,17 @@ struct flash_info {
* @parts: array of parts supported by this manufacturer
* @nparts: number of entries in the parts array
* @fixups: hooks called at various points in time during spi_nor_scan()
+ * @flags: manufacturer flags
*/
struct spi_nor_manufacturer {
const char *name;
const struct flash_info *parts;
unsigned int nparts;
const struct spi_nor_fixups *fixups;
+
+ u8 flags;
+#define SPI_NOR_MANUFACT_TRY_SFDP BIT(0)
+#define SPI_NOR_MANUFACT_DT_OTP BIT(0)
};
/**
@@ -11,8 +11,8 @@
#include "core.h"
-#define spi_nor_otp_region_len(nor) ((nor)->params->otp.org->len)
-#define spi_nor_otp_n_regions(nor) ((nor)->params->otp.org->n_regions)
+#define spi_nor_otp_region_len(nor) ((nor)->params->otp.org.len)
+#define spi_nor_otp_n_regions(nor) ((nor)->params->otp.org.n_regions)
/**
* spi_nor_otp_read_secr() - read security register
@@ -222,7 +222,7 @@ int spi_nor_otp_is_locked_sr2(struct spi_nor *nor, unsigned int region)
static loff_t spi_nor_otp_region_start(const struct spi_nor *nor, unsigned int region)
{
- const struct spi_nor_otp_organization *org = nor->params->otp.org;
+ const struct spi_nor_otp_organization *org = &nor->params->otp.org;
return org->base + region * org->offset;
}
@@ -307,7 +307,7 @@ static int winbond_nor_late_init(struct spi_nor *nor)
{
struct spi_nor_flash_parameter *params = nor->params;
- if (params->otp.org)
+ if (params->otp.org.n_regions)
params->otp.ops = &winbond_nor_otp_ops;
/*