diff options
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/Makefile | 8 | ||||
-rw-r--r-- | drivers/sh/clk/core.c | 123 | ||||
-rw-r--r-- | drivers/sh/intc/chip.c | 12 | ||||
-rw-r--r-- | drivers/sh/intc/core.c | 2 | ||||
-rw-r--r-- | drivers/sh/intc/dynamic.c | 1 | ||||
-rw-r--r-- | drivers/sh/intc/userimask.c | 1 | ||||
-rw-r--r-- | drivers/sh/intc/virq.c | 1 | ||||
-rw-r--r-- | drivers/sh/maple/maple.c | 1 | ||||
-rw-r--r-- | drivers/sh/pfc.c | 29 |
9 files changed, 91 insertions, 87 deletions
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 24e6cec..67e272a 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -7,3 +7,11 @@ obj-$(CONFIG_HAVE_CLK) += clk/ obj-$(CONFIG_MAPLE) += maple/ obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_GENERIC_GPIO) += pfc.o + +# +# For the moment we only use this framework for ARM-based SH/R-Mobile +# platforms and generic SH. SH-based SH-Mobile platforms are still using +# an older framework that is pending up-porting, at which point this +# special casing can go away. +# +obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 7e9c399..db257a3 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -25,7 +25,6 @@ #include <linux/seq_file.h> #include <linux/err.h> #include <linux/io.h> -#include <linux/debugfs.h> #include <linux/cpufreq.h> #include <linux/clk.h> #include <linux/sh_clk.h> @@ -34,6 +33,9 @@ static LIST_HEAD(clock_list); static DEFINE_SPINLOCK(clock_lock); static DEFINE_MUTEX(clock_list_sem); +/* clock disable operations are not passed on to hardware during boot */ +static int allow_disable; + void clk_rate_table_build(struct clk *clk, struct cpufreq_frequency_table *freq_table, int nr_freqs, @@ -170,6 +172,26 @@ long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, return clk_rate_round_helper(&div_range_round); } +static long clk_rate_mult_range_iter(unsigned int pos, + struct clk_rate_round_data *rounder) +{ + return clk_get_rate(rounder->arg) * pos; +} + +long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min, + unsigned int mult_max, unsigned long rate) +{ + struct clk_rate_round_data mult_range_round = { + .min = mult_min, + .max = mult_max, + .func = clk_rate_mult_range_iter, + .arg = clk_get_parent(clk), + .rate = rate, + }; + + return clk_rate_round_helper(&mult_range_round); +} + int clk_rate_table_find(struct clk *clk, struct cpufreq_frequency_table *freq_table, unsigned long rate) @@ -202,9 +224,6 @@ int clk_reparent(struct clk *child, struct clk *parent) list_add(&child->sibling, &parent->children); child->parent = parent; - /* now do the debugfs renaming to reattach the child - to the proper parent */ - return 0; } @@ -228,7 +247,7 @@ static void __clk_disable(struct clk *clk) return; if (!(--clk->usecount)) { - if (likely(clk->ops && clk->ops->disable)) + if (likely(allow_disable && clk->ops && clk->ops->disable)) clk->ops->disable(clk); if (likely(clk->parent)) __clk_disable(clk->parent); @@ -393,7 +412,7 @@ int clk_register(struct clk *clk) { int ret; - if (clk == NULL || IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) return -EINVAL; /* @@ -662,88 +681,24 @@ static int __init clk_syscore_init(void) subsys_initcall(clk_syscore_init); #endif -/* - * debugfs support to trace clock tree hierarchy and attributes - */ -static struct dentry *clk_debugfs_root; - -static int clk_debugfs_register_one(struct clk *c) -{ - int err; - struct dentry *d, *child, *child_tmp; - struct clk *pa = c->parent; - char s[255]; - char *p = s; - - p += sprintf(p, "%p", c); - d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root); - if (!d) - return -ENOMEM; - c->dentry = d; - - d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount); - if (!d) { - err = -ENOMEM; - goto err_out; - } - d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate); - if (!d) { - err = -ENOMEM; - goto err_out; - } - d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags); - if (!d) { - err = -ENOMEM; - goto err_out; - } - return 0; - -err_out: - d = c->dentry; - list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) - debugfs_remove(child); - debugfs_remove(c->dentry); - return err; -} - -static int clk_debugfs_register(struct clk *c) +static int __init clk_late_init(void) { - int err; - struct clk *pa = c->parent; - - if (pa && !pa->dentry) { - err = clk_debugfs_register(pa); - if (err) - return err; - } + unsigned long flags; + struct clk *clk; - if (!c->dentry) { - err = clk_debugfs_register_one(c); - if (err) - return err; - } - return 0; -} + /* disable all clocks with zero use count */ + mutex_lock(&clock_list_sem); + spin_lock_irqsave(&clock_lock, flags); -static int __init clk_debugfs_init(void) -{ - struct clk *c; - struct dentry *d; - int err; + list_for_each_entry(clk, &clock_list, node) + if (!clk->usecount && clk->ops && clk->ops->disable) + clk->ops->disable(clk); - d = debugfs_create_dir("clock", NULL); - if (!d) - return -ENOMEM; - clk_debugfs_root = d; + /* from now on allow clock disable operations */ + allow_disable = 1; - list_for_each_entry(c, &clock_list, node) { - err = clk_debugfs_register(c); - if (err) - goto err_out; - } + spin_unlock_irqrestore(&clock_lock, flags); + mutex_unlock(&clock_list_sem); return 0; -err_out: - debugfs_remove_recursive(clk_debugfs_root); - return err; } -late_initcall(clk_debugfs_init); +late_initcall(clk_late_init); diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c index f33e2dd..7b246ef 100644 --- a/drivers/sh/intc/chip.c +++ b/drivers/sh/intc/chip.c @@ -186,6 +186,9 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { !defined(CONFIG_CPU_SUBTYPE_SH7709) [IRQ_TYPE_LEVEL_HIGH] = VALID(3), #endif +#if defined(CONFIG_ARM) /* all recent SH-Mobile / R-Mobile ARM support this */ + [IRQ_TYPE_EDGE_BOTH] = VALID(4), +#endif }; static int intc_set_type(struct irq_data *data, unsigned int type) @@ -199,11 +202,16 @@ static int intc_set_type(struct irq_data *data, unsigned int type) if (!value) return -EINVAL; + value &= ~SENSE_VALID_FLAG; + ihp = intc_find_irq(d->sense, d->nr_sense, irq); if (ihp) { + /* PINT has 2-bit sense registers, should fail on EDGE_BOTH */ + if (value >= (1 << _INTC_WIDTH(ihp->handle))) + return -EINVAL; + addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0); - intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, - value & ~SENSE_VALID_FLAG); + intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value); } return 0; diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index c6ca115..8b7a141 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -22,6 +22,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/stat.h> #include <linux/interrupt.h> #include <linux/sh_intc.h> #include <linux/sysdev.h> @@ -29,6 +30,7 @@ #include <linux/list.h> #include <linux/spinlock.h> #include <linux/radix-tree.h> +#include <linux/export.h> #include "internals.h" LIST_HEAD(intc_list); diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c index a3677c9..5fea1ee 100644 --- a/drivers/sh/intc/dynamic.c +++ b/drivers/sh/intc/dynamic.c @@ -14,6 +14,7 @@ #include <linux/irq.h> #include <linux/bitmap.h> #include <linux/spinlock.h> +#include <linux/module.h> #include "internals.h" /* only for activate_irq() damage.. */ /* diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c index e32304b..56bf933 100644 --- a/drivers/sh/intc/userimask.c +++ b/drivers/sh/intc/userimask.c @@ -13,6 +13,7 @@ #include <linux/sysdev.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/stat.h> #include <asm/sizes.h> #include "internals.h" diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c index 1e6e2d0..c7ec49f 100644 --- a/drivers/sh/intc/virq.c +++ b/drivers/sh/intc/virq.c @@ -14,6 +14,7 @@ #include <linux/list.h> #include <linux/radix-tree.h> #include <linux/spinlock.h> +#include <linux/export.h> #include "internals.h" static struct intc_map_entry intc_irq_xlate[NR_IRQS]; diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 1e20604..bec81c2 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -20,6 +20,7 @@ #include <linux/maple.h> #include <linux/dma-mapping.h> #include <linux/delay.h> +#include <linux/module.h> #include <asm/cacheflush.h> #include <asm/dma.h> #include <asm/io.h> diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c index 75934e3..e67fe17 100644 --- a/drivers/sh/pfc.c +++ b/drivers/sh/pfc.c @@ -217,7 +217,7 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, if (!r_width) break; - for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) { + for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) { if (config_reg->enum_ids[n] == enum_id) { *crp = config_reg; *indexp = n; @@ -577,6 +577,32 @@ static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value) sh_gpio_set_value(chip_to_pinmux(chip), offset, value); } +static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct pinmux_info *gpioc = chip_to_pinmux(chip); + pinmux_enum_t enum_id; + pinmux_enum_t *enum_ids; + int i, k, pos; + + pos = 0; + enum_id = 0; + while (1) { + pos = get_gpio_enum_id(gpioc, offset, pos, &enum_id); + if (pos <= 0 || !enum_id) + break; + + for (i = 0; i < gpioc->gpio_irq_size; i++) { + enum_ids = gpioc->gpio_irq[i].enum_ids; + for (k = 0; enum_ids[k]; k++) { + if (enum_ids[k] == enum_id) + return gpioc->gpio_irq[i].irq; + } + } + } + + return -ENOSYS; +} + int register_pinmux(struct pinmux_info *pip) { struct gpio_chip *chip = &pip->chip; @@ -592,6 +618,7 @@ int register_pinmux(struct pinmux_info *pip) chip->get = sh_gpio_get; chip->direction_output = sh_gpio_direction_output; chip->set = sh_gpio_set; + chip->to_irq = sh_gpio_to_irq; WARN_ON(pip->first_gpio != 0); /* needs testing */ |