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
arch
arm
plat-pxa
ssp.c
Go to the documentation of this file.
1
/*
2
* linux/arch/arm/mach-pxa/ssp.c
3
*
4
* based on linux/arch/arm/mach-sa1100/ssp.c by Russell King
5
*
6
* Copyright (C) 2003 Russell King.
7
* Copyright (C) 2003 Wolfson Microelectronics PLC
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
12
*
13
* PXA2xx SSP driver. This provides the generic core for simple
14
* IO-based SSP applications and allows easy port setup for DMA access.
15
*
16
* Author: Liam Girdwood <
[email protected]
>
17
*/
18
19
#include <linux/module.h>
20
#include <linux/kernel.h>
21
#include <linux/sched.h>
22
#include <linux/slab.h>
23
#include <linux/errno.h>
24
#include <
linux/interrupt.h
>
25
#include <
linux/ioport.h
>
26
#include <
linux/init.h
>
27
#include <
linux/mutex.h
>
28
#include <
linux/clk.h
>
29
#include <
linux/err.h
>
30
#include <
linux/platform_device.h
>
31
#include <
linux/spi/pxa2xx_spi.h
>
32
#include <
linux/io.h
>
33
34
#include <asm/irq.h>
35
#include <mach/hardware.h>
36
37
static
DEFINE_MUTEX
(ssp_lock);
38
static
LIST_HEAD
(ssp_list);
39
40
struct
ssp_device
*
pxa_ssp_request
(
int
port
,
const
char
*
label
)
41
{
42
struct
ssp_device
*
ssp
=
NULL
;
43
44
mutex_lock
(&ssp_lock);
45
46
list_for_each_entry
(ssp, &ssp_list,
node
) {
47
if
(ssp->
port_id
== port && ssp->
use_count
== 0) {
48
ssp->
use_count
++;
49
ssp->
label
=
label
;
50
break
;
51
}
52
}
53
54
mutex_unlock
(&ssp_lock);
55
56
if
(&ssp->
node
== &ssp_list)
57
return
NULL
;
58
59
return
ssp
;
60
}
61
EXPORT_SYMBOL
(
pxa_ssp_request
);
62
63
void
pxa_ssp_free
(
struct
ssp_device
*
ssp
)
64
{
65
mutex_lock
(&ssp_lock);
66
if
(ssp->
use_count
) {
67
ssp->
use_count
--;
68
ssp->
label
=
NULL
;
69
}
else
70
dev_err
(&ssp->
pdev
->dev,
"device already free\n"
);
71
mutex_unlock
(&ssp_lock);
72
}
73
EXPORT_SYMBOL
(
pxa_ssp_free
);
74
75
static
int
__devinit
pxa_ssp_probe(
struct
platform_device
*
pdev
)
76
{
77
const
struct
platform_device_id
*
id
=
platform_get_device_id
(pdev);
78
struct
resource
*
res
;
79
struct
ssp_device
*
ssp
;
80
int
ret
= 0;
81
82
ssp = kzalloc(
sizeof
(
struct
ssp_device
),
GFP_KERNEL
);
83
if
(ssp ==
NULL
) {
84
dev_err
(&pdev->
dev
,
"failed to allocate memory"
);
85
return
-
ENOMEM
;
86
}
87
ssp->
pdev
=
pdev
;
88
89
ssp->
clk
=
clk_get
(&pdev->
dev
,
NULL
);
90
if
(IS_ERR(ssp->
clk
)) {
91
ret = PTR_ERR(ssp->
clk
);
92
goto
err_free;
93
}
94
95
res =
platform_get_resource
(pdev,
IORESOURCE_DMA
, 0);
96
if
(res ==
NULL
) {
97
dev_err
(&pdev->
dev
,
"no SSP RX DRCMR defined\n"
);
98
ret = -
ENODEV
;
99
goto
err_free_clk;
100
}
101
ssp->
drcmr_rx
= res->
start
;
102
103
res =
platform_get_resource
(pdev,
IORESOURCE_DMA
, 1);
104
if
(res ==
NULL
) {
105
dev_err
(&pdev->
dev
,
"no SSP TX DRCMR defined\n"
);
106
ret = -
ENODEV
;
107
goto
err_free_clk;
108
}
109
ssp->
drcmr_tx
= res->
start
;
110
111
res =
platform_get_resource
(pdev,
IORESOURCE_MEM
, 0);
112
if
(res ==
NULL
) {
113
dev_err
(&pdev->
dev
,
"no memory resource defined\n"
);
114
ret = -
ENODEV
;
115
goto
err_free_clk;
116
}
117
118
res =
request_mem_region
(res->
start
, resource_size(res),
119
pdev->
name
);
120
if
(res ==
NULL
) {
121
dev_err
(&pdev->
dev
,
"failed to request memory resource\n"
);
122
ret = -
EBUSY
;
123
goto
err_free_clk;
124
}
125
126
ssp->
phys_base
= res->
start
;
127
128
ssp->
mmio_base
=
ioremap
(res->
start
, resource_size(res));
129
if
(ssp->
mmio_base
==
NULL
) {
130
dev_err
(&pdev->
dev
,
"failed to ioremap() registers\n"
);
131
ret = -
ENODEV
;
132
goto
err_free_mem;
133
}
134
135
ssp->
irq
=
platform_get_irq
(pdev, 0);
136
if
(ssp->
irq
< 0) {
137
dev_err
(&pdev->
dev
,
"no IRQ resource defined\n"
);
138
ret = -
ENODEV
;
139
goto
err_free_io;
140
}
141
142
/* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
143
* starts from 0, do a translation here
144
*/
145
ssp->
port_id
= pdev->
id
+ 1;
146
ssp->
use_count
= 0;
147
ssp->
type
= (
int
)id->driver_data;
148
149
mutex_lock
(&ssp_lock);
150
list_add(&ssp->
node
, &ssp_list);
151
mutex_unlock
(&ssp_lock);
152
153
platform_set_drvdata(pdev, ssp);
154
return
0;
155
156
err_free_io:
157
iounmap
(ssp->
mmio_base
);
158
err_free_mem:
159
release_mem_region
(res->
start
, resource_size(res));
160
err_free_clk:
161
clk_put
(ssp->
clk
);
162
err_free:
163
kfree
(ssp);
164
return
ret
;
165
}
166
167
static
int
__devexit
pxa_ssp_remove(
struct
platform_device
*pdev)
168
{
169
struct
resource
*
res
;
170
struct
ssp_device
*
ssp
;
171
172
ssp = platform_get_drvdata(pdev);
173
if
(ssp ==
NULL
)
174
return
-
ENODEV
;
175
176
iounmap
(ssp->
mmio_base
);
177
178
res =
platform_get_resource
(pdev,
IORESOURCE_MEM
, 0);
179
release_mem_region
(res->
start
, resource_size(res));
180
181
clk_put
(ssp->
clk
);
182
183
mutex_lock
(&ssp_lock);
184
list_del
(&ssp->
node
);
185
mutex_unlock
(&ssp_lock);
186
187
kfree
(ssp);
188
return
0;
189
}
190
191
static
const
struct
platform_device_id
ssp_id_table[] = {
192
{
"pxa25x-ssp"
,
PXA25x_SSP
},
193
{
"pxa25x-nssp"
,
PXA25x_NSSP
},
194
{
"pxa27x-ssp"
,
PXA27x_SSP
},
195
{
"pxa168-ssp"
,
PXA168_SSP
},
196
{
"pxa910-ssp"
,
PXA910_SSP
},
197
{ },
198
};
199
200
static
struct
platform_driver
pxa_ssp_driver = {
201
.probe = pxa_ssp_probe,
202
.remove =
__devexit_p
(pxa_ssp_remove),
203
.driver = {
204
.owner =
THIS_MODULE
,
205
.name =
"pxa2xx-ssp"
,
206
},
207
.id_table = ssp_id_table,
208
};
209
210
static
int
__init
pxa_ssp_init(
void
)
211
{
212
return
platform_driver_register
(&pxa_ssp_driver);
213
}
214
215
static
void
__exit
pxa_ssp_exit(
void
)
216
{
217
platform_driver_unregister
(&pxa_ssp_driver);
218
}
219
220
arch_initcall
(pxa_ssp_init);
221
module_exit
(pxa_ssp_exit);
222
223
MODULE_DESCRIPTION
(
"PXA SSP driver"
);
224
MODULE_AUTHOR
(
"Liam Girdwood"
);
225
MODULE_LICENSE
(
"GPL"
);
Generated on Thu Jan 10 2013 13:01:49 for Linux Kernel by
1.8.2