Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
* [PATCH v5 0/2] add NXP LINFlexD UART clock support for S32G2/S32G3
@ 2024-11-18 15:44 Ciprian Costea
  2024-11-18 15:44 ` [PATCH v5 1/2] dt-bindings: serial: fsl-linflexuart: add clock definitions Ciprian Costea
  2024-11-18 15:44 ` [PATCH v5 2/2] serial: fsl_linflexuart: add clock management Ciprian Costea
  0 siblings, 2 replies; 4+ messages in thread
From: Ciprian Costea @ 2024-11-18 15:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chester Lin
  Cc: linux-kernel, linux-serial, devicetree, imx, NXP S32 Linux,
	Christophe Lizzi, Alberto Ruiz, Enric Balletbo,
	Ciprian Marian Costea

From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>

LINFlexD driver was working on S32 based boards without clock management
because the downstream bootloaders (TF-A [1] and U-Boot [2]) were
performing the LINFlexD clock management.

LINFlexD driver from Linux Kernel should manage its clocks independently
and not rely on a previous bootloader configuration.

[1] https://github.com/nxp-auto-linux/arm-trusted-firmware
[2] https://github.com/nxp-auto-linux/u-boot

Changes in V5:
- Use 'devm_add_action_or_reset' to disable LINFlexD clocks if errors
occur on the probe path.

Changes in V4:
- Switched clock management to 'clk bulk' API usage
- Added more context for this patchset

Changes in V3:
- Fixed an error reported by 'dt_bindings_check'

Changes in V2:
- Updated bindings by adding more information related to required
LINFlexD clocks

Ciprian Marian Costea (2):
  dt-bindings: serial: fsl-linflexuart: add clock definitions
  serial: fsl_linflexuart: add clock management

 .../bindings/serial/fsl,s32-linflexuart.yaml  | 16 ++++
 drivers/tty/serial/fsl_linflexuart.c          | 95 ++++++++++++++++---
 2 files changed, 97 insertions(+), 14 deletions(-)

-- 
2.45.2


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v5 1/2] dt-bindings: serial: fsl-linflexuart: add clock definitions
  2024-11-18 15:44 [PATCH v5 0/2] add NXP LINFlexD UART clock support for S32G2/S32G3 Ciprian Costea
@ 2024-11-18 15:44 ` Ciprian Costea
  2024-11-18 15:44 ` [PATCH v5 2/2] serial: fsl_linflexuart: add clock management Ciprian Costea
  1 sibling, 0 replies; 4+ messages in thread
From: Ciprian Costea @ 2024-11-18 15:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chester Lin
  Cc: linux-kernel, linux-serial, devicetree, imx, NXP S32 Linux,
	Christophe Lizzi, Alberto Ruiz, Enric Balletbo,
	Ciprian Marian Costea, Conor Dooley

From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>

Add clock definitions for NXP LINFlexD UART bindings.

The LINFlexD driver was working because the LINFlexD clocks were
configured and kept enabled by the downstream bootloader (TF-A [1]
and U-Boot [2]). This is not ideal since LINFlexD Linux driver should
manage its clocks independently and not rely on a previous bootloader
configuration.

[1] https://github.com/nxp-auto-linux/arm-trusted-firmware
[2] https://github.com/nxp-auto-linux/u-boot

Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
 .../bindings/serial/fsl,s32-linflexuart.yaml     | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.yaml b/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.yaml
index 4171f524a928..ca3146d9b872 100644
--- a/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.yaml
@@ -34,10 +34,24 @@ properties:
   interrupts:
     maxItems: 1
 
+  clocks:
+    items:
+      - description:
+          ipg clock drives the access to the LINFlexD
+          iomapped registers
+      - description: lin is the frequency of the baud clock
+
+  clock-names:
+    items:
+      - const: ipg
+      - const: lin
+
 required:
   - compatible
   - reg
   - interrupts
+  - clocks
+  - clock-names
 
 unevaluatedProperties: false
 
@@ -47,4 +61,6 @@ examples:
         compatible = "fsl,s32v234-linflexuart";
         reg = <0x40053000 0x1000>;
         interrupts = <0 59 4>;
+        clocks = <&clks 132>, <&clks 131>;
+        clock-names = "ipg", "lin";
     };
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 2/2] serial: fsl_linflexuart: add clock management
  2024-11-18 15:44 [PATCH v5 0/2] add NXP LINFlexD UART clock support for S32G2/S32G3 Ciprian Costea
  2024-11-18 15:44 ` [PATCH v5 1/2] dt-bindings: serial: fsl-linflexuart: add clock definitions Ciprian Costea
@ 2024-11-18 15:44 ` Ciprian Costea
  2024-11-21 22:36   ` kernel test robot
  1 sibling, 1 reply; 4+ messages in thread
From: Ciprian Costea @ 2024-11-18 15:44 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chester Lin
  Cc: linux-kernel, linux-serial, devicetree, imx, NXP S32 Linux,
	Christophe Lizzi, Alberto Ruiz, Enric Balletbo,
	Ciprian Marian Costea

From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>

Add optional clock 'ipg' and 'lin' support to NXP LINFlexD UART driver,
which is used by S32G2 and S32G3 SoCs.

LINFlex driver should perform clock management and not rely on a previous
bootloader configuration.

Clocking support is added as optional in order to not break existing
support for S32V234 SoC. Therefore, there should be no impact if not
providing LINFlexD clocks and continue to rely on a bootloader clock
configuration and enablement.

Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
---
 drivers/tty/serial/fsl_linflexuart.c | 95 ++++++++++++++++++++++++----
 1 file changed, 81 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c
index e972df4b188d..394c2f66d4a2 100644
--- a/drivers/tty/serial/fsl_linflexuart.c
+++ b/drivers/tty/serial/fsl_linflexuart.c
@@ -3,9 +3,10 @@
  * Freescale LINFlexD UART serial port driver
  *
  * Copyright 2012-2016 Freescale Semiconductor, Inc.
- * Copyright 2017-2019 NXP
+ * Copyright 2017-2019, 2024 NXP
  */
 
+#include <linux/clk.h>
 #include <linux/console.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -120,9 +121,29 @@
 
 #define PREINIT_DELAY			2000 /* us */
 
+struct linflex_devtype_data {
+	const char * const *clks_names;
+	int n_clks;
+};
+
+struct linflex_port {
+	struct uart_port port;
+	struct clk_bulk_data *clks;
+	const struct linflex_devtype_data *devtype_data;
+};
+
+static const char * const s32v234_clk_names[] = {
+	"ipg", "lin",
+};
+
+static const struct linflex_devtype_data s32v234_data = {
+	.clks_names = s32v234_clk_names,
+	.n_clks = ARRAY_SIZE(s32v234_clk_names),
+};
+
 static const struct of_device_id linflex_dt_ids[] = {
 	{
-		.compatible = "fsl,s32v234-linflexuart",
+		.compatible = "fsl,s32v234-linflexuart", .data = &s32v234_data,
 	},
 	{ /* sentinel */ }
 };
@@ -776,6 +797,14 @@ static void linflex_earlycon_write(struct console *con, const char *s,
 	uart_console_write(&dev->port, s, n, linflex_earlycon_putchar);
 }
 
+static void linflex_disable_clks(void *data)
+{
+	struct linflex_port *lfport = data;
+
+	clk_bulk_disable_unprepare(lfport->devtype_data->n_clks,
+				   lfport->clks);
+}
+
 static int __init linflex_early_console_setup(struct earlycon_device *device,
 					      const char *options)
 {
@@ -807,12 +836,13 @@ static struct uart_driver linflex_reg = {
 static int linflex_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
+	struct linflex_port *lfport;
 	struct uart_port *sport;
 	struct resource *res;
-	int ret;
+	int i, ret;
 
-	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
-	if (!sport)
+	lfport = devm_kzalloc(&pdev->dev, sizeof(*lfport), GFP_KERNEL);
+	if (!lfport)
 		return -ENOMEM;
 
 	ret = of_alias_get_id(np, "serial");
@@ -826,8 +856,14 @@ static int linflex_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	sport = &lfport->port;
 	sport->line = ret;
 
+	lfport->devtype_data = of_device_get_match_data(&pdev->dev);
+	if (!lfport->devtype_data)
+		return dev_err_probe(&pdev->dev, -ENODEV,
+				"Failed to get linflexuart driver data\n");
+
 	sport->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(sport->membase))
 		return PTR_ERR(sport->membase);
@@ -844,37 +880,68 @@ static int linflex_probe(struct platform_device *pdev)
 	sport->flags = UPF_BOOT_AUTOCONF;
 	sport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE);
 
-	linflex_ports[sport->line] = sport;
+	lfport->clks = devm_kmalloc_array(&pdev->dev, lfport->devtype_data->n_clks,
+					  sizeof(*lfport->clks), GFP_KERNEL);
+	if (!lfport->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < lfport->devtype_data->n_clks; i++)
+		lfport->clks[i].id = lfport->devtype_data->clks_names[i];
+
+	ret = devm_clk_bulk_get_optional(&pdev->dev,
+					 lfport->devtype_data->n_clks, lfport->clks);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				"Failed to get linflexuart clocks\n");
 
-	platform_set_drvdata(pdev, sport);
+	ret = clk_bulk_prepare_enable(lfport->devtype_data->n_clks,
+				      lfport->clks);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				"Failed to enable linflexuart clocks\n");
+
+	ret = devm_add_action_or_reset(&pdev->dev,
+				       linflex_disable_clks, lfport);
+	if (ret)
+		return ret;
+
+	linflex_ports[sport->line] = sport;
+	platform_set_drvdata(pdev, lfport);
 
 	return uart_add_one_port(&linflex_reg, sport);
 }
 
 static void linflex_remove(struct platform_device *pdev)
 {
-	struct uart_port *sport = platform_get_drvdata(pdev);
+	struct linflex_port *lfport = platform_get_drvdata(pdev);
 
-	uart_remove_one_port(&linflex_reg, sport);
+	uart_remove_one_port(&linflex_reg, &lfport->port);
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int linflex_suspend(struct device *dev)
 {
-	struct uart_port *sport = dev_get_drvdata(dev);
+	struct linflex_port *lfport = dev_get_drvdata(dev);
 
-	uart_suspend_port(&linflex_reg, sport);
+	uart_suspend_port(&linflex_reg, &lfport->port);
+
+	clk_bulk_disable_unprepare(lfport->devtype_data->n_clks,
+				   lfport->clks);
 
 	return 0;
 }
 
 static int linflex_resume(struct device *dev)
 {
-	struct uart_port *sport = dev_get_drvdata(dev);
+	struct linflex_port *lfport = dev_get_drvdata(dev);
+	int ret;
 
-	uart_resume_port(&linflex_reg, sport);
+	ret = clk_bulk_prepare_enable(lfport->devtype_data->n_clks,
+				      lfport->clks);
+	if (ret)
+		return ret;
 
-	return 0;
+	return uart_resume_port(&linflex_reg, &lfport->port);
 }
 #endif
 
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v5 2/2] serial: fsl_linflexuart: add clock management
  2024-11-18 15:44 ` [PATCH v5 2/2] serial: fsl_linflexuart: add clock management Ciprian Costea
@ 2024-11-21 22:36   ` kernel test robot
  0 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2024-11-21 22:36 UTC (permalink / raw)
  To: Ciprian Costea, Greg Kroah-Hartman, Jiri Slaby, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Chester Lin
  Cc: oe-kbuild-all, linux-kernel, linux-serial, devicetree, imx,
	NXP S32 Linux, Christophe Lizzi, Alberto Ruiz, Enric Balletbo,
	Ciprian Marian Costea

Hi Ciprian,

kernel test robot noticed the following build errors:

[auto build test ERROR on tty/tty-testing]
[also build test ERROR on tty/tty-next tty/tty-linus usb/usb-testing usb/usb-next usb/usb-linus robh/for-next linus/master v6.12 next-20241121]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ciprian-Costea/dt-bindings-serial-fsl-linflexuart-add-clock-definitions/20241121-130303
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
patch link:    https://lore.kernel.org/r/20241118154449.3895692-3-ciprianmarian.costea%40oss.nxp.com
patch subject: [PATCH v5 2/2] serial: fsl_linflexuart: add clock management
config: arm64-randconfig-001-20241122 (https://download.01.org/0day-ci/archive/20241122/202411220621.UfubUV0X-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241122/202411220621.UfubUV0X-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202411220621.UfubUV0X-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/platform_device.h:13,
                    from drivers/tty/serial/fsl_linflexuart.c:15:
   drivers/tty/serial/fsl_linflexuart.c: In function 'linflex_probe':
>> drivers/tty/serial/fsl_linflexuart.c:904:40: error: 'linflex_disable_clks' undeclared (first use in this function)
     904 |                                        linflex_disable_clks, lfport);
         |                                        ^~~~~~~~~~~~~~~~~~~~
   include/linux/device.h:421:41: note: in definition of macro 'devm_add_action_or_reset'
     421 |         __devm_add_action_or_reset(dev, action, data, #action)
         |                                         ^~~~~~
   drivers/tty/serial/fsl_linflexuart.c:904:40: note: each undeclared identifier is reported only once for each function it appears in
     904 |                                        linflex_disable_clks, lfport);
         |                                        ^~~~~~~~~~~~~~~~~~~~
   include/linux/device.h:421:41: note: in definition of macro 'devm_add_action_or_reset'
     421 |         __devm_add_action_or_reset(dev, action, data, #action)
         |                                         ^~~~~~


vim +/linflex_disable_clks +904 drivers/tty/serial/fsl_linflexuart.c

   835	
   836	static int linflex_probe(struct platform_device *pdev)
   837	{
   838		struct device_node *np = pdev->dev.of_node;
   839		struct linflex_port *lfport;
   840		struct uart_port *sport;
   841		struct resource *res;
   842		int i, ret;
   843	
   844		lfport = devm_kzalloc(&pdev->dev, sizeof(*lfport), GFP_KERNEL);
   845		if (!lfport)
   846			return -ENOMEM;
   847	
   848		ret = of_alias_get_id(np, "serial");
   849		if (ret < 0) {
   850			dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
   851			return ret;
   852		}
   853		if (ret >= UART_NR) {
   854			dev_err(&pdev->dev, "driver limited to %d serial ports\n",
   855				UART_NR);
   856			return -ENOMEM;
   857		}
   858	
   859		sport = &lfport->port;
   860		sport->line = ret;
   861	
   862		lfport->devtype_data = of_device_get_match_data(&pdev->dev);
   863		if (!lfport->devtype_data)
   864			return dev_err_probe(&pdev->dev, -ENODEV,
   865					"Failed to get linflexuart driver data\n");
   866	
   867		sport->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
   868		if (IS_ERR(sport->membase))
   869			return PTR_ERR(sport->membase);
   870		sport->mapbase = res->start;
   871	
   872		ret = platform_get_irq(pdev, 0);
   873		if (ret < 0)
   874			return ret;
   875	
   876		sport->dev = &pdev->dev;
   877		sport->iotype = UPIO_MEM;
   878		sport->irq = ret;
   879		sport->ops = &linflex_pops;
   880		sport->flags = UPF_BOOT_AUTOCONF;
   881		sport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE);
   882	
   883		lfport->clks = devm_kmalloc_array(&pdev->dev, lfport->devtype_data->n_clks,
   884						  sizeof(*lfport->clks), GFP_KERNEL);
   885		if (!lfport->clks)
   886			return -ENOMEM;
   887	
   888		for (i = 0; i < lfport->devtype_data->n_clks; i++)
   889			lfport->clks[i].id = lfport->devtype_data->clks_names[i];
   890	
   891		ret = devm_clk_bulk_get_optional(&pdev->dev,
   892						 lfport->devtype_data->n_clks, lfport->clks);
   893		if (ret)
   894			return dev_err_probe(&pdev->dev, ret,
   895					"Failed to get linflexuart clocks\n");
   896	
   897		ret = clk_bulk_prepare_enable(lfport->devtype_data->n_clks,
   898					      lfport->clks);
   899		if (ret)
   900			return dev_err_probe(&pdev->dev, ret,
   901					"Failed to enable linflexuart clocks\n");
   902	
   903		ret = devm_add_action_or_reset(&pdev->dev,
 > 904					       linflex_disable_clks, lfport);
   905		if (ret)
   906			return ret;
   907	
   908		linflex_ports[sport->line] = sport;
   909		platform_set_drvdata(pdev, lfport);
   910	
   911		return uart_add_one_port(&linflex_reg, sport);
   912	}
   913	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-11-21 22:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-18 15:44 [PATCH v5 0/2] add NXP LINFlexD UART clock support for S32G2/S32G3 Ciprian Costea
2024-11-18 15:44 ` [PATCH v5 1/2] dt-bindings: serial: fsl-linflexuart: add clock definitions Ciprian Costea
2024-11-18 15:44 ` [PATCH v5 2/2] serial: fsl_linflexuart: add clock management Ciprian Costea
2024-11-21 22:36   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox