Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
ce7fb74f
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
ce7fb74f
编写于
3月 11, 2016
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'spi/topic/imx' into spi-next
上级
a75481ab
6b6192c0
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
183 addition
and
158 deletion
+183
-158
drivers/spi/spi-imx.c
drivers/spi/spi-imx.c
+183
-158
未找到文件。
drivers/spi/spi-imx.c
浏览文件 @
ce7fb74f
...
...
@@ -56,7 +56,6 @@
/* The maximum bytes that a sdma BD can transfer.*/
#define MAX_SDMA_BD_BYTES (1 << 15)
#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000))
struct
spi_imx_config
{
unsigned
int
speed_hz
;
unsigned
int
bpw
;
...
...
@@ -86,12 +85,18 @@ struct spi_imx_devtype_data {
struct
spi_imx_data
{
struct
spi_bitbang
bitbang
;
struct
device
*
dev
;
struct
completion
xfer_done
;
void
__iomem
*
base
;
unsigned
long
base_phys
;
struct
clk
*
clk_per
;
struct
clk
*
clk_ipg
;
unsigned
long
spi_clk
;
unsigned
int
spi_bus_clk
;
unsigned
int
bytes_per_word
;
unsigned
int
count
;
void
(
*
tx
)(
struct
spi_imx_data
*
);
...
...
@@ -101,8 +106,6 @@ struct spi_imx_data {
unsigned
int
txfifo
;
/* number of words pushed in tx FIFO */
/* DMA */
unsigned
int
dma_is_inited
;
unsigned
int
dma_finished
;
bool
usedma
;
u32
wml
;
struct
completion
dma_rx_completion
;
...
...
@@ -199,15 +202,35 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return
7
;
}
static
int
spi_imx_bytes_per_word
(
const
int
bpw
)
{
return
DIV_ROUND_UP
(
bpw
,
BITS_PER_BYTE
);
}
static
bool
spi_imx_can_dma
(
struct
spi_master
*
master
,
struct
spi_device
*
spi
,
struct
spi_transfer
*
transfer
)
{
struct
spi_imx_data
*
spi_imx
=
spi_master_get_devdata
(
master
);
unsigned
int
bpw
=
transfer
->
bits_per_word
;
if
(
spi_imx
->
dma_is_inited
&&
transfer
->
len
>=
spi_imx
->
wml
&&
(
transfer
->
len
%
spi_imx
->
wml
)
==
0
)
return
true
;
if
(
!
master
->
dma_rx
)
return
false
;
if
(
!
bpw
)
bpw
=
spi
->
bits_per_word
;
bpw
=
spi_imx_bytes_per_word
(
bpw
);
if
(
bpw
!=
1
&&
bpw
!=
2
&&
bpw
!=
4
)
return
false
;
if
(
transfer
->
len
<
spi_imx
->
wml
*
bpw
)
return
false
;
if
(
transfer
->
len
%
(
spi_imx
->
wml
*
bpw
))
return
false
;
return
true
;
}
#define MX51_ECSPI_CTRL 0x08
...
...
@@ -232,16 +255,13 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_INT_RREN (1 << 3)
#define MX51_ECSPI_DMA 0x14
#define MX51_ECSPI_DMA_TX_WML_OFFSET 0
#define MX51_ECSPI_DMA_TX_WML_MASK 0x3F
#define MX51_ECSPI_DMA_RX_WML_OFFSET 16
#define MX51_ECSPI_DMA_RX_WML_MASK (0x3F << 16)
#define MX51_ECSPI_DMA_RXT_WML_OFFSET 24
#define MX51_ECSPI_DMA_RXT_WML_MASK (0x3F << 24)
#define MX51_ECSPI_DMA_TX_WML(wml) ((wml) & 0x3f)
#define MX51_ECSPI_DMA_RX_WML(wml) (((wml) & 0x3f) << 16)
#define MX51_ECSPI_DMA_RXT_WML(wml) (((wml) & 0x3f) << 24)
#define MX51_ECSPI_DMA_TEDEN
_OFFSET 7
#define MX51_ECSPI_DMA_RXDEN
_OFFSET 23
#define MX51_ECSPI_DMA_RXTDEN
_OFFSET 31
#define MX51_ECSPI_DMA_TEDEN
(1 << 7)
#define MX51_ECSPI_DMA_RXDEN
(1 << 23)
#define MX51_ECSPI_DMA_RXTDEN
(1 << 31)
#define MX51_ECSPI_STAT 0x18
#define MX51_ECSPI_STAT_RR (1 << 3)
...
...
@@ -250,14 +270,15 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_TESTREG_LBC BIT(31)
/* MX51 eCSPI */
static
unsigned
int
mx51_ecspi_clkdiv
(
unsigned
int
fin
,
unsigned
int
fspi
,
unsigned
int
*
fres
)
static
unsigned
int
mx51_ecspi_clkdiv
(
struct
spi_imx_data
*
spi_imx
,
unsigned
int
fspi
,
unsigned
int
*
fres
)
{
/*
* there are two 4-bit dividers, the pre-divider divides by
* $pre, the post-divider by 2^$post
*/
unsigned
int
pre
,
post
;
unsigned
int
fin
=
spi_imx
->
spi_clk
;
if
(
unlikely
(
fspi
>
fin
))
return
0
;
...
...
@@ -270,14 +291,14 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
post
=
max
(
4U
,
post
)
-
4
;
if
(
unlikely
(
post
>
0xf
))
{
pr_err
(
"%s:
cannot set clock freq: %u (base freq: %u)
\n
"
,
__func__
,
fspi
,
fin
);
dev_err
(
spi_imx
->
dev
,
"
cannot set clock freq: %u (base freq: %u)
\n
"
,
fspi
,
fin
);
return
0xff
;
}
pre
=
DIV_ROUND_UP
(
fin
,
fspi
<<
post
)
-
1
;
pr_debug
(
"%s: fin: %u, fspi: %u, post: %u, pre: %u
\n
"
,
dev_dbg
(
spi_imx
->
dev
,
"%s: fin: %u, fspi: %u, post: %u, pre: %u
\n
"
,
__func__
,
fin
,
fspi
,
post
,
pre
);
/* Resulting frequency for the SCLK line. */
...
...
@@ -302,22 +323,17 @@ static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int
static
void
__maybe_unused
mx51_ecspi_trigger
(
struct
spi_imx_data
*
spi_imx
)
{
u32
reg
=
readl
(
spi_imx
->
base
+
MX51_ECSPI_CTRL
)
;
u32
reg
;
if
(
!
spi_imx
->
usedma
)
reg
=
readl
(
spi_imx
->
base
+
MX51_ECSPI_CTRL
);
reg
|=
MX51_ECSPI_CTRL_XCH
;
else
if
(
!
spi_imx
->
dma_finished
)
reg
|=
MX51_ECSPI_CTRL_SMC
;
else
reg
&=
~
MX51_ECSPI_CTRL_SMC
;
writel
(
reg
,
spi_imx
->
base
+
MX51_ECSPI_CTRL
);
}
static
int
__maybe_unused
mx51_ecspi_config
(
struct
spi_imx_data
*
spi_imx
,
struct
spi_imx_config
*
config
)
{
u32
ctrl
=
MX51_ECSPI_CTRL_ENABLE
,
cfg
=
0
,
dma
=
0
;
u32
tx_wml_cfg
,
rx_wml_cfg
,
rxt_wml_cfg
;
u32
ctrl
=
MX51_ECSPI_CTRL_ENABLE
,
cfg
=
0
;
u32
clk
=
config
->
speed_hz
,
delay
,
reg
;
/*
...
...
@@ -330,7 +346,8 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
ctrl
|=
MX51_ECSPI_CTRL_MODE_MASK
;
/* set clock speed */
ctrl
|=
mx51_ecspi_clkdiv
(
spi_imx
->
spi_clk
,
config
->
speed_hz
,
&
clk
);
ctrl
|=
mx51_ecspi_clkdiv
(
spi_imx
,
config
->
speed_hz
,
&
clk
);
spi_imx
->
spi_bus_clk
=
clk
;
/* set chip select to use */
ctrl
|=
MX51_ECSPI_CTRL_CS
(
config
->
cs
);
...
...
@@ -341,20 +358,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
if
(
config
->
mode
&
SPI_CPHA
)
cfg
|=
MX51_ECSPI_CONFIG_SCLKPHA
(
config
->
cs
);
else
cfg
&=
~
MX51_ECSPI_CONFIG_SCLKPHA
(
config
->
cs
);
if
(
config
->
mode
&
SPI_CPOL
)
{
cfg
|=
MX51_ECSPI_CONFIG_SCLKPOL
(
config
->
cs
);
cfg
|=
MX51_ECSPI_CONFIG_SCLKCTL
(
config
->
cs
);
}
else
{
cfg
&=
~
MX51_ECSPI_CONFIG_SCLKPOL
(
config
->
cs
);
cfg
&=
~
MX51_ECSPI_CONFIG_SCLKCTL
(
config
->
cs
);
}
if
(
config
->
mode
&
SPI_CS_HIGH
)
cfg
|=
MX51_ECSPI_CONFIG_SSBPOL
(
config
->
cs
);
else
cfg
&=
~
MX51_ECSPI_CONFIG_SSBPOL
(
config
->
cs
);
if
(
spi_imx
->
usedma
)
ctrl
|=
MX51_ECSPI_CTRL_SMC
;
/* CTRL register always go first to bring out controller from reset */
writel
(
ctrl
,
spi_imx
->
base
+
MX51_ECSPI_CTRL
);
...
...
@@ -389,22 +402,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
* Configure the DMA register: setup the watermark
* and enable DMA request.
*/
if
(
spi_imx
->
dma_is_inited
)
{
dma
=
readl
(
spi_imx
->
base
+
MX51_ECSPI_DMA
);
rx_wml_cfg
=
spi_imx
->
wml
<<
MX51_ECSPI_DMA_RX_WML_OFFSET
;
tx_wml_cfg
=
spi_imx
->
wml
<<
MX51_ECSPI_DMA_TX_WML_OFFSET
;
rxt_wml_cfg
=
spi_imx
->
wml
<<
MX51_ECSPI_DMA_RXT_WML_OFFSET
;
dma
=
(
dma
&
~
MX51_ECSPI_DMA_TX_WML_MASK
&
~
MX51_ECSPI_DMA_RX_WML_MASK
&
~
MX51_ECSPI_DMA_RXT_WML_MASK
)
|
rx_wml_cfg
|
tx_wml_cfg
|
rxt_wml_cfg
|
(
1
<<
MX51_ECSPI_DMA_TEDEN_OFFSET
)
|
(
1
<<
MX51_ECSPI_DMA_RXDEN_OFFSET
)
|
(
1
<<
MX51_ECSPI_DMA_RXTDEN_OFFSET
);
writel
(
dma
,
spi_imx
->
base
+
MX51_ECSPI_DMA
);
}
writel
(
MX51_ECSPI_DMA_RX_WML
(
spi_imx
->
wml
)
|
MX51_ECSPI_DMA_TX_WML
(
spi_imx
->
wml
)
|
MX51_ECSPI_DMA_RXT_WML
(
spi_imx
->
wml
)
|
MX51_ECSPI_DMA_TEDEN
|
MX51_ECSPI_DMA_RXDEN
|
MX51_ECSPI_DMA_RXTDEN
,
spi_imx
->
base
+
MX51_ECSPI_DMA
);
return
0
;
}
...
...
@@ -784,11 +787,63 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return
IRQ_HANDLED
;
}
static
int
spi_imx_dma_configure
(
struct
spi_master
*
master
,
int
bytes_per_word
)
{
int
ret
;
enum
dma_slave_buswidth
buswidth
;
struct
dma_slave_config
rx
=
{},
tx
=
{};
struct
spi_imx_data
*
spi_imx
=
spi_master_get_devdata
(
master
);
if
(
bytes_per_word
==
spi_imx
->
bytes_per_word
)
/* Same as last time */
return
0
;
switch
(
bytes_per_word
)
{
case
4
:
buswidth
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
break
;
case
2
:
buswidth
=
DMA_SLAVE_BUSWIDTH_2_BYTES
;
break
;
case
1
:
buswidth
=
DMA_SLAVE_BUSWIDTH_1_BYTE
;
break
;
default:
return
-
EINVAL
;
}
tx
.
direction
=
DMA_MEM_TO_DEV
;
tx
.
dst_addr
=
spi_imx
->
base_phys
+
MXC_CSPITXDATA
;
tx
.
dst_addr_width
=
buswidth
;
tx
.
dst_maxburst
=
spi_imx
->
wml
;
ret
=
dmaengine_slave_config
(
master
->
dma_tx
,
&
tx
);
if
(
ret
)
{
dev_err
(
spi_imx
->
dev
,
"TX dma configuration failed with %d
\n
"
,
ret
);
return
ret
;
}
rx
.
direction
=
DMA_DEV_TO_MEM
;
rx
.
src_addr
=
spi_imx
->
base_phys
+
MXC_CSPIRXDATA
;
rx
.
src_addr_width
=
buswidth
;
rx
.
src_maxburst
=
spi_imx
->
wml
;
ret
=
dmaengine_slave_config
(
master
->
dma_rx
,
&
rx
);
if
(
ret
)
{
dev_err
(
spi_imx
->
dev
,
"RX dma configuration failed with %d
\n
"
,
ret
);
return
ret
;
}
spi_imx
->
bytes_per_word
=
bytes_per_word
;
return
0
;
}
static
int
spi_imx_setupxfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
t
)
{
struct
spi_imx_data
*
spi_imx
=
spi_master_get_devdata
(
spi
->
master
);
struct
spi_imx_config
config
;
int
ret
;
config
.
bpw
=
t
?
t
->
bits_per_word
:
spi
->
bits_per_word
;
config
.
speed_hz
=
t
?
t
->
speed_hz
:
spi
->
max_speed_hz
;
...
...
@@ -812,6 +867,18 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx
->
tx
=
spi_imx_buf_tx_u32
;
}
if
(
spi_imx_can_dma
(
spi_imx
->
bitbang
.
master
,
spi
,
t
))
spi_imx
->
usedma
=
1
;
else
spi_imx
->
usedma
=
0
;
if
(
spi_imx
->
usedma
)
{
ret
=
spi_imx_dma_configure
(
spi
->
master
,
spi_imx_bytes_per_word
(
config
.
bpw
));
if
(
ret
)
return
ret
;
}
spi_imx
->
devtype_data
->
config
(
spi_imx
,
&
config
);
return
0
;
...
...
@@ -830,15 +897,11 @@ static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
dma_release_channel
(
master
->
dma_tx
);
master
->
dma_tx
=
NULL
;
}
spi_imx
->
dma_is_inited
=
0
;
}
static
int
spi_imx_sdma_init
(
struct
device
*
dev
,
struct
spi_imx_data
*
spi_imx
,
struct
spi_master
*
master
,
const
struct
resource
*
res
)
struct
spi_master
*
master
)
{
struct
dma_slave_config
slave_config
=
{};
int
ret
;
/* use pio mode for i.mx6dl chip TKT238285 */
...
...
@@ -856,16 +919,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
goto
err
;
}
slave_config
.
direction
=
DMA_MEM_TO_DEV
;
slave_config
.
dst_addr
=
res
->
start
+
MXC_CSPITXDATA
;
slave_config
.
dst_addr_width
=
DMA_SLAVE_BUSWIDTH_1_BYTE
;
slave_config
.
dst_maxburst
=
spi_imx
->
wml
;
ret
=
dmaengine_slave_config
(
master
->
dma_tx
,
&
slave_config
);
if
(
ret
)
{
dev_err
(
dev
,
"error in TX dma configuration.
\n
"
);
goto
err
;
}
/* Prepare for RX : */
master
->
dma_rx
=
dma_request_slave_channel_reason
(
dev
,
"rx"
);
if
(
IS_ERR
(
master
->
dma_rx
))
{
...
...
@@ -875,15 +928,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
goto
err
;
}
slave_config
.
direction
=
DMA_DEV_TO_MEM
;
slave_config
.
src_addr
=
res
->
start
+
MXC_CSPIRXDATA
;
slave_config
.
src_addr_width
=
DMA_SLAVE_BUSWIDTH_1_BYTE
;
slave_config
.
src_maxburst
=
spi_imx
->
wml
;
ret
=
dmaengine_slave_config
(
master
->
dma_rx
,
&
slave_config
);
if
(
ret
)
{
dev_err
(
dev
,
"error in RX dma configuration.
\n
"
);
goto
err
;
}
spi_imx_dma_configure
(
master
,
1
);
init_completion
(
&
spi_imx
->
dma_rx_completion
);
init_completion
(
&
spi_imx
->
dma_tx_completion
);
...
...
@@ -891,7 +936,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
master
->
max_dma_len
=
MAX_SDMA_BD_BYTES
;
spi_imx
->
bitbang
.
master
->
flags
=
SPI_MASTER_MUST_RX
|
SPI_MASTER_MUST_TX
;
spi_imx
->
dma_is_inited
=
1
;
return
0
;
err:
...
...
@@ -913,95 +957,81 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete
(
&
spi_imx
->
dma_tx_completion
);
}
static
int
spi_imx_calculate_timeout
(
struct
spi_imx_data
*
spi_imx
,
int
size
)
{
unsigned
long
timeout
=
0
;
/* Time with actual data transfer and CS change delay related to HW */
timeout
=
(
8
+
4
)
*
size
/
spi_imx
->
spi_bus_clk
;
/* Add extra second for scheduler related activities */
timeout
+=
1
;
/* Double calculated timeout */
return
msecs_to_jiffies
(
2
*
timeout
*
MSEC_PER_SEC
);
}
static
int
spi_imx_dma_transfer
(
struct
spi_imx_data
*
spi_imx
,
struct
spi_transfer
*
transfer
)
{
struct
dma_async_tx_descriptor
*
desc_tx
=
NULL
,
*
desc_rx
=
NULL
;
int
re
t
;
struct
dma_async_tx_descriptor
*
desc_tx
,
*
desc_rx
;
unsigned
long
transfer_timeou
t
;
unsigned
long
timeout
;
struct
spi_master
*
master
=
spi_imx
->
bitbang
.
master
;
struct
sg_table
*
tx
=
&
transfer
->
tx_sg
,
*
rx
=
&
transfer
->
rx_sg
;
if
(
tx
)
{
desc_tx
=
dmaengine_prep_slave_sg
(
master
->
dma_tx
,
tx
->
sgl
,
tx
->
nents
,
DMA_MEM_TO_DEV
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc_tx
)
goto
tx_nodma
;
desc_tx
->
callback
=
spi_imx_dma_tx_callback
;
desc_tx
->
callback_param
=
(
void
*
)
spi_imx
;
dmaengine_submit
(
desc_tx
);
}
if
(
rx
)
{
/*
* The TX DMA setup starts the transfer, so make sure RX is configured
* before TX.
*/
desc_rx
=
dmaengine_prep_slave_sg
(
master
->
dma_rx
,
rx
->
sgl
,
rx
->
nents
,
DMA_DEV_TO_MEM
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc_rx
)
goto
rx_nodma
;
return
-
EINVAL
;
desc_rx
->
callback
=
spi_imx_dma_rx_callback
;
desc_rx
->
callback_param
=
(
void
*
)
spi_imx
;
dmaengine_submit
(
desc_rx
);
}
reinit_completion
(
&
spi_imx
->
dma_rx_completion
);
reinit_completion
(
&
spi_imx
->
dma_tx_completion
);
dma_async_issue_pending
(
master
->
dma_rx
);
/* Trigger the cspi module. */
spi_imx
->
dma_finished
=
0
;
desc_tx
=
dmaengine_prep_slave_sg
(
master
->
dma_tx
,
tx
->
sgl
,
tx
->
nents
,
DMA_MEM_TO_DEV
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc_tx
)
{
dmaengine_terminate_all
(
master
->
dma_tx
);
return
-
EINVAL
;
}
/*
* Set these order to avoid potential RX overflow. The overflow may
* happen if we enable SPI HW before starting RX DMA due to rescheduling
* for another task and/or interrupt.
* So RX DMA enabled first to make sure data would be read out from FIFO
* ASAP. TX DMA enabled next to start filling TX FIFO with new data.
* And finaly SPI HW enabled to start actual data transfer.
*/
dma_async_issue_pending
(
master
->
dma_rx
);
desc_tx
->
callback
=
spi_imx_dma_tx_callback
;
desc_tx
->
callback_param
=
(
void
*
)
spi_imx
;
dmaengine_submit
(
desc_tx
);
reinit_completion
(
&
spi_imx
->
dma_tx_completion
);
dma_async_issue_pending
(
master
->
dma_tx
);
spi_imx
->
devtype_data
->
trigger
(
spi_imx
);
transfer_timeout
=
spi_imx_calculate_timeout
(
spi_imx
,
transfer
->
len
);
/* Wait SDMA to finish the data transfer.*/
timeout
=
wait_for_completion_timeout
(
&
spi_imx
->
dma_tx_completion
,
IMX_DMA_TIMEOUT
);
transfer_timeout
);
if
(
!
timeout
)
{
pr_warn
(
"%s %s: I/O Error in DMA TX
\n
"
,
dev_driver_string
(
&
master
->
dev
),
dev_name
(
&
master
->
dev
));
dev_err
(
spi_imx
->
dev
,
"I/O Error in DMA TX
\n
"
);
dmaengine_terminate_all
(
master
->
dma_tx
);
dmaengine_terminate_all
(
master
->
dma_rx
);
}
else
{
timeout
=
wait_for_completion_timeout
(
&
spi_imx
->
dma_rx_completion
,
IMX_DMA_TIMEOUT
);
return
-
ETIMEDOUT
;
}
timeout
=
wait_for_completion_timeout
(
&
spi_imx
->
dma_rx_completion
,
transfer_timeout
);
if
(
!
timeout
)
{
pr_warn
(
"%s %s: I/O Error in DMA RX
\n
"
,
dev_driver_string
(
&
master
->
dev
),
dev_name
(
&
master
->
dev
));
dev_err
(
&
master
->
dev
,
"I/O Error in DMA RX
\n
"
);
spi_imx
->
devtype_data
->
reset
(
spi_imx
);
dmaengine_terminate_all
(
master
->
dma_rx
);
return
-
ETIMEDOUT
;
}
}
spi_imx
->
dma_finished
=
1
;
spi_imx
->
devtype_data
->
trigger
(
spi_imx
);
if
(
!
timeout
)
ret
=
-
ETIMEDOUT
;
else
ret
=
transfer
->
len
;
return
ret
;
rx_nodma:
dmaengine_terminate_all
(
master
->
dma_tx
);
tx_nodma:
pr_warn_once
(
"%s %s: DMA not available, falling back to PIO
\n
"
,
dev_driver_string
(
&
master
->
dev
),
dev_name
(
&
master
->
dev
));
return
-
EAGAIN
;
return
transfer
->
len
;
}
static
int
spi_imx_pio_transfer
(
struct
spi_device
*
spi
,
...
...
@@ -1028,18 +1058,11 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
static
int
spi_imx_transfer
(
struct
spi_device
*
spi
,
struct
spi_transfer
*
transfer
)
{
int
ret
;
struct
spi_imx_data
*
spi_imx
=
spi_master_get_devdata
(
spi
->
master
);
if
(
spi_imx
->
bitbang
.
master
->
can_dma
&&
spi_imx_can_dma
(
spi_imx
->
bitbang
.
master
,
spi
,
transfer
))
{
spi_imx
->
usedma
=
true
;
ret
=
spi_imx_dma_transfer
(
spi_imx
,
transfer
);
if
(
ret
!=
-
EAGAIN
)
return
ret
;
}
spi_imx
->
usedma
=
false
;
if
(
spi_imx
->
usedma
)
return
spi_imx_dma_transfer
(
spi_imx
,
transfer
);
else
return
spi_imx_pio_transfer
(
spi
,
transfer
);
}
...
...
@@ -1130,6 +1153,7 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx
=
spi_master_get_devdata
(
master
);
spi_imx
->
bitbang
.
master
=
master
;
spi_imx
->
dev
=
&
pdev
->
dev
;
spi_imx
->
devtype_data
=
of_id
?
of_id
->
data
:
(
struct
spi_imx_devtype_data
*
)
pdev
->
id_entry
->
driver_data
;
...
...
@@ -1170,6 +1194,7 @@ static int spi_imx_probe(struct platform_device *pdev)
ret
=
PTR_ERR
(
spi_imx
->
base
);
goto
out_master_put
;
}
spi_imx
->
base_phys
=
res
->
start
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
{
...
...
@@ -1210,7 +1235,7 @@ static int spi_imx_probe(struct platform_device *pdev)
* other chips.
*/
if
(
is_imx51_ecspi
(
spi_imx
))
{
ret
=
spi_imx_sdma_init
(
&
pdev
->
dev
,
spi_imx
,
master
,
res
);
ret
=
spi_imx_sdma_init
(
&
pdev
->
dev
,
spi_imx
,
master
);
if
(
ret
==
-
EPROBE_DEFER
)
goto
out_clk_put
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录