diff options
Diffstat (limited to 'drivers/sh/pfc.c')
-rw-r--r-- | drivers/sh/pfc.c | 137 |
1 files changed, 113 insertions, 24 deletions
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 @@ | |||
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
21 | #include <linux/gpio.h> | 21 | #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 | } | ||
22 | 91 | ||
23 | static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) | 92 | static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) |
24 | { | 93 | { |
@@ -31,35 +100,35 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) | |||
31 | return 1; | 100 | return 1; |
32 | } | 101 | } |
33 | 102 | ||
34 | static unsigned long gpio_read_raw_reg(unsigned long reg, | 103 | static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg, |
35 | unsigned long reg_width) | 104 | unsigned long reg_width) |
36 | { | 105 | { |
37 | switch (reg_width) { | 106 | switch (reg_width) { |
38 | case 8: | 107 | case 8: |
39 | return __raw_readb(reg); | 108 | return ioread8(mapped_reg); |
40 | case 16: | 109 | case 16: |
41 | return __raw_readw(reg); | 110 | return ioread16(mapped_reg); |
42 | case 32: | 111 | case 32: |
43 | return __raw_readl(reg); | 112 | return ioread32(mapped_reg); |
44 | } | 113 | } |
45 | 114 | ||
46 | BUG(); | 115 | BUG(); |
47 | return 0; | 116 | return 0; |
48 | } | 117 | } |
49 | 118 | ||
50 | static void gpio_write_raw_reg(unsigned long reg, | 119 | static void gpio_write_raw_reg(void __iomem *mapped_reg, |
51 | unsigned long reg_width, | 120 | unsigned long reg_width, |
52 | unsigned long data) | 121 | unsigned long data) |
53 | { | 122 | { |
54 | switch (reg_width) { | 123 | switch (reg_width) { |
55 | case 8: | 124 | case 8: |
56 | __raw_writeb(data, reg); | 125 | iowrite8(data, mapped_reg); |
57 | return; | 126 | return; |
58 | case 16: | 127 | case 16: |
59 | __raw_writew(data, reg); | 128 | iowrite16(data, mapped_reg); |
60 | return; | 129 | return; |
61 | case 32: | 130 | case 32: |
62 | __raw_writel(data, reg); | 131 | iowrite32(data, mapped_reg); |
63 | return; | 132 | return; |
64 | } | 133 | } |
65 | 134 | ||
@@ -82,11 +151,12 @@ static void gpio_write_bit(struct pinmux_data_reg *dr, | |||
82 | else | 151 | else |
83 | clear_bit(pos, &dr->reg_shadow); | 152 | clear_bit(pos, &dr->reg_shadow); |
84 | 153 | ||
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); |
86 | } | 155 | } |
87 | 156 | ||
88 | static int gpio_read_reg(unsigned long reg, unsigned long reg_width, | 157 | static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width, |
89 | unsigned long field_width, unsigned long in_pos) | 158 | unsigned long field_width, unsigned long in_pos, |
159 | unsigned long reg) | ||
90 | { | 160 | { |
91 | unsigned long data, mask, pos; | 161 | unsigned long data, mask, pos; |
92 | 162 | ||
@@ -98,13 +168,13 @@ static int gpio_read_reg(unsigned long reg, unsigned long reg_width, | |||
98 | "r_width = %ld, f_width = %ld\n", | 168 | "r_width = %ld, f_width = %ld\n", |
99 | reg, pos, reg_width, field_width); | 169 | reg, pos, reg_width, field_width); |
100 | 170 | ||
101 | data = gpio_read_raw_reg(reg, reg_width); | 171 | data = gpio_read_raw_reg(mapped_reg, reg_width); |
102 | return (data >> pos) & mask; | 172 | return (data >> pos) & mask; |
103 | } | 173 | } |
104 | 174 | ||
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, |
106 | unsigned long field_width, unsigned long in_pos, | 176 | unsigned long field_width, unsigned long in_pos, |
107 | unsigned long value) | 177 | unsigned long value, unsigned long reg) |
108 | { | 178 | { |
109 | unsigned long mask, pos; | 179 | unsigned long mask, pos; |
110 | 180 | ||
@@ -120,13 +190,13 @@ static void gpio_write_reg(unsigned long reg, unsigned long reg_width, | |||
120 | 190 | ||
121 | switch (reg_width) { | 191 | switch (reg_width) { |
122 | case 8: | 192 | case 8: |
123 | __raw_writeb((__raw_readb(reg) & mask) | value, reg); | 193 | iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg); |
124 | break; | 194 | break; |
125 | case 16: | 195 | case 16: |
126 | __raw_writew((__raw_readw(reg) & mask) | value, reg); | 196 | iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg); |
127 | break; | 197 | break; |
128 | case 32: | 198 | case 32: |
129 | __raw_writel((__raw_readl(reg) & mask) | value, reg); | 199 | iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg); |
130 | break; | 200 | break; |
131 | } | 201 | } |
132 | } | 202 | } |
@@ -147,6 +217,8 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) | |||
147 | if (!data_reg->reg_width) | 217 | if (!data_reg->reg_width) |
148 | break; | 218 | break; |
149 | 219 | ||
220 | data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg); | ||
221 | |||
150 | for (n = 0; n < data_reg->reg_width; n++) { | 222 | for (n = 0; n < data_reg->reg_width; n++) { |
151 | if (data_reg->enum_ids[n] == gpiop->enum_id) { | 223 | if (data_reg->enum_ids[n] == gpiop->enum_id) { |
152 | gpiop->flags &= ~PINMUX_FLAG_DREG; | 224 | gpiop->flags &= ~PINMUX_FLAG_DREG; |
@@ -179,7 +251,8 @@ static void setup_data_regs(struct pinmux_info *gpioc) | |||
179 | if (!drp->reg_width) | 251 | if (!drp->reg_width) |
180 | break; | 252 | break; |
181 | 253 | ||
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); | ||
183 | k++; | 256 | k++; |
184 | } | 257 | } |
185 | } | 258 | } |
@@ -266,12 +339,16 @@ static void write_config_reg(struct pinmux_info *gpioc, | |||
266 | int index) | 339 | int index) |
267 | { | 340 | { |
268 | unsigned long ncomb, pos, value; | 341 | unsigned long ncomb, pos, value; |
342 | void __iomem *mapped_reg; | ||
269 | 343 | ||
270 | ncomb = 1 << crp->field_width; | 344 | ncomb = 1 << crp->field_width; |
271 | pos = index / ncomb; | 345 | pos = index / ncomb; |
272 | value = index % ncomb; | 346 | value = index % ncomb; |
273 | 347 | ||
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); | ||
275 | } | 352 | } |
276 | 353 | ||
277 | static int check_config_reg(struct pinmux_info *gpioc, | 354 | static int check_config_reg(struct pinmux_info *gpioc, |
@@ -279,13 +356,16 @@ static int check_config_reg(struct pinmux_info *gpioc, | |||
279 | int index) | 356 | int index) |
280 | { | 357 | { |
281 | unsigned long ncomb, pos, value; | 358 | unsigned long ncomb, pos, value; |
359 | void __iomem *mapped_reg; | ||
282 | 360 | ||
283 | ncomb = 1 << crp->field_width; | 361 | ncomb = 1 << crp->field_width; |
284 | pos = index / ncomb; | 362 | pos = index / ncomb; |
285 | value = index % ncomb; | 363 | value = index % ncomb; |
286 | 364 | ||
287 | if (gpio_read_reg(crp->reg, crp->reg_width, | 365 | mapped_reg = pfc_phys_to_virt(gpioc, crp->reg); |
288 | crp->field_width, pos) == value) | 366 | |
367 | if (gpio_read_reg(mapped_reg, crp->reg_width, | ||
368 | crp->field_width, pos, crp->reg) == value) | ||
289 | return 0; | 369 | return 0; |
290 | 370 | ||
291 | return -1; | 371 | return -1; |
@@ -564,7 +644,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) | |||
564 | if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) | 644 | if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) |
565 | return -EINVAL; | 645 | return -EINVAL; |
566 | 646 | ||
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); |
568 | } | 648 | } |
569 | 649 | ||
570 | static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) | 650 | 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) | |||
606 | int register_pinmux(struct pinmux_info *pip) | 686 | int register_pinmux(struct pinmux_info *pip) |
607 | { | 687 | { |
608 | struct gpio_chip *chip = &pip->chip; | 688 | struct gpio_chip *chip = &pip->chip; |
689 | int ret; | ||
609 | 690 | ||
610 | pr_info("%s handling gpio %d -> %d\n", | 691 | pr_info("%s handling gpio %d -> %d\n", |
611 | pip->name, pip->first_gpio, pip->last_gpio); | 692 | pip->name, pip->first_gpio, pip->last_gpio); |
612 | 693 | ||
694 | ret = pfc_ioremap(pip); | ||
695 | if (ret < 0) | ||
696 | return ret; | ||
697 | |||
613 | setup_data_regs(pip); | 698 | setup_data_regs(pip); |
614 | 699 | ||
615 | chip->request = sh_gpio_request; | 700 | chip->request = sh_gpio_request; |
@@ -627,12 +712,16 @@ int register_pinmux(struct pinmux_info *pip) | |||
627 | chip->base = pip->first_gpio; | 712 | chip->base = pip->first_gpio; |
628 | chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; | 713 | chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; |
629 | 714 | ||
630 | return gpiochip_add(chip); | 715 | ret = gpiochip_add(chip); |
716 | if (ret < 0) | ||
717 | pfc_iounmap(pip); | ||
718 | |||
719 | return ret; | ||
631 | } | 720 | } |
632 | 721 | ||
633 | int unregister_pinmux(struct pinmux_info *pip) | 722 | int unregister_pinmux(struct pinmux_info *pip) |
634 | { | 723 | { |
635 | pr_info("%s deregistering\n", pip->name); | 724 | pr_info("%s deregistering\n", pip->name); |
636 | 725 | pfc_iounmap(pip); | |
637 | return gpiochip_remove(&pip->chip); | 726 | return gpiochip_remove(&pip->chip); |
638 | } | 727 | } |