Skip to content

Commit b0e1021

Browse files
Magnus Dammpmundt
authored andcommitted
sh: pfc: ioremap() support
Add support for non-entity mapped PFC registers through the use of struct resource and ioremap()/iounmap(). The PFC main data structure gets updated with a pointer to a struct resources array that point out all register windows used by the PFC instance. The register definitions are kept as physical addresses but the PFC code will do transparent conversion into virtual addresses whenever register windows are specified using with struct resource. To introduce as little performance penalty as possible the virtual address of each data register is cached in memory. The virtual address of each configuration register is however calculated during run time. This because the configuration is considered slow path so focus is instead put on keeping memory foot print as small as possible. The PFC register access code is in this patch updated from __raw_readN() / __raw_writeN() into ioreadN() / iowriteN(). This patch is needed to support the PFC block in r8a7779. Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
1 parent 883381d commit b0e1021

2 files changed

Lines changed: 124 additions & 24 deletions

File tree

drivers/sh/pfc.c

Lines changed: 113 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,75 @@
1919
#include <linux/irq.h>
2020
#include <linux/bitops.h>
2121
#include <linux/gpio.h>
22+
#include <linux/slab.h>
23+
#include <linux/ioport.h>
24+
25+
static void pfc_iounmap(struct pinmux_info *pip)
26+
{
27+
int k;
28+
29+
for (k = 0; k < pip->num_resources; k++)
30+
if (pip->window[k].virt)
31+
iounmap(pip->window[k].virt);
32+
33+
kfree(pip->window);
34+
pip->window = NULL;
35+
}
36+
37+
static int pfc_ioremap(struct pinmux_info *pip)
38+
{
39+
struct resource *res;
40+
int k;
41+
42+
if (!pip->num_resources)
43+
return 0;
44+
45+
pip->window = kzalloc(pip->num_resources * sizeof(*pip->window),
46+
GFP_NOWAIT);
47+
if (!pip->window)
48+
goto err1;
49+
50+
for (k = 0; k < pip->num_resources; k++) {
51+
res = pip->resource + k;
52+
WARN_ON(resource_type(res) != IORESOURCE_MEM);
53+
pip->window[k].phys = res->start;
54+
pip->window[k].size = resource_size(res);
55+
pip->window[k].virt = ioremap_nocache(res->start,
56+
resource_size(res));
57+
if (!pip->window[k].virt)
58+
goto err2;
59+
}
60+
61+
return 0;
62+
63+
err2:
64+
pfc_iounmap(pip);
65+
err1:
66+
return -1;
67+
}
68+
69+
static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip,
70+
unsigned long address)
71+
{
72+
struct pfc_window *window;
73+
int k;
74+
75+
/* scan through physical windows and convert address */
76+
for (k = 0; k < pip->num_resources; k++) {
77+
window = pip->window + k;
78+
79+
if (address < window->phys)
80+
continue;
81+
82+
if (address >= (window->phys + window->size))
83+
continue;
84+
85+
return window->virt + (address - window->phys);
86+
}
87+
88+
/* no windows defined, register must be 1:1 mapped virt:phys */
89+
return (void __iomem *)address;
90+
}
2291

2392
static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
2493
{
@@ -31,35 +100,35 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
31100
return 1;
32101
}
33102

34-
static unsigned long gpio_read_raw_reg(unsigned long reg,
103+
static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
35104
unsigned long reg_width)
36105
{
37106
switch (reg_width) {
38107
case 8:
39-
return __raw_readb(reg);
108+
return ioread8(mapped_reg);
40109
case 16:
41-
return __raw_readw(reg);
110+
return ioread16(mapped_reg);
42111
case 32:
43-
return __raw_readl(reg);
112+
return ioread32(mapped_reg);
44113
}
45114

46115
BUG();
47116
return 0;
48117
}
49118

50-
static void gpio_write_raw_reg(unsigned long reg,
119+
static void gpio_write_raw_reg(void __iomem *mapped_reg,
51120
unsigned long reg_width,
52121
unsigned long data)
53122
{
54123
switch (reg_width) {
55124
case 8:
56-
__raw_writeb(data, reg);
125+
iowrite8(data, mapped_reg);
57126
return;
58127
case 16:
59-
__raw_writew(data, reg);
128+
iowrite16(data, mapped_reg);
60129
return;
61130
case 32:
62-
__raw_writel(data, reg);
131+
iowrite32(data, mapped_reg);
63132
return;
64133
}
65134

@@ -82,11 +151,12 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
82151
else
83152
clear_bit(pos, &dr->reg_shadow);
84153

85-
gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
154+
gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
86155
}
87156

88-
static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
89-
unsigned long field_width, unsigned long in_pos)
157+
static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width,
158+
unsigned long field_width, unsigned long in_pos,
159+
unsigned long reg)
90160
{
91161
unsigned long data, mask, pos;
92162

@@ -98,13 +168,13 @@ static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
98168
"r_width = %ld, f_width = %ld\n",
99169
reg, pos, reg_width, field_width);
100170

101-
data = gpio_read_raw_reg(reg, reg_width);
171+
data = gpio_read_raw_reg(mapped_reg, reg_width);
102172
return (data >> pos) & mask;
103173
}
104174

105-
static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
175+
static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width,
106176
unsigned long field_width, unsigned long in_pos,
107-
unsigned long value)
177+
unsigned long value, unsigned long reg)
108178
{
109179
unsigned long mask, pos;
110180

@@ -120,13 +190,13 @@ static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
120190

121191
switch (reg_width) {
122192
case 8:
123-
__raw_writeb((__raw_readb(reg) & mask) | value, reg);
193+
iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg);
124194
break;
125195
case 16:
126-
__raw_writew((__raw_readw(reg) & mask) | value, reg);
196+
iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg);
127197
break;
128198
case 32:
129-
__raw_writel((__raw_readl(reg) & mask) | value, reg);
199+
iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg);
130200
break;
131201
}
132202
}
@@ -147,6 +217,8 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
147217
if (!data_reg->reg_width)
148218
break;
149219

220+
data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
221+
150222
for (n = 0; n < data_reg->reg_width; n++) {
151223
if (data_reg->enum_ids[n] == gpiop->enum_id) {
152224
gpiop->flags &= ~PINMUX_FLAG_DREG;
@@ -179,7 +251,8 @@ static void setup_data_regs(struct pinmux_info *gpioc)
179251
if (!drp->reg_width)
180252
break;
181253

182-
drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
254+
drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
255+
drp->reg_width);
183256
k++;
184257
}
185258
}
@@ -266,26 +339,33 @@ static void write_config_reg(struct pinmux_info *gpioc,
266339
int index)
267340
{
268341
unsigned long ncomb, pos, value;
342+
void __iomem *mapped_reg;
269343

270344
ncomb = 1 << crp->field_width;
271345
pos = index / ncomb;
272346
value = index % ncomb;
273347

274-
gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
348+
mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
349+
350+
gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width,
351+
pos, value, crp->reg);
275352
}
276353

277354
static int check_config_reg(struct pinmux_info *gpioc,
278355
struct pinmux_cfg_reg *crp,
279356
int index)
280357
{
281358
unsigned long ncomb, pos, value;
359+
void __iomem *mapped_reg;
282360

283361
ncomb = 1 << crp->field_width;
284362
pos = index / ncomb;
285363
value = index % ncomb;
286364

287-
if (gpio_read_reg(crp->reg, crp->reg_width,
288-
crp->field_width, pos) == value)
365+
mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
366+
367+
if (gpio_read_reg(mapped_reg, crp->reg_width,
368+
crp->field_width, pos, crp->reg) == value)
289369
return 0;
290370

291371
return -1;
@@ -564,7 +644,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
564644
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
565645
return -EINVAL;
566646

567-
return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
647+
return gpio_read_reg(dr->mapped_reg, dr->reg_width, 1, bit, dr->reg);
568648
}
569649

570650
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)
606686
int register_pinmux(struct pinmux_info *pip)
607687
{
608688
struct gpio_chip *chip = &pip->chip;
689+
int ret;
609690

610691
pr_info("%s handling gpio %d -> %d\n",
611692
pip->name, pip->first_gpio, pip->last_gpio);
612693

694+
ret = pfc_ioremap(pip);
695+
if (ret < 0)
696+
return ret;
697+
613698
setup_data_regs(pip);
614699

615700
chip->request = sh_gpio_request;
@@ -627,12 +712,16 @@ int register_pinmux(struct pinmux_info *pip)
627712
chip->base = pip->first_gpio;
628713
chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
629714

630-
return gpiochip_add(chip);
715+
ret = gpiochip_add(chip);
716+
if (ret < 0)
717+
pfc_iounmap(pip);
718+
719+
return ret;
631720
}
632721

633722
int unregister_pinmux(struct pinmux_info *pip)
634723
{
635724
pr_info("%s deregistering\n", pip->name);
636-
725+
pfc_iounmap(pip);
637726
return gpiochip_remove(&pip->chip);
638727
}

include/linux/sh_pfc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct pinmux_cfg_reg {
5555
struct pinmux_data_reg {
5656
unsigned long reg, reg_width, reg_shadow;
5757
pinmux_enum_t *enum_ids;
58+
void __iomem *mapped_reg;
5859
};
5960

6061
#define PINMUX_DATA_REG(name, r, r_width) \
@@ -75,6 +76,12 @@ struct pinmux_range {
7576
pinmux_enum_t force;
7677
};
7778

79+
struct pfc_window {
80+
phys_addr_t phys;
81+
void __iomem *virt;
82+
unsigned long size;
83+
};
84+
7885
struct pinmux_info {
7986
char *name;
8087
pinmux_enum_t reserved_id;
@@ -98,6 +105,10 @@ struct pinmux_info {
98105
struct pinmux_irq *gpio_irq;
99106
unsigned int gpio_irq_size;
100107

108+
struct resource *resource;
109+
unsigned int num_resources;
110+
struct pfc_window *window;
111+
101112
struct gpio_chip chip;
102113
};
103114

0 commit comments

Comments
 (0)