blob: 47a6a9dfc9e8c191d8194dc11e5e979e7a5b1d06 [file] [log] [blame]
Jarkko Nikulab711f682021-06-02 14:32:59 +03001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel Quadrature Encoder Peripheral driver
4 *
5 * Copyright (C) 2019-2021 Intel Corporation
6 *
7 * Author: Felipe Balbi (Intel)
8 * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com>
9 * Author: Raymond Tan <raymond.tan@intel.com>
10 */
Jarkko Nikulab711f682021-06-02 14:32:59 +030011#include <linux/counter.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/mutex.h>
15#include <linux/pci.h>
16#include <linux/pm_runtime.h>
17
18#define INTEL_QEPCON 0x00
19#define INTEL_QEPFLT 0x04
20#define INTEL_QEPCOUNT 0x08
21#define INTEL_QEPMAX 0x0c
22#define INTEL_QEPWDT 0x10
23#define INTEL_QEPCAPDIV 0x14
24#define INTEL_QEPCNTR 0x18
25#define INTEL_QEPCAPBUF 0x1c
26#define INTEL_QEPINT_STAT 0x20
27#define INTEL_QEPINT_MASK 0x24
28
29/* QEPCON */
30#define INTEL_QEPCON_EN BIT(0)
31#define INTEL_QEPCON_FLT_EN BIT(1)
32#define INTEL_QEPCON_EDGE_A BIT(2)
33#define INTEL_QEPCON_EDGE_B BIT(3)
34#define INTEL_QEPCON_EDGE_INDX BIT(4)
35#define INTEL_QEPCON_SWPAB BIT(5)
36#define INTEL_QEPCON_OP_MODE BIT(6)
37#define INTEL_QEPCON_PH_ERR BIT(7)
38#define INTEL_QEPCON_COUNT_RST_MODE BIT(8)
39#define INTEL_QEPCON_INDX_GATING_MASK GENMASK(10, 9)
40#define INTEL_QEPCON_INDX_GATING(n) (((n) & 3) << 9)
41#define INTEL_QEPCON_INDX_PAL_PBL INTEL_QEPCON_INDX_GATING(0)
42#define INTEL_QEPCON_INDX_PAL_PBH INTEL_QEPCON_INDX_GATING(1)
43#define INTEL_QEPCON_INDX_PAH_PBL INTEL_QEPCON_INDX_GATING(2)
44#define INTEL_QEPCON_INDX_PAH_PBH INTEL_QEPCON_INDX_GATING(3)
45#define INTEL_QEPCON_CAP_MODE BIT(11)
46#define INTEL_QEPCON_FIFO_THRE_MASK GENMASK(14, 12)
47#define INTEL_QEPCON_FIFO_THRE(n) ((((n) - 1) & 7) << 12)
48#define INTEL_QEPCON_FIFO_EMPTY BIT(15)
49
50/* QEPFLT */
51#define INTEL_QEPFLT_MAX_COUNT(n) ((n) & 0x1fffff)
52
53/* QEPINT */
54#define INTEL_QEPINT_FIFOCRIT BIT(5)
55#define INTEL_QEPINT_FIFOENTRY BIT(4)
56#define INTEL_QEPINT_QEPDIR BIT(3)
57#define INTEL_QEPINT_QEPRST_UP BIT(2)
58#define INTEL_QEPINT_QEPRST_DOWN BIT(1)
59#define INTEL_QEPINT_WDT BIT(0)
60
61#define INTEL_QEPINT_MASK_ALL GENMASK(5, 0)
62
63#define INTEL_QEP_CLK_PERIOD_NS 10
64
Jarkko Nikulab711f682021-06-02 14:32:59 +030065struct intel_qep {
Jarkko Nikulab711f682021-06-02 14:32:59 +030066 struct mutex lock;
67 struct device *dev;
68 void __iomem *regs;
69 bool enabled;
70 /* Context save registers */
71 u32 qepcon;
72 u32 qepflt;
73 u32 qepmax;
74};
75
76static inline u32 intel_qep_readl(struct intel_qep *qep, u32 offset)
77{
78 return readl(qep->regs + offset);
79}
80
81static inline void intel_qep_writel(struct intel_qep *qep,
82 u32 offset, u32 value)
83{
84 writel(value, qep->regs + offset);
85}
86
87static void intel_qep_init(struct intel_qep *qep)
88{
89 u32 reg;
90
91 reg = intel_qep_readl(qep, INTEL_QEPCON);
92 reg &= ~INTEL_QEPCON_EN;
93 intel_qep_writel(qep, INTEL_QEPCON, reg);
94 qep->enabled = false;
95 /*
96 * Make sure peripheral is disabled by flushing the write with
97 * a dummy read
98 */
99 reg = intel_qep_readl(qep, INTEL_QEPCON);
100
101 reg &= ~(INTEL_QEPCON_OP_MODE | INTEL_QEPCON_FLT_EN);
102 reg |= INTEL_QEPCON_EDGE_A | INTEL_QEPCON_EDGE_B |
103 INTEL_QEPCON_EDGE_INDX | INTEL_QEPCON_COUNT_RST_MODE;
104 intel_qep_writel(qep, INTEL_QEPCON, reg);
105 intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL);
106}
107
108static int intel_qep_count_read(struct counter_device *counter,
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900109 struct counter_count *count, u64 *val)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300110{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100111 struct intel_qep *const qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300112
113 pm_runtime_get_sync(qep->dev);
114 *val = intel_qep_readl(qep, INTEL_QEPCOUNT);
115 pm_runtime_put(qep->dev);
116
117 return 0;
118}
119
William Breathitt Gray394a0152021-08-03 21:06:15 +0900120static const enum counter_function intel_qep_count_functions[] = {
121 COUNTER_FUNCTION_QUADRATURE_X4,
Jarkko Nikulab711f682021-06-02 14:32:59 +0300122};
123
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900124static int intel_qep_function_read(struct counter_device *counter,
125 struct counter_count *count,
126 enum counter_function *function)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300127{
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900128 *function = COUNTER_FUNCTION_QUADRATURE_X4;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300129
130 return 0;
131}
132
133static const enum counter_synapse_action intel_qep_synapse_actions[] = {
134 COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
135};
136
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900137static int intel_qep_action_read(struct counter_device *counter,
138 struct counter_count *count,
139 struct counter_synapse *synapse,
140 enum counter_synapse_action *action)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300141{
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900142 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300143 return 0;
144}
145
146static const struct counter_ops intel_qep_counter_ops = {
147 .count_read = intel_qep_count_read,
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900148 .function_read = intel_qep_function_read,
149 .action_read = intel_qep_action_read,
Jarkko Nikulab711f682021-06-02 14:32:59 +0300150};
151
152#define INTEL_QEP_SIGNAL(_id, _name) { \
153 .id = (_id), \
154 .name = (_name), \
155}
156
157static struct counter_signal intel_qep_signals[] = {
158 INTEL_QEP_SIGNAL(0, "Phase A"),
159 INTEL_QEP_SIGNAL(1, "Phase B"),
160 INTEL_QEP_SIGNAL(2, "Index"),
161};
162
163#define INTEL_QEP_SYNAPSE(_signal_id) { \
164 .actions_list = intel_qep_synapse_actions, \
165 .num_actions = ARRAY_SIZE(intel_qep_synapse_actions), \
166 .signal = &intel_qep_signals[(_signal_id)], \
167}
168
169static struct counter_synapse intel_qep_count_synapses[] = {
170 INTEL_QEP_SYNAPSE(0),
171 INTEL_QEP_SYNAPSE(1),
172 INTEL_QEP_SYNAPSE(2),
173};
174
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900175static int intel_qep_ceiling_read(struct counter_device *counter,
176 struct counter_count *count, u64 *ceiling)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300177{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100178 struct intel_qep *qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300179
180 pm_runtime_get_sync(qep->dev);
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900181 *ceiling = intel_qep_readl(qep, INTEL_QEPMAX);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300182 pm_runtime_put(qep->dev);
183
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900184 return 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300185}
186
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900187static int intel_qep_ceiling_write(struct counter_device *counter,
188 struct counter_count *count, u64 max)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300189{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100190 struct intel_qep *qep = counter_priv(counter);
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900191 int ret = 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300192
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900193 /* Intel QEP ceiling configuration only supports 32-bit values */
194 if (max != (u32)max)
195 return -ERANGE;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300196
197 mutex_lock(&qep->lock);
198 if (qep->enabled) {
199 ret = -EBUSY;
200 goto out;
201 }
202
203 pm_runtime_get_sync(qep->dev);
204 intel_qep_writel(qep, INTEL_QEPMAX, max);
205 pm_runtime_put(qep->dev);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300206
207out:
208 mutex_unlock(&qep->lock);
209 return ret;
210}
211
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900212static int intel_qep_enable_read(struct counter_device *counter,
213 struct counter_count *count, u8 *enable)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300214{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100215 struct intel_qep *qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300216
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900217 *enable = qep->enabled;
218
219 return 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300220}
221
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900222static int intel_qep_enable_write(struct counter_device *counter,
223 struct counter_count *count, u8 val)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300224{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100225 struct intel_qep *qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300226 u32 reg;
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900227 bool changed;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300228
229 mutex_lock(&qep->lock);
230 changed = val ^ qep->enabled;
231 if (!changed)
232 goto out;
233
234 pm_runtime_get_sync(qep->dev);
235 reg = intel_qep_readl(qep, INTEL_QEPCON);
236 if (val) {
237 /* Enable peripheral and keep runtime PM always on */
238 reg |= INTEL_QEPCON_EN;
239 pm_runtime_get_noresume(qep->dev);
240 } else {
241 /* Let runtime PM be idle and disable peripheral */
242 pm_runtime_put_noidle(qep->dev);
243 reg &= ~INTEL_QEPCON_EN;
244 }
245 intel_qep_writel(qep, INTEL_QEPCON, reg);
246 pm_runtime_put(qep->dev);
247 qep->enabled = val;
248
249out:
250 mutex_unlock(&qep->lock);
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900251 return 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300252}
253
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900254static int intel_qep_spike_filter_ns_read(struct counter_device *counter,
255 struct counter_count *count,
256 u64 *length)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300257{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100258 struct intel_qep *qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300259 u32 reg;
260
261 pm_runtime_get_sync(qep->dev);
262 reg = intel_qep_readl(qep, INTEL_QEPCON);
263 if (!(reg & INTEL_QEPCON_FLT_EN)) {
264 pm_runtime_put(qep->dev);
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900265 return 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300266 }
267 reg = INTEL_QEPFLT_MAX_COUNT(intel_qep_readl(qep, INTEL_QEPFLT));
268 pm_runtime_put(qep->dev);
269
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900270 *length = (reg + 2) * INTEL_QEP_CLK_PERIOD_NS;
271
272 return 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300273}
274
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900275static int intel_qep_spike_filter_ns_write(struct counter_device *counter,
276 struct counter_count *count,
277 u64 length)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300278{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100279 struct intel_qep *qep = counter_priv(counter);
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900280 u32 reg;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300281 bool enable;
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900282 int ret = 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300283
284 /*
285 * Spike filter length is (MAX_COUNT + 2) clock periods.
286 * Disable filter when userspace writes 0, enable for valid
287 * nanoseconds values and error out otherwise.
288 */
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900289 do_div(length, INTEL_QEP_CLK_PERIOD_NS);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300290 if (length == 0) {
291 enable = false;
292 length = 0;
293 } else if (length >= 2) {
294 enable = true;
295 length -= 2;
296 } else {
297 return -EINVAL;
298 }
299
300 if (length > INTEL_QEPFLT_MAX_COUNT(length))
William Breathitt Graye2ff3192021-08-03 21:06:13 +0900301 return -ERANGE;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300302
303 mutex_lock(&qep->lock);
304 if (qep->enabled) {
305 ret = -EBUSY;
306 goto out;
307 }
308
309 pm_runtime_get_sync(qep->dev);
310 reg = intel_qep_readl(qep, INTEL_QEPCON);
311 if (enable)
312 reg |= INTEL_QEPCON_FLT_EN;
313 else
314 reg &= ~INTEL_QEPCON_FLT_EN;
315 intel_qep_writel(qep, INTEL_QEPFLT, length);
316 intel_qep_writel(qep, INTEL_QEPCON, reg);
317 pm_runtime_put(qep->dev);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300318
319out:
320 mutex_unlock(&qep->lock);
321 return ret;
322}
323
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900324static int intel_qep_preset_enable_read(struct counter_device *counter,
325 struct counter_count *count,
326 u8 *preset_enable)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300327{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100328 struct intel_qep *qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300329 u32 reg;
330
331 pm_runtime_get_sync(qep->dev);
332 reg = intel_qep_readl(qep, INTEL_QEPCON);
333 pm_runtime_put(qep->dev);
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900334
335 *preset_enable = !(reg & INTEL_QEPCON_COUNT_RST_MODE);
336
337 return 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300338}
339
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900340static int intel_qep_preset_enable_write(struct counter_device *counter,
341 struct counter_count *count, u8 val)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300342{
Uwe Kleine-König53ada092021-12-30 16:02:45 +0100343 struct intel_qep *qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300344 u32 reg;
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900345 int ret = 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300346
347 mutex_lock(&qep->lock);
348 if (qep->enabled) {
349 ret = -EBUSY;
350 goto out;
351 }
352
353 pm_runtime_get_sync(qep->dev);
354 reg = intel_qep_readl(qep, INTEL_QEPCON);
355 if (val)
356 reg &= ~INTEL_QEPCON_COUNT_RST_MODE;
357 else
358 reg |= INTEL_QEPCON_COUNT_RST_MODE;
359
360 intel_qep_writel(qep, INTEL_QEPCON, reg);
361 pm_runtime_put(qep->dev);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300362
363out:
364 mutex_unlock(&qep->lock);
365
366 return ret;
367}
368
William Breathitt Grayaaec1a02021-08-27 12:47:47 +0900369static struct counter_comp intel_qep_count_ext[] = {
370 COUNTER_COMP_ENABLE(intel_qep_enable_read, intel_qep_enable_write),
371 COUNTER_COMP_CEILING(intel_qep_ceiling_read, intel_qep_ceiling_write),
372 COUNTER_COMP_PRESET_ENABLE(intel_qep_preset_enable_read,
373 intel_qep_preset_enable_write),
374 COUNTER_COMP_COUNT_U64("spike_filter_ns",
375 intel_qep_spike_filter_ns_read,
376 intel_qep_spike_filter_ns_write),
Jarkko Nikulab711f682021-06-02 14:32:59 +0300377};
378
379static struct counter_count intel_qep_counter_count[] = {
380 {
381 .id = 0,
382 .name = "Channel 1 Count",
383 .functions_list = intel_qep_count_functions,
384 .num_functions = ARRAY_SIZE(intel_qep_count_functions),
385 .synapses = intel_qep_count_synapses,
386 .num_synapses = ARRAY_SIZE(intel_qep_count_synapses),
387 .ext = intel_qep_count_ext,
388 .num_ext = ARRAY_SIZE(intel_qep_count_ext),
389 },
390};
391
392static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id)
393{
Uwe Kleine-Könige99dec82021-12-30 16:02:54 +0100394 struct counter_device *counter;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300395 struct intel_qep *qep;
396 struct device *dev = &pci->dev;
397 void __iomem *regs;
398 int ret;
399
Uwe Kleine-Könige99dec82021-12-30 16:02:54 +0100400 counter = devm_counter_alloc(dev, sizeof(*qep));
401 if (!counter)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300402 return -ENOMEM;
Uwe Kleine-Könige99dec82021-12-30 16:02:54 +0100403 qep = counter_priv(counter);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300404
405 ret = pcim_enable_device(pci);
406 if (ret)
407 return ret;
408
409 pci_set_master(pci);
410
411 ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
412 if (ret)
413 return ret;
414
415 regs = pcim_iomap_table(pci)[0];
416 if (!regs)
417 return -ENOMEM;
418
419 qep->dev = dev;
420 qep->regs = regs;
421 mutex_init(&qep->lock);
422
423 intel_qep_init(qep);
424 pci_set_drvdata(pci, qep);
425
Uwe Kleine-Könige99dec82021-12-30 16:02:54 +0100426 counter->name = pci_name(pci);
427 counter->parent = dev;
428 counter->ops = &intel_qep_counter_ops;
429 counter->counts = intel_qep_counter_count;
430 counter->num_counts = ARRAY_SIZE(intel_qep_counter_count);
431 counter->signals = intel_qep_signals;
432 counter->num_signals = ARRAY_SIZE(intel_qep_signals);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300433 qep->enabled = false;
434
435 pm_runtime_put(dev);
436 pm_runtime_allow(dev);
437
Uwe Kleine-Könige99dec82021-12-30 16:02:54 +0100438 ret = devm_counter_add(&pci->dev, counter);
439 if (ret < 0)
440 return dev_err_probe(&pci->dev, ret, "Failed to add counter\n");
441
442 return 0;
Jarkko Nikulab711f682021-06-02 14:32:59 +0300443}
444
445static void intel_qep_remove(struct pci_dev *pci)
446{
447 struct intel_qep *qep = pci_get_drvdata(pci);
448 struct device *dev = &pci->dev;
449
450 pm_runtime_forbid(dev);
451 if (!qep->enabled)
452 pm_runtime_get(dev);
453
454 intel_qep_writel(qep, INTEL_QEPCON, 0);
455}
456
Jarkko Nikulaac3bd9d2021-06-11 14:55:57 +0300457static int __maybe_unused intel_qep_suspend(struct device *dev)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300458{
Jarkko Nikula93466212021-06-11 14:55:58 +0300459 struct pci_dev *pdev = to_pci_dev(dev);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300460 struct intel_qep *qep = pci_get_drvdata(pdev);
461
462 qep->qepcon = intel_qep_readl(qep, INTEL_QEPCON);
463 qep->qepflt = intel_qep_readl(qep, INTEL_QEPFLT);
464 qep->qepmax = intel_qep_readl(qep, INTEL_QEPMAX);
465
466 return 0;
467}
468
Jarkko Nikulaac3bd9d2021-06-11 14:55:57 +0300469static int __maybe_unused intel_qep_resume(struct device *dev)
Jarkko Nikulab711f682021-06-02 14:32:59 +0300470{
Jarkko Nikula93466212021-06-11 14:55:58 +0300471 struct pci_dev *pdev = to_pci_dev(dev);
Jarkko Nikulab711f682021-06-02 14:32:59 +0300472 struct intel_qep *qep = pci_get_drvdata(pdev);
473
474 /*
475 * Make sure peripheral is disabled when restoring registers and
476 * control register bits that are writable only when the peripheral
477 * is disabled
478 */
479 intel_qep_writel(qep, INTEL_QEPCON, 0);
480 intel_qep_readl(qep, INTEL_QEPCON);
481
482 intel_qep_writel(qep, INTEL_QEPFLT, qep->qepflt);
483 intel_qep_writel(qep, INTEL_QEPMAX, qep->qepmax);
484 intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL);
485
486 /* Restore all other control register bits except enable status */
487 intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon & ~INTEL_QEPCON_EN);
488 intel_qep_readl(qep, INTEL_QEPCON);
489
490 /* Restore enable status */
491 intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon);
492
493 return 0;
494}
Jarkko Nikulab711f682021-06-02 14:32:59 +0300495
496static UNIVERSAL_DEV_PM_OPS(intel_qep_pm_ops,
497 intel_qep_suspend, intel_qep_resume, NULL);
498
499static const struct pci_device_id intel_qep_id_table[] = {
500 /* EHL */
501 { PCI_VDEVICE(INTEL, 0x4bc3), },
502 { PCI_VDEVICE(INTEL, 0x4b81), },
503 { PCI_VDEVICE(INTEL, 0x4b82), },
504 { PCI_VDEVICE(INTEL, 0x4b83), },
505 { } /* Terminating Entry */
506};
507MODULE_DEVICE_TABLE(pci, intel_qep_id_table);
508
509static struct pci_driver intel_qep_driver = {
510 .name = "intel-qep",
511 .id_table = intel_qep_id_table,
512 .probe = intel_qep_probe,
513 .remove = intel_qep_remove,
514 .driver = {
515 .pm = &intel_qep_pm_ops,
516 }
517};
518
519module_pci_driver(intel_qep_driver);
520
521MODULE_AUTHOR("Felipe Balbi (Intel)");
522MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>");
523MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
524MODULE_LICENSE("GPL");
525MODULE_DESCRIPTION("Intel Quadrature Encoder Peripheral driver");