summaryrefslogtreecommitdiff
path: root/drivers/sh
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sh')
-rw-r--r--drivers/sh/clk/core.c116
-rw-r--r--drivers/sh/clk/cpg.c79
-rw-r--r--drivers/sh/intc/core.c37
-rw-r--r--drivers/sh/intc/internals.h7
-rw-r--r--drivers/sh/intc/userimask.c16
-rw-r--r--drivers/sh/pfc.c137
6 files changed, 232 insertions, 160 deletions
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index dc8d022c07a1..7715de2629c1 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -25,7 +25,6 @@
#include <linux/seq_file.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/debugfs.h>
#include <linux/cpufreq.h>
#include <linux/clk.h>
#include <linux/sh_clk.h>
@@ -173,6 +172,26 @@ long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
return clk_rate_round_helper(&div_range_round);
}
+static long clk_rate_mult_range_iter(unsigned int pos,
+ struct clk_rate_round_data *rounder)
+{
+ return clk_get_rate(rounder->arg) * pos;
+}
+
+long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min,
+ unsigned int mult_max, unsigned long rate)
+{
+ struct clk_rate_round_data mult_range_round = {
+ .min = mult_min,
+ .max = mult_max,
+ .func = clk_rate_mult_range_iter,
+ .arg = clk_get_parent(clk),
+ .rate = rate,
+ };
+
+ return clk_rate_round_helper(&mult_range_round);
+}
+
int clk_rate_table_find(struct clk *clk,
struct cpufreq_frequency_table *freq_table,
unsigned long rate)
@@ -205,9 +224,6 @@ int clk_reparent(struct clk *child, struct clk *parent)
list_add(&child->sibling, &parent->children);
child->parent = parent;
- /* now do the debugfs renaming to reattach the child
- to the proper parent */
-
return 0;
}
@@ -339,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk)
*/
if (!clk->parent) {
clk->mapping = &dummy_mapping;
- return 0;
+ goto out;
}
/*
@@ -368,6 +384,9 @@ static int clk_establish_mapping(struct clk *clk)
}
clk->mapping = mapping;
+out:
+ clk->mapped_reg = clk->mapping->base;
+ clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys;
return 0;
}
@@ -386,10 +405,12 @@ static void clk_teardown_mapping(struct clk *clk)
/* Nothing to do */
if (mapping == &dummy_mapping)
- return;
+ goto out;
kref_put(&mapping->ref, clk_destroy_mapping);
clk->mapping = NULL;
+out:
+ clk->mapped_reg = NULL;
}
int clk_register(struct clk *clk)
@@ -665,89 +686,6 @@ static int __init clk_syscore_init(void)
subsys_initcall(clk_syscore_init);
#endif
-/*
- * debugfs support to trace clock tree hierarchy and attributes
- */
-static struct dentry *clk_debugfs_root;
-
-static int clk_debugfs_register_one(struct clk *c)
-{
- int err;
- struct dentry *d;
- struct clk *pa = c->parent;
- char s[255];
- char *p = s;
-
- p += sprintf(p, "%p", c);
- d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
- if (!d)
- return -ENOMEM;
- c->dentry = d;
-
- d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- return 0;
-
-err_out:
- debugfs_remove_recursive(c->dentry);
- return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
- int err;
- struct clk *pa = c->parent;
-
- if (pa && !pa->dentry) {
- err = clk_debugfs_register(pa);
- if (err)
- return err;
- }
-
- if (!c->dentry) {
- err = clk_debugfs_register_one(c);
- if (err)
- return err;
- }
- return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
- struct clk *c;
- struct dentry *d;
- int err;
-
- d = debugfs_create_dir("clock", NULL);
- if (!d)
- return -ENOMEM;
- clk_debugfs_root = d;
-
- list_for_each_entry(c, &clock_list, node) {
- err = clk_debugfs_register(c);
- if (err)
- goto err_out;
- }
- return 0;
-err_out:
- debugfs_remove_recursive(clk_debugfs_root);
- return err;
-}
-late_initcall(clk_debugfs_init);
-
static int __init clk_late_init(void)
{
unsigned long flags;
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 82dd6fb17838..45fee368b092 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -15,15 +15,15 @@
static int sh_clk_mstp32_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+ clk->mapped_reg);
return 0;
}
static void sh_clk_mstp32_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+ clk->mapped_reg);
}
static struct clk_ops sh_clk_mstp32_clk_ops = {
@@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, NULL);
- idx = __raw_readl(clk->enable_reg) & 0x003f;
+ idx = ioread32(clk->mapped_reg) & 0x003f;
return clk->freq_table[idx].frequency;
}
@@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
if (ret < 0)
return ret;
- value = __raw_readl(clk->enable_reg) &
+ value = ioread32(clk->mapped_reg) &
~(((1 << clk->src_width) - 1) << clk->src_shift);
- __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
+ iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
/* Rebuild the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x3f;
value |= idx;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
return 0;
}
@@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk *clk)
ret = sh_clk_div6_set_rate(clk, clk->rate);
if (ret == 0) {
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x100; /* clear stop bit to enable clock */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
return ret;
}
@@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct clk *clk)
{
unsigned long value;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value |= 0x100; /* stop clock */
value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
static struct clk_ops sh_clk_div6_clk_ops = {
@@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = {
.set_parent = sh_clk_div6_set_parent,
};
+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 = (ioread32(clk->mapped_reg) >> 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->parent = 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_div6_register_ops(struct clk *clks, int nr,
struct clk_ops *ops)
{
@@ -190,8 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
clkp->ops = ops;
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)
+ break;
+
+ ret = sh_clk_init_parent(clkp);
}
return ret;
@@ -217,7 +252,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, &clk->arch_flags);
- idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+ idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
return clk->freq_table[idx].frequency;
}
@@ -235,15 +270,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
*/
if (parent->flags & CLK_ENABLE_ON_INIT)
- value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+ value = ioread32(clk->mapped_reg) & ~(1 << 7);
else
- value = __raw_readl(clk->enable_reg) | (1 << 7);
+ value = ioread32(clk->mapped_reg) | (1 << 7);
ret = clk_reparent(clk, parent);
if (ret < 0)
return ret;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
/* Rebiuld the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -260,10 +295,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~(0xf << clk->enable_bit);
value |= (idx << clk->enable_bit);
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
if (d4t->kick)
d4t->kick(clk);
@@ -273,13 +308,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
static int sh_clk_div4_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
return 0;
}
static void sh_clk_div4_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
}
static struct clk_ops sh_clk_div4_clk_ops = {
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 8b7a141ff35e..e53e449b4eca 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -25,7 +25,7 @@
#include <linux/stat.h>
#include <linux/interrupt.h>
#include <linux/sh_intc.h>
-#include <linux/sysdev.h>
+#include <linux/device.h>
#include <linux/syscore_ops.h>
#include <linux/list.h>
#include <linux/spinlock.h>
@@ -354,6 +354,8 @@ int __init register_intc_controller(struct intc_desc *desc)
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;
@@ -386,6 +388,9 @@ static int intc_suspend(void)
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;
@@ -409,6 +414,9 @@ static void intc_resume(void)
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;
@@ -434,46 +442,47 @@ struct syscore_ops intc_syscore_ops = {
.resume = intc_resume,
};
-struct sysdev_class intc_sysdev_class = {
+struct bus_type intc_subsys = {
.name = "intc",
+ .dev_name = "intc",
};
static ssize_t
-show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
+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, sysdev);
+ d = container_of(dev, struct intc_desc_int, dev);
return sprintf(buf, "%s\n", d->chip.name);
}
-static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
+static DEVICE_ATTR(name, S_IRUGO, show_intc_name, NULL);
-static int __init register_intc_sysdevs(void)
+static int __init register_intc_devs(void)
{
struct intc_desc_int *d;
int error;
register_syscore_ops(&intc_syscore_ops);
- error = sysdev_class_register(&intc_sysdev_class);
+ error = subsys_system_register(&intc_subsys, NULL);
if (!error) {
list_for_each_entry(d, &intc_list, list) {
- d->sysdev.id = d->index;
- d->sysdev.cls = &intc_sysdev_class;
- error = sysdev_register(&d->sysdev);
+ d->dev.id = d->index;
+ d->dev.bus = &intc_subsys;
+ error = device_register(&d->dev);
if (error == 0)
- error = sysdev_create_file(&d->sysdev,
- &attr_name);
+ error = device_create_file(&d->dev,
+ &dev_attr_name);
if (error)
break;
}
}
if (error)
- pr_err("sysdev registration error\n");
+ pr_err("device registration error\n");
return error;
}
-device_initcall(register_intc_sysdevs);
+device_initcall(register_intc_devs);
diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h
index 5b934851efa8..b0e9155ff739 100644
--- a/drivers/sh/intc/internals.h
+++ b/drivers/sh/intc/internals.h
@@ -4,7 +4,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/radix-tree.h>
-#include <linux/sysdev.h>
+#include <linux/device.h>
#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -51,7 +51,7 @@ struct intc_subgroup_entry {
struct intc_desc_int {
struct list_head list;
- struct sys_device sysdev;
+ struct device dev;
struct radix_tree_root tree;
raw_spinlock_t lock;
unsigned int index;
@@ -67,6 +67,7 @@ struct intc_desc_int {
struct intc_window *window;
unsigned int nr_windows;
struct irq_chip chip;
+ bool skip_suspend;
};
@@ -157,7 +158,7 @@ void _intc_enable(struct irq_data *data, unsigned long handle);
extern struct list_head intc_list;
extern raw_spinlock_t intc_big_lock;
extern unsigned int nr_intc_controllers;
-extern struct sysdev_class intc_sysdev_class;
+extern struct bus_type intc_subsys;
unsigned int intc_get_dfl_prio_level(void);
unsigned int intc_get_prio_level(unsigned int irq);
diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c
index 56bf9336b92b..e649ceaaa410 100644
--- a/drivers/sh/intc/userimask.c
+++ b/drivers/sh/intc/userimask.c
@@ -10,7 +10,7 @@
#define pr_fmt(fmt) "intc: " fmt
#include <linux/errno.h>
-#include <linux/sysdev.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/stat.h>
@@ -20,15 +20,15 @@
static void __iomem *uimask;
static ssize_t
-show_intc_userimask(struct sysdev_class *cls,
- struct sysdev_class_attribute *attr, char *buf)
+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 sysdev_class *cls,
- struct sysdev_class_attribute *attr,
+store_intc_userimask(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long level;
@@ -55,8 +55,8 @@ store_intc_userimask(struct sysdev_class *cls,
return count;
}
-static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR,
- show_intc_userimask, store_intc_userimask);
+static DEVICE_ATTR(userimask, S_IRUSR | S_IWUSR,
+ show_intc_userimask, store_intc_userimask);
static int __init userimask_sysdev_init(void)
@@ -64,7 +64,7 @@ static int __init userimask_sysdev_init(void)
if (unlikely(!uimask))
return -ENXIO;
- return sysdev_class_create_file(&intc_sysdev_class, &attr_userimask);
+ return device_create_file(intc_subsys.dev_root, &dev_attr_userimask);
}
late_initcall(userimask_sysdev_init);
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index e67fe170d8d5..e7d127a9c1c5 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -19,6 +19,75 @@
#include <linux/irq.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+
+static void pfc_iounmap(struct pinmux_info *pip)
+{
+ int k;
+
+ for (k = 0; k < pip->num_resources; k++)
+ if (pip->window[k].virt)
+ iounmap(pip->window[k].virt);
+
+ kfree(pip->window);
+ pip->window = NULL;
+}
+
+static int pfc_ioremap(struct pinmux_info *pip)
+{
+ struct resource *res;
+ int k;
+
+ if (!pip->num_resources)
+ return 0;
+
+ pip->window = kzalloc(pip->num_resources * sizeof(*pip->window),
+ GFP_NOWAIT);
+ if (!pip->window)
+ goto err1;
+
+ for (k = 0; k < pip->num_resources; k++) {
+ res = pip->resource + k;
+ WARN_ON(resource_type(res) != IORESOURCE_MEM);
+ pip->window[k].phys = res->start;
+ pip->window[k].size = resource_size(res);
+ pip->window[k].virt = ioremap_nocache(res->start,
+ resource_size(res));
+ if (!pip->window[k].virt)
+ goto err2;
+ }
+
+ return 0;
+
+err2:
+ pfc_iounmap(pip);
+err1:
+ return -1;
+}
+
+static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip,
+ unsigned long address)
+{
+ struct pfc_window *window;
+ int k;
+
+ /* scan through physical windows and convert address */
+ for (k = 0; k < pip->num_resources; k++) {
+ window = pip->window + k;
+
+ if (address < window->phys)
+ continue;
+
+ if (address >= (window->phys + window->size))
+ continue;
+
+ return window->virt + (address - window->phys);
+ }
+
+ /* no windows defined, register must be 1:1 mapped virt:phys */
+ return (void __iomem *)address;
+}
static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
{
@@ -31,35 +100,35 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
return 1;
}
-static unsigned long gpio_read_raw_reg(unsigned long reg,
+static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width)
{
switch (reg_width) {
case 8:
- return __raw_readb(reg);
+ return ioread8(mapped_reg);
case 16:
- return __raw_readw(reg);
+ return ioread16(mapped_reg);
case 32:
- return __raw_readl(reg);
+ return ioread32(mapped_reg);
}
BUG();
return 0;
}
-static void gpio_write_raw_reg(unsigned long reg,
+static void gpio_write_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width,
unsigned long data)
{
switch (reg_width) {
case 8:
- __raw_writeb(data, reg);
+ iowrite8(data, mapped_reg);
return;
case 16:
- __raw_writew(data, reg);
+ iowrite16(data, mapped_reg);
return;
case 32:
- __raw_writel(data, reg);
+ iowrite32(data, mapped_reg);
return;
}
@@ -82,11 +151,12 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
else
clear_bit(pos, &dr->reg_shadow);
- gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
+ gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
}
-static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
- unsigned long field_width, unsigned long in_pos)
+static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width,
+ unsigned long field_width, unsigned long in_pos,
+ unsigned long reg)
{
unsigned long data, mask, pos;
@@ -98,13 +168,13 @@ static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
"r_width = %ld, f_width = %ld\n",
reg, pos, reg_width, field_width);
- data = gpio_read_raw_reg(reg, reg_width);
+ data = gpio_read_raw_reg(mapped_reg, reg_width);
return (data >> pos) & mask;
}
-static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
+static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width,
unsigned long field_width, unsigned long in_pos,
- unsigned long value)
+ unsigned long value, unsigned long reg)
{
unsigned long mask, pos;
@@ -120,13 +190,13 @@ static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
switch (reg_width) {
case 8:
- __raw_writeb((__raw_readb(reg) & mask) | value, reg);
+ iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg);
break;
case 16:
- __raw_writew((__raw_readw(reg) & mask) | value, reg);
+ iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg);
break;
case 32:
- __raw_writel((__raw_readl(reg) & mask) | value, reg);
+ iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg);
break;
}
}
@@ -147,6 +217,8 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
if (!data_reg->reg_width)
break;
+ data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
+
for (n = 0; n < data_reg->reg_width; n++) {
if (data_reg->enum_ids[n] == gpiop->enum_id) {
gpiop->flags &= ~PINMUX_FLAG_DREG;
@@ -179,7 +251,8 @@ static void setup_data_regs(struct pinmux_info *gpioc)
if (!drp->reg_width)
break;
- drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
+ drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
+ drp->reg_width);
k++;
}
}
@@ -266,12 +339,16 @@ static void write_config_reg(struct pinmux_info *gpioc,
int index)
{
unsigned long ncomb, pos, value;
+ void __iomem *mapped_reg;
ncomb = 1 << crp->field_width;
pos = index / ncomb;
value = index % ncomb;
- gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
+ mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
+
+ gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width,
+ pos, value, crp->reg);
}
static int check_config_reg(struct pinmux_info *gpioc,
@@ -279,13 +356,16 @@ static int check_config_reg(struct pinmux_info *gpioc,
int index)
{
unsigned long ncomb, pos, value;
+ void __iomem *mapped_reg;
ncomb = 1 << crp->field_width;
pos = index / ncomb;
value = index % ncomb;
- if (gpio_read_reg(crp->reg, crp->reg_width,
- crp->field_width, pos) == value)
+ mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
+
+ if (gpio_read_reg(mapped_reg, crp->reg_width,
+ crp->field_width, pos, crp->reg) == value)
return 0;
return -1;
@@ -564,7 +644,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
return -EINVAL;
- return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
+ return gpio_read_reg(dr->mapped_reg, dr->reg_width, 1, bit, dr->reg);
}
static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -606,10 +686,15 @@ static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
int register_pinmux(struct pinmux_info *pip)
{
struct gpio_chip *chip = &pip->chip;
+ int ret;
pr_info("%s handling gpio %d -> %d\n",
pip->name, pip->first_gpio, pip->last_gpio);
+ ret = pfc_ioremap(pip);
+ if (ret < 0)
+ return ret;
+
setup_data_regs(pip);
chip->request = sh_gpio_request;
@@ -627,12 +712,16 @@ int register_pinmux(struct pinmux_info *pip)
chip->base = pip->first_gpio;
chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
- return gpiochip_add(chip);
+ ret = gpiochip_add(chip);
+ if (ret < 0)
+ pfc_iounmap(pip);
+
+ return ret;
}
int unregister_pinmux(struct pinmux_info *pip)
{
pr_info("%s deregistering\n", pip->name);
-
+ pfc_iounmap(pip);
return gpiochip_remove(&pip->chip);
}