Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
misc
atmel-ssc.c
Go to the documentation of this file.
1
/*
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/spinlock.h
>
17
#include <
linux/atmel-ssc.h
>
18
#include <linux/slab.h>
19
#include <linux/module.h>
20
21
/* Serialize access to ssc_list and user count */
22
static
DEFINE_SPINLOCK
(user_lock);
23
static
LIST_HEAD
(ssc_list);
24
25
struct
ssc_device
*
ssc_request
(
unsigned
int
ssc_num)
26
{
27
int
ssc_valid = 0;
28
struct
ssc_device
*
ssc
;
29
30
spin_lock(&user_lock);
31
list_for_each_entry
(ssc, &ssc_list,
list
) {
32
if
(ssc->
pdev
->id == ssc_num) {
33
ssc_valid = 1;
34
break
;
35
}
36
}
37
38
if
(!ssc_valid) {
39
spin_unlock(&user_lock);
40
pr_err
(
"ssc: ssc%d platform device is missing\n"
, ssc_num);
41
return
ERR_PTR(-
ENODEV
);
42
}
43
44
if
(ssc->
user
) {
45
spin_unlock(&user_lock);
46
dev_dbg
(&ssc->
pdev
->dev,
"module busy\n"
);
47
return
ERR_PTR(-
EBUSY
);
48
}
49
ssc->
user
++;
50
spin_unlock(&user_lock);
51
52
clk_enable
(ssc->
clk
);
53
54
return
ssc
;
55
}
56
EXPORT_SYMBOL
(
ssc_request
);
57
58
void
ssc_free
(
struct
ssc_device
*
ssc
)
59
{
60
spin_lock(&user_lock);
61
if
(ssc->
user
) {
62
ssc->
user
--;
63
clk_disable
(ssc->
clk
);
64
}
else
{
65
dev_dbg
(&ssc->
pdev
->dev,
"device already free\n"
);
66
}
67
spin_unlock(&user_lock);
68
}
69
EXPORT_SYMBOL
(
ssc_free
);
70
71
static
int
__init
ssc_probe(
struct
platform_device
*
pdev
)
72
{
73
int
retval
= 0;
74
struct
resource
*
regs
;
75
struct
ssc_device
*
ssc
;
76
77
ssc = kzalloc(
sizeof
(
struct
ssc_device
),
GFP_KERNEL
);
78
if
(!ssc) {
79
dev_dbg
(&pdev->
dev
,
"out of memory\n"
);
80
retval = -
ENOMEM
;
81
goto
out
;
82
}
83
84
regs =
platform_get_resource
(pdev,
IORESOURCE_MEM
, 0);
85
if
(!regs) {
86
dev_dbg
(&pdev->
dev
,
"no mmio resource defined\n"
);
87
retval = -
ENXIO
;
88
goto
out_free;
89
}
90
91
ssc->
clk
=
clk_get
(&pdev->
dev
,
"pclk"
);
92
if
(IS_ERR(ssc->
clk
)) {
93
dev_dbg
(&pdev->
dev
,
"no pclk clock defined\n"
);
94
retval = -
ENXIO
;
95
goto
out_free;
96
}
97
98
ssc->
pdev
=
pdev
;
99
ssc->
regs
=
ioremap
(regs->
start
, resource_size(regs));
100
if
(!ssc->
regs
) {
101
dev_dbg
(&pdev->
dev
,
"ioremap failed\n"
);
102
retval = -
EINVAL
;
103
goto
out_clk;
104
}
105
106
/* disable all interrupts */
107
clk_enable
(ssc->
clk
);
108
ssc_writel
(ssc->
regs
,
IDR
, ~0
UL
);
109
ssc_readl
(ssc->
regs
,
SR
);
110
clk_disable
(ssc->
clk
);
111
112
ssc->
irq
=
platform_get_irq
(pdev, 0);
113
if
(!ssc->
irq
) {
114
dev_dbg
(&pdev->
dev
,
"could not get irq\n"
);
115
retval = -
ENXIO
;
116
goto
out_unmap;
117
}
118
119
spin_lock(&user_lock);
120
list_add_tail
(&ssc->
list
, &ssc_list);
121
spin_unlock(&user_lock);
122
123
platform_set_drvdata(pdev, ssc);
124
125
dev_info
(&pdev->
dev
,
"Atmel SSC device at 0x%p (irq %d)\n"
,
126
ssc->
regs
, ssc->
irq
);
127
128
goto
out
;
129
130
out_unmap:
131
iounmap
(ssc->
regs
);
132
out_clk:
133
clk_put
(ssc->
clk
);
134
out_free:
135
kfree
(ssc);
136
out
:
137
return
retval
;
138
}
139
140
static
int
__devexit
ssc_remove(
struct
platform_device
*pdev)
141
{
142
struct
ssc_device
*ssc = platform_get_drvdata(pdev);
143
144
spin_lock(&user_lock);
145
iounmap
(ssc->
regs
);
146
clk_put
(ssc->
clk
);
147
list_del
(&ssc->
list
);
148
kfree
(ssc);
149
spin_unlock(&user_lock);
150
151
return
0;
152
}
153
154
static
struct
platform_driver
ssc_driver = {
155
.remove =
__devexit_p
(ssc_remove),
156
.driver = {
157
.name =
"ssc"
,
158
.owner =
THIS_MODULE
,
159
},
160
};
161
162
static
int
__init
ssc_init(
void
)
163
{
164
return
platform_driver_probe
(&ssc_driver, ssc_probe);
165
}
166
module_init
(ssc_init);
167
168
static
void
__exit
ssc_exit(
void
)
169
{
170
platform_driver_unregister
(&ssc_driver);
171
}
172
module_exit
(ssc_exit);
173
174
MODULE_AUTHOR
(
"Hans-Christian Egtvedt <
[email protected]
>"
);
175
MODULE_DESCRIPTION
(
"SSC driver for Atmel AVR32 and AT91"
);
176
MODULE_LICENSE
(
"GPL"
);
177
MODULE_ALIAS
(
"platform:ssc"
);
Generated on Thu Jan 10 2013 13:54:34 for Linux Kernel by
1.8.2