* [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller
@ 2024-11-13 9:49 Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 1/7] memory: ti-aemif: Create aemif_check_cs_timings() Bastien Curutchet
` (6 more replies)
0 siblings, 7 replies; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet
Hi all,
This patch series aims to implement the setup_interface() operation in
the DaVinci NAND controller to enable the use of all ONFI modes and
improve the NAND access speed.
PATCH 3 depends on PATCH 1-2
PATCH 7 depends on PATCH 3-5-6
This NAND controller is present in the DaVinci (OMAP L138) and Keystone2
SoCs and functions as a 'child' of the AEMIF controller. So its timings
are set by the AEMIF controller itself from device-tree properties.
Implementing the setup_interface() callback implies being able to update
dynamically these timings, so the first three patches of the series modify
the AEMIF driver to provide its 'children' a way to modify their chip
select timing configuration.
The remaining patches implement the setup_interface() operation.
The computation of the register's contents is directly based on
§20.3.2.3 of the OMAP-L138 TRM [1]
This has been tested on two platforms based upon the DaVinci SoC. One is
interfaced with a Macronix MX30UF4G18AC NAND, the other with a Toshiba
NAND.
[1] : https://www.ti.com/lit/ug/spruh77c/spruh77c.pdf
Change log:
* v3
PATCH 1 [new]:
- Wrap the verification of CS timing configuration into a function
PATCH 2:
- Fix comments
PATCH 3:
- Replace the spin-lock with a mutex
PATCH 7:
- Add handling of the NAND_DATA_IFACE_CHECK_ONLY case
- setup_interface() returns errno on failures
* v2
Cover letter :
- Add dependency details
- Remove the question about ti-aemif.h location
PATCH 1 :
- Fix aemif_cs_timings's description in the comments
PATCH 2 :
- Fix typo in the config_cs_lock's description in the comments
- Move include/memory/ti-aemif.h to include/linux/memory/ti-aemif.h
PATCH 3 [NEW] :
- Fix dependency issue with aemif controller in Kconfig
PATCH 5 :
- Add details about the clock bindings in the commit log
- Replace devm_clk_get() with devm_clk_get_enabled()
- Use dev_err_probe() to return the devm_clk_get_enabled() error
[v1] : https://lore.kernel.org/all/20241030104717.88688-1-bastien.curutchet@bootlin.com/
[v2] : https://lore.kernel.org/all/20241106085507.76425-1-bastien.curutchet@bootlin.com/
Bastien Curutchet (7):
memory: ti-aemif: Create aemif_check_cs_timings()
memory: ti-aemif: Create aemif_set_cs_timings()
memory: ti-aemif: Export aemif_*_cs_timings()
mtd: rawnand: davinci: Always depends on TI_AEMIF
mtd: rawnand: davinci: Order headers alphabetically
mtd: rawnand: davinci: Add clock resource
mtd: rawnand: davinci: Implement setup_interface() operation
drivers/memory/ti-aemif.c | 137 +++++++++++++++++++++-------
drivers/mtd/nand/raw/Kconfig | 4 +-
drivers/mtd/nand/raw/davinci_nand.c | 94 ++++++++++++++++++-
include/linux/memory/ti-aemif.h | 32 +++++++
4 files changed, 229 insertions(+), 38 deletions(-)
create mode 100644 include/linux/memory/ti-aemif.h
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 1/7] memory: ti-aemif: Create aemif_check_cs_timings()
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
@ 2024-11-13 9:49 ` Bastien Curutchet
2024-11-13 10:51 ` Miquel Raynal
2024-11-13 9:49 ` [PATCH v3 2/7] memory: ti-aemif: Create aemif_set_cs_timings() Bastien Curutchet
` (5 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet
aemif_calc_rate() check the validity of a new computed timing against a
'max' value given as input. This isn't convenient if we want to check
the CS timing configuration somewhere else in the code.
Wrap the verification of all the chip select's timing configuration into a
single function to ease its exportation in upcoming patches.
Remove the 'max' input from aemif_calc_rate() as it's no longer used.
Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
drivers/memory/ti-aemif.c | 89 ++++++++++++++++++++++++++++++---------
1 file changed, 69 insertions(+), 20 deletions(-)
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
index d54dc3cfff73..eef086c8371b 100644
--- a/drivers/memory/ti-aemif.c
+++ b/drivers/memory/ti-aemif.c
@@ -107,6 +107,27 @@ struct aemif_cs_data {
u8 asize;
};
+/**
+ * struct aemif_cs_timings: structure to hold CS timing configuration
+ * values are expressed in number of clock cycles - 1
+ * @ta: minimum turn around time
+ * @rhold: read hold width
+ * @rstrobe: read strobe width
+ * @rsetup: read setup width
+ * @whold: write hold width
+ * @wstrobe: write strobe width
+ * @wsetup: write setup width
+ */
+struct aemif_cs_timings {
+ u32 ta;
+ u32 rhold;
+ u32 rstrobe;
+ u32 rsetup;
+ u32 whold;
+ u32 wstrobe;
+ u32 wsetup;
+};
+
/**
* struct aemif_device: structure to hold device data
* @base: base address of AEMIF registers
@@ -125,18 +146,48 @@ struct aemif_device {
struct aemif_cs_data cs_data[NUM_CS];
};
+/**
+ * aemif_check_cs_timings - Check the validity of a CS timing configuration.
+ * @timings: timings configuration
+ *
+ * @return: 0 if the timing configuration is valid, negative errno otherwise.
+ */
+static int aemif_check_cs_timings(struct aemif_cs_timings *timings)
+{
+ if (timings->ta > TA_MAX)
+ return -EINVAL;
+
+ if (timings->rhold > RHOLD_MAX)
+ return -EINVAL;
+
+ if (timings->rstrobe > RSTROBE_MAX)
+ return -EINVAL;
+
+ if (timings->rsetup > RSETUP_MAX)
+ return -EINVAL;
+
+ if (timings->whold > WHOLD_MAX)
+ return -EINVAL;
+
+ if (timings->wstrobe > WSTROBE_MAX)
+ return -EINVAL;
+
+ if (timings->wsetup > WSETUP_MAX)
+ return -EINVAL;
+
+ return 0;
+}
+
/**
* aemif_calc_rate - calculate timing data.
* @pdev: platform device to calculate for
* @wanted: The cycle time needed in nanoseconds.
* @clk: The input clock rate in kHz.
- * @max: The maximum divider value that can be programmed.
*
* On success, returns the calculated timing value minus 1 for easy
* programming into AEMIF timing registers, else negative errno.
*/
-static int aemif_calc_rate(struct platform_device *pdev, int wanted,
- unsigned long clk, int max)
+static int aemif_calc_rate(struct platform_device *pdev, int wanted, unsigned long clk)
{
int result;
@@ -149,10 +200,6 @@ static int aemif_calc_rate(struct platform_device *pdev, int wanted,
if (result < 0)
result = 0;
- /* ... But configuring tighter timings is not an option. */
- else if (result > max)
- result = -EINVAL;
-
return result;
}
@@ -174,30 +221,32 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum)
{
struct aemif_device *aemif = platform_get_drvdata(pdev);
struct aemif_cs_data *data = &aemif->cs_data[csnum];
- int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
unsigned long clk_rate = aemif->clk_rate;
+ struct aemif_cs_timings timings;
unsigned offset;
u32 set, val;
+ int ret;
offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4;
- ta = aemif_calc_rate(pdev, data->ta, clk_rate, TA_MAX);
- rhold = aemif_calc_rate(pdev, data->rhold, clk_rate, RHOLD_MAX);
- rstrobe = aemif_calc_rate(pdev, data->rstrobe, clk_rate, RSTROBE_MAX);
- rsetup = aemif_calc_rate(pdev, data->rsetup, clk_rate, RSETUP_MAX);
- whold = aemif_calc_rate(pdev, data->whold, clk_rate, WHOLD_MAX);
- wstrobe = aemif_calc_rate(pdev, data->wstrobe, clk_rate, WSTROBE_MAX);
- wsetup = aemif_calc_rate(pdev, data->wsetup, clk_rate, WSETUP_MAX);
+ timings.ta = aemif_calc_rate(pdev, data->ta, clk_rate);
+ timings.rhold = aemif_calc_rate(pdev, data->rhold, clk_rate);
+ timings.rstrobe = aemif_calc_rate(pdev, data->rstrobe, clk_rate);
+ timings.rsetup = aemif_calc_rate(pdev, data->rsetup, clk_rate);
+ timings.whold = aemif_calc_rate(pdev, data->whold, clk_rate);
+ timings.wstrobe = aemif_calc_rate(pdev, data->wstrobe, clk_rate);
+ timings.wsetup = aemif_calc_rate(pdev, data->wsetup, clk_rate);
- if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
- whold < 0 || wstrobe < 0 || wsetup < 0) {
+ ret = aemif_check_cs_timings(&timings);
+ if (ret) {
dev_err(&pdev->dev, "%s: cannot get suitable timings\n",
__func__);
- return -EINVAL;
+ return ret;
}
- set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
- WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
+ set = TA(timings.ta) |
+ RHOLD(timings.rhold) | RSTROBE(timings.rstrobe) | RSETUP(timings.rsetup) |
+ WHOLD(timings.whold) | WSTROBE(timings.wstrobe) | WSETUP(timings.wsetup);
set |= (data->asize & ACR_ASIZE_MASK);
if (data->enable_ew)
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 2/7] memory: ti-aemif: Create aemif_set_cs_timings()
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 1/7] memory: ti-aemif: Create aemif_check_cs_timings() Bastien Curutchet
@ 2024-11-13 9:49 ` Bastien Curutchet
2024-11-13 10:52 ` Miquel Raynal
2024-11-13 9:49 ` [PATCH v3 3/7] memory: ti-aemif: Export aemif_*_cs_timings() Bastien Curutchet
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet
Create an aemif_set_cs_timings() function to isolate the setting of a
chip select timing configuration and ease its exportation.
Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
drivers/memory/ti-aemif.c | 64 ++++++++++++++++++++++++++++++---------
1 file changed, 49 insertions(+), 15 deletions(-)
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
index eef086c8371b..b1236cc9ce92 100644
--- a/drivers/memory/ti-aemif.c
+++ b/drivers/memory/ti-aemif.c
@@ -69,15 +69,15 @@
#define ACR_SSTROBE_MASK BIT(31)
#define ASIZE_16BIT 1
-#define CONFIG_MASK (TA(TA_MAX) | \
- RHOLD(RHOLD_MAX) | \
- RSTROBE(RSTROBE_MAX) | \
- RSETUP(RSETUP_MAX) | \
- WHOLD(WHOLD_MAX) | \
- WSTROBE(WSTROBE_MAX) | \
- WSETUP(WSETUP_MAX) | \
- EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | \
- ASIZE_MAX)
+#define TIMINGS_MASK (TA(TA_MAX) | \
+ RHOLD(RHOLD_MAX) | \
+ RSTROBE(RSTROBE_MAX) | \
+ RSETUP(RSETUP_MAX) | \
+ WHOLD(WHOLD_MAX) | \
+ WSTROBE(WSTROBE_MAX) | \
+ WSETUP(WSETUP_MAX))
+
+#define CONFIG_MASK (EW(EW_MAX) | SSTROBE(SSTROBE_MAX) | ASIZE_MAX)
/**
* struct aemif_cs_data: structure to hold cs parameters
@@ -178,6 +178,44 @@ static int aemif_check_cs_timings(struct aemif_cs_timings *timings)
return 0;
}
+/**
+ * aemif_set_cs_timings - Set the timing configuration of a given chip select.
+ * @aemif: aemif device to configure
+ * @cs: index of the chip select to configure
+ * @timings: timings configuration to set
+ *
+ * @return: 0 on success, else negative errno.
+ */
+static int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings)
+{
+ unsigned int offset;
+ u32 val, set;
+ int ret;
+
+ if (!timings || !aemif)
+ return -EINVAL;
+
+ if (cs > aemif->num_cs)
+ return -EINVAL;
+
+ ret = aemif_check_cs_timings(timings);
+ if (ret)
+ return ret;
+
+ set = TA(timings->ta) | RHOLD(timings->rhold) | RSTROBE(timings->rstrobe) |
+ RSETUP(timings->rsetup) | WHOLD(timings->whold) |
+ WSTROBE(timings->wstrobe) | WSETUP(timings->wsetup);
+
+ offset = A1CR_OFFSET + cs * 4;
+
+ val = readl(aemif->base + offset);
+ val &= ~TIMINGS_MASK;
+ val |= set;
+ writel(val, aemif->base + offset);
+
+ return 0;
+}
+
/**
* aemif_calc_rate - calculate timing data.
* @pdev: platform device to calculate for
@@ -244,11 +282,7 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum)
return ret;
}
- set = TA(timings.ta) |
- RHOLD(timings.rhold) | RSTROBE(timings.rstrobe) | RSETUP(timings.rsetup) |
- WHOLD(timings.whold) | WSTROBE(timings.wstrobe) | WSETUP(timings.wsetup);
-
- set |= (data->asize & ACR_ASIZE_MASK);
+ set = (data->asize & ACR_ASIZE_MASK);
if (data->enable_ew)
set |= ACR_EW_MASK;
if (data->enable_ss)
@@ -259,7 +293,7 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum)
val |= set;
writel(val, aemif->base + offset);
- return 0;
+ return aemif_set_cs_timings(aemif, data->cs - aemif->cs_offset, &timings);
}
static inline int aemif_cycles_to_nsec(int val, unsigned long clk_rate)
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 3/7] memory: ti-aemif: Export aemif_*_cs_timings()
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 1/7] memory: ti-aemif: Create aemif_check_cs_timings() Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 2/7] memory: ti-aemif: Create aemif_set_cs_timings() Bastien Curutchet
@ 2024-11-13 9:49 ` Bastien Curutchet
2024-11-13 10:55 ` Miquel Raynal
2024-11-13 9:49 ` [PATCH v3 4/7] mtd: rawnand: davinci: Always depends on TI_AEMIF Bastien Curutchet
` (3 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet
Export the aemif_set_cs_timing() and aemif_check_cs_timing() symbols so
they can be used by other drivers
Add a mutex to protect the CS configuration register from concurrent
accesses between the AEMIF and its 'children'.
Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
drivers/memory/ti-aemif.c | 36 ++++++++++++---------------------
include/linux/memory/ti-aemif.h | 32 +++++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 23 deletions(-)
create mode 100644 include/linux/memory/ti-aemif.h
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
index b1236cc9ce92..7f0ca256db3c 100644
--- a/drivers/memory/ti-aemif.c
+++ b/drivers/memory/ti-aemif.c
@@ -13,7 +13,9 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/memory/ti-aemif.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
@@ -107,27 +109,6 @@ struct aemif_cs_data {
u8 asize;
};
-/**
- * struct aemif_cs_timings: structure to hold CS timing configuration
- * values are expressed in number of clock cycles - 1
- * @ta: minimum turn around time
- * @rhold: read hold width
- * @rstrobe: read strobe width
- * @rsetup: read setup width
- * @whold: write hold width
- * @wstrobe: write strobe width
- * @wsetup: write setup width
- */
-struct aemif_cs_timings {
- u32 ta;
- u32 rhold;
- u32 rstrobe;
- u32 rsetup;
- u32 whold;
- u32 wstrobe;
- u32 wsetup;
-};
-
/**
* struct aemif_device: structure to hold device data
* @base: base address of AEMIF registers
@@ -136,6 +117,7 @@ struct aemif_cs_timings {
* @num_cs: number of assigned chip-selects
* @cs_offset: start number of cs nodes
* @cs_data: array of chip-select settings
+ * @config_cs_lock: lock used to access CS configuration
*/
struct aemif_device {
void __iomem *base;
@@ -144,6 +126,7 @@ struct aemif_device {
u8 num_cs;
int cs_offset;
struct aemif_cs_data cs_data[NUM_CS];
+ struct mutex config_cs_lock;
};
/**
@@ -152,7 +135,7 @@ struct aemif_device {
*
* @return: 0 if the timing configuration is valid, negative errno otherwise.
*/
-static int aemif_check_cs_timings(struct aemif_cs_timings *timings)
+int aemif_check_cs_timings(struct aemif_cs_timings *timings)
{
if (timings->ta > TA_MAX)
return -EINVAL;
@@ -177,6 +160,7 @@ static int aemif_check_cs_timings(struct aemif_cs_timings *timings)
return 0;
}
+EXPORT_SYMBOL(aemif_check_cs_timings);
/**
* aemif_set_cs_timings - Set the timing configuration of a given chip select.
@@ -186,7 +170,7 @@ static int aemif_check_cs_timings(struct aemif_cs_timings *timings)
*
* @return: 0 on success, else negative errno.
*/
-static int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings)
+int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings)
{
unsigned int offset;
u32 val, set;
@@ -208,13 +192,16 @@ static int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_
offset = A1CR_OFFSET + cs * 4;
+ mutex_lock(&aemif->config_cs_lock);
val = readl(aemif->base + offset);
val &= ~TIMINGS_MASK;
val |= set;
writel(val, aemif->base + offset);
+ mutex_unlock(&aemif->config_cs_lock);
return 0;
}
+EXPORT_SYMBOL(aemif_set_cs_timings);
/**
* aemif_calc_rate - calculate timing data.
@@ -288,10 +275,12 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum)
if (data->enable_ss)
set |= ACR_SSTROBE_MASK;
+ mutex_lock(&aemif->config_cs_lock);
val = readl(aemif->base + offset);
val &= ~CONFIG_MASK;
val |= set;
writel(val, aemif->base + offset);
+ mutex_unlock(&aemif->config_cs_lock);
return aemif_set_cs_timings(aemif, data->cs - aemif->cs_offset, &timings);
}
@@ -434,6 +423,7 @@ static int aemif_probe(struct platform_device *pdev)
if (IS_ERR(aemif->base))
return PTR_ERR(aemif->base);
+ mutex_init(&aemif->config_cs_lock);
if (np) {
/*
* For every controller device node, there is a cs device node
diff --git a/include/linux/memory/ti-aemif.h b/include/linux/memory/ti-aemif.h
new file mode 100644
index 000000000000..0640d30f6321
--- /dev/null
+++ b/include/linux/memory/ti-aemif.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __TI_AEMIF_H
+#define __TI_AEMIF_H
+
+/**
+ * struct aemif_cs_timings: structure to hold CS timing configuration
+ * values are expressed in number of clock cycles - 1
+ * @ta: minimum turn around time
+ * @rhold: read hold width
+ * @rstrobe: read strobe width
+ * @rsetup: read setup width
+ * @whold: write hold width
+ * @wstrobe: write strobe width
+ * @wsetup: write setup width
+ */
+struct aemif_cs_timings {
+ u32 ta;
+ u32 rhold;
+ u32 rstrobe;
+ u32 rsetup;
+ u32 whold;
+ u32 wstrobe;
+ u32 wsetup;
+};
+
+struct aemif_device;
+
+int aemif_set_cs_timings(struct aemif_device *aemif, u8 cs, struct aemif_cs_timings *timings);
+int aemif_check_cs_timings(struct aemif_cs_timings *timings);
+
+#endif // __TI_AEMIF_H
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 4/7] mtd: rawnand: davinci: Always depends on TI_AEMIF
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
` (2 preceding siblings ...)
2024-11-13 9:49 ` [PATCH v3 3/7] memory: ti-aemif: Export aemif_*_cs_timings() Bastien Curutchet
@ 2024-11-13 9:49 ` Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 5/7] mtd: rawnand: davinci: Order headers alphabetically Bastien Curutchet
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet, kernel test robot
DAVINCI_NAND depends on TI_AEMIF only when ARCH_KEYSTONE is selected
while the NAND controller is also always a part of the AEMIF controller
on DaVinci SoCs.
Set a dependency on TI_AEMIF regardless of the selected architecture.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202411020140.3wsKJOSB-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202411020957.X1T8T9ZR-lkp@intel.com/
Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
drivers/mtd/nand/raw/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index d0aaccf72d78..bb61434347bd 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -279,8 +279,8 @@ config MTD_NAND_SH_FLCTL
config MTD_NAND_DAVINCI
tristate "DaVinci/Keystone NAND controller"
- depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF) || COMPILE_TEST
- depends on HAS_IOMEM
+ depends on COMPILE_TEST || ARCH_DAVINCI || ARCH_KEYSTONE
+ depends on HAS_IOMEM && TI_AEMIF
help
Enable the driver for NAND flash chips on Texas Instruments
DaVinci/Keystone processors.
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 5/7] mtd: rawnand: davinci: Order headers alphabetically
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
` (3 preceding siblings ...)
2024-11-13 9:49 ` [PATCH v3 4/7] mtd: rawnand: davinci: Always depends on TI_AEMIF Bastien Curutchet
@ 2024-11-13 9:49 ` Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 6/7] mtd: rawnand: davinci: Add clock resource Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 7/7] mtd: rawnand: davinci: Implement setup_interface() operation Bastien Curutchet
6 siblings, 0 replies; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet
Order headers alphabetically for better readability.
Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
drivers/mtd/nand/raw/davinci_nand.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 392678143a36..3c0efbdd789e 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -10,15 +10,15 @@
* Dirk Behme <Dirk.Behme@gmail.com>
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
-#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
#define NRCSR_OFFSET 0x00
#define NANDFCR_OFFSET 0x60
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 6/7] mtd: rawnand: davinci: Add clock resource
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
` (4 preceding siblings ...)
2024-11-13 9:49 ` [PATCH v3 5/7] mtd: rawnand: davinci: Order headers alphabetically Bastien Curutchet
@ 2024-11-13 9:49 ` Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 7/7] mtd: rawnand: davinci: Implement setup_interface() operation Bastien Curutchet
6 siblings, 0 replies; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet
NAND controller has a reference clock inherited from the AEMIF
(cf. Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt)
This clock isn't used yet by the driver.
Add a struct clock in the struct davinci_nand_info so it can be used
to compute timings.
Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
drivers/mtd/nand/raw/davinci_nand.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 3c0efbdd789e..563045c7ce08 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -10,6 +10,7 @@
* Dirk Behme <Dirk.Behme@gmail.com>
*/
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
@@ -117,6 +118,8 @@ struct davinci_nand_info {
uint32_t mask_cle;
uint32_t core_chipsel;
+
+ struct clk *clk;
};
static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -822,6 +825,10 @@ static int nand_davinci_probe(struct platform_device *pdev)
return -EADDRNOTAVAIL;
}
+ info->clk = devm_clk_get_enabled(&pdev->dev, "aemif");
+ if (IS_ERR(info->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(info->clk), "failed to get clock");
+
info->pdev = pdev;
info->base = base;
info->vaddr = vaddr;
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 7/7] mtd: rawnand: davinci: Implement setup_interface() operation
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
` (5 preceding siblings ...)
2024-11-13 9:49 ` [PATCH v3 6/7] mtd: rawnand: davinci: Add clock resource Bastien Curutchet
@ 2024-11-13 9:49 ` Bastien Curutchet
6 siblings, 0 replies; 11+ messages in thread
From: Bastien Curutchet @ 2024-11-13 9:49 UTC (permalink / raw)
To: Santosh Shilimkar, Krzysztof Kozlowski, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
Cc: linux-kernel, linux-mtd, Thomas Petazzoni, Herve Codina,
Christopher Cordahi, Bastien Curutchet
The setup_interface() operation isn't implemented. It forces the driver
to use the ONFI mode 0, though it could use more optimal modes.
Implement the setup_interface() operation. It uses the
aemif_set_cs_timings() function from the AEMIF driver to update the
chip select timings. The calculation of the register's contents is
directly extracted from §20.3.2.3 of the DaVinci TRM [1]
MAX_TH_PS and MAX_TSU_PS are the worst case timings based on the
Keystone2 and DaVinci datasheets.
[1] : https://www.ti.com/lit/ug/spruh77c/spruh77c.pdf
Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
---
drivers/mtd/nand/raw/davinci_nand.c | 79 +++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 563045c7ce08..00627c2783f8 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
+#include <linux/memory/ti-aemif.h>
#include <linux/module.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
@@ -44,6 +45,9 @@
#define MASK_ALE 0x08
#define MASK_CLE 0x10
+#define MAX_TSU_PS 3000 /* Input setup time in ps */
+#define MAX_TH_PS 1600 /* Input hold time in ps */
+
struct davinci_nand_pdata {
uint32_t mask_ale;
uint32_t mask_cle;
@@ -120,6 +124,7 @@ struct davinci_nand_info {
uint32_t core_chipsel;
struct clk *clk;
+ struct aemif_device *aemif;
};
static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -767,9 +772,82 @@ static int davinci_nand_exec_op(struct nand_chip *chip,
return 0;
}
+#define TO_CYCLES(ps, period_ns) (DIV_ROUND_UP((ps) / 1000, (period_ns)))
+
+static int davinci_nand_setup_interface(struct nand_chip *chip, int chipnr,
+ const struct nand_interface_config *conf)
+{
+ struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip));
+ const struct nand_sdr_timings *sdr;
+ struct aemif_cs_timings timings;
+ s32 cfg, min, cyc_ns;
+ int ret;
+
+ cyc_ns = 1000000000 / clk_get_rate(info->clk);
+
+ sdr = nand_get_sdr_timings(conf);
+ if (IS_ERR(sdr))
+ return PTR_ERR(sdr);
+
+ cfg = TO_CYCLES(sdr->tCLR_min, cyc_ns) - 1;
+ timings.rsetup = cfg > 0 ? cfg : 0;
+
+ cfg = max_t(s32, TO_CYCLES(sdr->tREA_max + MAX_TSU_PS, cyc_ns),
+ TO_CYCLES(sdr->tRP_min, cyc_ns)) - 1;
+ timings.rstrobe = cfg > 0 ? cfg : 0;
+
+ min = TO_CYCLES(sdr->tCEA_max + MAX_TSU_PS, cyc_ns) - 2;
+ while ((s32)(timings.rsetup + timings.rstrobe) < min)
+ timings.rstrobe++;
+
+ cfg = TO_CYCLES((s32)(MAX_TH_PS - sdr->tCHZ_max), cyc_ns) - 1;
+ timings.rhold = cfg > 0 ? cfg : 0;
+
+ min = TO_CYCLES(sdr->tRC_min, cyc_ns) - 3;
+ while ((s32)(timings.rsetup + timings.rstrobe + timings.rhold) < min)
+ timings.rhold++;
+
+ cfg = TO_CYCLES((s32)(sdr->tRHZ_max - (timings.rhold + 1) * cyc_ns * 1000), cyc_ns);
+ cfg = max_t(s32, cfg, TO_CYCLES(sdr->tCHZ_max, cyc_ns)) - 1;
+ timings.ta = cfg > 0 ? cfg : 0;
+
+ cfg = TO_CYCLES(sdr->tWP_min, cyc_ns) - 1;
+ timings.wstrobe = cfg > 0 ? cfg : 0;
+
+ cfg = max_t(s32, TO_CYCLES(sdr->tCLS_min, cyc_ns), TO_CYCLES(sdr->tALS_min, cyc_ns));
+ cfg = max_t(s32, cfg, TO_CYCLES(sdr->tCS_min, cyc_ns)) - 1;
+ timings.wsetup = cfg > 0 ? cfg : 0;
+
+ min = TO_CYCLES(sdr->tDS_min, cyc_ns) - 2;
+ while ((s32)(timings.wsetup + timings.wstrobe) < min)
+ timings.wstrobe++;
+
+ cfg = max_t(s32, TO_CYCLES(sdr->tCLH_min, cyc_ns), TO_CYCLES(sdr->tALH_min, cyc_ns));
+ cfg = max_t(s32, cfg, TO_CYCLES(sdr->tCH_min, cyc_ns));
+ cfg = max_t(s32, cfg, TO_CYCLES(sdr->tDH_min, cyc_ns)) - 1;
+ timings.whold = cfg > 0 ? cfg : 0;
+
+ min = TO_CYCLES(sdr->tWC_min, cyc_ns) - 2;
+ while ((s32)(timings.wsetup + timings.wstrobe + timings.whold) < min)
+ timings.whold++;
+
+ dev_dbg(&info->pdev->dev, "RSETUP %x RSTROBE %x RHOLD %x\n",
+ timings.rsetup, timings.rstrobe, timings.rhold);
+ dev_dbg(&info->pdev->dev, "TA %x\n", timings.ta);
+ dev_dbg(&info->pdev->dev, "WSETUP %x WSTROBE %x WHOLD %x\n",
+ timings.wsetup, timings.wstrobe, timings.whold);
+
+ ret = aemif_check_cs_timings(&timings);
+ if (ret || chipnr == NAND_DATA_IFACE_CHECK_ONLY)
+ return ret;
+
+ return aemif_set_cs_timings(info->aemif, info->core_chipsel, &timings);
+}
+
static const struct nand_controller_ops davinci_nand_controller_ops = {
.attach_chip = davinci_nand_attach_chip,
.exec_op = davinci_nand_exec_op,
+ .setup_interface = davinci_nand_setup_interface,
};
static int nand_davinci_probe(struct platform_device *pdev)
@@ -832,6 +910,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
info->pdev = pdev;
info->base = base;
info->vaddr = vaddr;
+ info->aemif = dev_get_drvdata(pdev->dev.parent);
mtd = nand_to_mtd(&info->chip);
mtd->dev.parent = &pdev->dev;
--
2.47.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/7] memory: ti-aemif: Create aemif_check_cs_timings()
2024-11-13 9:49 ` [PATCH v3 1/7] memory: ti-aemif: Create aemif_check_cs_timings() Bastien Curutchet
@ 2024-11-13 10:51 ` Miquel Raynal
0 siblings, 0 replies; 11+ messages in thread
From: Miquel Raynal @ 2024-11-13 10:51 UTC (permalink / raw)
To: Bastien Curutchet
Cc: Santosh Shilimkar, Krzysztof Kozlowski, Richard Weinberger,
Vignesh Raghavendra, linux-kernel, linux-mtd, Thomas Petazzoni,
Herve Codina, Christopher Cordahi
Hi Bastien,
On 13/11/2024 at 10:49:32 +01, Bastien Curutchet <bastien.curutchet@bootlin.com> wrote:
> aemif_calc_rate() check the validity of a new computed timing against a
> 'max' value given as input. This isn't convenient if we want to check
> the CS timing configuration somewhere else in the code.
>
> Wrap the verification of all the chip select's timing configuration into a
> single function to ease its exportation in upcoming patches.
> Remove the 'max' input from aemif_calc_rate() as it's no longer used.
I would split this commit into two separate smaller chunks. First, you
use a timings structure (which is a good idea), and second you
extract/clarify the timing checks. This is two different "features" IMO.
> Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
> ---
> drivers/memory/ti-aemif.c | 89 ++++++++++++++++++++++++++++++---------
> 1 file changed, 69 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
> index d54dc3cfff73..eef086c8371b 100644
> --- a/drivers/memory/ti-aemif.c
> +++ b/drivers/memory/ti-aemif.c
> @@ -107,6 +107,27 @@ struct aemif_cs_data {
> u8 asize;
> };
>
> +/**
> + * struct aemif_cs_timings: structure to hold CS timing configuration
> + * values are expressed in number of clock cycles - 1
> + * @ta: minimum turn around time
> + * @rhold: read hold width
> + * @rstrobe: read strobe width
> + * @rsetup: read setup width
> + * @whold: write hold width
> + * @wstrobe: write strobe width
> + * @wsetup: write setup width
> + */
> +struct aemif_cs_timings {
> + u32 ta;
> + u32 rhold;
> + u32 rstrobe;
> + u32 rsetup;
> + u32 whold;
> + u32 wstrobe;
> + u32 wsetup;
> +};
> +
> /**
> * struct aemif_device: structure to hold device data
> * @base: base address of AEMIF registers
> @@ -125,18 +146,48 @@ struct aemif_device {
> struct aemif_cs_data cs_data[NUM_CS];
> };
>
> +/**
> + * aemif_check_cs_timings - Check the validity of a CS timing configuration.
> + * @timings: timings configuration
> + *
> + * @return: 0 if the timing configuration is valid, negative errno
> otherwise.
I thinks errno is a bit connoted "userspace", here you return a
"negative error number".
> + */
> +static int aemif_check_cs_timings(struct aemif_cs_timings *timings)
> +{
> + if (timings->ta > TA_MAX)
> + return -EINVAL;
> +
> + if (timings->rhold > RHOLD_MAX)
> + return -EINVAL;
> +
> + if (timings->rstrobe > RSTROBE_MAX)
> + return -EINVAL;
> +
> + if (timings->rsetup > RSETUP_MAX)
> + return -EINVAL;
> +
> + if (timings->whold > WHOLD_MAX)
> + return -EINVAL;
> +
> + if (timings->wstrobe > WSTROBE_MAX)
> + return -EINVAL;
> +
> + if (timings->wsetup > WSETUP_MAX)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> /**
> * aemif_calc_rate - calculate timing data.
> * @pdev: platform device to calculate for
> * @wanted: The cycle time needed in nanoseconds.
> * @clk: The input clock rate in kHz.
> - * @max: The maximum divider value that can be programmed.
> *
> * On success, returns the calculated timing value minus 1 for easy
> * programming into AEMIF timing registers, else negative errno.
> */
> -static int aemif_calc_rate(struct platform_device *pdev, int wanted,
> - unsigned long clk, int max)
> +static int aemif_calc_rate(struct platform_device *pdev, int wanted, unsigned long clk)
> {
> int result;
>
> @@ -149,10 +200,6 @@ static int aemif_calc_rate(struct platform_device *pdev, int wanted,
> if (result < 0)
> result = 0;
>
> - /* ... But configuring tighter timings is not an option. */
> - else if (result > max)
> - result = -EINVAL;
> -
> return result;
> }
>
> @@ -174,30 +221,32 @@ static int aemif_config_abus(struct platform_device *pdev, int csnum)
> {
> struct aemif_device *aemif = platform_get_drvdata(pdev);
> struct aemif_cs_data *data = &aemif->cs_data[csnum];
> - int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
> unsigned long clk_rate = aemif->clk_rate;
> + struct aemif_cs_timings timings;
This is a matter of taste, but even though you fully initialize the
structure below *today*, I'd be future-proof by resetting the structure
here:
struct aemif_cs_timings timings = {};
> unsigned offset;
> u32 set, val;
> + int ret;
>
> offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4;
>
> - ta = aemif_calc_rate(pdev, data->ta, clk_rate, TA_MAX);
> - rhold = aemif_calc_rate(pdev, data->rhold, clk_rate, RHOLD_MAX);
> - rstrobe = aemif_calc_rate(pdev, data->rstrobe, clk_rate, RSTROBE_MAX);
> - rsetup = aemif_calc_rate(pdev, data->rsetup, clk_rate, RSETUP_MAX);
> - whold = aemif_calc_rate(pdev, data->whold, clk_rate, WHOLD_MAX);
> - wstrobe = aemif_calc_rate(pdev, data->wstrobe, clk_rate, WSTROBE_MAX);
> - wsetup = aemif_calc_rate(pdev, data->wsetup, clk_rate, WSETUP_MAX);
> + timings.ta = aemif_calc_rate(pdev, data->ta, clk_rate);
> + timings.rhold = aemif_calc_rate(pdev, data->rhold, clk_rate);
> + timings.rstrobe = aemif_calc_rate(pdev, data->rstrobe, clk_rate);
> + timings.rsetup = aemif_calc_rate(pdev, data->rsetup, clk_rate);
> + timings.whold = aemif_calc_rate(pdev, data->whold, clk_rate);
> + timings.wstrobe = aemif_calc_rate(pdev, data->wstrobe, clk_rate);
> + timings.wsetup = aemif_calc_rate(pdev, data->wsetup, clk_rate);
>
> - if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
> - whold < 0 || wstrobe < 0 || wsetup < 0) {
> + ret = aemif_check_cs_timings(&timings);
> + if (ret) {
> dev_err(&pdev->dev, "%s: cannot get suitable timings\n",
> __func__);
> - return -EINVAL;
> + return ret;
> }
>
> - set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
> - WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
> + set = TA(timings.ta) |
> + RHOLD(timings.rhold) | RSTROBE(timings.rstrobe) | RSETUP(timings.rsetup) |
> + WHOLD(timings.whold) | WSTROBE(timings.wstrobe) | WSETUP(timings.wsetup);
>
> set |= (data->asize & ACR_ASIZE_MASK);
> if (data->enable_ew)
Otherwise lgtm.
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 2/7] memory: ti-aemif: Create aemif_set_cs_timings()
2024-11-13 9:49 ` [PATCH v3 2/7] memory: ti-aemif: Create aemif_set_cs_timings() Bastien Curutchet
@ 2024-11-13 10:52 ` Miquel Raynal
0 siblings, 0 replies; 11+ messages in thread
From: Miquel Raynal @ 2024-11-13 10:52 UTC (permalink / raw)
To: Bastien Curutchet
Cc: Santosh Shilimkar, Krzysztof Kozlowski, Richard Weinberger,
Vignesh Raghavendra, linux-kernel, linux-mtd, Thomas Petazzoni,
Herve Codina, Christopher Cordahi
On 13/11/2024 at 10:49:33 +01, Bastien Curutchet <bastien.curutchet@bootlin.com> wrote:
> Create an aemif_set_cs_timings() function to isolate the setting of a
> chip select timing configuration and ease its exportation.
>
> Signed-off-by: Bastien Curutchet <bastien.curutchet@bootlin.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 3/7] memory: ti-aemif: Export aemif_*_cs_timings()
2024-11-13 9:49 ` [PATCH v3 3/7] memory: ti-aemif: Export aemif_*_cs_timings() Bastien Curutchet
@ 2024-11-13 10:55 ` Miquel Raynal
0 siblings, 0 replies; 11+ messages in thread
From: Miquel Raynal @ 2024-11-13 10:55 UTC (permalink / raw)
To: Bastien Curutchet
Cc: Santosh Shilimkar, Krzysztof Kozlowski, Richard Weinberger,
Vignesh Raghavendra, linux-kernel, linux-mtd, Thomas Petazzoni,
Herve Codina, Christopher Cordahi
On 13/11/2024 at 10:49:34 +01, Bastien Curutchet <bastien.curutchet@bootlin.com> wrote:
> Export the aemif_set_cs_timing() and aemif_check_cs_timing() symbols so
> they can be used by other drivers
>
> Add a mutex to protect the CS configuration register from concurrent
> accesses between the AEMIF and its 'children'.
I'll let Krzysztof judge whether it is okay to use EXPORT_SYMBOL instead
of EXPORT_SYMBOL_GPL here, but otherwise looks ok to me.
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2024-11-13 10:55 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-13 9:49 [PATCH v3 0/7] Implement setup_interface() in the DaVinci NAND controller Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 1/7] memory: ti-aemif: Create aemif_check_cs_timings() Bastien Curutchet
2024-11-13 10:51 ` Miquel Raynal
2024-11-13 9:49 ` [PATCH v3 2/7] memory: ti-aemif: Create aemif_set_cs_timings() Bastien Curutchet
2024-11-13 10:52 ` Miquel Raynal
2024-11-13 9:49 ` [PATCH v3 3/7] memory: ti-aemif: Export aemif_*_cs_timings() Bastien Curutchet
2024-11-13 10:55 ` Miquel Raynal
2024-11-13 9:49 ` [PATCH v3 4/7] mtd: rawnand: davinci: Always depends on TI_AEMIF Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 5/7] mtd: rawnand: davinci: Order headers alphabetically Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 6/7] mtd: rawnand: davinci: Add clock resource Bastien Curutchet
2024-11-13 9:49 ` [PATCH v3 7/7] mtd: rawnand: davinci: Implement setup_interface() operation Bastien Curutchet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).