aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/core.c
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2012-03-26 02:42:48 -0400
committerThierry Reding <thierry.reding@avionic-design.de>2012-06-15 06:56:53 -0400
commit8138d2ddbcca2a100482dac390133f83c5a60f94 (patch)
tree814645a7608376af451f9721dd3da585a87bbdd6 /drivers/pwm/core.c
parent62099abf67a20cfb98d4c031fb1925e10a78ee1b (diff)
pwm: Add table-based lookup for static mappings
In order to get rid of the global namespace for PWM devices, this commit provides an alternative method, similar to that of the regulator or clock frameworks, for registering a static mapping for PWM devices. This works by providing a table with a provider/consumer map in the board setup code. With the new pwm_get() and pwm_put() functions available, usage of pwm_request() and pwm_free() becomes deprecated. Reviewed-by: Shawn Guo <shawn.guo@linaro.org> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/pwm/core.c')
-rw-r--r--drivers/pwm/core.c169
1 files changed, 154 insertions, 15 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index aadc1d797449..a2af599e61ae 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -32,6 +32,8 @@
32 32
33#define MAX_PWMS 1024 33#define MAX_PWMS 1024
34 34
35static DEFINE_MUTEX(pwm_lookup_lock);
36static LIST_HEAD(pwm_lookup_list);
35static DEFINE_MUTEX(pwm_lock); 37static DEFINE_MUTEX(pwm_lock);
36static LIST_HEAD(pwm_chips); 38static LIST_HEAD(pwm_chips);
37static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); 39static DECLARE_BITMAP(allocated_pwms, MAX_PWMS);
@@ -80,6 +82,29 @@ static void free_pwms(struct pwm_chip *chip)
80 chip->pwms = NULL; 82 chip->pwms = NULL;
81} 83}
82 84
85static struct pwm_chip *pwmchip_find_by_name(const char *name)
86{
87 struct pwm_chip *chip;
88
89 if (!name)
90 return NULL;
91
92 mutex_lock(&pwm_lock);
93
94 list_for_each_entry(chip, &pwm_chips, list) {
95 const char *chip_name = dev_name(chip->dev);
96
97 if (chip_name && strcmp(chip_name, name) == 0) {
98 mutex_unlock(&pwm_lock);
99 return chip;
100 }
101 }
102
103 mutex_unlock(&pwm_lock);
104
105 return NULL;
106}
107
83static int pwm_device_request(struct pwm_device *pwm, const char *label) 108static int pwm_device_request(struct pwm_device *pwm, const char *label)
84{ 109{
85 int err; 110 int err;
@@ -218,6 +243,8 @@ EXPORT_SYMBOL_GPL(pwmchip_remove);
218 * pwm_request() - request a PWM device 243 * pwm_request() - request a PWM device
219 * @pwm_id: global PWM device index 244 * @pwm_id: global PWM device index
220 * @label: PWM device label 245 * @label: PWM device label
246 *
247 * This function is deprecated, use pwm_get() instead.
221 */ 248 */
222struct pwm_device *pwm_request(int pwm, const char *label) 249struct pwm_device *pwm_request(int pwm, const char *label)
223{ 250{
@@ -281,24 +308,12 @@ EXPORT_SYMBOL_GPL(pwm_request_from_chip);
281/** 308/**
282 * pwm_free() - free a PWM device 309 * pwm_free() - free a PWM device
283 * @pwm: PWM device 310 * @pwm: PWM device
311 *
312 * This function is deprecated, use pwm_put() instead.
284 */ 313 */
285void pwm_free(struct pwm_device *pwm) 314void pwm_free(struct pwm_device *pwm)
286{ 315{
287 mutex_lock(&pwm_lock); 316 pwm_put(pwm);
288
289 if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) {
290 pr_warning("PWM device already freed\n");
291 goto out;
292 }
293
294 if (pwm->chip->ops->free)
295 pwm->chip->ops->free(pwm->chip, pwm);
296
297 pwm->label = NULL;
298
299 module_put(pwm->chip->ops->owner);
300out:
301 mutex_unlock(&pwm_lock);
302} 317}
303EXPORT_SYMBOL_GPL(pwm_free); 318EXPORT_SYMBOL_GPL(pwm_free);
304 319
@@ -341,6 +356,130 @@ void pwm_disable(struct pwm_device *pwm)
341} 356}
342EXPORT_SYMBOL_GPL(pwm_disable); 357EXPORT_SYMBOL_GPL(pwm_disable);
343 358
359/**
360 * pwm_add_table() - register PWM device consumers
361 * @table: array of consumers to register
362 * @num: number of consumers in table
363 */
364void __init pwm_add_table(struct pwm_lookup *table, size_t num)
365{
366 mutex_lock(&pwm_lookup_lock);
367
368 while (num--) {
369 list_add_tail(&table->list, &pwm_lookup_list);
370 table++;
371 }
372
373 mutex_unlock(&pwm_lookup_lock);
374}
375
376/**
377 * pwm_get() - look up and request a PWM device
378 * @dev: device for PWM consumer
379 * @con_id: consumer name
380 *
381 * Look up a PWM chip and a relative index via a table supplied by board setup
382 * code (see pwm_add_table()).
383 *
384 * Once a PWM chip has been found the specified PWM device will be requested
385 * and is ready to be used.
386 */
387struct pwm_device *pwm_get(struct device *dev, const char *con_id)
388{
389 struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER);
390 const char *dev_id = dev ? dev_name(dev): NULL;
391 struct pwm_chip *chip = NULL;
392 unsigned int best = 0;
393 struct pwm_lookup *p;
394 unsigned int index;
395 unsigned int match;
396
397 /*
398 * We look up the provider in the static table typically provided by
399 * board setup code. We first try to lookup the consumer device by
400 * name. If the consumer device was passed in as NULL or if no match
401 * was found, we try to find the consumer by directly looking it up
402 * by name.
403 *
404 * If a match is found, the provider PWM chip is looked up by name
405 * and a PWM device is requested using the PWM device per-chip index.
406 *
407 * The lookup algorithm was shamelessly taken from the clock
408 * framework:
409 *
410 * We do slightly fuzzy matching here:
411 * An entry with a NULL ID is assumed to be a wildcard.
412 * If an entry has a device ID, it must match
413 * If an entry has a connection ID, it must match
414 * Then we take the most specific entry - with the following order
415 * of precedence: dev+con > dev only > con only.
416 */
417 mutex_lock(&pwm_lookup_lock);
418
419 list_for_each_entry(p, &pwm_lookup_list, list) {
420 match = 0;
421
422 if (p->dev_id) {
423 if (!dev_id || strcmp(p->dev_id, dev_id))
424 continue;
425
426 match += 2;
427 }
428
429 if (p->con_id) {
430 if (!con_id || strcmp(p->con_id, con_id))
431 continue;
432
433 match += 1;
434 }
435
436 if (match > best) {
437 chip = pwmchip_find_by_name(p->provider);
438 index = p->index;
439
440 if (match != 3)
441 best = match;
442 else
443 break;
444 }
445 }
446
447 if (chip)
448 pwm = pwm_request_from_chip(chip, index, con_id ?: dev_id);
449
450 mutex_unlock(&pwm_lookup_lock);
451
452 return pwm;
453}
454EXPORT_SYMBOL_GPL(pwm_get);
455
456/**
457 * pwm_put() - release a PWM device
458 * @pwm: PWM device
459 */
460void pwm_put(struct pwm_device *pwm)
461{
462 if (!pwm)
463 return;
464
465 mutex_lock(&pwm_lock);
466
467 if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) {
468 pr_warning("PWM device already freed\n");
469 goto out;
470 }
471
472 if (pwm->chip->ops->free)
473 pwm->chip->ops->free(pwm->chip, pwm);
474
475 pwm->label = NULL;
476
477 module_put(pwm->chip->ops->owner);
478out:
479 mutex_unlock(&pwm_lock);
480}
481EXPORT_SYMBOL_GPL(pwm_put);
482
344#ifdef CONFIG_DEBUG_FS 483#ifdef CONFIG_DEBUG_FS
345static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) 484static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
346{ 485{