diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-12 02:22:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-12 02:22:52 -0500 |
commit | 56c8bc3b7ed3d24c665e2ce992f86a5bedffc852 (patch) | |
tree | ee8747e83beb5a4323dd2328f3368ffb9031dc31 /drivers | |
parent | b8bf17d311c875de02550d5ce2af66588734159a (diff) | |
parent | 1c1744cc7cee83b96e3a89c1b9853fc033bafb9c (diff) |
Merge tag 'sh-for-linus' of git://github.com/pmundt/linux-sh
SuperH updates for 3.3 merge window.
* tag 'sh-for-linus' of git://github.com/pmundt/linux-sh: (38 commits)
sh: magicpanelr2: Update for parse_mtd_partitions() fallout.
sh: mach-rsk: Update for parse_mtd_partitions() fallout.
sh: sh2a: Improve cache flush/invalidate functions
sh: also without PM_RUNTIME pm_runtime.o must be built
sh: add a resource name for shdma
sh: Remove redundant try_to_freeze() invocations.
sh: Ensure IRQs are enabled across do_notify_resume().
sh: Fix up store queue code for subsys_interface changes.
sh: clkfwk: sh_clk_init_parent() should be called after clk_register()
sh: add platform_device for renesas_usbhs in board-sh7757lcr
sh: modify clock-sh7757 for renesas_usbhs
sh: pfc: ioremap() support
sh: use ioread32/iowrite32 and mapped_reg for div6
sh: use ioread32/iowrite32 and mapped_reg for div4
sh: use ioread32/iowrite32 and mapped_reg for mstp32
sh: extend clock struct with mapped_reg member
sh: clkfwk: clock-sh73a0: all div6_clks use SH_CLK_DIV6_EXT()
sh: clkfwk: clock-sh7724: all div6_clks use SH_CLK_DIV6_EXT()
sh: clock-sh7723: add CLKDEV_ICK_ID for cleanup
serial: sh-sci: Handle GPIO function requests.
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/sh/Makefile | 9 | ||||
-rw-r--r-- | drivers/sh/clk/core.c | 9 | ||||
-rw-r--r-- | drivers/sh/clk/cpg.c | 79 | ||||
-rw-r--r-- | drivers/sh/pfc.c | 137 | ||||
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 183 |
5 files changed, 343 insertions, 74 deletions
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 67e272ab1623..7139ad2f2086 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile | |||
@@ -7,11 +7,4 @@ obj-$(CONFIG_HAVE_CLK) += clk/ | |||
7 | obj-$(CONFIG_MAPLE) += maple/ | 7 | obj-$(CONFIG_MAPLE) += maple/ |
8 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 8 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
9 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o | 9 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o |
10 | 10 | obj-y += pm_runtime.o | |
11 | # | ||
12 | # For the moment we only use this framework for ARM-based SH/R-Mobile | ||
13 | # platforms and generic SH. SH-based SH-Mobile platforms are still using | ||
14 | # an older framework that is pending up-porting, at which point this | ||
15 | # special casing can go away. | ||
16 | # | ||
17 | obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o | ||
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index db257a35e71a..7715de2629c1 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c | |||
@@ -355,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk) | |||
355 | */ | 355 | */ |
356 | if (!clk->parent) { | 356 | if (!clk->parent) { |
357 | clk->mapping = &dummy_mapping; | 357 | clk->mapping = &dummy_mapping; |
358 | return 0; | 358 | goto out; |
359 | } | 359 | } |
360 | 360 | ||
361 | /* | 361 | /* |
@@ -384,6 +384,9 @@ static int clk_establish_mapping(struct clk *clk) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | clk->mapping = mapping; | 386 | clk->mapping = mapping; |
387 | out: | ||
388 | clk->mapped_reg = clk->mapping->base; | ||
389 | clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys; | ||
387 | return 0; | 390 | return 0; |
388 | } | 391 | } |
389 | 392 | ||
@@ -402,10 +405,12 @@ static void clk_teardown_mapping(struct clk *clk) | |||
402 | 405 | ||
403 | /* Nothing to do */ | 406 | /* Nothing to do */ |
404 | if (mapping == &dummy_mapping) | 407 | if (mapping == &dummy_mapping) |
405 | return; | 408 | goto out; |
406 | 409 | ||
407 | kref_put(&mapping->ref, clk_destroy_mapping); | 410 | kref_put(&mapping->ref, clk_destroy_mapping); |
408 | clk->mapping = NULL; | 411 | clk->mapping = NULL; |
412 | out: | ||
413 | clk->mapped_reg = NULL; | ||
409 | } | 414 | } |
410 | 415 | ||
411 | int clk_register(struct clk *clk) | 416 | int clk_register(struct clk *clk) |
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 @@ | |||
15 | 15 | ||
16 | static int sh_clk_mstp32_enable(struct clk *clk) | 16 | static int sh_clk_mstp32_enable(struct clk *clk) |
17 | { | 17 | { |
18 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), | 18 | iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), |
19 | clk->enable_reg); | 19 | clk->mapped_reg); |
20 | return 0; | 20 | return 0; |
21 | } | 21 | } |
22 | 22 | ||
23 | static void sh_clk_mstp32_disable(struct clk *clk) | 23 | static void sh_clk_mstp32_disable(struct clk *clk) |
24 | { | 24 | { |
25 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), | 25 | iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), |
26 | clk->enable_reg); | 26 | clk->mapped_reg); |
27 | } | 27 | } |
28 | 28 | ||
29 | static struct clk_ops sh_clk_mstp32_clk_ops = { | 29 | static struct clk_ops sh_clk_mstp32_clk_ops = { |
@@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) | |||
72 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 72 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
73 | table, NULL); | 73 | table, NULL); |
74 | 74 | ||
75 | idx = __raw_readl(clk->enable_reg) & 0x003f; | 75 | idx = ioread32(clk->mapped_reg) & 0x003f; |
76 | 76 | ||
77 | return clk->freq_table[idx].frequency; | 77 | return clk->freq_table[idx].frequency; |
78 | } | 78 | } |
@@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) | |||
98 | if (ret < 0) | 98 | if (ret < 0) |
99 | return ret; | 99 | return ret; |
100 | 100 | ||
101 | value = __raw_readl(clk->enable_reg) & | 101 | value = ioread32(clk->mapped_reg) & |
102 | ~(((1 << clk->src_width) - 1) << clk->src_shift); | 102 | ~(((1 << clk->src_width) - 1) << clk->src_shift); |
103 | 103 | ||
104 | __raw_writel(value | (i << clk->src_shift), clk->enable_reg); | 104 | iowrite32(value | (i << clk->src_shift), clk->mapped_reg); |
105 | 105 | ||
106 | /* Rebuild the frequency table */ | 106 | /* Rebuild the frequency table */ |
107 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 107 | 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) | |||
119 | if (idx < 0) | 119 | if (idx < 0) |
120 | return idx; | 120 | return idx; |
121 | 121 | ||
122 | value = __raw_readl(clk->enable_reg); | 122 | value = ioread32(clk->mapped_reg); |
123 | value &= ~0x3f; | 123 | value &= ~0x3f; |
124 | value |= idx; | 124 | value |= idx; |
125 | __raw_writel(value, clk->enable_reg); | 125 | iowrite32(value, clk->mapped_reg); |
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
@@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk *clk) | |||
133 | 133 | ||
134 | ret = sh_clk_div6_set_rate(clk, clk->rate); | 134 | ret = sh_clk_div6_set_rate(clk, clk->rate); |
135 | if (ret == 0) { | 135 | if (ret == 0) { |
136 | value = __raw_readl(clk->enable_reg); | 136 | value = ioread32(clk->mapped_reg); |
137 | value &= ~0x100; /* clear stop bit to enable clock */ | 137 | value &= ~0x100; /* clear stop bit to enable clock */ |
138 | __raw_writel(value, clk->enable_reg); | 138 | iowrite32(value, clk->mapped_reg); |
139 | } | 139 | } |
140 | return ret; | 140 | return ret; |
141 | } | 141 | } |
@@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct clk *clk) | |||
144 | { | 144 | { |
145 | unsigned long value; | 145 | unsigned long value; |
146 | 146 | ||
147 | value = __raw_readl(clk->enable_reg); | 147 | value = ioread32(clk->mapped_reg); |
148 | value |= 0x100; /* stop clock */ | 148 | value |= 0x100; /* stop clock */ |
149 | value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ | 149 | value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ |
150 | __raw_writel(value, clk->enable_reg); | 150 | iowrite32(value, clk->mapped_reg); |
151 | } | 151 | } |
152 | 152 | ||
153 | static struct clk_ops sh_clk_div6_clk_ops = { | 153 | static struct clk_ops sh_clk_div6_clk_ops = { |
@@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = { | |||
167 | .set_parent = sh_clk_div6_set_parent, | 167 | .set_parent = sh_clk_div6_set_parent, |
168 | }; | 168 | }; |
169 | 169 | ||
170 | static int __init sh_clk_init_parent(struct clk *clk) | ||
171 | { | ||
172 | u32 val; | ||
173 | |||
174 | if (clk->parent) | ||
175 | return 0; | ||
176 | |||
177 | if (!clk->parent_table || !clk->parent_num) | ||
178 | return 0; | ||
179 | |||
180 | if (!clk->src_width) { | ||
181 | pr_err("sh_clk_init_parent: cannot select parent clock\n"); | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | val = (ioread32(clk->mapped_reg) >> clk->src_shift); | ||
186 | val &= (1 << clk->src_width) - 1; | ||
187 | |||
188 | if (val >= clk->parent_num) { | ||
189 | pr_err("sh_clk_init_parent: parent table size failed\n"); | ||
190 | return -EINVAL; | ||
191 | } | ||
192 | |||
193 | clk->parent = clk->parent_table[val]; | ||
194 | if (!clk->parent) { | ||
195 | pr_err("sh_clk_init_parent: unable to set parent"); | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
170 | static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, | 202 | static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, |
171 | struct clk_ops *ops) | 203 | struct clk_ops *ops) |
172 | { | 204 | { |
@@ -190,8 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, | |||
190 | clkp->ops = ops; | 222 | clkp->ops = ops; |
191 | clkp->freq_table = freq_table + (k * freq_table_size); | 223 | clkp->freq_table = freq_table + (k * freq_table_size); |
192 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | 224 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; |
193 | |||
194 | ret = clk_register(clkp); | 225 | ret = clk_register(clkp); |
226 | if (ret < 0) | ||
227 | break; | ||
228 | |||
229 | ret = sh_clk_init_parent(clkp); | ||
195 | } | 230 | } |
196 | 231 | ||
197 | return ret; | 232 | return ret; |
@@ -217,7 +252,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) | |||
217 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 252 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
218 | table, &clk->arch_flags); | 253 | table, &clk->arch_flags); |
219 | 254 | ||
220 | idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; | 255 | idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f; |
221 | 256 | ||
222 | return clk->freq_table[idx].frequency; | 257 | return clk->freq_table[idx].frequency; |
223 | } | 258 | } |
@@ -235,15 +270,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) | |||
235 | */ | 270 | */ |
236 | 271 | ||
237 | if (parent->flags & CLK_ENABLE_ON_INIT) | 272 | if (parent->flags & CLK_ENABLE_ON_INIT) |
238 | value = __raw_readl(clk->enable_reg) & ~(1 << 7); | 273 | value = ioread32(clk->mapped_reg) & ~(1 << 7); |
239 | else | 274 | else |
240 | value = __raw_readl(clk->enable_reg) | (1 << 7); | 275 | value = ioread32(clk->mapped_reg) | (1 << 7); |
241 | 276 | ||
242 | ret = clk_reparent(clk, parent); | 277 | ret = clk_reparent(clk, parent); |
243 | if (ret < 0) | 278 | if (ret < 0) |
244 | return ret; | 279 | return ret; |
245 | 280 | ||
246 | __raw_writel(value, clk->enable_reg); | 281 | iowrite32(value, clk->mapped_reg); |
247 | 282 | ||
248 | /* Rebiuld the frequency table */ | 283 | /* Rebiuld the frequency table */ |
249 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 284 | 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) | |||
260 | if (idx < 0) | 295 | if (idx < 0) |
261 | return idx; | 296 | return idx; |
262 | 297 | ||
263 | value = __raw_readl(clk->enable_reg); | 298 | value = ioread32(clk->mapped_reg); |
264 | value &= ~(0xf << clk->enable_bit); | 299 | value &= ~(0xf << clk->enable_bit); |
265 | value |= (idx << clk->enable_bit); | 300 | value |= (idx << clk->enable_bit); |
266 | __raw_writel(value, clk->enable_reg); | 301 | iowrite32(value, clk->mapped_reg); |
267 | 302 | ||
268 | if (d4t->kick) | 303 | if (d4t->kick) |
269 | d4t->kick(clk); | 304 | d4t->kick(clk); |
@@ -273,13 +308,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) | |||
273 | 308 | ||
274 | static int sh_clk_div4_enable(struct clk *clk) | 309 | static int sh_clk_div4_enable(struct clk *clk) |
275 | { | 310 | { |
276 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); | 311 | iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg); |
277 | return 0; | 312 | return 0; |
278 | } | 313 | } |
279 | 314 | ||
280 | static void sh_clk_div4_disable(struct clk *clk) | 315 | static void sh_clk_div4_disable(struct clk *clk) |
281 | { | 316 | { |
282 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); | 317 | iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg); |
283 | } | 318 | } |
284 | 319 | ||
285 | static struct clk_ops sh_clk_div4_clk_ops = { | 320 | static struct clk_ops sh_clk_div4_clk_ops = { |
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 | } |
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index aff9d612dff0..9e62349b3d9f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/dma-mapping.h> | 50 | #include <linux/dma-mapping.h> |
51 | #include <linux/scatterlist.h> | 51 | #include <linux/scatterlist.h> |
52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
53 | #include <linux/gpio.h> | ||
53 | 54 | ||
54 | #ifdef CONFIG_SUPERH | 55 | #ifdef CONFIG_SUPERH |
55 | #include <asm/sh_bios.h> | 56 | #include <asm/sh_bios.h> |
@@ -73,6 +74,7 @@ struct sci_port { | |||
73 | struct clk *fclk; | 74 | struct clk *fclk; |
74 | 75 | ||
75 | char *irqstr[SCIx_NR_IRQS]; | 76 | char *irqstr[SCIx_NR_IRQS]; |
77 | char *gpiostr[SCIx_NR_FNS]; | ||
76 | 78 | ||
77 | struct dma_chan *chan_tx; | 79 | struct dma_chan *chan_tx; |
78 | struct dma_chan *chan_rx; | 80 | struct dma_chan *chan_rx; |
@@ -474,8 +476,15 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) | |||
474 | if (!reg->size) | 476 | if (!reg->size) |
475 | return; | 477 | return; |
476 | 478 | ||
477 | if (!(cflag & CRTSCTS)) | 479 | if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) && |
478 | sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */ | 480 | ((!(cflag & CRTSCTS)))) { |
481 | unsigned short status; | ||
482 | |||
483 | status = sci_in(port, SCSPTR); | ||
484 | status &= ~SCSPTR_CTSIO; | ||
485 | status |= SCSPTR_RTSIO; | ||
486 | sci_out(port, SCSPTR, status); /* Set RTS = 1 */ | ||
487 | } | ||
479 | } | 488 | } |
480 | 489 | ||
481 | static int sci_txfill(struct uart_port *port) | 490 | static int sci_txfill(struct uart_port *port) |
@@ -621,6 +630,7 @@ static void sci_receive_chars(struct uart_port *port) | |||
621 | } else { | 630 | } else { |
622 | for (i = 0; i < count; i++) { | 631 | for (i = 0; i < count; i++) { |
623 | char c = sci_in(port, SCxRDR); | 632 | char c = sci_in(port, SCxRDR); |
633 | |||
624 | status = sci_in(port, SCxSR); | 634 | status = sci_in(port, SCxSR); |
625 | #if defined(CONFIG_CPU_SH3) | 635 | #if defined(CONFIG_CPU_SH3) |
626 | /* Skip "chars" during break */ | 636 | /* Skip "chars" during break */ |
@@ -649,9 +659,11 @@ static void sci_receive_chars(struct uart_port *port) | |||
649 | /* Store data and status */ | 659 | /* Store data and status */ |
650 | if (status & SCxSR_FER(port)) { | 660 | if (status & SCxSR_FER(port)) { |
651 | flag = TTY_FRAME; | 661 | flag = TTY_FRAME; |
662 | port->icount.frame++; | ||
652 | dev_notice(port->dev, "frame error\n"); | 663 | dev_notice(port->dev, "frame error\n"); |
653 | } else if (status & SCxSR_PER(port)) { | 664 | } else if (status & SCxSR_PER(port)) { |
654 | flag = TTY_PARITY; | 665 | flag = TTY_PARITY; |
666 | port->icount.parity++; | ||
655 | dev_notice(port->dev, "parity error\n"); | 667 | dev_notice(port->dev, "parity error\n"); |
656 | } else | 668 | } else |
657 | flag = TTY_NORMAL; | 669 | flag = TTY_NORMAL; |
@@ -723,6 +735,8 @@ static int sci_handle_errors(struct uart_port *port) | |||
723 | */ | 735 | */ |
724 | if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) { | 736 | if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) { |
725 | if (status & (1 << s->cfg->overrun_bit)) { | 737 | if (status & (1 << s->cfg->overrun_bit)) { |
738 | port->icount.overrun++; | ||
739 | |||
726 | /* overrun error */ | 740 | /* overrun error */ |
727 | if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) | 741 | if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) |
728 | copied++; | 742 | copied++; |
@@ -737,6 +751,8 @@ static int sci_handle_errors(struct uart_port *port) | |||
737 | struct sci_port *sci_port = to_sci_port(port); | 751 | struct sci_port *sci_port = to_sci_port(port); |
738 | 752 | ||
739 | if (!sci_port->break_flag) { | 753 | if (!sci_port->break_flag) { |
754 | port->icount.brk++; | ||
755 | |||
740 | sci_port->break_flag = 1; | 756 | sci_port->break_flag = 1; |
741 | sci_schedule_break_timer(sci_port); | 757 | sci_schedule_break_timer(sci_port); |
742 | 758 | ||
@@ -752,6 +768,8 @@ static int sci_handle_errors(struct uart_port *port) | |||
752 | 768 | ||
753 | } else { | 769 | } else { |
754 | /* frame error */ | 770 | /* frame error */ |
771 | port->icount.frame++; | ||
772 | |||
755 | if (tty_insert_flip_char(tty, 0, TTY_FRAME)) | 773 | if (tty_insert_flip_char(tty, 0, TTY_FRAME)) |
756 | copied++; | 774 | copied++; |
757 | 775 | ||
@@ -761,6 +779,8 @@ static int sci_handle_errors(struct uart_port *port) | |||
761 | 779 | ||
762 | if (status & SCxSR_PER(port)) { | 780 | if (status & SCxSR_PER(port)) { |
763 | /* parity error */ | 781 | /* parity error */ |
782 | port->icount.parity++; | ||
783 | |||
764 | if (tty_insert_flip_char(tty, 0, TTY_PARITY)) | 784 | if (tty_insert_flip_char(tty, 0, TTY_PARITY)) |
765 | copied++; | 785 | copied++; |
766 | 786 | ||
@@ -787,6 +807,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port) | |||
787 | if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { | 807 | if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { |
788 | sci_out(port, SCLSR, 0); | 808 | sci_out(port, SCLSR, 0); |
789 | 809 | ||
810 | port->icount.overrun++; | ||
811 | |||
790 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 812 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
791 | tty_flip_buffer_push(tty); | 813 | tty_flip_buffer_push(tty); |
792 | 814 | ||
@@ -812,6 +834,9 @@ static int sci_handle_breaks(struct uart_port *port) | |||
812 | /* Debounce break */ | 834 | /* Debounce break */ |
813 | s->break_flag = 1; | 835 | s->break_flag = 1; |
814 | #endif | 836 | #endif |
837 | |||
838 | port->icount.brk++; | ||
839 | |||
815 | /* Notify of BREAK */ | 840 | /* Notify of BREAK */ |
816 | if (tty_insert_flip_char(tty, 0, TTY_BREAK)) | 841 | if (tty_insert_flip_char(tty, 0, TTY_BREAK)) |
817 | copied++; | 842 | copied++; |
@@ -1082,6 +1107,67 @@ static void sci_free_irq(struct sci_port *port) | |||
1082 | } | 1107 | } |
1083 | } | 1108 | } |
1084 | 1109 | ||
1110 | static const char *sci_gpio_names[SCIx_NR_FNS] = { | ||
1111 | "sck", "rxd", "txd", "cts", "rts", | ||
1112 | }; | ||
1113 | |||
1114 | static const char *sci_gpio_str(unsigned int index) | ||
1115 | { | ||
1116 | return sci_gpio_names[index]; | ||
1117 | } | ||
1118 | |||
1119 | static void __devinit sci_init_gpios(struct sci_port *port) | ||
1120 | { | ||
1121 | struct uart_port *up = &port->port; | ||
1122 | int i; | ||
1123 | |||
1124 | if (!port->cfg) | ||
1125 | return; | ||
1126 | |||
1127 | for (i = 0; i < SCIx_NR_FNS; i++) { | ||
1128 | const char *desc; | ||
1129 | int ret; | ||
1130 | |||
1131 | if (!port->cfg->gpios[i]) | ||
1132 | continue; | ||
1133 | |||
1134 | desc = sci_gpio_str(i); | ||
1135 | |||
1136 | port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s", | ||
1137 | dev_name(up->dev), desc); | ||
1138 | |||
1139 | /* | ||
1140 | * If we've failed the allocation, we can still continue | ||
1141 | * on with a NULL string. | ||
1142 | */ | ||
1143 | if (!port->gpiostr[i]) | ||
1144 | dev_notice(up->dev, "%s string allocation failure\n", | ||
1145 | desc); | ||
1146 | |||
1147 | ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]); | ||
1148 | if (unlikely(ret != 0)) { | ||
1149 | dev_notice(up->dev, "failed %s gpio request\n", desc); | ||
1150 | |||
1151 | /* | ||
1152 | * If we can't get the GPIO for whatever reason, | ||
1153 | * no point in keeping the verbose string around. | ||
1154 | */ | ||
1155 | kfree(port->gpiostr[i]); | ||
1156 | } | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | static void sci_free_gpios(struct sci_port *port) | ||
1161 | { | ||
1162 | int i; | ||
1163 | |||
1164 | for (i = 0; i < SCIx_NR_FNS; i++) | ||
1165 | if (port->cfg->gpios[i]) { | ||
1166 | gpio_free(port->cfg->gpios[i]); | ||
1167 | kfree(port->gpiostr[i]); | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1085 | static unsigned int sci_tx_empty(struct uart_port *port) | 1171 | static unsigned int sci_tx_empty(struct uart_port *port) |
1086 | { | 1172 | { |
1087 | unsigned short status = sci_in(port, SCxSR); | 1173 | unsigned short status = sci_in(port, SCxSR); |
@@ -1090,19 +1176,39 @@ static unsigned int sci_tx_empty(struct uart_port *port) | |||
1090 | return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0; | 1176 | return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0; |
1091 | } | 1177 | } |
1092 | 1178 | ||
1179 | /* | ||
1180 | * Modem control is a bit of a mixed bag for SCI(F) ports. Generally | ||
1181 | * CTS/RTS is supported in hardware by at least one port and controlled | ||
1182 | * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently | ||
1183 | * handled via the ->init_pins() op, which is a bit of a one-way street, | ||
1184 | * lacking any ability to defer pin control -- this will later be | ||
1185 | * converted over to the GPIO framework). | ||
1186 | * | ||
1187 | * Other modes (such as loopback) are supported generically on certain | ||
1188 | * port types, but not others. For these it's sufficient to test for the | ||
1189 | * existence of the support register and simply ignore the port type. | ||
1190 | */ | ||
1093 | static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) | 1191 | static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) |
1094 | { | 1192 | { |
1095 | /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */ | 1193 | if (mctrl & TIOCM_LOOP) { |
1096 | /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */ | 1194 | struct plat_sci_reg *reg; |
1097 | /* If you have signals for DTR and DCD, please implement here. */ | 1195 | |
1196 | /* | ||
1197 | * Standard loopback mode for SCFCR ports. | ||
1198 | */ | ||
1199 | reg = sci_getreg(port, SCFCR); | ||
1200 | if (reg->size) | ||
1201 | sci_out(port, SCFCR, sci_in(port, SCFCR) | 1); | ||
1202 | } | ||
1098 | } | 1203 | } |
1099 | 1204 | ||
1100 | static unsigned int sci_get_mctrl(struct uart_port *port) | 1205 | static unsigned int sci_get_mctrl(struct uart_port *port) |
1101 | { | 1206 | { |
1102 | /* This routine is used for getting signals of: DTR, DCD, DSR, RI, | 1207 | /* |
1103 | and CTS/RTS */ | 1208 | * CTS/RTS is handled in hardware when supported, while nothing |
1104 | 1209 | * else is wired up. Keep it simple and simply assert DSR/CAR. | |
1105 | return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR; | 1210 | */ |
1211 | return TIOCM_DSR | TIOCM_CAR; | ||
1106 | } | 1212 | } |
1107 | 1213 | ||
1108 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1214 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
@@ -1449,12 +1555,17 @@ static void sci_stop_rx(struct uart_port *port) | |||
1449 | 1555 | ||
1450 | static void sci_enable_ms(struct uart_port *port) | 1556 | static void sci_enable_ms(struct uart_port *port) |
1451 | { | 1557 | { |
1452 | /* Nothing here yet .. */ | 1558 | /* |
1559 | * Not supported by hardware, always a nop. | ||
1560 | */ | ||
1453 | } | 1561 | } |
1454 | 1562 | ||
1455 | static void sci_break_ctl(struct uart_port *port, int break_state) | 1563 | static void sci_break_ctl(struct uart_port *port, int break_state) |
1456 | { | 1564 | { |
1457 | /* Nothing here yet .. */ | 1565 | /* |
1566 | * Not supported by hardware. Most parts couple break and rx | ||
1567 | * interrupts together, with break detection always enabled. | ||
1568 | */ | ||
1458 | } | 1569 | } |
1459 | 1570 | ||
1460 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1571 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
@@ -1652,6 +1763,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, | |||
1652 | 1763 | ||
1653 | static void sci_reset(struct uart_port *port) | 1764 | static void sci_reset(struct uart_port *port) |
1654 | { | 1765 | { |
1766 | struct plat_sci_reg *reg; | ||
1655 | unsigned int status; | 1767 | unsigned int status; |
1656 | 1768 | ||
1657 | do { | 1769 | do { |
@@ -1660,7 +1772,8 @@ static void sci_reset(struct uart_port *port) | |||
1660 | 1772 | ||
1661 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ | 1773 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ |
1662 | 1774 | ||
1663 | if (port->type != PORT_SCI) | 1775 | reg = sci_getreg(port, SCFCR); |
1776 | if (reg->size) | ||
1664 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | 1777 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); |
1665 | } | 1778 | } |
1666 | 1779 | ||
@@ -1668,9 +1781,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1668 | struct ktermios *old) | 1781 | struct ktermios *old) |
1669 | { | 1782 | { |
1670 | struct sci_port *s = to_sci_port(port); | 1783 | struct sci_port *s = to_sci_port(port); |
1784 | struct plat_sci_reg *reg; | ||
1671 | unsigned int baud, smr_val, max_baud; | 1785 | unsigned int baud, smr_val, max_baud; |
1672 | int t = -1; | 1786 | int t = -1; |
1673 | u16 scfcr = 0; | ||
1674 | 1787 | ||
1675 | /* | 1788 | /* |
1676 | * earlyprintk comes here early on with port->uartclk set to zero. | 1789 | * earlyprintk comes here early on with port->uartclk set to zero. |
@@ -1720,7 +1833,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1720 | } | 1833 | } |
1721 | 1834 | ||
1722 | sci_init_pins(port, termios->c_cflag); | 1835 | sci_init_pins(port, termios->c_cflag); |
1723 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); | 1836 | |
1837 | reg = sci_getreg(port, SCFCR); | ||
1838 | if (reg->size) { | ||
1839 | unsigned short ctrl = sci_in(port, SCFCR); | ||
1840 | |||
1841 | if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) { | ||
1842 | if (termios->c_cflag & CRTSCTS) | ||
1843 | ctrl |= SCFCR_MCE; | ||
1844 | else | ||
1845 | ctrl &= ~SCFCR_MCE; | ||
1846 | } | ||
1847 | |||
1848 | /* | ||
1849 | * As we've done a sci_reset() above, ensure we don't | ||
1850 | * interfere with the FIFOs while toggling MCE. As the | ||
1851 | * reset values could still be set, simply mask them out. | ||
1852 | */ | ||
1853 | ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST); | ||
1854 | |||
1855 | sci_out(port, SCFCR, ctrl); | ||
1856 | } | ||
1724 | 1857 | ||
1725 | sci_out(port, SCSCR, s->cfg->scscr); | 1858 | sci_out(port, SCSCR, s->cfg->scscr); |
1726 | 1859 | ||
@@ -1892,6 +2025,8 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1892 | struct uart_port *port = &sci_port->port; | 2025 | struct uart_port *port = &sci_port->port; |
1893 | int ret; | 2026 | int ret; |
1894 | 2027 | ||
2028 | sci_port->cfg = p; | ||
2029 | |||
1895 | port->ops = &sci_uart_ops; | 2030 | port->ops = &sci_uart_ops; |
1896 | port->iotype = UPIO_MEM; | 2031 | port->iotype = UPIO_MEM; |
1897 | port->line = index; | 2032 | port->line = index; |
@@ -1937,6 +2072,8 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1937 | 2072 | ||
1938 | port->dev = &dev->dev; | 2073 | port->dev = &dev->dev; |
1939 | 2074 | ||
2075 | sci_init_gpios(sci_port); | ||
2076 | |||
1940 | pm_runtime_irq_safe(&dev->dev); | 2077 | pm_runtime_irq_safe(&dev->dev); |
1941 | pm_runtime_enable(&dev->dev); | 2078 | pm_runtime_enable(&dev->dev); |
1942 | } | 2079 | } |
@@ -1971,8 +2108,6 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1971 | p->error_mask |= (1 << p->overrun_bit); | 2108 | p->error_mask |= (1 << p->overrun_bit); |
1972 | } | 2109 | } |
1973 | 2110 | ||
1974 | sci_port->cfg = p; | ||
1975 | |||
1976 | port->mapbase = p->mapbase; | 2111 | port->mapbase = p->mapbase; |
1977 | port->type = p->type; | 2112 | port->type = p->type; |
1978 | port->flags = p->flags; | 2113 | port->flags = p->flags; |
@@ -2113,9 +2248,16 @@ static int sci_runtime_suspend(struct device *dev) | |||
2113 | struct uart_port *port = &sci_port->port; | 2248 | struct uart_port *port = &sci_port->port; |
2114 | 2249 | ||
2115 | if (uart_console(port)) { | 2250 | if (uart_console(port)) { |
2251 | struct plat_sci_reg *reg; | ||
2252 | |||
2116 | sci_port->saved_smr = sci_in(port, SCSMR); | 2253 | sci_port->saved_smr = sci_in(port, SCSMR); |
2117 | sci_port->saved_brr = sci_in(port, SCBRR); | 2254 | sci_port->saved_brr = sci_in(port, SCBRR); |
2118 | sci_port->saved_fcr = sci_in(port, SCFCR); | 2255 | |
2256 | reg = sci_getreg(port, SCFCR); | ||
2257 | if (reg->size) | ||
2258 | sci_port->saved_fcr = sci_in(port, SCFCR); | ||
2259 | else | ||
2260 | sci_port->saved_fcr = 0; | ||
2119 | } | 2261 | } |
2120 | return 0; | 2262 | return 0; |
2121 | } | 2263 | } |
@@ -2129,7 +2271,10 @@ static int sci_runtime_resume(struct device *dev) | |||
2129 | sci_reset(port); | 2271 | sci_reset(port); |
2130 | sci_out(port, SCSMR, sci_port->saved_smr); | 2272 | sci_out(port, SCSMR, sci_port->saved_smr); |
2131 | sci_out(port, SCBRR, sci_port->saved_brr); | 2273 | sci_out(port, SCBRR, sci_port->saved_brr); |
2132 | sci_out(port, SCFCR, sci_port->saved_fcr); | 2274 | |
2275 | if (sci_port->saved_fcr) | ||
2276 | sci_out(port, SCFCR, sci_port->saved_fcr); | ||
2277 | |||
2133 | sci_out(port, SCSCR, sci_port->cfg->scscr); | 2278 | sci_out(port, SCSCR, sci_port->cfg->scscr); |
2134 | } | 2279 | } |
2135 | return 0; | 2280 | return 0; |
@@ -2169,6 +2314,8 @@ static int sci_remove(struct platform_device *dev) | |||
2169 | cpufreq_unregister_notifier(&port->freq_transition, | 2314 | cpufreq_unregister_notifier(&port->freq_transition, |
2170 | CPUFREQ_TRANSITION_NOTIFIER); | 2315 | CPUFREQ_TRANSITION_NOTIFIER); |
2171 | 2316 | ||
2317 | sci_free_gpios(port); | ||
2318 | |||
2172 | uart_remove_one_port(&sci_uart_driver, &port->port); | 2319 | uart_remove_one_port(&sci_uart_driver, &port->port); |
2173 | 2320 | ||
2174 | clk_put(port->iclk); | 2321 | clk_put(port->iclk); |