77 * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com>
88 */
99#include <linux/acpi.h>
10+ #include <linux/bitfield.h>
11+ #include <linux/debugfs.h>
1012#include <linux/idr.h>
1113#include <linux/iopoll.h>
1214#include <linux/kernel.h>
1315#include <linux/module.h>
1416#include <linux/pci.h>
1517#include <linux/platform_device.h>
18+ #include <linux/pm_qos.h>
1619
1720struct mipi_i3c_hci_pci {
1821 struct pci_dev * pci ;
1922 struct platform_device * pdev ;
2023 const struct mipi_i3c_hci_pci_info * info ;
24+ void * private ;
2125};
2226
2327struct mipi_i3c_hci_pci_info {
@@ -34,6 +38,99 @@ static DEFINE_IDA(mipi_i3c_hci_pci_ida);
3438#define INTEL_RESETS_RESET_DONE BIT(1)
3539#define INTEL_RESETS_TIMEOUT_US (10 * USEC_PER_MSEC)
3640
41+ #define INTEL_ACTIVELTR 0x0c
42+ #define INTEL_IDLELTR 0x10
43+
44+ #define INTEL_LTR_REQ BIT(15)
45+ #define INTEL_LTR_SCALE_MASK GENMASK(11, 10)
46+ #define INTEL_LTR_SCALE_1US FIELD_PREP(INTEL_LTR_SCALE_MASK, 2)
47+ #define INTEL_LTR_SCALE_32US FIELD_PREP(INTEL_LTR_SCALE_MASK, 3)
48+ #define INTEL_LTR_VALUE_MASK GENMASK(9, 0)
49+
50+ struct intel_host {
51+ void __iomem * priv ;
52+ u32 active_ltr ;
53+ u32 idle_ltr ;
54+ struct dentry * debugfs_root ;
55+ };
56+
57+ static void intel_cache_ltr (struct intel_host * host )
58+ {
59+ host -> active_ltr = readl (host -> priv + INTEL_ACTIVELTR );
60+ host -> idle_ltr = readl (host -> priv + INTEL_IDLELTR );
61+ }
62+
63+ static void intel_ltr_set (struct device * dev , s32 val )
64+ {
65+ struct mipi_i3c_hci_pci * hci = dev_get_drvdata (dev );
66+ struct intel_host * host = hci -> private ;
67+ u32 ltr ;
68+
69+ /*
70+ * Program latency tolerance (LTR) accordingly what has been asked
71+ * by the PM QoS layer or disable it in case we were passed
72+ * negative value or PM_QOS_LATENCY_ANY.
73+ */
74+ ltr = readl (host -> priv + INTEL_ACTIVELTR );
75+
76+ if (val == PM_QOS_LATENCY_ANY || val < 0 ) {
77+ ltr &= ~INTEL_LTR_REQ ;
78+ } else {
79+ ltr |= INTEL_LTR_REQ ;
80+ ltr &= ~INTEL_LTR_SCALE_MASK ;
81+ ltr &= ~INTEL_LTR_VALUE_MASK ;
82+
83+ if (val > INTEL_LTR_VALUE_MASK ) {
84+ val >>= 5 ;
85+ if (val > INTEL_LTR_VALUE_MASK )
86+ val = INTEL_LTR_VALUE_MASK ;
87+ ltr |= INTEL_LTR_SCALE_32US | val ;
88+ } else {
89+ ltr |= INTEL_LTR_SCALE_1US | val ;
90+ }
91+ }
92+
93+ if (ltr == host -> active_ltr )
94+ return ;
95+
96+ writel (ltr , host -> priv + INTEL_ACTIVELTR );
97+ writel (ltr , host -> priv + INTEL_IDLELTR );
98+
99+ /* Cache the values into intel_host structure */
100+ intel_cache_ltr (host );
101+ }
102+
103+ static void intel_ltr_expose (struct device * dev )
104+ {
105+ dev -> power .set_latency_tolerance = intel_ltr_set ;
106+ dev_pm_qos_expose_latency_tolerance (dev );
107+ }
108+
109+ static void intel_ltr_hide (struct device * dev )
110+ {
111+ dev_pm_qos_hide_latency_tolerance (dev );
112+ dev -> power .set_latency_tolerance = NULL ;
113+ }
114+
115+ static void intel_add_debugfs (struct mipi_i3c_hci_pci * hci )
116+ {
117+ struct dentry * dir = debugfs_create_dir (dev_name (& hci -> pci -> dev ), NULL );
118+ struct intel_host * host = hci -> private ;
119+
120+ intel_cache_ltr (host );
121+
122+ host -> debugfs_root = dir ;
123+ debugfs_create_x32 ("active_ltr" , 0444 , dir , & host -> active_ltr );
124+ debugfs_create_x32 ("idle_ltr" , 0444 , dir , & host -> idle_ltr );
125+ }
126+
127+ static void intel_remove_debugfs (struct mipi_i3c_hci_pci * hci )
128+ {
129+ struct intel_host * host = hci -> private ;
130+
131+ debugfs_remove_recursive (host -> debugfs_root );
132+ }
133+
37134static void intel_reset (void __iomem * priv )
38135{
39136 u32 reg ;
@@ -55,20 +152,34 @@ static void __iomem *intel_priv(struct pci_dev *pci)
55152
56153static int intel_i3c_init (struct mipi_i3c_hci_pci * hci )
57154{
155+ struct intel_host * host = devm_kzalloc (& hci -> pci -> dev , sizeof (* host ), GFP_KERNEL );
58156 void __iomem * priv = intel_priv (hci -> pci );
59157
60- if (!priv )
158+ if (!host || ! priv )
61159 return - ENOMEM ;
62160
63161 dma_set_mask_and_coherent (& hci -> pci -> dev , DMA_BIT_MASK (64 ));
64162
163+ hci -> private = host ;
164+ host -> priv = priv ;
165+
65166 intel_reset (priv );
66167
168+ intel_ltr_expose (& hci -> pci -> dev );
169+ intel_add_debugfs (hci );
170+
67171 return 0 ;
68172}
69173
174+ static void intel_i3c_exit (struct mipi_i3c_hci_pci * hci )
175+ {
176+ intel_remove_debugfs (hci );
177+ intel_ltr_hide (& hci -> pci -> dev );
178+ }
179+
70180static const struct mipi_i3c_hci_pci_info intel_info = {
71181 .init = intel_i3c_init ,
182+ .exit = intel_i3c_exit ,
72183};
73184
74185static int mipi_i3c_hci_pci_probe (struct pci_dev * pci ,
0 commit comments