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
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
...
@@ -306,6 +306,14 @@ config SPI_OMAP24XX
SPI master controller for OMAP24XX and later Multichannel SPI
SPI master controller for OMAP24XX and later Multichannel SPI
(McSPI) modules.
(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
config SPI_OMAP_100K
tristate "OMAP SPI 100K"
tristate "OMAP SPI 100K"
depends on ARCH_OMAP850 || ARCH_OMAP730 || COMPILE_TEST
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
...
@@ -49,6 +49,7 @@ obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o
obj-$(CONFIG_SPI_OMAP_UWIRE)
+=
spi-omap-uwire.o
obj-$(CONFIG_SPI_OMAP_UWIRE)
+=
spi-omap-uwire.o
obj-$(CONFIG_SPI_OMAP_100K)
+=
spi-omap-100k.o
obj-$(CONFIG_SPI_OMAP_100K)
+=
spi-omap-100k.o
obj-$(CONFIG_SPI_OMAP24XX)
+=
spi-omap2-mcspi.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_ORION)
+=
spi-orion.o
obj-$(CONFIG_SPI_PL022)
+=
spi-pl022.o
obj-$(CONFIG_SPI_PL022)
+=
spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx)
+=
spi-ppc4xx.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,
...
@@ -231,24 +231,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
return
0
;
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
,
static
int
bcm63xx_spi_transfer_one
(
struct
spi_master
*
master
,
struct
spi_message
*
m
)
struct
spi_message
*
m
)
{
{
...
@@ -406,11 +388,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
...
@@ -406,11 +388,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
master
->
bus_num
=
pdata
->
bus_num
;
master
->
bus_num
=
pdata
->
bus_num
;
master
->
num_chipselect
=
pdata
->
num_chipselect
;
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
->
transfer_one_message
=
bcm63xx_spi_transfer_one
;
master
->
mode_bits
=
MODEBITS
;
master
->
mode_bits
=
MODEBITS
;
master
->
bits_per_word_mask
=
SPI_BPW_MASK
(
8
);
master
->
bits_per_word_mask
=
SPI_BPW_MASK
(
8
);
master
->
auto_runtime_pm
=
true
;
bs
->
msg_type_shift
=
pdata
->
msg_type_shift
;
bs
->
msg_type_shift
=
pdata
->
msg_type_shift
;
bs
->
msg_ctl_width
=
pdata
->
msg_ctl_width
;
bs
->
msg_ctl_width
=
pdata
->
msg_ctl_width
;
bs
->
tx_io
=
(
u8
*
)(
bs
->
regs
+
bcm63xx_spireg
(
SPI_MSG_DATA
));
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,
...
@@ -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
)
static
int
mcfqspi_setup
(
struct
spi_device
*
spi
)
{
{
if
(
spi
->
chip_select
>=
spi
->
master
->
num_chipselect
)
{
if
(
spi
->
chip_select
>=
spi
->
master
->
num_chipselect
)
{
...
@@ -473,8 +455,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
...
@@ -473,8 +455,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
8
,
16
);
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
8
,
16
);
master
->
setup
=
mcfqspi_setup
;
master
->
setup
=
mcfqspi_setup
;
master
->
transfer_one_message
=
mcfqspi_transfer_one_message
;
master
->
transfer_one_message
=
mcfqspi_transfer_one_message
;
master
->
prepare_transfer_hardware
=
mcfqspi_prepare_transfer_hw
;
master
->
auto_runtime_pm
=
true
;
master
->
unprepare_transfer_hardware
=
mcfqspi_unprepare_transfer_hw
;
platform_set_drvdata
(
pdev
,
master
);
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)
...
@@ -335,23 +335,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
__raw_writel
(
cs
->
chconf0
,
cs
->
base
+
OMAP2_MCSPI_CHCONF0
);
__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
)
static
int
mcspi_wait_for_reg_bit
(
void
__iomem
*
reg
,
unsigned
long
bit
)
{
{
unsigned
long
timeout
;
unsigned
long
timeout
;
...
@@ -1318,8 +1301,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
...
@@ -1318,8 +1301,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
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
->
prepare_transfer_hardware
=
omap2_prepare_transfer
;
master
->
auto_runtime_pm
=
true
;
master
->
unprepare_transfer_hardware
=
omap2_unprepare_transfer
;
master
->
transfer_one_message
=
omap2_mcspi_transfer_one_message
;
master
->
transfer_one_message
=
omap2_mcspi_transfer_one_message
;
master
->
cleanup
=
omap2_mcspi_cleanup
;
master
->
cleanup
=
omap2_mcspi_cleanup
;
master
->
dev
.
of_node
=
node
;
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,
...
@@ -1555,18 +1555,6 @@ static int pl022_transfer_one_message(struct spi_master *master,
return
0
;
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
)
static
int
pl022_unprepare_transfer_hardware
(
struct
spi_master
*
master
)
{
{
struct
pl022
*
pl022
=
spi_master_get_devdata
(
master
);
struct
pl022
*
pl022
=
spi_master_get_devdata
(
master
);
...
@@ -1575,13 +1563,6 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
...
@@ -1575,13 +1563,6 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
writew
((
readw
(
SSP_CR1
(
pl022
->
virtbase
))
&
writew
((
readw
(
SSP_CR1
(
pl022
->
virtbase
))
&
(
~
SSP_CR1_MASK_SSE
)),
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
;
return
0
;
}
}
...
@@ -2140,7 +2121,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
...
@@ -2140,7 +2121,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
master
->
num_chipselect
=
num_cs
;
master
->
num_chipselect
=
num_cs
;
master
->
cleanup
=
pl022_cleanup
;
master
->
cleanup
=
pl022_cleanup
;
master
->
setup
=
pl022_setup
;
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
->
transfer_one_message
=
pl022_transfer_one_message
;
master
->
unprepare_transfer_hardware
=
pl022_unprepare_transfer_hardware
;
master
->
unprepare_transfer_hardware
=
pl022_unprepare_transfer_hardware
;
master
->
rt
=
platform_info
->
rt
;
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,
...
@@ -811,14 +811,6 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
return
0
;
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
)
static
int
pxa2xx_spi_unprepare_transfer
(
struct
spi_master
*
master
)
{
{
struct
driver_data
*
drv_data
=
spi_master_get_devdata
(
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)
...
@@ -827,8 +819,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
write_SSCR0
(
read_SSCR0
(
drv_data
->
ioaddr
)
&
~
SSCR0_SSE
,
write_SSCR0
(
read_SSCR0
(
drv_data
->
ioaddr
)
&
~
SSCR0_SSE
,
drv_data
->
ioaddr
);
drv_data
->
ioaddr
);
pm_runtime_mark_last_busy
(
&
drv_data
->
pdev
->
dev
);
pm_runtime_put_autosuspend
(
&
drv_data
->
pdev
->
dev
);
return
0
;
return
0
;
}
}
...
@@ -1141,8 +1131,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
...
@@ -1141,8 +1131,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master
->
cleanup
=
cleanup
;
master
->
cleanup
=
cleanup
;
master
->
setup
=
setup
;
master
->
setup
=
setup
;
master
->
transfer_one_message
=
pxa2xx_spi_transfer_one_message
;
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
->
unprepare_transfer_hardware
=
pxa2xx_spi_unprepare_transfer
;
master
->
auto_runtime_pm
=
true
;
drv_data
->
ssp_type
=
ssp
->
type
;
drv_data
->
ssp_type
=
ssp
->
type
;
drv_data
->
null_dma_buf
=
(
u32
*
)
PTR_ALIGN
(
&
drv_data
[
1
],
DMA_ALIGNMENT
);
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)
...
@@ -356,8 +356,6 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
while
(
!
is_polling
(
sdd
)
&&
!
acquire_dma
(
sdd
))
while
(
!
is_polling
(
sdd
)
&&
!
acquire_dma
(
sdd
))
usleep_range
(
10000
,
11000
);
usleep_range
(
10000
,
11000
);
pm_runtime_get_sync
(
&
sdd
->
pdev
->
dev
);
return
0
;
return
0
;
}
}
...
@@ -372,7 +370,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
...
@@ -372,7 +370,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
sdd
->
ops
->
release
((
enum
dma_ch
)
sdd
->
tx_dma
.
ch
,
sdd
->
ops
->
release
((
enum
dma_ch
)
sdd
->
tx_dma
.
ch
,
&
s3c64xx_spi_dma_client
);
&
s3c64xx_spi_dma_client
);
}
}
pm_runtime_put
(
&
sdd
->
pdev
->
dev
);
return
0
;
return
0
;
}
}
...
@@ -1395,6 +1392,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
...
@@ -1395,6 +1392,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
SPI_BPW_MASK
(
8
);
SPI_BPW_MASK
(
8
);
/* the spi->mode bits understood by this driver: */
/* the spi->mode bits understood by this driver: */
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
auto_runtime_pm
=
true
;
sdd
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
mem_res
);
sdd
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
mem_res
);
if
(
IS_ERR
(
sdd
->
regs
))
{
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)
...
@@ -99,21 +99,6 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
/*
/*
* spi master function
* 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_enable(hspi) hspi_hw_cs_ctrl(hspi, 0)
#define hspi_hw_cs_disable(hspi) hspi_hw_cs_ctrl(hspi, 1)
#define hspi_hw_cs_disable(hspi) hspi_hw_cs_ctrl(hspi, 1)
...
@@ -316,9 +301,8 @@ static int hspi_probe(struct platform_device *pdev)
...
@@ -316,9 +301,8 @@ static int hspi_probe(struct platform_device *pdev)
master
->
setup
=
hspi_setup
;
master
->
setup
=
hspi_setup
;
master
->
cleanup
=
hspi_cleanup
;
master
->
cleanup
=
hspi_cleanup
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
;
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
->
transfer_one_message
=
hspi_transfer_one_message
;
master
->
unprepare_transfer_hardware
=
hspi_unprepare_transfer
;
ret
=
spi_register_master
(
master
);
ret
=
spi_register_master
(
master
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"spi_register_master error.
\n
"
);
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,
...
@@ -816,14 +816,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
msg
->
status
=
0
;
msg
->
status
=
0
;
msg
->
actual_length
=
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
);
single_xfer
=
list_is_singular
(
&
msg
->
transfers
);
list_for_each_entry
(
xfer
,
&
msg
->
transfers
,
transfer_list
)
{
list_for_each_entry
(
xfer
,
&
msg
->
transfers
,
transfer_list
)
{
INIT_COMPLETION
(
tspi
->
xfer_completion
);
INIT_COMPLETION
(
tspi
->
xfer_completion
);
...
@@ -859,7 +851,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
...
@@ -859,7 +851,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
ret
=
0
;
ret
=
0
;
exit:
exit:
tegra_spi_writel
(
tspi
,
tspi
->
def_command1_reg
,
SPI_COMMAND1
);
tegra_spi_writel
(
tspi
,
tspi
->
def_command1_reg
,
SPI_COMMAND1
);
pm_runtime_put
(
tspi
->
dev
);
msg
->
status
=
ret
;
msg
->
status
=
ret
;
spi_finalize_current_message
(
master
);
spi_finalize_current_message
(
master
);
return
ret
;
return
ret
;
...
@@ -1053,6 +1044,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
...
@@ -1053,6 +1044,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
master
->
transfer_one_message
=
tegra_spi_transfer_one_message
;
master
->
transfer_one_message
=
tegra_spi_transfer_one_message
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
bus_num
=
-
1
;
master
->
bus_num
=
-
1
;
master
->
auto_runtime_pm
=
true
;
tspi
->
master
=
master
;
tspi
->
master
=
master
;
tspi
->
dev
=
&
pdev
->
dev
;
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,
...
@@ -335,12 +335,6 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master,
struct
spi_device
*
spi
=
msg
->
spi
;
struct
spi_device
*
spi
=
msg
->
spi
;
int
ret
;
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
->
status
=
0
;
msg
->
actual_length
=
0
;
msg
->
actual_length
=
0
;
single_xfer
=
list_is_singular
(
&
msg
->
transfers
);
single_xfer
=
list_is_singular
(
&
msg
->
transfers
);
...
@@ -380,7 +374,6 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master,
...
@@ -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
);
tegra_sflash_writel
(
tsd
,
tsd
->
def_command_reg
,
SPI_COMMAND
);
msg
->
status
=
ret
;
msg
->
status
=
ret
;
spi_finalize_current_message
(
master
);
spi_finalize_current_message
(
master
);
pm_runtime_put
(
tsd
->
dev
);
return
ret
;
return
ret
;
}
}
...
@@ -477,6 +470,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
...
@@ -477,6 +470,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
;
master
->
setup
=
tegra_sflash_setup
;
master
->
setup
=
tegra_sflash_setup
;
master
->
transfer_one_message
=
tegra_sflash_transfer_one_message
;
master
->
transfer_one_message
=
tegra_sflash_transfer_one_message
;
master
->
auto_runtime_pm
=
true
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
bus_num
=
-
1
;
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,
...
@@ -836,11 +836,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
msg
->
status
=
0
;
msg
->
status
=
0
;
msg
->
actual_length
=
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
);
single_xfer
=
list_is_singular
(
&
msg
->
transfers
);
list_for_each_entry
(
xfer
,
&
msg
->
transfers
,
transfer_list
)
{
list_for_each_entry
(
xfer
,
&
msg
->
transfers
,
transfer_list
)
{
...
@@ -878,8 +873,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
...
@@ -878,8 +873,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
exit:
exit:
tegra_slink_writel
(
tspi
,
tspi
->
def_command_reg
,
SLINK_COMMAND
);
tegra_slink_writel
(
tspi
,
tspi
->
def_command_reg
,
SLINK_COMMAND
);
tegra_slink_writel
(
tspi
,
tspi
->
def_command2_reg
,
SLINK_COMMAND2
);
tegra_slink_writel
(
tspi
,
tspi
->
def_command2_reg
,
SLINK_COMMAND2
);
pm_runtime_put
(
tspi
->
dev
);
done:
msg
->
status
=
ret
;
msg
->
status
=
ret
;
spi_finalize_current_message
(
master
);
spi_finalize_current_message
(
master
);
return
ret
;
return
ret
;
...
@@ -1086,6 +1079,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
...
@@ -1086,6 +1079,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
;
master
->
setup
=
tegra_slink_setup
;
master
->
setup
=
tegra_slink_setup
;
master
->
transfer_one_message
=
tegra_slink_transfer_one_message
;
master
->
transfer_one_message
=
tegra_slink_transfer_one_message
;
master
->
auto_runtime_pm
=
true
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
num_chipselect
=
MAX_CHIP_SELECT
;
master
->
bus_num
=
-
1
;
master
->
bus_num
=
-
1
;
...
...
drivers/spi/spi-ti-qspi.c
0 → 100644
View file @
85cac431
/*
* TI QSPI driver
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
* Author: Sourav Poddar <sourav.poddar@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GPLv2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/omap-dma.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/spi/spi.h>
struct
ti_qspi_regs
{
u32
clkctrl
;
};
struct
ti_qspi
{
struct
completion
transfer_complete
;
/* IRQ synchronization */
spinlock_t
lock
;
/* list synchronization */
struct
mutex
list_lock
;
struct
spi_master
*
master
;
void
__iomem
*
base
;
struct
clk
*
fclk
;
struct
device
*
dev
;
struct
ti_qspi_regs
ctx_reg
;
u32
spi_max_frequency
;
u32
cmd
;
u32
dc
;
u32
stat
;
};
#define QSPI_PID (0x0)
#define QSPI_SYSCONFIG (0x10)
#define QSPI_INTR_STATUS_RAW_SET (0x20)
#define QSPI_INTR_STATUS_ENABLED_CLEAR (0x24)
#define QSPI_INTR_ENABLE_SET_REG (0x28)
#define QSPI_INTR_ENABLE_CLEAR_REG (0x2c)
#define QSPI_SPI_CLOCK_CNTRL_REG (0x40)
#define QSPI_SPI_DC_REG (0x44)
#define QSPI_SPI_CMD_REG (0x48)
#define QSPI_SPI_STATUS_REG (0x4c)
#define QSPI_SPI_DATA_REG (0x50)
#define QSPI_SPI_SETUP0_REG (0x54)
#define QSPI_SPI_SWITCH_REG (0x64)
#define QSPI_SPI_SETUP1_REG (0x58)
#define QSPI_SPI_SETUP2_REG (0x5c)
#define QSPI_SPI_SETUP3_REG (0x60)
#define QSPI_SPI_DATA_REG_1 (0x68)
#define QSPI_SPI_DATA_REG_2 (0x6c)
#define QSPI_SPI_DATA_REG_3 (0x70)
#define QSPI_COMPLETION_TIMEOUT msecs_to_jiffies(2000)
#define QSPI_FCLK 192000000
/* Clock Control */
#define QSPI_CLK_EN (1 << 31)
#define QSPI_CLK_DIV_MAX 0xffff
/* Command */
#define QSPI_EN_CS(n) (n << 28)
#define QSPI_WLEN(n) ((n - 1) << 19)
#define QSPI_3_PIN (1 << 18)
#define QSPI_RD_SNGL (1 << 16)
#define QSPI_WR_SNGL (2 << 16)
#define QSPI_RD_DUAL (3 << 16)
#define QSPI_RD_QUAD (7 << 16)
#define QSPI_INVAL (4 << 16)
#define QSPI_WC_CMD_INT_EN (1 << 14)
#define QSPI_FLEN(n) ((n - 1) << 0)
/* STATUS REGISTER */
#define WC 0x02
/* INTERRUPT REGISTER */
#define QSPI_WC_INT_EN (1 << 1)
#define QSPI_WC_INT_DISABLE (1 << 1)
/* Device Control */
#define QSPI_DD(m, n) (m << (3 + n * 8))
#define QSPI_CKPHA(n) (1 << (2 + n * 8))
#define QSPI_CSPOL(n) (1 << (1 + n * 8))
#define QSPI_CKPOL(n) (1 << (n * 8))
#define QSPI_FRAME 4096
#define QSPI_AUTOSUSPEND_TIMEOUT 2000
static
inline
unsigned
long
ti_qspi_read
(
struct
ti_qspi
*
qspi
,
unsigned
long
reg
)
{
return
readl
(
qspi
->
base
+
reg
);
}
static
inline
void
ti_qspi_write
(
struct
ti_qspi
*
qspi
,
unsigned
long
val
,
unsigned
long
reg
)
{
writel
(
val
,
qspi
->
base
+
reg
);
}
static
int
ti_qspi_setup
(
struct
spi_device
*
spi
)
{
struct
ti_qspi
*
qspi
=
spi_master_get_devdata
(
spi
->
master
);
struct
ti_qspi_regs
*
ctx_reg
=
&
qspi
->
ctx_reg
;
int
clk_div
=
0
,
ret
;
u32
clk_ctrl_reg
,
clk_rate
,
clk_mask
;
if
(
spi
->
master
->
busy
)
{
dev_dbg
(
qspi
->
dev
,
"master busy doing other trasnfers
\n
"
);
return
-
EBUSY
;
}
if
(
!
qspi
->
spi_max_frequency
)
{
dev_err
(
qspi
->
dev
,
"spi max frequency not defined
\n
"
);
return
-
EINVAL
;
}
clk_rate
=
clk_get_rate
(
qspi
->
fclk
);
clk_div
=
DIV_ROUND_UP
(
clk_rate
,
qspi
->
spi_max_frequency
)
-
1
;
if
(
clk_div
<
0
)
{
dev_dbg
(
qspi
->
dev
,
"clock divider < 0, using /1 divider
\n
"
);
return
-
EINVAL
;
}
if
(
clk_div
>
QSPI_CLK_DIV_MAX
)
{
dev_dbg
(
qspi
->
dev
,
"clock divider >%d , using /%d divider
\n
"
,
QSPI_CLK_DIV_MAX
,
QSPI_CLK_DIV_MAX
+
1
);
return
-
EINVAL
;
}
dev_dbg
(
qspi
->
dev
,
"hz: %d, clock divider %d
\n
"
,
qspi
->
spi_max_frequency
,
clk_div
);
ret
=
pm_runtime_get_sync
(
qspi
->
dev
);
if
(
ret
)
{
dev_err
(
qspi
->
dev
,
"pm_runtime_get_sync() failed
\n
"
);
return
ret
;
}
clk_ctrl_reg
=
ti_qspi_read
(
qspi
,
QSPI_SPI_CLOCK_CNTRL_REG
);
clk_ctrl_reg
&=
~
QSPI_CLK_EN
;
/* disable SCLK */
ti_qspi_write
(
qspi
,
clk_ctrl_reg
,
QSPI_SPI_CLOCK_CNTRL_REG
);
/* enable SCLK */
clk_mask
=
QSPI_CLK_EN
|
clk_div
;
ti_qspi_write
(
qspi
,
clk_mask
,
QSPI_SPI_CLOCK_CNTRL_REG
);
ctx_reg
->
clkctrl
=
clk_mask
;
pm_runtime_mark_last_busy
(
qspi
->
dev
);
ret
=
pm_runtime_put_autosuspend
(
qspi
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
qspi
->
dev
,
"pm_runtime_put_autosuspend() failed
\n
"
);
return
ret
;
}
return
0
;
}
static
void
ti_qspi_restore_ctx
(
struct
ti_qspi
*
qspi
)
{
struct
ti_qspi_regs
*
ctx_reg
=
&
qspi
->
ctx_reg
;
ti_qspi_write
(
qspi
,
ctx_reg
->
clkctrl
,
QSPI_SPI_CLOCK_CNTRL_REG
);
}
static
int
qspi_write_msg
(
struct
ti_qspi
*
qspi
,
struct
spi_transfer
*
t
)
{
int
wlen
,
count
,
ret
;
unsigned
int
cmd
;
const
u8
*
txbuf
;
txbuf
=
t
->
tx_buf
;
cmd
=
qspi
->
cmd
|
QSPI_WR_SNGL
;
count
=
t
->
len
;
wlen
=
t
->
bits_per_word
;
while
(
count
)
{
switch
(
wlen
)
{
case
8
:
dev_dbg
(
qspi
->
dev
,
"tx cmd %08x dc %08x data %02x
\n
"
,
cmd
,
qspi
->
dc
,
*
txbuf
);
writeb
(
*
txbuf
,
qspi
->
base
+
QSPI_SPI_DATA_REG
);
ti_qspi_write
(
qspi
,
cmd
,
QSPI_SPI_CMD_REG
);
ret
=
wait_for_completion_timeout
(
&
qspi
->
transfer_complete
,
QSPI_COMPLETION_TIMEOUT
);
if
(
ret
==
0
)
{
dev_err
(
qspi
->
dev
,
"write timed out
\n
"
);
return
-
ETIMEDOUT
;
}
txbuf
+=
1
;
count
-=
1
;
break
;
case
16
:
dev_dbg
(
qspi
->
dev
,
"tx cmd %08x dc %08x data %04x
\n
"
,
cmd
,
qspi
->
dc
,
*
txbuf
);
writew
(
*
((
u16
*
)
txbuf
),
qspi
->
base
+
QSPI_SPI_DATA_REG
);
ti_qspi_write
(
qspi
,
cmd
,
QSPI_SPI_CMD_REG
);
ret
=
wait_for_completion_timeout
(
&
qspi
->
transfer_complete
,
QSPI_COMPLETION_TIMEOUT
);
if
(
ret
==
0
)
{
dev_err
(
qspi
->
dev
,
"write timed out
\n
"
);
return
-
ETIMEDOUT
;
}
txbuf
+=
2
;
count
-=
2
;
break
;
case
32
:
dev_dbg
(
qspi
->
dev
,
"tx cmd %08x dc %08x data %08x
\n
"
,
cmd
,
qspi
->
dc
,
*
txbuf
);
writel
(
*
((
u32
*
)
txbuf
),
qspi
->
base
+
QSPI_SPI_DATA_REG
);
ti_qspi_write
(
qspi
,
cmd
,
QSPI_SPI_CMD_REG
);
ret
=
wait_for_completion_timeout
(
&
qspi
->
transfer_complete
,
QSPI_COMPLETION_TIMEOUT
);
if
(
ret
==
0
)
{
dev_err
(
qspi
->
dev
,
"write timed out
\n
"
);
return
-
ETIMEDOUT
;
}
txbuf
+=
4
;
count
-=
4
;
break
;
}
}
return
0
;
}
static
int
qspi_read_msg
(
struct
ti_qspi
*
qspi
,
struct
spi_transfer
*
t
)
{
int
wlen
,
count
,
ret
;
unsigned
int
cmd
;
u8
*
rxbuf
;
rxbuf
=
t
->
rx_buf
;
cmd
=
qspi
->
cmd
;
switch
(
t
->
rx_nbits
)
{
case
SPI_NBITS_DUAL
:
cmd
|=
QSPI_RD_DUAL
;
break
;
case
SPI_NBITS_QUAD
:
cmd
|=
QSPI_RD_QUAD
;
break
;
default:
cmd
|=
QSPI_RD_SNGL
;
break
;
}
count
=
t
->
len
;
wlen
=
t
->
bits_per_word
;
while
(
count
)
{
dev_dbg
(
qspi
->
dev
,
"rx cmd %08x dc %08x
\n
"
,
cmd
,
qspi
->
dc
);
ti_qspi_write
(
qspi
,
cmd
,
QSPI_SPI_CMD_REG
);
ret
=
wait_for_completion_timeout
(
&
qspi
->
transfer_complete
,
QSPI_COMPLETION_TIMEOUT
);
if
(
ret
==
0
)
{
dev_err
(
qspi
->
dev
,
"read timed out
\n
"
);
return
-
ETIMEDOUT
;
}
switch
(
wlen
)
{
case
8
:
*
rxbuf
=
readb
(
qspi
->
base
+
QSPI_SPI_DATA_REG
);
rxbuf
+=
1
;
count
-=
1
;
break
;
case
16
:
*
((
u16
*
)
rxbuf
)
=
readw
(
qspi
->
base
+
QSPI_SPI_DATA_REG
);
rxbuf
+=
2
;
count
-=
2
;
break
;
case
32
:
*
((
u32
*
)
rxbuf
)
=
readl
(
qspi
->
base
+
QSPI_SPI_DATA_REG
);
rxbuf
+=
4
;
count
-=
4
;
break
;
}
}
return
0
;
}
static
int
qspi_transfer_msg
(
struct
ti_qspi
*
qspi
,
struct
spi_transfer
*
t
)
{
int
ret
;
if
(
t
->
tx_buf
)
{
ret
=
qspi_write_msg
(
qspi
,
t
);
if
(
ret
)
{
dev_dbg
(
qspi
->
dev
,
"Error while writing
\n
"
);
return
ret
;
}
}
if
(
t
->
rx_buf
)
{
ret
=
qspi_read_msg
(
qspi
,
t
);
if
(
ret
)
{
dev_dbg
(
qspi
->
dev
,
"Error while reading
\n
"
);
return
ret
;
}
}
return
0
;
}
static
int
ti_qspi_start_transfer_one
(
struct
spi_master
*
master
,
struct
spi_message
*
m
)
{
struct
ti_qspi
*
qspi
=
spi_master_get_devdata
(
master
);
struct
spi_device
*
spi
=
m
->
spi
;
struct
spi_transfer
*
t
;
int
status
=
0
,
ret
;
int
frame_length
;
/* setup device control reg */
qspi
->
dc
=
0
;
if
(
spi
->
mode
&
SPI_CPHA
)
qspi
->
dc
|=
QSPI_CKPHA
(
spi
->
chip_select
);
if
(
spi
->
mode
&
SPI_CPOL
)
qspi
->
dc
|=
QSPI_CKPOL
(
spi
->
chip_select
);
if
(
spi
->
mode
&
SPI_CS_HIGH
)
qspi
->
dc
|=
QSPI_CSPOL
(
spi
->
chip_select
);
frame_length
=
(
m
->
frame_length
<<
3
)
/
spi
->
bits_per_word
;
frame_length
=
clamp
(
frame_length
,
0
,
QSPI_FRAME
);
/* setup command reg */
qspi
->
cmd
=
0
;
qspi
->
cmd
|=
QSPI_EN_CS
(
spi
->
chip_select
);
qspi
->
cmd
|=
QSPI_FLEN
(
frame_length
);
qspi
->
cmd
|=
QSPI_WC_CMD_INT_EN
;
ti_qspi_write
(
qspi
,
QSPI_WC_INT_EN
,
QSPI_INTR_ENABLE_SET_REG
);
ti_qspi_write
(
qspi
,
qspi
->
dc
,
QSPI_SPI_DC_REG
);
mutex_lock
(
&
qspi
->
list_lock
);
list_for_each_entry
(
t
,
&
m
->
transfers
,
transfer_list
)
{
qspi
->
cmd
|=
QSPI_WLEN
(
t
->
bits_per_word
);
ret
=
qspi_transfer_msg
(
qspi
,
t
);
if
(
ret
)
{
dev_dbg
(
qspi
->
dev
,
"transfer message failed
\n
"
);
mutex_unlock
(
&
qspi
->
list_lock
);
return
-
EINVAL
;
}
m
->
actual_length
+=
t
->
len
;
}
mutex_unlock
(
&
qspi
->
list_lock
);
m
->
status
=
status
;
spi_finalize_current_message
(
master
);
ti_qspi_write
(
qspi
,
qspi
->
cmd
|
QSPI_INVAL
,
QSPI_SPI_CMD_REG
);
return
status
;
}
static
irqreturn_t
ti_qspi_isr
(
int
irq
,
void
*
dev_id
)
{
struct
ti_qspi
*
qspi
=
dev_id
;
u16
int_stat
;
irqreturn_t
ret
=
IRQ_HANDLED
;
spin_lock
(
&
qspi
->
lock
);
int_stat
=
ti_qspi_read
(
qspi
,
QSPI_INTR_STATUS_ENABLED_CLEAR
);
qspi
->
stat
=
ti_qspi_read
(
qspi
,
QSPI_SPI_STATUS_REG
);
if
(
!
int_stat
)
{
dev_dbg
(
qspi
->
dev
,
"No IRQ triggered
\n
"
);
ret
=
IRQ_NONE
;
goto
out
;
}
ret
=
IRQ_WAKE_THREAD
;
ti_qspi_write
(
qspi
,
QSPI_WC_INT_DISABLE
,
QSPI_INTR_ENABLE_CLEAR_REG
);
ti_qspi_write
(
qspi
,
QSPI_WC_INT_DISABLE
,
QSPI_INTR_STATUS_ENABLED_CLEAR
);
out:
spin_unlock
(
&
qspi
->
lock
);
return
ret
;
}
static
irqreturn_t
ti_qspi_threaded_isr
(
int
this_irq
,
void
*
dev_id
)
{
struct
ti_qspi
*
qspi
=
dev_id
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
qspi
->
lock
,
flags
);
if
(
qspi
->
stat
&
WC
)
complete
(
&
qspi
->
transfer_complete
);
spin_unlock_irqrestore
(
&
qspi
->
lock
,
flags
);
ti_qspi_write
(
qspi
,
QSPI_WC_INT_EN
,
QSPI_INTR_ENABLE_SET_REG
);
return
IRQ_HANDLED
;
}
static
int
ti_qspi_runtime_resume
(
struct
device
*
dev
)
{
struct
ti_qspi
*
qspi
;
struct
spi_master
*
master
;
master
=
dev_get_drvdata
(
dev
);
qspi
=
spi_master_get_devdata
(
master
);
ti_qspi_restore_ctx
(
qspi
);
return
0
;
}
static
const
struct
of_device_id
ti_qspi_match
[]
=
{
{.
compatible
=
"ti,dra7xxx-qspi"
},
{.
compatible
=
"ti,am4372-qspi"
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
ti_qspi_match
);
static
int
ti_qspi_probe
(
struct
platform_device
*
pdev
)
{
struct
ti_qspi
*
qspi
;
struct
spi_master
*
master
;
struct
resource
*
r
;
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
u32
max_freq
;
int
ret
=
0
,
num_cs
,
irq
;
master
=
spi_alloc_master
(
&
pdev
->
dev
,
sizeof
(
*
qspi
));
if
(
!
master
)
return
-
ENOMEM
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
;
master
->
bus_num
=
-
1
;
master
->
flags
=
SPI_MASTER_HALF_DUPLEX
;
master
->
setup
=
ti_qspi_setup
;
master
->
auto_runtime_pm
=
true
;
master
->
transfer_one_message
=
ti_qspi_start_transfer_one
;
master
->
dev
.
of_node
=
pdev
->
dev
.
of_node
;
master
->
bits_per_word_mask
=
BIT
(
32
-
1
)
|
BIT
(
16
-
1
)
|
BIT
(
8
-
1
);
if
(
!
of_property_read_u32
(
np
,
"num-cs"
,
&
num_cs
))
master
->
num_chipselect
=
num_cs
;
platform_set_drvdata
(
pdev
,
master
);
qspi
=
spi_master_get_devdata
(
master
);
qspi
->
master
=
master
;
qspi
->
dev
=
&
pdev
->
dev
;
r
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"no irq resource?
\n
"
);
return
irq
;
}
spin_lock_init
(
&
qspi
->
lock
);
mutex_init
(
&
qspi
->
list_lock
);
qspi
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
r
);
if
(
IS_ERR
(
qspi
->
base
))
{
ret
=
PTR_ERR
(
qspi
->
base
);
goto
free_master
;
}
ret
=
devm_request_threaded_irq
(
&
pdev
->
dev
,
irq
,
ti_qspi_isr
,
ti_qspi_threaded_isr
,
0
,
dev_name
(
&
pdev
->
dev
),
qspi
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to register ISR for IRQ %d
\n
"
,
irq
);
goto
free_master
;
}
qspi
->
fclk
=
devm_clk_get
(
&
pdev
->
dev
,
"fck"
);
if
(
IS_ERR
(
qspi
->
fclk
))
{
ret
=
PTR_ERR
(
qspi
->
fclk
);
dev_err
(
&
pdev
->
dev
,
"could not get clk: %d
\n
"
,
ret
);
}
init_completion
(
&
qspi
->
transfer_complete
);
pm_runtime_use_autosuspend
(
&
pdev
->
dev
);
pm_runtime_set_autosuspend_delay
(
&
pdev
->
dev
,
QSPI_AUTOSUSPEND_TIMEOUT
);
pm_runtime_enable
(
&
pdev
->
dev
);
if
(
!
of_property_read_u32
(
np
,
"spi-max-frequency"
,
&
max_freq
))
qspi
->
spi_max_frequency
=
max_freq
;
ret
=
spi_register_master
(
master
);
if
(
ret
)
goto
free_master
;
return
0
;
free_master:
spi_master_put
(
master
);
return
ret
;
}
static
int
ti_qspi_remove
(
struct
platform_device
*
pdev
)
{
struct
ti_qspi
*
qspi
=
platform_get_drvdata
(
pdev
);
spi_unregister_master
(
qspi
->
master
);
return
0
;
}
static
const
struct
dev_pm_ops
ti_qspi_pm_ops
=
{
.
runtime_resume
=
ti_qspi_runtime_resume
,
};
static
struct
platform_driver
ti_qspi_driver
=
{
.
probe
=
ti_qspi_probe
,
.
remove
=
ti_qspi_remove
,
.
driver
=
{
.
name
=
"ti,dra7xxx-qspi"
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
ti_qspi_pm_ops
,
.
of_match_table
=
ti_qspi_match
,
}
};
module_platform_driver
(
ti_qspi_driver
);
MODULE_AUTHOR
(
"Sourav Poddar <sourav.poddar@ti.com>"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_DESCRIPTION
(
"TI QSPI controller driver"
);
drivers/spi/spi.c
View file @
85cac431
...
@@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work)
...
@@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work)
master
->
unprepare_transfer_hardware
(
master
))
master
->
unprepare_transfer_hardware
(
master
))
dev_err
(
&
master
->
dev
,
dev_err
(
&
master
->
dev
,
"failed to unprepare transfer hardware
\n
"
);
"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
;
return
;
}
}
...
@@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work)
...
@@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work)
master
->
busy
=
true
;
master
->
busy
=
true
;
spin_unlock_irqrestore
(
&
master
->
queue_lock
,
flags
);
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
)
{
if
(
!
was_busy
&&
master
->
prepare_transfer_hardware
)
{
ret
=
master
->
prepare_transfer_hardware
(
master
);
ret
=
master
->
prepare_transfer_hardware
(
master
);
if
(
ret
)
{
if
(
ret
)
{
dev_err
(
&
master
->
dev
,
dev_err
(
&
master
->
dev
,
"failed to prepare transfer hardware
\n
"
);
"failed to prepare transfer hardware
\n
"
);
if
(
master
->
auto_runtime_pm
)
pm_runtime_put
(
master
->
dev
.
parent
);
return
;
return
;
}
}
}
}
...
@@ -869,6 +885,51 @@ static void of_register_spi_devices(struct spi_master *master)
...
@@ -869,6 +885,51 @@ static void of_register_spi_devices(struct spi_master *master)
if
(
of_find_property
(
nc
,
"spi-3wire"
,
NULL
))
if
(
of_find_property
(
nc
,
"spi-3wire"
,
NULL
))
spi
->
mode
|=
SPI_3WIRE
;
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 */
/* Device speed */
prop
=
of_get_property
(
nc
,
"spi-max-frequency"
,
&
len
);
prop
=
of_get_property
(
nc
,
"spi-max-frequency"
,
&
len
);
if
(
!
prop
||
len
<
sizeof
(
*
prop
))
{
if
(
!
prop
||
len
<
sizeof
(
*
prop
))
{
...
@@ -1316,6 +1377,19 @@ int spi_setup(struct spi_device *spi)
...
@@ -1316,6 +1377,19 @@ int spi_setup(struct spi_device *spi)
unsigned
bad_bits
;
unsigned
bad_bits
;
int
status
=
0
;
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
/* help drivers fail *cleanly* when they need options
* that aren't supported with their current master
* that aren't supported with their current master
*/
*/
...
@@ -1378,6 +1452,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
...
@@ -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
* Set transfer bits_per_word and max speed as spi device default if
* it is not set for this transfer.
* 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
)
{
list_for_each_entry
(
xfer
,
&
message
->
transfers
,
transfer_list
)
{
message
->
frame_length
+=
xfer
->
len
;
message
->
frame_length
+=
xfer
->
len
;
...
@@ -1404,7 +1480,47 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
...
@@ -1404,7 +1480,47 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
xfer
->
speed_hz
&&
master
->
max_speed_hz
&&
if
(
xfer
->
speed_hz
&&
master
->
max_speed_hz
&&
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
;
return
-
EINVAL
;
if
((
spi
->
mode
&
SPI_3WIRE
)
&&
(
xfer
->
rx_nbits
!=
SPI_NBITS_SINGLE
))
return
-
EINVAL
;
}
}
}
message
->
spi
=
spi
;
message
->
spi
=
spi
;
...
...
include/linux/spi/spi.h
View file @
85cac431
...
@@ -74,7 +74,7 @@ struct spi_device {
...
@@ -74,7 +74,7 @@ struct spi_device {
struct
spi_master
*
master
;
struct
spi_master
*
master
;
u32
max_speed_hz
;
u32
max_speed_hz
;
u8
chip_select
;
u8
chip_select
;
u
8
mode
;
u
16
mode
;
#define SPI_CPHA 0x01
/* clock phase */
#define SPI_CPHA 0x01
/* clock phase */
#define SPI_CPOL 0x02
/* clock polarity */
#define SPI_CPOL 0x02
/* clock polarity */
#define SPI_MODE_0 (0|0)
/* (original MicroWire) */
#define SPI_MODE_0 (0|0)
/* (original MicroWire) */
...
@@ -87,6 +87,10 @@ struct spi_device {
...
@@ -87,6 +87,10 @@ struct spi_device {
#define SPI_LOOP 0x20
/* loopback mode */
#define SPI_LOOP 0x20
/* loopback mode */
#define SPI_NO_CS 0x40
/* 1 dev/bus, no chipselect */
#define SPI_NO_CS 0x40
/* 1 dev/bus, no chipselect */
#define SPI_READY 0x80
/* slave pulls low to pause */
#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
;
u8
bits_per_word
;
int
irq
;
int
irq
;
void
*
controller_state
;
void
*
controller_state
;
...
@@ -256,6 +260,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
...
@@ -256,6 +260,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* @busy: message pump is busy
* @busy: message pump is busy
* @running: message pump is running
* @running: message pump is running
* @rt: whether this queue is set to run as a realtime task
* @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
* @prepare_transfer_hardware: a message will soon arrive from the queue
* so the subsystem requests the driver to prepare the transfer hardware
* so the subsystem requests the driver to prepare the transfer hardware
* by issuing this call
* by issuing this call
...
@@ -380,11 +387,13 @@ struct spi_master {
...
@@ -380,11 +387,13 @@ struct spi_master {
bool
busy
;
bool
busy
;
bool
running
;
bool
running
;
bool
rt
;
bool
rt
;
bool
auto_runtime_pm
;
int
(
*
prepare_transfer_hardware
)(
struct
spi_master
*
master
);
int
(
*
prepare_transfer_hardware
)(
struct
spi_master
*
master
);
int
(
*
transfer_one_message
)(
struct
spi_master
*
master
,
int
(
*
transfer_one_message
)(
struct
spi_master
*
master
,
struct
spi_message
*
mesg
);
struct
spi_message
*
mesg
);
int
(
*
unprepare_transfer_hardware
)(
struct
spi_master
*
master
);
int
(
*
unprepare_transfer_hardware
)(
struct
spi_master
*
master
);
/* gpio chip select */
/* gpio chip select */
int
*
cs_gpios
;
int
*
cs_gpios
;
};
};
...
@@ -454,6 +463,10 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
...
@@ -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
* @rx_buf: data to be read (dma-safe memory), or NULL
* @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
* @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
* @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)
* @len: size of rx and tx buffers (in bytes)
* @speed_hz: Select a speed other than the device default for this
* @speed_hz: Select a speed other than the device default for this
* transfer. If 0 the default (from @spi_device) is used.
* transfer. If 0 the default (from @spi_device) is used.
...
@@ -508,6 +521,11 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
...
@@ -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
* by the results of previous messages and where the whole transaction
* ends when the chipselect goes intactive.
* 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)
* The code that submits an spi_message (and its spi_transfers)
* to the lower layers is responsible for managing its memory.
* to the lower layers is responsible for managing its memory.
* Zero-initialize every field you don't set up explicitly, to
* Zero-initialize every field you don't set up explicitly, to
...
@@ -528,6 +546,11 @@ struct spi_transfer {
...
@@ -528,6 +546,11 @@ struct spi_transfer {
dma_addr_t
rx_dma
;
dma_addr_t
rx_dma
;
unsigned
cs_change
:
1
;
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
;
u8
bits_per_word
;
u16
delay_usecs
;
u16
delay_usecs
;
u32
speed_hz
;
u32
speed_hz
;
...
@@ -876,7 +899,7 @@ struct spi_board_info {
...
@@ -876,7 +899,7 @@ struct spi_board_info {
/* mode becomes spi_device.mode, and is essential for chips
/* mode becomes spi_device.mode, and is essential for chips
* where the default of SPI_CS_HIGH = 0 is wrong.
* 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.
/* ... may need additional spi_device chip config data here.
* avoid stuff protocol drivers can set; but include stuff
* 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