1111#include <linux/irq.h>
1212#include <linux/module.h>
1313#include <linux/of.h>
14+ #include <linux/pm_domain.h>
1415#include <linux/pm_opp.h>
1516#include <linux/platform_device.h>
1617#include <linux/pm_runtime.h>
99100#define DMA_RX_BUF_SIZE 2048
100101
101102static DEFINE_IDA (port_ida );
103+ #define DOMAIN_IDX_POWER 0
104+ #define DOMAIN_IDX_PERF 1
102105
103106struct qcom_geni_device_data {
104107 bool console ;
105108 enum geni_se_xfer_mode mode ;
109+ struct dev_pm_domain_attach_data pd_data ;
110+ int (* resources_init )(struct uart_port * uport );
111+ int (* set_rate )(struct uart_port * uport , unsigned int baud );
112+ int (* power_state )(struct uart_port * uport , bool state );
106113};
107114
108115struct qcom_geni_private_data {
@@ -140,6 +147,7 @@ struct qcom_geni_serial_port {
140147
141148 struct qcom_geni_private_data private_data ;
142149 const struct qcom_geni_device_data * dev_data ;
150+ struct dev_pm_domain_list * pd_list ;
143151};
144152
145153static const struct uart_ops qcom_geni_console_pops ;
@@ -1362,6 +1370,42 @@ static int geni_serial_set_rate(struct uart_port *uport, unsigned int baud)
13621370 return 0 ;
13631371}
13641372
1373+ static int geni_serial_set_level (struct uart_port * uport , unsigned int baud )
1374+ {
1375+ struct qcom_geni_serial_port * port = to_dev_port (uport );
1376+ struct device * perf_dev = port -> pd_list -> pd_devs [DOMAIN_IDX_PERF ];
1377+
1378+ /*
1379+ * The performance protocol sets UART communication
1380+ * speeds by selecting different performance levels
1381+ * through the OPP framework.
1382+ *
1383+ * Supported perf levels for baudrates in firmware are below
1384+ * +---------------------+--------------------+
1385+ * | Perf level value | Baudrate values |
1386+ * +---------------------+--------------------+
1387+ * | 300 | 300 |
1388+ * | 1200 | 1200 |
1389+ * | 2400 | 2400 |
1390+ * | 4800 | 4800 |
1391+ * | 9600 | 9600 |
1392+ * | 19200 | 19200 |
1393+ * | 38400 | 38400 |
1394+ * | 57600 | 57600 |
1395+ * | 115200 | 115200 |
1396+ * | 230400 | 230400 |
1397+ * | 460800 | 460800 |
1398+ * | 921600 | 921600 |
1399+ * | 2000000 | 2000000 |
1400+ * | 3000000 | 3000000 |
1401+ * | 3200000 | 3200000 |
1402+ * | 4000000 | 4000000 |
1403+ * +---------------------+--------------------+
1404+ */
1405+
1406+ return dev_pm_opp_set_level (perf_dev , baud );
1407+ }
1408+
13651409static void qcom_geni_serial_set_termios (struct uart_port * uport ,
13661410 struct ktermios * termios ,
13671411 const struct ktermios * old )
@@ -1380,7 +1424,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
13801424 /* baud rate */
13811425 baud = uart_get_baud_rate (uport , termios , old , 300 , 8000000 );
13821426
1383- ret = geni_serial_set_rate (uport , baud );
1427+ ret = port -> dev_data -> set_rate (uport , baud );
13841428 if (ret )
13851429 return ;
13861430
@@ -1667,8 +1711,27 @@ static int geni_serial_resources_off(struct uart_port *uport)
16671711 return 0 ;
16681712}
16691713
1670- static int geni_serial_resource_init (struct qcom_geni_serial_port * port )
1714+ static int geni_serial_resource_state (struct uart_port * uport , bool power_on )
1715+ {
1716+ return power_on ? geni_serial_resources_on (uport ) : geni_serial_resources_off (uport );
1717+ }
1718+
1719+ static int geni_serial_pwr_init (struct uart_port * uport )
1720+ {
1721+ struct qcom_geni_serial_port * port = to_dev_port (uport );
1722+ int ret ;
1723+
1724+ ret = dev_pm_domain_attach_list (port -> se .dev ,
1725+ & port -> dev_data -> pd_data , & port -> pd_list );
1726+ if (ret <= 0 )
1727+ return - EINVAL ;
1728+
1729+ return 0 ;
1730+ }
1731+
1732+ static int geni_serial_resource_init (struct uart_port * uport )
16711733{
1734+ struct qcom_geni_serial_port * port = to_dev_port (uport );
16721735 int ret ;
16731736
16741737 port -> se .clk = devm_clk_get (port -> se .dev , "se" );
@@ -1819,13 +1882,16 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
18191882 port -> se .dev = & pdev -> dev ;
18201883 port -> se .wrapper = dev_get_drvdata (pdev -> dev .parent );
18211884
1822- ret = geni_serial_resource_init ( port );
1885+ ret = port -> dev_data -> resources_init ( uport );
18231886 if (ret )
18241887 return ret ;
18251888
18261889 res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
1827- if (!res )
1828- return - EINVAL ;
1890+ if (!res ) {
1891+ ret = - EINVAL ;
1892+ goto error ;
1893+ }
1894+
18291895 uport -> mapbase = res -> start ;
18301896
18311897 uport -> rs485_config = qcom_geni_rs485_config ;
@@ -1837,19 +1903,26 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
18371903 if (!data -> console ) {
18381904 port -> rx_buf = devm_kzalloc (uport -> dev ,
18391905 DMA_RX_BUF_SIZE , GFP_KERNEL );
1840- if (!port -> rx_buf )
1841- return - ENOMEM ;
1906+ if (!port -> rx_buf ) {
1907+ ret = - ENOMEM ;
1908+ goto error ;
1909+ }
18421910 }
18431911
18441912 port -> name = devm_kasprintf (uport -> dev , GFP_KERNEL ,
18451913 "qcom_geni_serial_%s%d" ,
18461914 uart_console (uport ) ? "console" : "uart" , uport -> line );
1847- if (!port -> name )
1848- return - ENOMEM ;
1915+ if (!port -> name ) {
1916+ ret = - ENOMEM ;
1917+ goto error ;
1918+ }
18491919
18501920 irq = platform_get_irq (pdev , 0 );
1851- if (irq < 0 )
1852- return irq ;
1921+ if (irq < 0 ) {
1922+ ret = irq ;
1923+ goto error ;
1924+ }
1925+
18531926 uport -> irq = irq ;
18541927 uport -> has_sysrq = IS_ENABLED (CONFIG_SERIAL_QCOM_GENI_CONSOLE );
18551928
@@ -1871,7 +1944,7 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
18711944 IRQF_TRIGGER_HIGH , port -> name , uport );
18721945 if (ret ) {
18731946 dev_err (uport -> dev , "Failed to get IRQ ret %d\n" , ret );
1874- return ret ;
1947+ goto error ;
18751948 }
18761949
18771950 ret = uart_get_rs485_mode (uport );
@@ -1882,7 +1955,7 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
18821955
18831956 ret = uart_add_one_port (drv , uport );
18841957 if (ret )
1885- return ret ;
1958+ goto error ;
18861959
18871960 if (port -> wakeup_irq > 0 ) {
18881961 device_init_wakeup (& pdev -> dev , true);
@@ -1892,11 +1965,15 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
18921965 device_init_wakeup (& pdev -> dev , false);
18931966 ida_free (& port_ida , uport -> line );
18941967 uart_remove_one_port (drv , uport );
1895- return ret ;
1968+ goto error ;
18961969 }
18971970 }
18981971
18991972 return 0 ;
1973+
1974+ error :
1975+ dev_pm_domain_detach_list (port -> pd_list );
1976+ return ret ;
19001977}
19011978
19021979static void qcom_geni_serial_remove (struct platform_device * pdev )
@@ -1909,22 +1986,31 @@ static void qcom_geni_serial_remove(struct platform_device *pdev)
19091986 device_init_wakeup (& pdev -> dev , false);
19101987 ida_free (& port_ida , uport -> line );
19111988 uart_remove_one_port (drv , & port -> uport );
1989+ dev_pm_domain_detach_list (port -> pd_list );
19121990}
19131991
19141992static int __maybe_unused qcom_geni_serial_runtime_suspend (struct device * dev )
19151993{
19161994 struct qcom_geni_serial_port * port = dev_get_drvdata (dev );
19171995 struct uart_port * uport = & port -> uport ;
1996+ int ret = 0 ;
1997+
1998+ if (port -> dev_data -> power_state )
1999+ ret = port -> dev_data -> power_state (uport , false);
19182000
1919- return geni_serial_resources_off ( uport ) ;
2001+ return ret ;
19202002}
19212003
19222004static int __maybe_unused qcom_geni_serial_runtime_resume (struct device * dev )
19232005{
19242006 struct qcom_geni_serial_port * port = dev_get_drvdata (dev );
19252007 struct uart_port * uport = & port -> uport ;
2008+ int ret = 0 ;
19262009
1927- return geni_serial_resources_on (uport );
2010+ if (port -> dev_data -> power_state )
2011+ ret = port -> dev_data -> power_state (uport , true);
2012+
2013+ return ret ;
19282014}
19292015
19302016static int qcom_geni_serial_suspend (struct device * dev )
@@ -1962,11 +2048,41 @@ static int qcom_geni_serial_resume(struct device *dev)
19622048static const struct qcom_geni_device_data qcom_geni_console_data = {
19632049 .console = true,
19642050 .mode = GENI_SE_FIFO ,
2051+ .resources_init = geni_serial_resource_init ,
2052+ .set_rate = geni_serial_set_rate ,
2053+ .power_state = geni_serial_resource_state ,
19652054};
19662055
19672056static const struct qcom_geni_device_data qcom_geni_uart_data = {
19682057 .console = false,
19692058 .mode = GENI_SE_DMA ,
2059+ .resources_init = geni_serial_resource_init ,
2060+ .set_rate = geni_serial_set_rate ,
2061+ .power_state = geni_serial_resource_state ,
2062+ };
2063+
2064+ static const struct qcom_geni_device_data sa8255p_qcom_geni_console_data = {
2065+ .console = true,
2066+ .mode = GENI_SE_FIFO ,
2067+ .pd_data = {
2068+ .pd_flags = PD_FLAG_DEV_LINK_ON ,
2069+ .pd_names = (const char * []) { "power" , "perf" },
2070+ .num_pd_names = 2 ,
2071+ },
2072+ .resources_init = geni_serial_pwr_init ,
2073+ .set_rate = geni_serial_set_level ,
2074+ };
2075+
2076+ static const struct qcom_geni_device_data sa8255p_qcom_geni_uart_data = {
2077+ .console = false,
2078+ .mode = GENI_SE_DMA ,
2079+ .pd_data = {
2080+ .pd_flags = PD_FLAG_DEV_LINK_ON ,
2081+ .pd_names = (const char * []) { "power" , "perf" },
2082+ .num_pd_names = 2 ,
2083+ },
2084+ .resources_init = geni_serial_pwr_init ,
2085+ .set_rate = geni_serial_set_level ,
19702086};
19712087
19722088static const struct dev_pm_ops qcom_geni_serial_pm_ops = {
@@ -1980,10 +2096,18 @@ static const struct of_device_id qcom_geni_serial_match_table[] = {
19802096 .compatible = "qcom,geni-debug-uart" ,
19812097 .data = & qcom_geni_console_data ,
19822098 },
2099+ {
2100+ .compatible = "qcom,sa8255p-geni-debug-uart" ,
2101+ .data = & sa8255p_qcom_geni_console_data ,
2102+ },
19832103 {
19842104 .compatible = "qcom,geni-uart" ,
19852105 .data = & qcom_geni_uart_data ,
19862106 },
2107+ {
2108+ .compatible = "qcom,sa8255p-geni-uart" ,
2109+ .data = & sa8255p_qcom_geni_uart_data ,
2110+ },
19872111 {}
19882112};
19892113MODULE_DEVICE_TABLE (of , qcom_geni_serial_match_table );
0 commit comments