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
b14a8a80
Commit
b14a8a80
authored
Dec 12, 2016
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'spi/fix/atmel', 'spi/fix/mvbeu' and 'spi/fix/spidev' into spi-linus
parents
69973b83
39fe33f9
7243e0b2
e634b76c
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
99 additions
and
42 deletions
+99
-42
drivers/spi/spi-atmel.c
drivers/spi/spi-atmel.c
+44
-12
drivers/spi/spi-orion.c
drivers/spi/spi-orion.c
+54
-29
tools/spi/spidev_test.c
tools/spi/spidev_test.c
+1
-1
No files found.
drivers/spi/spi-atmel.c
View file @
b14a8a80
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/pm_runtime.h>
...
@@ -295,6 +296,7 @@ struct atmel_spi {
...
@@ -295,6 +296,7 @@ struct atmel_spi {
int
irq
;
int
irq
;
struct
clk
*
clk
;
struct
clk
*
clk
;
struct
platform_device
*
pdev
;
struct
platform_device
*
pdev
;
unsigned
long
spi_clk
;
struct
spi_transfer
*
current_transfer
;
struct
spi_transfer
*
current_transfer
;
int
current_remaining_bytes
;
int
current_remaining_bytes
;
...
@@ -864,7 +866,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
...
@@ -864,7 +866,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
unsigned
long
bus_hz
;
unsigned
long
bus_hz
;
/* v1 chips start out at half the peripheral bus speed. */
/* v1 chips start out at half the peripheral bus speed. */
bus_hz
=
clk_get_rate
(
as
->
clk
)
;
bus_hz
=
as
->
spi_clk
;
if
(
!
atmel_spi_is_v2
(
as
))
if
(
!
atmel_spi_is_v2
(
as
))
bus_hz
/=
2
;
bus_hz
/=
2
;
...
@@ -1204,7 +1206,6 @@ static int atmel_spi_setup(struct spi_device *spi)
...
@@ -1204,7 +1206,6 @@ static int atmel_spi_setup(struct spi_device *spi)
u32
csr
;
u32
csr
;
unsigned
int
bits
=
spi
->
bits_per_word
;
unsigned
int
bits
=
spi
->
bits_per_word
;
unsigned
int
npcs_pin
;
unsigned
int
npcs_pin
;
int
ret
;
as
=
spi_master_get_devdata
(
spi
->
master
);
as
=
spi_master_get_devdata
(
spi
->
master
);
...
@@ -1247,16 +1248,9 @@ static int atmel_spi_setup(struct spi_device *spi)
...
@@ -1247,16 +1248,9 @@ static int atmel_spi_setup(struct spi_device *spi)
if
(
!
asd
)
if
(
!
asd
)
return
-
ENOMEM
;
return
-
ENOMEM
;
if
(
as
->
use_cs_gpios
)
{
if
(
as
->
use_cs_gpios
)
ret
=
gpio_request
(
npcs_pin
,
dev_name
(
&
spi
->
dev
));
if
(
ret
)
{
kfree
(
asd
);
return
ret
;
}
gpio_direction_output
(
npcs_pin
,
gpio_direction_output
(
npcs_pin
,
!
(
spi
->
mode
&
SPI_CS_HIGH
));
!
(
spi
->
mode
&
SPI_CS_HIGH
));
}
asd
->
npcs_pin
=
npcs_pin
;
asd
->
npcs_pin
=
npcs_pin
;
spi
->
controller_state
=
asd
;
spi
->
controller_state
=
asd
;
...
@@ -1471,13 +1465,11 @@ static int atmel_spi_transfer_one_message(struct spi_master *master,
...
@@ -1471,13 +1465,11 @@ static int atmel_spi_transfer_one_message(struct spi_master *master,
static
void
atmel_spi_cleanup
(
struct
spi_device
*
spi
)
static
void
atmel_spi_cleanup
(
struct
spi_device
*
spi
)
{
{
struct
atmel_spi_device
*
asd
=
spi
->
controller_state
;
struct
atmel_spi_device
*
asd
=
spi
->
controller_state
;
unsigned
gpio
=
(
unsigned
long
)
spi
->
controller_data
;
if
(
!
asd
)
if
(
!
asd
)
return
;
return
;
spi
->
controller_state
=
NULL
;
spi
->
controller_state
=
NULL
;
gpio_free
(
gpio
);
kfree
(
asd
);
kfree
(
asd
);
}
}
...
@@ -1499,6 +1491,39 @@ static void atmel_get_caps(struct atmel_spi *as)
...
@@ -1499,6 +1491,39 @@ static void atmel_get_caps(struct atmel_spi *as)
}
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
static
int
atmel_spi_gpio_cs
(
struct
platform_device
*
pdev
)
{
struct
spi_master
*
master
=
platform_get_drvdata
(
pdev
);
struct
atmel_spi
*
as
=
spi_master_get_devdata
(
master
);
struct
device_node
*
np
=
master
->
dev
.
of_node
;
int
i
;
int
ret
=
0
;
int
nb
=
0
;
if
(
!
as
->
use_cs_gpios
)
return
0
;
if
(
!
np
)
return
0
;
nb
=
of_gpio_named_count
(
np
,
"cs-gpios"
);
for
(
i
=
0
;
i
<
nb
;
i
++
)
{
int
cs_gpio
=
of_get_named_gpio
(
pdev
->
dev
.
of_node
,
"cs-gpios"
,
i
);
if
(
cs_gpio
==
-
EPROBE_DEFER
)
return
cs_gpio
;
if
(
gpio_is_valid
(
cs_gpio
))
{
ret
=
devm_gpio_request
(
&
pdev
->
dev
,
cs_gpio
,
dev_name
(
&
pdev
->
dev
));
if
(
ret
)
return
ret
;
}
}
return
0
;
}
static
int
atmel_spi_probe
(
struct
platform_device
*
pdev
)
static
int
atmel_spi_probe
(
struct
platform_device
*
pdev
)
{
{
...
@@ -1577,6 +1602,10 @@ static int atmel_spi_probe(struct platform_device *pdev)
...
@@ -1577,6 +1602,10 @@ static int atmel_spi_probe(struct platform_device *pdev)
master
->
num_chipselect
=
4
;
master
->
num_chipselect
=
4
;
}
}
ret
=
atmel_spi_gpio_cs
(
pdev
);
if
(
ret
)
goto
out_unmap_regs
;
as
->
use_dma
=
false
;
as
->
use_dma
=
false
;
as
->
use_pdc
=
false
;
as
->
use_pdc
=
false
;
if
(
as
->
caps
.
has_dma_support
)
{
if
(
as
->
caps
.
has_dma_support
)
{
...
@@ -1606,6 +1635,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
...
@@ -1606,6 +1635,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
ret
=
clk_prepare_enable
(
clk
);
ret
=
clk_prepare_enable
(
clk
);
if
(
ret
)
if
(
ret
)
goto
out_free_irq
;
goto
out_free_irq
;
as
->
spi_clk
=
clk_get_rate
(
clk
);
spi_writel
(
as
,
CR
,
SPI_BIT
(
SWRST
));
spi_writel
(
as
,
CR
,
SPI_BIT
(
SWRST
));
spi_writel
(
as
,
CR
,
SPI_BIT
(
SWRST
));
/* AT91SAM9263 Rev B workaround */
spi_writel
(
as
,
CR
,
SPI_BIT
(
SWRST
));
/* AT91SAM9263 Rev B workaround */
if
(
as
->
caps
.
has_wdrbt
)
{
if
(
as
->
caps
.
has_wdrbt
)
{
...
...
drivers/spi/spi-orion.c
View file @
b14a8a80
...
@@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
...
@@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
tclk_hz
=
clk_get_rate
(
orion_spi
->
clk
);
tclk_hz
=
clk_get_rate
(
orion_spi
->
clk
);
if
(
devdata
->
typ
==
ARMADA_SPI
)
{
if
(
devdata
->
typ
==
ARMADA_SPI
)
{
unsigned
int
clk
,
spr
,
sppr
,
sppr2
,
err
;
/*
unsigned
int
best_spr
,
best_sppr
,
best_err
;
* Given the core_clk (tclk_hz) and the target rate (speed) we
* determine the best values for SPR (in [0 .. 15]) and SPPR (in
* [0..7]) such that
*
* core_clk / (SPR * 2 ** SPPR)
*
* is as big as possible but not bigger than speed.
*/
best_err
=
speed
;
/* best integer divider: */
best_spr
=
0
;
unsigned
divider
=
DIV_ROUND_UP
(
tclk_hz
,
speed
)
;
best_sppr
=
0
;
unsigned
spr
,
sppr
;
/* Iterate over the valid range looking for best fit */
if
(
divider
<
16
)
{
for
(
sppr
=
0
;
sppr
<
8
;
sppr
++
)
{
/* This is the easy case, divider is less than 16 */
sppr2
=
0x1
<<
sppr
;
spr
=
divider
;
sppr
=
0
;
spr
=
tclk_hz
/
sppr2
;
}
else
{
spr
=
DIV_ROUND_UP
(
spr
,
speed
);
unsigned
two_pow_sppr
;
if
((
spr
==
0
)
||
(
spr
>
15
))
/*
continue
;
* Find the highest bit set in divider. This and the
* three next bits define SPR (apart from rounding).
* SPPR is then the number of zero bits that must be
* appended:
*/
sppr
=
fls
(
divider
)
-
4
;
clk
=
tclk_hz
/
(
spr
*
sppr2
);
/*
err
=
speed
-
clk
;
* As SPR only has 4 bits, we have to round divider up
* to the next multiple of 2 ** sppr.
*/
two_pow_sppr
=
1
<<
sppr
;
divider
=
(
divider
+
two_pow_sppr
-
1
)
&
-
two_pow_sppr
;
if
(
err
<
best_err
)
{
/*
best_spr
=
spr
;
* recalculate sppr as rounding up divider might have
best_sppr
=
sppr
;
* increased it enough to change the position of the
best_err
=
err
;
* highest set bit. In this case the bit that now
}
* doesn't make it into SPR is 0, so there is no need to
}
* round again.
*/
sppr
=
fls
(
divider
)
-
4
;
spr
=
divider
>>
sppr
;
if
((
best_sppr
==
0
)
&&
(
best_spr
==
0
))
/*
* Now do range checking. SPR is constructed to have a
* width of 4 bits, so this is fine for sure. So we
* still need to check for sppr to fit into 3 bits:
*/
if
(
sppr
>
7
)
return
-
EINVAL
;
return
-
EINVAL
;
}
prescale
=
((
best_sppr
&
0x6
)
<<
5
)
|
prescale
=
((
sppr
&
0x6
)
<<
5
)
|
((
sppr
&
0x1
)
<<
4
)
|
spr
;
((
best_sppr
&
0x1
)
<<
4
)
|
best_spr
;
}
else
{
}
else
{
/*
/*
* the supported rates are: 4,6,8...30
* the supported rates are: 4,6,8...30
...
...
tools/spi/spidev_test.c
View file @
b14a8a80
...
@@ -315,7 +315,7 @@ static void transfer_file(int fd, char *filename)
...
@@ -315,7 +315,7 @@ static void transfer_file(int fd, char *filename)
pabort
(
"can't stat input file"
);
pabort
(
"can't stat input file"
);
tx_fd
=
open
(
filename
,
O_RDONLY
);
tx_fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
<
0
)
if
(
tx_
fd
<
0
)
pabort
(
"can't open input file"
);
pabort
(
"can't open input file"
);
tx
=
malloc
(
sb
.
st_size
);
tx
=
malloc
(
sb
.
st_size
);
...
...
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