Lines Matching +full:counter +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/counter.h>
25 #define I8254_M GENMASK(3, 1)
32 #define I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT 1
44 * struct i8254 - I8254 device private data structure
46 * @preset: array of Counter Register states
57 static int i8254_count_read(struct counter_device *const counter, struct counter_count *const count, in i8254_count_read() argument
60 struct i8254 *const priv = counter_priv(counter); in i8254_count_read()
64 mutex_lock(&priv->lock); in i8254_count_read()
66 ret = regmap_write(priv->map, I8254_CONTROL_REG, I8254_COUNTER_LATCH(count->id)); in i8254_count_read()
68 mutex_unlock(&priv->lock); in i8254_count_read()
71 ret = regmap_noinc_read(priv->map, I8254_COUNTER_REG(count->id), value, sizeof(value)); in i8254_count_read()
73 mutex_unlock(&priv->lock); in i8254_count_read()
77 mutex_unlock(&priv->lock); in i8254_count_read()
84 static int i8254_function_read(struct counter_device *const counter, in i8254_function_read() argument
94 #define I8254_SIGNAL_ID_GATE 1
96 static int i8254_action_read(struct counter_device *const counter, in i8254_action_read() argument
101 struct i8254 *const priv = counter_priv(counter); in i8254_action_read()
103 switch (synapse->signal->id % I8254_SYNAPSES_PER_COUNT) { in i8254_action_read()
108 switch (priv->out_mode[count->id]) { in i8254_action_read()
121 return -EINVAL; in i8254_action_read()
125 static int i8254_count_ceiling_read(struct counter_device *const counter, in i8254_count_ceiling_read() argument
128 struct i8254 *const priv = counter_priv(counter); in i8254_count_ceiling_read()
130 mutex_lock(&priv->lock); in i8254_count_ceiling_read()
132 switch (priv->out_mode[count->id]) { in i8254_count_ceiling_read()
134 /* Rate Generator decrements 0 by one and the counter "wraps around" */ in i8254_count_ceiling_read()
135 *ceiling = (priv->preset[count->id] == 0) ? U16_MAX : priv->preset[count->id]; in i8254_count_ceiling_read()
138 if (priv->preset[count->id] % 2) in i8254_count_ceiling_read()
139 *ceiling = priv->preset[count->id] - 1; in i8254_count_ceiling_read()
140 else if (priv->preset[count->id] == 0) in i8254_count_ceiling_read()
141 /* Square Wave Mode decrements 0 by two and the counter "wraps around" */ in i8254_count_ceiling_read()
142 *ceiling = U16_MAX - 1; in i8254_count_ceiling_read()
144 *ceiling = priv->preset[count->id]; in i8254_count_ceiling_read()
151 mutex_unlock(&priv->lock); in i8254_count_ceiling_read()
156 static int i8254_count_mode_read(struct counter_device *const counter, in i8254_count_mode_read() argument
160 const struct i8254 *const priv = counter_priv(counter); in i8254_count_mode_read()
162 switch (priv->out_mode[count->id]) { in i8254_count_mode_read()
183 return -EINVAL; in i8254_count_mode_read()
187 static int i8254_count_mode_write(struct counter_device *const counter, in i8254_count_mode_write() argument
191 struct i8254 *const priv = counter_priv(counter); in i8254_count_mode_write()
216 return -EINVAL; in i8254_count_mode_write()
219 mutex_lock(&priv->lock); in i8254_count_mode_write()
221 /* Counter Register is cleared when the counter is programmed */ in i8254_count_mode_write()
222 priv->preset[count->id] = 0; in i8254_count_mode_write()
223 priv->out_mode[count->id] = out_mode; in i8254_count_mode_write()
224 ret = regmap_write(priv->map, I8254_CONTROL_REG, in i8254_count_mode_write()
225 I8254_PROGRAM_COUNTER(count->id, out_mode)); in i8254_count_mode_write()
227 mutex_unlock(&priv->lock); in i8254_count_mode_write()
232 static int i8254_count_floor_read(struct counter_device *const counter, in i8254_count_floor_read() argument
235 struct i8254 *const priv = counter_priv(counter); in i8254_count_floor_read()
237 mutex_lock(&priv->lock); in i8254_count_floor_read()
239 switch (priv->out_mode[count->id]) { in i8254_count_floor_read()
241 /* counter is always reloaded after 1, but 0 is a possible reload value */ in i8254_count_floor_read()
242 *floor = (priv->preset[count->id] == 0) ? 0 : 1; in i8254_count_floor_read()
245 /* counter is always reloaded after 2 for even preset values */ in i8254_count_floor_read()
246 *floor = (priv->preset[count->id] % 2 || priv->preset[count->id] == 0) ? 0 : 2; in i8254_count_floor_read()
253 mutex_unlock(&priv->lock); in i8254_count_floor_read()
258 static int i8254_count_preset_read(struct counter_device *const counter, in i8254_count_preset_read() argument
261 const struct i8254 *const priv = counter_priv(counter); in i8254_count_preset_read()
263 *preset = priv->preset[count->id]; in i8254_count_preset_read()
268 static int i8254_count_preset_write(struct counter_device *const counter, in i8254_count_preset_write() argument
271 struct i8254 *const priv = counter_priv(counter); in i8254_count_preset_write()
276 return -ERANGE; in i8254_count_preset_write()
278 mutex_lock(&priv->lock); in i8254_count_preset_write()
280 if (priv->out_mode[count->id] == I8254_MODE_RATE_GENERATOR || in i8254_count_preset_write()
281 priv->out_mode[count->id] == I8254_MODE_SQUARE_WAVE_MODE) { in i8254_count_preset_write()
282 if (preset == 1) { in i8254_count_preset_write()
283 mutex_unlock(&priv->lock); in i8254_count_preset_write()
284 return -EINVAL; in i8254_count_preset_write()
288 priv->preset[count->id] = preset; in i8254_count_preset_write()
291 ret = regmap_noinc_write(priv->map, I8254_COUNTER_REG(count->id), value, 2); in i8254_count_preset_write()
293 mutex_unlock(&priv->lock); in i8254_count_preset_write()
304 /* Initialize each counter to Mode 0 */ in i8254_init_hw()
326 I8254_SIGNAL(0, "CLK 0"), I8254_SIGNAL(1, "GATE 0"),
327 I8254_SIGNAL(2, "CLK 1"), I8254_SIGNAL(3, "GATE 1"),
348 .signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 1], \
353 I8254_SYNAPSE_CLK(1), I8254_SYNAPSE_GATE(1),
392 I8254_COUNT(0, "Counter 0"), I8254_COUNT(1, "Counter 1"), I8254_COUNT(2, "Counter 2"),
396 * devm_i8254_regmap_register - Register an i8254 Counter device
397 * @dev: device that is registering this i8254 Counter device
400 * Registers an Intel 8254 Programmable Interval Timer Counter device. Returns 0 on success and
406 struct counter_device *counter; in devm_i8254_regmap_register() local
410 if (!config->parent) in devm_i8254_regmap_register()
411 return -EINVAL; in devm_i8254_regmap_register()
413 if (!config->map) in devm_i8254_regmap_register()
414 return -EINVAL; in devm_i8254_regmap_register()
416 counter = devm_counter_alloc(dev, sizeof(*priv)); in devm_i8254_regmap_register()
417 if (!counter) in devm_i8254_regmap_register()
418 return -ENOMEM; in devm_i8254_regmap_register()
419 priv = counter_priv(counter); in devm_i8254_regmap_register()
420 priv->map = config->map; in devm_i8254_regmap_register()
422 counter->name = dev_name(config->parent); in devm_i8254_regmap_register()
423 counter->parent = config->parent; in devm_i8254_regmap_register()
424 counter->ops = &i8254_ops; in devm_i8254_regmap_register()
425 counter->counts = i8254_counts; in devm_i8254_regmap_register()
426 counter->num_counts = ARRAY_SIZE(i8254_counts); in devm_i8254_regmap_register()
427 counter->signals = i8254_signals; in devm_i8254_regmap_register()
428 counter->num_signals = ARRAY_SIZE(i8254_signals); in devm_i8254_regmap_register()
430 mutex_init(&priv->lock); in devm_i8254_regmap_register()
432 err = i8254_init_hw(priv->map); in devm_i8254_regmap_register()
436 err = devm_counter_add(dev, counter); in devm_i8254_regmap_register()
438 return dev_err_probe(dev, err, "Failed to add counter\n"); in devm_i8254_regmap_register()
447 MODULE_IMPORT_NS(COUNTER);