diff options
Diffstat (limited to 'queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch')
-rw-r--r-- | queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch | 220 |
1 files changed, 0 insertions, 220 deletions
diff --git a/queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch b/queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch deleted file mode 100644 index 5831735a27..0000000000 --- a/queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 00311c92a5496aed8892149e05fc9b8d66c78b36 Mon Sep 17 00:00:00 2001 -From: Sasha Levin <sashal@kernel.org> -Date: Tue, 24 Dec 2024 18:05:46 +0100 -Subject: spi: spi-mem: Extend spi-mem operations with a per-operation maximum - frequency - -From: Miquel Raynal <miquel.raynal@bootlin.com> - -[ Upstream commit 0fefeade90e74bc8f40ab0e460f483565c492e28 ] - -In the spi subsystem, the bus frequency is derived as follows: -- the controller may expose a minimum and maximum operating frequency -- the hardware description, through the spi peripheral properties, - advise what is the maximum acceptable frequency from a device/wiring - point of view. -Transfers must be observed at a frequency which fits both (so in -practice, the lowest maximum). - -Actually, this second point mixes two information and already takes the -lowest frequency among: -- what the spi device is capable of (what is written in the component - datasheet) -- what the wiring allows (electromagnetic sensibility, crossovers, - terminations, antenna effect, etc). - -This logic works until spi devices are no longer capable of sustaining -their highest frequency regardless of the operation. Spi memories are -typically subject to such variation. Some devices are capable of -spitting their internally stored data (essentially in read mode) at a -very fast rate, typically up to 166MHz on Winbond SPI-NAND chips, using -"fast" commands. However, some of the low-end operations, such as -regular page read-from-cache commands, are more limited and can only be -executed at 54MHz at most. This is currently a problem in the SPI-NAND -subsystem. Another situation, even if not yet supported, will be with -DTR commands, when the data is latched on both edges of the clock. The -same chips as mentioned previously are in this case limited to -80MHz. Yet another example might be continuous reads, which, under -certain circumstances, can also run at most at 104 or 120MHz. - -As a matter of fact, the "one frequency per chip" policy is outdated and -more fine grain configuration is needed: we need to allow per-operation -frequency limitations. So far, all datasheets I encountered advertise a -maximum default frequency, which need to be lowered for certain specific -operations. So based on the current infrastructure, we can still expect -firmware (device trees in general) to continued advertising the same -maximum speed which is a mix between the PCB limitations and the chip -maximum capability, and expect per-operation lower frequencies when this -is relevant. - -Add a `struct spi_mem_op` member to carry this information. Not -providing this field explicitly from upper layers means that there is no -further constraint and the default spi device maximum speed will be -carried instead. The SPI_MEM_OP() macro is also expanded with an -optional frequency argument, because virtually all operations can be -subject to such a limitation, and this will allow for a smooth and -discrete transition. - -For controller drivers which do not implement the spi-mem interface, the -per-transfer speed is also set acordingly to a lower (than the maximum -default) speed when relevant. - -Acked-by: Pratyush Yadav <pratyush@kernel.org> -Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> -Link: https://patch.msgid.link/20241224-winbond-6-11-rc1-quad-support-v2-1-ad218dbc406f@bootlin.com -Signed-off-by: Mark Brown <broonie@kernel.org> -Signed-off-by: Sasha Levin <sashal@kernel.org> ---- - drivers/mtd/nand/spi/core.c | 2 ++ - drivers/spi/spi-mem.c | 28 ++++++++++++++++++++++++++++ - include/linux/spi/spi-mem.h | 12 +++++++++++- - 3 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c -index 4d76f9f71a0e9..075f513157603 100644 ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1214,6 +1214,8 @@ spinand_select_op_variant(struct spinand_device *spinand, - if (ret) - break; - -+ spi_mem_adjust_op_freq(spinand->spimem, &op); -+ - if (!spi_mem_supports_op(spinand->spimem, &op)) - break; - -diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c -index 17b8baf749e6a..f8b598ba962d9 100644 ---- a/drivers/spi/spi-mem.c -+++ b/drivers/spi/spi-mem.c -@@ -184,6 +184,10 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, - return false; - } - -+ if (op->max_freq && mem->spi->controller->min_speed_hz && -+ op->max_freq < mem->spi->controller->min_speed_hz) -+ return false; -+ - return spi_mem_check_buswidth(mem, op); - } - EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); -@@ -361,6 +365,9 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) - u8 *tmpbuf; - int ret; - -+ /* Make sure the operation frequency is correct before going futher */ -+ spi_mem_adjust_op_freq(mem, (struct spi_mem_op *)op); -+ - ret = spi_mem_check_op(op); - if (ret) - return ret; -@@ -407,6 +414,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) - xfers[xferpos].tx_buf = tmpbuf; - xfers[xferpos].len = op->cmd.nbytes; - xfers[xferpos].tx_nbits = op->cmd.buswidth; -+ xfers[xferpos].speed_hz = op->max_freq; - spi_message_add_tail(&xfers[xferpos], &msg); - xferpos++; - totalxferlen++; -@@ -421,6 +429,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) - xfers[xferpos].tx_buf = tmpbuf + 1; - xfers[xferpos].len = op->addr.nbytes; - xfers[xferpos].tx_nbits = op->addr.buswidth; -+ xfers[xferpos].speed_hz = op->max_freq; - spi_message_add_tail(&xfers[xferpos], &msg); - xferpos++; - totalxferlen += op->addr.nbytes; -@@ -432,6 +441,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) - xfers[xferpos].len = op->dummy.nbytes; - xfers[xferpos].tx_nbits = op->dummy.buswidth; - xfers[xferpos].dummy_data = 1; -+ xfers[xferpos].speed_hz = op->max_freq; - spi_message_add_tail(&xfers[xferpos], &msg); - xferpos++; - totalxferlen += op->dummy.nbytes; -@@ -447,6 +457,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) - } - - xfers[xferpos].len = op->data.nbytes; -+ xfers[xferpos].speed_hz = op->max_freq; - spi_message_add_tail(&xfers[xferpos], &msg); - xferpos++; - totalxferlen += op->data.nbytes; -@@ -525,6 +536,23 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) - } - EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size); - -+/** -+ * spi_mem_adjust_op_freq() - Adjust the frequency of a SPI mem operation to -+ * match controller, PCB and chip limitations -+ * @mem: the SPI memory -+ * @op: the operation to adjust -+ * -+ * Some chips have per-op frequency limitations and must adapt the maximum -+ * speed. This function allows SPI mem drivers to set @op->max_freq to the -+ * maximum supported value. -+ */ -+void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op) -+{ -+ if (!op->max_freq || op->max_freq > mem->spi->max_speed_hz) -+ op->max_freq = mem->spi->max_speed_hz; -+} -+EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq); -+ - static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc, - u64 offs, size_t len, void *buf) - { -diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h -index f866d5c8ed32a..44b7ecee0e74c 100644 ---- a/include/linux/spi/spi-mem.h -+++ b/include/linux/spi/spi-mem.h -@@ -68,6 +68,9 @@ enum spi_mem_data_dir { - SPI_MEM_DATA_OUT, - }; - -+#define SPI_MEM_OP_MAX_FREQ(__freq) \ -+ .max_freq = __freq -+ - /** - * struct spi_mem_op - describes a SPI memory operation - * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is -@@ -95,6 +98,9 @@ enum spi_mem_data_dir { - * operation does not involve transferring data - * @data.buf.in: input buffer (must be DMA-able) - * @data.buf.out: output buffer (must be DMA-able) -+ * @max_freq: frequency limitation wrt this operation. 0 means there is no -+ * specific constraint and the highest achievable frequency can be -+ * attempted. - */ - struct spi_mem_op { - struct { -@@ -132,14 +138,17 @@ struct spi_mem_op { - const void *out; - } buf; - } data; -+ -+ unsigned int max_freq; - }; - --#define SPI_MEM_OP(__cmd, __addr, __dummy, __data) \ -+#define SPI_MEM_OP(__cmd, __addr, __dummy, __data, ...) \ - { \ - .cmd = __cmd, \ - .addr = __addr, \ - .dummy = __dummy, \ - .data = __data, \ -+ __VA_ARGS__ \ - } - - /** -@@ -365,6 +374,7 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, - #endif /* CONFIG_SPI_MEM */ - - int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op); -+void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op); - - bool spi_mem_supports_op(struct spi_mem *mem, - const struct spi_mem_op *op); --- -2.39.5 - |