1414#include <linux/irq.h>
1515#include <linux/module.h>
1616#include <linux/of.h>
17+ #include <linux/pm_domain.h>
1718#include <linux/pm_opp.h>
1819#include <linux/platform_device.h>
1920#include <linux/pm_runtime.h>
101102#define DMA_RX_BUF_SIZE 2048
102103
103104static DEFINE_IDA (port_ida );
105+ #define DOMAIN_IDX_POWER 0
106+ #define DOMAIN_IDX_PERF 1
104107
105108struct qcom_geni_device_data {
106109 bool console ;
107110 enum geni_se_xfer_mode mode ;
111+ struct dev_pm_domain_attach_data pd_data ;
112+ int (* resources_init )(struct uart_port * uport );
113+ int (* set_rate )(struct uart_port * uport , unsigned int baud );
114+ int (* power_state )(struct uart_port * uport , bool state );
108115};
109116
110117struct qcom_geni_private_data {
@@ -142,6 +149,7 @@ struct qcom_geni_serial_port {
142149
143150 struct qcom_geni_private_data private_data ;
144151 const struct qcom_geni_device_data * dev_data ;
152+ struct dev_pm_domain_list * pd_list ;
145153};
146154
147155static const struct uart_ops qcom_geni_console_pops ;
@@ -1299,6 +1307,42 @@ static int geni_serial_set_rate(struct uart_port *uport, unsigned int baud)
12991307 return 0 ;
13001308}
13011309
1310+ static int geni_serial_set_level (struct uart_port * uport , unsigned int baud )
1311+ {
1312+ struct qcom_geni_serial_port * port = to_dev_port (uport );
1313+ struct device * perf_dev = port -> pd_list -> pd_devs [DOMAIN_IDX_PERF ];
1314+
1315+ /*
1316+ * The performance protocol sets UART communication
1317+ * speeds by selecting different performance levels
1318+ * through the OPP framework.
1319+ *
1320+ * Supported perf levels for baudrates in firmware are below
1321+ * +---------------------+--------------------+
1322+ * | Perf level value | Baudrate values |
1323+ * +---------------------+--------------------+
1324+ * | 300 | 300 |
1325+ * | 1200 | 1200 |
1326+ * | 2400 | 2400 |
1327+ * | 4800 | 4800 |
1328+ * | 9600 | 9600 |
1329+ * | 19200 | 19200 |
1330+ * | 38400 | 38400 |
1331+ * | 57600 | 57600 |
1332+ * | 115200 | 115200 |
1333+ * | 230400 | 230400 |
1334+ * | 460800 | 460800 |
1335+ * | 921600 | 921600 |
1336+ * | 2000000 | 2000000 |
1337+ * | 3000000 | 3000000 |
1338+ * | 3200000 | 3200000 |
1339+ * | 4000000 | 4000000 |
1340+ * +---------------------+--------------------+
1341+ */
1342+
1343+ return dev_pm_opp_set_level (perf_dev , baud );
1344+ }
1345+
13021346static void qcom_geni_serial_set_termios (struct uart_port * uport ,
13031347 struct ktermios * termios ,
13041348 const struct ktermios * old )
@@ -1317,7 +1361,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
13171361 /* baud rate */
13181362 baud = uart_get_baud_rate (uport , termios , old , 300 , 8000000 );
13191363
1320- ret = geni_serial_set_rate (uport , baud );
1364+ ret = port -> dev_data -> set_rate (uport , baud );
13211365 if (ret )
13221366 return ;
13231367
@@ -1604,8 +1648,27 @@ static int geni_serial_resources_off(struct uart_port *uport)
16041648 return 0 ;
16051649}
16061650
1607- static int geni_serial_resource_init (struct qcom_geni_serial_port * port )
1651+ static int geni_serial_resource_state (struct uart_port * uport , bool power_on )
1652+ {
1653+ return power_on ? geni_serial_resources_on (uport ) : geni_serial_resources_off (uport );
1654+ }
1655+
1656+ static int geni_serial_pwr_init (struct uart_port * uport )
1657+ {
1658+ struct qcom_geni_serial_port * port = to_dev_port (uport );
1659+ int ret ;
1660+
1661+ ret = dev_pm_domain_attach_list (port -> se .dev ,
1662+ & port -> dev_data -> pd_data , & port -> pd_list );
1663+ if (ret <= 0 )
1664+ return - EINVAL ;
1665+
1666+ return 0 ;
1667+ }
1668+
1669+ static int geni_serial_resource_init (struct uart_port * uport )
16081670{
1671+ struct qcom_geni_serial_port * port = to_dev_port (uport );
16091672 int ret ;
16101673
16111674 port -> se .clk = devm_clk_get (port -> se .dev , "se" );
@@ -1756,13 +1819,16 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
17561819 port -> se .dev = & pdev -> dev ;
17571820 port -> se .wrapper = dev_get_drvdata (pdev -> dev .parent );
17581821
1759- ret = geni_serial_resource_init ( port );
1822+ ret = port -> dev_data -> resources_init ( uport );
17601823 if (ret )
17611824 return ret ;
17621825
17631826 res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
1764- if (!res )
1765- return - EINVAL ;
1827+ if (!res ) {
1828+ ret = - EINVAL ;
1829+ goto error ;
1830+ }
1831+
17661832 uport -> mapbase = res -> start ;
17671833
17681834 uport -> rs485_config = qcom_geni_rs485_config ;
@@ -1774,19 +1840,26 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
17741840 if (!data -> console ) {
17751841 port -> rx_buf = devm_kzalloc (uport -> dev ,
17761842 DMA_RX_BUF_SIZE , GFP_KERNEL );
1777- if (!port -> rx_buf )
1778- return - ENOMEM ;
1843+ if (!port -> rx_buf ) {
1844+ ret = - ENOMEM ;
1845+ goto error ;
1846+ }
17791847 }
17801848
17811849 port -> name = devm_kasprintf (uport -> dev , GFP_KERNEL ,
17821850 "qcom_geni_serial_%s%d" ,
17831851 uart_console (uport ) ? "console" : "uart" , uport -> line );
1784- if (!port -> name )
1785- return - ENOMEM ;
1852+ if (!port -> name ) {
1853+ ret = - ENOMEM ;
1854+ goto error ;
1855+ }
17861856
17871857 irq = platform_get_irq (pdev , 0 );
1788- if (irq < 0 )
1789- return irq ;
1858+ if (irq < 0 ) {
1859+ ret = irq ;
1860+ goto error ;
1861+ }
1862+
17901863 uport -> irq = irq ;
17911864 uport -> has_sysrq = IS_ENABLED (CONFIG_SERIAL_QCOM_GENI_CONSOLE );
17921865
@@ -1808,18 +1881,18 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
18081881 IRQF_TRIGGER_HIGH , port -> name , uport );
18091882 if (ret ) {
18101883 dev_err (uport -> dev , "Failed to get IRQ ret %d\n" , ret );
1811- return ret ;
1884+ goto error ;
18121885 }
18131886
18141887 ret = uart_get_rs485_mode (uport );
18151888 if (ret )
1816- return ret ;
1889+ goto error ;
18171890
18181891 devm_pm_runtime_enable (port -> se .dev );
18191892
18201893 ret = uart_add_one_port (drv , uport );
18211894 if (ret )
1822- return ret ;
1895+ goto error ;
18231896
18241897 if (port -> wakeup_irq > 0 ) {
18251898 device_init_wakeup (& pdev -> dev , true);
@@ -1829,11 +1902,15 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
18291902 device_init_wakeup (& pdev -> dev , false);
18301903 ida_free (& port_ida , uport -> line );
18311904 uart_remove_one_port (drv , uport );
1832- return ret ;
1905+ goto error ;
18331906 }
18341907 }
18351908
18361909 return 0 ;
1910+
1911+ error :
1912+ dev_pm_domain_detach_list (port -> pd_list );
1913+ return ret ;
18371914}
18381915
18391916static void qcom_geni_serial_remove (struct platform_device * pdev )
@@ -1846,22 +1923,31 @@ static void qcom_geni_serial_remove(struct platform_device *pdev)
18461923 device_init_wakeup (& pdev -> dev , false);
18471924 ida_free (& port_ida , uport -> line );
18481925 uart_remove_one_port (drv , & port -> uport );
1926+ dev_pm_domain_detach_list (port -> pd_list );
18491927}
18501928
18511929static int __maybe_unused qcom_geni_serial_runtime_suspend (struct device * dev )
18521930{
18531931 struct qcom_geni_serial_port * port = dev_get_drvdata (dev );
18541932 struct uart_port * uport = & port -> uport ;
1933+ int ret = 0 ;
18551934
1856- return geni_serial_resources_off (uport );
1935+ if (port -> dev_data -> power_state )
1936+ ret = port -> dev_data -> power_state (uport , false);
1937+
1938+ return ret ;
18571939}
18581940
18591941static int __maybe_unused qcom_geni_serial_runtime_resume (struct device * dev )
18601942{
18611943 struct qcom_geni_serial_port * port = dev_get_drvdata (dev );
18621944 struct uart_port * uport = & port -> uport ;
1945+ int ret = 0 ;
1946+
1947+ if (port -> dev_data -> power_state )
1948+ ret = port -> dev_data -> power_state (uport , true);
18631949
1864- return geni_serial_resources_on ( uport ) ;
1950+ return ret ;
18651951}
18661952
18671953static int qcom_geni_serial_suspend (struct device * dev )
@@ -1899,11 +1985,41 @@ static int qcom_geni_serial_resume(struct device *dev)
18991985static const struct qcom_geni_device_data qcom_geni_console_data = {
19001986 .console = true,
19011987 .mode = GENI_SE_FIFO ,
1988+ .resources_init = geni_serial_resource_init ,
1989+ .set_rate = geni_serial_set_rate ,
1990+ .power_state = geni_serial_resource_state ,
19021991};
19031992
19041993static const struct qcom_geni_device_data qcom_geni_uart_data = {
19051994 .console = false,
19061995 .mode = GENI_SE_DMA ,
1996+ .resources_init = geni_serial_resource_init ,
1997+ .set_rate = geni_serial_set_rate ,
1998+ .power_state = geni_serial_resource_state ,
1999+ };
2000+
2001+ static const struct qcom_geni_device_data sa8255p_qcom_geni_console_data = {
2002+ .console = true,
2003+ .mode = GENI_SE_FIFO ,
2004+ .pd_data = {
2005+ .pd_flags = PD_FLAG_DEV_LINK_ON ,
2006+ .pd_names = (const char * []) { "power" , "perf" },
2007+ .num_pd_names = 2 ,
2008+ },
2009+ .resources_init = geni_serial_pwr_init ,
2010+ .set_rate = geni_serial_set_level ,
2011+ };
2012+
2013+ static const struct qcom_geni_device_data sa8255p_qcom_geni_uart_data = {
2014+ .console = false,
2015+ .mode = GENI_SE_DMA ,
2016+ .pd_data = {
2017+ .pd_flags = PD_FLAG_DEV_LINK_ON ,
2018+ .pd_names = (const char * []) { "power" , "perf" },
2019+ .num_pd_names = 2 ,
2020+ },
2021+ .resources_init = geni_serial_pwr_init ,
2022+ .set_rate = geni_serial_set_level ,
19072023};
19082024
19092025static const struct dev_pm_ops qcom_geni_serial_pm_ops = {
@@ -1917,10 +2033,18 @@ static const struct of_device_id qcom_geni_serial_match_table[] = {
19172033 .compatible = "qcom,geni-debug-uart" ,
19182034 .data = & qcom_geni_console_data ,
19192035 },
2036+ {
2037+ .compatible = "qcom,sa8255p-geni-debug-uart" ,
2038+ .data = & sa8255p_qcom_geni_console_data ,
2039+ },
19202040 {
19212041 .compatible = "qcom,geni-uart" ,
19222042 .data = & qcom_geni_uart_data ,
19232043 },
2044+ {
2045+ .compatible = "qcom,sa8255p-geni-uart" ,
2046+ .data = & sa8255p_qcom_geni_uart_data ,
2047+ },
19242048 {}
19252049};
19262050MODULE_DEVICE_TABLE (of , qcom_geni_serial_match_table );
0 commit comments