Skip to content

Commit c01ef12

Browse files
committed
Revert "mtd: spi-nor: parse SFDP Sector Map Parameter Table"
This reverts commit d2de66f. There are slightly different changes between what we applied back in linux4sam-6.0 and what reached mainline. Revert the 4BAIT, SMPT and non-uniform erase support and backport the support and fixes from mainline. Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
1 parent 4cf1d12 commit c01ef12

2 files changed

Lines changed: 16 additions & 264 deletions

File tree

drivers/mtd/spi-nor/spi-nor.c

Lines changed: 16 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,35 +2025,6 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
20252025
* Serial Flash Discoverable Parameters (SFDP) parsing.
20262026
*/
20272027

2028-
/**
2029-
* spi_nor_read_raw() - raw read of serial flash memory. read_opcode,
2030-
* addr_width and read_dummy members of the struct spi_nor should be previously
2031-
* set.
2032-
* @nor: pointer to a 'struct spi_nor'
2033-
* @addr: offset in the serial flash memory
2034-
* @len: number of bytes to read
2035-
* @buf: buffer where the data is copied into
2036-
*
2037-
* Return: 0 on success, -errno otherwise.
2038-
*/
2039-
static int spi_nor_read_raw(struct spi_nor *nor, u32 addr, size_t len, u8 *buf)
2040-
{
2041-
int ret;
2042-
2043-
while (len) {
2044-
ret = nor->read(nor, addr, len, buf);
2045-
if (!ret || ret > len)
2046-
return -EIO;
2047-
if (ret < 0)
2048-
return ret;
2049-
2050-
buf += ret;
2051-
addr += ret;
2052-
len -= ret;
2053-
}
2054-
return 0;
2055-
}
2056-
20572028
/**
20582029
* spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters.
20592030
* @nor: pointer to a 'struct spi_nor'
@@ -2081,8 +2052,22 @@ static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
20812052
nor->addr_width = 3;
20822053
nor->read_dummy = 8;
20832054

2084-
ret = spi_nor_read_raw(nor, addr, len, buf);
2055+
while (len) {
2056+
ret = nor->read(nor, addr, len, (u8 *)buf);
2057+
if (!ret || ret > len) {
2058+
ret = -EIO;
2059+
goto read_err;
2060+
}
2061+
if (ret < 0)
2062+
goto read_err;
20852063

2064+
buf += ret;
2065+
addr += ret;
2066+
len -= ret;
2067+
}
2068+
ret = 0;
2069+
2070+
read_err:
20862071
nor->read_opcode = read_opcode;
20872072
nor->addr_width = addr_width;
20882073
nor->read_dummy = read_dummy;
@@ -2602,228 +2587,6 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
26022587
return 0;
26032588
}
26042589

2605-
#define SMPT_CMD_ADDRESS_LEN_MASK GENMASK(23, 22)
2606-
#define SMPT_CMD_ADDRESS_LEN_0 (0x0UL << 22)
2607-
#define SMPT_CMD_ADDRESS_LEN_3 (0x1UL << 22)
2608-
#define SMPT_CMD_ADDRESS_LEN_4 (0x2UL << 22)
2609-
#define SMPT_CMD_ADDRESS_LEN_USE_CURRENT (0x3UL << 22)
2610-
2611-
#define SMPT_CMD_READ_DUMMY_MASK GENMASK(19, 16)
2612-
#define SMPT_CMD_READ_DUMMY_SHIFT 16
2613-
#define SMPT_CMD_READ_DUMMY(_cmd) \
2614-
((_cmd & SMPT_CMD_READ_DUMMY_MASK) >> SMPT_CMD_READ_DUMMY_SHIFT)
2615-
#define SMPT_CMD_READ_DUMMY_IS_VARIABLE 0xfUL
2616-
2617-
#define SMPT_CMD_READ_DATA_MASK GENMASK(31, 24)
2618-
#define SMPT_CMD_READ_DATA_SHIFT 24
2619-
#define SMPT_CMD_READ_DATA(_cmd) \
2620-
((_cmd & SMPT_CMD_READ_DATA_MASK) >> SMPT_CMD_READ_DATA_SHIFT)
2621-
2622-
#define SMPT_CMD_OPCODE_MASK GENMASK(15, 8)
2623-
#define SMPT_CMD_OPCODE_SHIFT 8
2624-
#define SMPT_CMD_OPCODE(_cmd) \
2625-
((_cmd & SMPT_CMD_OPCODE_MASK) >> SMPT_CMD_OPCODE_SHIFT)
2626-
2627-
#define SMPT_MAP_REGION_COUNT_MASK GENMASK(23, 16)
2628-
#define SMPT_MAP_REGION_COUNT_SHIFT 16
2629-
#define SMPT_MAP_REGION_COUNT(_header) \
2630-
(((_header & SMPT_MAP_REGION_COUNT_MASK) >> \
2631-
SMPT_MAP_REGION_COUNT_SHIFT) + 1)
2632-
2633-
#define SMPT_MAP_ID_MASK GENMASK(15, 8)
2634-
#define SMPT_MAP_ID_SHIFT 8
2635-
#define SMPT_MAP_ID(_header) ((_header & SMPT_MAP_ID_MASK) >> SMPT_MAP_ID_SHIFT)
2636-
2637-
#define SMPT_MAP_REGION_SIZE_MASK GENMASK(31, 8)
2638-
#define SMPT_MAP_REGION_SIZE_SHIFT 8
2639-
#define SMPT_MAP_REGION_SIZE(_region) \
2640-
((((_region & SMPT_MAP_REGION_SIZE_MASK) >> \
2641-
SMPT_MAP_REGION_SIZE_SHIFT) + 1) * 256)
2642-
2643-
#define SMPT_MAP_REGION_ERASE_TYPE_MASK GENMASK(3, 0)
2644-
#define SMPT_MAP_REGION_ERASE_TYPE(_region) \
2645-
(_region & SMPT_MAP_REGION_ERASE_TYPE_MASK)
2646-
2647-
#define SMPT_DESC_TYPE_MAP BIT(1)
2648-
#define SMPT_DESC_END BIT(0)
2649-
2650-
static u8 spi_nor_smpt_addr_width(const struct spi_nor *nor, const u32 settings)
2651-
{
2652-
switch (settings & SMPT_CMD_ADDRESS_LEN_MASK) {
2653-
case SMPT_CMD_ADDRESS_LEN_0:
2654-
return 0;
2655-
case SMPT_CMD_ADDRESS_LEN_3:
2656-
return 3;
2657-
case SMPT_CMD_ADDRESS_LEN_4:
2658-
return 4;
2659-
case SMPT_CMD_ADDRESS_LEN_USE_CURRENT:
2660-
/* fall through */
2661-
default:
2662-
return nor->addr_width;
2663-
}
2664-
}
2665-
2666-
static u8 spi_nor_smpt_read_dummy(const struct spi_nor *nor, const u32 settings)
2667-
{
2668-
u8 read_dummy = SMPT_CMD_READ_DUMMY(settings);
2669-
2670-
if (read_dummy == SMPT_CMD_READ_DUMMY_IS_VARIABLE)
2671-
return nor->read_dummy;
2672-
return read_dummy;
2673-
}
2674-
2675-
static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt)
2676-
{
2677-
const u32 *ret = NULL;
2678-
u32 i, addr;
2679-
int err;
2680-
u8 addr_width, read_opcode, read_dummy;
2681-
u8 read_data_mask, data_byte, map_id;
2682-
2683-
addr_width = nor->addr_width;
2684-
read_dummy = nor->read_dummy;
2685-
read_opcode = nor->read_opcode;
2686-
2687-
map_id = 0;
2688-
i = 0;
2689-
/* Determine if there are any optional Detection Command Descriptors */
2690-
while (!(smpt[i] & SMPT_DESC_TYPE_MAP)) {
2691-
read_data_mask = SMPT_CMD_READ_DATA(smpt[i]);
2692-
nor->addr_width = spi_nor_smpt_addr_width(nor, smpt[i]);
2693-
nor->read_dummy = spi_nor_smpt_read_dummy(nor, smpt[i]);
2694-
nor->read_opcode = SMPT_CMD_OPCODE(smpt[i]);
2695-
addr = smpt[i + 1];
2696-
2697-
err = spi_nor_read_raw(nor, addr, 1, &data_byte);
2698-
if (err)
2699-
goto out;
2700-
2701-
/*
2702-
* Build an index value that is used to select the Sector Map
2703-
* Configuration that is currently in use.
2704-
*/
2705-
map_id = map_id << 1 | (!(data_byte & read_data_mask) ? 0 : 1);
2706-
i = i + 2;
2707-
}
2708-
2709-
/* Find the matching configuration map */
2710-
while (SMPT_MAP_ID(smpt[i]) != map_id) {
2711-
if (smpt[i] & SMPT_DESC_END)
2712-
goto out;
2713-
/* increment the table index to the next map */
2714-
i += SMPT_MAP_REGION_COUNT(smpt[i]) + 1;
2715-
}
2716-
2717-
ret = smpt + i;
2718-
/* fall through */
2719-
out:
2720-
nor->addr_width = addr_width;
2721-
nor->read_dummy = read_dummy;
2722-
nor->read_opcode = read_opcode;
2723-
return ret;
2724-
}
2725-
2726-
static void
2727-
spi_nor_region_check_overlay(struct spi_nor_erase_region *region,
2728-
const struct spi_nor_erase_type *erase,
2729-
const u8 erase_type)
2730-
{
2731-
int i;
2732-
2733-
for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
2734-
if (!(erase_type & BIT(i)))
2735-
continue;
2736-
if (region->size & erase[i].size_mask) {
2737-
spi_nor_region_mark_overlay(region);
2738-
return;
2739-
}
2740-
}
2741-
}
2742-
2743-
static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
2744-
const u32 *smpt)
2745-
{
2746-
struct spi_nor_erase_map *map = &nor->erase_map;
2747-
const struct spi_nor_erase_type *erase = map->erase_type;
2748-
struct spi_nor_erase_region *region;
2749-
u64 offset;
2750-
u32 region_count;
2751-
int i, j;
2752-
u8 erase_type;
2753-
2754-
region_count = SMPT_MAP_REGION_COUNT(*smpt);
2755-
region = devm_kcalloc(nor->dev, region_count, sizeof(*region),
2756-
GFP_KERNEL);
2757-
if (!region)
2758-
return -ENOMEM;
2759-
map->regions = region;
2760-
2761-
map->uniform_erase_type = 0xff;
2762-
offset = 0;
2763-
for (i = 0; i < region_count; i++) {
2764-
j = i + 1; /* index for the region dword */
2765-
region[i].size = SMPT_MAP_REGION_SIZE(smpt[j]);
2766-
erase_type = SMPT_MAP_REGION_ERASE_TYPE(smpt[j]);
2767-
region[i].offset = offset | erase_type;
2768-
2769-
spi_nor_region_check_overlay(&region[i], erase, erase_type);
2770-
2771-
/*
2772-
* Save the erase types that are supported in all regions and
2773-
* can erase the entire flash memory.
2774-
*/
2775-
map->uniform_erase_type &= erase_type;
2776-
2777-
offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
2778-
region[i].size;
2779-
}
2780-
2781-
spi_nor_region_mark_end(&region[i - 1]);
2782-
2783-
return 0;
2784-
}
2785-
2786-
static int spi_nor_parse_smpt(struct spi_nor *nor,
2787-
const struct sfdp_parameter_header *smpt_header)
2788-
{
2789-
const u32 *sector_map;
2790-
u32 *smpt;
2791-
size_t len;
2792-
u32 addr;
2793-
int i, ret;
2794-
2795-
/* Read the Sector Map Parameter Table. */
2796-
len = smpt_header->length * sizeof(*smpt);
2797-
smpt = kzalloc(len, GFP_KERNEL);
2798-
if (!smpt)
2799-
return -ENOMEM;
2800-
2801-
addr = SFDP_PARAM_HEADER_PTP(smpt_header);
2802-
ret = spi_nor_read_sfdp(nor, addr, len, smpt);
2803-
if (ret)
2804-
goto out;
2805-
2806-
/* Fix endianness of the SMPT DWORDs. */
2807-
for (i = 0; i < smpt_header->length; i++)
2808-
smpt[i] = le32_to_cpu(smpt[i]);
2809-
2810-
sector_map = spi_nor_get_map_in_use(nor, smpt);
2811-
if (!sector_map) {
2812-
ret = -EINVAL;
2813-
goto out;
2814-
}
2815-
2816-
ret = spi_nor_init_non_uniform_erase_map(nor, sector_map);
2817-
if (ret)
2818-
goto out;
2819-
2820-
spi_nor_regions_sort_erase_types(&nor->erase_map);
2821-
/* fall through */
2822-
out:
2823-
kfree(smpt);
2824-
return ret;
2825-
}
2826-
28272590
/**
28282591
* spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
28292592
* @nor: pointer to a 'struct spi_nor'
@@ -2919,7 +2682,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
29192682

29202683
switch (SFDP_PARAM_HEADER_ID(param_header)) {
29212684
case SFDP_SECTOR_MAP_ID:
2922-
err = spi_nor_parse_smpt(nor, param_header);
2685+
dev_info(dev, "non-uniform erase sector maps are not supported yet.\n");
29232686
break;
29242687

29252688
default:

include/linux/mtd/spi-nor.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -415,17 +415,6 @@ static inline u64 spi_nor_region_end(const struct spi_nor_erase_region *region)
415415
return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
416416
}
417417

418-
static inline void spi_nor_region_mark_end(struct spi_nor_erase_region *region)
419-
{
420-
region->offset |= SNOR_LAST_REGION;
421-
}
422-
423-
static inline void
424-
spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
425-
{
426-
region->offset |= SNOR_OVERLAID_REGION;
427-
}
428-
429418
static inline bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
430419
{
431420
return !!nor->erase_map.uniform_erase_type;

0 commit comments

Comments
 (0)