aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sh')
-rw-r--r--drivers/sh/clk/core.c96
-rw-r--r--drivers/sh/intc/core.c2
-rw-r--r--drivers/sh/intc/dynamic.c2
3 files changed, 96 insertions, 4 deletions
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index fd0d1b98901c..09615b51d591 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -90,8 +90,8 @@ struct clk_rate_round_data {
90static long clk_rate_round_helper(struct clk_rate_round_data *rounder) 90static long clk_rate_round_helper(struct clk_rate_round_data *rounder)
91{ 91{
92 unsigned long rate_error, rate_error_prev = ~0UL; 92 unsigned long rate_error, rate_error_prev = ~0UL;
93 unsigned long rate_best_fit = rounder->rate;
94 unsigned long highest, lowest, freq; 93 unsigned long highest, lowest, freq;
94 long rate_best_fit = -ENOENT;
95 int i; 95 int i;
96 96
97 highest = 0; 97 highest = 0;
@@ -146,7 +146,7 @@ long clk_rate_table_round(struct clk *clk,
146 }; 146 };
147 147
148 if (clk->nr_freqs < 1) 148 if (clk->nr_freqs < 1)
149 return 0; 149 return -ENOSYS;
150 150
151 return clk_rate_round_helper(&table_round); 151 return clk_rate_round_helper(&table_round);
152} 152}
@@ -541,6 +541,98 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
541} 541}
542EXPORT_SYMBOL_GPL(clk_round_rate); 542EXPORT_SYMBOL_GPL(clk_round_rate);
543 543
544long clk_round_parent(struct clk *clk, unsigned long target,
545 unsigned long *best_freq, unsigned long *parent_freq,
546 unsigned int div_min, unsigned int div_max)
547{
548 struct cpufreq_frequency_table *freq, *best = NULL;
549 unsigned long error = ULONG_MAX, freq_high, freq_low, div;
550 struct clk *parent = clk_get_parent(clk);
551
552 if (!parent) {
553 *parent_freq = 0;
554 *best_freq = clk_round_rate(clk, target);
555 return abs(target - *best_freq);
556 }
557
558 for (freq = parent->freq_table; freq->frequency != CPUFREQ_TABLE_END;
559 freq++) {
560 if (freq->frequency == CPUFREQ_ENTRY_INVALID)
561 continue;
562
563 if (unlikely(freq->frequency / target <= div_min - 1)) {
564 unsigned long freq_max;
565
566 freq_max = (freq->frequency + div_min / 2) / div_min;
567 if (error > target - freq_max) {
568 error = target - freq_max;
569 best = freq;
570 if (best_freq)
571 *best_freq = freq_max;
572 }
573
574 pr_debug("too low freq %lu, error %lu\n", freq->frequency,
575 target - freq_max);
576
577 if (!error)
578 break;
579
580 continue;
581 }
582
583 if (unlikely(freq->frequency / target >= div_max)) {
584 unsigned long freq_min;
585
586 freq_min = (freq->frequency + div_max / 2) / div_max;
587 if (error > freq_min - target) {
588 error = freq_min - target;
589 best = freq;
590 if (best_freq)
591 *best_freq = freq_min;
592 }
593
594 pr_debug("too high freq %lu, error %lu\n", freq->frequency,
595 freq_min - target);
596
597 if (!error)
598 break;
599
600 continue;
601 }
602
603 div = freq->frequency / target;
604 freq_high = freq->frequency / div;
605 freq_low = freq->frequency / (div + 1);
606
607 if (freq_high - target < error) {
608 error = freq_high - target;
609 best = freq;
610 if (best_freq)
611 *best_freq = freq_high;
612 }
613
614 if (target - freq_low < error) {
615 error = target - freq_low;
616 best = freq;
617 if (best_freq)
618 *best_freq = freq_low;
619 }
620
621 pr_debug("%u / %lu = %lu, / %lu = %lu, best %lu, parent %u\n",
622 freq->frequency, div, freq_high, div + 1, freq_low,
623 *best_freq, best->frequency);
624
625 if (!error)
626 break;
627 }
628
629 if (parent_freq)
630 *parent_freq = best->frequency;
631
632 return error;
633}
634EXPORT_SYMBOL_GPL(clk_round_parent);
635
544#ifdef CONFIG_PM 636#ifdef CONFIG_PM
545static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) 637static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
546{ 638{
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 873a99ff8f64..e5e9e6735f7d 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -79,7 +79,7 @@ static void __init intc_register_irq(struct intc_desc *desc,
79 * Register the IRQ position with the global IRQ map, then insert 79 * Register the IRQ position with the global IRQ map, then insert
80 * it in to the radix tree. 80 * it in to the radix tree.
81 */ 81 */
82 irq_reserve_irqs(irq, 1); 82 irq_reserve_irq(irq);
83 83
84 raw_spin_lock_irqsave(&intc_big_lock, flags); 84 raw_spin_lock_irqsave(&intc_big_lock, flags);
85 radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq)); 85 radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq));
diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
index 4187cce20ffd..a3677c9dfe36 100644
--- a/drivers/sh/intc/dynamic.c
+++ b/drivers/sh/intc/dynamic.c
@@ -60,5 +60,5 @@ void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs)
60 int i; 60 int i;
61 61
62 for (i = 0; i < nr_vecs; i++) 62 for (i = 0; i < nr_vecs; i++)
63 irq_reserve_irqs(evt2irq(vectors[i].vect), 1); 63 irq_reserve_irq(evt2irq(vectors[i].vect));
64} 64}