Merge branches 'common/clkfwk', 'common/pfc' and 'common/serial-rework' into sh-latest

This commit is contained in:
Paul Mundt
2011-12-09 18:11:09 +09:00
475 changed files with 5066 additions and 3596 deletions

View File

@@ -355,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk)
*/
if (!clk->parent) {
clk->mapping = &dummy_mapping;
return 0;
goto out;
}
/*
@@ -384,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;
}
@@ -402,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)

View File

@@ -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,6 +222,9 @@ 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 = sh_clk_init_parent(clkp);
if (ret < 0)
break;
ret = clk_register(clkp);
}
@@ -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 = {

View File

@@ -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);
}