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
85cac431
Commit
85cac431
authored
Sep 01, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spi/topic/qspi' into spi-next
parents
793b3cb6
b6460366
Changes
16
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
757 additions
and
136 deletions
+757
-136
Documentation/devicetree/bindings/spi/ti_qspi.txt
Documentation/devicetree/bindings/spi/ti_qspi.txt
+22
-0
drivers/spi/Kconfig
drivers/spi/Kconfig
+8
-0
drivers/spi/Makefile
drivers/spi/Makefile
+1
-0
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bcm63xx.c
+1
-20
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-coldfire-qspi.c
+1
-20
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-omap2-mcspi.c
+1
-19
drivers/spi/spi-pl022.c
drivers/spi/spi-pl022.c
+1
-20
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-pxa2xx.c
+1
-11
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-s3c64xx.c
+1
-3
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-sh-hspi.c
+1
-17
drivers/spi/spi-tegra114.c
drivers/spi/spi-tegra114.c
+1
-9
drivers/spi/spi-tegra20-sflash.c
drivers/spi/spi-tegra20-sflash.c
+1
-7
drivers/spi/spi-tegra20-slink.c
drivers/spi/spi-tegra20-slink.c
+1
-7
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-ti-qspi.c
+574
-0
drivers/spi/spi.c
drivers/spi/spi.c
+117
-1
include/linux/spi/spi.h
include/linux/spi/spi.h
+25
-2
No files found.
Documentation/devicetree/bindings/spi/ti_qspi.txt
0 → 100644
View file @
85cac431
TI QSPI controller.
Required properties:
- compatible : should be "ti,dra7xxx-qspi" or "ti,am4372-qspi".
- reg: Should contain QSPI registers location and length.
- #address-cells, #size-cells : Must be present if the device has sub-nodes
- ti,hwmods: Name of the hwmod associated to the QSPI
Recommended properties:
- spi-max-frequency: Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
qspi: qspi@4b300000 {
compatible = "ti,dra7xxx-qspi";
reg = <0x4b300000 0x100>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <25000000>;
ti,hwmods = "qspi";
};
drivers/spi/Kconfig
View file @
85cac431
...
...
@@ -306,6 +306,14 @@ config SPI_OMAP24XX
SPI master controller for OMAP24XX and later Multichannel SPI
(McSPI) modules.
config SPI_TI_QSPI
tristate "DRA7xxx QSPI controller support"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
QSPI master controller for DRA7xxx used for flash devices.
This device supports single, dual and quad read support, while
it only supports single write mode.
config SPI_OMAP_100K
tristate "OMAP SPI 100K"
depends on ARCH_OMAP850 || ARCH_OMAP730 || COMPILE_TEST
...
...
drivers/spi/Makefile
View file @
85cac431
...
...
@@ -49,6 +49,7 @@ obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o
obj-$(CONFIG_SPI_OMAP_UWIRE)
+=
spi-omap-uwire.o
obj-$(CONFIG_SPI_OMAP_100K)
+=
spi-omap-100k.o
obj-$(CONFIG_SPI_OMAP24XX)
+=
spi-omap2-mcspi.o
obj-$(CONFIG_SPI_TI_QSPI)
+=
spi-ti-qspi.o
obj-$(CONFIG_SPI_ORION)
+=
spi-orion.o
obj-$(CONFIG_SPI_PL022)
+=
spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx)
+=
spi-ppc4xx.o
...
...
drivers/spi/spi-bcm63xx.c
View file @
85cac431
...
...
@@ -231,24 +231,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
return
0
;
}
static
int
bcm63xx_spi_prepare_transfer
(
struct
spi_master
*
master
)
{
struct
bcm63xx_spi
*
bs
=
spi_master_get_devdata
(
master
);
pm_runtime_get_sync
(
&
bs
->
pdev
->
dev
);
return
0
;
}
static
int
bcm63xx_spi_unprepare_transfer
(
struct
spi_master
*
master
)
{
struct
bcm63xx_spi
*
bs
=
spi_master_get_devdata
(
master
);
pm_runtime_put
(
&
bs
->
pdev
->
dev
);
return
0
;
}
static
int
bcm63xx_spi_transfer_one
(
struct
spi_master
*
master
,
struct
spi_message
*
m
)
{
...
...
@@ -406,11 +388,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
master
->
bus_num
=
pdata
->
bus_num
;
master
->
num_chipselect
=
pdata
->
num_chipselect
;
master
->
prepare_transfer_hardware
=
bcm63xx_spi_prepare_transfer
;
master
->
unprepare_transfer_hardware
=
bcm63xx_spi_unprepare_transfer
;
master
->
transfer_one_message
=
bcm63xx_spi_transfer_one
;
master
->
mode_bits
=
MODEBITS
;
master
->
bits_per_word_mask
=
SPI_BPW_MASK
(
8
);
master
->
auto_runtime_pm
=
true
;
bs
->
msg_type_shift
=
pdata
->
msg_type_shift
;
bs
->
msg_ctl_width
=
pdata
->
msg_ctl_width
;
bs
->
tx_io
=
(
u8
*
)(
bs
->
regs
+
bcm63xx_spireg
(
SPI_MSG_DATA
));
...
...
drivers/spi/spi-coldfire-qspi.c
View file @
85cac431
...
...
@@ -354,24 +354,6 @@ static int mcfqspi_transfer_one_message(struct spi_master *master,
}
static
int
mcfqspi_prepare_transfer_hw
(
struct
spi_master
*
master
)
{
struct
mcfqspi
*
mcfqspi
=
spi_master_get_devdata
(
master
);
pm_runtime_get_sync
(
mcfqspi
->
dev
);
return
0
;
}
static
int
mcfqspi_unprepare_transfer_hw
(
struct
spi_master
*
master
)
{
struct
mcfqspi
*
mcfqspi
=
spi_master_get_devdata
(
master
);
pm_runtime_put_sync
(
mcfqspi
->
dev
);
return
0
;
}
static
int
mcfqspi_setup
(
struct
spi_device
*
spi
)
{
if
(
spi
->
chip_select
>=
spi
->
master
->
num_chipselect
)
{
...
...
@@ -473,8 +455,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
8
,
16
);
master
->
setup
=
mcfqspi_setup
;
master
->
transfer_one_message
=
mcfqspi_transfer_one_message
;
master
->
prepare_transfer_hardware
=
mcfqspi_prepare_transfer_hw
;
master
->
unprepare_transfer_hardware
=
mcfqspi_unprepare_transfer_hw
;
master
->
auto_runtime_pm
=
true
;
platform_set_drvdata
(
pdev
,
master
);
...
...
drivers/spi/spi-omap2-mcspi.c
View file @
85cac431
...
...
@@ -335,23 +335,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
__raw_writel
(
cs
->
chconf0
,
cs
->
base
+
OMAP2_MCSPI_CHCONF0
);
}
static
int
omap2_prepare_transfer
(
struct
spi_master
*
master
)
{
struct
omap2_mcspi
*
mcspi
=
spi_master_get_devdata
(
master
);
pm_runtime_get_sync
(
mcspi
->
dev
);
return
0
;
}
static
int
omap2_unprepare_transfer
(
struct
spi_master
*
master
)
{
struct
omap2_mcspi
*
mcspi
=
spi_master_get_devdata
(
master
);
pm_runtime_mark_last_busy
(
mcspi
->
dev
);
pm_runtime_put_autosuspend
(
mcspi
->
dev
);
return
0
;
}
static
int
mcspi_wait_for_reg_bit
(
void
__iomem
*
reg
,
unsigned
long
bit
)
{
unsigned
long
timeout
;
...
...
@@ -1318,8 +1301,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
4
,
32
);
master
->
setup
=
omap2_mcspi_setup
;
master
->
prepare_transfer_hardware
=
omap2_prepare_transfer
;
master
->
unprepare_transfer_hardware
=
omap2_unprepare_transfer
;
master
->
auto_runtime_pm
=
true
;
master
->
transfer_one_message
=
omap2_mcspi_transfer_one_message
;
master
->
cleanup
=
omap2_mcspi_cleanup
;
master
->
dev
.
of_node
=
node
;
...
...
drivers/spi/spi-pl022.c
View file @
85cac431
...
...
@@ -1555,18 +1555,6 @@ static int pl022_transfer_one_message(struct spi_master *master,
return
0
;
}
static
int
pl022_prepare_transfer_hardware
(
struct
spi_master
*
master
)
{
struct
pl022
*
pl022
=
spi_master_get_devdata
(
master
);
/*
* Just make sure we have all we need to run the transfer by syncing
* with the runtime PM framework.
*/
pm_runtime_get_sync
(
&
pl022
->
adev
->
dev
);
return
0
;
}
static
int
pl022_unprepare_transfer_hardware
(
struct
spi_master
*
master
)
{
struct
pl022
*
pl022
=
spi_master_get_devdata
(
master
);
...
...
@@ -1575,13 +1563,6 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
writew
((
readw
(
SSP_CR1
(
pl022
->
virtbase
))
&
(
~
SSP_CR1_MASK_SSE
)),
SSP_CR1
(
pl022
->
virtbase
));
if
(
pl022
->
master_info
->
autosuspend_delay
>
0
)
{
pm_runtime_mark_last_busy
(
&
pl022
->
adev
->
dev
);
pm_runtime_put_autosuspend
(
&
pl022
->
adev
->
dev
);
}
else
{
pm_runtime_put
(
&
pl022
->
adev
->
dev
);
}
return
0
;
}
...
...
@@ -2140,7 +2121,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
master
->
num_chipselect
=
num_cs
;
master
->
cleanup
=
pl022_cleanup
;
master
->
setup
=
pl022_setup
;
master
->
prepare_transfer_hardware
=
pl022_prepare_transfer_hardwar
e
;
master
->
auto_runtime_pm
=
tru
e
;
master
->
transfer_one_message
=
pl022_transfer_one_message
;
master
->
unprepare_transfer_hardware
=
pl022_unprepare_transfer_hardware
;
master
->
rt
=
platform_info
->
rt
;
...
...
drivers/spi/spi-pxa2xx.c
View file @
85cac431
...
...
@@ -811,14 +811,6 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
return
0
;
}
static
int
pxa2xx_spi_prepare_transfer
(
struct
spi_master
*
master
)
{
struct
driver_data
*
drv_data
=
spi_master_get_devdata
(
master
);
pm_runtime_get_sync
(
&
drv_data
->
pdev
->
dev
);
return
0
;
}
static
int
pxa2xx_spi_unprepare_transfer
(
struct
spi_master
*
master
)
{
struct
driver_data
*
drv_data
=
spi_master_get_devdata
(
master
);
...
...
@@ -827,8 +819,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
write_SSCR0
(
read_SSCR0
(
drv_data
->
ioaddr
)
&
~
SSCR0_SSE
,
drv_data
->
ioaddr
);
pm_runtime_mark_last_busy
(
&
drv_data
->
pdev
->
dev
);
pm_runtime_put_autosuspend
(
&
drv_data
->
pdev
->
dev
);
return
0
;
}
...
...
@@ -1141,8 +1131,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master
->
cleanup
=
cleanup
;
master
->
setup
=
setup
;
master
->
transfer_one_message
=
pxa2xx_spi_transfer_one_message
;
master
->
prepare_transfer_hardware
=
pxa2xx_spi_prepare_transfer
;
master
->
unprepare_transfer_hardware
=
pxa2xx_spi_unprepare_transfer
;
master
->
auto_runtime_pm
=
true
;
drv_data
->
ssp_type
=
ssp
->
type
;
drv_data
->
null_dma_buf
=
(
u32
*
)
PTR_ALIGN
(
&
drv_data
[
1
],
DMA_ALIGNMENT
);
...
...
drivers/spi/spi-s3c64xx.c
View file @
85cac431
...
...
@@ -356,8 +356,6 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
while
(
!
is_polling
(
sdd
)
&&
!
acquire_dma
(
sdd
))
usleep_range
(
10000
,
11000
);
pm_runtime_get_sync
(
&
sdd
->
pdev
->
dev
);
return
0
;
}
...
...
@@ -372,7 +370,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
sdd
->
ops
->
release
((
enum
dma_ch
)
sdd
->
tx_dma
.
ch
,
&
s3c64xx_spi_dma_client
);
}
pm_runtime_put
(
&
sdd
->
pdev
->
dev
);
return
0
;
}
...
...
@@ -1395,6 +1392,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
SPI_BPW_MASK
(
8
);
/* the spi->mode bits understood by this driver: */
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
auto_runtime_pm
=
true
;
sdd
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
mem_res
);
if
(
IS_ERR
(
sdd
->
regs
))
{
...
...
drivers/spi/spi-sh-hspi.c
View file @
85cac431
...
...
@@ -99,21 +99,6 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
/*
* spi master function
*/
static
int
hspi_prepare_transfer
(
struct
spi_master
*
master
)
{
struct
hspi_priv
*
hspi
=
spi_master_get_devdata
(
master
);
pm_runtime_get_sync
(
hspi
->
dev
);
return
0
;
}
static
int
hspi_unprepare_transfer
(
struct
spi_master
*
master
)
{
struct
hspi_priv
*
hspi
=
spi_master_get_devdata
(
master
);
pm_runtime_put_sync
(
hspi
->
dev
);
return
0
;
}
#define hspi_hw_cs_enable(hspi) hspi_hw_cs_ctrl(hspi, 0)
#define hspi_hw_cs_disable(hspi) hspi_hw_cs_ctrl(hspi, 1)
...
...
@@ -316,9 +301,8 @@ static int hspi_probe(struct platform_device *pdev)
master
->
setup
=
hspi_setup
;
master
->
cleanup
=
hspi_cleanup
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
;
master
->
prepare_transfer_hardware
=
hspi_prepare_transfer
;
master
->
auto_runtime_pm
=
true
;
master
->
transfer_one_message
=
hspi_transfer_one_message
;
master
->
unprepare_transfer_hardware
=
hspi_unprepare_transfer
;
ret
=
spi_register_master
(
master
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"spi_register_master error.
\n
"
);
...
...
drivers/spi/spi-tegra114.c
View file @
85cac431
...
...
@@ -816,14 +816,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
msg
->
status
=
0
;
msg
->
actual_length
=
0
;
ret
=
pm_runtime_get_sync
(
tspi
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
tspi
->
dev
,
"runtime PM get failed: %d
\n
"
,
ret
);
msg
->
status
=
ret
;
spi_finalize_current_message
(
master
);
return
ret
;
}
single_xfer
=
list_is_singular
(
&
msg
->
transfers
);
list_for_each_entry
(
xfer
,
&
msg
->
transfers
,
transfer_list
)
{
INIT_COMPLETION
(
tspi
->
xfer_completion
);
...
...
@@ -859,7 +851,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
ret
=
0
;
exit:
tegra_spi_writel
(
tspi
,
tspi
->
def_command1_reg
,
SPI_COMMAND1
);
pm_runtime_put
(
tspi
->
dev
);
msg
->
status
=
ret
;
spi_finalize_current_message
(
master
);
return
ret
;
...
...
@@ -1053,6 +1044,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
master
->
transfer_one_message
=
tegra_spi_transfer_one_message
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
bus_num
=
-
1
;
master
->
auto_runtime_pm
=
true
;
tspi
->
master
=
master
;
tspi
->
dev
=
&
pdev
->
dev
;
...
...
drivers/spi/spi-tegra20-sflash.c
View file @
85cac431
...
...
@@ -335,12 +335,6 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master,
struct
spi_device
*
spi
=
msg
->
spi
;
int
ret
;
ret
=
pm_runtime_get_sync
(
tsd
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
tsd
->
dev
,
"pm_runtime_get() failed, err = %d
\n
"
,
ret
);
return
ret
;
}
msg
->
status
=
0
;
msg
->
actual_length
=
0
;
single_xfer
=
list_is_singular
(
&
msg
->
transfers
);
...
...
@@ -380,7 +374,6 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master,
tegra_sflash_writel
(
tsd
,
tsd
->
def_command_reg
,
SPI_COMMAND
);
msg
->
status
=
ret
;
spi_finalize_current_message
(
master
);
pm_runtime_put
(
tsd
->
dev
);
return
ret
;
}
...
...
@@ -477,6 +470,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
;
master
->
setup
=
tegra_sflash_setup
;
master
->
transfer_one_message
=
tegra_sflash_transfer_one_message
;
master
->
auto_runtime_pm
=
true
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
bus_num
=
-
1
;
...
...
drivers/spi/spi-tegra20-slink.c
View file @
85cac431
...
...
@@ -836,11 +836,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
msg
->
status
=
0
;
msg
->
actual_length
=
0
;
ret
=
pm_runtime_get_sync
(
tspi
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
tspi
->
dev
,
"runtime get failed: %d
\n
"
,
ret
);
goto
done
;
}
single_xfer
=
list_is_singular
(
&
msg
->
transfers
);
list_for_each_entry
(
xfer
,
&
msg
->
transfers
,
transfer_list
)
{
...
...
@@ -878,8 +873,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
exit:
tegra_slink_writel
(
tspi
,
tspi
->
def_command_reg
,
SLINK_COMMAND
);
tegra_slink_writel
(
tspi
,
tspi
->
def_command2_reg
,
SLINK_COMMAND2
);
pm_runtime_put
(
tspi
->
dev
);
done:
msg
->
status
=
ret
;
spi_finalize_current_message
(
master
);
return
ret
;
...
...
@@ -1086,6 +1079,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
setup
=
tegra_slink_setup
;
master
->
transfer_one_message
=
tegra_slink_transfer_one_message
;
master
->
auto_runtime_pm
=
true
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
bus_num
=
-
1
;
...
...
drivers/spi/spi-ti-qspi.c
0 → 100644
View file @
85cac431
This diff is collapsed.
Click to expand it.
drivers/spi/spi.c
View file @
85cac431
...
...
@@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work)
master
->
unprepare_transfer_hardware
(
master
))
dev_err
(
&
master
->
dev
,
"failed to unprepare transfer hardware
\n
"
);
if
(
master
->
auto_runtime_pm
)
{
pm_runtime_mark_last_busy
(
master
->
dev
.
parent
);
pm_runtime_put_autosuspend
(
master
->
dev
.
parent
);
}
return
;
}
...
...
@@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work)
master
->
busy
=
true
;
spin_unlock_irqrestore
(
&
master
->
queue_lock
,
flags
);
if
(
!
was_busy
&&
master
->
auto_runtime_pm
)
{
ret
=
pm_runtime_get_sync
(
master
->
dev
.
parent
);
if
(
ret
<
0
)
{
dev_err
(
&
master
->
dev
,
"Failed to power device: %d
\n
"
,
ret
);
return
;
}
}
if
(
!
was_busy
&&
master
->
prepare_transfer_hardware
)
{
ret
=
master
->
prepare_transfer_hardware
(
master
);
if
(
ret
)
{
dev_err
(
&
master
->
dev
,
"failed to prepare transfer hardware
\n
"
);
if
(
master
->
auto_runtime_pm
)
pm_runtime_put
(
master
->
dev
.
parent
);
return
;
}
}
...
...
@@ -869,6 +885,51 @@ static void of_register_spi_devices(struct spi_master *master)
if
(
of_find_property
(
nc
,
"spi-3wire"
,
NULL
))
spi
->
mode
|=
SPI_3WIRE
;
/* Device DUAL/QUAD mode */
prop
=
of_get_property
(
nc
,
"spi-tx-nbits"
,
&
len
);
if
(
!
prop
||
len
<
sizeof
(
*
prop
))
{
dev_err
(
&
master
->
dev
,
"%s has no 'spi-tx-nbits' property
\n
"
,
nc
->
full_name
);
spi_dev_put
(
spi
);
continue
;
}
switch
(
be32_to_cpup
(
prop
))
{
case
SPI_NBITS_SINGLE
:
break
;
case
SPI_NBITS_DUAL
:
spi
->
mode
|=
SPI_TX_DUAL
;
break
;
case
SPI_NBITS_QUAD
:
spi
->
mode
|=
SPI_TX_QUAD
;
break
;
default:
dev_err
(
&
master
->
dev
,
"spi-tx-nbits value is not supported
\n
"
);
spi_dev_put
(
spi
);
continue
;
}
prop
=
of_get_property
(
nc
,
"spi-rx-nbits"
,
&
len
);
if
(
!
prop
||
len
<
sizeof
(
*
prop
))
{
dev_err
(
&
master
->
dev
,
"%s has no 'spi-rx-nbits' property
\n
"
,
nc
->
full_name
);
spi_dev_put
(
spi
);
continue
;
}
switch
(
be32_to_cpup
(
prop
))
{
case
SPI_NBITS_SINGLE
:
break
;
case
SPI_NBITS_DUAL
:
spi
->
mode
|=
SPI_RX_DUAL
;
break
;
case
SPI_NBITS_QUAD
:
spi
->
mode
|=
SPI_RX_QUAD
;
break
;
default:
dev_err
(
&
master
->
dev
,
"spi-rx-nbits value is not supported
\n
"
);
spi_dev_put
(
spi
);
continue
;
}
/* Device speed */
prop
=
of_get_property
(
nc
,
"spi-max-frequency"
,
&
len
);
if
(
!
prop
||
len
<
sizeof
(
*
prop
))
{
...
...
@@ -1316,6 +1377,19 @@ int spi_setup(struct spi_device *spi)
unsigned
bad_bits
;
int
status
=
0
;
/* check mode to prevent that DUAL and QUAD set at the same time
*/
if
(((
spi
->
mode
&
SPI_TX_DUAL
)
&&
(
spi
->
mode
&
SPI_TX_QUAD
))
||
((
spi
->
mode
&
SPI_RX_DUAL
)
&&
(
spi
->
mode
&
SPI_RX_QUAD
)))
{
dev_err
(
&
spi
->
dev
,
"setup: can not select dual and quad at the same time
\n
"
);
return
-
EINVAL
;
}
/* if it is SPI_3WIRE mode, DUAL and QUAD should be forbidden
*/
if
((
spi
->
mode
&
SPI_3WIRE
)
&&
(
spi
->
mode
&
(
SPI_TX_DUAL
|
SPI_TX_QUAD
|
SPI_RX_DUAL
|
SPI_RX_QUAD
)))
return
-
EINVAL
;
/* help drivers fail *cleanly* when they need options
* that aren't supported with their current master
*/
...
...
@@ -1378,6 +1452,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
/**
* Set transfer bits_per_word and max speed as spi device default if
* it is not set for this transfer.
* Set transfer tx_nbits and rx_nbits as single transfer default
* (SPI_NBITS_SINGLE) if it is not set for this transfer.
*/
list_for_each_entry
(
xfer
,
&
message
->
transfers
,
transfer_list
)
{
message
->
frame_length
+=
xfer
->
len
;
...
...
@@ -1404,7 +1480,47 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
return
-
EINVAL
;
if
(
xfer
->
speed_hz
&&
master
->
max_speed_hz
&&
xfer
->
speed_hz
>
master
->
max_speed_hz
)
if
(
xfer
->
tx_buf
&&
!
xfer
->
tx_nbits
)
xfer
->
tx_nbits
=
SPI_NBITS_SINGLE
;
if
(
xfer
->
rx_buf
&&
!
xfer
->
rx_nbits
)
xfer
->
rx_nbits
=
SPI_NBITS_SINGLE
;
/* check transfer tx/rx_nbits:
* 1. keep the value is not out of single, dual and quad
* 2. keep tx/rx_nbits is contained by mode in spi_device
* 3. if SPI_3WIRE, tx/rx_nbits should be in single
*/
if
(
xfer
->
tx_buf
)
{
if
(
xfer
->
tx_nbits
!=
SPI_NBITS_SINGLE
&&
xfer
->
tx_nbits
!=
SPI_NBITS_DUAL
&&
xfer
->
tx_nbits
!=
SPI_NBITS_QUAD
)
return
-
EINVAL
;
if
((
xfer
->
tx_nbits
==
SPI_NBITS_DUAL
)
&&
!
(
spi
->
mode
&
(
SPI_TX_DUAL
|
SPI_TX_QUAD
)))
return
-
EINVAL
;
if
((
xfer
->
tx_nbits
==
SPI_NBITS_QUAD
)
&&
!
(
spi
->
mode
&
SPI_TX_QUAD
))
return
-
EINVAL
;
if
((
spi
->
mode
&
SPI_3WIRE
)
&&
(
xfer
->
tx_nbits
!=
SPI_NBITS_SINGLE
))
return
-
EINVAL
;
}
/* check transfer rx_nbits */
if
(
xfer
->
rx_buf
)
{
if
(
xfer
->
rx_nbits
!=
SPI_NBITS_SINGLE
&&
xfer
->
rx_nbits
!=
SPI_NBITS_DUAL
&&
xfer
->
rx_nbits
!=
SPI_NBITS_QUAD
)
return
-
EINVAL
;
if
((
xfer
->
rx_nbits
==
SPI_NBITS_DUAL
)
&&
!
(
spi
->
mode
&
(
SPI_RX_DUAL
|
SPI_RX_QUAD
)))
return
-
EINVAL
;
if
((
xfer
->
rx_nbits
==
SPI_NBITS_QUAD
)
&&
!
(
spi
->
mode
&
SPI_RX_QUAD
))
return
-
EINVAL
;
if
((
spi
->
mode
&
SPI_3WIRE
)
&&
(
xfer
->
rx_nbits
!=
SPI_NBITS_SINGLE
))
return
-
EINVAL
;
}
}
message
->
spi
=
spi
;
...
...
include/linux/spi/spi.h
View file @
85cac431
...
...
@@ -74,7 +74,7 @@ struct spi_device {
struct
spi_master
*
master
;
u32
max_speed_hz
;
u8
chip_select
;
u
8
mode
;
u
16
mode
;
#define SPI_CPHA 0x01
/* clock phase */
#define SPI_CPOL 0x02
/* clock polarity */
#define SPI_MODE_0 (0|0)
/* (original MicroWire) */
...
...
@@ -87,6 +87,10 @@ struct spi_device {
#define SPI_LOOP 0x20
/* loopback mode */
#define SPI_NO_CS 0x40
/* 1 dev/bus, no chipselect */
#define SPI_READY 0x80
/* slave pulls low to pause */
#define SPI_TX_DUAL 0x100
/* transmit with 2 wires */
#define SPI_TX_QUAD 0x200
/* transmit with 4 wires */
#define SPI_RX_DUAL 0x400
/* receive with 2 wires */
#define SPI_RX_QUAD 0x800
/* receive with 4 wires */
u8
bits_per_word
;
int
irq
;
void
*
controller_state
;
...
...
@@ -256,6 +260,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* @busy: message pump is busy
* @running: message pump is running
* @rt: whether this queue is set to run as a realtime task
* @auto_runtime_pm: the core should ensure a runtime PM reference is held
* while the hardware is prepared, using the parent
* device for the spidev
* @prepare_transfer_hardware: a message will soon arrive from the queue
* so the subsystem requests the driver to prepare the transfer hardware
* by issuing this call
...
...
@@ -380,11 +387,13 @@ struct spi_master {
bool
busy
;
bool
running
;
bool
rt
;
bool
auto_runtime_pm
;
int
(
*
prepare_transfer_hardware
)(
struct
spi_master
*
master
);
int
(
*
transfer_one_message
)(
struct
spi_master
*
master
,
struct
spi_message
*
mesg
);
int
(
*
unprepare_transfer_hardware
)(
struct
spi_master
*
master
);
/* gpio chip select */
int
*
cs_gpios
;
};
...
...
@@ -454,6 +463,10 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
* @rx_buf: data to be read (dma-safe memory), or NULL
* @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
* @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
* @tx_nbits: number of bits used for writting. If 0 the default
* (SPI_NBITS_SINGLE) is used.
* @rx_nbits: number of bits used for reading. If 0 the default
* (SPI_NBITS_SINGLE) is used.
* @len: size of rx and tx buffers (in bytes)
* @speed_hz: Select a speed other than the device default for this
* transfer. If 0 the default (from @spi_device) is used.
...
...
@@ -508,6 +521,11 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
* by the results of previous messages and where the whole transaction
* ends when the chipselect goes intactive.
*
* When SPI can transfer in 1x,2x or 4x. It can get this tranfer information
* from device through @tx_nbits and @rx_nbits. In Bi-direction, these
* two should both be set. User can set transfer mode with SPI_NBITS_SINGLE(1x)
* SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer.
*
* The code that submits an spi_message (and its spi_transfers)
* to the lower layers is responsible for managing its memory.
* Zero-initialize every field you don't set up explicitly, to
...
...
@@ -528,6 +546,11 @@ struct spi_transfer {
dma_addr_t
rx_dma
;
unsigned
cs_change
:
1
;
u8
tx_nbits
;
u8
rx_nbits
;
#define SPI_NBITS_SINGLE 0x01
/* 1bit transfer */
#define SPI_NBITS_DUAL 0x02
/* 2bits transfer */
#define SPI_NBITS_QUAD 0x04
/* 4bits transfer */
u8
bits_per_word
;
u16
delay_usecs
;
u32
speed_hz
;
...
...
@@ -876,7 +899,7 @@ struct spi_board_info {
/* mode becomes spi_device.mode, and is essential for chips
* where the default of SPI_CS_HIGH = 0 is wrong.
*/
u
8
mode
;
u
16
mode
;
/* ... may need additional spi_device chip config data here.
* avoid stuff protocol drivers can set; but include stuff
...
...
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