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
nexedi
linux
Commits
60ab73a2
Commit
60ab73a2
authored
Jun 18, 2015
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spi/topic/omap2-mcspi' into spi-next
parents
5d6ada67
c4339ac7
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
134 additions
and
146 deletions
+134
-146
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-omap2-mcspi.c
+134
-146
No files found.
drivers/spi/spi-omap2-mcspi.c
View file @
60ab73a2
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include <linux/gcd.h>
#include <linux/gcd.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
...
@@ -242,17 +243,27 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
...
@@ -242,17 +243,27 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
mcspi_read_cs_reg
(
spi
,
OMAP2_MCSPI_CHCTRL0
);
mcspi_read_cs_reg
(
spi
,
OMAP2_MCSPI_CHCTRL0
);
}
}
static
void
omap2_mcspi_
force_cs
(
struct
spi_device
*
spi
,
int
cs_activ
e
)
static
void
omap2_mcspi_
set_cs
(
struct
spi_device
*
spi
,
bool
enabl
e
)
{
{
u32
l
;
u32
l
;
/* The controller handles the inverted chip selects
* using the OMAP2_MCSPI_CHCONF_EPOL bit so revert
* the inversion from the core spi_set_cs function.
*/
if
(
spi
->
mode
&
SPI_CS_HIGH
)
enable
=
!
enable
;
if
(
spi
->
controller_state
)
{
l
=
mcspi_cached_chconf0
(
spi
);
l
=
mcspi_cached_chconf0
(
spi
);
if
(
cs_active
)
l
|=
OMAP2_MCSPI_CHCONF_FORCE
;
if
(
enable
)
else
l
&=
~
OMAP2_MCSPI_CHCONF_FORCE
;
l
&=
~
OMAP2_MCSPI_CHCONF_FORCE
;
else
l
|=
OMAP2_MCSPI_CHCONF_FORCE
;
mcspi_write_chconf0
(
spi
,
l
);
mcspi_write_chconf0
(
spi
,
l
);
}
}
}
static
void
omap2_mcspi_set_master_mode
(
struct
spi_master
*
master
)
static
void
omap2_mcspi_set_master_mode
(
struct
spi_master
*
master
)
...
@@ -1011,6 +1022,15 @@ static int omap2_mcspi_setup(struct spi_device *spi)
...
@@ -1011,6 +1022,15 @@ static int omap2_mcspi_setup(struct spi_device *spi)
return
ret
;
return
ret
;
}
}
if
(
gpio_is_valid
(
spi
->
cs_gpio
))
{
ret
=
gpio_request
(
spi
->
cs_gpio
,
dev_name
(
&
spi
->
dev
));
if
(
ret
)
{
dev_err
(
&
spi
->
dev
,
"failed to request gpio
\n
"
);
return
ret
;
}
gpio_direction_output
(
spi
->
cs_gpio
,
!
(
spi
->
mode
&
SPI_CS_HIGH
));
}
ret
=
pm_runtime_get_sync
(
mcspi
->
dev
);
ret
=
pm_runtime_get_sync
(
mcspi
->
dev
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -1050,9 +1070,13 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
...
@@ -1050,9 +1070,13 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
mcspi_dma
->
dma_tx
=
NULL
;
mcspi_dma
->
dma_tx
=
NULL
;
}
}
}
}
if
(
gpio_is_valid
(
spi
->
cs_gpio
))
gpio_free
(
spi
->
cs_gpio
);
}
}
static
void
omap2_mcspi_work
(
struct
omap2_mcspi
*
mcspi
,
struct
spi_message
*
m
)
static
int
omap2_mcspi_work_one
(
struct
omap2_mcspi
*
mcspi
,
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
{
/* We only enable one channel at a time -- the one whose message is
/* We only enable one channel at a time -- the one whose message is
...
@@ -1062,18 +1086,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
...
@@ -1062,18 +1086,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
* chipselect with the FORCE bit ... CS != channel enable.
* chipselect with the FORCE bit ... CS != channel enable.
*/
*/
struct
spi_device
*
spi
;
struct
spi_transfer
*
t
=
NULL
;
struct
spi_master
*
master
;
struct
spi_master
*
master
;
struct
omap2_mcspi_dma
*
mcspi_dma
;
struct
omap2_mcspi_dma
*
mcspi_dma
;
int
cs_active
=
0
;
struct
omap2_mcspi_cs
*
cs
;
struct
omap2_mcspi_cs
*
cs
;
struct
omap2_mcspi_device_config
*
cd
;
struct
omap2_mcspi_device_config
*
cd
;
int
par_override
=
0
;
int
par_override
=
0
;
int
status
=
0
;
int
status
=
0
;
u32
chconf
;
u32
chconf
;
spi
=
m
->
spi
;
master
=
spi
->
master
;
master
=
spi
->
master
;
mcspi_dma
=
mcspi
->
dma_channels
+
spi
->
chip_select
;
mcspi_dma
=
mcspi
->
dma_channels
+
spi
->
chip_select
;
cs
=
spi
->
controller_state
;
cs
=
spi
->
controller_state
;
...
@@ -1090,18 +1110,17 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
...
@@ -1090,18 +1110,17 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
par_override
=
1
;
par_override
=
1
;
omap2_mcspi_set_enable
(
spi
,
0
);
omap2_mcspi_set_enable
(
spi
,
0
);
list_for_each_entry
(
t
,
&
m
->
transfers
,
transfer_list
)
{
if
(
t
->
tx_buf
==
NULL
&&
t
->
rx_buf
==
NULL
&&
t
->
len
)
{
if
(
gpio_is_valid
(
spi
->
cs_gpio
))
status
=
-
EINVAL
;
omap2_mcspi_set_cs
(
spi
,
spi
->
mode
&
SPI_CS_HIGH
);
break
;
}
if
(
par_override
||
if
(
par_override
||
(
t
->
speed_hz
!=
spi
->
max_speed_hz
)
||
(
t
->
speed_hz
!=
spi
->
max_speed_hz
)
||
(
t
->
bits_per_word
!=
spi
->
bits_per_word
))
{
(
t
->
bits_per_word
!=
spi
->
bits_per_word
))
{
par_override
=
1
;
par_override
=
1
;
status
=
omap2_mcspi_setup_transfer
(
spi
,
t
);
status
=
omap2_mcspi_setup_transfer
(
spi
,
t
);
if
(
status
<
0
)
if
(
status
<
0
)
break
;
goto
out
;
if
(
t
->
speed_hz
==
spi
->
max_speed_hz
&&
if
(
t
->
speed_hz
==
spi
->
max_speed_hz
&&
t
->
bits_per_word
==
spi
->
bits_per_word
)
t
->
bits_per_word
==
spi
->
bits_per_word
)
par_override
=
0
;
par_override
=
0
;
...
@@ -1114,12 +1133,6 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
...
@@ -1114,12 +1133,6 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
mcspi_read_cs_reg
(
spi
,
OMAP2_MCSPI_MODULCTRL
);
mcspi_read_cs_reg
(
spi
,
OMAP2_MCSPI_MODULCTRL
);
}
}
if
(
!
cs_active
)
{
omap2_mcspi_force_cs
(
spi
,
1
);
cs_active
=
1
;
}
chconf
=
mcspi_cached_chconf0
(
spi
);
chconf
=
mcspi_cached_chconf0
(
spi
);
chconf
&=
~
OMAP2_MCSPI_CHCONF_TRM_MASK
;
chconf
&=
~
OMAP2_MCSPI_CHCONF_TRM_MASK
;
chconf
&=
~
OMAP2_MCSPI_CHCONF_TURBO
;
chconf
&=
~
OMAP2_MCSPI_CHCONF_TURBO
;
...
@@ -1141,7 +1154,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
...
@@ -1141,7 +1154,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
unsigned
count
;
unsigned
count
;
if
((
mcspi_dma
->
dma_rx
&&
mcspi_dma
->
dma_tx
)
&&
if
((
mcspi_dma
->
dma_rx
&&
mcspi_dma
->
dma_tx
)
&&
(
m
->
is_dma_mapped
||
t
->
len
>=
DMA_MIN_BYTES
))
(
t
->
len
>=
DMA_MIN_BYTES
))
omap2_mcspi_set_fifo
(
spi
,
t
,
1
);
omap2_mcspi_set_fifo
(
spi
,
t
,
1
);
omap2_mcspi_set_enable
(
spi
,
1
);
omap2_mcspi_set_enable
(
spi
,
1
);
...
@@ -1152,41 +1165,29 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
...
@@ -1152,41 +1165,29 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
+
OMAP2_MCSPI_TX0
);
+
OMAP2_MCSPI_TX0
);
if
((
mcspi_dma
->
dma_rx
&&
mcspi_dma
->
dma_tx
)
&&
if
((
mcspi_dma
->
dma_rx
&&
mcspi_dma
->
dma_tx
)
&&
(
m
->
is_dma_mapped
||
t
->
len
>=
DMA_MIN_BYTES
))
(
t
->
len
>=
DMA_MIN_BYTES
))
count
=
omap2_mcspi_txrx_dma
(
spi
,
t
);
count
=
omap2_mcspi_txrx_dma
(
spi
,
t
);
else
else
count
=
omap2_mcspi_txrx_pio
(
spi
,
t
);
count
=
omap2_mcspi_txrx_pio
(
spi
,
t
);
m
->
actual_length
+=
count
;
if
(
count
!=
t
->
len
)
{
if
(
count
!=
t
->
len
)
{
status
=
-
EIO
;
status
=
-
EIO
;
break
;
goto
out
;
}
}
}
if
(
t
->
delay_usecs
)
udelay
(
t
->
delay_usecs
);
/* ignore the "leave it on after last xfer" hint */
if
(
t
->
cs_change
)
{
omap2_mcspi_force_cs
(
spi
,
0
);
cs_active
=
0
;
}
}
omap2_mcspi_set_enable
(
spi
,
0
);
omap2_mcspi_set_enable
(
spi
,
0
);
if
(
mcspi
->
fifo_depth
>
0
)
if
(
mcspi
->
fifo_depth
>
0
)
omap2_mcspi_set_fifo
(
spi
,
t
,
0
);
omap2_mcspi_set_fifo
(
spi
,
t
,
0
);
}
out:
/* Restore defaults if they were overriden */
/* Restore defaults if they were overriden */
if
(
par_override
)
{
if
(
par_override
)
{
par_override
=
0
;
par_override
=
0
;
status
=
omap2_mcspi_setup_transfer
(
spi
,
NULL
);
status
=
omap2_mcspi_setup_transfer
(
spi
,
NULL
);
}
}
if
(
cs_active
)
omap2_mcspi_force_cs
(
spi
,
0
);
if
(
cd
&&
cd
->
cs_per_word
)
{
if
(
cd
&&
cd
->
cs_per_word
)
{
chconf
=
mcspi
->
ctx
.
modulctrl
;
chconf
=
mcspi
->
ctx
.
modulctrl
;
chconf
|=
OMAP2_MCSPI_MODULCTRL_SINGLE
;
chconf
|=
OMAP2_MCSPI_MODULCTRL_SINGLE
;
...
@@ -1197,32 +1198,27 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
...
@@ -1197,32 +1198,27 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
omap2_mcspi_set_enable
(
spi
,
0
);
omap2_mcspi_set_enable
(
spi
,
0
);
if
(
gpio_is_valid
(
spi
->
cs_gpio
))
omap2_mcspi_set_cs
(
spi
,
!
(
spi
->
mode
&
SPI_CS_HIGH
));
if
(
mcspi
->
fifo_depth
>
0
&&
t
)
if
(
mcspi
->
fifo_depth
>
0
&&
t
)
omap2_mcspi_set_fifo
(
spi
,
t
,
0
);
omap2_mcspi_set_fifo
(
spi
,
t
,
0
);
m
->
status
=
status
;
return
status
;
}
}
static
int
omap2_mcspi_transfer_one
_message
(
struct
spi_master
*
master
,
static
int
omap2_mcspi_transfer_one
(
struct
spi_master
*
master
,
struct
spi_
message
*
m
)
struct
spi_
device
*
spi
,
struct
spi_transfer
*
t
)
{
{
struct
spi_device
*
spi
;
struct
omap2_mcspi
*
mcspi
;
struct
omap2_mcspi
*
mcspi
;
struct
omap2_mcspi_dma
*
mcspi_dma
;
struct
omap2_mcspi_dma
*
mcspi_dma
;
struct
spi_transfer
*
t
;
int
status
;
spi
=
m
->
spi
;
mcspi
=
spi_master_get_devdata
(
master
);
mcspi_dma
=
mcspi
->
dma_channels
+
spi
->
chip_select
;
m
->
actual_length
=
0
;
m
->
status
=
0
;
list_for_each_entry
(
t
,
&
m
->
transfers
,
transfer_list
)
{
const
void
*
tx_buf
=
t
->
tx_buf
;
const
void
*
tx_buf
=
t
->
tx_buf
;
void
*
rx_buf
=
t
->
rx_buf
;
void
*
rx_buf
=
t
->
rx_buf
;
unsigned
len
=
t
->
len
;
unsigned
len
=
t
->
len
;
mcspi
=
spi_master_get_devdata
(
master
);
mcspi_dma
=
mcspi
->
dma_channels
+
spi
->
chip_select
;
if
((
len
&&
!
(
rx_buf
||
tx_buf
)))
{
if
((
len
&&
!
(
rx_buf
||
tx_buf
)))
{
dev_dbg
(
mcspi
->
dev
,
"transfer: %d Hz, %d %s%s, %d bpw
\n
"
,
dev_dbg
(
mcspi
->
dev
,
"transfer: %d Hz, %d %s%s, %d bpw
\n
"
,
t
->
speed_hz
,
t
->
speed_hz
,
...
@@ -1230,12 +1226,11 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
...
@@ -1230,12 +1226,11 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
tx_buf
?
"tx"
:
""
,
tx_buf
?
"tx"
:
""
,
rx_buf
?
"rx"
:
""
,
rx_buf
?
"rx"
:
""
,
t
->
bits_per_word
);
t
->
bits_per_word
);
status
=
-
EINVAL
;
return
-
EINVAL
;
goto
out
;
}
}
if
(
m
->
is_dma_mapped
||
len
<
DMA_MIN_BYTES
)
if
(
len
<
DMA_MIN_BYTES
)
continue
;
goto
skip_dma_map
;
if
(
mcspi_dma
->
dma_tx
&&
tx_buf
!=
NULL
)
{
if
(
mcspi_dma
->
dma_tx
&&
tx_buf
!=
NULL
)
{
t
->
tx_dma
=
dma_map_single
(
mcspi
->
dev
,
(
void
*
)
tx_buf
,
t
->
tx_dma
=
dma_map_single
(
mcspi
->
dev
,
(
void
*
)
tx_buf
,
...
@@ -1243,8 +1238,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
...
@@ -1243,8 +1238,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
if
(
dma_mapping_error
(
mcspi
->
dev
,
t
->
tx_dma
))
{
if
(
dma_mapping_error
(
mcspi
->
dev
,
t
->
tx_dma
))
{
dev_dbg
(
mcspi
->
dev
,
"dma %cX %d bytes error
\n
"
,
dev_dbg
(
mcspi
->
dev
,
"dma %cX %d bytes error
\n
"
,
'T'
,
len
);
'T'
,
len
);
status
=
-
EINVAL
;
return
-
EINVAL
;
goto
out
;
}
}
}
}
if
(
mcspi_dma
->
dma_rx
&&
rx_buf
!=
NULL
)
{
if
(
mcspi_dma
->
dma_rx
&&
rx_buf
!=
NULL
)
{
...
@@ -1256,19 +1250,12 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
...
@@ -1256,19 +1250,12 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
if
(
tx_buf
!=
NULL
)
if
(
tx_buf
!=
NULL
)
dma_unmap_single
(
mcspi
->
dev
,
t
->
tx_dma
,
dma_unmap_single
(
mcspi
->
dev
,
t
->
tx_dma
,
len
,
DMA_TO_DEVICE
);
len
,
DMA_TO_DEVICE
);
status
=
-
EINVAL
;
return
-
EINVAL
;
goto
out
;
}
}
}
}
}
omap2_mcspi_work
(
mcspi
,
m
);
skip_dma_map:
/* spi_finalize_current_message() changes the status inside the
return
omap2_mcspi_work_one
(
mcspi
,
spi
,
t
);
* spi_message, save the status here. */
status
=
m
->
status
;
out:
spi_finalize_current_message
(
master
);
return
status
;
}
}
static
int
omap2_mcspi_master_setup
(
struct
omap2_mcspi
*
mcspi
)
static
int
omap2_mcspi_master_setup
(
struct
omap2_mcspi
*
mcspi
)
...
@@ -1347,7 +1334,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
...
@@ -1347,7 +1334,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
4
,
32
);
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
4
,
32
);
master
->
setup
=
omap2_mcspi_setup
;
master
->
setup
=
omap2_mcspi_setup
;
master
->
auto_runtime_pm
=
true
;
master
->
auto_runtime_pm
=
true
;
master
->
transfer_one_message
=
omap2_mcspi_transfer_one_message
;
master
->
transfer_one
=
omap2_mcspi_transfer_one
;
master
->
set_cs
=
omap2_mcspi_set_cs
;
master
->
cleanup
=
omap2_mcspi_cleanup
;
master
->
cleanup
=
omap2_mcspi_cleanup
;
master
->
dev
.
of_node
=
node
;
master
->
dev
.
of_node
=
node
;
master
->
max_speed_hz
=
OMAP2_MCSPI_MAX_FREQ
;
master
->
max_speed_hz
=
OMAP2_MCSPI_MAX_FREQ
;
...
...
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