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
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
Hide 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
)
return
-
EINVAL
;
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