[PATCH] serial: replace all clk_get with clk_get_for_console

Ahmad Fatoum a.fatoum at pengutronix.de
Mon Jun 10 23:58:00 PDT 2024


Unlike clk_get, clk_get_for_console returns NULL when the clock provider
lacks a driver, but the UART has already been configured by DEBUG_LL.

This allows drivers to disable the set baudrate callback and continue
probe, so the user gets to an interactive shell, where they can debug
the system further.

This is a useful thing to have, so let's switch all instance of
clk_get in serial drivers to clk_get_for_console, like we already do
for the STM32 serial driver.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/serial/amba-pl011.c      |  4 ++--
 drivers/serial/atmel.c           | 19 +++++++++----------
 drivers/serial/serial_ar933x.c   | 16 ++++++++--------
 drivers/serial/serial_auart.c    | 28 ++++++++++++++++------------
 drivers/serial/serial_cadence.c  | 13 ++++++++-----
 drivers/serial/serial_clps711x.c |  4 ++--
 drivers/serial/serial_imx.c      | 13 ++++++++-----
 drivers/serial/serial_lpuart.c   | 13 ++++++++-----
 drivers/serial/serial_lpuart32.c |  7 ++++---
 drivers/serial/serial_ns16550.c  | 11 ++++-------
 drivers/serial/serial_sifive.c   | 12 +++++-------
 drivers/serial/stm-serial.c      | 28 +++++++++++++++-------------
 12 files changed, 89 insertions(+), 79 deletions(-)

diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index b53ff6877b77..380778b70e52 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -188,7 +188,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	}
 
 	uart = xzalloc(sizeof(struct amba_uart_port));
-	uart->clk = clk_get(&dev->dev, NULL);
+	uart->clk = clk_get_for_console(&dev->dev, NULL);
 	uart->base = amba_get_mem_region(dev);
 	uart->vendor = (void*)id->data;
 
@@ -200,7 +200,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	cdev->tstc = pl011_tstc;
 	cdev->putc = pl011_putc;
 	cdev->getc = pl011_getc;
-	cdev->setbrg = pl011_setbaudrate;
+	cdev->setbrg = uart->clk ? pl011_setbaudrate : NULL;
 	cdev->linux_console_name = "ttyAMA";
 	cdev->linux_earlycon_name = "pl011";
 	cdev->phys_base = uart->base;
diff --git a/drivers/serial/atmel.c b/drivers/serial/atmel.c
index b957b75284be..2dcb458fbd30 100644
--- a/drivers/serial/atmel.c
+++ b/drivers/serial/atmel.c
@@ -382,16 +382,14 @@ static int atmel_serial_set_mode(struct console_device *cdev, enum console_mode
  * are always 8 data bits, no parity, 1 stop bit, no start bits.
  *
  */
-static int atmel_serial_init_port(struct console_device *cdev)
+static int atmel_serial_init_port(struct device *dev,
+				  struct atmel_uart_port *uart)
 {
-	struct device *dev = cdev->dev;
-	struct atmel_uart_port *uart = to_atmel_uart_port(cdev);
-
 	uart->base = dev_request_mem_region_err_null(dev, 0);
 	if (!uart->base)
 		return -ENOENT;
 
-	uart->clk = clk_get(dev, "usart");
+	uart->clk = clk_get_for_console(dev, "usart");
 	if (IS_ERR(uart->clk)) {
 		dev_err(dev, "Failed to get 'usart' clock\n");
 		return PTR_ERR(uart->clk);
@@ -419,20 +417,21 @@ static int atmel_serial_probe(struct device *dev)
 	int ret;
 
 	uart = xzalloc(sizeof(struct atmel_uart_port));
+
+	ret = atmel_serial_init_port(dev, uart);
+	if (ret)
+		return ret;
+
 	cdev = &uart->uart;
 	cdev->dev = dev;
 	cdev->tstc = atmel_serial_tstc;
 	cdev->putc = atmel_serial_putc;
 	cdev->getc = atmel_serial_getc;
-	cdev->setbrg = atmel_serial_setbaudrate;
+	cdev->setbrg = uart->clk ? atmel_serial_setbaudrate : NULL;
 	cdev->set_mode = atmel_serial_set_mode;
 	cdev->linux_console_name = "ttyAT";
 	cdev->linux_earlycon_name = "atmel_serial";
 
-	ret = atmel_serial_init_port(cdev);
-	if (ret)
-		return ret;
-
 	cdev->phys_base = uart->base;
 
 	/* Enable UART */
diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c
index f5595ec1eed6..32fd0d30a68e 100644
--- a/drivers/serial/serial_ar933x.c
+++ b/drivers/serial/serial_ar933x.c
@@ -157,19 +157,19 @@ static int ar933x_serial_probe(struct device *dev)
 
 	dev->priv = priv;
 
-	cdev->dev = dev;
-	cdev->tstc = ar933x_serial_tstc;
-	cdev->putc = ar933x_serial_putc;
-	cdev->getc = ar933x_serial_getc;
-	cdev->setbrg = ar933x_serial_setbaudrate;
-	cdev->linux_console_name = "ttyATH";
-
-	priv->clk = clk_get(dev, NULL);
+	priv->clk = clk_get_for_console(dev, NULL);
 	if (IS_ERR(priv->clk)) {
 		dev_err(dev, "unable to get UART clock\n");
 		return PTR_ERR(priv->clk);
 	}
 
+	cdev->dev = dev;
+	cdev->tstc = ar933x_serial_tstc;
+	cdev->putc = ar933x_serial_putc;
+	cdev->getc = ar933x_serial_getc;
+	cdev->setbrg = priv->clk ? ar933x_serial_setbaudrate : NULL;
+	cdev->linux_console_name = "ttyATH";
+
 	uart_cs = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S)
 		| AR933X_UART_CS_TX_READY_ORIDE
 		| AR933X_UART_CS_RX_READY_ORIDE;
diff --git a/drivers/serial/serial_auart.c b/drivers/serial/serial_auart.c
index 217ac5c89183..cf362e8a7e0c 100644
--- a/drivers/serial/serial_auart.c
+++ b/drivers/serial/serial_auart.c
@@ -173,25 +173,26 @@ static int auart_serial_probe(struct device *dev)
 	struct console_device *cdev;
 
 	priv = xzalloc(sizeof *priv);
-	cdev = &priv->cdev;
-
-	cdev->tstc = auart_serial_tstc;
-	cdev->putc = auart_serial_putc;
-	cdev->getc = auart_serial_getc;
-	cdev->flush = auart_serial_flush;
-	cdev->setbrg = auart_serial_setbaudrate;
-	cdev->dev = dev;
-	cdev->linux_console_name = "ttyAPP";
 
 	dev->priv = priv;
 	iores = dev_request_mem_resource(dev, 0);
 	if (IS_ERR(iores))
 		return PTR_ERR(iores);
 	priv->base = IOMEM(iores->start);
-	priv->clk = clk_get(dev, NULL);
+	priv->clk = clk_get_for_console(dev, NULL);
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
+	cdev = &priv->cdev;
+
+	cdev->tstc = auart_serial_tstc;
+	cdev->putc = auart_serial_putc;
+	cdev->getc = auart_serial_getc;
+	cdev->flush = auart_serial_flush;
+	cdev->setbrg = priv->clk ? auart_serial_setbaudrate : NULL;
+	cdev->dev = dev;
+	cdev->linux_console_name = "ttyAPP";
+
 	auart_serial_init_port(priv);
 
 	/* Disable RTS/CTS, enable Rx, Tx, UART */
@@ -203,8 +204,11 @@ static int auart_serial_probe(struct device *dev)
 	       priv->base + HW_UARTAPP_CTRL2_SET);
 
 	console_register(cdev);
-	priv->notify.notifier_call = auart_clocksource_clock_change;
-	clock_register_client(&priv->notify);
+
+	if (priv->clk) {
+		priv->notify.notifier_call = auart_clocksource_clock_change;
+		clock_register_client(&priv->notify);
+	}
 
 	return 0;
 }
diff --git a/drivers/serial/serial_cadence.c b/drivers/serial/serial_cadence.c
index ee162e541aed..fe05d8a44d52 100644
--- a/drivers/serial/serial_cadence.c
+++ b/drivers/serial/serial_cadence.c
@@ -190,13 +190,13 @@ static int cadence_serial_probe(struct device *dev)
 	cdev = &priv->cdev;
 	dev->priv = priv;
 
-	priv->clk = clk_get(dev, NULL);
+	priv->clk = clk_get_for_console(dev, NULL);
 	if (IS_ERR(priv->clk)) {
 		ret = -ENODEV;
 		goto err_free;
 	}
 
-	if (devtype->mode & CADENCE_MODE_CLK_REF_DIV)
+	if (priv->clk && (devtype->mode & CADENCE_MODE_CLK_REF_DIV))
 		clk_set_rate(priv->clk, clk_get_rate(priv->clk) / 8);
 
 	iores = dev_request_mem_resource(dev, 0);
@@ -211,13 +211,16 @@ static int cadence_serial_probe(struct device *dev)
 	cdev->putc = cadence_serial_putc;
 	cdev->getc = cadence_serial_getc;
 	cdev->flush = cadence_serial_flush;
-	cdev->setbrg = cadence_serial_setbaudrate;
+	cdev->setbrg = priv->clk ? cadence_serial_setbaudrate : NULL;
 
 	cadence_serial_init_port(cdev);
 
 	console_register(cdev);
-	priv->notify.notifier_call = cadence_clocksource_clock_change;
-	clock_register_client(&priv->notify);
+
+	if (priv->clk) {
+		priv->notify.notifier_call = cadence_clocksource_clock_change;
+		clock_register_client(&priv->notify);
+	}
 
 	return 0;
 
diff --git a/drivers/serial/serial_clps711x.c b/drivers/serial/serial_clps711x.c
index 2a284909bfa6..35e13039be92 100644
--- a/drivers/serial/serial_clps711x.c
+++ b/drivers/serial/serial_clps711x.c
@@ -137,7 +137,7 @@ static int clps711x_probe(struct device *dev)
 
 	s = xzalloc(sizeof(struct clps711x_uart));
 
-	s->uart_clk = clk_get(dev, NULL);
+	s->uart_clk = clk_get_for_console(dev, NULL);
 	if (IS_ERR(s->uart_clk)) {
 		err = PTR_ERR(s->uart_clk);
 		goto out_err;
@@ -162,7 +162,7 @@ static int clps711x_probe(struct device *dev)
 	s->cdev.putc	= clps711x_putc;
 	s->cdev.getc	= clps711x_getc;
 	s->cdev.flush	= clps711x_flush;
-	s->cdev.setbrg	= clps711x_setbaudrate;
+	s->cdev.setbrg	= s->uart_clk ? clps711x_setbaudrate : NULL;
 	s->cdev.linux_console_name = "ttyCL";
 
 	devname = of_alias_get(dev->of_node);
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index 0f9102860591..77eea78aba64 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -92,7 +92,7 @@ static int imx_serial_init_port(struct console_device *cdev)
 	writel(val, regs + UFCR);
 
 
-	if (priv->devtype->onems)
+	if (priv->clk && priv->devtype->onems)
 		writel(imx_serial_reffreq(priv) / 1000, regs + priv->devtype->onems);
 
 	/* Enable FIFOs */
@@ -216,7 +216,7 @@ static int imx_serial_probe(struct device *dev)
 	cdev = &priv->cdev;
 	dev->priv = priv;
 
-	priv->clk = clk_get(dev, "per");
+	priv->clk = clk_get_for_console(dev, "per");
 	if (IS_ERR(priv->clk)) {
 		ret = PTR_ERR(priv->clk);
 		goto err_free;
@@ -232,7 +232,7 @@ static int imx_serial_probe(struct device *dev)
 	cdev->putc = imx_serial_putc;
 	cdev->getc = imx_serial_getc;
 	cdev->flush = imx_serial_flush;
-	cdev->setbrg = imx_serial_setbaudrate;
+	cdev->setbrg = priv->clk ? imx_serial_setbaudrate : NULL;
 	cdev->linux_console_name = "ttymxc";
 	cdev->linux_earlycon_name = "ec_imx6q";
 	cdev->phys_base = priv->regs;
@@ -259,8 +259,11 @@ static int imx_serial_probe(struct device *dev)
 	writel(val, priv->regs + UCR1);
 
 	console_register(cdev);
-	priv->notify.notifier_call = imx_clocksource_clock_change;
-	clock_register_client(&priv->notify);
+
+	if (priv->clk) {
+		priv->notify.notifier_call = imx_clocksource_clock_change;
+		clock_register_client(&priv->notify);
+	}
 
 	return 0;
 
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 828a0dd0bb42..8bbef08309f9 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -131,7 +131,7 @@ static int lpuart_serial_probe(struct device *dev)
 	}
 	lpuart->base = IOMEM(lpuart->io->start);
 
-	lpuart->clk = clk_get(dev, NULL);
+	lpuart->clk = clk_get_for_console(dev, NULL);
 	if (IS_ERR(lpuart->clk)) {
 		ret = PTR_ERR(lpuart->clk);
 		dev_err(dev, "Failed to get UART clock %d\n", ret);
@@ -149,7 +149,7 @@ static int lpuart_serial_probe(struct device *dev)
 	cdev->putc   = lpuart_serial_putc;
 	cdev->getc   = lpuart_serial_getc;
 	cdev->flush  = lpuart_serial_flush;
-	cdev->setbrg = lpuart_serial_setbaudrate;
+	cdev->setbrg = lpuart->clk ? lpuart_serial_setbaudrate : NULL;
 
 	if (dev->of_node) {
 		devname = of_alias_get(dev->of_node);
@@ -163,12 +163,15 @@ static int lpuart_serial_probe(struct device *dev)
 	cdev->linux_earlycon_name = "lpuart";
 	cdev->phys_base = lpuart->base;
 
-	lpuart_setup(lpuart->base, clk_get_rate(lpuart->clk));
+	if (lpuart->clk)
+		lpuart_setup(lpuart->base, clk_get_rate(lpuart->clk));
 
 	ret = console_register(cdev);
 	if (!ret) {
-		lpuart->notify.notifier_call = lpuart_clocksource_clock_change;
-		clock_register_client(&lpuart->notify);
+		if (lpuart->clk) {
+			lpuart->notify.notifier_call = lpuart_clocksource_clock_change;
+			clock_register_client(&lpuart->notify);
+		}
 
 		return 0;
 	}
diff --git a/drivers/serial/serial_lpuart32.c b/drivers/serial/serial_lpuart32.c
index 09d4b620beb8..6b52882bf0bd 100644
--- a/drivers/serial/serial_lpuart32.c
+++ b/drivers/serial/serial_lpuart32.c
@@ -119,7 +119,7 @@ static int lpuart32_serial_probe(struct device *dev)
 	}
 	lpuart32->base = IOMEM(lpuart32->io->start) + devtype->reg_offs;
 
-	lpuart32->clk = clk_get(dev, NULL);
+	lpuart32->clk = clk_get_for_console(dev, NULL);
 	if (IS_ERR(lpuart32->clk)) {
 		ret = PTR_ERR(lpuart32->clk);
 		dev_err(dev, "Failed to get UART clock %d\n", ret);
@@ -137,7 +137,7 @@ static int lpuart32_serial_probe(struct device *dev)
 	cdev->putc   = lpuart32_serial_putc;
 	cdev->getc   = lpuart32_serial_getc;
 	cdev->flush  = lpuart32_serial_flush;
-	cdev->setbrg = lpuart32_serial_setbaudrate;
+	cdev->setbrg = lpuart32->clk ? lpuart32_serial_setbaudrate : NULL;
 
 	if (dev->of_node) {
 		devname = of_alias_get(dev->of_node);
@@ -151,7 +151,8 @@ static int lpuart32_serial_probe(struct device *dev)
 	cdev->linux_earlycon_name = "lpuart";
 	cdev->phys_base = lpuart32->base;
 
-	lpuart32_setup(lpuart32->base, clk_get_rate(lpuart32->clk));
+	if (lpuart32->clk)
+		lpuart32_setup(lpuart32->base, clk_get_rate(lpuart32->clk));
 
 	ret = console_register(cdev);
 	if (!ret)
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 1b1692658f56..45341d1c9b4d 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -525,7 +525,7 @@ static int ns16550_probe(struct device *dev)
 		priv->plat.clock = devtype->clk_default;
 
 	if (!priv->plat.clock) {
-		priv->clk = clk_get(dev, NULL);
+		priv->clk = clk_get_for_console(dev, NULL);
 		if (IS_ERR(priv->clk)) {
 			ret = PTR_ERR(priv->clk);
 			dev_err(dev, "failed to get clk (%d)\n", ret);
@@ -537,18 +537,15 @@ static int ns16550_probe(struct device *dev)
 		priv->plat.clock = clk_get_rate(priv->clk);
 	}
 
-	if (priv->plat.clock == 0) {
-		dev_err(dev, "no valid clockrate\n");
-		ret = -EINVAL;
-		goto clk_disable;
-	}
+	if (priv->plat.clock == 0)
+		dev_warn(dev, "no valid clockrate\n");
 
 	cdev = &priv->cdev;
 	cdev->dev = dev;
 	cdev->tstc = ns16550_tstc;
 	cdev->putc = ns16550_putc;
 	cdev->getc = ns16550_getc;
-	cdev->setbrg = ns16550_setbaudrate;
+	cdev->setbrg = priv->plat.clock ? ns16550_setbaudrate : NULL;
 	cdev->flush = ns16550_flush;
 	cdev->linux_console_name = devtype->linux_console_name;
 	cdev->linux_earlycon_name = basprintf("%s,%s", devtype->linux_earlycon_name,
diff --git a/drivers/serial/serial_sifive.c b/drivers/serial/serial_sifive.c
index f056233b4efc..c1c325011ae0 100644
--- a/drivers/serial/serial_sifive.c
+++ b/drivers/serial/serial_sifive.c
@@ -121,21 +121,19 @@ static int sifive_serial_probe(struct device *dev)
 	struct sifive_serial_priv *priv;
 	struct resource *iores;
 	struct clk *clk;
-	u32 freq;
+	u32 freq = 0;
 	int ret;
 
-	clk = clk_get(dev, NULL);
-	if (!IS_ERR(clk)) {
+	clk = clk_get_for_console(dev, NULL);
+	if (!IS_ERR_OR_NULL(clk)) {
 		freq = clk_get_rate(clk);
 	} else {
 		dev_dbg(dev, "failed to get clock. Fallback to device tree.\n");
 
 		ret = of_property_read_u32(dev->of_node, "clock-frequency",
 					   &freq);
-		if (ret) {
+		if (ret)
 			dev_warn(dev, "unknown clock frequency\n");
-			return ret;
-		}
 	}
 
 	iores = dev_request_mem_resource(dev, 0);
@@ -152,7 +150,7 @@ static int sifive_serial_probe(struct device *dev)
 	priv->cdev.getc = sifive_serial_getc;
 	priv->cdev.tstc = sifive_serial_tstc;
 	priv->cdev.flush = sifive_serial_flush;
-	priv->cdev.setbrg = sifive_serial_setbrg,
+	priv->cdev.setbrg = freq ? sifive_serial_setbrg : 0,
 
 	sifive_serial_init(priv->regs);
 
diff --git a/drivers/serial/stm-serial.c b/drivers/serial/stm-serial.c
index af30bfa71d59..ccb8c91d1708 100644
--- a/drivers/serial/stm-serial.c
+++ b/drivers/serial/stm-serial.c
@@ -138,28 +138,27 @@ static int stm_serial_probe(struct device *dev)
 	struct console_device *cdev;
 
 	priv = xzalloc(sizeof *priv);
-
 	cdev = &priv->cdev;
 
-	cdev->tstc = stm_serial_tstc;
-	cdev->putc = stm_serial_putc;
-	cdev->getc = stm_serial_getc;
-	cdev->flush = stm_serial_flush;
-	cdev->setbrg = stm_serial_setbaudrate;
-	cdev->dev = dev;
-	cdev->linux_console_name = "ttyAMA";
-	cdev->linux_earlycon_name = "pl011";
-
 	dev->priv = priv;
 	iores = dev_request_mem_resource(dev, 0);
 	if (IS_ERR(iores))
 		return PTR_ERR(iores);
 	priv->base = IOMEM(iores->start);
 	cdev->phys_base = priv->base;
-	priv->clk = clk_get(dev, NULL);
+	priv->clk = clk_get_for_console(dev, NULL);
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
+	cdev->tstc = stm_serial_tstc;
+	cdev->putc = stm_serial_putc;
+	cdev->getc = stm_serial_getc;
+	cdev->flush = stm_serial_flush;
+	cdev->setbrg = priv->clk ? stm_serial_setbaudrate : NULL;
+	cdev->dev = dev;
+	cdev->linux_console_name = "ttyAMA";
+	cdev->linux_earlycon_name = "pl011";
+
 	stm_serial_init_port(priv);
 	stm_serial_setbaudrate(cdev, CONFIG_BAUDRATE);
 
@@ -167,8 +166,11 @@ static int stm_serial_probe(struct device *dev)
 	writel(TXE | RXE | UARTEN, priv->base + UARTDBGCR);
 
 	console_register(cdev);
-	priv->notify.notifier_call = stm_clocksource_clock_change;
-	clock_register_client(&priv->notify);
+
+	if (priv->clk) {
+		priv->notify.notifier_call = stm_clocksource_clock_change;
+		clock_register_client(&priv->notify);
+	}
 
 	return 0;
 }
-- 
2.39.2




More information about the barebox mailing list