Add the SNOR_F_HAS_LOCK flag and set it when SPI_NOR_HAS_LOCK is set in the flash_info entry or when it's a Micron or ST flash. Move the locking hooks in a separate struct so that we have just one field to update when we change the locking implementation.
Unified · Split
| @@ -1598,6 +1598,12 @@ static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) · 1597 unmodified lines | ||
| 1598 | 1598 | return stm_is_locked_sr(nor, ofs, len, status); |
| 1599 | 1599 | } |
| 1600 | 1600 | |
| 1601 | +static const struct spi_nor_locking_ops stm_locking_ops = { | |
| 1602 | + .lock = stm_lock, | |
| 1603 | + .unlock = stm_unlock, | |
| 1604 | + .is_locked = stm_is_locked, | |
| 1605 | +}; | |
| 1606 | + | |
| 1601 | 1607 | static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
| 1602 | 1608 | { |
| 1603 | 1609 | struct spi_nor *nor = mtd_to_spi_nor(mtd); |
| @@ -1607,7 +1613,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) · 3 unmodified lines | ||
| 1607 | 1613 | if (ret) |
| 1608 | 1614 | return ret; |
| 1609 | 1615 | |
| 1610 | − ret = nor->flash_lock(nor, ofs, len); | |
| 1616 | + ret = nor->params.locking_ops->lock(nor, ofs, len); | |
| 1611 | 1617 | |
| 1612 | 1618 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); |
| 1613 | 1619 | return ret; |
| @@ -1622,7 +1628,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) · 8 unmodified lines | ||
| 1622 | 1628 | if (ret) |
| 1623 | 1629 | return ret; |
| 1624 | 1630 | |
| 1625 | − ret = nor->flash_unlock(nor, ofs, len); | |
| 1631 | + ret = nor->params.locking_ops->unlock(nor, ofs, len); | |
| 1626 | 1632 | |
| 1627 | 1633 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); |
| 1628 | 1634 | return ret; |
| @@ -1637,7 +1643,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) · 8 unmodified lines | ||
| 1637 | 1643 | if (ret) |
| 1638 | 1644 | return ret; |
| 1639 | 1645 | |
| 1640 | − ret = nor->flash_is_locked(nor, ofs, len); | |
| 1646 | + ret = nor->params.locking_ops->is_locked(nor, ofs, len); | |
| 1641 | 1647 | |
| 1642 | 1648 | spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); |
| 1643 | 1649 | return ret; |
| @@ -4148,6 +4154,7 @@ static void macronix_set_default_init(struct spi_nor *nor) · 2504 unmodified lines | ||
| 4148 | 4154 | |
| 4149 | 4155 | static void st_micron_set_default_init(struct spi_nor *nor) |
| 4150 | 4156 | { |
| 4157 | + nor->flags |= SNOR_F_HAS_LOCK; | |
| 4151 | 4158 | nor->params.quad_enable = NULL; |
| 4152 | 4159 | nor->params.set_4byte = st_micron_set_4byte; |
| 4153 | 4160 | } |
| @@ -4291,6 +4298,23 @@ static void spi_nor_info_init_params(struct spi_nor *nor) · 137 unmodified lines | ||
| 4291 | 4298 | spi_nor_init_uniform_erase_map(map, erase_mask, params->size); |
| 4292 | 4299 | } |
| 4293 | 4300 | |
| 4301 | +/** | |
| 4302 | + * spi_nor_late_init_params() - Late initialization of default flash parameters. | |
| 4303 | + * @nor: pointer to a 'struct spi_nor' | |
| 4304 | + * | |
| 4305 | + * Used to set default flash parameters and settings when the ->default_init() | |
| 4306 | + * hook or the SFDP parser let voids. | |
| 4307 | + */ | |
| 4308 | +static void spi_nor_late_init_params(struct spi_nor *nor) | |
| 4309 | +{ | |
| 4310 | + /* | |
| 4311 | + * NOR protection support. When locking_ops are not provided, we pick | |
| 4312 | + * the default ones. | |
| 4313 | + */ | |
| 4314 | + if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops) | |
| 4315 | + nor->params.locking_ops = &stm_locking_ops; | |
| 4316 | +} | |
| 4317 | + | |
| 4294 | 4318 | /** |
| 4295 | 4319 | * spi_nor_init_params() - Initialize the flash's parameters and settings. |
| 4296 | 4320 | * @nor: pointer to a 'struct spi-nor'. |
| @@ -4316,6 +4340,10 @@ static void spi_nor_info_init_params(struct spi_nor *nor) · 19 unmodified lines | ||
| 4316 | 4340 | * Please note that there is a ->post_bfpt() fixup hook that can overwrite |
| 4317 | 4341 | * the flash parameters and settings immediately after parsing the Basic |
| 4318 | 4342 | * Flash Parameter Table. |
| 4343 | + * | |
| 4344 | + * 4/ Late default flash parameters initialization, used when the | |
| 4345 | + * ->default_init() hook or the SFDP parser do not set specific params. | |
| 4346 | + * spi_nor_late_init_params() | |
| 4319 | 4347 | */ |
| 4320 | 4348 | static void spi_nor_init_params(struct spi_nor *nor) |
| 4321 | 4349 | { |
| @@ -4326,6 +4354,8 @@ static void spi_nor_init_params(struct spi_nor *nor) · 4 unmodified lines | ||
| 4326 | 4354 | if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && |
| 4327 | 4355 | !(nor->info->flags & SPI_NOR_SKIP_SFDP)) |
| 4328 | 4356 | spi_nor_sfdp_init_params(nor); |
| 4357 | + | |
| 4358 | + spi_nor_late_init_params(nor); | |
| 4329 | 4359 | } |
| 4330 | 4360 | |
| 4331 | 4361 | static int spi_nor_select_read(struct spi_nor *nor, |
| @@ -4707,6 +4737,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, · 375 unmodified lines | ||
| 4707 | 4737 | if (info->flags & SPI_S3AN) |
| 4708 | 4738 | nor->flags |= SNOR_F_READY_XSR_RDY; |
| 4709 | 4739 | |
| 4740 | + if (info->flags & SPI_NOR_HAS_LOCK) | |
| 4741 | + nor->flags |= SNOR_F_HAS_LOCK; | |
| 4742 | + | |
| 4710 | 4743 | /* |
| 4711 | 4744 | * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up |
| 4712 | 4745 | * with the software protection bits set. |
| @@ -4731,16 +4764,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, · 18 unmodified lines | ||
| 4731 | 4764 | mtd->_read = spi_nor_read; |
| 4732 | 4765 | mtd->_resume = spi_nor_resume; |
| 4733 | 4766 | |
| 4734 | − /* NOR protection support for STmicro/Micron chips and similar */ | |
| 4735 | − if (JEDEC_MFR(info) == SNOR_MFR_ST || | |
| 4736 | − JEDEC_MFR(info) == SNOR_MFR_MICRON || | |
| 4737 | − info->flags & SPI_NOR_HAS_LOCK) { | |
| 4738 | − nor->flash_lock = stm_lock; | |
| 4739 | − nor->flash_unlock = stm_unlock; | |
| 4740 | − nor->flash_is_locked = stm_is_locked; | |
| 4741 | − } | |
| 4742 | − | |
| 4743 | − if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) { | |
| 4767 | + if (nor->params.locking_ops) { | |
| 4744 | 4768 | mtd->_lock = spi_nor_lock; |
| 4745 | 4769 | mtd->_unlock = spi_nor_unlock; |
| 4746 | 4770 | mtd->_is_locked = spi_nor_is_locked; |
| @@ -243,6 +243,7 @@ enum spi_nor_option_flags { · 242 unmodified lines | ||
| 243 | 243 | SNOR_F_BROKEN_RESET = BIT(6), |
| 244 | 244 | SNOR_F_4B_OPCODES = BIT(7), |
| 245 | 245 | SNOR_F_HAS_4BAIT = BIT(8), |
| 246 | + SNOR_F_HAS_LOCK = BIT(9), | |
| 246 | 247 | }; |
| 247 | 248 | |
| 248 | 249 | /** |
| @@ -465,6 +466,18 @@ enum spi_nor_pp_command_index { · 216 unmodified lines | ||
| 465 | 466 | /* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */ |
| 466 | 467 | struct spi_nor; |
| 467 | 468 | |
| 469 | +/** | |
| 470 | + * struct spi_nor_locking_ops - SPI NOR locking methods | |
| 471 | + * @lock: lock a region of the SPI NOR. | |
| 472 | + * @unlock: unlock a region of the SPI NOR. | |
| 473 | + * @is_locked: check if a region of the SPI NOR is completely locked | |
| 474 | + */ | |
| 475 | +struct spi_nor_locking_ops { | |
| 476 | + int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); | |
| 477 | + int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); | |
| 478 | + int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); | |
| 479 | +}; | |
| 480 | + | |
| 468 | 481 | /** |
| 469 | 482 | * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings. |
| 470 | 483 | * Includes legacy flash parameters and settings that can be overwritten |
| @@ -483,6 +496,7 @@ struct spi_nor; · 12 unmodified lines | ||
| 483 | 496 | * Table. |
| 484 | 497 | * @quad_enable: enables SPI NOR quad mode. |
| 485 | 498 | * @set_4byte: puts the SPI NOR in 4 byte addressing mode. |
| 499 | + * @locking_ops: SPI NOR locking methods. | |
| 486 | 500 | */ |
| 487 | 501 | struct spi_nor_flash_parameter { |
| 488 | 502 | u64 size; |
| @@ -496,6 +510,8 @@ struct spi_nor_flash_parameter { · 7 unmodified lines | ||
| 496 | 510 | |
| 497 | 511 | int (*quad_enable)(struct spi_nor *nor); |
| 498 | 512 | int (*set_4byte)(struct spi_nor *nor, bool enable); |
| 513 | + | |
| 514 | + const struct spi_nor_locking_ops *locking_ops; | |
| 499 | 515 | }; |
| 500 | 516 | |
| 501 | 517 | /** |
| @@ -536,10 +552,6 @@ struct flash_info; · 34 unmodified lines | ||
| 536 | 552 | * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR |
| 537 | 553 | * at the offset @offs; if not provided by the driver, |
| 538 | 554 | * spi-nor will send the erase opcode via write_reg() |
| 539 | − * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR | |
| 540 | − * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR | |
| 541 | − * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is | |
| 542 | − * completely locked | |
| 543 | 555 | * @clear_sr_bp: [FLASH-SPECIFIC] clears the Block Protection Bits from |
| 544 | 556 | * the SPI NOR Status Register. |
| 545 | 557 | * @params: [FLASH-SPECIFIC] SPI-NOR flash parameters and settings. |
| @@ -579,9 +591,6 @@ struct spi_nor { · 33 unmodified lines | ||
| 579 | 591 | size_t len, const u_char *write_buf); |
| 580 | 592 | int (*erase)(struct spi_nor *nor, loff_t offs); |
| 581 | 593 | |
| 582 | − int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); | |
| 583 | − int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); | |
| 584 | − int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); | |
| 585 | 594 | int (*clear_sr_bp)(struct spi_nor *nor); |
| 586 | 595 | struct spi_nor_flash_parameter params; |
| 587 | 596 | |