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
c1acb21b
Commit
c1acb21b
authored
Aug 10, 2018
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'spi-4.19' into spi-next
parents
c3c71262
401c0d77
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1167 additions
and
609 deletions
+1167
-609
Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
+4
-2
Documentation/devicetree/bindings/spi/spi-rockchip.txt
Documentation/devicetree/bindings/spi/spi-rockchip.txt
+1
-0
Documentation/devicetree/bindings/spi/spi-uniphier.txt
Documentation/devicetree/bindings/spi/spi-uniphier.txt
+22
-0
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/m25p80.c
+3
-0
drivers/spi/Kconfig
drivers/spi/Kconfig
+13
-0
drivers/spi/Makefile
drivers/spi/Makefile
+1
-0
drivers/spi/spi-ath79.c
drivers/spi/spi-ath79.c
+1
-1
drivers/spi/spi-bitbang.c
drivers/spi/spi-bitbang.c
+37
-13
drivers/spi/spi-butterfly.c
drivers/spi/spi-butterfly.c
+2
-2
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-dw-mmio.c
+90
-0
drivers/spi/spi-dw.c
drivers/spi/spi-dw.c
+5
-1
drivers/spi/spi-dw.h
drivers/spi/spi-dw.h
+2
-0
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-fsl-dspi.c
+259
-234
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-fsl-espi.c
+4
-1
drivers/spi/spi-gpio.c
drivers/spi/spi-gpio.c
+32
-17
drivers/spi/spi-img-spfi.c
drivers/spi/spi-img-spfi.c
+3
-0
drivers/spi/spi-imx.c
drivers/spi/spi-imx.c
+101
-61
drivers/spi/spi-lm70llp.c
drivers/spi/spi-lm70llp.c
+3
-2
drivers/spi/spi-mem.c
drivers/spi/spi-mem.c
+28
-0
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-omap2-mcspi.c
+0
-9
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-pxa2xx.c
+4
-0
drivers/spi/spi-sh-sci.c
drivers/spi/spi-sh-sci.c
+12
-8
drivers/spi/spi-uniphier.c
drivers/spi/spi-uniphier.c
+523
-0
drivers/spi/spi-xtensa-xtfpga.c
drivers/spi/spi-xtensa-xtfpga.c
+1
-1
include/linux/spi/adi_spi3.h
include/linux/spi/adi_spi3.h
+0
-254
include/linux/spi/spi-mem.h
include/linux/spi/spi-mem.h
+13
-1
include/linux/spi/spi_bitbang.h
include/linux/spi/spi_bitbang.h
+3
-2
No files found.
Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
View file @
c1acb21b
Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
Required properties:
- compatible : "snps,dw-apb-ssi"
- reg : The register base for the controller.
- compatible : "snps,dw-apb-ssi" or "mscc,<soc>-spi", where soc is "ocelot" or
"jaguar2"
- reg : The register base for the controller. For "mscc,<soc>-spi", a second
register set is required (named ICPU_CFG:SPI_MST)
- interrupts : One interrupt, used by the controller.
- #address-cells : <1>, as required by generic SPI binding.
- #size-cells : <0>, also as required by generic SPI binding.
...
...
Documentation/devicetree/bindings/spi/spi-rockchip.txt
View file @
c1acb21b
...
...
@@ -7,6 +7,7 @@ Required Properties:
- compatible: should be one of the following.
"rockchip,rv1108-spi" for rv1108 SoCs.
"rockchip,px30-spi", "rockchip,rk3066-spi" for px30 SoCs.
"rockchip,rk3036-spi" for rk3036 SoCS.
"rockchip,rk3066-spi" for rk3066 SoCs.
"rockchip,rk3188-spi" for rk3188 SoCs.
...
...
Documentation/devicetree/bindings/spi/spi-uniphier.txt
0 → 100644
View file @
c1acb21b
Socionext UniPhier SPI controller driver
UniPhier SoCs have SCSSI which supports SPI single channel.
Required properties:
- compatible: should be "socionext,uniphier-scssi"
- reg: address and length of the spi master registers
- #address-cells: must be <1>, see spi-bus.txt
- #size-cells: must be <0>, see spi-bus.txt
- clocks: A phandle to the clock for the device.
- resets: A phandle to the reset control for the device.
Example:
spi0: spi@54006000 {
compatible = "socionext,uniphier-scssi";
reg = <0x54006000 0x100>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&peri_clk 11>;
resets = <&peri_rst 11>;
};
drivers/mtd/devices/m25p80.c
View file @
c1acb21b
...
...
@@ -202,6 +202,9 @@ static int m25p_probe(struct spi_mem *spimem)
if
(
data
&&
data
->
name
)
nor
->
mtd
.
name
=
data
->
name
;
if
(
!
nor
->
mtd
.
name
)
nor
->
mtd
.
name
=
spi_mem_get_name
(
spimem
);
/* For some (historical?) reason many platforms provide two different
* names in flash_platform_data: "name" and "type". Quite often name is
* set to "m25p80" and then "type" provides a real chip name.
...
...
drivers/spi/Kconfig
View file @
c1acb21b
...
...
@@ -688,6 +688,19 @@ config SPI_TXX9
help
SPI driver for Toshiba TXx9 MIPS SoCs
config SPI_UNIPHIER
tristate "Socionext UniPhier SPI Controller"
depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
help
This enables a driver for the Socionext UniPhier SoC SCSSI SPI controller.
UniPhier SoCs have SCSSI and MCSSI SPI controllers.
Every UniPhier SoC has SCSSI which supports single channel.
Older UniPhier Pro4/Pro5 also has MCSSI which support multiple channels.
This driver supports SCSSI only.
If your SoC supports SCSSI, say Y here.
config SPI_XCOMM
tristate "Analog Devices AD-FMCOMMS1-EBZ SPI-I2C-bridge driver"
depends on I2C
...
...
drivers/spi/Makefile
View file @
c1acb21b
...
...
@@ -101,6 +101,7 @@ spi-thunderx-objs := spi-cavium.o spi-cavium-thunderx.o
obj-$(CONFIG_SPI_THUNDERX)
+=
spi-thunderx.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH)
+=
spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9)
+=
spi-txx9.o
obj-$(CONFIG_SPI_UNIPHIER)
+=
spi-uniphier.o
obj-$(CONFIG_SPI_XCOMM)
+=
spi-xcomm.o
obj-$(CONFIG_SPI_XILINX)
+=
spi-xilinx.o
obj-$(CONFIG_SPI_XLP)
+=
spi-xlp.o
...
...
drivers/spi/spi-ath79.c
View file @
c1acb21b
...
...
@@ -176,7 +176,7 @@ static void ath79_spi_cleanup(struct spi_device *spi)
}
static
u32
ath79_spi_txrx_mode0
(
struct
spi_device
*
spi
,
unsigned
int
nsecs
,
u32
word
,
u8
bits
)
u32
word
,
u8
bits
,
unsigned
flags
)
{
struct
ath79_spi
*
sp
=
ath79_spidev_to_sp
(
spi
);
u32
ioc
=
sp
->
ioc_base
;
...
...
drivers/spi/spi-bitbang.c
View file @
c1acb21b
...
...
@@ -49,22 +49,26 @@
struct
spi_bitbang_cs
{
unsigned
nsecs
;
/* (clock cycle time)/2 */
u32
(
*
txrx_word
)(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
);
u32
word
,
u8
bits
,
unsigned
flags
);
unsigned
(
*
txrx_bufs
)(
struct
spi_device
*
,
u32
(
*
txrx_word
)(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
),
unsigned
,
struct
spi_transfer
*
);
u32
word
,
u8
bits
,
unsigned
flags
),
unsigned
,
struct
spi_transfer
*
,
unsigned
);
};
static
unsigned
bitbang_txrx_8
(
struct
spi_device
*
spi
,
u32
(
*
txrx_word
)(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
),
u32
word
,
u8
bits
,
unsigned
flags
),
unsigned
ns
,
struct
spi_transfer
*
t
struct
spi_transfer
*
t
,
unsigned
flags
)
{
unsigned
bits
=
t
->
bits_per_word
;
unsigned
count
=
t
->
len
;
...
...
@@ -76,7 +80,7 @@ static unsigned bitbang_txrx_8(
if
(
tx
)
word
=
*
tx
++
;
word
=
txrx_word
(
spi
,
ns
,
word
,
bits
);
word
=
txrx_word
(
spi
,
ns
,
word
,
bits
,
flags
);
if
(
rx
)
*
rx
++
=
word
;
count
-=
1
;
...
...
@@ -88,9 +92,11 @@ static unsigned bitbang_txrx_16(
struct
spi_device
*
spi
,
u32
(
*
txrx_word
)(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
),
u32
word
,
u8
bits
,
unsigned
flags
),
unsigned
ns
,
struct
spi_transfer
*
t
struct
spi_transfer
*
t
,
unsigned
flags
)
{
unsigned
bits
=
t
->
bits_per_word
;
unsigned
count
=
t
->
len
;
...
...
@@ -102,7 +108,7 @@ static unsigned bitbang_txrx_16(
if
(
tx
)
word
=
*
tx
++
;
word
=
txrx_word
(
spi
,
ns
,
word
,
bits
);
word
=
txrx_word
(
spi
,
ns
,
word
,
bits
,
flags
);
if
(
rx
)
*
rx
++
=
word
;
count
-=
2
;
...
...
@@ -114,9 +120,11 @@ static unsigned bitbang_txrx_32(
struct
spi_device
*
spi
,
u32
(
*
txrx_word
)(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
),
u32
word
,
u8
bits
,
unsigned
flags
),
unsigned
ns
,
struct
spi_transfer
*
t
struct
spi_transfer
*
t
,
unsigned
flags
)
{
unsigned
bits
=
t
->
bits_per_word
;
unsigned
count
=
t
->
len
;
...
...
@@ -128,7 +136,7 @@ static unsigned bitbang_txrx_32(
if
(
tx
)
word
=
*
tx
++
;
word
=
txrx_word
(
spi
,
ns
,
word
,
bits
);
word
=
txrx_word
(
spi
,
ns
,
word
,
bits
,
flags
);
if
(
rx
)
*
rx
++
=
word
;
count
-=
4
;
...
...
@@ -235,8 +243,24 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct
spi_bitbang_cs
*
cs
=
spi
->
controller_state
;
unsigned
nsecs
=
cs
->
nsecs
;
struct
spi_bitbang
*
bitbang
;
bitbang
=
spi_master_get_devdata
(
spi
->
master
);
if
(
bitbang
->
set_line_direction
)
{
int
err
;
return
cs
->
txrx_bufs
(
spi
,
cs
->
txrx_word
,
nsecs
,
t
);
err
=
bitbang
->
set_line_direction
(
spi
,
!!
(
t
->
tx_buf
));
if
(
err
<
0
)
return
err
;
}
if
(
spi
->
mode
&
SPI_3WIRE
)
{
unsigned
flags
;
flags
=
t
->
tx_buf
?
SPI_MASTER_NO_RX
:
SPI_MASTER_NO_TX
;
return
cs
->
txrx_bufs
(
spi
,
cs
->
txrx_word
,
nsecs
,
t
,
flags
);
}
return
cs
->
txrx_bufs
(
spi
,
cs
->
txrx_word
,
nsecs
,
t
,
0
);
}
/*----------------------------------------------------------------------*/
...
...
drivers/spi/spi-butterfly.c
View file @
c1acb21b
...
...
@@ -144,9 +144,9 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
static
u32
butterfly_txrx_word_mode0
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
/*----------------------------------------------------------------------*/
...
...
drivers/spi/spi-dw-mmio.c
View file @
c1acb21b
...
...
@@ -15,11 +15,13 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/scatterlist.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include "spi-dw.h"
...
...
@@ -28,10 +30,90 @@
struct
dw_spi_mmio
{
struct
dw_spi
dws
;
struct
clk
*
clk
;
void
*
priv
;
};
#define MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24
#define OCELOT_IF_SI_OWNER_MASK GENMASK(5, 4)
#define OCELOT_IF_SI_OWNER_OFFSET 4
#define MSCC_IF_SI_OWNER_SISL 0
#define MSCC_IF_SI_OWNER_SIBM 1
#define MSCC_IF_SI_OWNER_SIMC 2
#define MSCC_SPI_MST_SW_MODE 0x14
#define MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE BIT(13)
#define MSCC_SPI_MST_SW_MODE_SW_SPI_CS(x) (x << 5)
struct
dw_spi_mscc
{
struct
regmap
*
syscon
;
void
__iomem
*
spi_mst
;
};
/*
* The Designware SPI controller (referred to as master in the documentation)
* automatically deasserts chip select when the tx fifo is empty. The chip
* selects then needs to be either driven as GPIOs or, for the first 4 using the
* the SPI boot controller registers. the final chip select is an OR gate
* between the Designware SPI controller and the SPI boot controller.
*/
static
void
dw_spi_mscc_set_cs
(
struct
spi_device
*
spi
,
bool
enable
)
{
struct
dw_spi
*
dws
=
spi_master_get_devdata
(
spi
->
master
);
struct
dw_spi_mmio
*
dwsmmio
=
container_of
(
dws
,
struct
dw_spi_mmio
,
dws
);
struct
dw_spi_mscc
*
dwsmscc
=
dwsmmio
->
priv
;
u32
cs
=
spi
->
chip_select
;
if
(
cs
<
4
)
{
u32
sw_mode
=
MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE
;
if
(
!
enable
)
sw_mode
|=
MSCC_SPI_MST_SW_MODE_SW_SPI_CS
(
BIT
(
cs
));
writel
(
sw_mode
,
dwsmscc
->
spi_mst
+
MSCC_SPI_MST_SW_MODE
);
}
dw_spi_set_cs
(
spi
,
enable
);
}
static
int
dw_spi_mscc_init
(
struct
platform_device
*
pdev
,
struct
dw_spi_mmio
*
dwsmmio
)
{
struct
dw_spi_mscc
*
dwsmscc
;
struct
resource
*
res
;
dwsmscc
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
dwsmscc
),
GFP_KERNEL
);
if
(
!
dwsmscc
)
return
-
ENOMEM
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
1
);
dwsmscc
->
spi_mst
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
dwsmscc
->
spi_mst
))
{
dev_err
(
&
pdev
->
dev
,
"SPI_MST region map failed
\n
"
);
return
PTR_ERR
(
dwsmscc
->
spi_mst
);
}
dwsmscc
->
syscon
=
syscon_regmap_lookup_by_compatible
(
"mscc,ocelot-cpu-syscon"
);
if
(
IS_ERR
(
dwsmscc
->
syscon
))
return
PTR_ERR
(
dwsmscc
->
syscon
);
/* Deassert all CS */
writel
(
0
,
dwsmscc
->
spi_mst
+
MSCC_SPI_MST_SW_MODE
);
/* Select the owner of the SI interface */
regmap_update_bits
(
dwsmscc
->
syscon
,
MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL
,
OCELOT_IF_SI_OWNER_MASK
,
MSCC_IF_SI_OWNER_SIMC
<<
OCELOT_IF_SI_OWNER_OFFSET
);
dwsmmio
->
dws
.
set_cs
=
dw_spi_mscc_set_cs
;
dwsmmio
->
priv
=
dwsmscc
;
return
0
;
}
static
int
dw_spi_mmio_probe
(
struct
platform_device
*
pdev
)
{
int
(
*
init_func
)(
struct
platform_device
*
pdev
,
struct
dw_spi_mmio
*
dwsmmio
);
struct
dw_spi_mmio
*
dwsmmio
;
struct
dw_spi
*
dws
;
struct
resource
*
mem
;
...
...
@@ -99,6 +181,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
}
}
init_func
=
device_get_match_data
(
&
pdev
->
dev
);
if
(
init_func
)
{
ret
=
init_func
(
pdev
,
dwsmmio
);
if
(
ret
)
goto
out
;
}
ret
=
dw_spi_add_host
(
&
pdev
->
dev
,
dws
);
if
(
ret
)
goto
out
;
...
...
@@ -123,6 +212,7 @@ static int dw_spi_mmio_remove(struct platform_device *pdev)
static
const
struct
of_device_id
dw_spi_mmio_of_match
[]
=
{
{
.
compatible
=
"snps,dw-apb-ssi"
,
},
{
.
compatible
=
"mscc,ocelot-spi"
,
.
data
=
dw_spi_mscc_init
},
{
/* end of table */
}
};
MODULE_DEVICE_TABLE
(
of
,
dw_spi_mmio_of_match
);
...
...
drivers/spi/spi-dw.c
View file @
c1acb21b
...
...
@@ -133,7 +133,7 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
}
#endif
/* CONFIG_DEBUG_FS */
static
void
dw_spi_set_cs
(
struct
spi_device
*
spi
,
bool
enable
)
void
dw_spi_set_cs
(
struct
spi_device
*
spi
,
bool
enable
)
{
struct
dw_spi
*
dws
=
spi_controller_get_devdata
(
spi
->
controller
);
struct
chip_data
*
chip
=
spi_get_ctldata
(
spi
);
...
...
@@ -145,6 +145,7 @@ static void dw_spi_set_cs(struct spi_device *spi, bool enable)
if
(
!
enable
)
dw_writel
(
dws
,
DW_SPI_SER
,
BIT
(
spi
->
chip_select
));
}
EXPORT_SYMBOL_GPL
(
dw_spi_set_cs
);
/* Return the max entries we can fill into tx fifo */
static
inline
u32
tx_max
(
struct
dw_spi
*
dws
)
...
...
@@ -507,6 +508,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master
->
dev
.
of_node
=
dev
->
of_node
;
master
->
flags
=
SPI_MASTER_GPIO_SS
;
if
(
dws
->
set_cs
)
master
->
set_cs
=
dws
->
set_cs
;
/* Basic HW init */
spi_hw_init
(
dev
,
dws
);
...
...
drivers/spi/spi-dw.h
View file @
c1acb21b
...
...
@@ -112,6 +112,7 @@ struct dw_spi {
u32
reg_io_width
;
/* DR I/O width in bytes */
u16
bus_num
;
u16
num_cs
;
/* supported slave numbers */
void
(
*
set_cs
)(
struct
spi_device
*
spi
,
bool
enable
);
/* Current message transfer state info */
size_t
len
;
...
...
@@ -244,6 +245,7 @@ struct dw_spi_chip {
void
(
*
cs_control
)(
u32
command
);
};
extern
void
dw_spi_set_cs
(
struct
spi_device
*
spi
,
bool
enable
);
extern
int
dw_spi_add_host
(
struct
device
*
dev
,
struct
dw_spi
*
dws
);
extern
void
dw_spi_remove_host
(
struct
dw_spi
*
dws
);
extern
int
dw_spi_suspend_host
(
struct
dw_spi
*
dws
);
...
...
drivers/spi/spi-fsl-dspi.c
View file @
c1acb21b
/*
* drivers/spi/spi-fsl-dspi.c
*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Freescale DSPI driver
* This file contains a driver for the Freescale DSPI
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright 2013 Freescale Semiconductor, Inc.
//
// Freescale DSPI driver
// This file contains a driver for the Freescale DSPI
#include <linux/clk.h>
#include <linux/delay.h>
...
...
@@ -38,10 +30,6 @@
#define DRIVER_NAME "fsl-dspi"
#define TRAN_STATE_RX_VOID 0x01
#define TRAN_STATE_TX_VOID 0x02
#define TRAN_STATE_WORD_ODD_NUM 0x04
#define DSPI_FIFO_SIZE 4
#define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024)
...
...
@@ -50,6 +38,7 @@
#define SPI_MCR_PCSIS (0x3F << 16)
#define SPI_MCR_CLR_TXF (1 << 11)
#define SPI_MCR_CLR_RXF (1 << 10)
#define SPI_MCR_XSPI (1 << 3)
#define SPI_TCR 0x08
#define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16)
...
...
@@ -86,11 +75,16 @@
#define SPI_RSER_TCFQE 0x80000000
#define SPI_PUSHR 0x34
#define SPI_PUSHR_CONT (1 << 31)
#define SPI_PUSHR_CTAS(x) (((x) & 0x00000003) << 28)
#define SPI_PUSHR_EOQ (1 << 27)
#define SPI_PUSHR_CTCNT (1 << 26)
#define SPI_PUSHR_PCS(x) (((1 << x) & 0x0000003f) << 16)
#define SPI_PUSHR_CMD_CONT (1 << 15)
#define SPI_PUSHR_CONT (SPI_PUSHR_CMD_CONT << 16)
#define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12)
#define SPI_PUSHR_CTAS(x) (SPI_PUSHR_CMD_CTAS(x) << 16)
#define SPI_PUSHR_CMD_EOQ (1 << 11)
#define SPI_PUSHR_EOQ (SPI_PUSHR_CMD_EOQ << 16)
#define SPI_PUSHR_CMD_CTCNT (1 << 10)
#define SPI_PUSHR_CTCNT (SPI_PUSHR_CMD_CTCNT << 16)
#define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f)
#define SPI_PUSHR_PCS(x) (SPI_PUSHR_CMD_PCS(x) << 16)
#define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff)
#define SPI_PUSHR_SLAVE 0x34
...
...
@@ -107,21 +101,31 @@
#define SPI_RXFR2 0x84
#define SPI_RXFR3 0x88
#define SPI_CTARE(x) (0x11c + (((x) & 0x3) * 4))
#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16)
#define SPI_CTARE_DTCP(x) ((x) & 0x7ff)
#define SPI_SREX 0x13c
#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1)
#define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf)
#define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf)
#define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7)
#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4)
#define SPI_FRAME_EBITS_MASK SPI_CTARE_FMSZE(1)
/* Register offsets for regmap_pushr */
#define PUSHR_CMD 0x0
#define PUSHR_TX 0x2
#define SPI_CS_INIT 0x01
#define SPI_CS_ASSERT 0x02
#define SPI_CS_DROP 0x04
#define SPI_TCR_TCNT_MAX 0x10000
#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000)
struct
chip_data
{
u32
mcr_val
;
u32
ctar_val
;
u16
void_write_data
;
};
...
...
@@ -135,6 +139,7 @@ enum dspi_trans_mode {
struct
fsl_dspi_devtype_data
{
enum
dspi_trans_mode
trans_mode
;
u8
max_clock_factor
;
bool
xspi_mode
;
};
static
const
struct
fsl_dspi_devtype_data
vf610_data
=
{
...
...
@@ -145,6 +150,7 @@ static const struct fsl_dspi_devtype_data vf610_data = {
static
const
struct
fsl_dspi_devtype_data
ls1021a_v1_data
=
{
.
trans_mode
=
DSPI_TCFQ_MODE
,
.
max_clock_factor
=
8
,
.
xspi_mode
=
true
,
};
static
const
struct
fsl_dspi_devtype_data
ls2085a_data
=
{
...
...
@@ -179,6 +185,7 @@ struct fsl_dspi {
struct
platform_device
*
pdev
;
struct
regmap
*
regmap
;
struct
regmap
*
regmap_pushr
;
int
irq
;
struct
clk
*
clk
;
...
...
@@ -186,32 +193,62 @@ struct fsl_dspi {
struct
spi_message
*
cur_msg
;
struct
chip_data
*
cur_chip
;
size_t
len
;
void
*
tx
;
void
*
tx_end
;
const
void
*
tx
;
void
*
rx
;
void
*
rx_end
;
char
dataflags
;
u8
cs
;
u16
void_write_data
;
u32
cs_change
;
u16
tx_cmd
;
u8
bits_per_word
;
u8
bytes_per_word
;
const
struct
fsl_dspi_devtype_data
*
devtype_data
;
wait_queue_head_t
waitq
;
u32
waitflags
;
u32
spi_tcnt
;
struct
fsl_dspi_dma
*
dma
;
};
static
u32
dspi_data_to_pushr
(
struct
fsl_dspi
*
dspi
,
int
tx_word
);
static
u32
dspi_pop_tx
(
struct
fsl_dspi
*
dspi
)
{
u32
txdata
=
0
;
if
(
dspi
->
tx
)
{
if
(
dspi
->
bytes_per_word
==
1
)
txdata
=
*
(
u8
*
)
dspi
->
tx
;
else
if
(
dspi
->
bytes_per_word
==
2
)
txdata
=
*
(
u16
*
)
dspi
->
tx
;
else
/* dspi->bytes_per_word == 4 */
txdata
=
*
(
u32
*
)
dspi
->
tx
;
dspi
->
tx
+=
dspi
->
bytes_per_word
;
}
dspi
->
len
-=
dspi
->
bytes_per_word
;
return
txdata
;
}
static
inline
int
is_double_byte_mode
(
struct
fsl_dspi
*
dspi
)
static
u32
dspi_pop_tx_pushr
(
struct
fsl_dspi
*
dspi
)
{
u
nsigned
int
val
;
u
16
cmd
=
dspi
->
tx_cmd
,
data
=
dspi_pop_tx
(
dspi
)
;
regmap_read
(
dspi
->
regmap
,
SPI_CTAR
(
0
),
&
val
);
if
(
dspi
->
len
>
0
)
cmd
|=
SPI_PUSHR_CMD_CONT
;
return
cmd
<<
16
|
data
;
}
return
((
val
&
SPI_FRAME_BITS_MASK
)
==
SPI_FRAME_BITS
(
8
))
?
0
:
1
;
static
void
dspi_push_rx
(
struct
fsl_dspi
*
dspi
,
u32
rxdata
)
{
if
(
!
dspi
->
rx
)
return
;
/* Mask of undefined bits */
rxdata
&=
(
1
<<
dspi
->
bits_per_word
)
-
1
;
if
(
dspi
->
bytes_per_word
==
1
)
*
(
u8
*
)
dspi
->
rx
=
rxdata
;
else
if
(
dspi
->
bytes_per_word
==
2
)
*
(
u16
*
)
dspi
->
rx
=
rxdata
;
else
/* dspi->bytes_per_word == 4 */
*
(
u32
*
)
dspi
->
rx
=
rxdata
;
dspi
->
rx
+=
dspi
->
bytes_per_word
;
}
static
void
dspi_tx_dma_callback
(
void
*
arg
)
...
...
@@ -226,19 +263,11 @@ static void dspi_rx_dma_callback(void *arg)
{
struct
fsl_dspi
*
dspi
=
arg
;
struct
fsl_dspi_dma
*
dma
=
dspi
->
dma
;
int
rx_word
;
int
i
;
u16
d
;
rx_word
=
is_double_byte_mode
(
dspi
);
if
(
!
(
dspi
->
dataflags
&
TRAN_STATE_RX_VOID
))
{
for
(
i
=
0
;
i
<
dma
->
curr_xfer_len
;
i
++
)
{
d
=
dspi
->
dma
->
rx_dma_buf
[
i
];
rx_word
?
(
*
(
u16
*
)
dspi
->
rx
=
d
)
:
(
*
(
u8
*
)
dspi
->
rx
=
d
);
dspi
->
rx
+=
rx_word
+
1
;
}
if
(
dspi
->
rx
)
{
for
(
i
=
0
;
i
<
dma
->
curr_xfer_len
;
i
++
)
dspi_push_rx
(
dspi
,
dspi
->
dma
->
rx_dma_buf
[
i
]);
}
complete
(
&
dma
->
cmd_rx_complete
);
...
...
@@ -249,16 +278,10 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
struct
fsl_dspi_dma
*
dma
=
dspi
->
dma
;
struct
device
*
dev
=
&
dspi
->
pdev
->
dev
;
int
time_left
;
int
tx_word
;
int
i
;
tx_word
=
is_double_byte_mode
(
dspi
);
for
(
i
=
0
;
i
<
dma
->
curr_xfer_len
;
i
++
)
{
dspi
->
dma
->
tx_dma_buf
[
i
]
=
dspi_data_to_pushr
(
dspi
,
tx_word
);
if
((
dspi
->
cs_change
)
&&
(
!
dspi
->
len
))
dspi
->
dma
->
tx_dma_buf
[
i
]
&=
~
SPI_PUSHR_CONT
;
}
for
(
i
=
0
;
i
<
dma
->
curr_xfer_len
;
i
++
)
dspi
->
dma
->
tx_dma_buf
[
i
]
=
dspi_pop_tx_pushr
(
dspi
);
dma
->
tx_desc
=
dmaengine_prep_slave_single
(
dma
->
chan_tx
,
dma
->
tx_dma_phys
,
...
...
@@ -327,18 +350,17 @@ static int dspi_dma_xfer(struct fsl_dspi *dspi)
{
struct
fsl_dspi_dma
*
dma
=
dspi
->
dma
;
struct
device
*
dev
=
&
dspi
->
pdev
->
dev
;
struct
spi_message
*
message
=
dspi
->
cur_msg
;
int
curr_remaining_bytes
;
int
bytes_per_buffer
;
int
word
=
1
;
int
ret
=
0
;
if
(
is_double_byte_mode
(
dspi
))
word
=
2
;
curr_remaining_bytes
=
dspi
->
len
;
bytes_per_buffer
=
DSPI_DMA_BUFSIZE
/
DSPI_FIFO_SIZE
;
while
(
curr_remaining_bytes
)
{
/* Check if current transfer fits the DMA buffer */
dma
->
curr_xfer_len
=
curr_remaining_bytes
/
word
;
dma
->
curr_xfer_len
=
curr_remaining_bytes
/
dspi
->
bytes_per_word
;
if
(
dma
->
curr_xfer_len
>
bytes_per_buffer
)
dma
->
curr_xfer_len
=
bytes_per_buffer
;
...
...
@@ -348,7 +370,10 @@ static int dspi_dma_xfer(struct fsl_dspi *dspi)
goto
exit
;
}
else
{
curr_remaining_bytes
-=
dma
->
curr_xfer_len
*
word
;
const
int
len
=
dma
->
curr_xfer_len
*
dspi
->
bytes_per_word
;
curr_remaining_bytes
-=
len
;
message
->
actual_length
+=
len
;
if
(
curr_remaining_bytes
<
0
)
curr_remaining_bytes
=
0
;
}
...
...
@@ -534,125 +559,91 @@ static void ns_delay_scale(char *psc, char *sc, int delay_ns,
}
}
static
u32
dspi_data_to_pushr
(
struct
fsl_dspi
*
dspi
,
int
tx_word
)
static
void
fifo_write
(
struct
fsl_dspi
*
dspi
)
{
u16
d16
;
if
(
!
(
dspi
->
dataflags
&
TRAN_STATE_TX_VOID
))
d16
=
tx_word
?
*
(
u16
*
)
dspi
->
tx
:
*
(
u8
*
)
dspi
->
tx
;
else
d16
=
dspi
->
void_write_data
;
dspi
->
tx
+=
tx_word
+
1
;
dspi
->
len
-=
tx_word
+
1
;
return
SPI_PUSHR_TXDATA
(
d16
)
|
SPI_PUSHR_PCS
(
dspi
->
cs
)
|
SPI_PUSHR_CTAS
(
0
)
|
SPI_PUSHR_CONT
;
regmap_write
(
dspi
->
regmap
,
SPI_PUSHR
,
dspi_pop_tx_pushr
(
dspi
));
}
static
void
dspi_data_from_popr
(
struct
fsl_dspi
*
dspi
,
int
rx_word
)
static
void
cmd_fifo_write
(
struct
fsl_dspi
*
dspi
)
{
u16
d
;
unsigned
int
val
;
regmap_read
(
dspi
->
regmap
,
SPI_POPR
,
&
val
);
d
=
SPI_POPR_RXDATA
(
val
);
u16
cmd
=
dspi
->
tx_cmd
;
if
(
!
(
dspi
->
dataflags
&
TRAN_STATE_RX_VOID
))
rx_word
?
(
*
(
u16
*
)
dspi
->
rx
=
d
)
:
(
*
(
u8
*
)
dspi
->
rx
=
d
);
dspi
->
rx
+=
rx_word
+
1
;
if
(
dspi
->
len
>
0
)
cmd
|=
SPI_PUSHR_CMD_CONT
;
regmap_write
(
dspi
->
regmap_pushr
,
PUSHR_CMD
,
cmd
);
}
static
int
dspi_eoq_write
(
struct
fsl_dspi
*
dspi
)
static
void
tx_fifo_write
(
struct
fsl_dspi
*
dspi
,
u16
txdata
)
{
int
tx_count
=
0
;
int
tx_word
;
u32
dspi_pushr
=
0
;
regmap_write
(
dspi
->
regmap_pushr
,
PUSHR_TX
,
txdata
);
}
tx_word
=
is_double_byte_mode
(
dspi
);
static
void
dspi_tcfq_write
(
struct
fsl_dspi
*
dspi
)
{
/* Clear transfer count */
dspi
->
tx_cmd
|=
SPI_PUSHR_CMD_CTCNT
;
while
(
dspi
->
len
&&
(
tx_count
<
DSPI_FIFO_SIZE
))
{
/* If we are in word mode, only have a single byte to transfer
* switch to byte mode temporarily. Will switch back at the
* end of the transfer.
if
(
dspi
->
devtype_data
->
xspi_mode
&&
dspi
->
bits_per_word
>
16
)
{
/* Write two TX FIFO entries first, and then the corresponding
* CMD FIFO entry.
*/
if
(
tx_word
&&
(
dspi
->
len
==
1
))
{
dspi
->
dataflags
|=
TRAN_STATE_WORD_ODD_NUM
;
regmap_update_bits
(
dspi
->
regmap
,
SPI_CTAR
(
0
),
SPI_FRAME_BITS_MASK
,
SPI_FRAME_BITS
(
8
));
tx_word
=
0
;
}
dspi_pushr
=
dspi_data_to_pushr
(
dspi
,
tx_word
);
if
(
dspi
->
len
==
0
||
tx_count
==
DSPI_FIFO_SIZE
-
1
)
{
/* last transfer in the transfer */
dspi_pushr
|=
SPI_PUSHR_EOQ
;
if
((
dspi
->
cs_change
)
&&
(
!
dspi
->
len
))
dspi_pushr
&=
~
SPI_PUSHR_CONT
;
}
else
if
(
tx_word
&&
(
dspi
->
len
==
1
))
dspi_pushr
|=
SPI_PUSHR_EOQ
;
u32
data
=
dspi_pop_tx
(
dspi
);
regmap_write
(
dspi
->
regmap
,
SPI_PUSHR
,
dspi_pushr
);
tx_count
++
;
if
(
dspi
->
cur_chip
->
ctar_val
&
SPI_CTAR_LSBFE
(
1
))
{
/* LSB */
tx_fifo_write
(
dspi
,
data
&
0xFFFF
);
tx_fifo_write
(
dspi
,
data
>>
16
);
}
else
{
/* MSB */
tx_fifo_write
(
dspi
,
data
>>
16
);
tx_fifo_write
(
dspi
,
data
&
0xFFFF
);
}
cmd_fifo_write
(
dspi
);
}
else
{
/* Write one entry to both TX FIFO and CMD FIFO
* simultaneously.
*/
fifo_write
(
dspi
);
}
return
tx_count
*
(
tx_word
+
1
);
}
static
int
dspi_eoq
_read
(
struct
fsl_dspi
*
dspi
)
static
u32
fifo
_read
(
struct
fsl_dspi
*
dspi
)
{
int
rx_count
=
0
;
int
rx_word
=
is_double_byte_mode
(
dspi
);
while
((
dspi
->
rx
<
dspi
->
rx_end
)
&&
(
rx_count
<
DSPI_FIFO_SIZE
))
{
if
(
rx_word
&&
(
dspi
->
rx_end
-
dspi
->
rx
)
==
1
)
rx_word
=
0
;
u32
rxdata
=
0
;
dspi_data_from_popr
(
dspi
,
rx_word
);
rx_count
++
;
}
return
rx_count
;
regmap_read
(
dspi
->
regmap
,
SPI_POPR
,
&
rxdata
);
return
rxdata
;
}
static
int
dspi_tcfq_write
(
struct
fsl_dspi
*
dspi
)
static
void
dspi_tcfq_read
(
struct
fsl_dspi
*
dspi
)
{
int
tx_word
;
u32
dspi_pushr
=
0
;
tx_word
=
is_double_byte_mode
(
dspi
);
dspi_push_rx
(
dspi
,
fifo_read
(
dspi
));
}
if
(
tx_word
&&
(
dspi
->
len
==
1
))
{
dspi
->
dataflags
|=
TRAN_STATE_WORD_ODD_NUM
;
regmap_update_bits
(
dspi
->
regmap
,
SPI_CTAR
(
0
),
SPI_FRAME_BITS_MASK
,
SPI_FRAME_BITS
(
8
));
tx_word
=
0
;
static
void
dspi_eoq_write
(
struct
fsl_dspi
*
dspi
)
{
int
fifo_size
=
DSPI_FIFO_SIZE
;
/* Fill TX FIFO with as many transfers as possible */
while
(
dspi
->
len
&&
fifo_size
--
)
{
/* Request EOQF for last transfer in FIFO */
if
(
dspi
->
len
==
dspi
->
bytes_per_word
||
fifo_size
==
0
)
dspi
->
tx_cmd
|=
SPI_PUSHR_CMD_EOQ
;
/* Clear transfer count for first transfer in FIFO */
if
(
fifo_size
==
(
DSPI_FIFO_SIZE
-
1
))
dspi
->
tx_cmd
|=
SPI_PUSHR_CMD_CTCNT
;
/* Write combined TX FIFO and CMD FIFO entry */
fifo_write
(
dspi
);
}
dspi_pushr
=
dspi_data_to_pushr
(
dspi
,
tx_word
);
if
((
dspi
->
cs_change
)
&&
(
!
dspi
->
len
))
dspi_pushr
&=
~
SPI_PUSHR_CONT
;
regmap_write
(
dspi
->
regmap
,
SPI_PUSHR
,
dspi_pushr
);
return
tx_word
+
1
;
}
static
void
dspi_
tcf
q_read
(
struct
fsl_dspi
*
dspi
)
static
void
dspi_
eo
q_read
(
struct
fsl_dspi
*
dspi
)
{
int
rx_word
=
is_double_byte_mode
(
dspi
);
if
(
rx_word
&&
(
dspi
->
rx_end
-
dspi
->
rx
)
==
1
)
rx_word
=
0
;
int
fifo_size
=
DSPI_FIFO_SIZE
;
dspi_data_from_popr
(
dspi
,
rx_word
);
/* Read one FIFO entry at and push to rx buffer */
while
((
dspi
->
rx
<
dspi
->
rx_end
)
&&
fifo_size
--
)
dspi_push_rx
(
dspi
,
fifo_read
(
dspi
));
}
static
int
dspi_transfer_one_message
(
struct
spi_master
*
master
,
...
...
@@ -663,10 +654,6 @@ static int dspi_transfer_one_message(struct spi_master *master,
struct
spi_transfer
*
transfer
;
int
status
=
0
;
enum
dspi_trans_mode
trans_mode
;
u32
spi_tcr
;
regmap_read
(
dspi
->
regmap
,
SPI_TCR
,
&
spi_tcr
);
dspi
->
spi_tcnt
=
SPI_TCR_GET_TCNT
(
spi_tcr
);
message
->
actual_length
=
0
;
...
...
@@ -674,32 +661,51 @@ static int dspi_transfer_one_message(struct spi_master *master,
dspi
->
cur_transfer
=
transfer
;
dspi
->
cur_msg
=
message
;
dspi
->
cur_chip
=
spi_get_ctldata
(
spi
);
dspi
->
cs
=
spi
->
chip_select
;
dspi
->
cs_change
=
0
;
/* Prepare command word for CMD FIFO */
dspi
->
tx_cmd
=
SPI_PUSHR_CMD_CTAS
(
0
)
|
SPI_PUSHR_CMD_PCS
(
spi
->
chip_select
);
if
(
list_is_last
(
&
dspi
->
cur_transfer
->
transfer_list
,
&
dspi
->
cur_msg
->
transfers
)
||
transfer
->
cs_change
)
dspi
->
cs_change
=
1
;
&
dspi
->
cur_msg
->
transfers
))
{
/* Leave PCS activated after last transfer when
* cs_change is set.
*/
if
(
transfer
->
cs_change
)
dspi
->
tx_cmd
|=
SPI_PUSHR_CMD_CONT
;
}
else
{
/* Keep PCS active between transfers in same message
* when cs_change is not set, and de-activate PCS
* between transfers in the same message when
* cs_change is set.
*/
if
(
!
transfer
->
cs_change
)
dspi
->
tx_cmd
|=
SPI_PUSHR_CMD_CONT
;
}
dspi
->
void_write_data
=
dspi
->
cur_chip
->
void_write_data
;
dspi
->
dataflags
=
0
;
dspi
->
tx
=
(
void
*
)
transfer
->
tx_buf
;
dspi
->
tx_end
=
dspi
->
tx
+
transfer
->
len
;
dspi
->
tx
=
transfer
->
tx_buf
;
dspi
->
rx
=
transfer
->
rx_buf
;
dspi
->
rx_end
=
dspi
->
rx
+
transfer
->
len
;
dspi
->
len
=
transfer
->
len
;
/* Validated transfer specific frame size (defaults applied) */
dspi
->
bits_per_word
=
transfer
->
bits_per_word
;
if
(
transfer
->
bits_per_word
<=
8
)
dspi
->
bytes_per_word
=
1
;
else
if
(
transfer
->
bits_per_word
<=
16
)
dspi
->
bytes_per_word
=
2
;
else
dspi
->
bytes_per_word
=
4
;
if
(
!
dspi
->
rx
)
dspi
->
dataflags
|=
TRAN_STATE_RX_VOID
;
if
(
!
dspi
->
tx
)
dspi
->
dataflags
|=
TRAN_STATE_TX_VOID
;
regmap_write
(
dspi
->
regmap
,
SPI_MCR
,
dspi
->
cur_chip
->
mcr_val
);
regmap_update_bits
(
dspi
->
regmap
,
SPI_MCR
,
SPI_MCR_CLR_TXF
|
SPI_MCR_CLR_RXF
,
SPI_MCR_CLR_TXF
|
SPI_MCR_CLR_RXF
);
SPI_MCR_CLR_TXF
|
SPI_MCR_CLR_RXF
,
SPI_MCR_CLR_TXF
|
SPI_MCR_CLR_RXF
);
regmap_write
(
dspi
->
regmap
,
SPI_CTAR
(
0
),
dspi
->
cur_chip
->
ctar_val
);
dspi
->
cur_chip
->
ctar_val
|
SPI_FRAME_BITS
(
transfer
->
bits_per_word
));
if
(
dspi
->
devtype_data
->
xspi_mode
)
regmap_write
(
dspi
->
regmap
,
SPI_CTARE
(
0
),
SPI_FRAME_EBITS
(
transfer
->
bits_per_word
)
|
SPI_CTARE_DTCP
(
1
));
trans_mode
=
dspi
->
devtype_data
->
trans_mode
;
switch
(
trans_mode
)
{
...
...
@@ -750,16 +756,9 @@ static int dspi_setup(struct spi_device *spi)
struct
fsl_dspi_platform_data
*
pdata
;
u32
cs_sck_delay
=
0
,
sck_cs_delay
=
0
;
unsigned
char
br
=
0
,
pbr
=
0
,
pcssck
=
0
,
cssck
=
0
;
unsigned
char
pasc
=
0
,
asc
=
0
,
fmsz
=
0
;
unsigned
char
pasc
=
0
,
asc
=
0
;
unsigned
long
clkrate
;
if
((
spi
->
bits_per_word
>=
4
)
&&
(
spi
->
bits_per_word
<=
16
))
{
fmsz
=
spi
->
bits_per_word
-
1
;
}
else
{
pr_err
(
"Invalid wordsize
\n
"
);
return
-
ENODEV
;
}
/* Only alloc on first setup */
chip
=
spi_get_ctldata
(
spi
);
if
(
chip
==
NULL
)
{
...
...
@@ -781,9 +780,6 @@ static int dspi_setup(struct spi_device *spi)
sck_cs_delay
=
pdata
->
sck_cs_delay
;
}
chip
->
mcr_val
=
SPI_MCR_MASTER
|
SPI_MCR_PCSIS
|
SPI_MCR_CLR_TXF
|
SPI_MCR_CLR_RXF
;
chip
->
void_write_data
=
0
;
clkrate
=
clk_get_rate
(
dspi
->
clk
);
...
...
@@ -795,8 +791,7 @@ static int dspi_setup(struct spi_device *spi)
/* Set After SCK delay scale values */
ns_delay_scale
(
&
pasc
,
&
asc
,
sck_cs_delay
,
clkrate
);
chip
->
ctar_val
=
SPI_CTAR_FMSZ
(
fmsz
)
|
SPI_CTAR_CPOL
(
spi
->
mode
&
SPI_CPOL
?
1
:
0
)
chip
->
ctar_val
=
SPI_CTAR_CPOL
(
spi
->
mode
&
SPI_CPOL
?
1
:
0
)
|
SPI_CTAR_CPHA
(
spi
->
mode
&
SPI_CPHA
?
1
:
0
)
|
SPI_CTAR_LSBFE
(
spi
->
mode
&
SPI_LSB_FIRST
?
1
:
0
)
|
SPI_CTAR_PCSSCK
(
pcssck
)
...
...
@@ -827,36 +822,20 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
struct
spi_message
*
msg
=
dspi
->
cur_msg
;
enum
dspi_trans_mode
trans_mode
;
u32
spi_sr
,
spi_tcr
;
u32
spi_tcnt
,
tcnt_diff
;
int
tx_word
;
u16
spi_tcnt
;
regmap_read
(
dspi
->
regmap
,
SPI_SR
,
&
spi_sr
);
regmap_write
(
dspi
->
regmap
,
SPI_SR
,
spi_sr
);
if
(
spi_sr
&
(
SPI_SR_EOQF
|
SPI_SR_TCFQF
))
{
tx_word
=
is_double_byte_mode
(
dspi
);
/* Get transfer counter (in number of SPI transfers). It was
* reset to 0 when transfer(s) were started.
*/
regmap_read
(
dspi
->
regmap
,
SPI_TCR
,
&
spi_tcr
);
spi_tcnt
=
SPI_TCR_GET_TCNT
(
spi_tcr
);
/*
* The width of SPI Transfer Counter in SPI_TCR is 16bits,
* so the max couner is 65535. When the counter reach 65535,
* it will wrap around, counter reset to zero.
* spi_tcnt my be less than dspi->spi_tcnt, it means the
* counter already wrapped around.
* SPI Transfer Counter is a counter of transmitted frames.
* The size of frame maybe two bytes.
*/
tcnt_diff
=
((
spi_tcnt
+
SPI_TCR_TCNT_MAX
)
-
dspi
->
spi_tcnt
)
%
SPI_TCR_TCNT_MAX
;
tcnt_diff
*=
(
tx_word
+
1
);
if
(
dspi
->
dataflags
&
TRAN_STATE_WORD_ODD_NUM
)
tcnt_diff
--
;
msg
->
actual_length
+=
tcnt_diff
;
dspi
->
spi_tcnt
=
spi_tcnt
;
/* Update total number of bytes that were transferred */
msg
->
actual_length
+=
spi_tcnt
*
dspi
->
bytes_per_word
;
trans_mode
=
dspi
->
devtype_data
->
trans_mode
;
switch
(
trans_mode
)
{
...
...
@@ -873,14 +852,6 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
}
if
(
!
dspi
->
len
)
{
if
(
dspi
->
dataflags
&
TRAN_STATE_WORD_ODD_NUM
)
{
regmap_update_bits
(
dspi
->
regmap
,
SPI_CTAR
(
0
),
SPI_FRAME_BITS_MASK
,
SPI_FRAME_BITS
(
16
));
dspi
->
dataflags
&=
~
TRAN_STATE_WORD_ODD_NUM
;
}
dspi
->
waitflags
=
1
;
wake_up_interruptible
(
&
dspi
->
waitq
);
}
else
{
...
...
@@ -962,9 +933,43 @@ static const struct regmap_config dspi_regmap_config = {
.
volatile_table
=
&
dspi_volatile_table
,
};
static
const
struct
regmap_range
dspi_xspi_volatile_ranges
[]
=
{
regmap_reg_range
(
SPI_MCR
,
SPI_TCR
),
regmap_reg_range
(
SPI_SR
,
SPI_SR
),
regmap_reg_range
(
SPI_PUSHR
,
SPI_RXFR3
),
regmap_reg_range
(
SPI_SREX
,
SPI_SREX
),
};
static
const
struct
regmap_access_table
dspi_xspi_volatile_table
=
{
.
yes_ranges
=
dspi_xspi_volatile_ranges
,
.
n_yes_ranges
=
ARRAY_SIZE
(
dspi_xspi_volatile_ranges
),
};
static
const
struct
regmap_config
dspi_xspi_regmap_config
[]
=
{
{
.
reg_bits
=
32
,
.
val_bits
=
32
,
.
reg_stride
=
4
,
.
max_register
=
0x13c
,
.
volatile_table
=
&
dspi_xspi_volatile_table
,
},
{
.
name
=
"pushr"
,
.
reg_bits
=
16
,
.
val_bits
=
16
,
.
reg_stride
=
2
,
.
max_register
=
0x2
,
},
};
static
void
dspi_init
(
struct
fsl_dspi
*
dspi
)
{
regmap_write
(
dspi
->
regmap
,
SPI_MCR
,
SPI_MCR_MASTER
|
SPI_MCR_PCSIS
|
(
dspi
->
devtype_data
->
xspi_mode
?
SPI_MCR_XSPI
:
0
));
regmap_write
(
dspi
->
regmap
,
SPI_SR
,
SPI_SR_CLEAR
);
if
(
dspi
->
devtype_data
->
xspi_mode
)
regmap_write
(
dspi
->
regmap
,
SPI_CTARE
(
0
),
SPI_CTARE_FMSZE
(
0
)
|
SPI_CTARE_DTCP
(
1
));
}
static
int
dspi_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -973,6 +978,7 @@ static int dspi_probe(struct platform_device *pdev)
struct
spi_master
*
master
;
struct
fsl_dspi
*
dspi
;
struct
resource
*
res
;
const
struct
regmap_config
*
regmap_config
;
void
__iomem
*
base
;
struct
fsl_dspi_platform_data
*
pdata
;
int
ret
=
0
,
cs_num
,
bus_num
;
...
...
@@ -992,8 +998,6 @@ static int dspi_probe(struct platform_device *pdev)
master
->
cleanup
=
dspi_cleanup
;
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_LSB_FIRST
;
master
->
bits_per_word_mask
=
SPI_BPW_MASK
(
4
)
|
SPI_BPW_MASK
(
8
)
|
SPI_BPW_MASK
(
16
);
pdata
=
dev_get_platdata
(
&
pdev
->
dev
);
if
(
pdata
)
{
...
...
@@ -1025,6 +1029,11 @@ static int dspi_probe(struct platform_device *pdev)
}
}
if
(
dspi
->
devtype_data
->
xspi_mode
)
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
4
,
32
);
else
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
4
,
16
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
base
))
{
...
...
@@ -1032,8 +1041,11 @@ static int dspi_probe(struct platform_device *pdev)
goto
out_master_put
;
}
dspi
->
regmap
=
devm_regmap_init_mmio_clk
(
&
pdev
->
dev
,
NULL
,
base
,
&
dspi_regmap_config
);
if
(
dspi
->
devtype_data
->
xspi_mode
)
regmap_config
=
&
dspi_xspi_regmap_config
[
0
];
else
regmap_config
=
&
dspi_regmap_config
;
dspi
->
regmap
=
devm_regmap_init_mmio
(
&
pdev
->
dev
,
base
,
regmap_config
);
if
(
IS_ERR
(
dspi
->
regmap
))
{
dev_err
(
&
pdev
->
dev
,
"failed to init regmap: %ld
\n
"
,
PTR_ERR
(
dspi
->
regmap
));
...
...
@@ -1041,30 +1053,43 @@ static int dspi_probe(struct platform_device *pdev)
goto
out_master_put
;
}
if
(
dspi
->
devtype_data
->
xspi_mode
)
{
dspi
->
regmap_pushr
=
devm_regmap_init_mmio
(
&
pdev
->
dev
,
base
+
SPI_PUSHR
,
&
dspi_xspi_regmap_config
[
1
]);
if
(
IS_ERR
(
dspi
->
regmap_pushr
))
{
dev_err
(
&
pdev
->
dev
,
"failed to init pushr regmap: %ld
\n
"
,
PTR_ERR
(
dspi
->
regmap_pushr
));
ret
=
PTR_ERR
(
dspi
->
regmap_pushr
);
goto
out_master_put
;
}
}
dspi
->
clk
=
devm_clk_get
(
&
pdev
->
dev
,
"dspi"
);
if
(
IS_ERR
(
dspi
->
clk
))
{
ret
=
PTR_ERR
(
dspi
->
clk
);
dev_err
(
&
pdev
->
dev
,
"unable to get clock
\n
"
);
goto
out_master_put
;
}
ret
=
clk_prepare_enable
(
dspi
->
clk
);
if
(
ret
)
goto
out_master_put
;
dspi_init
(
dspi
);
dspi
->
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
dspi
->
irq
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"can't get platform irq
\n
"
);
ret
=
dspi
->
irq
;
goto
out_
master
_put
;
goto
out_
clk
_put
;
}
ret
=
devm_request_irq
(
&
pdev
->
dev
,
dspi
->
irq
,
dspi_interrupt
,
0
,
pdev
->
name
,
dspi
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to attach DSPI interrupt
\n
"
);
goto
out_master_put
;
}
dspi
->
clk
=
devm_clk_get
(
&
pdev
->
dev
,
"dspi"
);
if
(
IS_ERR
(
dspi
->
clk
))
{
ret
=
PTR_ERR
(
dspi
->
clk
);
dev_err
(
&
pdev
->
dev
,
"unable to get clock
\n
"
);
goto
out_master_put
;
goto
out_clk_put
;
}
ret
=
clk_prepare_enable
(
dspi
->
clk
);
if
(
ret
)
goto
out_master_put
;
if
(
dspi
->
devtype_data
->
trans_mode
==
DSPI_DMA_MODE
)
{
ret
=
dspi_request_dma
(
dspi
,
res
->
start
);
...
...
drivers/spi/spi-fsl-espi.c
View file @
c1acb21b
...
...
@@ -547,8 +547,11 @@ static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
dev_err
(
espi
->
dev
,
"Transfer done but SPIE_DON isn't set!
\n
"
);
if
(
SPIE_RXCNT
(
events
)
||
SPIE_TXCNT
(
events
)
!=
FSL_ESPI_FIFO_SIZE
)
if
(
SPIE_RXCNT
(
events
)
||
SPIE_TXCNT
(
events
)
!=
FSL_ESPI_FIFO_SIZE
)
{
dev_err
(
espi
->
dev
,
"Transfer done but rx/tx fifo's aren't empty!
\n
"
);
dev_err
(
espi
->
dev
,
"SPIE_RXCNT = %d, SPIE_TXCNT = %d
\n
"
,
SPIE_RXCNT
(
events
),
SPIE_TXCNT
(
events
));
}
complete
(
&
espi
->
done
);
}
...
...
drivers/spi/spi-gpio.c
View file @
c1acb21b
...
...
@@ -121,7 +121,10 @@ static inline int getmiso(const struct spi_device *spi)
{
struct
spi_gpio
*
spi_gpio
=
spi_to_spi_gpio
(
spi
);
return
!!
gpiod_get_value_cansleep
(
spi_gpio
->
miso
);
if
(
spi
->
mode
&
SPI_3WIRE
)
return
!!
gpiod_get_value_cansleep
(
spi_gpio
->
mosi
);
else
return
!!
gpiod_get_value_cansleep
(
spi_gpio
->
miso
);
}
/*
...
...
@@ -149,27 +152,27 @@ static inline int getmiso(const struct spi_device *spi)
*/
static
u32
spi_gpio_txrx_word_mode0
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
static
u32
spi_gpio_txrx_word_mode1
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
0
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
static
u32
spi_gpio_txrx_word_mode2
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
1
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
1
,
flags
,
word
,
bits
);
}
static
u32
spi_gpio_txrx_word_mode3
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
1
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
1
,
flags
,
word
,
bits
);
}
/*
...
...
@@ -183,30 +186,30 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
*/
static
u32
spi_gpio_spec_txrx_word_mode0
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
unsigned
flags
=
spi
->
master
->
flags
;
flags
=
spi
->
master
->
flags
;
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
static
u32
spi_gpio_spec_txrx_word_mode1
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
unsigned
flags
=
spi
->
master
->
flags
;
flags
=
spi
->
master
->
flags
;
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
static
u32
spi_gpio_spec_txrx_word_mode2
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
unsigned
flags
=
spi
->
master
->
flags
;
flags
=
spi
->
master
->
flags
;
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
1
,
flags
,
word
,
bits
);
}
static
u32
spi_gpio_spec_txrx_word_mode3
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
unsigned
flags
=
spi
->
master
->
flags
;
flags
=
spi
->
master
->
flags
;
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
1
,
flags
,
word
,
bits
);
}
...
...
@@ -250,6 +253,16 @@ static int spi_gpio_setup(struct spi_device *spi)
return
status
;
}
static
int
spi_gpio_set_direction
(
struct
spi_device
*
spi
,
bool
output
)
{
struct
spi_gpio
*
spi_gpio
=
spi_to_spi_gpio
(
spi
);
if
(
output
)
return
gpiod_direction_output
(
spi_gpio
->
mosi
,
1
);
else
return
gpiod_direction_input
(
spi_gpio
->
mosi
);
}
static
void
spi_gpio_cleanup
(
struct
spi_device
*
spi
)
{
spi_bitbang_cleanup
(
spi
);
...
...
@@ -395,6 +408,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
return
status
;
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
1
,
32
);
master
->
mode_bits
=
SPI_3WIRE
|
SPI_CPHA
|
SPI_CPOL
;
master
->
flags
=
master_flags
;
master
->
bus_num
=
pdev
->
id
;
/* The master needs to think there is a chipselect even if not connected */
...
...
@@ -407,6 +421,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
spi_gpio
->
bitbang
.
master
=
master
;
spi_gpio
->
bitbang
.
chipselect
=
spi_gpio_chipselect
;
spi_gpio
->
bitbang
.
set_line_direction
=
spi_gpio_set_direction
;
if
((
master_flags
&
(
SPI_MASTER_NO_TX
|
SPI_MASTER_NO_RX
))
==
0
)
{
spi_gpio
->
bitbang
.
txrx_word
[
SPI_MODE_0
]
=
spi_gpio_txrx_word_mode0
;
...
...
drivers/spi/spi-img-spfi.c
View file @
c1acb21b
...
...
@@ -419,6 +419,9 @@ static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg)
u32
val
;
val
=
spfi_readl
(
spfi
,
SPFI_PORT_STATE
);
val
&=
~
(
SPFI_PORT_STATE_DEV_SEL_MASK
<<
SPFI_PORT_STATE_DEV_SEL_SHIFT
);
val
|=
msg
->
spi
->
chip_select
<<
SPFI_PORT_STATE_DEV_SEL_SHIFT
;
if
(
msg
->
spi
->
mode
&
SPI_CPHA
)
val
|=
SPFI_PORT_STATE_CK_PHASE
(
msg
->
spi
->
chip_select
);
else
...
...
drivers/spi/spi-imx.c
View file @
c1acb21b
...
...
@@ -94,8 +94,7 @@ struct spi_imx_data {
void
*
rx_buf
;
const
void
*
tx_buf
;
unsigned
int
txfifo
;
/* number of words pushed in tx FIFO */
unsigned
int
dynamic_burst
,
read_u32
;
unsigned
int
word_mask
;
unsigned
int
dynamic_burst
;
/* Slave mode */
bool
slave_mode
;
...
...
@@ -140,6 +139,8 @@ static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \
*(type *)spi_imx->rx_buf = val; \
spi_imx->rx_buf += sizeof(type); \
} \
\
spi_imx->remainder -= sizeof(type); \
}
#define MXC_SPI_BUF_TX(type) \
...
...
@@ -203,7 +204,12 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
static
int
spi_imx_bytes_per_word
(
const
int
bits_per_word
)
{
return
DIV_ROUND_UP
(
bits_per_word
,
BITS_PER_BYTE
);
if
(
bits_per_word
<=
8
)
return
1
;
else
if
(
bits_per_word
<=
16
)
return
2
;
else
return
4
;
}
static
bool
spi_imx_can_dma
(
struct
spi_master
*
master
,
struct
spi_device
*
spi
,
...
...
@@ -220,17 +226,11 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
bytes_per_word
=
spi_imx_bytes_per_word
(
transfer
->
bits_per_word
);
if
(
bytes_per_word
!=
1
&&
bytes_per_word
!=
2
&&
bytes_per_word
!=
4
)
return
false
;
for
(
i
=
spi_imx
->
devtype_data
->
fifo_size
/
2
;
i
>
0
;
i
--
)
{
if
(
!
(
transfer
->
len
%
(
i
*
bytes_per_word
)))
break
;
}
if
(
i
==
0
)
return
false
;
spi_imx
->
wml
=
i
;
spi_imx
->
dynamic_burst
=
0
;
...
...
@@ -291,26 +291,39 @@ static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
else
if
(
bytes_per_word
==
2
)
val
=
(
val
<<
16
)
|
(
val
>>
16
);
#endif
val
&=
spi_imx
->
word_mask
;
*
(
u32
*
)
spi_imx
->
rx_buf
=
val
;
spi_imx
->
rx_buf
+=
sizeof
(
u32
);
}
spi_imx
->
remainder
-=
sizeof
(
u32
);
}
static
void
spi_imx_buf_rx_swap
(
struct
spi_imx_data
*
spi_imx
)
{
unsigned
int
bytes_per_word
;
int
unaligned
;
u32
val
;
bytes_per_word
=
spi_imx_bytes_per_word
(
spi_imx
->
bits_per_word
);
if
(
spi_imx
->
read_u32
)
{
unaligned
=
spi_imx
->
remainder
%
4
;
if
(
!
unaligned
)
{
spi_imx_buf_rx_swap_u32
(
spi_imx
);
return
;
}
if
(
bytes_per_word
==
1
)
spi_imx_buf_rx_u8
(
spi_imx
);
else
if
(
bytes_per_word
==
2
)
if
(
spi_imx_bytes_per_word
(
spi_imx
->
bits_per_word
)
==
2
)
{
spi_imx_buf_rx_u16
(
spi_imx
);
return
;
}
val
=
readl
(
spi_imx
->
base
+
MXC_CSPIRXDATA
);
while
(
unaligned
--
)
{
if
(
spi_imx
->
rx_buf
)
{
*
(
u8
*
)
spi_imx
->
rx_buf
=
(
val
>>
(
8
*
unaligned
))
&
0xff
;
spi_imx
->
rx_buf
++
;
}
spi_imx
->
remainder
--
;
}
}
static
void
spi_imx_buf_tx_swap_u32
(
struct
spi_imx_data
*
spi_imx
)
...
...
@@ -322,7 +335,6 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
if
(
spi_imx
->
tx_buf
)
{
val
=
*
(
u32
*
)
spi_imx
->
tx_buf
;
val
&=
spi_imx
->
word_mask
;
spi_imx
->
tx_buf
+=
sizeof
(
u32
);
}
...
...
@@ -340,40 +352,30 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
static
void
spi_imx_buf_tx_swap
(
struct
spi_imx_data
*
spi_imx
)
{
u32
ctrl
,
val
;
u
nsigned
int
bytes_per_word
;
int
unaligned
;
u
32
val
=
0
;
if
(
spi_imx
->
count
==
spi_imx
->
remainder
)
{
ctrl
=
readl
(
spi_imx
->
base
+
MX51_ECSPI_CTRL
);
ctrl
&=
~
MX51_ECSPI_CTRL_BL_MASK
;
if
(
spi_imx
->
count
>
MX51_ECSPI_CTRL_MAX_BURST
)
{
spi_imx
->
remainder
=
spi_imx
->
count
%
MX51_ECSPI_CTRL_MAX_BURST
;
val
=
MX51_ECSPI_CTRL_MAX_BURST
*
8
-
1
;
}
else
if
(
spi_imx
->
count
>=
sizeof
(
u32
))
{
spi_imx
->
remainder
=
spi_imx
->
count
%
sizeof
(
u32
);
val
=
(
spi_imx
->
count
-
spi_imx
->
remainder
)
*
8
-
1
;
}
else
{
spi_imx
->
remainder
=
0
;
val
=
spi_imx
->
bits_per_word
-
1
;
spi_imx
->
read_u32
=
0
;
}
unaligned
=
spi_imx
->
count
%
4
;
ctrl
|=
(
val
<<
MX51_ECSPI_CTRL_BL_OFFSET
);
writel
(
ctrl
,
spi_imx
->
base
+
MX51_ECSPI_CTRL
);
if
(
!
unaligned
)
{
spi_imx_buf_tx_swap_u32
(
spi_imx
);
return
;
}
if
(
spi_imx
->
count
>=
sizeof
(
u32
)
)
{
spi_imx_buf_tx_
swap_u32
(
spi_imx
);
if
(
spi_imx
_bytes_per_word
(
spi_imx
->
bits_per_word
)
==
2
)
{
spi_imx_buf_tx_
u16
(
spi_imx
);
return
;
}
bytes_per_word
=
spi_imx_bytes_per_word
(
spi_imx
->
bits_per_word
);
while
(
unaligned
--
)
{
if
(
spi_imx
->
tx_buf
)
{
val
|=
*
(
u8
*
)
spi_imx
->
tx_buf
<<
(
8
*
unaligned
);
spi_imx
->
tx_buf
++
;
}
spi_imx
->
count
--
;
}
if
(
bytes_per_word
==
1
)
spi_imx_buf_tx_u8
(
spi_imx
);
else
if
(
bytes_per_word
==
2
)
spi_imx_buf_tx_u16
(
spi_imx
);
writel
(
val
,
spi_imx
->
base
+
MXC_CSPITXDATA
);
}
static
void
mx53_ecspi_rx_slave
(
struct
spi_imx_data
*
spi_imx
)
...
...
@@ -392,6 +394,8 @@ static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
spi_imx
->
rx_buf
+=
n_bytes
;
spi_imx
->
slave_burst
-=
n_bytes
;
}
spi_imx
->
remainder
-=
sizeof
(
u32
);
}
static
void
mx53_ecspi_tx_slave
(
struct
spi_imx_data
*
spi_imx
)
...
...
@@ -1001,12 +1005,52 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active)
gpio_set_value
(
spi
->
cs_gpio
,
dev_is_lowactive
^
active
);
}
static
void
spi_imx_set_burst_len
(
struct
spi_imx_data
*
spi_imx
,
int
n_bits
)
{
u32
ctrl
;
ctrl
=
readl
(
spi_imx
->
base
+
MX51_ECSPI_CTRL
);
ctrl
&=
~
MX51_ECSPI_CTRL_BL_MASK
;
ctrl
|=
((
n_bits
-
1
)
<<
MX51_ECSPI_CTRL_BL_OFFSET
);
writel
(
ctrl
,
spi_imx
->
base
+
MX51_ECSPI_CTRL
);
}
static
void
spi_imx_push
(
struct
spi_imx_data
*
spi_imx
)
{
unsigned
int
burst_len
,
fifo_words
;
if
(
spi_imx
->
dynamic_burst
)
fifo_words
=
4
;
else
fifo_words
=
spi_imx_bytes_per_word
(
spi_imx
->
bits_per_word
);
/*
* Reload the FIFO when the remaining bytes to be transferred in the
* current burst is 0. This only applies when bits_per_word is a
* multiple of 8.
*/
if
(
!
spi_imx
->
remainder
)
{
if
(
spi_imx
->
dynamic_burst
)
{
/* We need to deal unaligned data first */
burst_len
=
spi_imx
->
count
%
MX51_ECSPI_CTRL_MAX_BURST
;
if
(
!
burst_len
)
burst_len
=
MX51_ECSPI_CTRL_MAX_BURST
;
spi_imx_set_burst_len
(
spi_imx
,
burst_len
*
8
);
spi_imx
->
remainder
=
burst_len
;
}
else
{
spi_imx
->
remainder
=
fifo_words
;
}
}
while
(
spi_imx
->
txfifo
<
spi_imx
->
devtype_data
->
fifo_size
)
{
if
(
!
spi_imx
->
count
)
break
;
if
(
spi_imx
->
txfifo
&&
(
spi_imx
->
count
==
spi_imx
->
remainder
))
if
(
spi_imx
->
dynamic_burst
&&
spi_imx
->
txfifo
>=
DIV_ROUND_UP
(
spi_imx
->
remainder
,
fifo_words
))
break
;
spi_imx
->
tx
(
spi_imx
);
spi_imx
->
txfifo
++
;
...
...
@@ -1102,27 +1146,20 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx
->
bits_per_word
=
t
->
bits_per_word
;
spi_imx
->
speed_hz
=
t
->
speed_hz
;
/* Initialize the functions for transfer */
if
(
spi_imx
->
devtype_data
->
dynamic_burst
&&
!
spi_imx
->
slave_mode
)
{
u32
mask
;
spi_imx
->
dynamic_burst
=
0
;
spi_imx
->
remainder
=
0
;
spi_imx
->
read_u32
=
1
;
/*
* Initialize the functions for transfer. To transfer non byte-aligned
* words, we have to use multiple word-size bursts, we can't use
* dynamic_burst in that case.
*/
if
(
spi_imx
->
devtype_data
->
dynamic_burst
&&
!
spi_imx
->
slave_mode
&&
(
spi_imx
->
bits_per_word
==
8
||
spi_imx
->
bits_per_word
==
16
||
spi_imx
->
bits_per_word
==
32
))
{
mask
=
(
1
<<
spi_imx
->
bits_per_word
)
-
1
;
spi_imx
->
rx
=
spi_imx_buf_rx_swap
;
spi_imx
->
tx
=
spi_imx_buf_tx_swap
;
spi_imx
->
dynamic_burst
=
1
;
spi_imx
->
remainder
=
t
->
len
;
if
(
spi_imx
->
bits_per_word
<=
8
)
spi_imx
->
word_mask
=
mask
<<
24
|
mask
<<
16
|
mask
<<
8
|
mask
;
else
if
(
spi_imx
->
bits_per_word
<=
16
)
spi_imx
->
word_mask
=
mask
<<
16
|
mask
;
else
spi_imx
->
word_mask
=
mask
;
}
else
{
if
(
spi_imx
->
bits_per_word
<=
8
)
{
spi_imx
->
rx
=
spi_imx_buf_rx_u8
;
...
...
@@ -1134,6 +1171,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx
->
rx
=
spi_imx_buf_rx_u32
;
spi_imx
->
tx
=
spi_imx_buf_tx_u32
;
}
spi_imx
->
dynamic_burst
=
0
;
}
if
(
spi_imx_can_dma
(
spi_imx
->
bitbang
.
master
,
spi
,
t
))
...
...
@@ -1317,6 +1355,7 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
spi_imx
->
rx_buf
=
transfer
->
rx_buf
;
spi_imx
->
count
=
transfer
->
len
;
spi_imx
->
txfifo
=
0
;
spi_imx
->
remainder
=
0
;
reinit_completion
(
&
spi_imx
->
xfer_done
);
...
...
@@ -1354,6 +1393,7 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi,
spi_imx
->
rx_buf
=
transfer
->
rx_buf
;
spi_imx
->
count
=
transfer
->
len
;
spi_imx
->
txfifo
=
0
;
spi_imx
->
remainder
=
0
;
reinit_completion
(
&
spi_imx
->
xfer_done
);
spi_imx
->
slave_aborted
=
false
;
...
...
drivers/spi/spi-lm70llp.c
View file @
c1acb21b
...
...
@@ -188,9 +188,10 @@ static void lm70_chipselect(struct spi_device *spi, int value)
/*
* Our actual bitbanger routine.
*/
static
u32
lm70_txrx
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
static
u32
lm70_txrx
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
static
void
spi_lm70llp_attach
(
struct
parport
*
p
)
...
...
drivers/spi/spi-mem.c
View file @
c1acb21b
...
...
@@ -310,6 +310,24 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
}
EXPORT_SYMBOL_GPL
(
spi_mem_exec_op
);
/**
* spi_mem_get_name() - Return the SPI mem device name to be used by the
* upper layer if necessary
* @mem: the SPI memory
*
* This function allows SPI mem users to retrieve the SPI mem device name.
* It is useful if the upper layer needs to expose a custom name for
* compatibility reasons.
*
* Return: a string containing the name of the memory device to be used
* by the SPI mem user
*/
const
char
*
spi_mem_get_name
(
struct
spi_mem
*
mem
)
{
return
mem
->
name
;
}
EXPORT_SYMBOL_GPL
(
spi_mem_get_name
);
/**
* spi_mem_adjust_op_size() - Adjust the data size of a SPI mem operation to
* match controller limitations
...
...
@@ -344,6 +362,7 @@ static inline struct spi_mem_driver *to_spi_mem_drv(struct device_driver *drv)
static
int
spi_mem_probe
(
struct
spi_device
*
spi
)
{
struct
spi_mem_driver
*
memdrv
=
to_spi_mem_drv
(
spi
->
dev
.
driver
);
struct
spi_controller
*
ctlr
=
spi
->
controller
;
struct
spi_mem
*
mem
;
mem
=
devm_kzalloc
(
&
spi
->
dev
,
sizeof
(
*
mem
),
GFP_KERNEL
);
...
...
@@ -351,6 +370,15 @@ static int spi_mem_probe(struct spi_device *spi)
return
-
ENOMEM
;
mem
->
spi
=
spi
;
if
(
ctlr
->
mem_ops
&&
ctlr
->
mem_ops
->
get_name
)
mem
->
name
=
ctlr
->
mem_ops
->
get_name
(
mem
);
else
mem
->
name
=
dev_name
(
&
spi
->
dev
);
if
(
IS_ERR_OR_NULL
(
mem
->
name
))
return
PTR_ERR
(
mem
->
name
);
spi_set_drvdata
(
spi
,
mem
);
return
memdrv
->
probe
(
mem
);
...
...
drivers/spi/spi-omap2-mcspi.c
View file @
c1acb21b
...
...
@@ -398,11 +398,9 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
{
struct
omap2_mcspi
*
mcspi
;
struct
omap2_mcspi_dma
*
mcspi_dma
;
unsigned
int
count
;
mcspi
=
spi_master_get_devdata
(
spi
->
master
);
mcspi_dma
=
&
mcspi
->
dma_channels
[
spi
->
chip_select
];
count
=
xfer
->
len
;
if
(
mcspi_dma
->
dma_tx
)
{
struct
dma_async_tx_descriptor
*
tx
;
...
...
@@ -582,7 +580,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
struct
omap2_mcspi_cs
*
cs
=
spi
->
controller_state
;
struct
omap2_mcspi_dma
*
mcspi_dma
;
unsigned
int
count
;
u32
l
;
u8
*
rx
;
const
u8
*
tx
;
struct
dma_slave_config
cfg
;
...
...
@@ -595,8 +592,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
mcspi
=
spi_master_get_devdata
(
spi
->
master
);
mcspi_dma
=
&
mcspi
->
dma_channels
[
spi
->
chip_select
];
l
=
mcspi_cached_chconf0
(
spi
);
if
(
cs
->
word_len
<=
8
)
{
width
=
DMA_SLAVE_BUSWIDTH_1_BYTE
;
...
...
@@ -676,7 +671,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
static
unsigned
omap2_mcspi_txrx_pio
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
xfer
)
{
struct
omap2_mcspi
*
mcspi
;
struct
omap2_mcspi_cs
*
cs
=
spi
->
controller_state
;
unsigned
int
count
,
c
;
u32
l
;
...
...
@@ -686,7 +680,6 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
void
__iomem
*
chstat_reg
;
int
word_len
;
mcspi
=
spi_master_get_devdata
(
spi
->
master
);
count
=
xfer
->
len
;
c
=
count
;
word_len
=
cs
->
word_len
;
...
...
@@ -883,13 +876,11 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
{
struct
omap2_mcspi_cs
*
cs
=
spi
->
controller_state
;
struct
omap2_mcspi
*
mcspi
;
struct
spi_master
*
spi_cntrl
;
u32
l
=
0
,
clkd
=
0
,
div
,
extclk
=
0
,
clkg
=
0
;
u8
word_len
=
spi
->
bits_per_word
;
u32
speed_hz
=
spi
->
max_speed_hz
;
mcspi
=
spi_master_get_devdata
(
spi
->
master
);
spi_cntrl
=
mcspi
->
master
;
if
(
t
!=
NULL
&&
t
->
bits_per_word
)
word_len
=
t
->
bits_per_word
;
...
...
drivers/spi/spi-pxa2xx.c
View file @
c1acb21b
...
...
@@ -1391,6 +1391,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
{
PCI_VDEVICE
(
INTEL
,
0x31c2
),
LPSS_BXT_SSP
},
{
PCI_VDEVICE
(
INTEL
,
0x31c4
),
LPSS_BXT_SSP
},
{
PCI_VDEVICE
(
INTEL
,
0x31c6
),
LPSS_BXT_SSP
},
/* ICL-LP */
{
PCI_VDEVICE
(
INTEL
,
0x34aa
),
LPSS_CNL_SSP
},
{
PCI_VDEVICE
(
INTEL
,
0x34ab
),
LPSS_CNL_SSP
},
{
PCI_VDEVICE
(
INTEL
,
0x34fb
),
LPSS_CNL_SSP
},
/* APL */
{
PCI_VDEVICE
(
INTEL
,
0x5ac2
),
LPSS_BXT_SSP
},
{
PCI_VDEVICE
(
INTEL
,
0x5ac4
),
LPSS_BXT_SSP
},
...
...
drivers/spi/spi-sh-sci.c
View file @
c1acb21b
...
...
@@ -80,27 +80,31 @@ static inline u32 getmiso(struct spi_device *dev)
#include "spi-bitbang-txrx.h"
static
u32
sh_sci_spi_txrx_mode0
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
static
u32
sh_sci_spi_txrx_mode1
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
0
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
0
,
flags
,
word
,
bits
);
}
static
u32
sh_sci_spi_txrx_mode2
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
1
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha0
(
spi
,
nsecs
,
1
,
flags
,
word
,
bits
);
}
static
u32
sh_sci_spi_txrx_mode3
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
)
unsigned
nsecs
,
u32
word
,
u8
bits
,
unsigned
flags
)
{
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
1
,
0
,
word
,
bits
);
return
bitbang_txrx_be_cpha1
(
spi
,
nsecs
,
1
,
flags
,
word
,
bits
);
}
static
void
sh_sci_spi_chipselect
(
struct
spi_device
*
dev
,
int
value
)
...
...
drivers/spi/spi-uniphier.c
0 → 100644
View file @
c1acb21b
// SPDX-License-Identifier: GPL-2.0
// spi-uniphier.c - Socionext UniPhier SPI controller driver
// Copyright 2012 Panasonic Corporation
// Copyright 2016-2018 Socionext Inc.
#include <linux/kernel.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <asm/unaligned.h>
#define SSI_TIMEOUT_MS 2000
#define SSI_MAX_CLK_DIVIDER 254
#define SSI_MIN_CLK_DIVIDER 4
struct
uniphier_spi_priv
{
void
__iomem
*
base
;
struct
clk
*
clk
;
struct
spi_master
*
master
;
struct
completion
xfer_done
;
int
error
;
unsigned
int
tx_bytes
;
unsigned
int
rx_bytes
;
const
u8
*
tx_buf
;
u8
*
rx_buf
;
bool
is_save_param
;
u8
bits_per_word
;
u16
mode
;
u32
speed_hz
;
};
#define SSI_CTL 0x00
#define SSI_CTL_EN BIT(0)
#define SSI_CKS 0x04
#define SSI_CKS_CKRAT_MASK GENMASK(7, 0)
#define SSI_CKS_CKPHS BIT(14)
#define SSI_CKS_CKINIT BIT(13)
#define SSI_CKS_CKDLY BIT(12)
#define SSI_TXWDS 0x08
#define SSI_TXWDS_WDLEN_MASK GENMASK(13, 8)
#define SSI_TXWDS_TDTF_MASK GENMASK(7, 6)
#define SSI_TXWDS_DTLEN_MASK GENMASK(5, 0)
#define SSI_RXWDS 0x0c
#define SSI_RXWDS_DTLEN_MASK GENMASK(5, 0)
#define SSI_FPS 0x10
#define SSI_FPS_FSPOL BIT(15)
#define SSI_FPS_FSTRT BIT(14)
#define SSI_SR 0x14
#define SSI_SR_RNE BIT(0)
#define SSI_IE 0x18
#define SSI_IE_RCIE BIT(3)
#define SSI_IE_RORIE BIT(0)
#define SSI_IS 0x1c
#define SSI_IS_RXRS BIT(9)
#define SSI_IS_RCID BIT(3)
#define SSI_IS_RORID BIT(0)
#define SSI_IC 0x1c
#define SSI_IC_TCIC BIT(4)
#define SSI_IC_RCIC BIT(3)
#define SSI_IC_RORIC BIT(0)
#define SSI_FC 0x20
#define SSI_FC_TXFFL BIT(12)
#define SSI_FC_TXFTH_MASK GENMASK(11, 8)
#define SSI_FC_RXFFL BIT(4)
#define SSI_FC_RXFTH_MASK GENMASK(3, 0)
#define SSI_TXDR 0x24
#define SSI_RXDR 0x24
#define SSI_FIFO_DEPTH 8U
static
inline
unsigned
int
bytes_per_word
(
unsigned
int
bits
)
{
return
bits
<=
8
?
1
:
(
bits
<=
16
?
2
:
4
);
}
static
inline
void
uniphier_spi_irq_enable
(
struct
spi_device
*
spi
,
u32
mask
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
spi
->
master
);
u32
val
;
val
=
readl
(
priv
->
base
+
SSI_IE
);
val
|=
mask
;
writel
(
val
,
priv
->
base
+
SSI_IE
);
}
static
inline
void
uniphier_spi_irq_disable
(
struct
spi_device
*
spi
,
u32
mask
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
spi
->
master
);
u32
val
;
val
=
readl
(
priv
->
base
+
SSI_IE
);
val
&=
~
mask
;
writel
(
val
,
priv
->
base
+
SSI_IE
);
}
static
void
uniphier_spi_set_mode
(
struct
spi_device
*
spi
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
spi
->
master
);
u32
val1
,
val2
;
/*
* clock setting
* CKPHS capture timing. 0:rising edge, 1:falling edge
* CKINIT clock initial level. 0:low, 1:high
* CKDLY clock delay. 0:no delay, 1:delay depending on FSTRT
* (FSTRT=0: 1 clock, FSTRT=1: 0.5 clock)
*
* frame setting
* FSPOL frame signal porarity. 0: low, 1: high
* FSTRT start frame timing
* 0: rising edge of clock, 1: falling edge of clock
*/
switch
(
spi
->
mode
&
(
SPI_CPOL
|
SPI_CPHA
))
{
case
SPI_MODE_0
:
/* CKPHS=1, CKINIT=0, CKDLY=1, FSTRT=0 */
val1
=
SSI_CKS_CKPHS
|
SSI_CKS_CKDLY
;
val2
=
0
;
break
;
case
SPI_MODE_1
:
/* CKPHS=0, CKINIT=0, CKDLY=0, FSTRT=1 */
val1
=
0
;
val2
=
SSI_FPS_FSTRT
;
break
;
case
SPI_MODE_2
:
/* CKPHS=0, CKINIT=1, CKDLY=1, FSTRT=1 */
val1
=
SSI_CKS_CKINIT
|
SSI_CKS_CKDLY
;
val2
=
SSI_FPS_FSTRT
;
break
;
case
SPI_MODE_3
:
/* CKPHS=1, CKINIT=1, CKDLY=0, FSTRT=0 */
val1
=
SSI_CKS_CKPHS
|
SSI_CKS_CKINIT
;
val2
=
0
;
break
;
}
if
(
!
(
spi
->
mode
&
SPI_CS_HIGH
))
val2
|=
SSI_FPS_FSPOL
;
writel
(
val1
,
priv
->
base
+
SSI_CKS
);
writel
(
val2
,
priv
->
base
+
SSI_FPS
);
val1
=
0
;
if
(
spi
->
mode
&
SPI_LSB_FIRST
)
val1
|=
FIELD_PREP
(
SSI_TXWDS_TDTF_MASK
,
1
);
writel
(
val1
,
priv
->
base
+
SSI_TXWDS
);
writel
(
val1
,
priv
->
base
+
SSI_RXWDS
);
}
static
void
uniphier_spi_set_transfer_size
(
struct
spi_device
*
spi
,
int
size
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
spi
->
master
);
u32
val
;
val
=
readl
(
priv
->
base
+
SSI_TXWDS
);
val
&=
~
(
SSI_TXWDS_WDLEN_MASK
|
SSI_TXWDS_DTLEN_MASK
);
val
|=
FIELD_PREP
(
SSI_TXWDS_WDLEN_MASK
,
size
);
val
|=
FIELD_PREP
(
SSI_TXWDS_DTLEN_MASK
,
size
);
writel
(
val
,
priv
->
base
+
SSI_TXWDS
);
val
=
readl
(
priv
->
base
+
SSI_RXWDS
);
val
&=
~
SSI_RXWDS_DTLEN_MASK
;
val
|=
FIELD_PREP
(
SSI_RXWDS_DTLEN_MASK
,
size
);
writel
(
val
,
priv
->
base
+
SSI_RXWDS
);
}
static
void
uniphier_spi_set_baudrate
(
struct
spi_device
*
spi
,
unsigned
int
speed
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
spi
->
master
);
u32
val
,
ckdiv
;
/*
* the supported rates are even numbers from 4 to 254. (4,6,8...254)
* round up as we look for equal or less speed
*/
ckdiv
=
DIV_ROUND_UP
(
clk_get_rate
(
priv
->
clk
),
speed
);
ckdiv
=
round_up
(
ckdiv
,
2
);
val
=
readl
(
priv
->
base
+
SSI_CKS
);
val
&=
~
SSI_CKS_CKRAT_MASK
;
val
|=
ckdiv
&
SSI_CKS_CKRAT_MASK
;
writel
(
val
,
priv
->
base
+
SSI_CKS
);
}
static
void
uniphier_spi_setup_transfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
spi
->
master
);
u32
val
;
priv
->
error
=
0
;
priv
->
tx_buf
=
t
->
tx_buf
;
priv
->
rx_buf
=
t
->
rx_buf
;
priv
->
tx_bytes
=
priv
->
rx_bytes
=
t
->
len
;
if
(
!
priv
->
is_save_param
||
priv
->
mode
!=
spi
->
mode
)
{
uniphier_spi_set_mode
(
spi
);
priv
->
mode
=
spi
->
mode
;
}
if
(
!
priv
->
is_save_param
||
priv
->
bits_per_word
!=
t
->
bits_per_word
)
{
uniphier_spi_set_transfer_size
(
spi
,
t
->
bits_per_word
);
priv
->
bits_per_word
=
t
->
bits_per_word
;
}
if
(
!
priv
->
is_save_param
||
priv
->
speed_hz
!=
t
->
speed_hz
)
{
uniphier_spi_set_baudrate
(
spi
,
t
->
speed_hz
);
priv
->
speed_hz
=
t
->
speed_hz
;
}
if
(
!
priv
->
is_save_param
)
priv
->
is_save_param
=
true
;
/* reset FIFOs */
val
=
SSI_FC_TXFFL
|
SSI_FC_RXFFL
;
writel
(
val
,
priv
->
base
+
SSI_FC
);
}
static
void
uniphier_spi_send
(
struct
uniphier_spi_priv
*
priv
)
{
int
wsize
;
u32
val
=
0
;
wsize
=
min
(
bytes_per_word
(
priv
->
bits_per_word
),
priv
->
tx_bytes
);
priv
->
tx_bytes
-=
wsize
;
if
(
priv
->
tx_buf
)
{
switch
(
wsize
)
{
case
1
:
val
=
*
priv
->
tx_buf
;
break
;
case
2
:
val
=
get_unaligned_le16
(
priv
->
tx_buf
);
break
;
case
4
:
val
=
get_unaligned_le32
(
priv
->
tx_buf
);
break
;
}
priv
->
tx_buf
+=
wsize
;
}
writel
(
val
,
priv
->
base
+
SSI_TXDR
);
}
static
void
uniphier_spi_recv
(
struct
uniphier_spi_priv
*
priv
)
{
int
rsize
;
u32
val
;
rsize
=
min
(
bytes_per_word
(
priv
->
bits_per_word
),
priv
->
rx_bytes
);
priv
->
rx_bytes
-=
rsize
;
val
=
readl
(
priv
->
base
+
SSI_RXDR
);
if
(
priv
->
rx_buf
)
{
switch
(
rsize
)
{
case
1
:
*
priv
->
rx_buf
=
val
;
break
;
case
2
:
put_unaligned_le16
(
val
,
priv
->
rx_buf
);
break
;
case
4
:
put_unaligned_le32
(
val
,
priv
->
rx_buf
);
break
;
}
priv
->
rx_buf
+=
rsize
;
}
}
static
void
uniphier_spi_fill_tx_fifo
(
struct
uniphier_spi_priv
*
priv
)
{
unsigned
int
tx_count
;
u32
val
;
tx_count
=
DIV_ROUND_UP
(
priv
->
tx_bytes
,
bytes_per_word
(
priv
->
bits_per_word
));
tx_count
=
min
(
tx_count
,
SSI_FIFO_DEPTH
);
/* set fifo threshold */
val
=
readl
(
priv
->
base
+
SSI_FC
);
val
&=
~
(
SSI_FC_TXFTH_MASK
|
SSI_FC_RXFTH_MASK
);
val
|=
FIELD_PREP
(
SSI_FC_TXFTH_MASK
,
tx_count
);
val
|=
FIELD_PREP
(
SSI_FC_RXFTH_MASK
,
tx_count
);
writel
(
val
,
priv
->
base
+
SSI_FC
);
while
(
tx_count
--
)
uniphier_spi_send
(
priv
);
}
static
void
uniphier_spi_set_cs
(
struct
spi_device
*
spi
,
bool
enable
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
spi
->
master
);
u32
val
;
val
=
readl
(
priv
->
base
+
SSI_FPS
);
if
(
enable
)
val
|=
SSI_FPS_FSPOL
;
else
val
&=
~
SSI_FPS_FSPOL
;
writel
(
val
,
priv
->
base
+
SSI_FPS
);
}
static
int
uniphier_spi_transfer_one
(
struct
spi_master
*
master
,
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
master
);
int
status
;
uniphier_spi_setup_transfer
(
spi
,
t
);
reinit_completion
(
&
priv
->
xfer_done
);
uniphier_spi_fill_tx_fifo
(
priv
);
uniphier_spi_irq_enable
(
spi
,
SSI_IE_RCIE
|
SSI_IE_RORIE
);
status
=
wait_for_completion_timeout
(
&
priv
->
xfer_done
,
msecs_to_jiffies
(
SSI_TIMEOUT_MS
));
uniphier_spi_irq_disable
(
spi
,
SSI_IE_RCIE
|
SSI_IE_RORIE
);
if
(
status
<
0
)
return
status
;
return
priv
->
error
;
}
static
int
uniphier_spi_prepare_transfer_hardware
(
struct
spi_master
*
master
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
master
);
writel
(
SSI_CTL_EN
,
priv
->
base
+
SSI_CTL
);
return
0
;
}
static
int
uniphier_spi_unprepare_transfer_hardware
(
struct
spi_master
*
master
)
{
struct
uniphier_spi_priv
*
priv
=
spi_master_get_devdata
(
master
);
writel
(
0
,
priv
->
base
+
SSI_CTL
);
return
0
;
}
static
irqreturn_t
uniphier_spi_handler
(
int
irq
,
void
*
dev_id
)
{
struct
uniphier_spi_priv
*
priv
=
dev_id
;
u32
val
,
stat
;
stat
=
readl
(
priv
->
base
+
SSI_IS
);
val
=
SSI_IC_TCIC
|
SSI_IC_RCIC
|
SSI_IC_RORIC
;
writel
(
val
,
priv
->
base
+
SSI_IC
);
/* rx fifo overrun */
if
(
stat
&
SSI_IS_RORID
)
{
priv
->
error
=
-
EIO
;
goto
done
;
}
/* rx complete */
if
((
stat
&
SSI_IS_RCID
)
&&
(
stat
&
SSI_IS_RXRS
))
{
while
((
readl
(
priv
->
base
+
SSI_SR
)
&
SSI_SR_RNE
)
&&
(
priv
->
rx_bytes
-
priv
->
tx_bytes
)
>
0
)
uniphier_spi_recv
(
priv
);
if
((
readl
(
priv
->
base
+
SSI_SR
)
&
SSI_SR_RNE
)
||
(
priv
->
rx_bytes
!=
priv
->
tx_bytes
))
{
priv
->
error
=
-
EIO
;
goto
done
;
}
else
if
(
priv
->
rx_bytes
==
0
)
goto
done
;
/* next tx transfer */
uniphier_spi_fill_tx_fifo
(
priv
);
return
IRQ_HANDLED
;
}
return
IRQ_NONE
;
done:
complete
(
&
priv
->
xfer_done
);
return
IRQ_HANDLED
;
}
static
int
uniphier_spi_probe
(
struct
platform_device
*
pdev
)
{
struct
uniphier_spi_priv
*
priv
;
struct
spi_master
*
master
;
struct
resource
*
res
;
unsigned
long
clk_rate
;
int
irq
;
int
ret
;
master
=
spi_alloc_master
(
&
pdev
->
dev
,
sizeof
(
*
priv
));
if
(
!
master
)
return
-
ENOMEM
;
platform_set_drvdata
(
pdev
,
master
);
priv
=
spi_master_get_devdata
(
master
);
priv
->
master
=
master
;
priv
->
is_save_param
=
false
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
priv
->
base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
priv
->
base
))
{
ret
=
PTR_ERR
(
priv
->
base
);
goto
out_master_put
;
}
priv
->
clk
=
devm_clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
priv
->
clk
))
{
dev_err
(
&
pdev
->
dev
,
"failed to get clock
\n
"
);
ret
=
PTR_ERR
(
priv
->
clk
);
goto
out_master_put
;
}
ret
=
clk_prepare_enable
(
priv
->
clk
);
if
(
ret
)
goto
out_master_put
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to get IRQ
\n
"
);
ret
=
irq
;
goto
out_disable_clk
;
}
ret
=
devm_request_irq
(
&
pdev
->
dev
,
irq
,
uniphier_spi_handler
,
0
,
"uniphier-spi"
,
priv
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request IRQ
\n
"
);
goto
out_disable_clk
;
}
init_completion
(
&
priv
->
xfer_done
);
clk_rate
=
clk_get_rate
(
priv
->
clk
);
master
->
max_speed_hz
=
DIV_ROUND_UP
(
clk_rate
,
SSI_MIN_CLK_DIVIDER
);
master
->
min_speed_hz
=
DIV_ROUND_UP
(
clk_rate
,
SSI_MAX_CLK_DIVIDER
);
master
->
mode_bits
=
SPI_CPOL
|
SPI_CPHA
|
SPI_CS_HIGH
|
SPI_LSB_FIRST
;
master
->
dev
.
of_node
=
pdev
->
dev
.
of_node
;
master
->
bus_num
=
pdev
->
id
;
master
->
bits_per_word_mask
=
SPI_BPW_RANGE_MASK
(
1
,
32
);
master
->
set_cs
=
uniphier_spi_set_cs
;
master
->
transfer_one
=
uniphier_spi_transfer_one
;
master
->
prepare_transfer_hardware
=
uniphier_spi_prepare_transfer_hardware
;
master
->
unprepare_transfer_hardware
=
uniphier_spi_unprepare_transfer_hardware
;
master
->
num_chipselect
=
1
;
ret
=
devm_spi_register_master
(
&
pdev
->
dev
,
master
);
if
(
ret
)
goto
out_disable_clk
;
return
0
;
out_disable_clk:
clk_disable_unprepare
(
priv
->
clk
);
out_master_put:
spi_master_put
(
master
);
return
ret
;
}
static
int
uniphier_spi_remove
(
struct
platform_device
*
pdev
)
{
struct
uniphier_spi_priv
*
priv
=
platform_get_drvdata
(
pdev
);
clk_disable_unprepare
(
priv
->
clk
);
return
0
;
}
static
const
struct
of_device_id
uniphier_spi_match
[]
=
{
{
.
compatible
=
"socionext,uniphier-scssi"
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE
(
of
,
uniphier_spi_match
);
static
struct
platform_driver
uniphier_spi_driver
=
{
.
probe
=
uniphier_spi_probe
,
.
remove
=
uniphier_spi_remove
,
.
driver
=
{
.
name
=
"uniphier-spi"
,
.
of_match_table
=
uniphier_spi_match
,
},
};
module_platform_driver
(
uniphier_spi_driver
);
MODULE_AUTHOR
(
"Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"
);
MODULE_AUTHOR
(
"Keiji Hayashibara <hayashibara.keiji@socionext.com>"
);
MODULE_DESCRIPTION
(
"Socionext UniPhier SPI controller driver"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/spi/spi-xtensa-xtfpga.c
View file @
c1acb21b
...
...
@@ -54,7 +54,7 @@ static inline void xtfpga_spi_wait_busy(struct xtfpga_spi *xspi)
}
static
u32
xtfpga_spi_txrx_word
(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
v
,
u8
bits
)
u32
v
,
u8
bits
,
unsigned
flags
)
{
struct
xtfpga_spi
*
xspi
=
spi_master_get_devdata
(
spi
->
master
);
...
...
include/linux/spi/adi_spi3.h
deleted
100644 → 0
View file @
c3c71262
/*
* Analog Devices SPI3 controller driver
*
* Copyright (c) 2014 Analog Devices Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#ifndef _ADI_SPI3_H_
#define _ADI_SPI3_H_
#include <linux/types.h>
/* SPI_CONTROL */
#define SPI_CTL_EN 0x00000001
/* Enable */
#define SPI_CTL_MSTR 0x00000002
/* Master/Slave */
#define SPI_CTL_PSSE 0x00000004
/* controls modf error in master mode */
#define SPI_CTL_ODM 0x00000008
/* Open Drain Mode */
#define SPI_CTL_CPHA 0x00000010
/* Clock Phase */
#define SPI_CTL_CPOL 0x00000020
/* Clock Polarity */
#define SPI_CTL_ASSEL 0x00000040
/* Slave Select Pin Control */
#define SPI_CTL_SELST 0x00000080
/* Slave Select Polarity in-between transfers */
#define SPI_CTL_EMISO 0x00000100
/* Enable MISO */
#define SPI_CTL_SIZE 0x00000600
/* Word Transfer Size */
#define SPI_CTL_SIZE08 0x00000000
/* SIZE: 8 bits */
#define SPI_CTL_SIZE16 0x00000200
/* SIZE: 16 bits */
#define SPI_CTL_SIZE32 0x00000400
/* SIZE: 32 bits */
#define SPI_CTL_LSBF 0x00001000
/* LSB First */
#define SPI_CTL_FCEN 0x00002000
/* Flow-Control Enable */
#define SPI_CTL_FCCH 0x00004000
/* Flow-Control Channel Selection */
#define SPI_CTL_FCPL 0x00008000
/* Flow-Control Polarity */
#define SPI_CTL_FCWM 0x00030000
/* Flow-Control Water-Mark */
#define SPI_CTL_FIFO0 0x00000000
/* FCWM: TFIFO empty or RFIFO Full */
#define SPI_CTL_FIFO1 0x00010000
/* FCWM: TFIFO 75% or more empty or RFIFO 75% or more full */
#define SPI_CTL_FIFO2 0x00020000
/* FCWM: TFIFO 50% or more empty or RFIFO 50% or more full */
#define SPI_CTL_FMODE 0x00040000
/* Fast-mode Enable */
#define SPI_CTL_MIOM 0x00300000
/* Multiple I/O Mode */
#define SPI_CTL_MIO_DIS 0x00000000
/* MIOM: Disable */
#define SPI_CTL_MIO_DUAL 0x00100000
/* MIOM: Enable DIOM (Dual I/O Mode) */
#define SPI_CTL_MIO_QUAD 0x00200000
/* MIOM: Enable QUAD (Quad SPI Mode) */
#define SPI_CTL_SOSI 0x00400000
/* Start on MOSI */
/* SPI_RX_CONTROL */
#define SPI_RXCTL_REN 0x00000001
/* Receive Channel Enable */
#define SPI_RXCTL_RTI 0x00000004
/* Receive Transfer Initiate */
#define SPI_RXCTL_RWCEN 0x00000008
/* Receive Word Counter Enable */
#define SPI_RXCTL_RDR 0x00000070
/* Receive Data Request */
#define SPI_RXCTL_RDR_DIS 0x00000000
/* RDR: Disabled */
#define SPI_RXCTL_RDR_NE 0x00000010
/* RDR: RFIFO not empty */
#define SPI_RXCTL_RDR_25 0x00000020
/* RDR: RFIFO 25% full */
#define SPI_RXCTL_RDR_50 0x00000030
/* RDR: RFIFO 50% full */
#define SPI_RXCTL_RDR_75 0x00000040
/* RDR: RFIFO 75% full */
#define SPI_RXCTL_RDR_FULL 0x00000050
/* RDR: RFIFO full */
#define SPI_RXCTL_RDO 0x00000100
/* Receive Data Over-Run */
#define SPI_RXCTL_RRWM 0x00003000
/* FIFO Regular Water-Mark */
#define SPI_RXCTL_RWM_0 0x00000000
/* RRWM: RFIFO Empty */
#define SPI_RXCTL_RWM_25 0x00001000
/* RRWM: RFIFO 25% full */
#define SPI_RXCTL_RWM_50 0x00002000
/* RRWM: RFIFO 50% full */
#define SPI_RXCTL_RWM_75 0x00003000
/* RRWM: RFIFO 75% full */
#define SPI_RXCTL_RUWM 0x00070000
/* FIFO Urgent Water-Mark */
#define SPI_RXCTL_UWM_DIS 0x00000000
/* RUWM: Disabled */
#define SPI_RXCTL_UWM_25 0x00010000
/* RUWM: RFIFO 25% full */
#define SPI_RXCTL_UWM_50 0x00020000
/* RUWM: RFIFO 50% full */
#define SPI_RXCTL_UWM_75 0x00030000
/* RUWM: RFIFO 75% full */
#define SPI_RXCTL_UWM_FULL 0x00040000
/* RUWM: RFIFO full */
/* SPI_TX_CONTROL */
#define SPI_TXCTL_TEN 0x00000001
/* Transmit Channel Enable */
#define SPI_TXCTL_TTI 0x00000004
/* Transmit Transfer Initiate */
#define SPI_TXCTL_TWCEN 0x00000008
/* Transmit Word Counter Enable */
#define SPI_TXCTL_TDR 0x00000070
/* Transmit Data Request */
#define SPI_TXCTL_TDR_DIS 0x00000000
/* TDR: Disabled */
#define SPI_TXCTL_TDR_NF 0x00000010
/* TDR: TFIFO not full */
#define SPI_TXCTL_TDR_25 0x00000020
/* TDR: TFIFO 25% empty */
#define SPI_TXCTL_TDR_50 0x00000030
/* TDR: TFIFO 50% empty */
#define SPI_TXCTL_TDR_75 0x00000040
/* TDR: TFIFO 75% empty */
#define SPI_TXCTL_TDR_EMPTY 0x00000050
/* TDR: TFIFO empty */
#define SPI_TXCTL_TDU 0x00000100
/* Transmit Data Under-Run */
#define SPI_TXCTL_TRWM 0x00003000
/* FIFO Regular Water-Mark */
#define SPI_TXCTL_RWM_FULL 0x00000000
/* TRWM: TFIFO full */
#define SPI_TXCTL_RWM_25 0x00001000
/* TRWM: TFIFO 25% empty */
#define SPI_TXCTL_RWM_50 0x00002000
/* TRWM: TFIFO 50% empty */
#define SPI_TXCTL_RWM_75 0x00003000
/* TRWM: TFIFO 75% empty */
#define SPI_TXCTL_TUWM 0x00070000
/* FIFO Urgent Water-Mark */
#define SPI_TXCTL_UWM_DIS 0x00000000
/* TUWM: Disabled */
#define SPI_TXCTL_UWM_25 0x00010000
/* TUWM: TFIFO 25% empty */
#define SPI_TXCTL_UWM_50 0x00020000
/* TUWM: TFIFO 50% empty */
#define SPI_TXCTL_UWM_75 0x00030000
/* TUWM: TFIFO 75% empty */
#define SPI_TXCTL_UWM_EMPTY 0x00040000
/* TUWM: TFIFO empty */
/* SPI_CLOCK */
#define SPI_CLK_BAUD 0x0000FFFF
/* Baud Rate */
/* SPI_DELAY */
#define SPI_DLY_STOP 0x000000FF
/* Transfer delay time in multiples of SCK period */
#define SPI_DLY_LEADX 0x00000100
/* Extended (1 SCK) LEAD Control */
#define SPI_DLY_LAGX 0x00000200
/* Extended (1 SCK) LAG control */
/* SPI_SSEL */
#define SPI_SLVSEL_SSE1 0x00000002
/* SPISSEL1 Enable */
#define SPI_SLVSEL_SSE2 0x00000004
/* SPISSEL2 Enable */
#define SPI_SLVSEL_SSE3 0x00000008
/* SPISSEL3 Enable */
#define SPI_SLVSEL_SSE4 0x00000010
/* SPISSEL4 Enable */
#define SPI_SLVSEL_SSE5 0x00000020
/* SPISSEL5 Enable */
#define SPI_SLVSEL_SSE6 0x00000040
/* SPISSEL6 Enable */
#define SPI_SLVSEL_SSE7 0x00000080
/* SPISSEL7 Enable */
#define SPI_SLVSEL_SSEL1 0x00000200
/* SPISSEL1 Value */
#define SPI_SLVSEL_SSEL2 0x00000400
/* SPISSEL2 Value */
#define SPI_SLVSEL_SSEL3 0x00000800
/* SPISSEL3 Value */
#define SPI_SLVSEL_SSEL4 0x00001000
/* SPISSEL4 Value */
#define SPI_SLVSEL_SSEL5 0x00002000
/* SPISSEL5 Value */
#define SPI_SLVSEL_SSEL6 0x00004000
/* SPISSEL6 Value */
#define SPI_SLVSEL_SSEL7 0x00008000
/* SPISSEL7 Value */
/* SPI_RWC */
#define SPI_RWC_VALUE 0x0000FFFF
/* Received Word-Count */
/* SPI_RWCR */
#define SPI_RWCR_VALUE 0x0000FFFF
/* Received Word-Count Reload */
/* SPI_TWC */
#define SPI_TWC_VALUE 0x0000FFFF
/* Transmitted Word-Count */
/* SPI_TWCR */
#define SPI_TWCR_VALUE 0x0000FFFF
/* Transmitted Word-Count Reload */
/* SPI_IMASK */
#define SPI_IMSK_RUWM 0x00000002
/* Receive Urgent Water-Mark Interrupt Mask */
#define SPI_IMSK_TUWM 0x00000004
/* Transmit Urgent Water-Mark Interrupt Mask */
#define SPI_IMSK_ROM 0x00000010
/* Receive Over-Run Error Interrupt Mask */
#define SPI_IMSK_TUM 0x00000020
/* Transmit Under-Run Error Interrupt Mask */
#define SPI_IMSK_TCM 0x00000040
/* Transmit Collision Error Interrupt Mask */
#define SPI_IMSK_MFM 0x00000080
/* Mode Fault Error Interrupt Mask */
#define SPI_IMSK_RSM 0x00000100
/* Receive Start Interrupt Mask */
#define SPI_IMSK_TSM 0x00000200
/* Transmit Start Interrupt Mask */
#define SPI_IMSK_RFM 0x00000400
/* Receive Finish Interrupt Mask */
#define SPI_IMSK_TFM 0x00000800
/* Transmit Finish Interrupt Mask */
/* SPI_IMASKCL */
#define SPI_IMSK_CLR_RUW 0x00000002
/* Receive Urgent Water-Mark Interrupt Mask */
#define SPI_IMSK_CLR_TUWM 0x00000004
/* Transmit Urgent Water-Mark Interrupt Mask */
#define SPI_IMSK_CLR_ROM 0x00000010
/* Receive Over-Run Error Interrupt Mask */
#define SPI_IMSK_CLR_TUM 0x00000020
/* Transmit Under-Run Error Interrupt Mask */
#define SPI_IMSK_CLR_TCM 0x00000040
/* Transmit Collision Error Interrupt Mask */
#define SPI_IMSK_CLR_MFM 0x00000080
/* Mode Fault Error Interrupt Mask */
#define SPI_IMSK_CLR_RSM 0x00000100
/* Receive Start Interrupt Mask */
#define SPI_IMSK_CLR_TSM 0x00000200
/* Transmit Start Interrupt Mask */
#define SPI_IMSK_CLR_RFM 0x00000400
/* Receive Finish Interrupt Mask */
#define SPI_IMSK_CLR_TFM 0x00000800
/* Transmit Finish Interrupt Mask */
/* SPI_IMASKST */
#define SPI_IMSK_SET_RUWM 0x00000002
/* Receive Urgent Water-Mark Interrupt Mask */
#define SPI_IMSK_SET_TUWM 0x00000004
/* Transmit Urgent Water-Mark Interrupt Mask */
#define SPI_IMSK_SET_ROM 0x00000010
/* Receive Over-Run Error Interrupt Mask */
#define SPI_IMSK_SET_TUM 0x00000020
/* Transmit Under-Run Error Interrupt Mask */
#define SPI_IMSK_SET_TCM 0x00000040
/* Transmit Collision Error Interrupt Mask */
#define SPI_IMSK_SET_MFM 0x00000080
/* Mode Fault Error Interrupt Mask */
#define SPI_IMSK_SET_RSM 0x00000100
/* Receive Start Interrupt Mask */
#define SPI_IMSK_SET_TSM 0x00000200
/* Transmit Start Interrupt Mask */
#define SPI_IMSK_SET_RFM 0x00000400
/* Receive Finish Interrupt Mask */
#define SPI_IMSK_SET_TFM 0x00000800
/* Transmit Finish Interrupt Mask */
/* SPI_STATUS */
#define SPI_STAT_SPIF 0x00000001
/* SPI Finished */
#define SPI_STAT_RUWM 0x00000002
/* Receive Urgent Water-Mark Breached */
#define SPI_STAT_TUWM 0x00000004
/* Transmit Urgent Water-Mark Breached */
#define SPI_STAT_ROE 0x00000010
/* Receive Over-Run Error Indication */
#define SPI_STAT_TUE 0x00000020
/* Transmit Under-Run Error Indication */
#define SPI_STAT_TCE 0x00000040
/* Transmit Collision Error Indication */
#define SPI_STAT_MODF 0x00000080
/* Mode Fault Error Indication */
#define SPI_STAT_RS 0x00000100
/* Receive Start Indication */
#define SPI_STAT_TS 0x00000200
/* Transmit Start Indication */
#define SPI_STAT_RF 0x00000400
/* Receive Finish Indication */
#define SPI_STAT_TF 0x00000800
/* Transmit Finish Indication */
#define SPI_STAT_RFS 0x00007000
/* SPI_RFIFO status */
#define SPI_STAT_RFIFO_EMPTY 0x00000000
/* RFS: RFIFO Empty */
#define SPI_STAT_RFIFO_25 0x00001000
/* RFS: RFIFO 25% Full */
#define SPI_STAT_RFIFO_50 0x00002000
/* RFS: RFIFO 50% Full */
#define SPI_STAT_RFIFO_75 0x00003000
/* RFS: RFIFO 75% Full */
#define SPI_STAT_RFIFO_FULL 0x00004000
/* RFS: RFIFO Full */
#define SPI_STAT_TFS 0x00070000
/* SPI_TFIFO status */
#define SPI_STAT_TFIFO_FULL 0x00000000
/* TFS: TFIFO full */
#define SPI_STAT_TFIFO_25 0x00010000
/* TFS: TFIFO 25% empty */
#define SPI_STAT_TFIFO_50 0x00020000
/* TFS: TFIFO 50% empty */
#define SPI_STAT_TFIFO_75 0x00030000
/* TFS: TFIFO 75% empty */
#define SPI_STAT_TFIFO_EMPTY 0x00040000
/* TFS: TFIFO empty */
#define SPI_STAT_FCS 0x00100000
/* Flow-Control Stall Indication */
#define SPI_STAT_RFE 0x00400000
/* SPI_RFIFO Empty */
#define SPI_STAT_TFF 0x00800000
/* SPI_TFIFO Full */
/* SPI_ILAT */
#define SPI_ILAT_RUWMI 0x00000002
/* Receive Urgent Water Mark Interrupt */
#define SPI_ILAT_TUWMI 0x00000004
/* Transmit Urgent Water Mark Interrupt */
#define SPI_ILAT_ROI 0x00000010
/* Receive Over-Run Error Indication */
#define SPI_ILAT_TUI 0x00000020
/* Transmit Under-Run Error Indication */
#define SPI_ILAT_TCI 0x00000040
/* Transmit Collision Error Indication */
#define SPI_ILAT_MFI 0x00000080
/* Mode Fault Error Indication */
#define SPI_ILAT_RSI 0x00000100
/* Receive Start Indication */
#define SPI_ILAT_TSI 0x00000200
/* Transmit Start Indication */
#define SPI_ILAT_RFI 0x00000400
/* Receive Finish Indication */
#define SPI_ILAT_TFI 0x00000800
/* Transmit Finish Indication */
/* SPI_ILATCL */
#define SPI_ILAT_CLR_RUWMI 0x00000002
/* Receive Urgent Water Mark Interrupt */
#define SPI_ILAT_CLR_TUWMI 0x00000004
/* Transmit Urgent Water Mark Interrupt */
#define SPI_ILAT_CLR_ROI 0x00000010
/* Receive Over-Run Error Indication */
#define SPI_ILAT_CLR_TUI 0x00000020
/* Transmit Under-Run Error Indication */
#define SPI_ILAT_CLR_TCI 0x00000040
/* Transmit Collision Error Indication */
#define SPI_ILAT_CLR_MFI 0x00000080
/* Mode Fault Error Indication */
#define SPI_ILAT_CLR_RSI 0x00000100
/* Receive Start Indication */
#define SPI_ILAT_CLR_TSI 0x00000200
/* Transmit Start Indication */
#define SPI_ILAT_CLR_RFI 0x00000400
/* Receive Finish Indication */
#define SPI_ILAT_CLR_TFI 0x00000800
/* Transmit Finish Indication */
/*
* adi spi3 registers layout
*/
struct
adi_spi_regs
{
u32
revid
;
u32
control
;
u32
rx_control
;
u32
tx_control
;
u32
clock
;
u32
delay
;
u32
ssel
;
u32
rwc
;
u32
rwcr
;
u32
twc
;
u32
twcr
;
u32
reserved0
;
u32
emask
;
u32
emaskcl
;
u32
emaskst
;
u32
reserved1
;
u32
status
;
u32
elat
;
u32
elatcl
;
u32
reserved2
;
u32
rfifo
;
u32
reserved3
;
u32
tfifo
;
};
#define MAX_CTRL_CS 8
/* cs in spi controller */
/* device.platform_data for SSP controller devices */
struct
adi_spi3_master
{
u16
num_chipselect
;
u16
pin_req
[
7
];
};
/* spi_board_info.controller_data for SPI slave devices,
* copied to spi_device.platform_data ... mostly for dma tuning
*/
struct
adi_spi3_chip
{
u32
control
;
u16
cs_chg_udelay
;
/* Some devices require 16-bit delays */
u32
tx_dummy_val
;
/* tx value for rx only transfer */
bool
enable_dma
;
};
#endif
/* _ADI_SPI3_H_ */
include/linux/spi/spi-mem.h
View file @
c1acb21b
...
...
@@ -122,7 +122,8 @@ struct spi_mem_op {
/**
* struct spi_mem - describes a SPI memory device
* @spi: the underlying SPI device
* @drvpriv: spi_mem_drviver private data
* @drvpriv: spi_mem_driver private data
* @name: name of the SPI memory device
*
* Extra information that describe the SPI memory device and may be needed by
* the controller to properly handle this device should be placed here.
...
...
@@ -133,6 +134,7 @@ struct spi_mem_op {
struct
spi_mem
{
struct
spi_device
*
spi
;
void
*
drvpriv
;
const
char
*
name
;
};
/**
...
...
@@ -165,6 +167,13 @@ static inline void *spi_mem_get_drvdata(struct spi_mem *mem)
* limitations)
* @supports_op: check if an operation is supported by the controller
* @exec_op: execute a SPI memory operation
* @get_name: get a custom name for the SPI mem device from the controller.
* This might be needed if the controller driver has been ported
* to use the SPI mem layer and a custom name is used to keep
* mtdparts compatible.
* Note that if the implementation of this function allocates memory
* dynamically, then it should do so with devm_xxx(), as we don't
* have a ->free_name() function.
*
* This interface should be implemented by SPI controllers providing an
* high-level interface to execute SPI memory operation, which is usually the
...
...
@@ -176,6 +185,7 @@ struct spi_controller_mem_ops {
const
struct
spi_mem_op
*
op
);
int
(
*
exec_op
)(
struct
spi_mem
*
mem
,
const
struct
spi_mem_op
*
op
);
const
char
*
(
*
get_name
)(
struct
spi_mem
*
mem
);
};
/**
...
...
@@ -234,6 +244,8 @@ bool spi_mem_supports_op(struct spi_mem *mem,
int
spi_mem_exec_op
(
struct
spi_mem
*
mem
,
const
struct
spi_mem_op
*
op
);
const
char
*
spi_mem_get_name
(
struct
spi_mem
*
mem
);
int
spi_mem_driver_register_with_owner
(
struct
spi_mem_driver
*
drv
,
struct
module
*
owner
);
...
...
include/linux/spi/spi_bitbang.h
View file @
c1acb21b
...
...
@@ -8,7 +8,7 @@ struct spi_bitbang {
struct
mutex
lock
;
u8
busy
;
u8
use_dma
;
u
8
flags
;
/* extra spi->mode support */
u
16
flags
;
/* extra spi->mode support */
struct
spi_master
*
master
;
...
...
@@ -30,7 +30,8 @@ struct spi_bitbang {
/* txrx_word[SPI_MODE_*]() just looks like a shift register */
u32
(
*
txrx_word
[
4
])(
struct
spi_device
*
spi
,
unsigned
nsecs
,
u32
word
,
u8
bits
);
u32
word
,
u8
bits
,
unsigned
flags
);
int
(
*
set_line_direction
)(
struct
spi_device
*
spi
,
bool
output
);
};
/* you can call these default bitbang->master methods from your custom
...
...
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