Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

serial: msm: Use OPP table for DVFS support

Parse the OPP table from the device tree and use dev_pm_opp_set_rate()
instead of clk_set_rate() to allow making performance state votes
specified in the OPP table (e.g. for power domains and interconnects).

Without an OPP table in the device tree this will behave just as before
this patch.

Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
Link: https://lore.kernel.org/r/20231128-serial-msm-dvfs-v1-2-4f290d20a4be@kernkonzept.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Stephan Gerhold and committed by
Greg Kroah-Hartman
173ebded 692079bd

+17 -2
+17 -2
drivers/tty/serial/msm_serial.c
··· 24 24 #include <linux/slab.h> 25 25 #include <linux/clk.h> 26 26 #include <linux/platform_device.h> 27 + #include <linux/pm_opp.h> 27 28 #include <linux/delay.h> 28 29 #include <linux/of.h> 29 30 #include <linux/of_device.h> ··· 1132 1131 uart_port_unlock_irqrestore(port, flags); 1133 1132 1134 1133 entry = msm_find_best_baud(port, baud, &rate); 1135 - clk_set_rate(msm_port->clk, rate); 1134 + dev_pm_opp_set_rate(port->dev, rate); 1136 1135 baud = rate / 16 / entry->divisor; 1137 1136 1138 1137 uart_port_lock_irqsave(port, &flags); ··· 1187 1186 { 1188 1187 struct msm_port *msm_port = to_msm_port(port); 1189 1188 1189 + dev_pm_opp_set_rate(port->dev, port->uartclk); 1190 1190 clk_prepare_enable(msm_port->clk); 1191 1191 clk_prepare_enable(msm_port->pclk); 1192 1192 msm_serial_set_mnd_regs(port); ··· 1241 1239 1242 1240 clk_disable_unprepare(msm_port->pclk); 1243 1241 clk_disable_unprepare(msm_port->clk); 1242 + dev_pm_opp_set_rate(port->dev, 0); 1244 1243 1245 1244 return ret; 1246 1245 } ··· 1257 1254 msm_release_dma(msm_port); 1258 1255 1259 1256 clk_disable_unprepare(msm_port->clk); 1257 + dev_pm_opp_set_rate(port->dev, 0); 1260 1258 1261 1259 free_irq(port->irq, port); 1262 1260 } ··· 1423 1419 1424 1420 switch (state) { 1425 1421 case 0: 1422 + dev_pm_opp_set_rate(port->dev, port->uartclk); 1426 1423 clk_prepare_enable(msm_port->clk); 1427 1424 clk_prepare_enable(msm_port->pclk); 1428 1425 break; 1429 1426 case 3: 1430 1427 clk_disable_unprepare(msm_port->clk); 1428 + dev_pm_opp_set_rate(port->dev, 0); 1431 1429 clk_disable_unprepare(msm_port->pclk); 1432 1430 break; 1433 1431 default: ··· 1795 1789 struct resource *resource; 1796 1790 struct uart_port *port; 1797 1791 const struct of_device_id *id; 1798 - int irq, line; 1792 + int irq, line, ret; 1799 1793 1800 1794 if (pdev->dev.of_node) 1801 1795 line = of_alias_get_id(pdev->dev.of_node, "serial"); ··· 1829 1823 if (IS_ERR(msm_port->pclk)) 1830 1824 return PTR_ERR(msm_port->pclk); 1831 1825 } 1826 + 1827 + ret = devm_pm_opp_set_clkname(&pdev->dev, "core"); 1828 + if (ret) 1829 + return ret; 1830 + 1831 + /* OPP table is optional */ 1832 + ret = devm_pm_opp_of_add_table(&pdev->dev); 1833 + if (ret && ret != -ENODEV) 1834 + return dev_err_probe(&pdev->dev, ret, "invalid OPP table\n"); 1832 1835 1833 1836 port->uartclk = clk_get_rate(msm_port->clk); 1834 1837 dev_info(&pdev->dev, "uartclk = %d\n", port->uartclk);