History

mtd: spi-nor: Add a ->setup() method

nor->params.setup() configures the SPI NOR memory. Useful for SPI NOR flashes that have peculiarities to the SPI NOR standard, e.g. different opcodes, specific address calculation, page size, etc. Right now the only user will be the S3AN chips, but other manufacturers can implement it if needed. Move spi_nor_setup() related code in order to avoid a forward declaration to spi_nor_default_setup().

Tudor Ambarus committed 7 years ago

Commit 2d7ff851 parent 36499592 files · +226 −211Browse files

Unified · Split

2 files
  1. drivers/mtd/spi-nor/spi-nor.c +221 −211
  2. include/linux/mtd/spi-nor.h +5 −0
drivers/mtd/spi-nor/spi-nor.c+221−211
@@ -4144,6 +4144,226 @@ exit: · 4143 unmodified lines
41444144 return err;
41454145 }
41464146
4147+static int spi_nor_select_read(struct spi_nor *nor,
4148+ u32 shared_hwcaps)
4149+{
4150+ int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_READ_MASK) - 1;
4151+ const struct spi_nor_read_command *read;
4152+
4153+ if (best_match < 0)
4154+ return -EINVAL;
4155+
4156+ cmd = spi_nor_hwcaps_read2cmd(BIT(best_match));
4157+ if (cmd < 0)
4158+ return -EINVAL;
4159+
4160+ read = &nor->params.reads[cmd];
4161+ nor->read_opcode = read->opcode;
4162+ nor->read_proto = read->proto;
4163+
4164+ /*
4165+ * In the spi-nor framework, we don't need to make the difference
4166+ * between mode clock cycles and wait state clock cycles.
4167+ * Indeed, the value of the mode clock cycles is used by a QSPI
4168+ * flash memory to know whether it should enter or leave its 0-4-4
4169+ * (Continuous Read / XIP) mode.
4170+ * eXecution In Place is out of the scope of the mtd sub-system.
4171+ * Hence we choose to merge both mode and wait state clock cycles
4172+ * into the so called dummy clock cycles.
4173+ */
4174+ nor->read_dummy = read->num_mode_clocks + read->num_wait_states;
4175+ return 0;
4176+}
4177+
4178+static int spi_nor_select_pp(struct spi_nor *nor,
4179+ u32 shared_hwcaps)
4180+{
4181+ int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_PP_MASK) - 1;
4182+ const struct spi_nor_pp_command *pp;
4183+
4184+ if (best_match < 0)
4185+ return -EINVAL;
4186+
4187+ cmd = spi_nor_hwcaps_pp2cmd(BIT(best_match));
4188+ if (cmd < 0)
4189+ return -EINVAL;
4190+
4191+ pp = &nor->params.page_programs[cmd];
4192+ nor->program_opcode = pp->opcode;
4193+ nor->write_proto = pp->proto;
4194+ return 0;
4195+}
4196+
4197+/**
4198+ * spi_nor_select_uniform_erase() - select optimum uniform erase type
4199+ * @map: the erase map of the SPI NOR
4200+ * @wanted_size: the erase type size to search for. Contains the value of
4201+ * info->sector_size or of the "small sector" size in case
4202+ * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined.
4203+ *
4204+ * Once the optimum uniform sector erase command is found, disable all the
4205+ * other.
4206+ *
4207+ * Return: pointer to erase type on success, NULL otherwise.
4208+ */
4209+static const struct spi_nor_erase_type *
4210+spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
4211+ const u32 wanted_size)
4212+{
4213+ const struct spi_nor_erase_type *tested_erase, *erase = NULL;
4214+ int i;
4215+ u8 uniform_erase_type = map->uniform_erase_type;
4216+
4217+ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
4218+ if (!(uniform_erase_type & BIT(i)))
4219+ continue;
4220+
4221+ tested_erase = &map->erase_type[i];
4222+
4223+ /*
4224+ * If the current erase size is the one, stop here:
4225+ * we have found the right uniform Sector Erase command.
4226+ */
4227+ if (tested_erase->size == wanted_size) {
4228+ erase = tested_erase;
4229+ break;
4230+ }
4231+
4232+ /*
4233+ * Otherwise, the current erase size is still a valid canditate.
4234+ * Select the biggest valid candidate.
4235+ */
4236+ if (!erase && tested_erase->size)
4237+ erase = tested_erase;
4238+ /* keep iterating to find the wanted_size */
4239+ }
4240+
4241+ if (!erase)
4242+ return NULL;
4243+
4244+ /* Disable all other Sector Erase commands. */
4245+ map->uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK;
4246+ map->uniform_erase_type |= BIT(erase - map->erase_type);
4247+ return erase;
4248+}
4249+
4250+static int spi_nor_select_erase(struct spi_nor *nor, u32 wanted_size)
4251+{
4252+ struct spi_nor_erase_map *map = &nor->params.erase_map;
4253+ const struct spi_nor_erase_type *erase = NULL;
4254+ struct mtd_info *mtd = &nor->mtd;
4255+ int i;
4256+
4257+ /*
4258+ * The previous implementation handling Sector Erase commands assumed
4259+ * that the SPI flash memory has an uniform layout then used only one
4260+ * of the supported erase sizes for all Sector Erase commands.
4261+ * So to be backward compatible, the new implementation also tries to
4262+ * manage the SPI flash memory as uniform with a single erase sector
4263+ * size, when possible.
4264+ */
4265+#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
4266+ /* prefer "small sector" erase if possible */
4267+ wanted_size = 4096u;
4268+#endif
4269+
4270+ if (spi_nor_has_uniform_erase(nor)) {
4271+ erase = spi_nor_select_uniform_erase(map, wanted_size);
4272+ if (!erase)
4273+ return -EINVAL;
4274+ nor->erase_opcode = erase->opcode;
4275+ mtd->erasesize = erase->size;
4276+ return 0;
4277+ }
4278+
4279+ /*
4280+ * For non-uniform SPI flash memory, set mtd->erasesize to the
4281+ * maximum erase sector size. No need to set nor->erase_opcode.
4282+ */
4283+ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
4284+ if (map->erase_type[i].size) {
4285+ erase = &map->erase_type[i];
4286+ break;
4287+ }
4288+ }
4289+
4290+ if (!erase)
4291+ return -EINVAL;
4292+
4293+ mtd->erasesize = erase->size;
4294+ return 0;
4295+}
4296+
4297+static int spi_nor_default_setup(struct spi_nor *nor,
4298+ const struct spi_nor_hwcaps *hwcaps)
4299+{
4300+ struct spi_nor_flash_parameter *params = &nor->params;
4301+ u32 ignored_mask, shared_mask;
4302+ int err;
4303+
4304+ /*
4305+ * Keep only the hardware capabilities supported by both the SPI
4306+ * controller and the SPI flash memory.
4307+ */
4308+ shared_mask = hwcaps->mask & params->hwcaps.mask;
4309+
4310+ if (nor->spimem) {
4311+ /*
4312+ * When called from spi_nor_probe(), all caps are set and we
4313+ * need to discard some of them based on what the SPI
4314+ * controller actually supports (using spi_mem_supports_op()).
4315+ */
4316+ spi_nor_spimem_adjust_hwcaps(nor, &shared_mask);
4317+ } else {
4318+ /*
4319+ * SPI n-n-n protocols are not supported when the SPI
4320+ * controller directly implements the spi_nor interface.
4321+ * Yet another reason to switch to spi-mem.
4322+ */
4323+ ignored_mask = SNOR_HWCAPS_X_X_X;
4324+ if (shared_mask & ignored_mask) {
4325+ dev_dbg(nor->dev,
4326+ "SPI n-n-n protocols are not supported.\n");
4327+ shared_mask &= ~ignored_mask;
4328+ }
4329+ }
4330+
4331+ /* Select the (Fast) Read command. */
4332+ err = spi_nor_select_read(nor, shared_mask);
4333+ if (err) {
4334+ dev_err(nor->dev,
4335+ "can't select read settings supported by both the SPI controller and memory.\n");
4336+ return err;
4337+ }
4338+
4339+ /* Select the Page Program command. */
4340+ err = spi_nor_select_pp(nor, shared_mask);
4341+ if (err) {
4342+ dev_err(nor->dev,
4343+ "can't select write settings supported by both the SPI controller and memory.\n");
4344+ return err;
4345+ }
4346+
4347+ /* Select the Sector Erase command. */
4348+ err = spi_nor_select_erase(nor, nor->info->sector_size);
4349+ if (err) {
4350+ dev_err(nor->dev,
4351+ "can't select erase settings supported by both the SPI controller and memory.\n");
4352+ return err;
4353+ }
4354+
4355+ return 0;
4356+}
4357+
4358+static int spi_nor_setup(struct spi_nor *nor,
4359+ const struct spi_nor_hwcaps *hwcaps)
4360+{
4361+ if (!nor->params.setup)
4362+ return 0;
4363+
4364+ return nor->params.setup(nor, hwcaps);
4365+}
4366+
41474367 static void macronix_set_default_init(struct spi_nor *nor)
41484368 {
41494369 nor->params.quad_enable = macronix_quad_enable;
@@ -4229,6 +4449,7 @@ static void spi_nor_info_init_params(struct spi_nor *nor) · 79 unmodified lines
42294449 /* Initialize legacy flash parameters and settings. */
42304450 params->quad_enable = spansion_quad_enable;
42314451 params->set_4byte = spansion_set_4byte;
4452+ params->setup = spi_nor_default_setup;
42324453
42334454 /* Set SPI NOR sizes. */
42344455 params->size = (u64)info->sector_size * info->n_sectors;
@@ -4403,217 +4624,6 @@ static void spi_nor_init_params(struct spi_nor *nor) · 168 unmodified lines
44034624 spi_nor_late_init_params(nor);
44044625 }
44054626
4406−static int spi_nor_select_read(struct spi_nor *nor,
4407− u32 shared_hwcaps)
4408−{
4409− int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_READ_MASK) - 1;
4410− const struct spi_nor_read_command *read;
4411−
4412− if (best_match < 0)
4413− return -EINVAL;
4414−
4415− cmd = spi_nor_hwcaps_read2cmd(BIT(best_match));
4416− if (cmd < 0)
4417− return -EINVAL;
4418−
4419− read = &nor->params.reads[cmd];
4420− nor->read_opcode = read->opcode;
4421− nor->read_proto = read->proto;
4422−
4423− /*
4424− * In the spi-nor framework, we don't need to make the difference
4425− * between mode clock cycles and wait state clock cycles.
4426− * Indeed, the value of the mode clock cycles is used by a QSPI
4427− * flash memory to know whether it should enter or leave its 0-4-4
4428− * (Continuous Read / XIP) mode.
4429− * eXecution In Place is out of the scope of the mtd sub-system.
4430− * Hence we choose to merge both mode and wait state clock cycles
4431− * into the so called dummy clock cycles.
4432− */
4433− nor->read_dummy = read->num_mode_clocks + read->num_wait_states;
4434− return 0;
4435−}
4436−
4437−static int spi_nor_select_pp(struct spi_nor *nor,
4438− u32 shared_hwcaps)
4439−{
4440− int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_PP_MASK) - 1;
4441− const struct spi_nor_pp_command *pp;
4442−
4443− if (best_match < 0)
4444− return -EINVAL;
4445−
4446− cmd = spi_nor_hwcaps_pp2cmd(BIT(best_match));
4447− if (cmd < 0)
4448− return -EINVAL;
4449−
4450− pp = &nor->params.page_programs[cmd];
4451− nor->program_opcode = pp->opcode;
4452− nor->write_proto = pp->proto;
4453− return 0;
4454−}
4455−
4456−/**
4457− * spi_nor_select_uniform_erase() - select optimum uniform erase type
4458− * @map: the erase map of the SPI NOR
4459− * @wanted_size: the erase type size to search for. Contains the value of
4460− * info->sector_size or of the "small sector" size in case
4461− * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined.
4462− *
4463− * Once the optimum uniform sector erase command is found, disable all the
4464− * other.
4465− *
4466− * Return: pointer to erase type on success, NULL otherwise.
4467− */
4468−static const struct spi_nor_erase_type *
4469−spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
4470− const u32 wanted_size)
4471−{
4472− const struct spi_nor_erase_type *tested_erase, *erase = NULL;
4473− int i;
4474− u8 uniform_erase_type = map->uniform_erase_type;
4475−
4476− for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
4477− if (!(uniform_erase_type & BIT(i)))
4478− continue;
4479−
4480− tested_erase = &map->erase_type[i];
4481−
4482− /*
4483− * If the current erase size is the one, stop here:
4484− * we have found the right uniform Sector Erase command.
4485− */
4486− if (tested_erase->size == wanted_size) {
4487− erase = tested_erase;
4488− break;
4489− }
4490−
4491− /*
4492− * Otherwise, the current erase size is still a valid canditate.
4493− * Select the biggest valid candidate.
4494− */
4495− if (!erase && tested_erase->size)
4496− erase = tested_erase;
4497− /* keep iterating to find the wanted_size */
4498− }
4499−
4500− if (!erase)
4501− return NULL;
4502−
4503− /* Disable all other Sector Erase commands. */
4504− map->uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK;
4505− map->uniform_erase_type |= BIT(erase - map->erase_type);
4506− return erase;
4507−}
4508−
4509−static int spi_nor_select_erase(struct spi_nor *nor, u32 wanted_size)
4510−{
4511− struct spi_nor_erase_map *map = &nor->params.erase_map;
4512− const struct spi_nor_erase_type *erase = NULL;
4513− struct mtd_info *mtd = &nor->mtd;
4514− int i;
4515−
4516− /*
4517− * The previous implementation handling Sector Erase commands assumed
4518− * that the SPI flash memory has an uniform layout then used only one
4519− * of the supported erase sizes for all Sector Erase commands.
4520− * So to be backward compatible, the new implementation also tries to
4521− * manage the SPI flash memory as uniform with a single erase sector
4522− * size, when possible.
4523− */
4524−#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
4525− /* prefer "small sector" erase if possible */
4526− wanted_size = 4096u;
4527−#endif
4528−
4529− if (spi_nor_has_uniform_erase(nor)) {
4530− erase = spi_nor_select_uniform_erase(map, wanted_size);
4531− if (!erase)
4532− return -EINVAL;
4533− nor->erase_opcode = erase->opcode;
4534− mtd->erasesize = erase->size;
4535− return 0;
4536− }
4537−
4538− /*
4539− * For non-uniform SPI flash memory, set mtd->erasesize to the
4540− * maximum erase sector size. No need to set nor->erase_opcode.
4541− */
4542− for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
4543− if (map->erase_type[i].size) {
4544− erase = &map->erase_type[i];
4545− break;
4546− }
4547− }
4548−
4549− if (!erase)
4550− return -EINVAL;
4551−
4552− mtd->erasesize = erase->size;
4553− return 0;
4554−}
4555−
4556−static int spi_nor_setup(struct spi_nor *nor,
4557− const struct spi_nor_hwcaps *hwcaps)
4558−{
4559− struct spi_nor_flash_parameter *params = &nor->params;
4560− u32 ignored_mask, shared_mask;
4561− int err;
4562−
4563− /*
4564− * Keep only the hardware capabilities supported by both the SPI
4565− * controller and the SPI flash memory.
4566− */
4567− shared_mask = hwcaps->mask & params->hwcaps.mask;
4568−
4569− if (nor->spimem) {
4570− /*
4571− * When called from spi_nor_probe(), all caps are set and we
4572− * need to discard some of them based on what the SPI
4573− * controller actually supports (using spi_mem_supports_op()).
4574− */
4575− spi_nor_spimem_adjust_hwcaps(nor, &shared_mask);
4576− } else {
4577− /*
4578− * SPI n-n-n protocols are not supported when the SPI
4579− * controller directly implements the spi_nor interface.
4580− * Yet another reason to switch to spi-mem.
4581− */
4582− ignored_mask = SNOR_HWCAPS_X_X_X;
4583− if (shared_mask & ignored_mask) {
4584− dev_dbg(nor->dev,
4585− "SPI n-n-n protocols are not supported.\n");
4586− shared_mask &= ~ignored_mask;
4587− }
4588− }
4589−
4590− /* Select the (Fast) Read command. */
4591− err = spi_nor_select_read(nor, shared_mask);
4592− if (err) {
4593− dev_err(nor->dev,
4594− "can't select read settings supported by both the SPI controller and memory.\n");
4595− return err;
4596− }
4597−
4598− /* Select the Page Program command. */
4599− err = spi_nor_select_pp(nor, shared_mask);
4600− if (err) {
4601− dev_err(nor->dev,
4602− "can't select write settings supported by both the SPI controller and memory.\n");
4603− return err;
4604− }
4605−
4606− /* Select the Sector Erase command. */
4607− err = spi_nor_select_erase(nor, nor->info->sector_size);
4608− if (err) {
4609− dev_err(nor->dev,
4610− "can't select erase settings supported by both the SPI controller and memory.\n");
4611− return err;
4612− }
4613−
4614− return 0;
4615−}
4616−
46174627 /**
46184628 * spi_nor_quad_enable() - enable Quad I/O if needed.
46194629 * @nor: pointer to a 'struct spi_nor'
include/linux/mtd/spi-nor.h+5−0
@@ -498,6 +498,10 @@ struct spi_nor_locking_ops { · 497 unmodified lines
498498 * @convert_addr: converts an absolute address into something the flash
499499 * will understand. Particularly useful when pagesize is
500500 * not a power-of-2.
501+ * @setup: configures the SPI NOR memory. Useful for SPI NOR
502+ * flashes that have peculiarities to the SPI NOR standard
503+ * e.g. different opcodes, specific address calculation,
504+ * page size, etc.
501505 * @locking_ops: SPI NOR locking methods.
502506 */
503507 struct spi_nor_flash_parameter {
@@ -513,6 +517,7 @@ struct spi_nor_flash_parameter { · 9 unmodified lines
513517 int (*quad_enable)(struct spi_nor *nor);
514518 int (*set_4byte)(struct spi_nor *nor, bool enable);
515519 u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
520+ int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
516521
517522 const struct spi_nor_locking_ops *locking_ops;
518523 };

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t