Now that arch/sh is removed these drivers are dead code. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- drivers/Makefile | 1 - drivers/sh/Kconfig | 6 - drivers/sh/Makefile | 12 - drivers/sh/clk/Makefile | 4 - drivers/sh/clk/core.c | 624 ---------------- drivers/sh/clk/cpg.c | 477 ------------ drivers/sh/intc/Kconfig | 44 -- drivers/sh/intc/Makefile | 6 - drivers/sh/intc/access.c | 246 ------- drivers/sh/intc/balancing.c | 97 --- drivers/sh/intc/chip.c | 211 ------ drivers/sh/intc/core.c | 501 ------------- drivers/sh/intc/handle.c | 306 -------- drivers/sh/intc/internals.h | 191 ----- drivers/sh/intc/irqdomain.c | 68 -- drivers/sh/intc/userimask.c | 84 --- drivers/sh/intc/virq-debugfs.c | 54 -- drivers/sh/intc/virq.c | 269 ------- drivers/sh/maple/Makefile | 4 - drivers/sh/maple/maple.c | 895 ----------------------- drivers/sh/pm_runtime.c | 40 - drivers/sh/superhyway/Makefile | 8 - drivers/sh/superhyway/superhyway-sysfs.c | 54 -- drivers/sh/superhyway/superhyway.c | 234 ------ include/linux/sh_clk.h | 213 ------ include/linux/superhyway.h | 107 --- 26 files changed, 4756 deletions(-) delete mode 100644 drivers/sh/Kconfig delete mode 100644 drivers/sh/Makefile delete mode 100644 drivers/sh/clk/Makefile delete mode 100644 drivers/sh/clk/core.c delete mode 100644 drivers/sh/clk/cpg.c delete mode 100644 drivers/sh/intc/Kconfig delete mode 100644 drivers/sh/intc/Makefile delete mode 100644 drivers/sh/intc/access.c delete mode 100644 drivers/sh/intc/balancing.c delete mode 100644 drivers/sh/intc/chip.c delete mode 100644 drivers/sh/intc/core.c delete mode 100644 drivers/sh/intc/handle.c delete mode 100644 drivers/sh/intc/internals.h delete mode 100644 drivers/sh/intc/irqdomain.c delete mode 100644 drivers/sh/intc/userimask.c delete mode 100644 drivers/sh/intc/virq-debugfs.c delete mode 100644 drivers/sh/intc/virq.c delete mode 100644 drivers/sh/maple/Makefile delete mode 100644 drivers/sh/maple/maple.c delete mode 100644 drivers/sh/pm_runtime.c delete mode 100644 drivers/sh/superhyway/Makefile delete mode 100644 drivers/sh/superhyway/superhyway-sysfs.c delete mode 100644 drivers/sh/superhyway/superhyway.c delete mode 100644 include/linux/sh_clk.h delete mode 100644 include/linux/superhyway.h diff --git a/drivers/Makefile b/drivers/Makefile index bdf1c66141c9bd..b97a69a4c40b91 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -134,7 +134,6 @@ obj-$(CONFIG_NEW_LEDS) += leds/ obj-$(CONFIG_INFINIBAND) += infiniband/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ -obj-$(CONFIG_SUPERH) += sh/ obj-y += clocksource/ obj-$(CONFIG_DCA) += dca/ obj-$(CONFIG_HID) += hid/ diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig deleted file mode 100644 index 3588fcc9c0d23b..00000000000000 --- a/drivers/sh/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menu "SuperH / SH-Mobile Driver Options" - -source "drivers/sh/intc/Kconfig" - -endmenu diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile deleted file mode 100644 index c53262835e85e2..00000000000000 --- a/drivers/sh/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the SuperH specific drivers. -# -obj-$(CONFIG_SH_INTC) += intc/ -ifneq ($(CONFIG_COMMON_CLK),y) -obj-$(CONFIG_HAVE_CLK) += clk/ -endif -obj-$(CONFIG_MAPLE) += maple/ -obj-$(CONFIG_SUPERHYWAY) += superhyway/ - -obj-y += pm_runtime.o diff --git a/drivers/sh/clk/Makefile b/drivers/sh/clk/Makefile deleted file mode 100644 index 0158ff3ba9d544..00000000000000 --- a/drivers/sh/clk/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y := core.o - -obj-$(CONFIG_SH_CLK_CPG) += cpg.o diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c deleted file mode 100644 index d996782a710642..00000000000000 --- a/drivers/sh/clk/core.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * SuperH clock framework - * - * Copyright (C) 2005 - 2010 Paul Mundt - * - * This clock framework is derived from the OMAP version by: - * - * Copyright (C) 2004 - 2008 Nokia Corporation - * Written by Tuukka Tikkanen <tuukka.tikkanen@xxxxxxxxxxxxxx> - * - * Modified for omap shared clock framework by Tony Lindgren <tony@xxxxxxxxxxx> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "clock: " fmt - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/list.h> -#include <linux/syscore_ops.h> -#include <linux/seq_file.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/cpufreq.h> -#include <linux/clk.h> -#include <linux/sh_clk.h> - -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, - struct clk_div_mult_table *src_table, - unsigned long *bitmap) -{ - unsigned long mult, div; - unsigned long freq; - int i; - - clk->nr_freqs = nr_freqs; - - for (i = 0; i < nr_freqs; i++) { - div = 1; - mult = 1; - - if (src_table->divisors && i < src_table->nr_divisors) - div = src_table->divisors[i]; - - if (src_table->multipliers && i < src_table->nr_multipliers) - mult = src_table->multipliers[i]; - - if (!div || !mult || (bitmap && !test_bit(i, bitmap))) - freq = CPUFREQ_ENTRY_INVALID; - else - freq = clk->parent->rate * mult / div; - - freq_table[i].driver_data = i; - freq_table[i].frequency = freq; - } - - /* Termination entry */ - freq_table[i].driver_data = i; - freq_table[i].frequency = CPUFREQ_TABLE_END; -} - -struct clk_rate_round_data; - -struct clk_rate_round_data { - unsigned long rate; - unsigned int min, max; - long (*func)(unsigned int, struct clk_rate_round_data *); - void *arg; -}; - -#define for_each_frequency(pos, r, freq) \ - for (pos = r->min, freq = r->func(pos, r); \ - pos <= r->max; pos++, freq = r->func(pos, r)) \ - if (unlikely(freq == 0)) \ - ; \ - else - -static long clk_rate_round_helper(struct clk_rate_round_data *rounder) -{ - unsigned long rate_error, rate_error_prev = ~0UL; - unsigned long highest, lowest, freq; - long rate_best_fit = -ENOENT; - int i; - - highest = 0; - lowest = ~0UL; - - for_each_frequency(i, rounder, freq) { - if (freq > highest) - highest = freq; - if (freq < lowest) - lowest = freq; - - rate_error = abs(freq - rounder->rate); - if (rate_error < rate_error_prev) { - rate_best_fit = freq; - rate_error_prev = rate_error; - } - - if (rate_error == 0) - break; - } - - if (rounder->rate >= highest) - rate_best_fit = highest; - if (rounder->rate <= lowest) - rate_best_fit = lowest; - - return rate_best_fit; -} - -static long clk_rate_table_iter(unsigned int pos, - struct clk_rate_round_data *rounder) -{ - struct cpufreq_frequency_table *freq_table = rounder->arg; - unsigned long freq = freq_table[pos].frequency; - - if (freq == CPUFREQ_ENTRY_INVALID) - freq = 0; - - return freq; -} - -long clk_rate_table_round(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate) -{ - struct clk_rate_round_data table_round = { - .min = 0, - .max = clk->nr_freqs - 1, - .func = clk_rate_table_iter, - .arg = freq_table, - .rate = rate, - }; - - if (clk->nr_freqs < 1) - return -ENOSYS; - - return clk_rate_round_helper(&table_round); -} - -static long clk_rate_div_range_iter(unsigned int pos, - struct clk_rate_round_data *rounder) -{ - return clk_get_rate(rounder->arg) / pos; -} - -long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, - unsigned int div_max, unsigned long rate) -{ - struct clk_rate_round_data div_range_round = { - .min = div_min, - .max = div_max, - .func = clk_rate_div_range_iter, - .arg = clk_get_parent(clk), - .rate = rate, - }; - - 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) -{ - struct cpufreq_frequency_table *pos; - int idx; - - cpufreq_for_each_valid_entry_idx(pos, freq_table, idx) - if (pos->frequency == rate) - return idx; - - return -ENOENT; -} - -/* Used for clocks that always have same value as the parent clock */ -unsigned long followparent_recalc(struct clk *clk) -{ - return clk->parent ? clk->parent->rate : 0; -} - -int clk_reparent(struct clk *child, struct clk *parent) -{ - list_del_init(&child->sibling); - if (parent) - list_add(&child->sibling, &parent->children); - child->parent = parent; - - return 0; -} - -/* Propagate rate to children */ -void propagate_rate(struct clk *tclk) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &tclk->children, sibling) { - if (clkp->ops && clkp->ops->recalc) - clkp->rate = clkp->ops->recalc(clkp); - - propagate_rate(clkp); - } -} - -static void __clk_disable(struct clk *clk) -{ - if (WARN(!clk->usecount, "Trying to disable clock %p with 0 usecount\n", - clk)) - return; - - if (!(--clk->usecount)) { - if (likely(allow_disable && clk->ops && clk->ops->disable)) - clk->ops->disable(clk); - if (likely(clk->parent)) - __clk_disable(clk->parent); - } -} - -void clk_disable(struct clk *clk) -{ - unsigned long flags; - - if (!clk) - return; - - spin_lock_irqsave(&clock_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&clock_lock, flags); -} -EXPORT_SYMBOL_GPL(clk_disable); - -static int __clk_enable(struct clk *clk) -{ - int ret = 0; - - if (clk->usecount++ == 0) { - if (clk->parent) { - ret = __clk_enable(clk->parent); - if (unlikely(ret)) - goto err; - } - - if (clk->ops && clk->ops->enable) { - ret = clk->ops->enable(clk); - if (ret) { - if (clk->parent) - __clk_disable(clk->parent); - goto err; - } - } - } - - return ret; -err: - clk->usecount--; - return ret; -} - -int clk_enable(struct clk *clk) -{ - unsigned long flags; - int ret; - - if (!clk) - return -EINVAL; - - spin_lock_irqsave(&clock_lock, flags); - ret = __clk_enable(clk); - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_enable); - -static LIST_HEAD(root_clks); - -/** - * recalculate_root_clocks - recalculate and propagate all root clocks - * - * Recalculates all root clocks (clocks with no parent), which if the - * clock's .recalc is set correctly, should also propagate their rates. - * Called at init. - */ -void recalculate_root_clocks(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &root_clks, sibling) { - if (clkp->ops && clkp->ops->recalc) - clkp->rate = clkp->ops->recalc(clkp); - propagate_rate(clkp); - } -} - -static struct clk_mapping dummy_mapping; - -static struct clk *lookup_root_clock(struct clk *clk) -{ - while (clk->parent) - clk = clk->parent; - - return clk; -} - -static int clk_establish_mapping(struct clk *clk) -{ - struct clk_mapping *mapping = clk->mapping; - - /* - * Propagate mappings. - */ - if (!mapping) { - struct clk *clkp; - - /* - * dummy mapping for root clocks with no specified ranges - */ - if (!clk->parent) { - clk->mapping = &dummy_mapping; - goto out; - } - - /* - * If we're on a child clock and it provides no mapping of its - * own, inherit the mapping from its root clock. - */ - clkp = lookup_root_clock(clk); - mapping = clkp->mapping; - BUG_ON(!mapping); - } - - /* - * Establish initial mapping. - */ - if (!mapping->base && mapping->phys) { - kref_init(&mapping->ref); - - mapping->base = ioremap(mapping->phys, mapping->len); - if (unlikely(!mapping->base)) - return -ENXIO; - } else if (mapping->base) { - /* - * Bump the refcount for an existing mapping - */ - kref_get(&mapping->ref); - } - - clk->mapping = mapping; -out: - clk->mapped_reg = clk->mapping->base; - clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys; - return 0; -} - -static void clk_destroy_mapping(struct kref *kref) -{ - struct clk_mapping *mapping; - - mapping = container_of(kref, struct clk_mapping, ref); - - iounmap(mapping->base); -} - -static void clk_teardown_mapping(struct clk *clk) -{ - struct clk_mapping *mapping = clk->mapping; - - /* Nothing to do */ - if (mapping == &dummy_mapping) - goto out; - - kref_put(&mapping->ref, clk_destroy_mapping); - clk->mapping = NULL; -out: - clk->mapped_reg = NULL; -} - -int clk_register(struct clk *clk) -{ - int ret; - - if (IS_ERR_OR_NULL(clk)) - return -EINVAL; - - /* - * trap out already registered clocks - */ - if (clk->node.next || clk->node.prev) - return 0; - - mutex_lock(&clock_list_sem); - - INIT_LIST_HEAD(&clk->children); - clk->usecount = 0; - - ret = clk_establish_mapping(clk); - if (unlikely(ret)) - goto out_unlock; - - if (clk->parent) - list_add(&clk->sibling, &clk->parent->children); - else - list_add(&clk->sibling, &root_clks); - - list_add(&clk->node, &clock_list); - -#ifdef CONFIG_SH_CLK_CPG_LEGACY - if (clk->ops && clk->ops->init) - clk->ops->init(clk); -#endif - -out_unlock: - mutex_unlock(&clock_list_sem); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clock_list_sem); - list_del(&clk->sibling); - list_del(&clk->node); - clk_teardown_mapping(clk); - mutex_unlock(&clock_list_sem); -} -EXPORT_SYMBOL_GPL(clk_unregister); - -void clk_enable_init_clocks(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &clock_list, node) - if (clkp->flags & CLK_ENABLE_ON_INIT) - clk_enable(clkp); -} - -unsigned long clk_get_rate(struct clk *clk) -{ - if (!clk) - return 0; - - return clk->rate; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret = -EOPNOTSUPP; - unsigned long flags; - - if (!clk) - return 0; - - spin_lock_irqsave(&clock_lock, flags); - - if (likely(clk->ops && clk->ops->set_rate)) { - ret = clk->ops->set_rate(clk, rate); - if (ret != 0) - goto out_unlock; - } else { - clk->rate = rate; - ret = 0; - } - - if (clk->ops && clk->ops->recalc) - clk->rate = clk->ops->recalc(clk); - - propagate_rate(clk); - -out_unlock: - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - unsigned long flags; - int ret = -EINVAL; - - if (!parent || !clk) - return ret; - if (clk->parent == parent) - return 0; - - spin_lock_irqsave(&clock_lock, flags); - if (clk->usecount == 0) { - if (clk->ops->set_parent) - ret = clk->ops->set_parent(clk, parent); - else - ret = clk_reparent(clk, parent); - - if (ret == 0) { - if (clk->ops->recalc) - clk->rate = clk->ops->recalc(clk); - pr_debug("set parent of %p to %p (new rate %ld)\n", - clk, clk->parent, clk->rate); - propagate_rate(clk); - } - } else - ret = -EBUSY; - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -struct clk *clk_get_parent(struct clk *clk) -{ - if (!clk) - return NULL; - - return clk->parent; -} -EXPORT_SYMBOL_GPL(clk_get_parent); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (!clk) - return 0; - - if (likely(clk->ops && clk->ops->round_rate)) { - unsigned long flags, rounded; - - spin_lock_irqsave(&clock_lock, flags); - rounded = clk->ops->round_rate(clk, rate); - spin_unlock_irqrestore(&clock_lock, flags); - - return rounded; - } - - return clk_get_rate(clk); -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -#ifdef CONFIG_PM -static void clks_core_resume(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->usecount && clkp->ops)) { - unsigned long rate = clkp->rate; - - if (likely(clkp->ops->set_parent)) - clkp->ops->set_parent(clkp, - clkp->parent); - if (likely(clkp->ops->set_rate)) - clkp->ops->set_rate(clkp, rate); - else if (likely(clkp->ops->recalc)) - clkp->rate = clkp->ops->recalc(clkp); - } - } -} - -static struct syscore_ops clks_syscore_ops = { - .resume = clks_core_resume, -}; - -static int __init clk_syscore_init(void) -{ - register_syscore_ops(&clks_syscore_ops); - - return 0; -} -subsys_initcall(clk_syscore_init); -#endif - -static int __init clk_late_init(void) -{ - unsigned long flags; - struct clk *clk; - - /* disable all clocks with zero use count */ - mutex_lock(&clock_list_sem); - spin_lock_irqsave(&clock_lock, flags); - - list_for_each_entry(clk, &clock_list, node) - if (!clk->usecount && clk->ops && clk->ops->disable) - clk->ops->disable(clk); - - /* from now on allow clock disable operations */ - allow_disable = 1; - - spin_unlock_irqrestore(&clock_lock, flags); - mutex_unlock(&clock_list_sem); - return 0; -} -late_initcall(clk_late_init); diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c deleted file mode 100644 index fd72d9088bdcbc..00000000000000 --- a/drivers/sh/clk/cpg.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Helper routines for SuperH Clock Pulse Generator blocks (CPG). - * - * Copyright (C) 2010 Magnus Damm - * Copyright (C) 2010 - 2012 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/clk.h> -#include <linux/compiler.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/sh_clk.h> - -#define CPG_CKSTP_BIT BIT(8) - -static unsigned int sh_clk_read(struct clk *clk) -{ - if (clk->flags & CLK_ENABLE_REG_8BIT) - return ioread8(clk->mapped_reg); - else if (clk->flags & CLK_ENABLE_REG_16BIT) - return ioread16(clk->mapped_reg); - - return ioread32(clk->mapped_reg); -} - -static void sh_clk_write(int value, struct clk *clk) -{ - if (clk->flags & CLK_ENABLE_REG_8BIT) - iowrite8(value, clk->mapped_reg); - else if (clk->flags & CLK_ENABLE_REG_16BIT) - iowrite16(value, clk->mapped_reg); - else - iowrite32(value, clk->mapped_reg); -} - -static int sh_clk_mstp_enable(struct clk *clk) -{ - sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk); - if (clk->status_reg) { - unsigned int (*read)(const void __iomem *addr); - int i; - void __iomem *mapped_status = (phys_addr_t)clk->status_reg - - (phys_addr_t)clk->enable_reg + clk->mapped_reg; - - if (clk->flags & CLK_ENABLE_REG_8BIT) - read = ioread8; - else if (clk->flags & CLK_ENABLE_REG_16BIT) - read = ioread16; - else - read = ioread32; - - for (i = 1000; - (read(mapped_status) & (1 << clk->enable_bit)) && i; - i--) - cpu_relax(); - if (!i) { - pr_err("cpg: failed to enable %p[%d]\n", - clk->enable_reg, clk->enable_bit); - return -ETIMEDOUT; - } - } - return 0; -} - -static void sh_clk_mstp_disable(struct clk *clk) -{ - sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk); -} - -static struct sh_clk_ops sh_clk_mstp_clk_ops = { - .enable = sh_clk_mstp_enable, - .disable = sh_clk_mstp_disable, - .recalc = followparent_recalc, -}; - -int __init sh_clk_mstp_register(struct clk *clks, int nr) -{ - struct clk *clkp; - int ret = 0; - int k; - - for (k = 0; !ret && (k < nr); k++) { - clkp = clks + k; - clkp->ops = &sh_clk_mstp_clk_ops; - ret |= clk_register(clkp); - } - - return ret; -} - -/* - * Div/mult table lookup helpers - */ -static inline struct clk_div_table *clk_to_div_table(struct clk *clk) -{ - return clk->priv; -} - -static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk) -{ - return clk_to_div_table(clk)->div_mult_table; -} - -/* - * Common div ops - */ -static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) -{ - return clk_rate_table_round(clk, clk->freq_table, rate); -} - -static unsigned long sh_clk_div_recalc(struct clk *clk) -{ - struct clk_div_mult_table *table = clk_to_div_mult_table(clk); - unsigned int idx; - - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, clk->arch_flags ? &clk->arch_flags : NULL); - - idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask; - - return clk->freq_table[idx].frequency; -} - -static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk_div_table *dt = clk_to_div_table(clk); - unsigned long value; - int idx; - - idx = clk_rate_table_find(clk, clk->freq_table, rate); - if (idx < 0) - return idx; - - value = sh_clk_read(clk); - value &= ~(clk->div_mask << clk->enable_bit); - value |= (idx << clk->enable_bit); - sh_clk_write(value, clk); - - /* XXX: Should use a post-change notifier */ - if (dt->kick) - dt->kick(clk); - - return 0; -} - -static int sh_clk_div_enable(struct clk *clk) -{ - if (clk->div_mask == SH_CLK_DIV6_MSK) { - int ret = sh_clk_div_set_rate(clk, clk->rate); - if (ret < 0) - return ret; - } - - sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); - return 0; -} - -static void sh_clk_div_disable(struct clk *clk) -{ - unsigned int val; - - val = sh_clk_read(clk); - val |= CPG_CKSTP_BIT; - - /* - * div6 clocks require the divisor field to be non-zero or the - * above CKSTP toggle silently fails. Ensure that the divisor - * array is reset to its initial state on disable. - */ - if (clk->flags & CLK_MASK_DIV_ON_DISABLE) - val |= clk->div_mask; - - sh_clk_write(val, clk); -} - -static struct sh_clk_ops sh_clk_div_clk_ops = { - .recalc = sh_clk_div_recalc, - .set_rate = sh_clk_div_set_rate, - .round_rate = sh_clk_div_round_rate, -}; - -static struct sh_clk_ops sh_clk_div_enable_clk_ops = { - .recalc = sh_clk_div_recalc, - .set_rate = sh_clk_div_set_rate, - .round_rate = sh_clk_div_round_rate, - .enable = sh_clk_div_enable, - .disable = sh_clk_div_disable, -}; - -static int __init sh_clk_init_parent(struct clk *clk) -{ - u32 val; - - if (clk->parent) - return 0; - - if (!clk->parent_table || !clk->parent_num) - return 0; - - if (!clk->src_width) { - pr_err("sh_clk_init_parent: cannot select parent clock\n"); - return -EINVAL; - } - - val = (sh_clk_read(clk) >> clk->src_shift); - val &= (1 << clk->src_width) - 1; - - if (val >= clk->parent_num) { - pr_err("sh_clk_init_parent: parent table size failed\n"); - return -EINVAL; - } - - clk_reparent(clk, clk->parent_table[val]); - if (!clk->parent) { - pr_err("sh_clk_init_parent: unable to set parent"); - return -EINVAL; - } - - return 0; -} - -static int __init sh_clk_div_register_ops(struct clk *clks, int nr, - struct clk_div_table *table, struct sh_clk_ops *ops) -{ - struct clk *clkp; - void *freq_table; - int nr_divs = table->div_mult_table->nr_divisors; - int freq_table_size = sizeof(struct cpufreq_frequency_table); - int ret = 0; - int k; - - freq_table_size *= (nr_divs + 1); - freq_table = kcalloc(nr, freq_table_size, GFP_KERNEL); - if (!freq_table) { - pr_err("%s: unable to alloc memory\n", __func__); - return -ENOMEM; - } - - for (k = 0; !ret && (k < nr); k++) { - clkp = clks + k; - - clkp->ops = ops; - clkp->priv = table; - - clkp->freq_table = freq_table + (k * freq_table_size); - clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; - - ret = clk_register(clkp); - if (ret == 0) - ret = sh_clk_init_parent(clkp); - } - - return ret; -} - -/* - * div6 support - */ -static int sh_clk_div6_divisors[64] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 -}; - -static struct clk_div_mult_table div6_div_mult_table = { - .divisors = sh_clk_div6_divisors, - .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), -}; - -static struct clk_div_table sh_clk_div6_table = { - .div_mult_table = &div6_div_mult_table, -}; - -static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk_div_mult_table *table = clk_to_div_mult_table(clk); - u32 value; - int ret, i; - - if (!clk->parent_table || !clk->parent_num) - return -EINVAL; - - /* Search the parent */ - for (i = 0; i < clk->parent_num; i++) - if (clk->parent_table[i] == parent) - break; - - if (i == clk->parent_num) - return -ENODEV; - - ret = clk_reparent(clk, parent); - if (ret < 0) - return ret; - - value = sh_clk_read(clk) & - ~(((1 << clk->src_width) - 1) << clk->src_shift); - - sh_clk_write(value | (i << clk->src_shift), clk); - - /* Rebuild the frequency table */ - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, NULL); - - return 0; -} - -static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { - .recalc = sh_clk_div_recalc, - .round_rate = sh_clk_div_round_rate, - .set_rate = sh_clk_div_set_rate, - .enable = sh_clk_div_enable, - .disable = sh_clk_div_disable, - .set_parent = sh_clk_div6_set_parent, -}; - -int __init sh_clk_div6_register(struct clk *clks, int nr) -{ - return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, - &sh_clk_div_enable_clk_ops); -} - -int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) -{ - return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, - &sh_clk_div6_reparent_clk_ops); -} - -/* - * div4 support - */ -static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk_div_mult_table *table = clk_to_div_mult_table(clk); - u32 value; - int ret; - - /* we really need a better way to determine parent index, but for - * now assume internal parent comes with CLK_ENABLE_ON_INIT set, - * no CLK_ENABLE_ON_INIT means external clock... - */ - - if (parent->flags & CLK_ENABLE_ON_INIT) - value = sh_clk_read(clk) & ~(1 << 7); - else - value = sh_clk_read(clk) | (1 << 7); - - ret = clk_reparent(clk, parent); - if (ret < 0) - return ret; - - sh_clk_write(value, clk); - - /* Rebiuld the frequency table */ - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, &clk->arch_flags); - - return 0; -} - -static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { - .recalc = sh_clk_div_recalc, - .set_rate = sh_clk_div_set_rate, - .round_rate = sh_clk_div_round_rate, - .enable = sh_clk_div_enable, - .disable = sh_clk_div_disable, - .set_parent = sh_clk_div4_set_parent, -}; - -int __init sh_clk_div4_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops); -} - -int __init sh_clk_div4_enable_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div_register_ops(clks, nr, table, - &sh_clk_div_enable_clk_ops); -} - -int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div_register_ops(clks, nr, table, - &sh_clk_div4_reparent_clk_ops); -} - -/* FSI-DIV */ -static unsigned long fsidiv_recalc(struct clk *clk) -{ - u32 value; - - value = __raw_readl(clk->mapping->base); - - value >>= 16; - if (value < 2) - return clk->parent->rate; - - return clk->parent->rate / value; -} - -static long fsidiv_round_rate(struct clk *clk, unsigned long rate) -{ - return clk_rate_div_range_round(clk, 1, 0xffff, rate); -} - -static void fsidiv_disable(struct clk *clk) -{ - __raw_writel(0, clk->mapping->base); -} - -static int fsidiv_enable(struct clk *clk) -{ - u32 value; - - value = __raw_readl(clk->mapping->base) >> 16; - if (value < 2) - return 0; - - __raw_writel((value << 16) | 0x3, clk->mapping->base); - - return 0; -} - -static int fsidiv_set_rate(struct clk *clk, unsigned long rate) -{ - int idx; - - idx = (clk->parent->rate / rate) & 0xffff; - if (idx < 2) - __raw_writel(0, clk->mapping->base); - else - __raw_writel(idx << 16, clk->mapping->base); - - return 0; -} - -static struct sh_clk_ops fsidiv_clk_ops = { - .recalc = fsidiv_recalc, - .round_rate = fsidiv_round_rate, - .set_rate = fsidiv_set_rate, - .enable = fsidiv_enable, - .disable = fsidiv_disable, -}; - -int __init sh_clk_fsidiv_register(struct clk *clks, int nr) -{ - struct clk_mapping *map; - int i; - - for (i = 0; i < nr; i++) { - - map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL); - if (!map) { - pr_err("%s: unable to alloc memory\n", __func__); - return -ENOMEM; - } - - /* clks[i].enable_reg came from SH_CLK_FSIDIV() */ - map->phys = (phys_addr_t)clks[i].enable_reg; - map->len = 8; - - clks[i].enable_reg = 0; /* remove .enable_reg */ - clks[i].ops = &fsidiv_clk_ops; - clks[i].mapping = map; - - clk_register(&clks[i]); - } - - return 0; -} diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig deleted file mode 100644 index 5c701709fef528..00000000000000 --- a/drivers/sh/intc/Kconfig +++ /dev/null @@ -1,44 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config SH_INTC - bool - select IRQ_DOMAIN - -if SH_INTC - -comment "Interrupt controller options" - -config INTC_USERIMASK - bool "Userspace interrupt masking support" - depends on (SUPERH && CPU_SH4A) || COMPILE_TEST - help - This enables support for hardware-assisted userspace hardirq - masking. - - SH-4A and newer interrupt blocks all support a special shadowed - page with all non-masking registers obscured when mapped in to - userspace. This is primarily for use by userspace device - drivers that are using special priority levels. - - If in doubt, say N. - -config INTC_BALANCING - bool "Hardware IRQ balancing support" - depends on SMP && SUPERH && CPU_SHX3 - help - This enables support for IRQ auto-distribution mode on SH-X3 - SMP parts. All of the balancing and CPU wakeup decisions are - taken care of automatically by hardware for distributed - vectors. - - If in doubt, say N. - -config INTC_MAPPING_DEBUG - bool "Expose IRQ to per-controller id mapping via debugfs" - depends on DEBUG_FS - help - This will create a debugfs entry for showing the relationship - between system IRQs and the per-controller id tables. - - If in doubt, say N. - -endif diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile deleted file mode 100644 index bdd855327e41d5..00000000000000 --- a/drivers/sh/intc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y := access.o chip.o core.o handle.o irqdomain.o virq.o - -obj-$(CONFIG_INTC_BALANCING) += balancing.o -obj-$(CONFIG_INTC_USERIMASK) += userimask.o -obj-$(CONFIG_INTC_MAPPING_DEBUG) += virq-debugfs.o diff --git a/drivers/sh/intc/access.c b/drivers/sh/intc/access.c deleted file mode 100644 index 114390f967d26e..00000000000000 --- a/drivers/sh/intc/access.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Common INTC2 register accessors - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009, 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/io.h> -#include "internals.h" - -unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address) -{ - struct intc_window *window; - int k; - - /* scan through physical windows and convert address */ - for (k = 0; k < d->nr_windows; k++) { - window = d->window + k; - - if (address < window->phys) - continue; - - if (address >= (window->phys + window->size)) - continue; - - address -= window->phys; - address += (unsigned long)window->virt; - - return address; - } - - /* no windows defined, register must be 1:1 mapped virt:phys */ - return address; -} - -unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address) -{ - unsigned int k; - - address = intc_phys_to_virt(d, address); - - for (k = 0; k < d->nr_reg; k++) { - if (d->reg[k] == address) - return k; - } - - BUG(); - return 0; -} - -unsigned int intc_set_field_from_handle(unsigned int value, - unsigned int field_value, - unsigned int handle) -{ - unsigned int width = _INTC_WIDTH(handle); - unsigned int shift = _INTC_SHIFT(handle); - - value &= ~(((1 << width) - 1) << shift); - value |= field_value << shift; - return value; -} - -unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle) -{ - unsigned int width = _INTC_WIDTH(handle); - unsigned int shift = _INTC_SHIFT(handle); - unsigned int mask = ((1 << width) - 1) << shift; - - return (value & mask) >> shift; -} - -static unsigned long test_8(unsigned long addr, unsigned long h, - unsigned long ignore) -{ - void __iomem *ptr = (void __iomem *)addr; - return intc_get_field_from_handle(__raw_readb(ptr), h); -} - -static unsigned long test_16(unsigned long addr, unsigned long h, - unsigned long ignore) -{ - void __iomem *ptr = (void __iomem *)addr; - return intc_get_field_from_handle(__raw_readw(ptr), h); -} - -static unsigned long test_32(unsigned long addr, unsigned long h, - unsigned long ignore) -{ - void __iomem *ptr = (void __iomem *)addr; - return intc_get_field_from_handle(__raw_readl(ptr), h); -} - -static unsigned long write_8(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - __raw_writeb(intc_set_field_from_handle(0, data, h), ptr); - (void)__raw_readb(ptr); /* Defeat write posting */ - return 0; -} - -static unsigned long write_16(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - __raw_writew(intc_set_field_from_handle(0, data, h), ptr); - (void)__raw_readw(ptr); /* Defeat write posting */ - return 0; -} - -static unsigned long write_32(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - __raw_writel(intc_set_field_from_handle(0, data, h), ptr); - (void)__raw_readl(ptr); /* Defeat write posting */ - return 0; -} - -static unsigned long modify_8(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - unsigned long flags; - unsigned int value; - local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readb(ptr), data, h); - __raw_writeb(value, ptr); - (void)__raw_readb(ptr); /* Defeat write posting */ - local_irq_restore(flags); - return 0; -} - -static unsigned long modify_16(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - unsigned long flags; - unsigned int value; - local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readw(ptr), data, h); - __raw_writew(value, ptr); - (void)__raw_readw(ptr); /* Defeat write posting */ - local_irq_restore(flags); - return 0; -} - -static unsigned long modify_32(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - unsigned long flags; - unsigned int value; - local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readl(ptr), data, h); - __raw_writel(value, ptr); - (void)__raw_readl(ptr); /* Defeat write posting */ - local_irq_restore(flags); - return 0; -} - -static unsigned long intc_mode_field(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) -{ - return fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1)); -} - -static unsigned long intc_mode_zero(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) -{ - return fn(addr, handle, 0); -} - -static unsigned long intc_mode_prio(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) -{ - return fn(addr, handle, intc_get_prio_level(irq)); -} - -unsigned long (*intc_reg_fns[])(unsigned long addr, - unsigned long h, - unsigned long data) = { - [REG_FN_TEST_BASE + 0] = test_8, - [REG_FN_TEST_BASE + 1] = test_16, - [REG_FN_TEST_BASE + 3] = test_32, - [REG_FN_WRITE_BASE + 0] = write_8, - [REG_FN_WRITE_BASE + 1] = write_16, - [REG_FN_WRITE_BASE + 3] = write_32, - [REG_FN_MODIFY_BASE + 0] = modify_8, - [REG_FN_MODIFY_BASE + 1] = modify_16, - [REG_FN_MODIFY_BASE + 3] = modify_32, -}; - -unsigned long (*intc_enable_fns[])(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) = { - [MODE_ENABLE_REG] = intc_mode_field, - [MODE_MASK_REG] = intc_mode_zero, - [MODE_DUAL_REG] = intc_mode_field, - [MODE_PRIO_REG] = intc_mode_prio, - [MODE_PCLR_REG] = intc_mode_prio, -}; - -unsigned long (*intc_disable_fns[])(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) = { - [MODE_ENABLE_REG] = intc_mode_zero, - [MODE_MASK_REG] = intc_mode_field, - [MODE_DUAL_REG] = intc_mode_field, - [MODE_PRIO_REG] = intc_mode_zero, - [MODE_PCLR_REG] = intc_mode_field, -}; - -unsigned long (*intc_enable_noprio_fns[])(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) = { - [MODE_ENABLE_REG] = intc_mode_field, - [MODE_MASK_REG] = intc_mode_zero, - [MODE_DUAL_REG] = intc_mode_field, - [MODE_PRIO_REG] = intc_mode_field, - [MODE_PCLR_REG] = intc_mode_field, -}; diff --git a/drivers/sh/intc/balancing.c b/drivers/sh/intc/balancing.c deleted file mode 100644 index bc780807ccb0fe..00000000000000 --- a/drivers/sh/intc/balancing.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Support for hardware-managed IRQ auto-distribution. - * - * Copyright (C) 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include "internals.h" - -static unsigned long dist_handle[INTC_NR_IRQS]; - -void intc_balancing_enable(unsigned int irq) -{ - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = dist_handle[irq]; - unsigned long addr; - - if (irq_balancing_disabled(irq) || !handle) - return; - - addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); - intc_reg_fns[_INTC_FN(handle)](addr, handle, 1); -} - -void intc_balancing_disable(unsigned int irq) -{ - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = dist_handle[irq]; - unsigned long addr; - - if (irq_balancing_disabled(irq) || !handle) - return; - - addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); - intc_reg_fns[_INTC_FN(handle)](addr, handle, 0); -} - -static unsigned int intc_dist_data(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id) -{ - struct intc_mask_reg *mr = desc->hw.mask_regs; - unsigned int i, j, fn, mode; - unsigned long reg_e, reg_d; - - for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) { - mr = desc->hw.mask_regs + i; - - /* - * Skip this entry if there's no auto-distribution - * register associated with it. - */ - if (!mr->dist_reg) - continue; - - for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { - if (mr->enum_ids[j] != enum_id) - continue; - - fn = REG_FN_MODIFY_BASE; - mode = MODE_ENABLE_REG; - reg_e = mr->dist_reg; - reg_d = mr->dist_reg; - - fn += (mr->reg_width >> 3) - 1; - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - 1, - (mr->reg_width - 1) - j); - } - } - - /* - * It's possible we've gotten here with no distribution options - * available for the IRQ in question, so we just skip over those. - */ - return 0; -} - -void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id) -{ - unsigned long flags; - - /* - * Nothing to do for this IRQ. - */ - if (!desc->hw.mask_regs) - return; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - dist_handle[irq] = intc_dist_data(desc, d, id); - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c deleted file mode 100644 index 828d81e02b37ab..00000000000000 --- a/drivers/sh/intc/chip.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * IRQ chip definitions for INTC IRQs. - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009 - 2012 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/cpumask.h> -#include <linux/bsearch.h> -#include <linux/io.h> -#include "internals.h" - -void _intc_enable(struct irq_data *data, unsigned long handle) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long addr; - unsigned int cpu; - - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) { -#ifdef CONFIG_SMP - if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data))) - continue; -#endif - addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu); - intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ - [_INTC_FN(handle)], irq); - } - - intc_balancing_enable(irq); -} - -static void intc_enable(struct irq_data *data) -{ - _intc_enable(data, (unsigned long)irq_data_get_irq_chip_data(data)); -} - -static void intc_disable(struct irq_data *data) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = (unsigned long)irq_data_get_irq_chip_data(data); - unsigned long addr; - unsigned int cpu; - - intc_balancing_disable(irq); - - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { -#ifdef CONFIG_SMP - if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data))) - continue; -#endif - addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu); - intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\ - [_INTC_FN(handle)], irq); - } -} - -#ifdef CONFIG_SMP -/* - * This is held with the irq desc lock held, so we don't require any - * additional locking here at the intc desc level. The affinity mask is - * later tested in the enable/disable paths. - */ -static int intc_set_affinity(struct irq_data *data, - const struct cpumask *cpumask, - bool force) -{ - if (!cpumask_intersects(cpumask, cpu_online_mask)) - return -1; - - irq_data_update_affinity(data, cpumask); - - return IRQ_SET_MASK_OK_NOCOPY; -} -#endif - -static void intc_mask_ack(struct irq_data *data) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = intc_get_ack_handle(irq); - void __iomem *addr; - - intc_disable(data); - - /* read register and write zero only to the associated bit */ - if (handle) { - unsigned int value; - - addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0); - value = intc_set_field_from_handle(0, 1, handle); - - switch (_INTC_FN(handle)) { - case REG_FN_MODIFY_BASE + 0: /* 8bit */ - __raw_readb(addr); - __raw_writeb(0xff ^ value, addr); - break; - case REG_FN_MODIFY_BASE + 1: /* 16bit */ - __raw_readw(addr); - __raw_writew(0xffff ^ value, addr); - break; - case REG_FN_MODIFY_BASE + 3: /* 32bit */ - __raw_readl(addr); - __raw_writel(0xffffffff ^ value, addr); - break; - default: - BUG(); - break; - } - } -} - -static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, - unsigned int nr_hp, - unsigned int irq) -{ - struct intc_handle_int key; - - key.irq = irq; - key.handle = 0; - - return bsearch(&key, hp, nr_hp, sizeof(*hp), intc_handle_int_cmp); -} - -int intc_set_priority(unsigned int irq, unsigned int prio) -{ - struct intc_desc_int *d = get_intc_desc(irq); - struct irq_data *data = irq_get_irq_data(irq); - struct intc_handle_int *ihp; - - if (!intc_get_prio_level(irq) || prio <= 1) - return -EINVAL; - - ihp = intc_find_irq(d->prio, d->nr_prio, irq); - if (ihp) { - if (prio >= (1 << _INTC_WIDTH(ihp->handle))) - return -EINVAL; - - intc_set_prio_level(irq, prio); - - /* - * only set secondary masking method directly - * primary masking method is using intc_prio_level[irq] - * priority level will be set during next enable() - */ - if (_INTC_FN(ihp->handle) != REG_FN_ERR) - _intc_enable(data, ihp->handle); - } - return 0; -} - -#define SENSE_VALID_FLAG 0x80 -#define VALID(x) (x | SENSE_VALID_FLAG) - -static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { - [IRQ_TYPE_EDGE_FALLING] = VALID(0), - [IRQ_TYPE_EDGE_RISING] = VALID(1), - [IRQ_TYPE_LEVEL_LOW] = VALID(2), - /* SH7706, SH7707 and SH7709 do not support high level triggered */ -#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \ - !defined(CONFIG_CPU_SUBTYPE_SH7707) && \ - !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) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK]; - struct intc_handle_int *ihp; - unsigned long addr; - - 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); - } - - return 0; -} - -struct irq_chip intc_irq_chip = { - .irq_mask = intc_disable, - .irq_unmask = intc_enable, - .irq_mask_ack = intc_mask_ack, - .irq_enable = intc_enable, - .irq_disable = intc_disable, - .irq_set_type = intc_set_type, -#ifdef CONFIG_SMP - .irq_set_affinity = intc_set_affinity, -#endif - .flags = IRQCHIP_SKIP_SET_WAKE, -}; diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c deleted file mode 100644 index ca4f4ca413f11d..00000000000000 --- a/drivers/sh/intc/core.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Shared interrupt handling code for IPR and INTC2 types of IRQs. - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009 - 2012 Paul Mundt - * - * Based on intc2.c and ipr.c - * - * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi - * Copyright (C) 2000 Kazumoto Kojima - * Copyright (C) 2001 David J. Mckay (david.mckay@xxxxxx) - * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@xxxxxxxxxxxxxxxx> - * Copyright (C) 2005, 2006 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include <linux/init.h> -#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/irqdomain.h> -#include <linux/device.h> -#include <linux/syscore_ops.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/radix-tree.h> -#include <linux/export.h> -#include <linux/sort.h> -#include "internals.h" - -LIST_HEAD(intc_list); -DEFINE_RAW_SPINLOCK(intc_big_lock); -static unsigned int nr_intc_controllers; - -/* - * Default priority level - * - this needs to be at least 2 for 5-bit priorities on 7780 - */ -static unsigned int default_prio_level = 2; /* 2 - 16 */ -static unsigned int intc_prio_level[INTC_NR_IRQS]; /* for now */ - -unsigned int intc_get_dfl_prio_level(void) -{ - return default_prio_level; -} - -unsigned int intc_get_prio_level(unsigned int irq) -{ - return intc_prio_level[irq]; -} - -void intc_set_prio_level(unsigned int irq, unsigned int level) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - intc_prio_level[irq] = level; - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} - -static void intc_redirect_irq(struct irq_desc *desc) -{ - generic_handle_irq((unsigned int)irq_desc_get_handler_data(desc)); -} - -static void __init intc_register_irq(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, - unsigned int irq) -{ - struct intc_handle_int *hp; - struct irq_data *irq_data; - unsigned int data[2], primary; - unsigned long flags; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq)); - raw_spin_unlock_irqrestore(&intc_big_lock, flags); - - /* - * Prefer single interrupt source bitmap over other combinations: - * - * 1. bitmap, single interrupt source - * 2. priority, single interrupt source - * 3. bitmap, multiple interrupt sources (groups) - * 4. priority, multiple interrupt sources (groups) - */ - data[0] = intc_get_mask_handle(desc, d, enum_id, 0); - data[1] = intc_get_prio_handle(desc, d, enum_id, 0); - - primary = 0; - if (!data[0] && data[1]) - primary = 1; - - if (!data[0] && !data[1]) - pr_warn("missing unique irq mask for irq %d (vect 0x%04x)\n", - irq, irq2evt(irq)); - - data[0] = data[0] ? data[0] : intc_get_mask_handle(desc, d, enum_id, 1); - data[1] = data[1] ? data[1] : intc_get_prio_handle(desc, d, enum_id, 1); - - if (!data[primary]) - primary ^= 1; - - BUG_ON(!data[primary]); /* must have primary masking method */ - - irq_data = irq_get_irq_data(irq); - - disable_irq_nosync(irq); - irq_set_chip_and_handler_name(irq, &d->chip, handle_level_irq, - "level"); - irq_set_chip_data(irq, (void *)data[primary]); - - /* - * set priority level - */ - intc_set_prio_level(irq, intc_get_dfl_prio_level()); - - /* enable secondary masking method if present */ - if (data[!primary]) - _intc_enable(irq_data, data[!primary]); - - /* add irq to d->prio list if priority is available */ - if (data[1]) { - hp = d->prio + d->nr_prio; - hp->irq = irq; - hp->handle = data[1]; - - if (primary) { - /* - * only secondary priority should access registers, so - * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority() - */ - hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0); - hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0); - } - d->nr_prio++; - } - - /* add irq to d->sense list if sense is available */ - data[0] = intc_get_sense_handle(desc, d, enum_id); - if (data[0]) { - (d->sense + d->nr_sense)->irq = irq; - (d->sense + d->nr_sense)->handle = data[0]; - d->nr_sense++; - } - - /* irq should be disabled by default */ - d->chip.irq_mask(irq_data); - - intc_set_ack_handle(irq, desc, d, enum_id); - intc_set_dist_handle(irq, desc, d, enum_id); - - activate_irq(irq); -} - -static unsigned int __init save_reg(struct intc_desc_int *d, - unsigned int cnt, - unsigned long value, - unsigned int smp) -{ - if (value) { - value = intc_phys_to_virt(d, value); - - d->reg[cnt] = value; -#ifdef CONFIG_SMP - d->smp[cnt] = smp; -#endif - return 1; - } - - return 0; -} - -static bool __init intc_map(struct irq_domain *domain, int irq) -{ - if (!irq_to_desc(irq) && irq_alloc_desc_at(irq, NUMA_NO_NODE) != irq) { - pr_err("uname to allocate IRQ %d\n", irq); - return false; - } - - if (irq_domain_associate(domain, irq, irq)) { - pr_err("domain association failure\n"); - return false; - } - - return true; -} - -int __init register_intc_controller(struct intc_desc *desc) -{ - unsigned int i, k, smp; - struct intc_hw_desc *hw = &desc->hw; - struct intc_desc_int *d; - struct resource *res; - - pr_info("Registered controller '%s' with %u IRQs\n", - desc->name, hw->nr_vectors); - - d = kzalloc(sizeof(*d), GFP_NOWAIT); - if (!d) - goto err0; - - INIT_LIST_HEAD(&d->list); - list_add_tail(&d->list, &intc_list); - - raw_spin_lock_init(&d->lock); - INIT_RADIX_TREE(&d->tree, GFP_ATOMIC); - - d->index = nr_intc_controllers; - - if (desc->num_resources) { - d->nr_windows = desc->num_resources; - d->window = kcalloc(d->nr_windows, sizeof(*d->window), - GFP_NOWAIT); - if (!d->window) - goto err1; - - for (k = 0; k < d->nr_windows; k++) { - res = desc->resource + k; - WARN_ON(resource_type(res) != IORESOURCE_MEM); - d->window[k].phys = res->start; - d->window[k].size = resource_size(res); - d->window[k].virt = ioremap(res->start, - resource_size(res)); - if (!d->window[k].virt) - goto err2; - } - } - - d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; -#ifdef CONFIG_INTC_BALANCING - if (d->nr_reg) - d->nr_reg += hw->nr_mask_regs; -#endif - d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; - d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; - d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; - d->nr_reg += hw->subgroups ? hw->nr_subgroups : 0; - - d->reg = kcalloc(d->nr_reg, sizeof(*d->reg), GFP_NOWAIT); - if (!d->reg) - goto err2; - -#ifdef CONFIG_SMP - d->smp = kcalloc(d->nr_reg, sizeof(*d->smp), GFP_NOWAIT); - if (!d->smp) - goto err3; -#endif - k = 0; - - if (hw->mask_regs) { - for (i = 0; i < hw->nr_mask_regs; i++) { - smp = IS_SMP(hw->mask_regs[i]); - k += save_reg(d, k, hw->mask_regs[i].set_reg, smp); - k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); -#ifdef CONFIG_INTC_BALANCING - k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0); -#endif - } - } - - if (hw->prio_regs) { - d->prio = kcalloc(hw->nr_vectors, sizeof(*d->prio), - GFP_NOWAIT); - if (!d->prio) - goto err4; - - for (i = 0; i < hw->nr_prio_regs; i++) { - smp = IS_SMP(hw->prio_regs[i]); - k += save_reg(d, k, hw->prio_regs[i].set_reg, smp); - k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp); - } - - sort(d->prio, hw->nr_prio_regs, sizeof(*d->prio), - intc_handle_int_cmp, NULL); - } - - if (hw->sense_regs) { - d->sense = kcalloc(hw->nr_vectors, sizeof(*d->sense), - GFP_NOWAIT); - if (!d->sense) - goto err5; - - for (i = 0; i < hw->nr_sense_regs; i++) - k += save_reg(d, k, hw->sense_regs[i].reg, 0); - - sort(d->sense, hw->nr_sense_regs, sizeof(*d->sense), - intc_handle_int_cmp, NULL); - } - - if (hw->subgroups) - for (i = 0; i < hw->nr_subgroups; i++) - if (hw->subgroups[i].reg) - k+= save_reg(d, k, hw->subgroups[i].reg, 0); - - memcpy(&d->chip, &intc_irq_chip, sizeof(struct irq_chip)); - d->chip.name = desc->name; - - if (hw->ack_regs) - for (i = 0; i < hw->nr_ack_regs; i++) - k += save_reg(d, k, hw->ack_regs[i].set_reg, 0); - else - d->chip.irq_mask_ack = d->chip.irq_disable; - - /* disable bits matching force_disable before registering irqs */ - if (desc->force_disable) - intc_enable_disable_enum(desc, d, desc->force_disable, 0); - - /* disable bits matching force_enable before registering irqs */ - if (desc->force_enable) - intc_enable_disable_enum(desc, d, desc->force_enable, 0); - - BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ - - intc_irq_domain_init(d, hw); - - /* register the vectors one by one */ - for (i = 0; i < hw->nr_vectors; i++) { - struct intc_vect *vect = hw->vectors + i; - unsigned int irq = evt2irq(vect->vect); - - if (!vect->enum_id) - continue; - - if (!intc_map(d->domain, irq)) - continue; - - intc_irq_xlate_set(irq, vect->enum_id, d); - intc_register_irq(desc, d, vect->enum_id, irq); - - for (k = i + 1; k < hw->nr_vectors; k++) { - struct intc_vect *vect2 = hw->vectors + k; - unsigned int irq2 = evt2irq(vect2->vect); - - if (vect->enum_id != vect2->enum_id) - continue; - - /* - * In the case of multi-evt handling and sparse - * IRQ support, each vector still needs to have - * its own backing irq_desc. - */ - if (!intc_map(d->domain, irq2)) - continue; - - vect2->enum_id = 0; - - /* redirect this interrupts to the first one */ - irq_set_chip(irq2, &dummy_irq_chip); - irq_set_chained_handler_and_data(irq2, - intc_redirect_irq, - (void *)irq); - } - } - - intc_subgroup_init(desc, d); - - /* enable bits matching force_enable after registering irqs */ - if (desc->force_enable) - intc_enable_disable_enum(desc, d, desc->force_enable, 1); - - d->skip_suspend = desc->skip_syscore_suspend; - - nr_intc_controllers++; - - return 0; -err5: - kfree(d->prio); -err4: -#ifdef CONFIG_SMP - kfree(d->smp); -err3: -#endif - kfree(d->reg); -err2: - for (k = 0; k < d->nr_windows; k++) - if (d->window[k].virt) - iounmap(d->window[k].virt); - - kfree(d->window); -err1: - kfree(d); -err0: - pr_err("unable to allocate INTC memory\n"); - - return -ENOMEM; -} - -static int intc_suspend(void) -{ - struct intc_desc_int *d; - - list_for_each_entry(d, &intc_list, list) { - int irq; - - if (d->skip_suspend) - continue; - - /* enable wakeup irqs belonging to this intc controller */ - for_each_active_irq(irq) { - struct irq_data *data; - struct irq_chip *chip; - - data = irq_get_irq_data(irq); - chip = irq_data_get_irq_chip(data); - if (chip != &d->chip) - continue; - if (irqd_is_wakeup_set(data)) - chip->irq_enable(data); - } - } - return 0; -} - -static void intc_resume(void) -{ - struct intc_desc_int *d; - - list_for_each_entry(d, &intc_list, list) { - int irq; - - if (d->skip_suspend) - continue; - - for_each_active_irq(irq) { - struct irq_data *data; - struct irq_chip *chip; - - data = irq_get_irq_data(irq); - chip = irq_data_get_irq_chip(data); - /* - * This will catch the redirect and VIRQ cases - * due to the dummy_irq_chip being inserted. - */ - if (chip != &d->chip) - continue; - if (irqd_irq_disabled(data)) - chip->irq_disable(data); - else - chip->irq_enable(data); - } - } -} - -struct syscore_ops intc_syscore_ops = { - .suspend = intc_suspend, - .resume = intc_resume, -}; - -struct bus_type intc_subsys = { - .name = "intc", - .dev_name = "intc", -}; - -static ssize_t -show_intc_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct intc_desc_int *d; - - d = container_of(dev, struct intc_desc_int, dev); - - return sprintf(buf, "%s\n", d->chip.name); -} - -static DEVICE_ATTR(name, S_IRUGO, show_intc_name, NULL); - -static int __init register_intc_devs(void) -{ - struct intc_desc_int *d; - int error; - - register_syscore_ops(&intc_syscore_ops); - - error = subsys_system_register(&intc_subsys, NULL); - if (!error) { - list_for_each_entry(d, &intc_list, list) { - d->dev.id = d->index; - d->dev.bus = &intc_subsys; - error = device_register(&d->dev); - if (error == 0) - error = device_create_file(&d->dev, - &dev_attr_name); - if (error) - break; - } - } - - if (error) - pr_err("device registration error\n"); - - return error; -} -device_initcall(register_intc_devs); diff --git a/drivers/sh/intc/handle.c b/drivers/sh/intc/handle.c deleted file mode 100644 index 7863a44918a293..00000000000000 --- a/drivers/sh/intc/handle.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Shared interrupt handling code for IPR and INTC2 types of IRQs. - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009, 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/spinlock.h> -#include "internals.h" - -static unsigned long ack_handle[INTC_NR_IRQS]; - -static intc_enum __init intc_grp_id(struct intc_desc *desc, - intc_enum enum_id) -{ - struct intc_group *g = desc->hw.groups; - unsigned int i, j; - - for (i = 0; g && enum_id && i < desc->hw.nr_groups; i++) { - g = desc->hw.groups + i; - - for (j = 0; g->enum_ids[j]; j++) { - if (g->enum_ids[j] != enum_id) - continue; - - return g->enum_id; - } - } - - return 0; -} - -static unsigned int __init _intc_mask_data(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, - unsigned int *reg_idx, - unsigned int *fld_idx) -{ - struct intc_mask_reg *mr = desc->hw.mask_regs; - unsigned int fn, mode; - unsigned long reg_e, reg_d; - - while (mr && enum_id && *reg_idx < desc->hw.nr_mask_regs) { - mr = desc->hw.mask_regs + *reg_idx; - - for (; *fld_idx < ARRAY_SIZE(mr->enum_ids); (*fld_idx)++) { - if (mr->enum_ids[*fld_idx] != enum_id) - continue; - - if (mr->set_reg && mr->clr_reg) { - fn = REG_FN_WRITE_BASE; - mode = MODE_DUAL_REG; - reg_e = mr->clr_reg; - reg_d = mr->set_reg; - } else { - fn = REG_FN_MODIFY_BASE; - if (mr->set_reg) { - mode = MODE_ENABLE_REG; - reg_e = mr->set_reg; - reg_d = mr->set_reg; - } else { - mode = MODE_MASK_REG; - reg_e = mr->clr_reg; - reg_d = mr->clr_reg; - } - } - - fn += (mr->reg_width >> 3) - 1; - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - 1, - (mr->reg_width - 1) - *fld_idx); - } - - *fld_idx = 0; - (*reg_idx)++; - } - - return 0; -} - -unsigned int __init -intc_get_mask_handle(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id, int do_grps) -{ - unsigned int i = 0; - unsigned int j = 0; - unsigned int ret; - - ret = _intc_mask_data(desc, d, enum_id, &i, &j); - if (ret) - return ret; - - if (do_grps) - return intc_get_mask_handle(desc, d, intc_grp_id(desc, enum_id), 0); - - return 0; -} - -static unsigned int __init _intc_prio_data(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, - unsigned int *reg_idx, - unsigned int *fld_idx) -{ - struct intc_prio_reg *pr = desc->hw.prio_regs; - unsigned int fn, n, mode, bit; - unsigned long reg_e, reg_d; - - while (pr && enum_id && *reg_idx < desc->hw.nr_prio_regs) { - pr = desc->hw.prio_regs + *reg_idx; - - for (; *fld_idx < ARRAY_SIZE(pr->enum_ids); (*fld_idx)++) { - if (pr->enum_ids[*fld_idx] != enum_id) - continue; - - if (pr->set_reg && pr->clr_reg) { - fn = REG_FN_WRITE_BASE; - mode = MODE_PCLR_REG; - reg_e = pr->set_reg; - reg_d = pr->clr_reg; - } else { - fn = REG_FN_MODIFY_BASE; - mode = MODE_PRIO_REG; - if (!pr->set_reg) - BUG(); - reg_e = pr->set_reg; - reg_d = pr->set_reg; - } - - fn += (pr->reg_width >> 3) - 1; - n = *fld_idx + 1; - - BUG_ON(n * pr->field_width > pr->reg_width); - - bit = pr->reg_width - (n * pr->field_width); - - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - pr->field_width, bit); - } - - *fld_idx = 0; - (*reg_idx)++; - } - - return 0; -} - -unsigned int __init -intc_get_prio_handle(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id, int do_grps) -{ - unsigned int i = 0; - unsigned int j = 0; - unsigned int ret; - - ret = _intc_prio_data(desc, d, enum_id, &i, &j); - if (ret) - return ret; - - if (do_grps) - return intc_get_prio_handle(desc, d, intc_grp_id(desc, enum_id), 0); - - return 0; -} - -static unsigned int intc_ack_data(struct intc_desc *desc, - struct intc_desc_int *d, intc_enum enum_id) -{ - struct intc_mask_reg *mr = desc->hw.ack_regs; - unsigned int i, j, fn, mode; - unsigned long reg_e, reg_d; - - for (i = 0; mr && enum_id && i < desc->hw.nr_ack_regs; i++) { - mr = desc->hw.ack_regs + i; - - for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { - if (mr->enum_ids[j] != enum_id) - continue; - - fn = REG_FN_MODIFY_BASE; - mode = MODE_ENABLE_REG; - reg_e = mr->set_reg; - reg_d = mr->set_reg; - - fn += (mr->reg_width >> 3) - 1; - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - 1, - (mr->reg_width - 1) - j); - } - } - - return 0; -} - -static void intc_enable_disable(struct intc_desc_int *d, - unsigned long handle, int do_enable) -{ - unsigned long addr; - unsigned int cpu; - unsigned long (*fn)(unsigned long, unsigned long, - unsigned long (*)(unsigned long, unsigned long, - unsigned long), - unsigned int); - - if (do_enable) { - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) { - addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu); - fn = intc_enable_noprio_fns[_INTC_MODE(handle)]; - fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0); - } - } else { - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { - addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu); - fn = intc_disable_fns[_INTC_MODE(handle)]; - fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0); - } - } -} - -void __init intc_enable_disable_enum(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, int enable) -{ - unsigned int i, j, data; - - /* go through and enable/disable all mask bits */ - i = j = 0; - do { - data = _intc_mask_data(desc, d, enum_id, &i, &j); - if (data) - intc_enable_disable(d, data, enable); - j++; - } while (data); - - /* go through and enable/disable all priority fields */ - i = j = 0; - do { - data = _intc_prio_data(desc, d, enum_id, &i, &j); - if (data) - intc_enable_disable(d, data, enable); - - j++; - } while (data); -} - -unsigned int __init -intc_get_sense_handle(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id) -{ - struct intc_sense_reg *sr = desc->hw.sense_regs; - unsigned int i, j, fn, bit; - - for (i = 0; sr && enum_id && i < desc->hw.nr_sense_regs; i++) { - sr = desc->hw.sense_regs + i; - - for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) { - if (sr->enum_ids[j] != enum_id) - continue; - - fn = REG_FN_MODIFY_BASE; - fn += (sr->reg_width >> 3) - 1; - - BUG_ON((j + 1) * sr->field_width > sr->reg_width); - - bit = sr->reg_width - ((j + 1) * sr->field_width); - - return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg), - 0, sr->field_width, bit); - } - } - - return 0; -} - - -void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id) -{ - unsigned long flags; - - /* - * Nothing to do for this IRQ. - */ - if (!desc->hw.ack_regs) - return; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - ack_handle[irq] = intc_ack_data(desc, d, id); - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} - -unsigned long intc_get_ack_handle(unsigned int irq) -{ - return ack_handle[irq]; -} diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h deleted file mode 100644 index fa73c173b56a60..00000000000000 --- a/drivers/sh/intc/internals.h +++ /dev/null @@ -1,191 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include <linux/sh_intc.h> -#include <linux/irq.h> -#include <linux/irqdomain.h> -#include <linux/list.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/radix-tree.h> -#include <linux/device.h> - -#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ - ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ - ((addr_e) << 16) | ((addr_d << 24))) - -#define _INTC_SHIFT(h) (h & 0x1f) -#define _INTC_WIDTH(h) ((h >> 5) & 0xf) -#define _INTC_FN(h) ((h >> 9) & 0xf) -#define _INTC_MODE(h) ((h >> 13) & 0x7) -#define _INTC_ADDR_E(h) ((h >> 16) & 0xff) -#define _INTC_ADDR_D(h) ((h >> 24) & 0xff) - -#ifdef CONFIG_SMP -#define IS_SMP(x) (x.smp) -#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c)) -#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1) -#else -#define IS_SMP(x) 0 -#define INTC_REG(d, x, c) (d->reg[(x)]) -#define SMP_NR(d, x) 1 -#endif - -struct intc_handle_int { - unsigned int irq; - unsigned long handle; -}; - -struct intc_window { - phys_addr_t phys; - void __iomem *virt; - unsigned long size; -}; - -struct intc_map_entry { - intc_enum enum_id; - struct intc_desc_int *desc; -}; - -struct intc_subgroup_entry { - unsigned int pirq; - intc_enum enum_id; - unsigned long handle; -}; - -struct intc_desc_int { - struct list_head list; - struct device dev; - struct radix_tree_root tree; - raw_spinlock_t lock; - unsigned int index; - unsigned long *reg; -#ifdef CONFIG_SMP - unsigned long *smp; -#endif - unsigned int nr_reg; - struct intc_handle_int *prio; - unsigned int nr_prio; - struct intc_handle_int *sense; - unsigned int nr_sense; - struct intc_window *window; - unsigned int nr_windows; - struct irq_domain *domain; - struct irq_chip chip; - bool skip_suspend; -}; - - -enum { - REG_FN_ERR = 0, - REG_FN_TEST_BASE = 1, - REG_FN_WRITE_BASE = 5, - REG_FN_MODIFY_BASE = 9 -}; - -enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */ - MODE_MASK_REG, /* Bit(s) set -> interrupt disabled */ - MODE_DUAL_REG, /* Two registers, set bit to enable / disable */ - MODE_PRIO_REG, /* Priority value written to enable interrupt */ - MODE_PCLR_REG, /* Above plus all bits set to disable interrupt */ -}; - -static inline struct intc_desc_int *get_intc_desc(unsigned int irq) -{ - struct irq_chip *chip = irq_get_chip(irq); - - return container_of(chip, struct intc_desc_int, chip); -} - -/* - * Grumble. - */ -static inline void activate_irq(int irq) -{ - irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE); -} - -static inline int intc_handle_int_cmp(const void *a, const void *b) -{ - const struct intc_handle_int *_a = a; - const struct intc_handle_int *_b = b; - - return _a->irq - _b->irq; -} - -/* access.c */ -extern unsigned long -(*intc_reg_fns[])(unsigned long addr, unsigned long h, unsigned long data); - -extern unsigned long -(*intc_enable_fns[])(unsigned long addr, unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, unsigned long), - unsigned int irq); -extern unsigned long -(*intc_disable_fns[])(unsigned long addr, unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, unsigned long), - unsigned int irq); -extern unsigned long -(*intc_enable_noprio_fns[])(unsigned long addr, unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, unsigned long), - unsigned int irq); - -unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address); -unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address); -unsigned int intc_set_field_from_handle(unsigned int value, - unsigned int field_value, - unsigned int handle); -unsigned long intc_get_field_from_handle(unsigned int value, - unsigned int handle); - -/* balancing.c */ -#ifdef CONFIG_INTC_BALANCING -void intc_balancing_enable(unsigned int irq); -void intc_balancing_disable(unsigned int irq); -void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id); -#else -static inline void intc_balancing_enable(unsigned int irq) { } -static inline void intc_balancing_disable(unsigned int irq) { } -static inline void -intc_set_dist_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id) { } -#endif - -/* chip.c */ -extern struct irq_chip intc_irq_chip; -void _intc_enable(struct irq_data *data, unsigned long handle); - -/* core.c */ -extern struct list_head intc_list; -extern raw_spinlock_t intc_big_lock; -extern struct bus_type intc_subsys; - -unsigned int intc_get_dfl_prio_level(void); -unsigned int intc_get_prio_level(unsigned int irq); -void intc_set_prio_level(unsigned int irq, unsigned int level); - -/* handle.c */ -unsigned int intc_get_mask_handle(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, int do_grps); -unsigned int intc_get_prio_handle(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, int do_grps); -unsigned int intc_get_sense_handle(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id); -void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id); -unsigned long intc_get_ack_handle(unsigned int irq); -void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id, int enable); - -/* irqdomain.c */ -void intc_irq_domain_init(struct intc_desc_int *d, struct intc_hw_desc *hw); - -/* virq.c */ -void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d); -void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d); -struct intc_map_entry *intc_irq_xlate_get(unsigned int irq); diff --git a/drivers/sh/intc/irqdomain.c b/drivers/sh/intc/irqdomain.c deleted file mode 100644 index 3968f1c3c5c308..00000000000000 --- a/drivers/sh/intc/irqdomain.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * IRQ domain support for SH INTC subsystem - * - * Copyright (C) 2012 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include <linux/irqdomain.h> -#include <linux/sh_intc.h> -#include <linux/export.h> -#include "internals.h" - -/** - * intc_irq_domain_evt_xlate() - Generic xlate for vectored IRQs. - * - * This takes care of exception vector to hwirq translation through - * by way of evt2irq() translation. - * - * Note: For platforms that use a flat vector space without INTEVT this - * basically just mimics irq_domain_xlate_onecell() by way of a nopped - * out evt2irq() implementation. - */ -static int intc_evt_xlate(struct irq_domain *d, struct device_node *ctrlr, - const u32 *intspec, unsigned int intsize, - unsigned long *out_hwirq, unsigned int *out_type) -{ - if (WARN_ON(intsize < 1)) - return -EINVAL; - - *out_hwirq = evt2irq(intspec[0]); - *out_type = IRQ_TYPE_NONE; - - return 0; -} - -static const struct irq_domain_ops intc_evt_ops = { - .xlate = intc_evt_xlate, -}; - -void __init intc_irq_domain_init(struct intc_desc_int *d, - struct intc_hw_desc *hw) -{ - unsigned int irq_base, irq_end; - - /* - * Quick linear revmap check - */ - irq_base = evt2irq(hw->vectors[0].vect); - irq_end = evt2irq(hw->vectors[hw->nr_vectors - 1].vect); - - /* - * Linear domains have a hard-wired assertion that IRQs start at - * 0 in order to make some performance optimizations. Lamely - * restrict the linear case to these conditions here, taking the - * tree penalty for linear cases with non-zero hwirq bases. - */ - if (irq_base == 0 && irq_end == (irq_base + hw->nr_vectors - 1)) - d->domain = irq_domain_add_linear(NULL, hw->nr_vectors, - &intc_evt_ops, NULL); - else - d->domain = irq_domain_add_tree(NULL, &intc_evt_ops, NULL); - - BUG_ON(!d->domain); -} diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c deleted file mode 100644 index f9f043a3d90a23..00000000000000 --- a/drivers/sh/intc/userimask.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Support for hardware-assisted userspace interrupt masking. - * - * Copyright (C) 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include <linux/errno.h> -#include <linux/device.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/stat.h> -#include <linux/sizes.h> -#include "internals.h" - -static void __iomem *uimask; - -static ssize_t -show_intc_userimask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf); -} - -static ssize_t -store_intc_userimask(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long level; - - level = simple_strtoul(buf, NULL, 10); - - /* - * Minimal acceptable IRQ levels are in the 2 - 16 range, but - * these are chomped so as to not interfere with normal IRQs. - * - * Level 1 is a special case on some CPUs in that it's not - * directly settable, but given that USERIMASK cuts off below a - * certain level, we don't care about this limitation here. - * Level 0 on the other hand equates to user masking disabled. - * - * We use the default priority level as a cut off so that only - * special case opt-in IRQs can be mangled. - */ - if (level >= intc_get_dfl_prio_level()) - return -EINVAL; - - __raw_writel(0xa5 << 24 | level << 4, uimask); - - return count; -} - -static DEVICE_ATTR(userimask, S_IRUSR | S_IWUSR, - show_intc_userimask, store_intc_userimask); - - -static int __init userimask_sysdev_init(void) -{ - if (unlikely(!uimask)) - return -ENXIO; - - return device_create_file(intc_subsys.dev_root, &dev_attr_userimask); -} -late_initcall(userimask_sysdev_init); - -int register_intc_userimask(unsigned long addr) -{ - if (unlikely(uimask)) - return -EBUSY; - - uimask = ioremap(addr, SZ_4K); - if (unlikely(!uimask)) - return -ENOMEM; - - pr_info("userimask support registered for levels 0 -> %d\n", - intc_get_dfl_prio_level() - 1); - - return 0; -} diff --git a/drivers/sh/intc/virq-debugfs.c b/drivers/sh/intc/virq-debugfs.c deleted file mode 100644 index 939915a07d9997..00000000000000 --- a/drivers/sh/intc/virq-debugfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Support for virtual IRQ subgroups debugfs mapping. - * - * Copyright (C) 2010 Paul Mundt - * - * Modelled after arch/powerpc/kernel/irq.c. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/seq_file.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/debugfs.h> -#include "internals.h" - -static int intc_irq_xlate_show(struct seq_file *m, void *priv) -{ - int i; - - seq_printf(m, "%-5s %-7s %-15s\n", "irq", "enum", "chip name"); - - for (i = 1; i < nr_irqs; i++) { - struct intc_map_entry *entry = intc_irq_xlate_get(i); - struct intc_desc_int *desc = entry->desc; - - if (!desc) - continue; - - seq_printf(m, "%5d ", i); - seq_printf(m, "0x%05x ", entry->enum_id); - seq_printf(m, "%-15s\n", desc->chip.name); - } - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(intc_irq_xlate); - -static int __init intc_irq_xlate_init(void) -{ - /* - * XXX.. use arch_debugfs_dir here when all of the intc users are - * converted. - */ - if (debugfs_create_file("intc_irq_xlate", S_IRUGO, NULL, NULL, - &intc_irq_xlate_fops) == NULL) - return -ENOMEM; - - return 0; -} -fs_initcall(intc_irq_xlate_init); diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c deleted file mode 100644 index a638c3048207c0..00000000000000 --- a/drivers/sh/intc/virq.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Support for virtual IRQ subgroups. - * - * Copyright (C) 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include <linux/slab.h> -#include <linux/irq.h> -#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[INTC_NR_IRQS]; - -struct intc_virq_list { - unsigned int irq; - struct intc_virq_list *next; -}; - -#define for_each_virq(entry, head) \ - for (entry = head; entry; entry = entry->next) - -/* - * Tags for the radix tree - */ -#define INTC_TAG_VIRQ_NEEDS_ALLOC 0 - -void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - intc_irq_xlate[irq].enum_id = id; - intc_irq_xlate[irq].desc = d; - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} - -struct intc_map_entry *intc_irq_xlate_get(unsigned int irq) -{ - return intc_irq_xlate + irq; -} - -int intc_irq_lookup(const char *chipname, intc_enum enum_id) -{ - struct intc_map_entry *ptr; - struct intc_desc_int *d; - int irq = -1; - - list_for_each_entry(d, &intc_list, list) { - int tagged; - - if (strcmp(d->chip.name, chipname) != 0) - continue; - - /* - * Catch early lookups for subgroup VIRQs that have not - * yet been allocated an IRQ. This already includes a - * fast-path out if the tree is untagged, so there is no - * need to explicitly test the root tree. - */ - tagged = radix_tree_tag_get(&d->tree, enum_id, - INTC_TAG_VIRQ_NEEDS_ALLOC); - if (unlikely(tagged)) - break; - - ptr = radix_tree_lookup(&d->tree, enum_id); - if (ptr) { - irq = ptr - intc_irq_xlate; - break; - } - } - - return irq; -} -EXPORT_SYMBOL_GPL(intc_irq_lookup); - -static int add_virq_to_pirq(unsigned int irq, unsigned int virq) -{ - struct intc_virq_list *entry; - struct intc_virq_list **last = NULL; - - /* scan for duplicates */ - for_each_virq(entry, irq_get_handler_data(irq)) { - if (entry->irq == virq) - return 0; - last = &entry->next; - } - - entry = kzalloc(sizeof(struct intc_virq_list), GFP_ATOMIC); - if (!entry) - return -ENOMEM; - - entry->irq = virq; - - if (last) - *last = entry; - else - irq_set_handler_data(irq, entry); - - return 0; -} - -static void intc_virq_handler(struct irq_desc *desc) -{ - unsigned int irq = irq_desc_get_irq(desc); - struct irq_data *data = irq_desc_get_irq_data(desc); - struct irq_chip *chip = irq_data_get_irq_chip(data); - struct intc_virq_list *entry, *vlist = irq_data_get_irq_handler_data(data); - struct intc_desc_int *d = get_intc_desc(irq); - - chip->irq_mask_ack(data); - - for_each_virq(entry, vlist) { - unsigned long addr, handle; - struct irq_desc *vdesc = irq_to_desc(entry->irq); - - if (vdesc) { - handle = (unsigned long)irq_desc_get_handler_data(vdesc); - addr = INTC_REG(d, _INTC_ADDR_E(handle), 0); - if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0)) - generic_handle_irq_desc(vdesc); - } - } - - chip->irq_unmask(data); -} - -static unsigned long __init intc_subgroup_data(struct intc_subgroup *subgroup, - struct intc_desc_int *d, - unsigned int index) -{ - unsigned int fn = REG_FN_TEST_BASE + (subgroup->reg_width >> 3) - 1; - - return _INTC_MK(fn, MODE_ENABLE_REG, intc_get_reg(d, subgroup->reg), - 0, 1, (subgroup->reg_width - 1) - index); -} - -static void __init intc_subgroup_init_one(struct intc_desc *desc, - struct intc_desc_int *d, - struct intc_subgroup *subgroup) -{ - struct intc_map_entry *mapped; - unsigned int pirq; - unsigned long flags; - int i; - - mapped = radix_tree_lookup(&d->tree, subgroup->parent_id); - if (!mapped) { - WARN_ON(1); - return; - } - - pirq = mapped - intc_irq_xlate; - - raw_spin_lock_irqsave(&d->lock, flags); - - for (i = 0; i < ARRAY_SIZE(subgroup->enum_ids); i++) { - struct intc_subgroup_entry *entry; - int err; - - if (!subgroup->enum_ids[i]) - continue; - - entry = kmalloc(sizeof(*entry), GFP_NOWAIT); - if (!entry) - break; - - entry->pirq = pirq; - entry->enum_id = subgroup->enum_ids[i]; - entry->handle = intc_subgroup_data(subgroup, d, i); - - err = radix_tree_insert(&d->tree, entry->enum_id, entry); - if (unlikely(err < 0)) - break; - - radix_tree_tag_set(&d->tree, entry->enum_id, - INTC_TAG_VIRQ_NEEDS_ALLOC); - } - - raw_spin_unlock_irqrestore(&d->lock, flags); -} - -void __init intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d) -{ - int i; - - if (!desc->hw.subgroups) - return; - - for (i = 0; i < desc->hw.nr_subgroups; i++) - intc_subgroup_init_one(desc, d, desc->hw.subgroups + i); -} - -static void __init intc_subgroup_map(struct intc_desc_int *d) -{ - struct intc_subgroup_entry *entries[32]; - unsigned long flags; - unsigned int nr_found; - int i; - - raw_spin_lock_irqsave(&d->lock, flags); - -restart: - nr_found = radix_tree_gang_lookup_tag_slot(&d->tree, - (void ***)entries, 0, ARRAY_SIZE(entries), - INTC_TAG_VIRQ_NEEDS_ALLOC); - - for (i = 0; i < nr_found; i++) { - struct intc_subgroup_entry *entry; - int irq; - - entry = radix_tree_deref_slot((void **)entries[i]); - if (unlikely(!entry)) - continue; - if (radix_tree_deref_retry(entry)) - goto restart; - - irq = irq_alloc_desc(numa_node_id()); - if (unlikely(irq < 0)) { - pr_err("no more free IRQs, bailing..\n"); - break; - } - - activate_irq(irq); - - pr_info("Setting up a chained VIRQ from %d -> %d\n", - irq, entry->pirq); - - intc_irq_xlate_set(irq, entry->enum_id, d); - - irq_set_chip_and_handler_name(irq, irq_get_chip(entry->pirq), - handle_simple_irq, "virq"); - irq_set_chip_data(irq, irq_get_chip_data(entry->pirq)); - - irq_set_handler_data(irq, (void *)entry->handle); - - /* - * Set the virtual IRQ as non-threadable. - */ - irq_set_nothread(irq); - - /* Set handler data before installing the handler */ - add_virq_to_pirq(entry->pirq, irq); - irq_set_chained_handler(entry->pirq, intc_virq_handler); - - radix_tree_tag_clear(&d->tree, entry->enum_id, - INTC_TAG_VIRQ_NEEDS_ALLOC); - radix_tree_replace_slot(&d->tree, (void **)entries[i], - &intc_irq_xlate[irq]); - } - - raw_spin_unlock_irqrestore(&d->lock, flags); -} - -void __init intc_finalize(void) -{ - struct intc_desc_int *d; - - list_for_each_entry(d, &intc_list, list) - if (radix_tree_tagged(&d->tree, INTC_TAG_VIRQ_NEEDS_ALLOC)) - intc_subgroup_map(d); -} diff --git a/drivers/sh/maple/Makefile b/drivers/sh/maple/Makefile deleted file mode 100644 index c3a80910c212ce..00000000000000 --- a/drivers/sh/maple/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Makefile for Maple Bus - -obj-$(CONFIG_MAPLE) := maple.o diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c deleted file mode 100644 index e24e220e56eea1..00000000000000 --- a/drivers/sh/maple/maple.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Core maple bus functionality - * - * Copyright (C) 2007 - 2009 Adrian McMenamin - * Copyright (C) 2001 - 2008 Paul Mundt - * Copyright (C) 2000 - 2001 YAEGASHI Takeshi - * Copyright (C) 2001 M. R. Brown - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/io.h> -#include <linux/slab.h> -#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> -#include <mach/dma.h> -#include <mach/sysasic.h> - -MODULE_AUTHOR("Adrian McMenamin <adrian@xxxxxxxxxxxxxxxxx>"); -MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); -MODULE_LICENSE("GPL v2"); - -static void maple_dma_handler(struct work_struct *work); -static void maple_vblank_handler(struct work_struct *work); - -static DECLARE_WORK(maple_dma_process, maple_dma_handler); -static DECLARE_WORK(maple_vblank_process, maple_vblank_handler); - -static LIST_HEAD(maple_waitq); -static LIST_HEAD(maple_sentq); - -/* mutex to protect queue of waiting packets */ -static DEFINE_MUTEX(maple_wlist_lock); - -static struct maple_driver maple_unsupported_device; -static struct device maple_bus; -static int subdevice_map[MAPLE_PORTS]; -static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; -static unsigned long maple_pnp_time; -static int started, scanning, fullscan; -static struct kmem_cache *maple_queue_cache; - -struct maple_device_specify { - int port; - int unit; -}; - -static bool checked[MAPLE_PORTS]; -static bool empty[MAPLE_PORTS]; -static struct maple_device *baseunits[MAPLE_PORTS]; - -/** - * maple_driver_register - register a maple driver - * @drv: maple driver to be registered. - * - * Registers the passed in @drv, while updating the bus type. - * Devices with matching function IDs will be automatically probed. - */ -int maple_driver_register(struct maple_driver *drv) -{ - if (!drv) - return -EINVAL; - - drv->drv.bus = &maple_bus_type; - - return driver_register(&drv->drv); -} -EXPORT_SYMBOL_GPL(maple_driver_register); - -/** - * maple_driver_unregister - unregister a maple driver. - * @drv: maple driver to unregister. - * - * Cleans up after maple_driver_register(). To be invoked in the exit - * path of any module drivers. - */ -void maple_driver_unregister(struct maple_driver *drv) -{ - driver_unregister(&drv->drv); -} -EXPORT_SYMBOL_GPL(maple_driver_unregister); - -/* set hardware registers to enable next round of dma */ -static void maple_dma_reset(void) -{ - __raw_writel(MAPLE_MAGIC, MAPLE_RESET); - /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ - __raw_writel(1, MAPLE_TRIGTYPE); - /* - * Maple system register - * bits 31 - 16 timeout in units of 20nsec - * bit 12 hard trigger - set 0 to keep responding to VBLANK - * bits 9 - 8 set 00 for 2 Mbps, 01 for 1 Mbps - * bits 3 - 0 delay (in 1.3ms) between VBLANK and start of DMA - * max delay is 11 - */ - __raw_writel(MAPLE_2MBPS | MAPLE_TIMEOUT(0xFFFF), MAPLE_SPEED); - __raw_writel(virt_to_phys(maple_sendbuf), MAPLE_DMAADDR); - __raw_writel(1, MAPLE_ENABLE); -} - -/** - * maple_getcond_callback - setup handling MAPLE_COMMAND_GETCOND - * @dev: device responding - * @callback: handler callback - * @interval: interval in jiffies between callbacks - * @function: the function code for the device - */ -void maple_getcond_callback(struct maple_device *dev, - void (*callback) (struct mapleq *mq), - unsigned long interval, unsigned long function) -{ - dev->callback = callback; - dev->interval = interval; - dev->function = cpu_to_be32(function); - dev->when = jiffies; -} -EXPORT_SYMBOL_GPL(maple_getcond_callback); - -static int maple_dma_done(void) -{ - return (__raw_readl(MAPLE_STATE) & 1) == 0; -} - -static void maple_release_device(struct device *dev) -{ - struct maple_device *mdev; - struct mapleq *mq; - - mdev = to_maple_dev(dev); - mq = mdev->mq; - kmem_cache_free(maple_queue_cache, mq->recvbuf); - kfree(mq); - kfree(mdev); -} - -/** - * maple_add_packet - add a single instruction to the maple bus queue - * @mdev: maple device - * @function: function on device being queried - * @command: maple command to add - * @length: length of command string (in 32 bit words) - * @data: remainder of command string - */ -int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, - size_t length, void *data) -{ - int ret = 0; - void *sendbuf = NULL; - - if (length) { - sendbuf = kcalloc(length, 4, GFP_KERNEL); - if (!sendbuf) { - ret = -ENOMEM; - goto out; - } - ((__be32 *)sendbuf)[0] = cpu_to_be32(function); - } - - mdev->mq->command = command; - mdev->mq->length = length; - if (length > 1) - memcpy(sendbuf + 4, data, (length - 1) * 4); - mdev->mq->sendbuf = sendbuf; - - mutex_lock(&maple_wlist_lock); - list_add_tail(&mdev->mq->list, &maple_waitq); - mutex_unlock(&maple_wlist_lock); -out: - return ret; -} -EXPORT_SYMBOL_GPL(maple_add_packet); - -static struct mapleq *maple_allocq(struct maple_device *mdev) -{ - struct mapleq *mq; - - mq = kzalloc(sizeof(*mq), GFP_KERNEL); - if (!mq) - goto failed_nomem; - - INIT_LIST_HEAD(&mq->list); - mq->dev = mdev; - mq->recvbuf = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); - if (!mq->recvbuf) - goto failed_p2; - mq->recvbuf->buf = &((mq->recvbuf->bufx)[0]); - - return mq; - -failed_p2: - kfree(mq); -failed_nomem: - dev_err(&mdev->dev, "could not allocate memory for device (%d, %d)\n", - mdev->port, mdev->unit); - return NULL; -} - -static struct maple_device *maple_alloc_dev(int port, int unit) -{ - struct maple_device *mdev; - - /* zero this out to avoid kobj subsystem - * thinking it has already been registered */ - - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return NULL; - - mdev->port = port; - mdev->unit = unit; - - mdev->mq = maple_allocq(mdev); - - if (!mdev->mq) { - kfree(mdev); - return NULL; - } - mdev->dev.bus = &maple_bus_type; - mdev->dev.parent = &maple_bus; - init_waitqueue_head(&mdev->maple_wait); - return mdev; -} - -static void maple_free_dev(struct maple_device *mdev) -{ - kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf); - kfree(mdev->mq); - kfree(mdev); -} - -/* process the command queue into a maple command block - * terminating command has bit 32 of first long set to 0 - */ -static void maple_build_block(struct mapleq *mq) -{ - int port, unit, from, to, len; - unsigned long *lsendbuf = mq->sendbuf; - - port = mq->dev->port & 3; - unit = mq->dev->unit; - len = mq->length; - from = port << 6; - to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20); - - *maple_lastptr &= 0x7fffffff; - maple_lastptr = maple_sendptr; - - *maple_sendptr++ = (port << 16) | len | 0x80000000; - *maple_sendptr++ = virt_to_phys(mq->recvbuf->buf); - *maple_sendptr++ = - mq->command | (to << 8) | (from << 16) | (len << 24); - while (len-- > 0) - *maple_sendptr++ = *lsendbuf++; -} - -/* build up command queue */ -static void maple_send(void) -{ - int i, maple_packets = 0; - struct mapleq *mq, *nmq; - - if (!maple_dma_done()) - return; - - /* disable DMA */ - __raw_writel(0, MAPLE_ENABLE); - - if (!list_empty(&maple_sentq)) - goto finish; - - mutex_lock(&maple_wlist_lock); - if (list_empty(&maple_waitq)) { - mutex_unlock(&maple_wlist_lock); - goto finish; - } - - maple_lastptr = maple_sendbuf; - maple_sendptr = maple_sendbuf; - - list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { - maple_build_block(mq); - list_del_init(&mq->list); - list_add_tail(&mq->list, &maple_sentq); - if (maple_packets++ > MAPLE_MAXPACKETS) - break; - } - mutex_unlock(&maple_wlist_lock); - if (maple_packets > 0) { - for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) - __flush_purge_region(maple_sendbuf + i * PAGE_SIZE, - PAGE_SIZE); - } - -finish: - maple_dma_reset(); -} - -/* check if there is a driver registered likely to match this device */ -static int maple_check_matching_driver(struct device_driver *driver, - void *devptr) -{ - struct maple_driver *maple_drv; - struct maple_device *mdev; - - mdev = devptr; - maple_drv = to_maple_driver(driver); - if (mdev->devinfo.function & cpu_to_be32(maple_drv->function)) - return 1; - return 0; -} - -static void maple_detach_driver(struct maple_device *mdev) -{ - device_unregister(&mdev->dev); -} - -/* process initial MAPLE_COMMAND_DEVINFO for each device or port */ -static void maple_attach_driver(struct maple_device *mdev) -{ - char *p, *recvbuf; - unsigned long function; - int matched, error; - - recvbuf = mdev->mq->recvbuf->buf; - /* copy the data as individual elements in - * case of memory optimisation */ - memcpy(&mdev->devinfo.function, recvbuf + 4, 4); - memcpy(&mdev->devinfo.function_data[0], recvbuf + 8, 12); - memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1); - memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1); - memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30); - memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2); - memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2); - memcpy(mdev->product_name, mdev->devinfo.product_name, 30); - mdev->product_name[30] = '\0'; - memcpy(mdev->product_licence, mdev->devinfo.product_licence, 60); - mdev->product_licence[60] = '\0'; - - for (p = mdev->product_name + 29; mdev->product_name <= p; p--) - if (*p == ' ') - *p = '\0'; - else - break; - for (p = mdev->product_licence + 59; mdev->product_licence <= p; p--) - if (*p == ' ') - *p = '\0'; - else - break; - - function = be32_to_cpu(mdev->devinfo.function); - - dev_info(&mdev->dev, "detected %s: function 0x%lX: at (%d, %d)\n", - mdev->product_name, function, mdev->port, mdev->unit); - - if (function > 0x200) { - /* Do this silently - as not a real device */ - function = 0; - mdev->driver = &maple_unsupported_device; - dev_set_name(&mdev->dev, "%d:0.port", mdev->port); - } else { - matched = - bus_for_each_drv(&maple_bus_type, NULL, mdev, - maple_check_matching_driver); - - if (matched == 0) { - /* Driver does not exist yet */ - dev_info(&mdev->dev, "no driver found\n"); - mdev->driver = &maple_unsupported_device; - } - dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, - mdev->unit, function); - } - - mdev->function = function; - mdev->dev.release = &maple_release_device; - - atomic_set(&mdev->busy, 0); - error = device_register(&mdev->dev); - if (error) { - dev_warn(&mdev->dev, "could not register device at" - " (%d, %d), with error 0x%X\n", mdev->unit, - mdev->port, error); - maple_free_dev(mdev); - mdev = NULL; - return; - } -} - -/* - * if device has been registered for the given - * port and unit then return 1 - allows identification - * of which devices need to be attached or detached - */ -static int check_maple_device(struct device *device, void *portptr) -{ - struct maple_device_specify *ds; - struct maple_device *mdev; - - ds = portptr; - mdev = to_maple_dev(device); - if (mdev->port == ds->port && mdev->unit == ds->unit) - return 1; - return 0; -} - -static int setup_maple_commands(struct device *device, void *ignored) -{ - int add; - struct maple_device *mdev = to_maple_dev(device); - if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 && - time_after(jiffies, mdev->when)) { - /* bounce if we cannot add */ - add = maple_add_packet(mdev, - be32_to_cpu(mdev->devinfo.function), - MAPLE_COMMAND_GETCOND, 1, NULL); - if (!add) - mdev->when = jiffies + mdev->interval; - } else { - if (time_after(jiffies, maple_pnp_time)) - /* Ensure we don't have block reads and devinfo - * calls interfering with one another - so flag the - * device as busy */ - if (atomic_read(&mdev->busy) == 0) { - atomic_set(&mdev->busy, 1); - maple_add_packet(mdev, 0, - MAPLE_COMMAND_DEVINFO, 0, NULL); - } - } - return 0; -} - -/* VBLANK bottom half - implemented via workqueue */ -static void maple_vblank_handler(struct work_struct *work) -{ - int x, locking; - struct maple_device *mdev; - - if (!maple_dma_done()) - return; - - __raw_writel(0, MAPLE_ENABLE); - - if (!list_empty(&maple_sentq)) - goto finish; - - /* - * Set up essential commands - to fetch data and - * check devices are still present - */ - bus_for_each_dev(&maple_bus_type, NULL, NULL, - setup_maple_commands); - - if (time_after(jiffies, maple_pnp_time)) { - /* - * Scan the empty ports - bus is flakey and may have - * mis-reported emptyness - */ - for (x = 0; x < MAPLE_PORTS; x++) { - if (checked[x] && empty[x]) { - mdev = baseunits[x]; - if (!mdev) - break; - atomic_set(&mdev->busy, 1); - locking = maple_add_packet(mdev, 0, - MAPLE_COMMAND_DEVINFO, 0, NULL); - if (!locking) - break; - } - } - - maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; - } - -finish: - maple_send(); -} - -/* handle devices added via hotplugs - placing them on queue for DEVINFO */ -static void maple_map_subunits(struct maple_device *mdev, int submask) -{ - int retval, k, devcheck; - struct maple_device *mdev_add; - struct maple_device_specify ds; - - ds.port = mdev->port; - for (k = 0; k < 5; k++) { - ds.unit = k + 1; - retval = - bus_for_each_dev(&maple_bus_type, NULL, &ds, - check_maple_device); - if (retval) { - submask = submask >> 1; - continue; - } - devcheck = submask & 0x01; - if (devcheck) { - mdev_add = maple_alloc_dev(mdev->port, k + 1); - if (!mdev_add) - return; - atomic_set(&mdev_add->busy, 1); - maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, - 0, NULL); - /* mark that we are checking sub devices */ - scanning = 1; - } - submask = submask >> 1; - } -} - -/* mark a device as removed */ -static void maple_clean_submap(struct maple_device *mdev) -{ - int killbit; - - killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20); - killbit = ~killbit; - killbit &= 0xFF; - subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit; -} - -/* handle empty port or hotplug removal */ -static void maple_response_none(struct maple_device *mdev) -{ - maple_clean_submap(mdev); - - if (likely(mdev->unit != 0)) { - /* - * Block devices play up - * and give the impression they have - * been removed even when still in place or - * trip the mtd layer when they have - * really gone - this code traps that eventuality - * and ensures we aren't overloaded with useless - * error messages - */ - if (mdev->can_unload) { - if (!mdev->can_unload(mdev)) { - atomic_set(&mdev->busy, 2); - wake_up(&mdev->maple_wait); - return; - } - } - - dev_info(&mdev->dev, "detaching device at (%d, %d)\n", - mdev->port, mdev->unit); - maple_detach_driver(mdev); - return; - } else { - if (!started || !fullscan) { - if (checked[mdev->port] == false) { - checked[mdev->port] = true; - empty[mdev->port] = true; - dev_info(&mdev->dev, "no devices" - " to port %d\n", mdev->port); - } - return; - } - } - /* Some hardware devices generate false detach messages on unit 0 */ - atomic_set(&mdev->busy, 0); -} - -/* preprocess hotplugs or scans */ -static void maple_response_devinfo(struct maple_device *mdev, - char *recvbuf) -{ - char submask; - if (!started || (scanning == 2) || !fullscan) { - if ((mdev->unit == 0) && (checked[mdev->port] == false)) { - checked[mdev->port] = true; - maple_attach_driver(mdev); - } else { - if (mdev->unit != 0) - maple_attach_driver(mdev); - if (mdev->unit == 0) { - empty[mdev->port] = false; - maple_attach_driver(mdev); - } - } - } - if (mdev->unit == 0) { - submask = recvbuf[2] & 0x1F; - if (submask ^ subdevice_map[mdev->port]) { - maple_map_subunits(mdev, submask); - subdevice_map[mdev->port] = submask; - } - } -} - -static void maple_response_fileerr(struct maple_device *mdev, void *recvbuf) -{ - if (mdev->fileerr_handler) { - mdev->fileerr_handler(mdev, recvbuf); - return; - } else - dev_warn(&mdev->dev, "device at (%d, %d) reports" - "file error 0x%X\n", mdev->port, mdev->unit, - ((int *)recvbuf)[1]); -} - -static void maple_port_rescan(void) -{ - int i; - struct maple_device *mdev; - - fullscan = 1; - for (i = 0; i < MAPLE_PORTS; i++) { - if (checked[i] == false) { - fullscan = 0; - mdev = baseunits[i]; - maple_add_packet(mdev, 0, MAPLE_COMMAND_DEVINFO, - 0, NULL); - } - } -} - -/* maple dma end bottom half - implemented via workqueue */ -static void maple_dma_handler(struct work_struct *work) -{ - struct mapleq *mq, *nmq; - struct maple_device *mdev; - char *recvbuf; - enum maple_code code; - - if (!maple_dma_done()) - return; - __raw_writel(0, MAPLE_ENABLE); - if (!list_empty(&maple_sentq)) { - list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { - mdev = mq->dev; - recvbuf = mq->recvbuf->buf; - __flush_invalidate_region(sh_cacheop_vaddr(recvbuf), - 0x400); - code = recvbuf[0]; - kfree(mq->sendbuf); - list_del_init(&mq->list); - switch (code) { - case MAPLE_RESPONSE_NONE: - maple_response_none(mdev); - break; - - case MAPLE_RESPONSE_DEVINFO: - maple_response_devinfo(mdev, recvbuf); - atomic_set(&mdev->busy, 0); - break; - - case MAPLE_RESPONSE_DATATRF: - if (mdev->callback) - mdev->callback(mq); - atomic_set(&mdev->busy, 0); - wake_up(&mdev->maple_wait); - break; - - case MAPLE_RESPONSE_FILEERR: - maple_response_fileerr(mdev, recvbuf); - atomic_set(&mdev->busy, 0); - wake_up(&mdev->maple_wait); - break; - - case MAPLE_RESPONSE_AGAIN: - case MAPLE_RESPONSE_BADCMD: - case MAPLE_RESPONSE_BADFUNC: - dev_warn(&mdev->dev, "non-fatal error" - " 0x%X at (%d, %d)\n", code, - mdev->port, mdev->unit); - atomic_set(&mdev->busy, 0); - break; - - case MAPLE_RESPONSE_ALLINFO: - dev_notice(&mdev->dev, "extended" - " device information request for (%d, %d)" - " but call is not supported\n", mdev->port, - mdev->unit); - atomic_set(&mdev->busy, 0); - break; - - case MAPLE_RESPONSE_OK: - atomic_set(&mdev->busy, 0); - wake_up(&mdev->maple_wait); - break; - - default: - break; - } - } - /* if scanning is 1 then we have subdevices to check */ - if (scanning == 1) { - maple_send(); - scanning = 2; - } else - scanning = 0; - /*check if we have actually tested all ports yet */ - if (!fullscan) - maple_port_rescan(); - /* mark that we have been through the first scan */ - started = 1; - } - maple_send(); -} - -static irqreturn_t maple_dma_interrupt(int irq, void *dev_id) -{ - /* Load everything into the bottom half */ - schedule_work(&maple_dma_process); - return IRQ_HANDLED; -} - -static irqreturn_t maple_vblank_interrupt(int irq, void *dev_id) -{ - schedule_work(&maple_vblank_process); - return IRQ_HANDLED; -} - -static int maple_set_dma_interrupt_handler(void) -{ - return request_irq(HW_EVENT_MAPLE_DMA, maple_dma_interrupt, - IRQF_SHARED, "maple bus DMA", &maple_unsupported_device); -} - -static int maple_set_vblank_interrupt_handler(void) -{ - return request_irq(HW_EVENT_VSYNC, maple_vblank_interrupt, - IRQF_SHARED, "maple bus VBLANK", &maple_unsupported_device); -} - -static int maple_get_dma_buffer(void) -{ - maple_sendbuf = - (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, - MAPLE_DMA_PAGES); - if (!maple_sendbuf) - return -ENOMEM; - return 0; -} - -static int maple_match_bus_driver(struct device *devptr, - struct device_driver *drvptr) -{ - struct maple_driver *maple_drv = to_maple_driver(drvptr); - struct maple_device *maple_dev = to_maple_dev(devptr); - - /* Trap empty port case */ - if (maple_dev->devinfo.function == 0xFFFFFFFF) - return 0; - else if (maple_dev->devinfo.function & - cpu_to_be32(maple_drv->function)) - return 1; - return 0; -} - -static int maple_bus_uevent(struct device *dev, - struct kobj_uevent_env *env) -{ - return 0; -} - -static void maple_bus_release(struct device *dev) -{ -} - -static struct maple_driver maple_unsupported_device = { - .drv = { - .name = "maple_unsupported_device", - .bus = &maple_bus_type, - }, -}; -/* - * maple_bus_type - core maple bus structure - */ -struct bus_type maple_bus_type = { - .name = "maple", - .match = maple_match_bus_driver, - .uevent = maple_bus_uevent, -}; -EXPORT_SYMBOL_GPL(maple_bus_type); - -static struct device maple_bus = { - .init_name = "maple", - .release = maple_bus_release, -}; - -static int __init maple_bus_init(void) -{ - int retval, i; - struct maple_device *mdev[MAPLE_PORTS]; - - __raw_writel(0, MAPLE_ENABLE); - - retval = device_register(&maple_bus); - if (retval) - goto cleanup; - - retval = bus_register(&maple_bus_type); - if (retval) - goto cleanup_device; - - retval = driver_register(&maple_unsupported_device.drv); - if (retval) - goto cleanup_bus; - - /* allocate memory for maple bus dma */ - retval = maple_get_dma_buffer(); - if (retval) { - dev_err(&maple_bus, "failed to allocate DMA buffers\n"); - goto cleanup_basic; - } - - /* set up DMA interrupt handler */ - retval = maple_set_dma_interrupt_handler(); - if (retval) { - dev_err(&maple_bus, "bus failed to grab maple " - "DMA IRQ\n"); - goto cleanup_dma; - } - - /* set up VBLANK interrupt handler */ - retval = maple_set_vblank_interrupt_handler(); - if (retval) { - dev_err(&maple_bus, "bus failed to grab VBLANK IRQ\n"); - goto cleanup_irq; - } - - maple_queue_cache = KMEM_CACHE(maple_buffer, SLAB_HWCACHE_ALIGN); - - if (!maple_queue_cache) { - retval = -ENOMEM; - goto cleanup_bothirqs; - } - - INIT_LIST_HEAD(&maple_waitq); - INIT_LIST_HEAD(&maple_sentq); - - /* setup maple ports */ - for (i = 0; i < MAPLE_PORTS; i++) { - checked[i] = false; - empty[i] = false; - mdev[i] = maple_alloc_dev(i, 0); - if (!mdev[i]) { - while (i-- > 0) - maple_free_dev(mdev[i]); - retval = -ENOMEM; - goto cleanup_cache; - } - baseunits[i] = mdev[i]; - atomic_set(&mdev[i]->busy, 1); - maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); - subdevice_map[i] = 0; - } - - maple_pnp_time = jiffies + HZ; - /* prepare initial queue */ - maple_send(); - dev_info(&maple_bus, "bus core now registered\n"); - - return 0; - -cleanup_cache: - kmem_cache_destroy(maple_queue_cache); - -cleanup_bothirqs: - free_irq(HW_EVENT_VSYNC, 0); - -cleanup_irq: - free_irq(HW_EVENT_MAPLE_DMA, 0); - -cleanup_dma: - free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); - -cleanup_basic: - driver_unregister(&maple_unsupported_device.drv); - -cleanup_bus: - bus_unregister(&maple_bus_type); - -cleanup_device: - device_unregister(&maple_bus); - -cleanup: - printk(KERN_ERR "Maple bus registration failed\n"); - return retval; -} -/* Push init to later to ensure hardware gets detected */ -fs_initcall(maple_bus_init); diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c deleted file mode 100644 index c887ecdaf19b7c..00000000000000 --- a/drivers/sh/pm_runtime.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Runtime PM support code - * - * Copyright (C) 2009-2010 Magnus Damm - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/pm_runtime.h> -#include <linux/pm_domain.h> -#include <linux/pm_clock.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/sh_clk.h> -#include <linux/bitmap.h> -#include <linux/slab.h> - -static struct dev_pm_domain default_pm_domain = { - .ops = { - USE_PM_CLK_RUNTIME_OPS - USE_PLATFORM_PM_SLEEP_OPS - }, -}; - -static struct pm_clk_notifier_block platform_bus_notifier = { - .pm_domain = &default_pm_domain, - .con_ids = { NULL, }, -}; - -static int __init sh_pm_runtime_init(void) -{ - pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); - return 0; -} -core_initcall(sh_pm_runtime_init); diff --git a/drivers/sh/superhyway/Makefile b/drivers/sh/superhyway/Makefile deleted file mode 100644 index 6dfa41f160af6b..00000000000000 --- a/drivers/sh/superhyway/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the SuperHyway bus drivers. -# - -obj-$(CONFIG_SUPERHYWAY) += superhyway.o -obj-$(CONFIG_SYSFS) += superhyway-sysfs.o - diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c deleted file mode 100644 index 774f31b564f8f8..00000000000000 --- a/drivers/sh/superhyway/superhyway-sysfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * drivers/sh/superhyway/superhyway-sysfs.c - * - * SuperHyway Bus sysfs interface - * - * Copyright (C) 2004, 2005 Paul Mundt <lethal@xxxxxxxxxxxx> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/superhyway.h> - -#define superhyway_ro_attr(name, fmt, field) \ -static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct superhyway_device *s = to_superhyway_device(dev); \ - return sprintf(buf, fmt, s->field); \ -} \ -static DEVICE_ATTR_RO(name); - -/* VCR flags */ -superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags); -superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags); -superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers); -superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id); -superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb); -superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb); - -/* Misc */ -superhyway_ro_attr(resource, "0x%08lx\n", resource[0].start); - -static struct attribute *superhyway_dev_attrs[] = { - &dev_attr_perr_flags.attr, - &dev_attr_merr_flags.attr, - &dev_attr_mod_vers.attr, - &dev_attr_mod_id.attr, - &dev_attr_bot_mb.attr, - &dev_attr_top_mb.attr, - &dev_attr_resource.attr, - NULL, -}; - -static const struct attribute_group superhyway_dev_group = { - .attrs = superhyway_dev_attrs, -}; - -const struct attribute_group *superhyway_dev_groups[] = { - &superhyway_dev_group, - NULL, -}; diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c deleted file mode 100644 index 44324abe21dada..00000000000000 --- a/drivers/sh/superhyway/superhyway.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * drivers/sh/superhyway/superhyway.c - * - * SuperHyway Bus Driver - * - * Copyright (C) 2004, 2005 Paul Mundt <lethal@xxxxxxxxxxxx> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/list.h> -#include <linux/superhyway.h> -#include <linux/string.h> -#include <linux/slab.h> - -static int superhyway_devices; - -static struct device superhyway_bus_device = { - .init_name = "superhyway", -}; - -static void superhyway_device_release(struct device *dev) -{ - struct superhyway_device *sdev = to_superhyway_device(dev); - - kfree(sdev->resource); - kfree(sdev); -} - -/** - * superhyway_add_device - Add a SuperHyway module - * @base: Physical address where module is mapped. - * @sdev: SuperHyway device to add, or NULL to allocate a new one. - * @bus: Bus where SuperHyway module resides. - * - * This is responsible for adding a new SuperHyway module. This sets up a new - * struct superhyway_device for the module being added if @sdev == NULL. - * - * Devices are initially added in the order that they are scanned (from the - * top-down of the memory map), and are assigned an ID based on the order that - * they are added. Any manual addition of a module will thus get the ID after - * the devices already discovered regardless of where it resides in memory. - * - * Further work can and should be done in superhyway_scan_bus(), to be sure - * that any new modules are properly discovered and subsequently registered. - */ -int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, - struct superhyway_bus *bus) -{ - struct superhyway_device *dev = sdev; - - if (!dev) { - dev = kzalloc(sizeof(struct superhyway_device), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - } - - dev->bus = bus; - superhyway_read_vcr(dev, base, &dev->vcr); - - if (!dev->resource) { - dev->resource = kzalloc(sizeof(struct resource), GFP_KERNEL); - if (!dev->resource) { - kfree(dev); - return -ENOMEM; - } - - dev->resource->name = dev->name; - dev->resource->start = base; - dev->resource->end = dev->resource->start + 0x01000000; - } - - dev->dev.parent = &superhyway_bus_device; - dev->dev.bus = &superhyway_bus_type; - dev->dev.release = superhyway_device_release; - dev->id.id = dev->vcr.mod_id; - - sprintf(dev->name, "SuperHyway device %04x", dev->id.id); - dev_set_name(&dev->dev, "%02x", superhyway_devices); - - superhyway_devices++; - - return device_register(&dev->dev); -} - -int superhyway_add_devices(struct superhyway_bus *bus, - struct superhyway_device **devices, - int nr_devices) -{ - int i, ret = 0; - - for (i = 0; i < nr_devices; i++) { - struct superhyway_device *dev = devices[i]; - ret |= superhyway_add_device(dev->resource[0].start, dev, bus); - } - - return ret; -} - -static int __init superhyway_init(void) -{ - struct superhyway_bus *bus; - int ret; - - ret = device_register(&superhyway_bus_device); - if (unlikely(ret)) - return ret; - - for (bus = superhyway_channels; bus->ops; bus++) - ret |= superhyway_scan_bus(bus); - - return ret; -} -postcore_initcall(superhyway_init); - -static const struct superhyway_device_id * -superhyway_match_id(const struct superhyway_device_id *ids, - struct superhyway_device *dev) -{ - while (ids->id) { - if (ids->id == dev->id.id) - return ids; - - ids++; - } - - return NULL; -} - -static int superhyway_device_probe(struct device *dev) -{ - struct superhyway_device *shyway_dev = to_superhyway_device(dev); - struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver); - - if (shyway_drv && shyway_drv->probe) { - const struct superhyway_device_id *id; - - id = superhyway_match_id(shyway_drv->id_table, shyway_dev); - if (id) - return shyway_drv->probe(shyway_dev, id); - } - - return -ENODEV; -} - -static void superhyway_device_remove(struct device *dev) -{ - struct superhyway_device *shyway_dev = to_superhyway_device(dev); - struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver); - - if (shyway_drv->remove) - shyway_drv->remove(shyway_dev); -} - -/** - * superhyway_register_driver - Register a new SuperHyway driver - * @drv: SuperHyway driver to register. - * - * This registers the passed in @drv. Any devices matching the id table will - * automatically be populated and handed off to the driver's specified probe - * routine. - */ -int superhyway_register_driver(struct superhyway_driver *drv) -{ - drv->drv.name = drv->name; - drv->drv.bus = &superhyway_bus_type; - - return driver_register(&drv->drv); -} - -/** - * superhyway_unregister_driver - Unregister a SuperHyway driver - * @drv: SuperHyway driver to unregister. - * - * This cleans up after superhyway_register_driver(), and should be invoked in - * the exit path of any module drivers. - */ -void superhyway_unregister_driver(struct superhyway_driver *drv) -{ - driver_unregister(&drv->drv); -} - -static int superhyway_bus_match(struct device *dev, struct device_driver *drv) -{ - struct superhyway_device *shyway_dev = to_superhyway_device(dev); - struct superhyway_driver *shyway_drv = to_superhyway_driver(drv); - const struct superhyway_device_id *ids = shyway_drv->id_table; - - if (!ids) - return -EINVAL; - if (superhyway_match_id(ids, shyway_dev)) - return 1; - - return -ENODEV; -} - -struct bus_type superhyway_bus_type = { - .name = "superhyway", - .match = superhyway_bus_match, -#ifdef CONFIG_SYSFS - .dev_groups = superhyway_dev_groups, -#endif - .probe = superhyway_device_probe, - .remove = superhyway_device_remove, -}; - -static int __init superhyway_bus_init(void) -{ - return bus_register(&superhyway_bus_type); -} - -static void __exit superhyway_bus_exit(void) -{ - device_unregister(&superhyway_bus_device); - bus_unregister(&superhyway_bus_type); -} - -core_initcall(superhyway_bus_init); -module_exit(superhyway_bus_exit); - -EXPORT_SYMBOL(superhyway_bus_type); -EXPORT_SYMBOL(superhyway_add_device); -EXPORT_SYMBOL(superhyway_add_devices); -EXPORT_SYMBOL(superhyway_register_driver); -EXPORT_SYMBOL(superhyway_unregister_driver); - -MODULE_LICENSE("GPL"); diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h deleted file mode 100644 index 7bed5be886c657..00000000000000 --- a/include/linux/sh_clk.h +++ /dev/null @@ -1,213 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __SH_CLOCK_H -#define __SH_CLOCK_H - -#include <linux/list.h> -#include <linux/seq_file.h> -#include <linux/cpufreq.h> -#include <linux/types.h> -#include <linux/kref.h> -#include <linux/clk.h> -#include <linux/err.h> - -struct clk; - -struct clk_mapping { - phys_addr_t phys; - void __iomem *base; - unsigned long len; - struct kref ref; -}; - -struct sh_clk_ops { -#ifdef CONFIG_SH_CLK_CPG_LEGACY - void (*init)(struct clk *clk); -#endif - int (*enable)(struct clk *clk); - void (*disable)(struct clk *clk); - unsigned long (*recalc)(struct clk *clk); - int (*set_rate)(struct clk *clk, unsigned long rate); - int (*set_parent)(struct clk *clk, struct clk *parent); - long (*round_rate)(struct clk *clk, unsigned long rate); -}; - -#define SH_CLK_DIV_MSK(div) ((1 << (div)) - 1) -#define SH_CLK_DIV4_MSK SH_CLK_DIV_MSK(4) -#define SH_CLK_DIV6_MSK SH_CLK_DIV_MSK(6) - -struct clk { - struct list_head node; - struct clk *parent; - struct clk **parent_table; /* list of parents to */ - unsigned short parent_num; /* choose between */ - unsigned char src_shift; /* source clock field in the */ - unsigned char src_width; /* configuration register */ - struct sh_clk_ops *ops; - - struct list_head children; - struct list_head sibling; /* node for children */ - - int usecount; - - unsigned long rate; - unsigned long flags; - - void __iomem *enable_reg; - void __iomem *status_reg; - unsigned int enable_bit; - void __iomem *mapped_reg; - - unsigned int div_mask; - unsigned long arch_flags; - void *priv; - struct clk_mapping *mapping; - struct cpufreq_frequency_table *freq_table; - unsigned int nr_freqs; -}; - -#define CLK_ENABLE_ON_INIT BIT(0) - -#define CLK_ENABLE_REG_32BIT BIT(1) /* default access size */ -#define CLK_ENABLE_REG_16BIT BIT(2) -#define CLK_ENABLE_REG_8BIT BIT(3) - -#define CLK_MASK_DIV_ON_DISABLE BIT(4) - -#define CLK_ENABLE_REG_MASK (CLK_ENABLE_REG_32BIT | \ - CLK_ENABLE_REG_16BIT | \ - CLK_ENABLE_REG_8BIT) - -/* drivers/sh/clk.c */ -unsigned long followparent_recalc(struct clk *); -void recalculate_root_clocks(void); -void propagate_rate(struct clk *); -int clk_reparent(struct clk *child, struct clk *parent); -int clk_register(struct clk *); -void clk_unregister(struct clk *); -void clk_enable_init_clocks(void); - -struct clk_div_mult_table { - unsigned int *divisors; - unsigned int nr_divisors; - unsigned int *multipliers; - unsigned int nr_multipliers; -}; - -struct cpufreq_frequency_table; -void clk_rate_table_build(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - int nr_freqs, - struct clk_div_mult_table *src_table, - unsigned long *bitmap); - -long clk_rate_table_round(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate); - -int clk_rate_table_find(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate); - -long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, - unsigned int div_max, unsigned long rate); - -long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min, - unsigned int mult_max, unsigned long rate); - -#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _status_reg, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_enable_reg, \ - .enable_bit = _enable_bit, \ - .status_reg = _status_reg, \ - .flags = _flags, \ -} - -#define SH_CLK_MSTP32(_p, _r, _b, _f) \ - SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_32BIT) - -#define SH_CLK_MSTP32_STS(_p, _r, _b, _s, _f) \ - SH_CLK_MSTP(_p, _r, _b, _s, _f | CLK_ENABLE_REG_32BIT) - -#define SH_CLK_MSTP16(_p, _r, _b, _f) \ - SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_16BIT) - -#define SH_CLK_MSTP8(_p, _r, _b, _f) \ - SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_8BIT) - -int sh_clk_mstp_register(struct clk *clks, int nr); - -/* - * MSTP registration never really cared about access size, despite the - * original enable/disable pairs assuming a 32-bit access. Clocks are - * responsible for defining their access sizes either directly or via the - * clock definition wrappers. - */ -static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr) -{ - return sh_clk_mstp_register(clks, nr); -} - -#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = _shift, \ - .arch_flags = _div_bitmap, \ - .div_mask = SH_CLK_DIV4_MSK, \ - .flags = _flags, \ -} - -struct clk_div_table { - struct clk_div_mult_table *div_mult_table; - void (*kick)(struct clk *clk); -}; - -#define clk_div4_table clk_div_table - -int sh_clk_div4_register(struct clk *clks, int nr, - struct clk_div4_table *table); -int sh_clk_div4_enable_register(struct clk *clks, int nr, - struct clk_div4_table *table); -int sh_clk_div4_reparent_register(struct clk *clks, int nr, - struct clk_div4_table *table); - -#define SH_CLK_DIV6_EXT(_reg, _flags, _parents, \ - _num_parents, _src_shift, _src_width) \ -{ \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = 0, /* unused */ \ - .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \ - .div_mask = SH_CLK_DIV6_MSK, \ - .parent_table = _parents, \ - .parent_num = _num_parents, \ - .src_shift = _src_shift, \ - .src_width = _src_width, \ -} - -#define SH_CLK_DIV6(_parent, _reg, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = 0, /* unused */ \ - .div_mask = SH_CLK_DIV6_MSK, \ - .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \ -} - -int sh_clk_div6_register(struct clk *clks, int nr); -int sh_clk_div6_reparent_register(struct clk *clks, int nr); - -#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } -#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } -#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk } - -/* .enable_reg will be updated to .mapping on sh_clk_fsidiv_register() */ -#define SH_CLK_FSIDIV(_reg, _parent) \ -{ \ - .enable_reg = (void __iomem *)_reg, \ - .parent = _parent, \ -} - -int sh_clk_fsidiv_register(struct clk *clks, int nr); - -#endif /* __SH_CLOCK_H */ diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h deleted file mode 100644 index 8d3376775813d3..00000000000000 --- a/include/linux/superhyway.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * include/linux/superhyway.h - * - * SuperHyway Bus definitions - * - * Copyright (C) 2004, 2005 Paul Mundt <lethal@xxxxxxxxxxxx> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#ifndef __LINUX_SUPERHYWAY_H -#define __LINUX_SUPERHYWAY_H - -#include <linux/device.h> - -/* - * SuperHyway IDs - */ -#define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183 - -struct superhyway_vcr_info { - u8 perr_flags; /* P-port Error flags */ - u8 merr_flags; /* Module Error flags */ - u16 mod_vers; /* Module Version */ - u16 mod_id; /* Module ID */ - u8 bot_mb; /* Bottom Memory block */ - u8 top_mb; /* Top Memory block */ -}; - -struct superhyway_ops { - int (*read_vcr)(unsigned long base, struct superhyway_vcr_info *vcr); - int (*write_vcr)(unsigned long base, struct superhyway_vcr_info vcr); -}; - -struct superhyway_bus { - struct superhyway_ops *ops; -}; - -extern struct superhyway_bus superhyway_channels[]; - -struct superhyway_device_id { - unsigned int id; - unsigned long driver_data; -}; - -struct superhyway_device; -extern struct bus_type superhyway_bus_type; - -struct superhyway_driver { - char *name; - - const struct superhyway_device_id *id_table; - struct device_driver drv; - - int (*probe)(struct superhyway_device *dev, const struct superhyway_device_id *id); - void (*remove)(struct superhyway_device *dev); -}; - -#define to_superhyway_driver(d) container_of((d), struct superhyway_driver, drv) - -struct superhyway_device { - char name[32]; - - struct device dev; - - struct superhyway_device_id id; - struct superhyway_driver *drv; - struct superhyway_bus *bus; - - int num_resources; - struct resource *resource; - struct superhyway_vcr_info vcr; -}; - -#define to_superhyway_device(d) container_of((d), struct superhyway_device, dev) - -#define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev) -#define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p)) - -static inline int -superhyway_read_vcr(struct superhyway_device *dev, unsigned long base, - struct superhyway_vcr_info *vcr) -{ - return dev->bus->ops->read_vcr(base, vcr); -} - -static inline int -superhyway_write_vcr(struct superhyway_device *dev, unsigned long base, - struct superhyway_vcr_info vcr) -{ - return dev->bus->ops->write_vcr(base, vcr); -} - -extern int superhyway_scan_bus(struct superhyway_bus *); - -/* drivers/sh/superhyway/superhyway.c */ -int superhyway_register_driver(struct superhyway_driver *); -void superhyway_unregister_driver(struct superhyway_driver *); -int superhyway_add_device(unsigned long base, struct superhyway_device *, struct superhyway_bus *); -int superhyway_add_devices(struct superhyway_bus *bus, struct superhyway_device **devices, int nr_devices); - -/* drivers/sh/superhyway/superhyway-sysfs.c */ -extern const struct attribute_group *superhyway_dev_groups[]; - -#endif /* __LINUX_SUPERHYWAY_H */ - -- 2.39.0