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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [misc/] [atmel-ssc.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Atmel SSC driver
3
 *
4
 * Copyright (C) 2007 Atmel Corporation
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License version 2 as
8
 * published by the Free Software Foundation.
9
 */
10
 
11
#include <linux/platform_device.h>
12
#include <linux/list.h>
13
#include <linux/clk.h>
14
#include <linux/err.h>
15
#include <linux/io.h>
16
#include <linux/list.h>
17
#include <linux/spinlock.h>
18
#include <linux/atmel-ssc.h>
19
 
20
/* Serialize access to ssc_list and user count */
21
static DEFINE_SPINLOCK(user_lock);
22
static LIST_HEAD(ssc_list);
23
 
24
struct ssc_device *ssc_request(unsigned int ssc_num)
25
{
26
        int ssc_valid = 0;
27
        struct ssc_device *ssc;
28
 
29
        spin_lock(&user_lock);
30
        list_for_each_entry(ssc, &ssc_list, list) {
31
                if (ssc->pdev->id == ssc_num) {
32
                        ssc_valid = 1;
33
                        break;
34
                }
35
        }
36
 
37
        if (!ssc_valid) {
38
                spin_unlock(&user_lock);
39
                dev_dbg(&ssc->pdev->dev, "could not find requested device\n");
40
                return ERR_PTR(-ENODEV);
41
        }
42
 
43
        if (ssc->user) {
44
                spin_unlock(&user_lock);
45
                dev_dbg(&ssc->pdev->dev, "module busy\n");
46
                return ERR_PTR(-EBUSY);
47
        }
48
        ssc->user++;
49
        spin_unlock(&user_lock);
50
 
51
        clk_enable(ssc->clk);
52
 
53
        return ssc;
54
}
55
EXPORT_SYMBOL(ssc_request);
56
 
57
void ssc_free(struct ssc_device *ssc)
58
{
59
        spin_lock(&user_lock);
60
        if (ssc->user) {
61
                ssc->user--;
62
                clk_disable(ssc->clk);
63
        } else {
64
                dev_dbg(&ssc->pdev->dev, "device already free\n");
65
        }
66
        spin_unlock(&user_lock);
67
}
68
EXPORT_SYMBOL(ssc_free);
69
 
70
static int __init ssc_probe(struct platform_device *pdev)
71
{
72
        int retval = 0;
73
        struct resource *regs;
74
        struct ssc_device *ssc;
75
 
76
        ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
77
        if (!ssc) {
78
                dev_dbg(&pdev->dev, "out of memory\n");
79
                retval = -ENOMEM;
80
                goto out;
81
        }
82
 
83
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
84
        if (!regs) {
85
                dev_dbg(&pdev->dev, "no mmio resource defined\n");
86
                retval = -ENXIO;
87
                goto out_free;
88
        }
89
 
90
        ssc->clk = clk_get(&pdev->dev, "pclk");
91
        if (IS_ERR(ssc->clk)) {
92
                dev_dbg(&pdev->dev, "no pclk clock defined\n");
93
                retval = -ENXIO;
94
                goto out_free;
95
        }
96
 
97
        ssc->pdev = pdev;
98
        ssc->regs = ioremap(regs->start, regs->end - regs->start + 1);
99
        if (!ssc->regs) {
100
                dev_dbg(&pdev->dev, "ioremap failed\n");
101
                retval = -EINVAL;
102
                goto out_clk;
103
        }
104
 
105
        /* disable all interrupts */
106
        clk_enable(ssc->clk);
107
        ssc_writel(ssc->regs, IDR, ~0UL);
108
        ssc_readl(ssc->regs, SR);
109
        clk_disable(ssc->clk);
110
 
111
        ssc->irq = platform_get_irq(pdev, 0);
112
        if (!ssc->irq) {
113
                dev_dbg(&pdev->dev, "could not get irq\n");
114
                retval = -ENXIO;
115
                goto out_unmap;
116
        }
117
 
118
        spin_lock(&user_lock);
119
        list_add_tail(&ssc->list, &ssc_list);
120
        spin_unlock(&user_lock);
121
 
122
        platform_set_drvdata(pdev, ssc);
123
 
124
        dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
125
                        ssc->regs, ssc->irq);
126
 
127
        goto out;
128
 
129
out_unmap:
130
        iounmap(ssc->regs);
131
out_clk:
132
        clk_put(ssc->clk);
133
out_free:
134
        kfree(ssc);
135
out:
136
        return retval;
137
}
138
 
139
static int __devexit ssc_remove(struct platform_device *pdev)
140
{
141
        struct ssc_device *ssc = platform_get_drvdata(pdev);
142
 
143
        spin_lock(&user_lock);
144
        iounmap(ssc->regs);
145
        clk_put(ssc->clk);
146
        list_del(&ssc->list);
147
        kfree(ssc);
148
        spin_unlock(&user_lock);
149
 
150
        return 0;
151
}
152
 
153
static struct platform_driver ssc_driver = {
154
        .remove         = __devexit_p(ssc_remove),
155
        .driver         = {
156
                .name           = "ssc",
157
        },
158
};
159
 
160
static int __init ssc_init(void)
161
{
162
        return platform_driver_probe(&ssc_driver, ssc_probe);
163
}
164
module_init(ssc_init);
165
 
166
static void __exit ssc_exit(void)
167
{
168
        platform_driver_unregister(&ssc_driver);
169
}
170
module_exit(ssc_exit);
171
 
172
MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
173
MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
174
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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