diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:37:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:37:47 -0400 |
commit | b1af9ccce9cff5b48c37424dbdbb3aa9021915db (patch) | |
tree | cce75cb4406c7ed412c334fa632dd1d185d2dced /drivers | |
parent | cc216c5d429892872f70f76975e243aef7ad9db1 (diff) | |
parent | 440fc172ae333c52c458401fe059afcc6e91eebf (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (27 commits)
sh: Fix up L2 cache probe.
sh: Fix up SH-4A part probe.
sh: Add support for SH7723 CPU subtype.
sh: Fix up SH7763 build.
sh: Add migor_ts support to MigoR
sh: Add rs5c732b RTC support to MigoR
sh: Add I2C support to MigoR
sh: Add I2C platform data to sh7722
sh: MigoR NAND flash support using gen_flash
sh: MigoR NOR flash support using physmap-flash
sh: Fix up mach-types formatting from merge damage.
sh: r7780rp: Hook up the I2C and SMBus platform devices.
sh: Use phyical addresses for MigoR smc91x resources
sh: Use physical addresses for sh7722 USBF resources
sh: Add MigoR header file
Fix sh_keysc double free
sh: Fix up __access_ok() check for nommu.
sh: Allow optimized clear/copy page routines to be used on SH-2.
sh: Hook up the rest of the SH7770 serial ports.
sh: Add support for Solution Engine SH7721 board
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/keyboard/Kconfig | 9 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/sh_keysc.c | 280 | ||||
-rw-r--r-- | drivers/rtc/rtc-sh.c | 296 | ||||
-rw-r--r-- | drivers/serial/sh-sci.c | 7 | ||||
-rw-r--r-- | drivers/serial/sh-sci.h | 60 |
6 files changed, 528 insertions, 125 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 8ea709be3306..efd70a974591 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -314,4 +314,13 @@ config KEYBOARD_BFIN | |||
314 | To compile this driver as a module, choose M here: the | 314 | To compile this driver as a module, choose M here: the |
315 | module will be called bf54x-keys. | 315 | module will be called bf54x-keys. |
316 | 316 | ||
317 | config KEYBOARD_SH_KEYSC | ||
318 | tristate "SuperH KEYSC keypad support" | ||
319 | depends on SUPERH | ||
320 | help | ||
321 | Say Y here if you want to use a keypad attached to the KEYSC block | ||
322 | on SuperH processors such as sh7722 and sh7343. | ||
323 | |||
324 | To compile this driver as a module, choose M here: the | ||
325 | module will be called sh_keysc. | ||
317 | endif | 326 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index e741f4031012..0edc8f285d1c 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -26,3 +26,4 @@ obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | |||
26 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | 26 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o |
27 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | 27 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o |
28 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 28 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
29 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | ||
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c new file mode 100644 index 000000000000..8486abc457ed --- /dev/null +++ b/drivers/input/keyboard/sh_keysc.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * SuperH KEYSC Keypad Driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Magnus Damm | ||
5 | * | ||
6 | * Based on gpio_keys.c, Copyright 2005 Phil Blundell | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <asm/sh_keysc.h> | ||
23 | |||
24 | #define KYCR1_OFFS 0x00 | ||
25 | #define KYCR2_OFFS 0x04 | ||
26 | #define KYINDR_OFFS 0x08 | ||
27 | #define KYOUTDR_OFFS 0x0c | ||
28 | |||
29 | #define KYCR2_IRQ_LEVEL 0x10 | ||
30 | #define KYCR2_IRQ_DISABLED 0x00 | ||
31 | |||
32 | static const struct { | ||
33 | unsigned char kymd, keyout, keyin; | ||
34 | } sh_keysc_mode[] = { | ||
35 | [SH_KEYSC_MODE_1] = { 0, 6, 5 }, | ||
36 | [SH_KEYSC_MODE_2] = { 1, 5, 6 }, | ||
37 | [SH_KEYSC_MODE_3] = { 2, 4, 7 }, | ||
38 | }; | ||
39 | |||
40 | struct sh_keysc_priv { | ||
41 | void __iomem *iomem_base; | ||
42 | unsigned long last_keys; | ||
43 | struct input_dev *input; | ||
44 | struct sh_keysc_info pdata; | ||
45 | }; | ||
46 | |||
47 | static irqreturn_t sh_keysc_isr(int irq, void *dev_id) | ||
48 | { | ||
49 | struct platform_device *pdev = dev_id; | ||
50 | struct sh_keysc_priv *priv = platform_get_drvdata(pdev); | ||
51 | struct sh_keysc_info *pdata = &priv->pdata; | ||
52 | unsigned long keys, keys1, keys0, mask; | ||
53 | unsigned char keyin_set, tmp; | ||
54 | int i, k; | ||
55 | |||
56 | dev_dbg(&pdev->dev, "isr!\n"); | ||
57 | |||
58 | keys1 = ~0; | ||
59 | keys0 = 0; | ||
60 | |||
61 | do { | ||
62 | keys = 0; | ||
63 | keyin_set = 0; | ||
64 | |||
65 | iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); | ||
66 | |||
67 | for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { | ||
68 | iowrite16(0xfff ^ (3 << (i * 2)), | ||
69 | priv->iomem_base + KYOUTDR_OFFS); | ||
70 | udelay(pdata->delay); | ||
71 | tmp = ioread16(priv->iomem_base + KYINDR_OFFS); | ||
72 | keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); | ||
73 | tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; | ||
74 | keyin_set |= tmp; | ||
75 | } | ||
76 | |||
77 | iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); | ||
78 | iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8), | ||
79 | priv->iomem_base + KYCR2_OFFS); | ||
80 | |||
81 | keys ^= ~0; | ||
82 | keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * | ||
83 | sh_keysc_mode[pdata->mode].keyout)) - 1; | ||
84 | keys1 &= keys; | ||
85 | keys0 |= keys; | ||
86 | |||
87 | dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); | ||
88 | |||
89 | } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01); | ||
90 | |||
91 | dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", | ||
92 | priv->last_keys, keys0, keys1); | ||
93 | |||
94 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { | ||
95 | k = pdata->keycodes[i]; | ||
96 | if (!k) | ||
97 | continue; | ||
98 | |||
99 | mask = 1 << i; | ||
100 | |||
101 | if (!((priv->last_keys ^ keys0) & mask)) | ||
102 | continue; | ||
103 | |||
104 | if ((keys1 | keys0) & mask) { | ||
105 | input_event(priv->input, EV_KEY, k, 1); | ||
106 | priv->last_keys |= mask; | ||
107 | } | ||
108 | |||
109 | if (!(keys1 & mask)) { | ||
110 | input_event(priv->input, EV_KEY, k, 0); | ||
111 | priv->last_keys &= ~mask; | ||
112 | } | ||
113 | |||
114 | } | ||
115 | input_sync(priv->input); | ||
116 | |||
117 | return IRQ_HANDLED; | ||
118 | } | ||
119 | |||
120 | #define res_size(res) ((res)->end - (res)->start + 1) | ||
121 | |||
122 | static int __devinit sh_keysc_probe(struct platform_device *pdev) | ||
123 | { | ||
124 | struct sh_keysc_priv *priv; | ||
125 | struct sh_keysc_info *pdata; | ||
126 | struct resource *res; | ||
127 | struct input_dev *input; | ||
128 | int i, k; | ||
129 | int irq, error; | ||
130 | |||
131 | if (!pdev->dev.platform_data) { | ||
132 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
133 | error = -EINVAL; | ||
134 | goto err0; | ||
135 | } | ||
136 | |||
137 | error = -ENXIO; | ||
138 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
139 | if (res == NULL) { | ||
140 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
141 | goto err0; | ||
142 | } | ||
143 | |||
144 | irq = platform_get_irq(pdev, 0); | ||
145 | if (irq < 0) { | ||
146 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
147 | goto err0; | ||
148 | } | ||
149 | |||
150 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
151 | if (priv == NULL) { | ||
152 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
153 | error = -ENOMEM; | ||
154 | goto err0; | ||
155 | } | ||
156 | |||
157 | platform_set_drvdata(pdev, priv); | ||
158 | memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); | ||
159 | pdata = &priv->pdata; | ||
160 | |||
161 | res = request_mem_region(res->start, res_size(res), pdev->name); | ||
162 | if (res == NULL) { | ||
163 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
164 | error = -EBUSY; | ||
165 | goto err1; | ||
166 | } | ||
167 | |||
168 | priv->iomem_base = ioremap_nocache(res->start, res_size(res)); | ||
169 | if (priv->iomem_base == NULL) { | ||
170 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
171 | error = -ENXIO; | ||
172 | goto err2; | ||
173 | } | ||
174 | |||
175 | priv->input = input_allocate_device(); | ||
176 | if (!priv->input) { | ||
177 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
178 | error = -ENOMEM; | ||
179 | goto err3; | ||
180 | } | ||
181 | |||
182 | input = priv->input; | ||
183 | input->evbit[0] = BIT_MASK(EV_KEY); | ||
184 | |||
185 | input->name = pdev->name; | ||
186 | input->phys = "sh-keysc-keys/input0"; | ||
187 | input->dev.parent = &pdev->dev; | ||
188 | |||
189 | input->id.bustype = BUS_HOST; | ||
190 | input->id.vendor = 0x0001; | ||
191 | input->id.product = 0x0001; | ||
192 | input->id.version = 0x0100; | ||
193 | |||
194 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); | ||
195 | if (error) { | ||
196 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
197 | goto err4; | ||
198 | } | ||
199 | |||
200 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { | ||
201 | k = pdata->keycodes[i]; | ||
202 | if (k) | ||
203 | input_set_capability(input, EV_KEY, k); | ||
204 | } | ||
205 | |||
206 | error = input_register_device(input); | ||
207 | if (error) { | ||
208 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
209 | goto err5; | ||
210 | } | ||
211 | |||
212 | iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | | ||
213 | pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); | ||
214 | iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); | ||
215 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); | ||
216 | return 0; | ||
217 | err5: | ||
218 | free_irq(irq, pdev); | ||
219 | err4: | ||
220 | input_free_device(input); | ||
221 | err3: | ||
222 | iounmap(priv->iomem_base); | ||
223 | err2: | ||
224 | release_mem_region(res->start, res_size(res)); | ||
225 | err1: | ||
226 | platform_set_drvdata(pdev, NULL); | ||
227 | kfree(priv); | ||
228 | err0: | ||
229 | return error; | ||
230 | } | ||
231 | |||
232 | static int __devexit sh_keysc_remove(struct platform_device *pdev) | ||
233 | { | ||
234 | struct sh_keysc_priv *priv = platform_get_drvdata(pdev); | ||
235 | struct resource *res; | ||
236 | |||
237 | iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); | ||
238 | |||
239 | input_unregister_device(priv->input); | ||
240 | free_irq(platform_get_irq(pdev, 0), pdev); | ||
241 | iounmap(priv->iomem_base); | ||
242 | |||
243 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
244 | release_mem_region(res->start, res_size(res)); | ||
245 | |||
246 | platform_set_drvdata(pdev, NULL); | ||
247 | kfree(priv); | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | |||
252 | #define sh_keysc_suspend NULL | ||
253 | #define sh_keysc_resume NULL | ||
254 | |||
255 | struct platform_driver sh_keysc_device_driver = { | ||
256 | .probe = sh_keysc_probe, | ||
257 | .remove = __devexit_p(sh_keysc_remove), | ||
258 | .suspend = sh_keysc_suspend, | ||
259 | .resume = sh_keysc_resume, | ||
260 | .driver = { | ||
261 | .name = "sh_keysc", | ||
262 | } | ||
263 | }; | ||
264 | |||
265 | static int __init sh_keysc_init(void) | ||
266 | { | ||
267 | return platform_driver_register(&sh_keysc_device_driver); | ||
268 | } | ||
269 | |||
270 | static void __exit sh_keysc_exit(void) | ||
271 | { | ||
272 | platform_driver_unregister(&sh_keysc_device_driver); | ||
273 | } | ||
274 | |||
275 | module_init(sh_keysc_init); | ||
276 | module_exit(sh_keysc_exit); | ||
277 | |||
278 | MODULE_AUTHOR("Magnus Damm"); | ||
279 | MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver"); | ||
280 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 9e9caa5d7f5f..c594b34c6767 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * SuperH On-Chip RTC Support | 2 | * SuperH On-Chip RTC Support |
3 | * | 3 | * |
4 | * Copyright (C) 2006, 2007 Paul Mundt | 4 | * Copyright (C) 2006, 2007, 2008 Paul Mundt |
5 | * Copyright (C) 2006 Jamie Lenehan | 5 | * Copyright (C) 2006 Jamie Lenehan |
6 | * Copyright (C) 2008 Angelo Castello | ||
6 | * | 7 | * |
7 | * Based on the old arch/sh/kernel/cpu/rtc.c by: | 8 | * Based on the old arch/sh/kernel/cpu/rtc.c by: |
8 | * | 9 | * |
@@ -26,7 +27,7 @@ | |||
26 | #include <asm/rtc.h> | 27 | #include <asm/rtc.h> |
27 | 28 | ||
28 | #define DRV_NAME "sh-rtc" | 29 | #define DRV_NAME "sh-rtc" |
29 | #define DRV_VERSION "0.1.6" | 30 | #define DRV_VERSION "0.2.0" |
30 | 31 | ||
31 | #define RTC_REG(r) ((r) * rtc_reg_size) | 32 | #define RTC_REG(r) ((r) * rtc_reg_size) |
32 | 33 | ||
@@ -63,6 +64,13 @@ | |||
63 | /* ALARM Bits - or with BCD encoded value */ | 64 | /* ALARM Bits - or with BCD encoded value */ |
64 | #define AR_ENB 0x80 /* Enable for alarm cmp */ | 65 | #define AR_ENB 0x80 /* Enable for alarm cmp */ |
65 | 66 | ||
67 | /* Period Bits */ | ||
68 | #define PF_HP 0x100 /* Enable Half Period to support 8,32,128Hz */ | ||
69 | #define PF_COUNT 0x200 /* Half periodic counter */ | ||
70 | #define PF_OXS 0x400 /* Periodic One x Second */ | ||
71 | #define PF_KOU 0x800 /* Kernel or User periodic request 1=kernel */ | ||
72 | #define PF_MASK 0xf00 | ||
73 | |||
66 | /* RCR1 Bits */ | 74 | /* RCR1 Bits */ |
67 | #define RCR1_CF 0x80 /* Carry Flag */ | 75 | #define RCR1_CF 0x80 /* Carry Flag */ |
68 | #define RCR1_CIE 0x10 /* Carry Interrupt Enable */ | 76 | #define RCR1_CIE 0x10 /* Carry Interrupt Enable */ |
@@ -84,33 +92,24 @@ struct sh_rtc { | |||
84 | unsigned int alarm_irq, periodic_irq, carry_irq; | 92 | unsigned int alarm_irq, periodic_irq, carry_irq; |
85 | struct rtc_device *rtc_dev; | 93 | struct rtc_device *rtc_dev; |
86 | spinlock_t lock; | 94 | spinlock_t lock; |
87 | int rearm_aie; | ||
88 | unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */ | 95 | unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */ |
96 | unsigned short periodic_freq; | ||
89 | }; | 97 | }; |
90 | 98 | ||
91 | static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) | 99 | static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) |
92 | { | 100 | { |
93 | struct platform_device *pdev = to_platform_device(dev_id); | 101 | struct sh_rtc *rtc = dev_id; |
94 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | 102 | unsigned int tmp; |
95 | unsigned int tmp, events = 0; | ||
96 | 103 | ||
97 | spin_lock(&rtc->lock); | 104 | spin_lock(&rtc->lock); |
98 | 105 | ||
99 | tmp = readb(rtc->regbase + RCR1); | 106 | tmp = readb(rtc->regbase + RCR1); |
100 | tmp &= ~RCR1_CF; | 107 | tmp &= ~RCR1_CF; |
101 | |||
102 | if (rtc->rearm_aie) { | ||
103 | if (tmp & RCR1_AF) | ||
104 | tmp &= ~RCR1_AF; /* try to clear AF again */ | ||
105 | else { | ||
106 | tmp |= RCR1_AIE; /* AF has cleared, rearm IRQ */ | ||
107 | rtc->rearm_aie = 0; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | writeb(tmp, rtc->regbase + RCR1); | 108 | writeb(tmp, rtc->regbase + RCR1); |
112 | 109 | ||
113 | rtc_update_irq(rtc->rtc_dev, 1, events); | 110 | /* Users have requested One x Second IRQ */ |
111 | if (rtc->periodic_freq & PF_OXS) | ||
112 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); | ||
114 | 113 | ||
115 | spin_unlock(&rtc->lock); | 114 | spin_unlock(&rtc->lock); |
116 | 115 | ||
@@ -119,47 +118,48 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) | |||
119 | 118 | ||
120 | static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) | 119 | static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) |
121 | { | 120 | { |
122 | struct platform_device *pdev = to_platform_device(dev_id); | 121 | struct sh_rtc *rtc = dev_id; |
123 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | 122 | unsigned int tmp; |
124 | unsigned int tmp, events = 0; | ||
125 | 123 | ||
126 | spin_lock(&rtc->lock); | 124 | spin_lock(&rtc->lock); |
127 | 125 | ||
128 | tmp = readb(rtc->regbase + RCR1); | 126 | tmp = readb(rtc->regbase + RCR1); |
129 | 127 | tmp &= ~(RCR1_AF | RCR1_AIE); | |
130 | /* | ||
131 | * If AF is set then the alarm has triggered. If we clear AF while | ||
132 | * the alarm time still matches the RTC time then AF will | ||
133 | * immediately be set again, and if AIE is enabled then the alarm | ||
134 | * interrupt will immediately be retrigger. So we clear AIE here | ||
135 | * and use rtc->rearm_aie so that the carry interrupt will keep | ||
136 | * trying to clear AF and once it stays cleared it'll re-enable | ||
137 | * AIE. | ||
138 | */ | ||
139 | if (tmp & RCR1_AF) { | ||
140 | events |= RTC_AF | RTC_IRQF; | ||
141 | |||
142 | tmp &= ~(RCR1_AF|RCR1_AIE); | ||
143 | |||
144 | writeb(tmp, rtc->regbase + RCR1); | 128 | writeb(tmp, rtc->regbase + RCR1); |
145 | 129 | ||
146 | rtc->rearm_aie = 1; | 130 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); |
147 | |||
148 | rtc_update_irq(rtc->rtc_dev, 1, events); | ||
149 | } | ||
150 | 131 | ||
151 | spin_unlock(&rtc->lock); | 132 | spin_unlock(&rtc->lock); |
133 | |||
152 | return IRQ_HANDLED; | 134 | return IRQ_HANDLED; |
153 | } | 135 | } |
154 | 136 | ||
155 | static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) | 137 | static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) |
156 | { | 138 | { |
157 | struct platform_device *pdev = to_platform_device(dev_id); | 139 | struct sh_rtc *rtc = dev_id; |
158 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | 140 | struct rtc_device *rtc_dev = rtc->rtc_dev; |
141 | unsigned int tmp; | ||
159 | 142 | ||
160 | spin_lock(&rtc->lock); | 143 | spin_lock(&rtc->lock); |
161 | 144 | ||
162 | rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); | 145 | tmp = readb(rtc->regbase + RCR2); |
146 | tmp &= ~RCR2_PEF; | ||
147 | writeb(tmp, rtc->regbase + RCR2); | ||
148 | |||
149 | /* Half period enabled than one skipped and the next notified */ | ||
150 | if ((rtc->periodic_freq & PF_HP) && (rtc->periodic_freq & PF_COUNT)) | ||
151 | rtc->periodic_freq &= ~PF_COUNT; | ||
152 | else { | ||
153 | if (rtc->periodic_freq & PF_HP) | ||
154 | rtc->periodic_freq |= PF_COUNT; | ||
155 | if (rtc->periodic_freq & PF_KOU) { | ||
156 | spin_lock(&rtc_dev->irq_task_lock); | ||
157 | if (rtc_dev->irq_task) | ||
158 | rtc_dev->irq_task->func(rtc_dev->irq_task->private_data); | ||
159 | spin_unlock(&rtc_dev->irq_task_lock); | ||
160 | } else | ||
161 | rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); | ||
162 | } | ||
163 | 163 | ||
164 | spin_unlock(&rtc->lock); | 164 | spin_unlock(&rtc->lock); |
165 | 165 | ||
@@ -176,8 +176,8 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable) | |||
176 | tmp = readb(rtc->regbase + RCR2); | 176 | tmp = readb(rtc->regbase + RCR2); |
177 | 177 | ||
178 | if (enable) { | 178 | if (enable) { |
179 | tmp &= ~RCR2_PESMASK; | 179 | tmp &= ~RCR2_PEF; /* Clear PES bit */ |
180 | tmp |= RCR2_PEF | (2 << 4); | 180 | tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */ |
181 | } else | 181 | } else |
182 | tmp &= ~(RCR2_PESMASK | RCR2_PEF); | 182 | tmp &= ~(RCR2_PESMASK | RCR2_PEF); |
183 | 183 | ||
@@ -186,82 +186,81 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable) | |||
186 | spin_unlock_irq(&rtc->lock); | 186 | spin_unlock_irq(&rtc->lock); |
187 | } | 187 | } |
188 | 188 | ||
189 | static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) | 189 | static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq) |
190 | { | 190 | { |
191 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 191 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
192 | unsigned int tmp; | 192 | int tmp, ret = 0; |
193 | 193 | ||
194 | spin_lock_irq(&rtc->lock); | 194 | spin_lock_irq(&rtc->lock); |
195 | tmp = rtc->periodic_freq & PF_MASK; | ||
195 | 196 | ||
196 | tmp = readb(rtc->regbase + RCR1); | 197 | switch (freq) { |
197 | 198 | case 0: | |
198 | if (!enable) { | 199 | rtc->periodic_freq = 0x00; |
199 | tmp &= ~RCR1_AIE; | 200 | break; |
200 | rtc->rearm_aie = 0; | 201 | case 1: |
201 | } else if (rtc->rearm_aie == 0) | 202 | rtc->periodic_freq = 0x60; |
202 | tmp |= RCR1_AIE; | 203 | break; |
204 | case 2: | ||
205 | rtc->periodic_freq = 0x50; | ||
206 | break; | ||
207 | case 4: | ||
208 | rtc->periodic_freq = 0x40; | ||
209 | break; | ||
210 | case 8: | ||
211 | rtc->periodic_freq = 0x30 | PF_HP; | ||
212 | break; | ||
213 | case 16: | ||
214 | rtc->periodic_freq = 0x30; | ||
215 | break; | ||
216 | case 32: | ||
217 | rtc->periodic_freq = 0x20 | PF_HP; | ||
218 | break; | ||
219 | case 64: | ||
220 | rtc->periodic_freq = 0x20; | ||
221 | break; | ||
222 | case 128: | ||
223 | rtc->periodic_freq = 0x10 | PF_HP; | ||
224 | break; | ||
225 | case 256: | ||
226 | rtc->periodic_freq = 0x10; | ||
227 | break; | ||
228 | default: | ||
229 | ret = -ENOTSUPP; | ||
230 | } | ||
203 | 231 | ||
204 | writeb(tmp, rtc->regbase + RCR1); | 232 | if (ret == 0) { |
233 | rtc->periodic_freq |= tmp; | ||
234 | rtc->rtc_dev->irq_freq = freq; | ||
235 | } | ||
205 | 236 | ||
206 | spin_unlock_irq(&rtc->lock); | 237 | spin_unlock_irq(&rtc->lock); |
238 | return ret; | ||
207 | } | 239 | } |
208 | 240 | ||
209 | static int sh_rtc_open(struct device *dev) | 241 | static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) |
210 | { | 242 | { |
211 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 243 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
212 | unsigned int tmp; | 244 | unsigned int tmp; |
213 | int ret; | ||
214 | |||
215 | tmp = readb(rtc->regbase + RCR1); | ||
216 | tmp &= ~RCR1_CF; | ||
217 | tmp |= RCR1_CIE; | ||
218 | writeb(tmp, rtc->regbase + RCR1); | ||
219 | 245 | ||
220 | ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED, | 246 | spin_lock_irq(&rtc->lock); |
221 | "sh-rtc period", dev); | ||
222 | if (unlikely(ret)) { | ||
223 | dev_err(dev, "request period IRQ failed with %d, IRQ %d\n", | ||
224 | ret, rtc->periodic_irq); | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED, | ||
229 | "sh-rtc carry", dev); | ||
230 | if (unlikely(ret)) { | ||
231 | dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n", | ||
232 | ret, rtc->carry_irq); | ||
233 | free_irq(rtc->periodic_irq, dev); | ||
234 | goto err_bad_carry; | ||
235 | } | ||
236 | 247 | ||
237 | ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED, | 248 | tmp = readb(rtc->regbase + RCR1); |
238 | "sh-rtc alarm", dev); | ||
239 | if (unlikely(ret)) { | ||
240 | dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n", | ||
241 | ret, rtc->alarm_irq); | ||
242 | goto err_bad_alarm; | ||
243 | } | ||
244 | 249 | ||
245 | return 0; | 250 | if (!enable) |
251 | tmp &= ~RCR1_AIE; | ||
252 | else | ||
253 | tmp |= RCR1_AIE; | ||
246 | 254 | ||
247 | err_bad_alarm: | 255 | writeb(tmp, rtc->regbase + RCR1); |
248 | free_irq(rtc->carry_irq, dev); | ||
249 | err_bad_carry: | ||
250 | free_irq(rtc->periodic_irq, dev); | ||
251 | 256 | ||
252 | return ret; | 257 | spin_unlock_irq(&rtc->lock); |
253 | } | 258 | } |
254 | 259 | ||
255 | static void sh_rtc_release(struct device *dev) | 260 | static void sh_rtc_release(struct device *dev) |
256 | { | 261 | { |
257 | struct sh_rtc *rtc = dev_get_drvdata(dev); | ||
258 | |||
259 | sh_rtc_setpie(dev, 0); | 262 | sh_rtc_setpie(dev, 0); |
260 | sh_rtc_setaie(dev, 0); | 263 | sh_rtc_setaie(dev, 0); |
261 | |||
262 | free_irq(rtc->periodic_irq, dev); | ||
263 | free_irq(rtc->carry_irq, dev); | ||
264 | free_irq(rtc->alarm_irq, dev); | ||
265 | } | 264 | } |
266 | 265 | ||
267 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) | 266 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) |
@@ -270,31 +269,44 @@ static int sh_rtc_proc(struct device *dev, struct seq_file *seq) | |||
270 | unsigned int tmp; | 269 | unsigned int tmp; |
271 | 270 | ||
272 | tmp = readb(rtc->regbase + RCR1); | 271 | tmp = readb(rtc->regbase + RCR1); |
273 | seq_printf(seq, "carry_IRQ\t: %s\n", | 272 | seq_printf(seq, "carry_IRQ\t: %s\n", (tmp & RCR1_CIE) ? "yes" : "no"); |
274 | (tmp & RCR1_CIE) ? "yes" : "no"); | ||
275 | 273 | ||
276 | tmp = readb(rtc->regbase + RCR2); | 274 | tmp = readb(rtc->regbase + RCR2); |
277 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 275 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
278 | (tmp & RCR2_PEF) ? "yes" : "no"); | 276 | (tmp & RCR2_PESMASK) ? "yes" : "no"); |
279 | 277 | ||
280 | return 0; | 278 | return 0; |
281 | } | 279 | } |
282 | 280 | ||
283 | static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 281 | static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
284 | { | 282 | { |
285 | unsigned int ret = -ENOIOCTLCMD; | 283 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
284 | unsigned int ret = 0; | ||
286 | 285 | ||
287 | switch (cmd) { | 286 | switch (cmd) { |
288 | case RTC_PIE_OFF: | 287 | case RTC_PIE_OFF: |
289 | case RTC_PIE_ON: | 288 | case RTC_PIE_ON: |
290 | sh_rtc_setpie(dev, cmd == RTC_PIE_ON); | 289 | sh_rtc_setpie(dev, cmd == RTC_PIE_ON); |
291 | ret = 0; | ||
292 | break; | 290 | break; |
293 | case RTC_AIE_OFF: | 291 | case RTC_AIE_OFF: |
294 | case RTC_AIE_ON: | 292 | case RTC_AIE_ON: |
295 | sh_rtc_setaie(dev, cmd == RTC_AIE_ON); | 293 | sh_rtc_setaie(dev, cmd == RTC_AIE_ON); |
296 | ret = 0; | ||
297 | break; | 294 | break; |
295 | case RTC_UIE_OFF: | ||
296 | rtc->periodic_freq &= ~PF_OXS; | ||
297 | break; | ||
298 | case RTC_UIE_ON: | ||
299 | rtc->periodic_freq |= PF_OXS; | ||
300 | break; | ||
301 | case RTC_IRQP_READ: | ||
302 | ret = put_user(rtc->rtc_dev->irq_freq, | ||
303 | (unsigned long __user *)arg); | ||
304 | break; | ||
305 | case RTC_IRQP_SET: | ||
306 | ret = sh_rtc_setfreq(dev, arg); | ||
307 | break; | ||
308 | default: | ||
309 | ret = -ENOIOCTLCMD; | ||
298 | } | 310 | } |
299 | 311 | ||
300 | return ret; | 312 | return ret; |
@@ -421,7 +433,7 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
421 | { | 433 | { |
422 | struct platform_device *pdev = to_platform_device(dev); | 434 | struct platform_device *pdev = to_platform_device(dev); |
423 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | 435 | struct sh_rtc *rtc = platform_get_drvdata(pdev); |
424 | struct rtc_time* tm = &wkalrm->time; | 436 | struct rtc_time *tm = &wkalrm->time; |
425 | 437 | ||
426 | spin_lock_irq(&rtc->lock); | 438 | spin_lock_irq(&rtc->lock); |
427 | 439 | ||
@@ -452,7 +464,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc, | |||
452 | writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off); | 464 | writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off); |
453 | } | 465 | } |
454 | 466 | ||
455 | static int sh_rtc_check_alarm(struct rtc_time* tm) | 467 | static int sh_rtc_check_alarm(struct rtc_time *tm) |
456 | { | 468 | { |
457 | /* | 469 | /* |
458 | * The original rtc says anything > 0xc0 is "don't care" or "match | 470 | * The original rtc says anything > 0xc0 is "don't care" or "match |
@@ -503,11 +515,9 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
503 | 515 | ||
504 | /* disable alarm interrupt and clear the alarm flag */ | 516 | /* disable alarm interrupt and clear the alarm flag */ |
505 | rcr1 = readb(rtc->regbase + RCR1); | 517 | rcr1 = readb(rtc->regbase + RCR1); |
506 | rcr1 &= ~(RCR1_AF|RCR1_AIE); | 518 | rcr1 &= ~(RCR1_AF | RCR1_AIE); |
507 | writeb(rcr1, rtc->regbase + RCR1); | 519 | writeb(rcr1, rtc->regbase + RCR1); |
508 | 520 | ||
509 | rtc->rearm_aie = 0; | ||
510 | |||
511 | /* set alarm time */ | 521 | /* set alarm time */ |
512 | sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR); | 522 | sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR); |
513 | sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR); | 523 | sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR); |
@@ -529,14 +539,34 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
529 | return 0; | 539 | return 0; |
530 | } | 540 | } |
531 | 541 | ||
542 | static int sh_rtc_irq_set_state(struct device *dev, int enabled) | ||
543 | { | ||
544 | struct platform_device *pdev = to_platform_device(dev); | ||
545 | struct sh_rtc *rtc = platform_get_drvdata(pdev); | ||
546 | |||
547 | if (enabled) { | ||
548 | rtc->periodic_freq |= PF_KOU; | ||
549 | return sh_rtc_ioctl(dev, RTC_PIE_ON, 0); | ||
550 | } else { | ||
551 | rtc->periodic_freq &= ~PF_KOU; | ||
552 | return sh_rtc_ioctl(dev, RTC_PIE_OFF, 0); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | static int sh_rtc_irq_set_freq(struct device *dev, int freq) | ||
557 | { | ||
558 | return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq); | ||
559 | } | ||
560 | |||
532 | static struct rtc_class_ops sh_rtc_ops = { | 561 | static struct rtc_class_ops sh_rtc_ops = { |
533 | .open = sh_rtc_open, | ||
534 | .release = sh_rtc_release, | 562 | .release = sh_rtc_release, |
535 | .ioctl = sh_rtc_ioctl, | 563 | .ioctl = sh_rtc_ioctl, |
536 | .read_time = sh_rtc_read_time, | 564 | .read_time = sh_rtc_read_time, |
537 | .set_time = sh_rtc_set_time, | 565 | .set_time = sh_rtc_set_time, |
538 | .read_alarm = sh_rtc_read_alarm, | 566 | .read_alarm = sh_rtc_read_alarm, |
539 | .set_alarm = sh_rtc_set_alarm, | 567 | .set_alarm = sh_rtc_set_alarm, |
568 | .irq_set_state = sh_rtc_irq_set_state, | ||
569 | .irq_set_freq = sh_rtc_irq_set_freq, | ||
540 | .proc = sh_rtc_proc, | 570 | .proc = sh_rtc_proc, |
541 | }; | 571 | }; |
542 | 572 | ||
@@ -544,6 +574,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
544 | { | 574 | { |
545 | struct sh_rtc *rtc; | 575 | struct sh_rtc *rtc; |
546 | struct resource *res; | 576 | struct resource *res; |
577 | unsigned int tmp; | ||
547 | int ret = -ENOENT; | 578 | int ret = -ENOENT; |
548 | 579 | ||
549 | rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); | 580 | rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); |
@@ -552,6 +583,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
552 | 583 | ||
553 | spin_lock_init(&rtc->lock); | 584 | spin_lock_init(&rtc->lock); |
554 | 585 | ||
586 | /* get periodic/carry/alarm irqs */ | ||
555 | rtc->periodic_irq = platform_get_irq(pdev, 0); | 587 | rtc->periodic_irq = platform_get_irq(pdev, 0); |
556 | if (unlikely(rtc->periodic_irq < 0)) { | 588 | if (unlikely(rtc->periodic_irq < 0)) { |
557 | dev_err(&pdev->dev, "No IRQ for period\n"); | 589 | dev_err(&pdev->dev, "No IRQ for period\n"); |
@@ -608,8 +640,48 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) | |||
608 | rtc->capabilities |= pinfo->capabilities; | 640 | rtc->capabilities |= pinfo->capabilities; |
609 | } | 641 | } |
610 | 642 | ||
643 | rtc->rtc_dev->max_user_freq = 256; | ||
644 | rtc->rtc_dev->irq_freq = 1; | ||
645 | rtc->periodic_freq = 0x60; | ||
646 | |||
611 | platform_set_drvdata(pdev, rtc); | 647 | platform_set_drvdata(pdev, rtc); |
612 | 648 | ||
649 | /* register periodic/carry/alarm irqs */ | ||
650 | ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED, | ||
651 | "sh-rtc period", rtc); | ||
652 | if (unlikely(ret)) { | ||
653 | dev_err(&pdev->dev, | ||
654 | "request period IRQ failed with %d, IRQ %d\n", ret, | ||
655 | rtc->periodic_irq); | ||
656 | goto err_badmap; | ||
657 | } | ||
658 | |||
659 | ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED, | ||
660 | "sh-rtc carry", rtc); | ||
661 | if (unlikely(ret)) { | ||
662 | dev_err(&pdev->dev, | ||
663 | "request carry IRQ failed with %d, IRQ %d\n", ret, | ||
664 | rtc->carry_irq); | ||
665 | free_irq(rtc->periodic_irq, rtc); | ||
666 | goto err_badmap; | ||
667 | } | ||
668 | |||
669 | ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED, | ||
670 | "sh-rtc alarm", rtc); | ||
671 | if (unlikely(ret)) { | ||
672 | dev_err(&pdev->dev, | ||
673 | "request alarm IRQ failed with %d, IRQ %d\n", ret, | ||
674 | rtc->alarm_irq); | ||
675 | free_irq(rtc->carry_irq, rtc); | ||
676 | free_irq(rtc->periodic_irq, rtc); | ||
677 | goto err_badmap; | ||
678 | } | ||
679 | |||
680 | tmp = readb(rtc->regbase + RCR1); | ||
681 | tmp &= ~RCR1_CF; | ||
682 | tmp |= RCR1_CIE; | ||
683 | writeb(tmp, rtc->regbase + RCR1); | ||
684 | |||
613 | return 0; | 685 | return 0; |
614 | 686 | ||
615 | err_badmap: | 687 | err_badmap: |
@@ -630,6 +702,10 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) | |||
630 | sh_rtc_setpie(&pdev->dev, 0); | 702 | sh_rtc_setpie(&pdev->dev, 0); |
631 | sh_rtc_setaie(&pdev->dev, 0); | 703 | sh_rtc_setaie(&pdev->dev, 0); |
632 | 704 | ||
705 | free_irq(rtc->carry_irq, rtc); | ||
706 | free_irq(rtc->periodic_irq, rtc); | ||
707 | free_irq(rtc->alarm_irq, rtc); | ||
708 | |||
633 | release_resource(rtc->res); | 709 | release_resource(rtc->res); |
634 | 710 | ||
635 | platform_set_drvdata(pdev, NULL); | 711 | platform_set_drvdata(pdev, NULL); |
@@ -662,6 +738,8 @@ module_exit(sh_rtc_exit); | |||
662 | 738 | ||
663 | MODULE_DESCRIPTION("SuperH on-chip RTC driver"); | 739 | MODULE_DESCRIPTION("SuperH on-chip RTC driver"); |
664 | MODULE_VERSION(DRV_VERSION); | 740 | MODULE_VERSION(DRV_VERSION); |
665 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, Jamie Lenehan <lenehan@twibble.org>"); | 741 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, " |
742 | "Jamie Lenehan <lenehan@twibble.org>, " | ||
743 | "Angelo Castello <angelo.castello@st.com>"); | ||
666 | MODULE_LICENSE("GPL"); | 744 | MODULE_LICENSE("GPL"); |
667 | MODULE_ALIAS("platform:" DRV_NAME); | 745 | MODULE_ALIAS("platform:" DRV_NAME); |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index eff593080d4f..c2ea5d4df44a 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -333,7 +333,6 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | |||
333 | } | 333 | } |
334 | sci_out(port, SCFCR, fcr_val); | 334 | sci_out(port, SCFCR, fcr_val); |
335 | } | 335 | } |
336 | |||
337 | #elif defined(CONFIG_CPU_SH3) | 336 | #elif defined(CONFIG_CPU_SH3) |
338 | /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */ | 337 | /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */ |
339 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | 338 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) |
@@ -384,6 +383,12 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | |||
384 | 383 | ||
385 | sci_out(port, SCFCR, fcr_val); | 384 | sci_out(port, SCFCR, fcr_val); |
386 | } | 385 | } |
386 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | ||
387 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | ||
388 | { | ||
389 | /* Nothing to do here.. */ | ||
390 | sci_out(port, SCFCR, 0); | ||
391 | } | ||
387 | #else | 392 | #else |
388 | /* For SH7750 */ | 393 | /* For SH7750 */ |
389 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | 394 | static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 01a9dd715f5d..fa8700a968fc 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -1,20 +1,5 @@ | |||
1 | /* $Id: sh-sci.h,v 1.4 2004/02/19 16:43:56 lethal Exp $ | ||
2 | * | ||
3 | * linux/drivers/serial/sh-sci.h | ||
4 | * | ||
5 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) | ||
6 | * Copyright (C) 1999, 2000 Niibe Yutaka | ||
7 | * Copyright (C) 2000 Greg Banks | ||
8 | * Copyright (C) 2002, 2003 Paul Mundt | ||
9 | * Modified to support multiple serial ports. Stuart Menefy (May 2000). | ||
10 | * Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003). | ||
11 | * Modified to support H8/300 Series Yoshinori Sato (Feb 2004). | ||
12 | * Removed SH7300 support (Jul 2007). | ||
13 | * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Aug 2007). | ||
14 | */ | ||
15 | #include <linux/serial_core.h> | 1 | #include <linux/serial_core.h> |
16 | #include <asm/io.h> | 2 | #include <asm/io.h> |
17 | |||
18 | #include <asm/gpio.h> | 3 | #include <asm/gpio.h> |
19 | 4 | ||
20 | #if defined(CONFIG_H83007) || defined(CONFIG_H83068) | 5 | #if defined(CONFIG_H83007) || defined(CONFIG_H83068) |
@@ -102,6 +87,15 @@ | |||
102 | # define SCSPTR0 SCPDR0 | 87 | # define SCSPTR0 SCPDR0 |
103 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 88 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
104 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 89 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ |
90 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | ||
91 | # define SCSPTR0 0xa4050160 | ||
92 | # define SCSPTR1 0xa405013e | ||
93 | # define SCSPTR2 0xa4050160 | ||
94 | # define SCSPTR3 0xa405013e | ||
95 | # define SCSPTR4 0xa4050128 | ||
96 | # define SCSPTR5 0xa4050128 | ||
97 | # define SCIF_ORER 0x0001 /* overrun error bit */ | ||
98 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
105 | # define SCIF_ONLY | 99 | # define SCIF_ONLY |
106 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) | 100 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) |
107 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ | 101 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ |
@@ -395,6 +389,11 @@ | |||
395 | h8_sci_offset, h8_sci_size) \ | 389 | h8_sci_offset, h8_sci_size) \ |
396 | CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) | 390 | CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) |
397 | #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) | 391 | #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) |
392 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | ||
393 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \ | ||
394 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) | ||
395 | #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ | ||
396 | CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) | ||
398 | #else | 397 | #else |
399 | #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ | 398 | #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ |
400 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ | 399 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ |
@@ -419,6 +418,18 @@ SCIF_FNS(SCFDR, 0x1c, 16) | |||
419 | SCIF_FNS(SCxTDR, 0x20, 8) | 418 | SCIF_FNS(SCxTDR, 0x20, 8) |
420 | SCIF_FNS(SCxRDR, 0x24, 8) | 419 | SCIF_FNS(SCxRDR, 0x24, 8) |
421 | SCIF_FNS(SCLSR, 0x24, 16) | 420 | SCIF_FNS(SCLSR, 0x24, 16) |
421 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | ||
422 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) | ||
423 | SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8) | ||
424 | SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16) | ||
425 | SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8) | ||
426 | SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16) | ||
427 | SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8) | ||
428 | SCIF_FNS(SCTDSR, 0x0c, 8) | ||
429 | SCIF_FNS(SCFER, 0x10, 16) | ||
430 | SCIF_FNS(SCFCR, 0x18, 16) | ||
431 | SCIF_FNS(SCFDR, 0x1c, 16) | ||
432 | SCIF_FNS(SCLSR, 0x24, 16) | ||
422 | #else | 433 | #else |
423 | /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/ | 434 | /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/ |
424 | /* name off sz off sz off sz off sz off sz*/ | 435 | /* name off sz off sz off sz off sz off sz*/ |
@@ -589,6 +600,23 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
589 | return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ | 600 | return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ |
590 | return 1; | 601 | return 1; |
591 | } | 602 | } |
603 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | ||
604 | static inline int sci_rxd_in(struct uart_port *port) | ||
605 | { | ||
606 | if (port->mapbase == 0xffe00000) | ||
607 | return ctrl_inb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */ | ||
608 | if (port->mapbase == 0xffe10000) | ||
609 | return ctrl_inb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */ | ||
610 | if (port->mapbase == 0xffe20000) | ||
611 | return ctrl_inb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */ | ||
612 | if (port->mapbase == 0xa4e30000) | ||
613 | return ctrl_inb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */ | ||
614 | if (port->mapbase == 0xa4e40000) | ||
615 | return ctrl_inb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */ | ||
616 | if (port->mapbase == 0xa4e50000) | ||
617 | return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ | ||
618 | return 1; | ||
619 | } | ||
592 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) | 620 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) |
593 | static inline int sci_rxd_in(struct uart_port *port) | 621 | static inline int sci_rxd_in(struct uart_port *port) |
594 | { | 622 | { |
@@ -727,6 +755,8 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
727 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 755 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
728 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 756 | defined(CONFIG_CPU_SUBTYPE_SH7721) |
729 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) | 757 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) |
758 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | ||
759 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(16*bps)-1) | ||
730 | #elif defined(__H8300H__) || defined(__H8300S__) | 760 | #elif defined(__H8300H__) || defined(__H8300S__) |
731 | #define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1) | 761 | #define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1) |
732 | #elif defined(CONFIG_SUPERH64) | 762 | #elif defined(CONFIG_SUPERH64) |