diff options
author | Adrian Bunk <bunk@stusta.de> | 2005-11-07 06:26:59 -0500 |
---|---|---|
committer | Adrian Bunk <bunk@r063144.stusta.swh.mhn.de> | 2005-11-07 06:26:59 -0500 |
commit | b7c4a9f83f3c0f6f2a2750a389a9b758c3d9e9d2 (patch) | |
tree | 66bf5c66ed505a739bf8633d1931f0d0526bd6d6 /drivers | |
parent | 65163fd73c65e4c61437c28ac4ef9f3c5ba16a80 (diff) | |
parent | 0b154bb7d0cce80e9c0bcf11d4f9e71b59409d26 (diff) |
Merge with http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/platform.c | 153 | ||||
-rw-r--r-- | drivers/net/depca.c | 24 | ||||
-rw-r--r-- | drivers/net/jazzsonic.c | 28 | ||||
-rw-r--r-- | drivers/net/macsonic.c | 27 | ||||
-rw-r--r-- | drivers/serial/8250.c | 73 | ||||
-rw-r--r-- | drivers/serial/8250.h | 1 | ||||
-rw-r--r-- | drivers/serial/8250_au1x00.c | 102 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 8 | ||||
-rw-r--r-- | drivers/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/serial/serial_core.c | 1 | ||||
-rw-r--r-- | drivers/video/arcfb.c | 25 | ||||
-rw-r--r-- | drivers/video/gbefb.c | 18 | ||||
-rw-r--r-- | drivers/video/sgivwfb.c | 24 |
13 files changed, 359 insertions, 126 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d597c922af11..6d4736e89f1a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -116,12 +116,115 @@ int platform_add_devices(struct platform_device **devs, int num) | |||
116 | return ret; | 116 | return ret; |
117 | } | 117 | } |
118 | 118 | ||
119 | struct platform_object { | ||
120 | struct platform_device pdev; | ||
121 | char name[1]; | ||
122 | }; | ||
123 | |||
119 | /** | 124 | /** |
120 | * platform_device_register - add a platform-level device | 125 | * platform_device_put |
126 | * @pdev: platform device to free | ||
127 | * | ||
128 | * Free all memory associated with a platform device. This function | ||
129 | * must _only_ be externally called in error cases. All other usage | ||
130 | * is a bug. | ||
131 | */ | ||
132 | void platform_device_put(struct platform_device *pdev) | ||
133 | { | ||
134 | if (pdev) | ||
135 | put_device(&pdev->dev); | ||
136 | } | ||
137 | EXPORT_SYMBOL_GPL(platform_device_put); | ||
138 | |||
139 | static void platform_device_release(struct device *dev) | ||
140 | { | ||
141 | struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev); | ||
142 | |||
143 | kfree(pa->pdev.dev.platform_data); | ||
144 | kfree(pa->pdev.resource); | ||
145 | kfree(pa); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * platform_device_alloc | ||
150 | * @name: base name of the device we're adding | ||
151 | * @id: instance id | ||
152 | * | ||
153 | * Create a platform device object which can have other objects attached | ||
154 | * to it, and which will have attached objects freed when it is released. | ||
155 | */ | ||
156 | struct platform_device *platform_device_alloc(const char *name, unsigned int id) | ||
157 | { | ||
158 | struct platform_object *pa; | ||
159 | |||
160 | pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); | ||
161 | if (pa) { | ||
162 | strcpy(pa->name, name); | ||
163 | pa->pdev.name = pa->name; | ||
164 | pa->pdev.id = id; | ||
165 | device_initialize(&pa->pdev.dev); | ||
166 | pa->pdev.dev.release = platform_device_release; | ||
167 | } | ||
168 | |||
169 | return pa ? &pa->pdev : NULL; | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(platform_device_alloc); | ||
172 | |||
173 | /** | ||
174 | * platform_device_add_resources | ||
175 | * @pdev: platform device allocated by platform_device_alloc to add resources to | ||
176 | * @res: set of resources that needs to be allocated for the device | ||
177 | * @num: number of resources | ||
178 | * | ||
179 | * Add a copy of the resources to the platform device. The memory | ||
180 | * associated with the resources will be freed when the platform | ||
181 | * device is released. | ||
182 | */ | ||
183 | int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num) | ||
184 | { | ||
185 | struct resource *r; | ||
186 | |||
187 | r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL); | ||
188 | if (r) { | ||
189 | memcpy(r, res, sizeof(struct resource) * num); | ||
190 | pdev->resource = r; | ||
191 | pdev->num_resources = num; | ||
192 | } | ||
193 | return r ? 0 : -ENOMEM; | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(platform_device_add_resources); | ||
196 | |||
197 | /** | ||
198 | * platform_device_add_data | ||
199 | * @pdev: platform device allocated by platform_device_alloc to add resources to | ||
200 | * @data: platform specific data for this platform device | ||
201 | * @size: size of platform specific data | ||
202 | * | ||
203 | * Add a copy of platform specific data to the platform device's platform_data | ||
204 | * pointer. The memory associated with the platform data will be freed | ||
205 | * when the platform device is released. | ||
206 | */ | ||
207 | int platform_device_add_data(struct platform_device *pdev, void *data, size_t size) | ||
208 | { | ||
209 | void *d; | ||
210 | |||
211 | d = kmalloc(size, GFP_KERNEL); | ||
212 | if (d) { | ||
213 | memcpy(d, data, size); | ||
214 | pdev->dev.platform_data = d; | ||
215 | } | ||
216 | return d ? 0 : -ENOMEM; | ||
217 | } | ||
218 | EXPORT_SYMBOL_GPL(platform_device_add_data); | ||
219 | |||
220 | /** | ||
221 | * platform_device_add - add a platform device to device hierarchy | ||
121 | * @pdev: platform device we're adding | 222 | * @pdev: platform device we're adding |
122 | * | 223 | * |
224 | * This is part 2 of platform_device_register(), though may be called | ||
225 | * separately _iff_ pdev was allocated by platform_device_alloc(). | ||
123 | */ | 226 | */ |
124 | int platform_device_register(struct platform_device * pdev) | 227 | int platform_device_add(struct platform_device *pdev) |
125 | { | 228 | { |
126 | int i, ret = 0; | 229 | int i, ret = 0; |
127 | 230 | ||
@@ -174,6 +277,18 @@ int platform_device_register(struct platform_device * pdev) | |||
174 | release_resource(&pdev->resource[i]); | 277 | release_resource(&pdev->resource[i]); |
175 | return ret; | 278 | return ret; |
176 | } | 279 | } |
280 | EXPORT_SYMBOL_GPL(platform_device_add); | ||
281 | |||
282 | /** | ||
283 | * platform_device_register - add a platform-level device | ||
284 | * @pdev: platform device we're adding | ||
285 | * | ||
286 | */ | ||
287 | int platform_device_register(struct platform_device * pdev) | ||
288 | { | ||
289 | device_initialize(&pdev->dev); | ||
290 | return platform_device_add(pdev); | ||
291 | } | ||
177 | 292 | ||
178 | /** | 293 | /** |
179 | * platform_device_unregister - remove a platform-level device | 294 | * platform_device_unregister - remove a platform-level device |
@@ -197,18 +312,6 @@ void platform_device_unregister(struct platform_device * pdev) | |||
197 | } | 312 | } |
198 | } | 313 | } |
199 | 314 | ||
200 | struct platform_object { | ||
201 | struct platform_device pdev; | ||
202 | struct resource resources[0]; | ||
203 | }; | ||
204 | |||
205 | static void platform_device_release_simple(struct device *dev) | ||
206 | { | ||
207 | struct platform_device *pdev = to_platform_device(dev); | ||
208 | |||
209 | kfree(container_of(pdev, struct platform_object, pdev)); | ||
210 | } | ||
211 | |||
212 | /** | 315 | /** |
213 | * platform_device_register_simple | 316 | * platform_device_register_simple |
214 | * @name: base name of the device we're adding | 317 | * @name: base name of the device we're adding |
@@ -225,33 +328,29 @@ static void platform_device_release_simple(struct device *dev) | |||
225 | struct platform_device *platform_device_register_simple(char *name, unsigned int id, | 328 | struct platform_device *platform_device_register_simple(char *name, unsigned int id, |
226 | struct resource *res, unsigned int num) | 329 | struct resource *res, unsigned int num) |
227 | { | 330 | { |
228 | struct platform_object *pobj; | 331 | struct platform_device *pdev; |
229 | int retval; | 332 | int retval; |
230 | 333 | ||
231 | pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL); | 334 | pdev = platform_device_alloc(name, id); |
232 | if (!pobj) { | 335 | if (!pdev) { |
233 | retval = -ENOMEM; | 336 | retval = -ENOMEM; |
234 | goto error; | 337 | goto error; |
235 | } | 338 | } |
236 | 339 | ||
237 | pobj->pdev.name = name; | ||
238 | pobj->pdev.id = id; | ||
239 | pobj->pdev.dev.release = platform_device_release_simple; | ||
240 | |||
241 | if (num) { | 340 | if (num) { |
242 | memcpy(pobj->resources, res, sizeof(struct resource) * num); | 341 | retval = platform_device_add_resources(pdev, res, num); |
243 | pobj->pdev.resource = pobj->resources; | 342 | if (retval) |
244 | pobj->pdev.num_resources = num; | 343 | goto error; |
245 | } | 344 | } |
246 | 345 | ||
247 | retval = platform_device_register(&pobj->pdev); | 346 | retval = platform_device_add(pdev); |
248 | if (retval) | 347 | if (retval) |
249 | goto error; | 348 | goto error; |
250 | 349 | ||
251 | return &pobj->pdev; | 350 | return pdev; |
252 | 351 | ||
253 | error: | 352 | error: |
254 | kfree(pobj); | 353 | platform_device_put(pdev); |
255 | return ERR_PTR(retval); | 354 | return ERR_PTR(retval); |
256 | } | 355 | } |
257 | 356 | ||
diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 4d26e5e7d18b..0d33a93df96b 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c | |||
@@ -1470,15 +1470,6 @@ static int __init depca_mca_probe(struct device *device) | |||
1470 | ** ISA bus I/O device probe | 1470 | ** ISA bus I/O device probe |
1471 | */ | 1471 | */ |
1472 | 1472 | ||
1473 | static void depca_platform_release (struct device *device) | ||
1474 | { | ||
1475 | struct platform_device *pldev; | ||
1476 | |||
1477 | /* free device */ | ||
1478 | pldev = to_platform_device (device); | ||
1479 | kfree (pldev); | ||
1480 | } | ||
1481 | |||
1482 | static void __init depca_platform_probe (void) | 1473 | static void __init depca_platform_probe (void) |
1483 | { | 1474 | { |
1484 | int i; | 1475 | int i; |
@@ -1491,19 +1482,16 @@ static void __init depca_platform_probe (void) | |||
1491 | * line, use it (if valid) */ | 1482 | * line, use it (if valid) */ |
1492 | if (io && io != depca_io_ports[i].iobase) | 1483 | if (io && io != depca_io_ports[i].iobase) |
1493 | continue; | 1484 | continue; |
1494 | 1485 | ||
1495 | if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) | 1486 | pldev = platform_device_alloc(depca_string, i); |
1487 | if (!pldev) | ||
1496 | continue; | 1488 | continue; |
1497 | 1489 | ||
1498 | memset (pldev, 0, sizeof (*pldev)); | ||
1499 | pldev->name = depca_string; | ||
1500 | pldev->id = i; | ||
1501 | pldev->dev.platform_data = (void *) depca_io_ports[i].iobase; | 1490 | pldev->dev.platform_data = (void *) depca_io_ports[i].iobase; |
1502 | pldev->dev.release = depca_platform_release; | ||
1503 | depca_io_ports[i].device = pldev; | 1491 | depca_io_ports[i].device = pldev; |
1504 | 1492 | ||
1505 | if (platform_device_register (pldev)) { | 1493 | if (platform_device_add(pldev)) { |
1506 | kfree (pldev); | 1494 | platform_device_put(pldev); |
1507 | depca_io_ports[i].device = NULL; | 1495 | depca_io_ports[i].device = NULL; |
1508 | continue; | 1496 | continue; |
1509 | } | 1497 | } |
@@ -1515,6 +1503,7 @@ static void __init depca_platform_probe (void) | |||
1515 | * allocated structure */ | 1503 | * allocated structure */ |
1516 | 1504 | ||
1517 | depca_io_ports[i].device = NULL; | 1505 | depca_io_ports[i].device = NULL; |
1506 | pldev->dev.platform_data = NULL; | ||
1518 | platform_device_unregister (pldev); | 1507 | platform_device_unregister (pldev); |
1519 | } | 1508 | } |
1520 | } | 1509 | } |
@@ -2112,6 +2101,7 @@ static void __exit depca_module_exit (void) | |||
2112 | 2101 | ||
2113 | for (i = 0; depca_io_ports[i].iobase; i++) { | 2102 | for (i = 0; depca_io_ports[i].iobase; i++) { |
2114 | if (depca_io_ports[i].device) { | 2103 | if (depca_io_ports[i].device) { |
2104 | depca_io_ports[i].device->dev.platform_data = NULL; | ||
2115 | platform_device_unregister (depca_io_ports[i].device); | 2105 | platform_device_unregister (depca_io_ports[i].device); |
2116 | depca_io_ports[i].device = NULL; | 2106 | depca_io_ports[i].device = NULL; |
2117 | } | 2107 | } |
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index a74a5cfaf5bc..2fb3101cb33e 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c | |||
@@ -285,18 +285,8 @@ static struct device_driver jazz_sonic_driver = { | |||
285 | .remove = __devexit_p(jazz_sonic_device_remove), | 285 | .remove = __devexit_p(jazz_sonic_device_remove), |
286 | }; | 286 | }; |
287 | 287 | ||
288 | static void jazz_sonic_platform_release (struct device *device) | ||
289 | { | ||
290 | struct platform_device *pldev; | ||
291 | |||
292 | /* free device */ | ||
293 | pldev = to_platform_device (device); | ||
294 | kfree (pldev); | ||
295 | } | ||
296 | |||
297 | static int __init jazz_sonic_init_module(void) | 288 | static int __init jazz_sonic_init_module(void) |
298 | { | 289 | { |
299 | struct platform_device *pldev; | ||
300 | int err; | 290 | int err; |
301 | 291 | ||
302 | if ((err = driver_register(&jazz_sonic_driver))) { | 292 | if ((err = driver_register(&jazz_sonic_driver))) { |
@@ -304,27 +294,19 @@ static int __init jazz_sonic_init_module(void) | |||
304 | return err; | 294 | return err; |
305 | } | 295 | } |
306 | 296 | ||
307 | jazz_sonic_device = NULL; | 297 | jazz_sonic_device = platform_device_alloc(jazz_sonic_string, 0); |
308 | 298 | if (!jazz_sonnic_device) | |
309 | if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) { | ||
310 | goto out_unregister; | 299 | goto out_unregister; |
311 | } | ||
312 | 300 | ||
313 | memset(pldev, 0, sizeof (*pldev)); | 301 | if (platform_device_add(jazz_sonic_device)) { |
314 | pldev->name = jazz_sonic_string; | 302 | platform_device_put(jazz_sonic_device); |
315 | pldev->id = 0; | ||
316 | pldev->dev.release = jazz_sonic_platform_release; | ||
317 | jazz_sonic_device = pldev; | ||
318 | |||
319 | if (platform_device_register (pldev)) { | ||
320 | kfree(pldev); | ||
321 | jazz_sonic_device = NULL; | 303 | jazz_sonic_device = NULL; |
322 | } | 304 | } |
323 | 305 | ||
324 | return 0; | 306 | return 0; |
325 | 307 | ||
326 | out_unregister: | 308 | out_unregister: |
327 | platform_device_unregister(pldev); | 309 | driver_unregister(&jazz_sonic_driver); |
328 | 310 | ||
329 | return -ENOMEM; | 311 | return -ENOMEM; |
330 | } | 312 | } |
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index e9c999d7eb39..9ef4592aca03 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c | |||
@@ -599,18 +599,8 @@ static struct device_driver mac_sonic_driver = { | |||
599 | .remove = __devexit_p(mac_sonic_device_remove), | 599 | .remove = __devexit_p(mac_sonic_device_remove), |
600 | }; | 600 | }; |
601 | 601 | ||
602 | static void mac_sonic_platform_release(struct device *device) | ||
603 | { | ||
604 | struct platform_device *pldev; | ||
605 | |||
606 | /* free device */ | ||
607 | pldev = to_platform_device (device); | ||
608 | kfree (pldev); | ||
609 | } | ||
610 | |||
611 | static int __init mac_sonic_init_module(void) | 602 | static int __init mac_sonic_init_module(void) |
612 | { | 603 | { |
613 | struct platform_device *pldev; | ||
614 | int err; | 604 | int err; |
615 | 605 | ||
616 | if ((err = driver_register(&mac_sonic_driver))) { | 606 | if ((err = driver_register(&mac_sonic_driver))) { |
@@ -618,27 +608,20 @@ static int __init mac_sonic_init_module(void) | |||
618 | return err; | 608 | return err; |
619 | } | 609 | } |
620 | 610 | ||
621 | mac_sonic_device = NULL; | 611 | mac_sonic_device = platform_device_alloc(mac_sonic_string, 0); |
622 | 612 | if (!mac_sonic_device) { | |
623 | if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) { | ||
624 | goto out_unregister; | 613 | goto out_unregister; |
625 | } | 614 | } |
626 | 615 | ||
627 | memset(pldev, 0, sizeof (*pldev)); | 616 | if (platform_device_add(mac_sonic_device)) { |
628 | pldev->name = mac_sonic_string; | 617 | platform_device_put(mac_sonic_device); |
629 | pldev->id = 0; | ||
630 | pldev->dev.release = mac_sonic_platform_release; | ||
631 | mac_sonic_device = pldev; | ||
632 | |||
633 | if (platform_device_register (pldev)) { | ||
634 | kfree(pldev); | ||
635 | mac_sonic_device = NULL; | 618 | mac_sonic_device = NULL; |
636 | } | 619 | } |
637 | 620 | ||
638 | return 0; | 621 | return 0; |
639 | 622 | ||
640 | out_unregister: | 623 | out_unregister: |
641 | platform_device_unregister(pldev); | 624 | driver_unregister(&mac_sonic_driver); |
642 | 625 | ||
643 | return -ENOMEM; | 626 | return -ENOMEM; |
644 | } | 627 | } |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index f47d2c454e33..186e96c47b3d 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -251,9 +251,53 @@ static const struct serial8250_config uart_config[] = { | |||
251 | }, | 251 | }, |
252 | }; | 252 | }; |
253 | 253 | ||
254 | #ifdef CONFIG_SERIAL_8250_AU1X00 | ||
255 | |||
256 | /* Au1x00 UART hardware has a weird register layout */ | ||
257 | static const u8 au_io_in_map[] = { | ||
258 | [UART_RX] = 0, | ||
259 | [UART_IER] = 2, | ||
260 | [UART_IIR] = 3, | ||
261 | [UART_LCR] = 5, | ||
262 | [UART_MCR] = 6, | ||
263 | [UART_LSR] = 7, | ||
264 | [UART_MSR] = 8, | ||
265 | }; | ||
266 | |||
267 | static const u8 au_io_out_map[] = { | ||
268 | [UART_TX] = 1, | ||
269 | [UART_IER] = 2, | ||
270 | [UART_FCR] = 4, | ||
271 | [UART_LCR] = 5, | ||
272 | [UART_MCR] = 6, | ||
273 | }; | ||
274 | |||
275 | /* sane hardware needs no mapping */ | ||
276 | static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) | ||
277 | { | ||
278 | if (up->port.iotype != UPIO_AU) | ||
279 | return offset; | ||
280 | return au_io_in_map[offset]; | ||
281 | } | ||
282 | |||
283 | static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | ||
284 | { | ||
285 | if (up->port.iotype != UPIO_AU) | ||
286 | return offset; | ||
287 | return au_io_out_map[offset]; | ||
288 | } | ||
289 | |||
290 | #else | ||
291 | |||
292 | /* sane hardware needs no mapping */ | ||
293 | #define map_8250_in_reg(up, offset) (offset) | ||
294 | #define map_8250_out_reg(up, offset) (offset) | ||
295 | |||
296 | #endif | ||
297 | |||
254 | static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) | 298 | static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) |
255 | { | 299 | { |
256 | offset <<= up->port.regshift; | 300 | offset = map_8250_in_reg(up, offset) << up->port.regshift; |
257 | 301 | ||
258 | switch (up->port.iotype) { | 302 | switch (up->port.iotype) { |
259 | case UPIO_HUB6: | 303 | case UPIO_HUB6: |
@@ -266,6 +310,11 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) | |||
266 | case UPIO_MEM32: | 310 | case UPIO_MEM32: |
267 | return readl(up->port.membase + offset); | 311 | return readl(up->port.membase + offset); |
268 | 312 | ||
313 | #ifdef CONFIG_SERIAL_8250_AU1X00 | ||
314 | case UPIO_AU: | ||
315 | return __raw_readl(up->port.membase + offset); | ||
316 | #endif | ||
317 | |||
269 | default: | 318 | default: |
270 | return inb(up->port.iobase + offset); | 319 | return inb(up->port.iobase + offset); |
271 | } | 320 | } |
@@ -274,7 +323,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) | |||
274 | static _INLINE_ void | 323 | static _INLINE_ void |
275 | serial_out(struct uart_8250_port *up, int offset, int value) | 324 | serial_out(struct uart_8250_port *up, int offset, int value) |
276 | { | 325 | { |
277 | offset <<= up->port.regshift; | 326 | offset = map_8250_out_reg(up, offset) << up->port.regshift; |
278 | 327 | ||
279 | switch (up->port.iotype) { | 328 | switch (up->port.iotype) { |
280 | case UPIO_HUB6: | 329 | case UPIO_HUB6: |
@@ -290,6 +339,12 @@ serial_out(struct uart_8250_port *up, int offset, int value) | |||
290 | writel(value, up->port.membase + offset); | 339 | writel(value, up->port.membase + offset); |
291 | break; | 340 | break; |
292 | 341 | ||
342 | #ifdef CONFIG_SERIAL_8250_AU1X00 | ||
343 | case UPIO_AU: | ||
344 | __raw_writel(value, up->port.membase + offset); | ||
345 | break; | ||
346 | #endif | ||
347 | |||
293 | default: | 348 | default: |
294 | outb(value, up->port.iobase + offset); | 349 | outb(value, up->port.iobase + offset); |
295 | } | 350 | } |
@@ -910,6 +965,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
910 | } | 965 | } |
911 | } | 966 | } |
912 | #endif | 967 | #endif |
968 | |||
969 | #ifdef CONFIG_SERIAL_8250_AU1X00 | ||
970 | /* if access method is AU, it is a 16550 with a quirk */ | ||
971 | if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) | ||
972 | up->bugs |= UART_BUG_NOMSR; | ||
973 | #endif | ||
974 | |||
913 | serial_outp(up, UART_LCR, save_lcr); | 975 | serial_outp(up, UART_LCR, save_lcr); |
914 | 976 | ||
915 | if (up->capabilities != uart_config[up->port.type].flags) { | 977 | if (up->capabilities != uart_config[up->port.type].flags) { |
@@ -1057,6 +1119,10 @@ static void serial8250_enable_ms(struct uart_port *port) | |||
1057 | { | 1119 | { |
1058 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1120 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
1059 | 1121 | ||
1122 | /* no MSR capabilities */ | ||
1123 | if (up->bugs & UART_BUG_NOMSR) | ||
1124 | return; | ||
1125 | |||
1060 | up->ier |= UART_IER_MSI; | 1126 | up->ier |= UART_IER_MSI; |
1061 | serial_out(up, UART_IER, up->ier); | 1127 | serial_out(up, UART_IER, up->ier); |
1062 | } | 1128 | } |
@@ -1774,7 +1840,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, | |||
1774 | * CTS flow control flag and modem status interrupts | 1840 | * CTS flow control flag and modem status interrupts |
1775 | */ | 1841 | */ |
1776 | up->ier &= ~UART_IER_MSI; | 1842 | up->ier &= ~UART_IER_MSI; |
1777 | if (UART_ENABLE_MS(&up->port, termios->c_cflag)) | 1843 | if (!(up->bugs & UART_BUG_NOMSR) && |
1844 | UART_ENABLE_MS(&up->port, termios->c_cflag)) | ||
1778 | up->ier |= UART_IER_MSI; | 1845 | up->ier |= UART_IER_MSI; |
1779 | if (up->capabilities & UART_CAP_UUE) | 1846 | if (up->capabilities & UART_CAP_UUE) |
1780 | up->ier |= UART_IER_UUE | UART_IER_RTOIE; | 1847 | up->ier |= UART_IER_UUE | UART_IER_RTOIE; |
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index b1b459efda52..a607b98016db 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h | |||
@@ -49,6 +49,7 @@ struct serial8250_config { | |||
49 | 49 | ||
50 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ | 50 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ |
51 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ | 51 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ |
52 | #define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ | ||
52 | 53 | ||
53 | #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) | 54 | #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) |
54 | #define _INLINE_ inline | 55 | #define _INLINE_ inline |
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c new file mode 100644 index 000000000000..06ae8fbcc947 --- /dev/null +++ b/drivers/serial/8250_au1x00.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Serial Device Initialisation for Au1x00 | ||
3 | * | ||
4 | * (C) Copyright Embedded Alley Solutions, Inc 2005 | ||
5 | * Author: Pantelis Antoniou <pantelis@embeddedalley.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/serial_core.h> | ||
19 | #include <linux/signal.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/types.h> | ||
22 | |||
23 | #include <linux/serial_8250.h> | ||
24 | |||
25 | #include <asm/mach-au1x00/au1000.h> | ||
26 | |||
27 | #include "8250.h" | ||
28 | |||
29 | #define PORT(_base, _irq) \ | ||
30 | { \ | ||
31 | .iobase = _base, \ | ||
32 | .membase = (void __iomem *)_base,\ | ||
33 | .mapbase = _base, \ | ||
34 | .irq = _irq, \ | ||
35 | .uartclk = 0, /* filled */ \ | ||
36 | .regshift = 2, \ | ||
37 | .iotype = UPIO_AU, \ | ||
38 | .flags = UPF_SKIP_TEST | \ | ||
39 | UPF_IOREMAP, \ | ||
40 | } | ||
41 | |||
42 | static struct plat_serial8250_port au1x00_data[] = { | ||
43 | #if defined(CONFIG_SOC_AU1000) | ||
44 | PORT(UART0_ADDR, AU1000_UART0_INT), | ||
45 | PORT(UART1_ADDR, AU1000_UART1_INT), | ||
46 | PORT(UART2_ADDR, AU1000_UART2_INT), | ||
47 | PORT(UART3_ADDR, AU1000_UART3_INT), | ||
48 | #elif defined(CONFIG_SOC_AU1500) | ||
49 | PORT(UART0_ADDR, AU1500_UART0_INT), | ||
50 | PORT(UART3_ADDR, AU1500_UART3_INT), | ||
51 | #elif defined(CONFIG_SOC_AU1100) | ||
52 | PORT(UART0_ADDR, AU1100_UART0_INT), | ||
53 | PORT(UART1_ADDR, AU1100_UART1_INT), | ||
54 | PORT(UART2_ADDR, AU1100_UART2_INT), | ||
55 | PORT(UART3_ADDR, AU1100_UART3_INT), | ||
56 | #elif defined(CONFIG_SOC_AU1550) | ||
57 | PORT(UART0_ADDR, AU1550_UART0_INT), | ||
58 | PORT(UART1_ADDR, AU1550_UART1_INT), | ||
59 | PORT(UART2_ADDR, AU1550_UART2_INT), | ||
60 | PORT(UART3_ADDR, AU1550_UART3_INT), | ||
61 | #elif defined(CONFIG_SOC_AU1200) | ||
62 | PORT(UART0_ADDR, AU1200_UART0_INT), | ||
63 | PORT(UART1_ADDR, AU1200_UART1_INT), | ||
64 | #endif | ||
65 | { }, | ||
66 | }; | ||
67 | |||
68 | static struct platform_device au1x00_device = { | ||
69 | .name = "serial8250", | ||
70 | .id = PLAT8250_DEV_AU1X00, | ||
71 | .dev = { | ||
72 | .platform_data = au1x00_data, | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static int __init au1x00_init(void) | ||
77 | { | ||
78 | int i; | ||
79 | unsigned int uartclk; | ||
80 | |||
81 | /* get uart clock */ | ||
82 | uartclk = get_au1x00_uart_baud_base() * 16; | ||
83 | |||
84 | /* fill up uartclk */ | ||
85 | for (i = 0; au1x00_data[i].flags ; i++) | ||
86 | au1x00_data[i].uartclk = uartclk; | ||
87 | |||
88 | return platform_device_register(&au1x00_device); | ||
89 | } | ||
90 | |||
91 | /* XXX: Yes, I know this doesn't yet work. */ | ||
92 | static void __exit au1x00_exit(void) | ||
93 | { | ||
94 | platform_device_unregister(&au1x00_device); | ||
95 | } | ||
96 | |||
97 | module_init(au1x00_init); | ||
98 | module_exit(au1x00_exit); | ||
99 | |||
100 | MODULE_AUTHOR("Pantelis Antoniou <pantelis@embeddedalley.com>"); | ||
101 | MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards"); | ||
102 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b745a1b9e835..ff36f0c9fdad 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -207,6 +207,14 @@ config SERIAL_8250_ACORN | |||
207 | system, say Y to this option. The driver can handle 1, 2, or 3 port | 207 | system, say Y to this option. The driver can handle 1, 2, or 3 port |
208 | cards. If unsure, say N. | 208 | cards. If unsure, say N. |
209 | 209 | ||
210 | config SERIAL_8250_AU1X00 | ||
211 | bool "AU1X00 serial port support" | ||
212 | depends on SERIAL_8250 != n && SOC_AU1X00 | ||
213 | help | ||
214 | If you have an Au1x00 board and want to use the serial port, say Y | ||
215 | to this option. The driver can handle 1 or 2 serial ports. | ||
216 | If unsure, say N. | ||
217 | |||
210 | comment "Non-8250 serial port support" | 218 | comment "Non-8250 serial port support" |
211 | 219 | ||
212 | config SERIAL_AMBA_PL010 | 220 | config SERIAL_AMBA_PL010 |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 11c7dc483f93..d7c7c7180e33 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -22,6 +22,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o | |||
22 | obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o | 22 | obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o |
23 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o | 23 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o |
24 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o | 24 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o |
25 | obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o | ||
25 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o | 26 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o |
26 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o | 27 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o |
27 | obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o | 28 | obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0745ce782974..427a23858076 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -1959,6 +1959,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) | |||
1959 | break; | 1959 | break; |
1960 | case UPIO_MEM: | 1960 | case UPIO_MEM: |
1961 | case UPIO_MEM32: | 1961 | case UPIO_MEM32: |
1962 | case UPIO_AU: | ||
1962 | snprintf(address, sizeof(address), | 1963 | snprintf(address, sizeof(address), |
1963 | "MMIO 0x%lx", port->mapbase); | 1964 | "MMIO 0x%lx", port->mapbase); |
1964 | break; | 1965 | break; |
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 126daff1c848..6aa9f824c185 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c | |||
@@ -502,10 +502,6 @@ static ssize_t arcfb_write(struct file *file, const char *buf, size_t count, | |||
502 | return err; | 502 | return err; |
503 | } | 503 | } |
504 | 504 | ||
505 | static void arcfb_platform_release(struct device *device) | ||
506 | { | ||
507 | } | ||
508 | |||
509 | static struct fb_ops arcfb_ops = { | 505 | static struct fb_ops arcfb_ops = { |
510 | .owner = THIS_MODULE, | 506 | .owner = THIS_MODULE, |
511 | .fb_open = arcfb_open, | 507 | .fb_open = arcfb_open, |
@@ -624,13 +620,7 @@ static struct device_driver arcfb_driver = { | |||
624 | .remove = arcfb_remove, | 620 | .remove = arcfb_remove, |
625 | }; | 621 | }; |
626 | 622 | ||
627 | static struct platform_device arcfb_device = { | 623 | static struct platform_device *arcfb_device; |
628 | .name = "arcfb", | ||
629 | .id = 0, | ||
630 | .dev = { | ||
631 | .release = arcfb_platform_release, | ||
632 | } | ||
633 | }; | ||
634 | 624 | ||
635 | static int __init arcfb_init(void) | 625 | static int __init arcfb_init(void) |
636 | { | 626 | { |
@@ -641,9 +631,16 @@ static int __init arcfb_init(void) | |||
641 | 631 | ||
642 | ret = driver_register(&arcfb_driver); | 632 | ret = driver_register(&arcfb_driver); |
643 | if (!ret) { | 633 | if (!ret) { |
644 | ret = platform_device_register(&arcfb_device); | 634 | arcfb_device = platform_device_alloc("arcfb", 0); |
645 | if (ret) | 635 | if (arcfb_device) { |
636 | ret = platform_device_add(arcfb_device); | ||
637 | } else { | ||
638 | ret = -ENOMEM; | ||
639 | } | ||
640 | if (ret) { | ||
641 | platform_device_put(arcfb_device); | ||
646 | driver_unregister(&arcfb_driver); | 642 | driver_unregister(&arcfb_driver); |
643 | } | ||
647 | } | 644 | } |
648 | return ret; | 645 | return ret; |
649 | 646 | ||
@@ -651,7 +648,7 @@ static int __init arcfb_init(void) | |||
651 | 648 | ||
652 | static void __exit arcfb_exit(void) | 649 | static void __exit arcfb_exit(void) |
653 | { | 650 | { |
654 | platform_device_unregister(&arcfb_device); | 651 | platform_device_unregister(arcfb_device); |
655 | driver_unregister(&arcfb_driver); | 652 | driver_unregister(&arcfb_driver); |
656 | } | 653 | } |
657 | 654 | ||
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 316bfe994811..ed853bef19e9 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c | |||
@@ -1260,24 +1260,30 @@ static struct device_driver gbefb_driver = { | |||
1260 | .remove = __devexit_p(gbefb_remove), | 1260 | .remove = __devexit_p(gbefb_remove), |
1261 | }; | 1261 | }; |
1262 | 1262 | ||
1263 | static struct platform_device gbefb_device = { | 1263 | static struct platform_device *gbefb_device; |
1264 | .name = "gbefb", | ||
1265 | }; | ||
1266 | 1264 | ||
1267 | int __init gbefb_init(void) | 1265 | int __init gbefb_init(void) |
1268 | { | 1266 | { |
1269 | int ret = driver_register(&gbefb_driver); | 1267 | int ret = driver_register(&gbefb_driver); |
1270 | if (!ret) { | 1268 | if (!ret) { |
1271 | ret = platform_device_register(&gbefb_device); | 1269 | gbefb_device = platform_device_alloc("gbefb", 0); |
1272 | if (ret) | 1270 | if (gbefb_device) { |
1271 | ret = platform_device_add(gbefb_device); | ||
1272 | } else { | ||
1273 | ret = -ENOMEM; | ||
1274 | } | ||
1275 | if (ret) { | ||
1276 | platform_device_put(gbefb_device); | ||
1273 | driver_unregister(&gbefb_driver); | 1277 | driver_unregister(&gbefb_driver); |
1278 | } | ||
1274 | } | 1279 | } |
1275 | return ret; | 1280 | return ret; |
1276 | } | 1281 | } |
1277 | 1282 | ||
1278 | void __exit gbefb_exit(void) | 1283 | void __exit gbefb_exit(void) |
1279 | { | 1284 | { |
1280 | driver_unregister(&gbefb_driver); | 1285 | platform_device_unregister(gbefb_device); |
1286 | driver_unregister(&gbefb_driver); | ||
1281 | } | 1287 | } |
1282 | 1288 | ||
1283 | module_init(gbefb_init); | 1289 | module_init(gbefb_init); |
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index cf5106eab2d5..5ce81f44c769 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c | |||
@@ -751,10 +751,6 @@ int __init sgivwfb_setup(char *options) | |||
751 | /* | 751 | /* |
752 | * Initialisation | 752 | * Initialisation |
753 | */ | 753 | */ |
754 | static void sgivwfb_release(struct device *device) | ||
755 | { | ||
756 | } | ||
757 | |||
758 | static int __init sgivwfb_probe(struct device *device) | 754 | static int __init sgivwfb_probe(struct device *device) |
759 | { | 755 | { |
760 | struct platform_device *dev = to_platform_device(device); | 756 | struct platform_device *dev = to_platform_device(device); |
@@ -859,13 +855,7 @@ static struct device_driver sgivwfb_driver = { | |||
859 | .remove = sgivwfb_remove, | 855 | .remove = sgivwfb_remove, |
860 | }; | 856 | }; |
861 | 857 | ||
862 | static struct platform_device sgivwfb_device = { | 858 | static struct platform_device *sgivwfb_device; |
863 | .name = "sgivwfb", | ||
864 | .id = 0, | ||
865 | .dev = { | ||
866 | .release = sgivwfb_release, | ||
867 | } | ||
868 | }; | ||
869 | 859 | ||
870 | int __init sgivwfb_init(void) | 860 | int __init sgivwfb_init(void) |
871 | { | 861 | { |
@@ -880,9 +870,15 @@ int __init sgivwfb_init(void) | |||
880 | #endif | 870 | #endif |
881 | ret = driver_register(&sgivwfb_driver); | 871 | ret = driver_register(&sgivwfb_driver); |
882 | if (!ret) { | 872 | if (!ret) { |
883 | ret = platform_device_register(&sgivwfb_device); | 873 | sgivwfb_device = platform_device_alloc("sgivwfb", 0); |
884 | if (ret) | 874 | if (sgivwfb_device) { |
875 | ret = platform_device_add(sgivwfb_device); | ||
876 | } else | ||
877 | ret = -ENOMEM; | ||
878 | if (ret) { | ||
885 | driver_unregister(&sgivwfb_driver); | 879 | driver_unregister(&sgivwfb_driver); |
880 | platform_device_put(sgivwfb_device); | ||
881 | } | ||
886 | } | 882 | } |
887 | return ret; | 883 | return ret; |
888 | } | 884 | } |
@@ -894,7 +890,7 @@ MODULE_LICENSE("GPL"); | |||
894 | 890 | ||
895 | static void __exit sgivwfb_exit(void) | 891 | static void __exit sgivwfb_exit(void) |
896 | { | 892 | { |
897 | platform_device_unregister(&sgivwfb_device); | 893 | platform_device_unregister(sgivwfb_device); |
898 | driver_unregister(&sgivwfb_driver); | 894 | driver_unregister(&sgivwfb_driver); |
899 | } | 895 | } |
900 | 896 | ||