11
11
#include <linux/irq.h>
12
12
#include <linux/module.h>
13
13
#include <linux/of.h>
14
+ #include <linux/pm_domain.h>
14
15
#include <linux/pm_opp.h>
15
16
#include <linux/platform_device.h>
16
17
#include <linux/pm_runtime.h>
99
100
#define DMA_RX_BUF_SIZE 2048
100
101
101
102
static DEFINE_IDA (port_ida );
103
+ #define DOMAIN_IDX_POWER 0
104
+ #define DOMAIN_IDX_PERF 1
102
105
103
106
struct qcom_geni_device_data {
104
107
bool console ;
105
108
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 );
106
113
};
107
114
108
115
struct qcom_geni_private_data {
@@ -140,6 +147,7 @@ struct qcom_geni_serial_port {
140
147
141
148
struct qcom_geni_private_data private_data ;
142
149
const struct qcom_geni_device_data * dev_data ;
150
+ struct dev_pm_domain_list * pd_list ;
143
151
};
144
152
145
153
static 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)
1362
1370
return 0 ;
1363
1371
}
1364
1372
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
+
1365
1409
static void qcom_geni_serial_set_termios (struct uart_port * uport ,
1366
1410
struct ktermios * termios ,
1367
1411
const struct ktermios * old )
@@ -1380,7 +1424,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
1380
1424
/* baud rate */
1381
1425
baud = uart_get_baud_rate (uport , termios , old , 300 , 8000000 );
1382
1426
1383
- ret = geni_serial_set_rate (uport , baud );
1427
+ ret = port -> dev_data -> set_rate (uport , baud );
1384
1428
if (ret )
1385
1429
return ;
1386
1430
@@ -1667,8 +1711,27 @@ static int geni_serial_resources_off(struct uart_port *uport)
1667
1711
return 0 ;
1668
1712
}
1669
1713
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 )
1671
1733
{
1734
+ struct qcom_geni_serial_port * port = to_dev_port (uport );
1672
1735
int ret ;
1673
1736
1674
1737
port -> se .clk = devm_clk_get (port -> se .dev , "se" );
@@ -1819,13 +1882,16 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
1819
1882
port -> se .dev = & pdev -> dev ;
1820
1883
port -> se .wrapper = dev_get_drvdata (pdev -> dev .parent );
1821
1884
1822
- ret = geni_serial_resource_init ( port );
1885
+ ret = port -> dev_data -> resources_init ( uport );
1823
1886
if (ret )
1824
1887
return ret ;
1825
1888
1826
1889
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
+
1829
1895
uport -> mapbase = res -> start ;
1830
1896
1831
1897
uport -> rs485_config = qcom_geni_rs485_config ;
@@ -1837,19 +1903,26 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
1837
1903
if (!data -> console ) {
1838
1904
port -> rx_buf = devm_kzalloc (uport -> dev ,
1839
1905
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
+ }
1842
1910
}
1843
1911
1844
1912
port -> name = devm_kasprintf (uport -> dev , GFP_KERNEL ,
1845
1913
"qcom_geni_serial_%s%d" ,
1846
1914
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
+ }
1849
1919
1850
1920
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
+
1853
1926
uport -> irq = irq ;
1854
1927
uport -> has_sysrq = IS_ENABLED (CONFIG_SERIAL_QCOM_GENI_CONSOLE );
1855
1928
@@ -1871,7 +1944,7 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
1871
1944
IRQF_TRIGGER_HIGH , port -> name , uport );
1872
1945
if (ret ) {
1873
1946
dev_err (uport -> dev , "Failed to get IRQ ret %d\n" , ret );
1874
- return ret ;
1947
+ goto error ;
1875
1948
}
1876
1949
1877
1950
ret = uart_get_rs485_mode (uport );
@@ -1882,7 +1955,7 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
1882
1955
1883
1956
ret = uart_add_one_port (drv , uport );
1884
1957
if (ret )
1885
- return ret ;
1958
+ goto error ;
1886
1959
1887
1960
if (port -> wakeup_irq > 0 ) {
1888
1961
device_init_wakeup (& pdev -> dev , true);
@@ -1892,11 +1965,15 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
1892
1965
device_init_wakeup (& pdev -> dev , false);
1893
1966
ida_free (& port_ida , uport -> line );
1894
1967
uart_remove_one_port (drv , uport );
1895
- return ret ;
1968
+ goto error ;
1896
1969
}
1897
1970
}
1898
1971
1899
1972
return 0 ;
1973
+
1974
+ error :
1975
+ dev_pm_domain_detach_list (port -> pd_list );
1976
+ return ret ;
1900
1977
}
1901
1978
1902
1979
static void qcom_geni_serial_remove (struct platform_device * pdev )
@@ -1909,22 +1986,31 @@ static void qcom_geni_serial_remove(struct platform_device *pdev)
1909
1986
device_init_wakeup (& pdev -> dev , false);
1910
1987
ida_free (& port_ida , uport -> line );
1911
1988
uart_remove_one_port (drv , & port -> uport );
1989
+ dev_pm_domain_detach_list (port -> pd_list );
1912
1990
}
1913
1991
1914
1992
static int __maybe_unused qcom_geni_serial_runtime_suspend (struct device * dev )
1915
1993
{
1916
1994
struct qcom_geni_serial_port * port = dev_get_drvdata (dev );
1917
1995
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);
1918
2000
1919
- return geni_serial_resources_off ( uport ) ;
2001
+ return ret ;
1920
2002
}
1921
2003
1922
2004
static int __maybe_unused qcom_geni_serial_runtime_resume (struct device * dev )
1923
2005
{
1924
2006
struct qcom_geni_serial_port * port = dev_get_drvdata (dev );
1925
2007
struct uart_port * uport = & port -> uport ;
2008
+ int ret = 0 ;
1926
2009
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 ;
1928
2014
}
1929
2015
1930
2016
static int qcom_geni_serial_suspend (struct device * dev )
@@ -1962,11 +2048,41 @@ static int qcom_geni_serial_resume(struct device *dev)
1962
2048
static const struct qcom_geni_device_data qcom_geni_console_data = {
1963
2049
.console = true,
1964
2050
.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 ,
1965
2054
};
1966
2055
1967
2056
static const struct qcom_geni_device_data qcom_geni_uart_data = {
1968
2057
.console = false,
1969
2058
.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 ,
1970
2086
};
1971
2087
1972
2088
static 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[] = {
1980
2096
.compatible = "qcom,geni-debug-uart" ,
1981
2097
.data = & qcom_geni_console_data ,
1982
2098
},
2099
+ {
2100
+ .compatible = "qcom,sa8255p-geni-debug-uart" ,
2101
+ .data = & sa8255p_qcom_geni_console_data ,
2102
+ },
1983
2103
{
1984
2104
.compatible = "qcom,geni-uart" ,
1985
2105
.data = & qcom_geni_uart_data ,
1986
2106
},
2107
+ {
2108
+ .compatible = "qcom,sa8255p-geni-uart" ,
2109
+ .data = & sa8255p_qcom_geni_uart_data ,
2110
+ },
1987
2111
{}
1988
2112
};
1989
2113
MODULE_DEVICE_TABLE (of , qcom_geni_serial_match_table );
0 commit comments