OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [base/] [platform.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * platform.c - platform 'pseudo' bus for legacy devices
3
 *
4
 * Copyright (c) 2002-3 Patrick Mochel
5
 * Copyright (c) 2002-3 Open Source Development Labs
6
 *
7
 * This file is released under the GPLv2
8
 *
9
 * Please see Documentation/driver-model/platform.txt for more
10
 * information.
11
 */
12
 
13
#include <linux/platform_device.h>
14
#include <linux/module.h>
15
#include <linux/init.h>
16
#include <linux/dma-mapping.h>
17
#include <linux/bootmem.h>
18
#include <linux/err.h>
19
#include <linux/slab.h>
20
 
21
#include "base.h"
22
 
23
#define to_platform_driver(drv) (container_of((drv), struct platform_driver, driver))
24
 
25
struct device platform_bus = {
26
        .bus_id         = "platform",
27
};
28
EXPORT_SYMBOL_GPL(platform_bus);
29
 
30
/**
31
 *      platform_get_resource - get a resource for a device
32
 *      @dev: platform device
33
 *      @type: resource type
34
 *      @num: resource index
35
 */
36
struct resource *
37
platform_get_resource(struct platform_device *dev, unsigned int type,
38
                      unsigned int num)
39
{
40
        int i;
41
 
42
        for (i = 0; i < dev->num_resources; i++) {
43
                struct resource *r = &dev->resource[i];
44
 
45
                if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
46
                                 IORESOURCE_IRQ|IORESOURCE_DMA))
47
                    == type)
48
                        if (num-- == 0)
49
                                return r;
50
        }
51
        return NULL;
52
}
53
EXPORT_SYMBOL_GPL(platform_get_resource);
54
 
55
/**
56
 *      platform_get_irq - get an IRQ for a device
57
 *      @dev: platform device
58
 *      @num: IRQ number index
59
 */
60
int platform_get_irq(struct platform_device *dev, unsigned int num)
61
{
62
        struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
63
 
64
        return r ? r->start : -ENXIO;
65
}
66
EXPORT_SYMBOL_GPL(platform_get_irq);
67
 
68
/**
69
 *      platform_get_resource_byname - get a resource for a device by name
70
 *      @dev: platform device
71
 *      @type: resource type
72
 *      @name: resource name
73
 */
74
struct resource *
75
platform_get_resource_byname(struct platform_device *dev, unsigned int type,
76
                      char *name)
77
{
78
        int i;
79
 
80
        for (i = 0; i < dev->num_resources; i++) {
81
                struct resource *r = &dev->resource[i];
82
 
83
                if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
84
                                 IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
85
                        if (!strcmp(r->name, name))
86
                                return r;
87
        }
88
        return NULL;
89
}
90
EXPORT_SYMBOL_GPL(platform_get_resource_byname);
91
 
92
/**
93
 *      platform_get_irq - get an IRQ for a device
94
 *      @dev: platform device
95
 *      @name: IRQ name
96
 */
97
int platform_get_irq_byname(struct platform_device *dev, char *name)
98
{
99
        struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
100
 
101
        return r ? r->start : -ENXIO;
102
}
103
EXPORT_SYMBOL_GPL(platform_get_irq_byname);
104
 
105
/**
106
 *      platform_add_devices - add a numbers of platform devices
107
 *      @devs: array of platform devices to add
108
 *      @num: number of platform devices in array
109
 */
110
int platform_add_devices(struct platform_device **devs, int num)
111
{
112
        int i, ret = 0;
113
 
114
        for (i = 0; i < num; i++) {
115
                ret = platform_device_register(devs[i]);
116
                if (ret) {
117
                        while (--i >= 0)
118
                                platform_device_unregister(devs[i]);
119
                        break;
120
                }
121
        }
122
 
123
        return ret;
124
}
125
EXPORT_SYMBOL_GPL(platform_add_devices);
126
 
127
struct platform_object {
128
        struct platform_device pdev;
129
        char name[1];
130
};
131
 
132
/**
133
 *      platform_device_put
134
 *      @pdev:  platform device to free
135
 *
136
 *      Free all memory associated with a platform device.  This function
137
 *      must _only_ be externally called in error cases.  All other usage
138
 *      is a bug.
139
 */
140
void platform_device_put(struct platform_device *pdev)
141
{
142
        if (pdev)
143
                put_device(&pdev->dev);
144
}
145
EXPORT_SYMBOL_GPL(platform_device_put);
146
 
147
static void platform_device_release(struct device *dev)
148
{
149
        struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev);
150
 
151
        kfree(pa->pdev.dev.platform_data);
152
        kfree(pa->pdev.resource);
153
        kfree(pa);
154
}
155
 
156
/**
157
 *      platform_device_alloc
158
 *      @name:  base name of the device we're adding
159
 *      @id:    instance id
160
 *
161
 *      Create a platform device object which can have other objects attached
162
 *      to it, and which will have attached objects freed when it is released.
163
 */
164
struct platform_device *platform_device_alloc(const char *name, int id)
165
{
166
        struct platform_object *pa;
167
 
168
        pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
169
        if (pa) {
170
                strcpy(pa->name, name);
171
                pa->pdev.name = pa->name;
172
                pa->pdev.id = id;
173
                device_initialize(&pa->pdev.dev);
174
                pa->pdev.dev.release = platform_device_release;
175
        }
176
 
177
        return pa ? &pa->pdev : NULL;
178
}
179
EXPORT_SYMBOL_GPL(platform_device_alloc);
180
 
181
/**
182
 *      platform_device_add_resources
183
 *      @pdev:  platform device allocated by platform_device_alloc to add resources to
184
 *      @res:   set of resources that needs to be allocated for the device
185
 *      @num:   number of resources
186
 *
187
 *      Add a copy of the resources to the platform device.  The memory
188
 *      associated with the resources will be freed when the platform
189
 *      device is released.
190
 */
191
int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num)
192
{
193
        struct resource *r;
194
 
195
        r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL);
196
        if (r) {
197
                memcpy(r, res, sizeof(struct resource) * num);
198
                pdev->resource = r;
199
                pdev->num_resources = num;
200
        }
201
        return r ? 0 : -ENOMEM;
202
}
203
EXPORT_SYMBOL_GPL(platform_device_add_resources);
204
 
205
/**
206
 *      platform_device_add_data
207
 *      @pdev:  platform device allocated by platform_device_alloc to add resources to
208
 *      @data:  platform specific data for this platform device
209
 *      @size:  size of platform specific data
210
 *
211
 *      Add a copy of platform specific data to the platform device's platform_data
212
 *      pointer.  The memory associated with the platform data will be freed
213
 *      when the platform device is released.
214
 */
215
int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)
216
{
217
        void *d;
218
 
219
        d = kmalloc(size, GFP_KERNEL);
220
        if (d) {
221
                memcpy(d, data, size);
222
                pdev->dev.platform_data = d;
223
        }
224
        return d ? 0 : -ENOMEM;
225
}
226
EXPORT_SYMBOL_GPL(platform_device_add_data);
227
 
228
/**
229
 *      platform_device_add - add a platform device to device hierarchy
230
 *      @pdev:  platform device we're adding
231
 *
232
 *      This is part 2 of platform_device_register(), though may be called
233
 *      separately _iff_ pdev was allocated by platform_device_alloc().
234
 */
235
int platform_device_add(struct platform_device *pdev)
236
{
237
        int i, ret = 0;
238
 
239
        if (!pdev)
240
                return -EINVAL;
241
 
242
        if (!pdev->dev.parent)
243
                pdev->dev.parent = &platform_bus;
244
 
245
        pdev->dev.bus = &platform_bus_type;
246
 
247
        if (pdev->id != -1)
248
                snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,
249
                         pdev->id);
250
        else
251
                strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
252
 
253
        for (i = 0; i < pdev->num_resources; i++) {
254
                struct resource *p, *r = &pdev->resource[i];
255
 
256
                if (r->name == NULL)
257
                        r->name = pdev->dev.bus_id;
258
 
259
                p = r->parent;
260
                if (!p) {
261
                        if (r->flags & IORESOURCE_MEM)
262
                                p = &iomem_resource;
263
                        else if (r->flags & IORESOURCE_IO)
264
                                p = &ioport_resource;
265
                }
266
 
267
                if (p && insert_resource(p, r)) {
268
                        printk(KERN_ERR
269
                               "%s: failed to claim resource %d\n",
270
                               pdev->dev.bus_id, i);
271
                        ret = -EBUSY;
272
                        goto failed;
273
                }
274
        }
275
 
276
        pr_debug("Registering platform device '%s'. Parent at %s\n",
277
                 pdev->dev.bus_id, pdev->dev.parent->bus_id);
278
 
279
        ret = device_add(&pdev->dev);
280
        if (ret == 0)
281
                return ret;
282
 
283
 failed:
284
        while (--i >= 0)
285
                if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
286
                        release_resource(&pdev->resource[i]);
287
        return ret;
288
}
289
EXPORT_SYMBOL_GPL(platform_device_add);
290
 
291
/**
292
 *      platform_device_del - remove a platform-level device
293
 *      @pdev:  platform device we're removing
294
 *
295
 *      Note that this function will also release all memory- and port-based
296
 *      resources owned by the device (@dev->resource).  This function
297
 *      must _only_ be externally called in error cases.  All other usage
298
 *      is a bug.
299
 */
300
void platform_device_del(struct platform_device *pdev)
301
{
302
        int i;
303
 
304
        if (pdev) {
305
                device_del(&pdev->dev);
306
 
307
                for (i = 0; i < pdev->num_resources; i++) {
308
                        struct resource *r = &pdev->resource[i];
309
                        if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
310
                                release_resource(r);
311
                }
312
        }
313
}
314
EXPORT_SYMBOL_GPL(platform_device_del);
315
 
316
/**
317
 *      platform_device_register - add a platform-level device
318
 *      @pdev:  platform device we're adding
319
 *
320
 */
321
int platform_device_register(struct platform_device * pdev)
322
{
323
        device_initialize(&pdev->dev);
324
        return platform_device_add(pdev);
325
}
326
EXPORT_SYMBOL_GPL(platform_device_register);
327
 
328
/**
329
 *      platform_device_unregister - unregister a platform-level device
330
 *      @pdev:  platform device we're unregistering
331
 *
332
 *      Unregistration is done in 2 steps. First we release all resources
333
 *      and remove it from the subsystem, then we drop reference count by
334
 *      calling platform_device_put().
335
 */
336
void platform_device_unregister(struct platform_device * pdev)
337
{
338
        platform_device_del(pdev);
339
        platform_device_put(pdev);
340
}
341
EXPORT_SYMBOL_GPL(platform_device_unregister);
342
 
343
/**
344
 *      platform_device_register_simple
345
 *      @name:  base name of the device we're adding
346
 *      @id:    instance id
347
 *      @res:   set of resources that needs to be allocated for the device
348
 *      @num:   number of resources
349
 *
350
 *      This function creates a simple platform device that requires minimal
351
 *      resource and memory management. Canned release function freeing
352
 *      memory allocated for the device allows drivers using such devices
353
 *      to be unloaded without waiting for the last reference to the device
354
 *      to be dropped.
355
 *
356
 *      This interface is primarily intended for use with legacy drivers
357
 *      which probe hardware directly.  Because such drivers create sysfs
358
 *      device nodes themselves, rather than letting system infrastructure
359
 *      handle such device enumeration tasks, they don't fully conform to
360
 *      the Linux driver model.  In particular, when such drivers are built
361
 *      as modules, they can't be "hotplugged".
362
 */
363
struct platform_device *platform_device_register_simple(char *name, int id,
364
                                                        struct resource *res, unsigned int num)
365
{
366
        struct platform_device *pdev;
367
        int retval;
368
 
369
        pdev = platform_device_alloc(name, id);
370
        if (!pdev) {
371
                retval = -ENOMEM;
372
                goto error;
373
        }
374
 
375
        if (num) {
376
                retval = platform_device_add_resources(pdev, res, num);
377
                if (retval)
378
                        goto error;
379
        }
380
 
381
        retval = platform_device_add(pdev);
382
        if (retval)
383
                goto error;
384
 
385
        return pdev;
386
 
387
error:
388
        platform_device_put(pdev);
389
        return ERR_PTR(retval);
390
}
391
EXPORT_SYMBOL_GPL(platform_device_register_simple);
392
 
393
static int platform_drv_probe(struct device *_dev)
394
{
395
        struct platform_driver *drv = to_platform_driver(_dev->driver);
396
        struct platform_device *dev = to_platform_device(_dev);
397
 
398
        return drv->probe(dev);
399
}
400
 
401
static int platform_drv_probe_fail(struct device *_dev)
402
{
403
        return -ENXIO;
404
}
405
 
406
static int platform_drv_remove(struct device *_dev)
407
{
408
        struct platform_driver *drv = to_platform_driver(_dev->driver);
409
        struct platform_device *dev = to_platform_device(_dev);
410
 
411
        return drv->remove(dev);
412
}
413
 
414
static void platform_drv_shutdown(struct device *_dev)
415
{
416
        struct platform_driver *drv = to_platform_driver(_dev->driver);
417
        struct platform_device *dev = to_platform_device(_dev);
418
 
419
        drv->shutdown(dev);
420
}
421
 
422
static int platform_drv_suspend(struct device *_dev, pm_message_t state)
423
{
424
        struct platform_driver *drv = to_platform_driver(_dev->driver);
425
        struct platform_device *dev = to_platform_device(_dev);
426
 
427
        return drv->suspend(dev, state);
428
}
429
 
430
static int platform_drv_resume(struct device *_dev)
431
{
432
        struct platform_driver *drv = to_platform_driver(_dev->driver);
433
        struct platform_device *dev = to_platform_device(_dev);
434
 
435
        return drv->resume(dev);
436
}
437
 
438
/**
439
 *      platform_driver_register
440
 *      @drv: platform driver structure
441
 */
442
int platform_driver_register(struct platform_driver *drv)
443
{
444
        drv->driver.bus = &platform_bus_type;
445
        if (drv->probe)
446
                drv->driver.probe = platform_drv_probe;
447
        if (drv->remove)
448
                drv->driver.remove = platform_drv_remove;
449
        if (drv->shutdown)
450
                drv->driver.shutdown = platform_drv_shutdown;
451
        if (drv->suspend)
452
                drv->driver.suspend = platform_drv_suspend;
453
        if (drv->resume)
454
                drv->driver.resume = platform_drv_resume;
455
        return driver_register(&drv->driver);
456
}
457
EXPORT_SYMBOL_GPL(platform_driver_register);
458
 
459
/**
460
 *      platform_driver_unregister
461
 *      @drv: platform driver structure
462
 */
463
void platform_driver_unregister(struct platform_driver *drv)
464
{
465
        driver_unregister(&drv->driver);
466
}
467
EXPORT_SYMBOL_GPL(platform_driver_unregister);
468
 
469
/**
470
 * platform_driver_probe - register driver for non-hotpluggable device
471
 * @drv: platform driver structure
472
 * @probe: the driver probe routine, probably from an __init section
473
 *
474
 * Use this instead of platform_driver_register() when you know the device
475
 * is not hotpluggable and has already been registered, and you want to
476
 * remove its run-once probe() infrastructure from memory after the driver
477
 * has bound to the device.
478
 *
479
 * One typical use for this would be with drivers for controllers integrated
480
 * into system-on-chip processors, where the controller devices have been
481
 * configured as part of board setup.
482
 *
483
 * Returns zero if the driver registered and bound to a device, else returns
484
 * a negative error code and with the driver not registered.
485
 */
486
int __init_or_module platform_driver_probe(struct platform_driver *drv,
487
                int (*probe)(struct platform_device *))
488
{
489
        int retval, code;
490
 
491
        /* temporary section violation during probe() */
492
        drv->probe = probe;
493
        retval = code = platform_driver_register(drv);
494
 
495
        /* Fixup that section violation, being paranoid about code scanning
496
         * the list of drivers in order to probe new devices.  Check to see
497
         * if the probe was successful, and make sure any forced probes of
498
         * new devices fail.
499
         */
500
        spin_lock(&platform_bus_type.klist_drivers.k_lock);
501
        drv->probe = NULL;
502
        if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))
503
                retval = -ENODEV;
504
        drv->driver.probe = platform_drv_probe_fail;
505
        spin_unlock(&platform_bus_type.klist_drivers.k_lock);
506
 
507
        if (code != retval)
508
                platform_driver_unregister(drv);
509
        return retval;
510
}
511
EXPORT_SYMBOL_GPL(platform_driver_probe);
512
 
513
/* modalias support enables more hands-off userspace setup:
514
 * (a) environment variable lets new-style hotplug events work once system is
515
 *     fully running:  "modprobe $MODALIAS"
516
 * (b) sysfs attribute lets new-style coldplug recover from hotplug events
517
 *     mishandled before system is fully running:  "modprobe $(cat modalias)"
518
 */
519
static ssize_t
520
modalias_show(struct device *dev, struct device_attribute *a, char *buf)
521
{
522
        struct platform_device  *pdev = to_platform_device(dev);
523
        int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
524
 
525
        return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
526
}
527
 
528
static struct device_attribute platform_dev_attrs[] = {
529
        __ATTR_RO(modalias),
530
        __ATTR_NULL,
531
};
532
 
533
static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
534
{
535
        struct platform_device  *pdev = to_platform_device(dev);
536
 
537
        add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);
538
        return 0;
539
}
540
 
541
 
542
/**
543
 *      platform_match - bind platform device to platform driver.
544
 *      @dev:   device.
545
 *      @drv:   driver.
546
 *
547
 *      Platform device IDs are assumed to be encoded like this:
548
 *      "<name><instance>", where <name> is a short description of the
549
 *      type of device, like "pci" or "floppy", and <instance> is the
550
 *      enumerated instance of the device, like '0' or '42'.
551
 *      Driver IDs are simply "<name>".
552
 *      So, extract the <name> from the platform_device structure,
553
 *      and compare it against the name of the driver. Return whether
554
 *      they match or not.
555
 */
556
 
557
static int platform_match(struct device * dev, struct device_driver * drv)
558
{
559
        struct platform_device *pdev = container_of(dev, struct platform_device, dev);
560
 
561
        return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
562
}
563
 
564
static int platform_suspend(struct device *dev, pm_message_t mesg)
565
{
566
        int ret = 0;
567
 
568
        if (dev->driver && dev->driver->suspend)
569
                ret = dev->driver->suspend(dev, mesg);
570
 
571
        return ret;
572
}
573
 
574
static int platform_suspend_late(struct device *dev, pm_message_t mesg)
575
{
576
        struct platform_driver *drv = to_platform_driver(dev->driver);
577
        struct platform_device *pdev = container_of(dev, struct platform_device, dev);
578
        int ret = 0;
579
 
580
        if (dev->driver && drv->suspend_late)
581
                ret = drv->suspend_late(pdev, mesg);
582
 
583
        return ret;
584
}
585
 
586
static int platform_resume_early(struct device *dev)
587
{
588
        struct platform_driver *drv = to_platform_driver(dev->driver);
589
        struct platform_device *pdev = container_of(dev, struct platform_device, dev);
590
        int ret = 0;
591
 
592
        if (dev->driver && drv->resume_early)
593
                ret = drv->resume_early(pdev);
594
 
595
        return ret;
596
}
597
 
598
static int platform_resume(struct device * dev)
599
{
600
        int ret = 0;
601
 
602
        if (dev->driver && dev->driver->resume)
603
                ret = dev->driver->resume(dev);
604
 
605
        return ret;
606
}
607
 
608
struct bus_type platform_bus_type = {
609
        .name           = "platform",
610
        .dev_attrs      = platform_dev_attrs,
611
        .match          = platform_match,
612
        .uevent         = platform_uevent,
613
        .suspend        = platform_suspend,
614
        .suspend_late   = platform_suspend_late,
615
        .resume_early   = platform_resume_early,
616
        .resume         = platform_resume,
617
};
618
EXPORT_SYMBOL_GPL(platform_bus_type);
619
 
620
int __init platform_bus_init(void)
621
{
622
        int error;
623
 
624
        error = device_register(&platform_bus);
625
        if (error)
626
                return error;
627
        error =  bus_register(&platform_bus_type);
628
        if (error)
629
                device_unregister(&platform_bus);
630
        return error;
631
}
632
 
633
#ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK
634
u64 dma_get_required_mask(struct device *dev)
635
{
636
        u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
637
        u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));
638
        u64 mask;
639
 
640
        if (!high_totalram) {
641
                /* convert to mask just covering totalram */
642
                low_totalram = (1 << (fls(low_totalram) - 1));
643
                low_totalram += low_totalram - 1;
644
                mask = low_totalram;
645
        } else {
646
                high_totalram = (1 << (fls(high_totalram) - 1));
647
                high_totalram += high_totalram - 1;
648
                mask = (((u64)high_totalram) << 32) + 0xffffffff;
649
        }
650
        return mask & *dev->dma_mask;
651
}
652
EXPORT_SYMBOL_GPL(dma_get_required_mask);
653
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.