Skip to content

Commit a5819b5

Browse files
Rajendra Nayakandersson
authored andcommitted
tty: serial: qcom_geni_serial: Use OPP API to set clk/perf state
geni serial needs to express a perforamnce state requirement on CX powerdomain depending on the frequency of the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state. Signed-off-by: Rajendra Nayak <[email protected]> Reviewed-by: Matthias Kaehlcke <[email protected]> Acked-by: Greg Kroah-Hartman <[email protected]> Cc: Akash Asthana <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent cff8064 commit a5819b5

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

drivers/tty/serial/qcom_geni_serial.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/module.h>
1010
#include <linux/of.h>
1111
#include <linux/of_device.h>
12+
#include <linux/pm_opp.h>
1213
#include <linux/platform_device.h>
1314
#include <linux/pm_runtime.h>
1415
#include <linux/pm_wakeirq.h>
@@ -963,7 +964,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
963964
goto out_restart_rx;
964965

965966
uport->uartclk = clk_rate;
966-
clk_set_rate(port->se.clk, clk_rate);
967+
dev_pm_opp_set_rate(uport->dev, clk_rate);
967968
ser_clk_cfg = SER_CLK_EN;
968969
ser_clk_cfg |= clk_div << CLK_DIV_SHFT;
969970

@@ -1383,21 +1384,33 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
13831384
if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap"))
13841385
port->cts_rts_swap = true;
13851386

1387+
port->se.opp_table = dev_pm_opp_set_clkname(&pdev->dev, "se");
1388+
if (IS_ERR(port->se.opp_table))
1389+
return PTR_ERR(port->se.opp_table);
1390+
/* OPP table is optional */
1391+
ret = dev_pm_opp_of_add_table(&pdev->dev);
1392+
if (!ret) {
1393+
port->se.has_opp_table = true;
1394+
} else if (ret != -ENODEV) {
1395+
dev_err(&pdev->dev, "invalid OPP table in device tree\n");
1396+
return ret;
1397+
}
1398+
13861399
uport->private_data = drv;
13871400
platform_set_drvdata(pdev, port);
13881401
port->handle_rx = console ? handle_rx_console : handle_rx_uart;
13891402

13901403
ret = uart_add_one_port(drv, uport);
13911404
if (ret)
1392-
return ret;
1405+
goto err;
13931406

13941407
irq_set_status_flags(uport->irq, IRQ_NOAUTOEN);
13951408
ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr,
13961409
IRQF_TRIGGER_HIGH, port->name, uport);
13971410
if (ret) {
13981411
dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret);
13991412
uart_remove_one_port(drv, uport);
1400-
return ret;
1413+
goto err;
14011414
}
14021415

14031416
/*
@@ -1414,18 +1427,26 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
14141427
if (ret) {
14151428
device_init_wakeup(&pdev->dev, false);
14161429
uart_remove_one_port(drv, uport);
1417-
return ret;
1430+
goto err;
14181431
}
14191432
}
14201433

14211434
return 0;
1435+
err:
1436+
if (port->se.has_opp_table)
1437+
dev_pm_opp_of_remove_table(&pdev->dev);
1438+
dev_pm_opp_put_clkname(port->se.opp_table);
1439+
return ret;
14221440
}
14231441

14241442
static int qcom_geni_serial_remove(struct platform_device *pdev)
14251443
{
14261444
struct qcom_geni_serial_port *port = platform_get_drvdata(pdev);
14271445
struct uart_driver *drv = port->uport.private_data;
14281446

1447+
if (port->se.has_opp_table)
1448+
dev_pm_opp_of_remove_table(&pdev->dev);
1449+
dev_pm_opp_put_clkname(port->se.opp_table);
14291450
dev_pm_clear_wake_irq(&pdev->dev);
14301451
device_init_wakeup(&pdev->dev, false);
14311452
uart_remove_one_port(drv, &port->uport);

include/linux/qcom-geni-se.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ struct geni_icc_path {
4747
* @num_clk_levels: Number of valid clock levels in clk_perf_tbl
4848
* @clk_perf_tbl: Table of clock frequency input to serial engine clock
4949
* @icc_paths: Array of ICC paths for SE
50+
* @opp_table: Pointer to the OPP table
51+
* @has_opp_table: Specifies if the SE has an OPP table
5052
*/
5153
struct geni_se {
5254
void __iomem *base;
@@ -56,6 +58,8 @@ struct geni_se {
5658
unsigned int num_clk_levels;
5759
unsigned long *clk_perf_tbl;
5860
struct geni_icc_path icc_paths[3];
61+
struct opp_table *opp_table;
62+
bool has_opp_table;
5963
};
6064

6165
/* Common SE registers */

0 commit comments

Comments
 (0)