Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
4374f332
Commit
4374f332
authored
Sep 01, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spi/topic/omap-100k' into spi-next
parents
45bb5065
2d0c6148
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
78 additions
and
198 deletions
+78
-198
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap-100k.c
+78
-198
No files found.
drivers/spi/spi-omap-100k.c
View file @
4374f332
...
...
@@ -83,11 +83,6 @@
#define SPI_SHUTDOWN 1
struct
omap1_spi100k
{
struct
work_struct
work
;
/* lock protects queue and registers */
spinlock_t
lock
;
struct
list_head
msg_queue
;
struct
spi_master
*
master
;
struct
clk
*
ick
;
struct
clk
*
fck
;
...
...
@@ -104,8 +99,6 @@ struct omap1_spi100k_cs {
int
word_len
;
};
static
struct
workqueue_struct
*
omap1_spi100k_wq
;
#define MOD_REG_BIT(val, mask, set) do { \
if (set) \
val |= mask; \
...
...
@@ -310,50 +303,36 @@ static int omap1_spi100k_setup(struct spi_device *spi)
spi100k_open
(
spi
->
master
);
clk_enable
(
spi100k
->
ick
);
clk_enable
(
spi100k
->
fck
);
clk_
prepare_
enable
(
spi100k
->
ick
);
clk_
prepare_
enable
(
spi100k
->
fck
);
ret
=
omap1_spi100k_setup_transfer
(
spi
,
NULL
);
clk_disable
(
spi100k
->
ick
);
clk_disable
(
spi100k
->
fck
);
clk_disable
_unprepare
(
spi100k
->
ick
);
clk_disable
_unprepare
(
spi100k
->
fck
);
return
ret
;
}
static
void
omap1_spi100k_work
(
struct
work_struct
*
work
)
static
int
omap1_spi100k_prepare_hardware
(
struct
spi_master
*
master
)
{
struct
omap1_spi100k
*
spi100k
;
int
status
=
0
;
struct
omap1_spi100k
*
spi100k
=
spi_master_get_devdata
(
master
);
spi100k
=
container_of
(
work
,
struct
omap1_spi100k
,
wor
k
);
spin_lock_irq
(
&
spi100k
->
lo
ck
);
clk_prepare_enable
(
spi100k
->
ic
k
);
clk_prepare_enable
(
spi100k
->
f
ck
);
clk_enable
(
spi100k
->
ick
)
;
clk_enable
(
spi100k
->
fck
);
return
0
;
}
/* We only enable one channel at a time -- the one whose message is
* at the head of the queue -- although this controller would gladly
* arbitrate among multiple channels. This corresponds to "single
* channel" master mode. As a side effect, we need to manage the
* chipselect with the FORCE bit ... CS != channel enable.
*/
while
(
!
list_empty
(
&
spi100k
->
msg_queue
))
{
struct
spi_message
*
m
;
struct
spi_device
*
spi
;
static
int
omap1_spi100k_transfer_one_message
(
struct
spi_master
*
master
,
struct
spi_message
*
m
)
{
struct
omap1_spi100k
*
spi100k
=
spi_master_get_devdata
(
master
);
struct
spi_device
*
spi
=
m
->
spi
;
struct
spi_transfer
*
t
=
NULL
;
int
cs_active
=
0
;
struct
omap1_spi100k_cs
*
cs
;
int
par_override
=
0
;
m
=
container_of
(
spi100k
->
msg_queue
.
next
,
struct
spi_message
,
queue
);
list_del_init
(
&
m
->
queue
);
spin_unlock_irq
(
&
spi100k
->
lock
);
spi
=
m
->
spi
;
cs
=
spi
->
controller_state
;
int
status
=
0
;
list_for_each_entry
(
t
,
&
m
->
transfers
,
transfer_list
)
{
if
(
t
->
tx_buf
==
NULL
&&
t
->
rx_buf
==
NULL
&&
t
->
len
)
{
...
...
@@ -407,73 +386,19 @@ static void omap1_spi100k_work(struct work_struct *work)
omap1_spi100k_force_cs
(
spi100k
,
0
);
m
->
status
=
status
;
m
->
complete
(
m
->
context
);
spin_lock_irq
(
&
spi100k
->
lock
);
}
spi_finalize_current_message
(
master
);
clk_disable
(
spi100k
->
ick
);
clk_disable
(
spi100k
->
fck
);
spin_unlock_irq
(
&
spi100k
->
lock
);
if
(
status
<
0
)
printk
(
KERN_WARNING
"spi transfer failed with %d
\n
"
,
status
);
return
status
;
}
static
int
omap1_spi100k_
transfer
(
struct
spi_device
*
spi
,
struct
spi_message
*
m
)
static
int
omap1_spi100k_
unprepare_hardware
(
struct
spi_master
*
master
)
{
struct
omap1_spi100k
*
spi100k
;
unsigned
long
flags
;
struct
spi_transfer
*
t
;
m
->
actual_length
=
0
;
m
->
status
=
-
EINPROGRESS
;
spi100k
=
spi_master_get_devdata
(
spi
->
master
);
/* Don't accept new work if we're shutting down */
if
(
spi100k
->
state
==
SPI_SHUTDOWN
)
return
-
ESHUTDOWN
;
/* reject invalid messages and transfers */
if
(
list_empty
(
&
m
->
transfers
)
||
!
m
->
complete
)
return
-
EINVAL
;
list_for_each_entry
(
t
,
&
m
->
transfers
,
transfer_list
)
{
const
void
*
tx_buf
=
t
->
tx_buf
;
void
*
rx_buf
=
t
->
rx_buf
;
unsigned
len
=
t
->
len
;
if
(
t
->
speed_hz
>
OMAP1_SPI100K_MAX_FREQ
||
(
len
&&
!
(
rx_buf
||
tx_buf
)))
{
dev_dbg
(
&
spi
->
dev
,
"transfer: %d Hz, %d %s%s, %d bpw
\n
"
,
t
->
speed_hz
,
len
,
tx_buf
?
"tx"
:
""
,
rx_buf
?
"rx"
:
""
,
t
->
bits_per_word
);
return
-
EINVAL
;
}
if
(
t
->
speed_hz
&&
t
->
speed_hz
<
OMAP1_SPI100K_MAX_FREQ
/
(
1
<<
16
))
{
dev_dbg
(
&
spi
->
dev
,
"%d Hz max exceeds %d
\n
"
,
t
->
speed_hz
,
OMAP1_SPI100K_MAX_FREQ
/
(
1
<<
16
));
return
-
EINVAL
;
}
}
spin_lock_irqsave
(
&
spi100k
->
lock
,
flags
);
list_add_tail
(
&
m
->
queue
,
&
spi100k
->
msg_queue
);
queue_work
(
omap1_spi100k_wq
,
&
spi100k
->
work
);
spin_unlock_irqrestore
(
&
spi100k
->
lock
,
flags
);
struct
omap1_spi100k
*
spi100k
=
spi_master_get_devdata
(
master
);
return
0
;
}
clk_disable_unprepare
(
spi100k
->
ick
)
;
clk_disable_unprepare
(
spi100k
->
fck
);
static
int
omap1_spi100k_reset
(
struct
omap1_spi100k
*
spi100k
)
{
return
0
;
}
...
...
@@ -496,11 +421,15 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
master
->
bus_num
=
pdev
->
id
;
master
->
setup
=
omap1_spi100k_setup
;
master
->
transfer
=
omap1_spi100k_transfer
;
master
->
transfer_one_message
=
omap1_spi100k_transfer_one_message
;
master
->
prepare_transfer_hardware
=
omap1_spi100k_prepare_hardware
;
master
->
unprepare_transfer_hardware
=
omap1_spi100k_unprepare_hardware
;
master
->
cleanup
=
NULL
;
master
->
num_chipselect
=
2
;
master
->
mode_bits
=
MODEBITS
;
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
4
,
32
);
master
->
min_speed_hz
=
OMAP1_SPI100K_MAX_FREQ
/
(
1
<<
16
);
master
->
max_speed_hz
=
OMAP1_SPI100K_MAX_FREQ
;
platform_set_drvdata
(
pdev
,
master
);
...
...
@@ -514,40 +443,29 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
*/
spi100k
->
base
=
(
void
__iomem
*
)
pdev
->
dev
.
platform_data
;
INIT_WORK
(
&
spi100k
->
work
,
omap1_spi100k_work
);
spin_lock_init
(
&
spi100k
->
lock
);
INIT_LIST_HEAD
(
&
spi100k
->
msg_queue
);
spi100k
->
ick
=
clk_get
(
&
pdev
->
dev
,
"ick"
);
spi100k
->
ick
=
devm_clk_get
(
&
pdev
->
dev
,
"ick"
);
if
(
IS_ERR
(
spi100k
->
ick
))
{
dev_dbg
(
&
pdev
->
dev
,
"can't get spi100k_ick
\n
"
);
status
=
PTR_ERR
(
spi100k
->
ick
);
goto
err
1
;
goto
err
;
}
spi100k
->
fck
=
clk_get
(
&
pdev
->
dev
,
"fck"
);
spi100k
->
fck
=
devm_
clk_get
(
&
pdev
->
dev
,
"fck"
);
if
(
IS_ERR
(
spi100k
->
fck
))
{
dev_dbg
(
&
pdev
->
dev
,
"can't get spi100k_fck
\n
"
);
status
=
PTR_ERR
(
spi100k
->
fck
);
goto
err
2
;
goto
err
;
}
if
(
omap1_spi100k_reset
(
spi100k
)
<
0
)
goto
err3
;
status
=
spi_register_master
(
master
);
if
(
status
<
0
)
goto
err
3
;
goto
err
;
spi100k
->
state
=
SPI_RUNNING
;
return
status
;
err3:
clk_put
(
spi100k
->
fck
);
err2:
clk_put
(
spi100k
->
ick
);
err1:
err:
spi_master_put
(
master
);
return
status
;
}
...
...
@@ -557,33 +475,14 @@ static int omap1_spi100k_remove(struct platform_device *pdev)
struct
spi_master
*
master
;
struct
omap1_spi100k
*
spi100k
;
struct
resource
*
r
;
unsigned
limit
=
500
;
unsigned
long
flags
;
int
status
=
0
;
master
=
platform_get_drvdata
(
pdev
);
spi100k
=
spi_master_get_devdata
(
master
);
spin_lock_irqsave
(
&
spi100k
->
lock
,
flags
);
spi100k
->
state
=
SPI_SHUTDOWN
;
while
(
!
list_empty
(
&
spi100k
->
msg_queue
)
&&
limit
--
)
{
spin_unlock_irqrestore
(
&
spi100k
->
lock
,
flags
);
msleep
(
10
);
spin_lock_irqsave
(
&
spi100k
->
lock
,
flags
);
}
if
(
!
list_empty
(
&
spi100k
->
msg_queue
))
status
=
-
EBUSY
;
spin_unlock_irqrestore
(
&
spi100k
->
lock
,
flags
);
if
(
status
!=
0
)
return
status
;
clk_put
(
spi100k
->
fck
);
clk_put
(
spi100k
->
ick
);
r
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
spi_unregister_master
(
master
);
...
...
@@ -596,30 +495,11 @@ static struct platform_driver omap1_spi100k_driver = {
.
name
=
"omap1_spi100k"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
omap1_spi100k_probe
,
.
remove
=
omap1_spi100k_remove
,
};
static
int
__init
omap1_spi100k_init
(
void
)
{
omap1_spi100k_wq
=
create_singlethread_workqueue
(
omap1_spi100k_driver
.
driver
.
name
);
if
(
omap1_spi100k_wq
==
NULL
)
return
-
1
;
return
platform_driver_probe
(
&
omap1_spi100k_driver
,
omap1_spi100k_probe
);
}
static
void
__exit
omap1_spi100k_exit
(
void
)
{
platform_driver_unregister
(
&
omap1_spi100k_driver
);
destroy_workqueue
(
omap1_spi100k_wq
);
}
module_init
(
omap1_spi100k_init
);
module_exit
(
omap1_spi100k_exit
);
module_platform_driver
(
omap1_spi100k_driver
);
MODULE_DESCRIPTION
(
"OMAP7xx SPI 100k controller driver"
);
MODULE_AUTHOR
(
"Fabrice Crohas <fcrohas@gmail.com>"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment