1b711f687SJarkko Nikula // SPDX-License-Identifier: GPL-2.0
2b711f687SJarkko Nikula /*
3b711f687SJarkko Nikula * Intel Quadrature Encoder Peripheral driver
4b711f687SJarkko Nikula *
5b711f687SJarkko Nikula * Copyright (C) 2019-2021 Intel Corporation
6b711f687SJarkko Nikula *
7b711f687SJarkko Nikula * Author: Felipe Balbi (Intel)
8b711f687SJarkko Nikula * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com>
9b711f687SJarkko Nikula * Author: Raymond Tan <raymond.tan@intel.com>
10b711f687SJarkko Nikula */
11b711f687SJarkko Nikula #include <linux/counter.h>
12b711f687SJarkko Nikula #include <linux/kernel.h>
13b711f687SJarkko Nikula #include <linux/module.h>
14b711f687SJarkko Nikula #include <linux/mutex.h>
15b711f687SJarkko Nikula #include <linux/pci.h>
16b711f687SJarkko Nikula #include <linux/pm_runtime.h>
17b711f687SJarkko Nikula
18b711f687SJarkko Nikula #define INTEL_QEPCON 0x00
19b711f687SJarkko Nikula #define INTEL_QEPFLT 0x04
20b711f687SJarkko Nikula #define INTEL_QEPCOUNT 0x08
21b711f687SJarkko Nikula #define INTEL_QEPMAX 0x0c
22b711f687SJarkko Nikula #define INTEL_QEPWDT 0x10
23b711f687SJarkko Nikula #define INTEL_QEPCAPDIV 0x14
24b711f687SJarkko Nikula #define INTEL_QEPCNTR 0x18
25b711f687SJarkko Nikula #define INTEL_QEPCAPBUF 0x1c
26b711f687SJarkko Nikula #define INTEL_QEPINT_STAT 0x20
27b711f687SJarkko Nikula #define INTEL_QEPINT_MASK 0x24
28b711f687SJarkko Nikula
29b711f687SJarkko Nikula /* QEPCON */
30b711f687SJarkko Nikula #define INTEL_QEPCON_EN BIT(0)
31b711f687SJarkko Nikula #define INTEL_QEPCON_FLT_EN BIT(1)
32b711f687SJarkko Nikula #define INTEL_QEPCON_EDGE_A BIT(2)
33b711f687SJarkko Nikula #define INTEL_QEPCON_EDGE_B BIT(3)
34b711f687SJarkko Nikula #define INTEL_QEPCON_EDGE_INDX BIT(4)
35b711f687SJarkko Nikula #define INTEL_QEPCON_SWPAB BIT(5)
36b711f687SJarkko Nikula #define INTEL_QEPCON_OP_MODE BIT(6)
37b711f687SJarkko Nikula #define INTEL_QEPCON_PH_ERR BIT(7)
38b711f687SJarkko Nikula #define INTEL_QEPCON_COUNT_RST_MODE BIT(8)
39b711f687SJarkko Nikula #define INTEL_QEPCON_INDX_GATING_MASK GENMASK(10, 9)
40b711f687SJarkko Nikula #define INTEL_QEPCON_INDX_GATING(n) (((n) & 3) << 9)
41b711f687SJarkko Nikula #define INTEL_QEPCON_INDX_PAL_PBL INTEL_QEPCON_INDX_GATING(0)
42b711f687SJarkko Nikula #define INTEL_QEPCON_INDX_PAL_PBH INTEL_QEPCON_INDX_GATING(1)
43b711f687SJarkko Nikula #define INTEL_QEPCON_INDX_PAH_PBL INTEL_QEPCON_INDX_GATING(2)
44b711f687SJarkko Nikula #define INTEL_QEPCON_INDX_PAH_PBH INTEL_QEPCON_INDX_GATING(3)
45b711f687SJarkko Nikula #define INTEL_QEPCON_CAP_MODE BIT(11)
46b711f687SJarkko Nikula #define INTEL_QEPCON_FIFO_THRE_MASK GENMASK(14, 12)
47b711f687SJarkko Nikula #define INTEL_QEPCON_FIFO_THRE(n) ((((n) - 1) & 7) << 12)
48b711f687SJarkko Nikula #define INTEL_QEPCON_FIFO_EMPTY BIT(15)
49b711f687SJarkko Nikula
50b711f687SJarkko Nikula /* QEPFLT */
51b711f687SJarkko Nikula #define INTEL_QEPFLT_MAX_COUNT(n) ((n) & 0x1fffff)
52b711f687SJarkko Nikula
53b711f687SJarkko Nikula /* QEPINT */
54b711f687SJarkko Nikula #define INTEL_QEPINT_FIFOCRIT BIT(5)
55b711f687SJarkko Nikula #define INTEL_QEPINT_FIFOENTRY BIT(4)
56b711f687SJarkko Nikula #define INTEL_QEPINT_QEPDIR BIT(3)
57b711f687SJarkko Nikula #define INTEL_QEPINT_QEPRST_UP BIT(2)
58b711f687SJarkko Nikula #define INTEL_QEPINT_QEPRST_DOWN BIT(1)
59b711f687SJarkko Nikula #define INTEL_QEPINT_WDT BIT(0)
60b711f687SJarkko Nikula
61b711f687SJarkko Nikula #define INTEL_QEPINT_MASK_ALL GENMASK(5, 0)
62b711f687SJarkko Nikula
63b711f687SJarkko Nikula #define INTEL_QEP_CLK_PERIOD_NS 10
64b711f687SJarkko Nikula
65b711f687SJarkko Nikula struct intel_qep {
66b711f687SJarkko Nikula struct mutex lock;
67b711f687SJarkko Nikula struct device *dev;
68b711f687SJarkko Nikula void __iomem *regs;
69b711f687SJarkko Nikula bool enabled;
70b711f687SJarkko Nikula /* Context save registers */
71b711f687SJarkko Nikula u32 qepcon;
72b711f687SJarkko Nikula u32 qepflt;
73b711f687SJarkko Nikula u32 qepmax;
74b711f687SJarkko Nikula };
75b711f687SJarkko Nikula
intel_qep_readl(struct intel_qep * qep,u32 offset)76b711f687SJarkko Nikula static inline u32 intel_qep_readl(struct intel_qep *qep, u32 offset)
77b711f687SJarkko Nikula {
78b711f687SJarkko Nikula return readl(qep->regs + offset);
79b711f687SJarkko Nikula }
80b711f687SJarkko Nikula
intel_qep_writel(struct intel_qep * qep,u32 offset,u32 value)81b711f687SJarkko Nikula static inline void intel_qep_writel(struct intel_qep *qep,
82b711f687SJarkko Nikula u32 offset, u32 value)
83b711f687SJarkko Nikula {
84b711f687SJarkko Nikula writel(value, qep->regs + offset);
85b711f687SJarkko Nikula }
86b711f687SJarkko Nikula
intel_qep_init(struct intel_qep * qep)87b711f687SJarkko Nikula static void intel_qep_init(struct intel_qep *qep)
88b711f687SJarkko Nikula {
89b711f687SJarkko Nikula u32 reg;
90b711f687SJarkko Nikula
91b711f687SJarkko Nikula reg = intel_qep_readl(qep, INTEL_QEPCON);
92b711f687SJarkko Nikula reg &= ~INTEL_QEPCON_EN;
93b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, reg);
94b711f687SJarkko Nikula qep->enabled = false;
95b711f687SJarkko Nikula /*
96b711f687SJarkko Nikula * Make sure peripheral is disabled by flushing the write with
97b711f687SJarkko Nikula * a dummy read
98b711f687SJarkko Nikula */
99b711f687SJarkko Nikula reg = intel_qep_readl(qep, INTEL_QEPCON);
100b711f687SJarkko Nikula
101b711f687SJarkko Nikula reg &= ~(INTEL_QEPCON_OP_MODE | INTEL_QEPCON_FLT_EN);
102b711f687SJarkko Nikula reg |= INTEL_QEPCON_EDGE_A | INTEL_QEPCON_EDGE_B |
103b711f687SJarkko Nikula INTEL_QEPCON_EDGE_INDX | INTEL_QEPCON_COUNT_RST_MODE;
104b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, reg);
105b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL);
106b711f687SJarkko Nikula }
107b711f687SJarkko Nikula
intel_qep_count_read(struct counter_device * counter,struct counter_count * count,u64 * val)108b711f687SJarkko Nikula static int intel_qep_count_read(struct counter_device *counter,
109aaec1a0fSWilliam Breathitt Gray struct counter_count *count, u64 *val)
110b711f687SJarkko Nikula {
11153ada095SUwe Kleine-König struct intel_qep *const qep = counter_priv(counter);
112b711f687SJarkko Nikula
113b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
114b711f687SJarkko Nikula *val = intel_qep_readl(qep, INTEL_QEPCOUNT);
115b711f687SJarkko Nikula pm_runtime_put(qep->dev);
116b711f687SJarkko Nikula
117b711f687SJarkko Nikula return 0;
118b711f687SJarkko Nikula }
119b711f687SJarkko Nikula
120394a0150SWilliam Breathitt Gray static const enum counter_function intel_qep_count_functions[] = {
121394a0150SWilliam Breathitt Gray COUNTER_FUNCTION_QUADRATURE_X4,
122b711f687SJarkko Nikula };
123b711f687SJarkko Nikula
intel_qep_function_read(struct counter_device * counter,struct counter_count * count,enum counter_function * function)124aaec1a0fSWilliam Breathitt Gray static int intel_qep_function_read(struct counter_device *counter,
125b711f687SJarkko Nikula struct counter_count *count,
126aaec1a0fSWilliam Breathitt Gray enum counter_function *function)
127b711f687SJarkko Nikula {
128aaec1a0fSWilliam Breathitt Gray *function = COUNTER_FUNCTION_QUADRATURE_X4;
129b711f687SJarkko Nikula
130b711f687SJarkko Nikula return 0;
131b711f687SJarkko Nikula }
132b711f687SJarkko Nikula
133b711f687SJarkko Nikula static const enum counter_synapse_action intel_qep_synapse_actions[] = {
134b711f687SJarkko Nikula COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
135b711f687SJarkko Nikula };
136b711f687SJarkko Nikula
intel_qep_action_read(struct counter_device * counter,struct counter_count * count,struct counter_synapse * synapse,enum counter_synapse_action * action)137aaec1a0fSWilliam Breathitt Gray static int intel_qep_action_read(struct counter_device *counter,
138b711f687SJarkko Nikula struct counter_count *count,
139b711f687SJarkko Nikula struct counter_synapse *synapse,
140aaec1a0fSWilliam Breathitt Gray enum counter_synapse_action *action)
141b711f687SJarkko Nikula {
142aaec1a0fSWilliam Breathitt Gray *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
143b711f687SJarkko Nikula return 0;
144b711f687SJarkko Nikula }
145b711f687SJarkko Nikula
146b711f687SJarkko Nikula static const struct counter_ops intel_qep_counter_ops = {
147b711f687SJarkko Nikula .count_read = intel_qep_count_read,
148aaec1a0fSWilliam Breathitt Gray .function_read = intel_qep_function_read,
149aaec1a0fSWilliam Breathitt Gray .action_read = intel_qep_action_read,
150b711f687SJarkko Nikula };
151b711f687SJarkko Nikula
152b711f687SJarkko Nikula #define INTEL_QEP_SIGNAL(_id, _name) { \
153b711f687SJarkko Nikula .id = (_id), \
154b711f687SJarkko Nikula .name = (_name), \
155b711f687SJarkko Nikula }
156b711f687SJarkko Nikula
157b711f687SJarkko Nikula static struct counter_signal intel_qep_signals[] = {
158b711f687SJarkko Nikula INTEL_QEP_SIGNAL(0, "Phase A"),
159b711f687SJarkko Nikula INTEL_QEP_SIGNAL(1, "Phase B"),
160b711f687SJarkko Nikula INTEL_QEP_SIGNAL(2, "Index"),
161b711f687SJarkko Nikula };
162b711f687SJarkko Nikula
163b711f687SJarkko Nikula #define INTEL_QEP_SYNAPSE(_signal_id) { \
164b711f687SJarkko Nikula .actions_list = intel_qep_synapse_actions, \
165b711f687SJarkko Nikula .num_actions = ARRAY_SIZE(intel_qep_synapse_actions), \
166b711f687SJarkko Nikula .signal = &intel_qep_signals[(_signal_id)], \
167b711f687SJarkko Nikula }
168b711f687SJarkko Nikula
169b711f687SJarkko Nikula static struct counter_synapse intel_qep_count_synapses[] = {
170b711f687SJarkko Nikula INTEL_QEP_SYNAPSE(0),
171b711f687SJarkko Nikula INTEL_QEP_SYNAPSE(1),
172b711f687SJarkko Nikula INTEL_QEP_SYNAPSE(2),
173b711f687SJarkko Nikula };
174b711f687SJarkko Nikula
intel_qep_ceiling_read(struct counter_device * counter,struct counter_count * count,u64 * ceiling)175aaec1a0fSWilliam Breathitt Gray static int intel_qep_ceiling_read(struct counter_device *counter,
176aaec1a0fSWilliam Breathitt Gray struct counter_count *count, u64 *ceiling)
177b711f687SJarkko Nikula {
17853ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
179b711f687SJarkko Nikula
180b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
181aaec1a0fSWilliam Breathitt Gray *ceiling = intel_qep_readl(qep, INTEL_QEPMAX);
182b711f687SJarkko Nikula pm_runtime_put(qep->dev);
183b711f687SJarkko Nikula
184aaec1a0fSWilliam Breathitt Gray return 0;
185b711f687SJarkko Nikula }
186b711f687SJarkko Nikula
intel_qep_ceiling_write(struct counter_device * counter,struct counter_count * count,u64 max)187aaec1a0fSWilliam Breathitt Gray static int intel_qep_ceiling_write(struct counter_device *counter,
188aaec1a0fSWilliam Breathitt Gray struct counter_count *count, u64 max)
189b711f687SJarkko Nikula {
19053ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
191aaec1a0fSWilliam Breathitt Gray int ret = 0;
192b711f687SJarkko Nikula
193aaec1a0fSWilliam Breathitt Gray /* Intel QEP ceiling configuration only supports 32-bit values */
194aaec1a0fSWilliam Breathitt Gray if (max != (u32)max)
195aaec1a0fSWilliam Breathitt Gray return -ERANGE;
196b711f687SJarkko Nikula
197b711f687SJarkko Nikula mutex_lock(&qep->lock);
198b711f687SJarkko Nikula if (qep->enabled) {
199b711f687SJarkko Nikula ret = -EBUSY;
200b711f687SJarkko Nikula goto out;
201b711f687SJarkko Nikula }
202b711f687SJarkko Nikula
203b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
204b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPMAX, max);
205b711f687SJarkko Nikula pm_runtime_put(qep->dev);
206b711f687SJarkko Nikula
207b711f687SJarkko Nikula out:
208b711f687SJarkko Nikula mutex_unlock(&qep->lock);
209b711f687SJarkko Nikula return ret;
210b711f687SJarkko Nikula }
211b711f687SJarkko Nikula
intel_qep_enable_read(struct counter_device * counter,struct counter_count * count,u8 * enable)212aaec1a0fSWilliam Breathitt Gray static int intel_qep_enable_read(struct counter_device *counter,
213aaec1a0fSWilliam Breathitt Gray struct counter_count *count, u8 *enable)
214b711f687SJarkko Nikula {
21553ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
216b711f687SJarkko Nikula
217aaec1a0fSWilliam Breathitt Gray *enable = qep->enabled;
218aaec1a0fSWilliam Breathitt Gray
219aaec1a0fSWilliam Breathitt Gray return 0;
220b711f687SJarkko Nikula }
221b711f687SJarkko Nikula
intel_qep_enable_write(struct counter_device * counter,struct counter_count * count,u8 val)222aaec1a0fSWilliam Breathitt Gray static int intel_qep_enable_write(struct counter_device *counter,
223aaec1a0fSWilliam Breathitt Gray struct counter_count *count, u8 val)
224b711f687SJarkko Nikula {
22553ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
226b711f687SJarkko Nikula u32 reg;
227aaec1a0fSWilliam Breathitt Gray bool changed;
228b711f687SJarkko Nikula
229b711f687SJarkko Nikula mutex_lock(&qep->lock);
230b711f687SJarkko Nikula changed = val ^ qep->enabled;
231b711f687SJarkko Nikula if (!changed)
232b711f687SJarkko Nikula goto out;
233b711f687SJarkko Nikula
234b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
235b711f687SJarkko Nikula reg = intel_qep_readl(qep, INTEL_QEPCON);
236b711f687SJarkko Nikula if (val) {
237b711f687SJarkko Nikula /* Enable peripheral and keep runtime PM always on */
238b711f687SJarkko Nikula reg |= INTEL_QEPCON_EN;
239b711f687SJarkko Nikula pm_runtime_get_noresume(qep->dev);
240b711f687SJarkko Nikula } else {
241b711f687SJarkko Nikula /* Let runtime PM be idle and disable peripheral */
242b711f687SJarkko Nikula pm_runtime_put_noidle(qep->dev);
243b711f687SJarkko Nikula reg &= ~INTEL_QEPCON_EN;
244b711f687SJarkko Nikula }
245b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, reg);
246b711f687SJarkko Nikula pm_runtime_put(qep->dev);
247b711f687SJarkko Nikula qep->enabled = val;
248b711f687SJarkko Nikula
249b711f687SJarkko Nikula out:
250b711f687SJarkko Nikula mutex_unlock(&qep->lock);
251aaec1a0fSWilliam Breathitt Gray return 0;
252b711f687SJarkko Nikula }
253b711f687SJarkko Nikula
intel_qep_spike_filter_ns_read(struct counter_device * counter,struct counter_count * count,u64 * length)254aaec1a0fSWilliam Breathitt Gray static int intel_qep_spike_filter_ns_read(struct counter_device *counter,
255b711f687SJarkko Nikula struct counter_count *count,
256aaec1a0fSWilliam Breathitt Gray u64 *length)
257b711f687SJarkko Nikula {
25853ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
259b711f687SJarkko Nikula u32 reg;
260b711f687SJarkko Nikula
261b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
262b711f687SJarkko Nikula reg = intel_qep_readl(qep, INTEL_QEPCON);
263b711f687SJarkko Nikula if (!(reg & INTEL_QEPCON_FLT_EN)) {
264b711f687SJarkko Nikula pm_runtime_put(qep->dev);
265aaec1a0fSWilliam Breathitt Gray return 0;
266b711f687SJarkko Nikula }
267b711f687SJarkko Nikula reg = INTEL_QEPFLT_MAX_COUNT(intel_qep_readl(qep, INTEL_QEPFLT));
268b711f687SJarkko Nikula pm_runtime_put(qep->dev);
269b711f687SJarkko Nikula
270aaec1a0fSWilliam Breathitt Gray *length = (reg + 2) * INTEL_QEP_CLK_PERIOD_NS;
271aaec1a0fSWilliam Breathitt Gray
272aaec1a0fSWilliam Breathitt Gray return 0;
273b711f687SJarkko Nikula }
274b711f687SJarkko Nikula
intel_qep_spike_filter_ns_write(struct counter_device * counter,struct counter_count * count,u64 length)275aaec1a0fSWilliam Breathitt Gray static int intel_qep_spike_filter_ns_write(struct counter_device *counter,
276b711f687SJarkko Nikula struct counter_count *count,
277aaec1a0fSWilliam Breathitt Gray u64 length)
278b711f687SJarkko Nikula {
27953ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
280aaec1a0fSWilliam Breathitt Gray u32 reg;
281b711f687SJarkko Nikula bool enable;
282aaec1a0fSWilliam Breathitt Gray int ret = 0;
283b711f687SJarkko Nikula
284b711f687SJarkko Nikula /*
285b711f687SJarkko Nikula * Spike filter length is (MAX_COUNT + 2) clock periods.
286b711f687SJarkko Nikula * Disable filter when userspace writes 0, enable for valid
287b711f687SJarkko Nikula * nanoseconds values and error out otherwise.
288b711f687SJarkko Nikula */
289aaec1a0fSWilliam Breathitt Gray do_div(length, INTEL_QEP_CLK_PERIOD_NS);
290b711f687SJarkko Nikula if (length == 0) {
291b711f687SJarkko Nikula enable = false;
292b711f687SJarkko Nikula length = 0;
293b711f687SJarkko Nikula } else if (length >= 2) {
294b711f687SJarkko Nikula enable = true;
295b711f687SJarkko Nikula length -= 2;
296b711f687SJarkko Nikula } else {
297b711f687SJarkko Nikula return -EINVAL;
298b711f687SJarkko Nikula }
299b711f687SJarkko Nikula
300b711f687SJarkko Nikula if (length > INTEL_QEPFLT_MAX_COUNT(length))
301e2ff3198SWilliam Breathitt Gray return -ERANGE;
302b711f687SJarkko Nikula
303b711f687SJarkko Nikula mutex_lock(&qep->lock);
304b711f687SJarkko Nikula if (qep->enabled) {
305b711f687SJarkko Nikula ret = -EBUSY;
306b711f687SJarkko Nikula goto out;
307b711f687SJarkko Nikula }
308b711f687SJarkko Nikula
309b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
310b711f687SJarkko Nikula reg = intel_qep_readl(qep, INTEL_QEPCON);
311b711f687SJarkko Nikula if (enable)
312b711f687SJarkko Nikula reg |= INTEL_QEPCON_FLT_EN;
313b711f687SJarkko Nikula else
314b711f687SJarkko Nikula reg &= ~INTEL_QEPCON_FLT_EN;
315b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPFLT, length);
316b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, reg);
317b711f687SJarkko Nikula pm_runtime_put(qep->dev);
318b711f687SJarkko Nikula
319b711f687SJarkko Nikula out:
320b711f687SJarkko Nikula mutex_unlock(&qep->lock);
321b711f687SJarkko Nikula return ret;
322b711f687SJarkko Nikula }
323b711f687SJarkko Nikula
intel_qep_preset_enable_read(struct counter_device * counter,struct counter_count * count,u8 * preset_enable)324aaec1a0fSWilliam Breathitt Gray static int intel_qep_preset_enable_read(struct counter_device *counter,
325b711f687SJarkko Nikula struct counter_count *count,
326aaec1a0fSWilliam Breathitt Gray u8 *preset_enable)
327b711f687SJarkko Nikula {
32853ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
329b711f687SJarkko Nikula u32 reg;
330b711f687SJarkko Nikula
331b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
332b711f687SJarkko Nikula reg = intel_qep_readl(qep, INTEL_QEPCON);
333b711f687SJarkko Nikula pm_runtime_put(qep->dev);
334aaec1a0fSWilliam Breathitt Gray
335aaec1a0fSWilliam Breathitt Gray *preset_enable = !(reg & INTEL_QEPCON_COUNT_RST_MODE);
336aaec1a0fSWilliam Breathitt Gray
337aaec1a0fSWilliam Breathitt Gray return 0;
338b711f687SJarkko Nikula }
339b711f687SJarkko Nikula
intel_qep_preset_enable_write(struct counter_device * counter,struct counter_count * count,u8 val)340aaec1a0fSWilliam Breathitt Gray static int intel_qep_preset_enable_write(struct counter_device *counter,
341aaec1a0fSWilliam Breathitt Gray struct counter_count *count, u8 val)
342b711f687SJarkko Nikula {
34353ada095SUwe Kleine-König struct intel_qep *qep = counter_priv(counter);
344b711f687SJarkko Nikula u32 reg;
345aaec1a0fSWilliam Breathitt Gray int ret = 0;
346b711f687SJarkko Nikula
347b711f687SJarkko Nikula mutex_lock(&qep->lock);
348b711f687SJarkko Nikula if (qep->enabled) {
349b711f687SJarkko Nikula ret = -EBUSY;
350b711f687SJarkko Nikula goto out;
351b711f687SJarkko Nikula }
352b711f687SJarkko Nikula
353b711f687SJarkko Nikula pm_runtime_get_sync(qep->dev);
354b711f687SJarkko Nikula reg = intel_qep_readl(qep, INTEL_QEPCON);
355b711f687SJarkko Nikula if (val)
356b711f687SJarkko Nikula reg &= ~INTEL_QEPCON_COUNT_RST_MODE;
357b711f687SJarkko Nikula else
358b711f687SJarkko Nikula reg |= INTEL_QEPCON_COUNT_RST_MODE;
359b711f687SJarkko Nikula
360b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, reg);
361b711f687SJarkko Nikula pm_runtime_put(qep->dev);
362b711f687SJarkko Nikula
363b711f687SJarkko Nikula out:
364b711f687SJarkko Nikula mutex_unlock(&qep->lock);
365b711f687SJarkko Nikula
366b711f687SJarkko Nikula return ret;
367b711f687SJarkko Nikula }
368b711f687SJarkko Nikula
369aaec1a0fSWilliam Breathitt Gray static struct counter_comp intel_qep_count_ext[] = {
370aaec1a0fSWilliam Breathitt Gray COUNTER_COMP_ENABLE(intel_qep_enable_read, intel_qep_enable_write),
371aaec1a0fSWilliam Breathitt Gray COUNTER_COMP_CEILING(intel_qep_ceiling_read, intel_qep_ceiling_write),
372aaec1a0fSWilliam Breathitt Gray COUNTER_COMP_PRESET_ENABLE(intel_qep_preset_enable_read,
373aaec1a0fSWilliam Breathitt Gray intel_qep_preset_enable_write),
374aaec1a0fSWilliam Breathitt Gray COUNTER_COMP_COUNT_U64("spike_filter_ns",
375aaec1a0fSWilliam Breathitt Gray intel_qep_spike_filter_ns_read,
376aaec1a0fSWilliam Breathitt Gray intel_qep_spike_filter_ns_write),
377b711f687SJarkko Nikula };
378b711f687SJarkko Nikula
379b711f687SJarkko Nikula static struct counter_count intel_qep_counter_count[] = {
380b711f687SJarkko Nikula {
381b711f687SJarkko Nikula .id = 0,
382b711f687SJarkko Nikula .name = "Channel 1 Count",
383b711f687SJarkko Nikula .functions_list = intel_qep_count_functions,
384b711f687SJarkko Nikula .num_functions = ARRAY_SIZE(intel_qep_count_functions),
385b711f687SJarkko Nikula .synapses = intel_qep_count_synapses,
386b711f687SJarkko Nikula .num_synapses = ARRAY_SIZE(intel_qep_count_synapses),
387b711f687SJarkko Nikula .ext = intel_qep_count_ext,
388b711f687SJarkko Nikula .num_ext = ARRAY_SIZE(intel_qep_count_ext),
389b711f687SJarkko Nikula },
390b711f687SJarkko Nikula };
391b711f687SJarkko Nikula
intel_qep_probe(struct pci_dev * pci,const struct pci_device_id * id)392b711f687SJarkko Nikula static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id)
393b711f687SJarkko Nikula {
394e99dec87SUwe Kleine-König struct counter_device *counter;
395b711f687SJarkko Nikula struct intel_qep *qep;
396b711f687SJarkko Nikula struct device *dev = &pci->dev;
397b711f687SJarkko Nikula void __iomem *regs;
398b711f687SJarkko Nikula int ret;
399b711f687SJarkko Nikula
400e99dec87SUwe Kleine-König counter = devm_counter_alloc(dev, sizeof(*qep));
401e99dec87SUwe Kleine-König if (!counter)
402b711f687SJarkko Nikula return -ENOMEM;
403e99dec87SUwe Kleine-König qep = counter_priv(counter);
404b711f687SJarkko Nikula
405b711f687SJarkko Nikula ret = pcim_enable_device(pci);
406b711f687SJarkko Nikula if (ret)
407b711f687SJarkko Nikula return ret;
408b711f687SJarkko Nikula
409b711f687SJarkko Nikula pci_set_master(pci);
410b711f687SJarkko Nikula
411b711f687SJarkko Nikula ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
412b711f687SJarkko Nikula if (ret)
413b711f687SJarkko Nikula return ret;
414b711f687SJarkko Nikula
415b711f687SJarkko Nikula regs = pcim_iomap_table(pci)[0];
416b711f687SJarkko Nikula if (!regs)
417b711f687SJarkko Nikula return -ENOMEM;
418b711f687SJarkko Nikula
419b711f687SJarkko Nikula qep->dev = dev;
420b711f687SJarkko Nikula qep->regs = regs;
421b711f687SJarkko Nikula mutex_init(&qep->lock);
422b711f687SJarkko Nikula
423b711f687SJarkko Nikula intel_qep_init(qep);
424b711f687SJarkko Nikula pci_set_drvdata(pci, qep);
425b711f687SJarkko Nikula
426e99dec87SUwe Kleine-König counter->name = pci_name(pci);
427e99dec87SUwe Kleine-König counter->parent = dev;
428e99dec87SUwe Kleine-König counter->ops = &intel_qep_counter_ops;
429e99dec87SUwe Kleine-König counter->counts = intel_qep_counter_count;
430e99dec87SUwe Kleine-König counter->num_counts = ARRAY_SIZE(intel_qep_counter_count);
431e99dec87SUwe Kleine-König counter->signals = intel_qep_signals;
432e99dec87SUwe Kleine-König counter->num_signals = ARRAY_SIZE(intel_qep_signals);
433b711f687SJarkko Nikula qep->enabled = false;
434b711f687SJarkko Nikula
435b711f687SJarkko Nikula pm_runtime_put(dev);
436b711f687SJarkko Nikula pm_runtime_allow(dev);
437b711f687SJarkko Nikula
438e99dec87SUwe Kleine-König ret = devm_counter_add(&pci->dev, counter);
439e99dec87SUwe Kleine-König if (ret < 0)
440e99dec87SUwe Kleine-König return dev_err_probe(&pci->dev, ret, "Failed to add counter\n");
441e99dec87SUwe Kleine-König
442e99dec87SUwe Kleine-König return 0;
443b711f687SJarkko Nikula }
444b711f687SJarkko Nikula
intel_qep_remove(struct pci_dev * pci)445b711f687SJarkko Nikula static void intel_qep_remove(struct pci_dev *pci)
446b711f687SJarkko Nikula {
447b711f687SJarkko Nikula struct intel_qep *qep = pci_get_drvdata(pci);
448b711f687SJarkko Nikula struct device *dev = &pci->dev;
449b711f687SJarkko Nikula
450b711f687SJarkko Nikula pm_runtime_forbid(dev);
451b711f687SJarkko Nikula if (!qep->enabled)
452b711f687SJarkko Nikula pm_runtime_get(dev);
453b711f687SJarkko Nikula
454b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, 0);
455b711f687SJarkko Nikula }
456b711f687SJarkko Nikula
intel_qep_suspend(struct device * dev)457ac3bd9d6SJarkko Nikula static int __maybe_unused intel_qep_suspend(struct device *dev)
458b711f687SJarkko Nikula {
45993466212SJarkko Nikula struct pci_dev *pdev = to_pci_dev(dev);
460b711f687SJarkko Nikula struct intel_qep *qep = pci_get_drvdata(pdev);
461b711f687SJarkko Nikula
462b711f687SJarkko Nikula qep->qepcon = intel_qep_readl(qep, INTEL_QEPCON);
463b711f687SJarkko Nikula qep->qepflt = intel_qep_readl(qep, INTEL_QEPFLT);
464b711f687SJarkko Nikula qep->qepmax = intel_qep_readl(qep, INTEL_QEPMAX);
465b711f687SJarkko Nikula
466b711f687SJarkko Nikula return 0;
467b711f687SJarkko Nikula }
468b711f687SJarkko Nikula
intel_qep_resume(struct device * dev)469ac3bd9d6SJarkko Nikula static int __maybe_unused intel_qep_resume(struct device *dev)
470b711f687SJarkko Nikula {
47193466212SJarkko Nikula struct pci_dev *pdev = to_pci_dev(dev);
472b711f687SJarkko Nikula struct intel_qep *qep = pci_get_drvdata(pdev);
473b711f687SJarkko Nikula
474b711f687SJarkko Nikula /*
475b711f687SJarkko Nikula * Make sure peripheral is disabled when restoring registers and
476b711f687SJarkko Nikula * control register bits that are writable only when the peripheral
477b711f687SJarkko Nikula * is disabled
478b711f687SJarkko Nikula */
479b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, 0);
480b711f687SJarkko Nikula intel_qep_readl(qep, INTEL_QEPCON);
481b711f687SJarkko Nikula
482b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPFLT, qep->qepflt);
483b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPMAX, qep->qepmax);
484b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL);
485b711f687SJarkko Nikula
486b711f687SJarkko Nikula /* Restore all other control register bits except enable status */
487b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon & ~INTEL_QEPCON_EN);
488b711f687SJarkko Nikula intel_qep_readl(qep, INTEL_QEPCON);
489b711f687SJarkko Nikula
490b711f687SJarkko Nikula /* Restore enable status */
491b711f687SJarkko Nikula intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon);
492b711f687SJarkko Nikula
493b711f687SJarkko Nikula return 0;
494b711f687SJarkko Nikula }
495b711f687SJarkko Nikula
496b711f687SJarkko Nikula static UNIVERSAL_DEV_PM_OPS(intel_qep_pm_ops,
497b711f687SJarkko Nikula intel_qep_suspend, intel_qep_resume, NULL);
498b711f687SJarkko Nikula
499b711f687SJarkko Nikula static const struct pci_device_id intel_qep_id_table[] = {
500b711f687SJarkko Nikula /* EHL */
501b711f687SJarkko Nikula { PCI_VDEVICE(INTEL, 0x4bc3), },
502b711f687SJarkko Nikula { PCI_VDEVICE(INTEL, 0x4b81), },
503b711f687SJarkko Nikula { PCI_VDEVICE(INTEL, 0x4b82), },
504b711f687SJarkko Nikula { PCI_VDEVICE(INTEL, 0x4b83), },
505b711f687SJarkko Nikula { } /* Terminating Entry */
506b711f687SJarkko Nikula };
507b711f687SJarkko Nikula MODULE_DEVICE_TABLE(pci, intel_qep_id_table);
508b711f687SJarkko Nikula
509b711f687SJarkko Nikula static struct pci_driver intel_qep_driver = {
510b711f687SJarkko Nikula .name = "intel-qep",
511b711f687SJarkko Nikula .id_table = intel_qep_id_table,
512b711f687SJarkko Nikula .probe = intel_qep_probe,
513b711f687SJarkko Nikula .remove = intel_qep_remove,
514b711f687SJarkko Nikula .driver = {
515b711f687SJarkko Nikula .pm = &intel_qep_pm_ops,
516b711f687SJarkko Nikula }
517b711f687SJarkko Nikula };
518b711f687SJarkko Nikula
519b711f687SJarkko Nikula module_pci_driver(intel_qep_driver);
520b711f687SJarkko Nikula
521b711f687SJarkko Nikula MODULE_AUTHOR("Felipe Balbi (Intel)");
522b711f687SJarkko Nikula MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>");
523b711f687SJarkko Nikula MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
524b711f687SJarkko Nikula MODULE_LICENSE("GPL");
525b711f687SJarkko Nikula MODULE_DESCRIPTION("Intel Quadrature Encoder Peripheral driver");
526*3216e551SWilliam Breathitt Gray MODULE_IMPORT_NS(COUNTER);
527