Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
2dc5165e
U
U-Boot.Mirror
项目概览
OS
/
U-Boot.Mirror
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
U-Boot.Mirror
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2dc5165e
编写于
3月 25, 2018
作者:
T
Tom Rini
浏览文件
操作
浏览文件
下载
差异文件
Merge
git://git.denx.de/u-boot-spi
上级
f7c9e76f
63018a3e
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
89 addition
and
47 deletion
+89
-47
drivers/spi/designware_spi.c
drivers/spi/designware_spi.c
+85
-45
drivers/spi/omap3_spi.c
drivers/spi/omap3_spi.c
+4
-2
未找到文件。
drivers/spi/designware_spi.c
浏览文件 @
2dc5165e
...
...
@@ -10,6 +10,7 @@
* SPDX-License-Identifier: GPL-2.0
*/
#include <asm-generic/gpio.h>
#include <common.h>
#include <clk.h>
#include <dm.h>
...
...
@@ -18,6 +19,7 @@
#include <spi.h>
#include <fdtdec.h>
#include <linux/compat.h>
#include <linux/iopoll.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR
;
...
...
@@ -97,6 +99,8 @@ struct dw_spi_priv {
struct
clk
clk
;
unsigned
long
bus_clk_rate
;
struct
gpio_desc
cs_gpio
;
/* External chip-select gpio */
int
bits_per_word
;
u8
cs
;
/* chip select pin */
u8
tmode
;
/* TR/TO/RO/EEPROM */
...
...
@@ -110,24 +114,40 @@ struct dw_spi_priv {
void
*
rx_end
;
};
static
inline
u32
dw_read
l
(
struct
dw_spi_priv
*
priv
,
u32
offset
)
static
inline
u32
dw_read
(
struct
dw_spi_priv
*
priv
,
u32
offset
)
{
return
__raw_readl
(
priv
->
regs
+
offset
);
}
static
inline
void
dw_write
l
(
struct
dw_spi_priv
*
priv
,
u32
offset
,
u32
val
)
static
inline
void
dw_write
(
struct
dw_spi_priv
*
priv
,
u32
offset
,
u32
val
)
{
__raw_writel
(
val
,
priv
->
regs
+
offset
);
}
static
in
line
u16
dw_readw
(
struct
dw_spi_priv
*
priv
,
u32
offset
)
static
in
t
request_gpio_cs
(
struct
udevice
*
bus
)
{
return
__raw_readw
(
priv
->
regs
+
offset
);
}
#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD)
struct
dw_spi_priv
*
priv
=
dev_get_priv
(
bus
);
int
ret
;
static
inline
void
dw_writew
(
struct
dw_spi_priv
*
priv
,
u32
offset
,
u16
val
)
{
__raw_writew
(
val
,
priv
->
regs
+
offset
);
/* External chip select gpio line is optional */
ret
=
gpio_request_by_name
(
bus
,
"cs-gpio"
,
0
,
&
priv
->
cs_gpio
,
0
);
if
(
ret
==
-
ENOENT
)
return
0
;
if
(
ret
<
0
)
{
printf
(
"Error: %d: Can't get %s gpio!
\n
"
,
ret
,
bus
->
name
);
return
ret
;
}
if
(
dm_gpio_is_valid
(
&
priv
->
cs_gpio
))
{
dm_gpio_set_dir_flags
(
&
priv
->
cs_gpio
,
GPIOD_IS_OUT
|
GPIOD_IS_OUT_ACTIVE
);
}
debug
(
"%s: used external gpio for CS management
\n
"
,
__func__
);
#endif
return
0
;
}
static
int
dw_spi_ofdata_to_platdata
(
struct
udevice
*
bus
)
...
...
@@ -144,19 +164,19 @@ static int dw_spi_ofdata_to_platdata(struct udevice *bus)
debug
(
"%s: regs=%p max-frequency=%d
\n
"
,
__func__
,
plat
->
regs
,
plat
->
frequency
);
return
0
;
return
request_gpio_cs
(
bus
)
;
}
static
inline
void
spi_enable_chip
(
struct
dw_spi_priv
*
priv
,
int
enable
)
{
dw_write
l
(
priv
,
DW_SPI_SSIENR
,
(
enable
?
1
:
0
));
dw_write
(
priv
,
DW_SPI_SSIENR
,
(
enable
?
1
:
0
));
}
/* Restart the controller, disable all interrupts, clean rx fifo */
static
void
spi_hw_init
(
struct
dw_spi_priv
*
priv
)
{
spi_enable_chip
(
priv
,
0
);
dw_write
l
(
priv
,
DW_SPI_IMR
,
0xff
);
dw_write
(
priv
,
DW_SPI_IMR
,
0xff
);
spi_enable_chip
(
priv
,
1
);
/*
...
...
@@ -167,13 +187,13 @@ static void spi_hw_init(struct dw_spi_priv *priv)
u32
fifo
;
for
(
fifo
=
1
;
fifo
<
256
;
fifo
++
)
{
dw_write
w
(
priv
,
DW_SPI_TXFLTR
,
fifo
);
if
(
fifo
!=
dw_read
w
(
priv
,
DW_SPI_TXFLTR
))
dw_write
(
priv
,
DW_SPI_TXFLTR
,
fifo
);
if
(
fifo
!=
dw_read
(
priv
,
DW_SPI_TXFLTR
))
break
;
}
priv
->
fifo_len
=
(
fifo
==
1
)
?
0
:
fifo
;
dw_write
w
(
priv
,
DW_SPI_TXFLTR
,
0
);
dw_write
(
priv
,
DW_SPI_TXFLTR
,
0
);
}
debug
(
"%s: fifo_len=%d
\n
"
,
__func__
,
priv
->
fifo_len
);
}
...
...
@@ -242,7 +262,7 @@ static inline u32 tx_max(struct dw_spi_priv *priv)
u32
tx_left
,
tx_room
,
rxtx_gap
;
tx_left
=
(
priv
->
tx_end
-
priv
->
tx
)
/
(
priv
->
bits_per_word
>>
3
);
tx_room
=
priv
->
fifo_len
-
dw_read
w
(
priv
,
DW_SPI_TXFLR
);
tx_room
=
priv
->
fifo_len
-
dw_read
(
priv
,
DW_SPI_TXFLR
);
/*
* Another concern is about the tx/rx mismatch, we
...
...
@@ -263,7 +283,7 @@ static inline u32 rx_max(struct dw_spi_priv *priv)
{
u32
rx_left
=
(
priv
->
rx_end
-
priv
->
rx
)
/
(
priv
->
bits_per_word
>>
3
);
return
min_t
(
u32
,
rx_left
,
dw_read
w
(
priv
,
DW_SPI_RXFLR
));
return
min_t
(
u32
,
rx_left
,
dw_read
(
priv
,
DW_SPI_RXFLR
));
}
static
void
dw_writer
(
struct
dw_spi_priv
*
priv
)
...
...
@@ -279,34 +299,22 @@ static void dw_writer(struct dw_spi_priv *priv)
else
txw
=
*
(
u16
*
)(
priv
->
tx
);
}
dw_write
w
(
priv
,
DW_SPI_DR
,
txw
);
dw_write
(
priv
,
DW_SPI_DR
,
txw
);
debug
(
"%s: tx=0x%02x
\n
"
,
__func__
,
txw
);
priv
->
tx
+=
priv
->
bits_per_word
>>
3
;
}
}
static
int
dw_reader
(
struct
dw_spi_priv
*
priv
)
static
void
dw_reader
(
struct
dw_spi_priv
*
priv
)
{
unsigned
start
=
get_timer
(
0
);
u32
max
;
u32
max
=
rx_max
(
priv
);
u16
rxw
;
/* Wait for rx data to be ready */
while
(
rx_max
(
priv
)
==
0
)
{
if
(
get_timer
(
start
)
>
RX_TIMEOUT
)
return
-
ETIMEDOUT
;
}
max
=
rx_max
(
priv
);
while
(
max
--
)
{
rxw
=
dw_read
w
(
priv
,
DW_SPI_DR
);
rxw
=
dw_read
(
priv
,
DW_SPI_DR
);
debug
(
"%s: rx=0x%02x
\n
"
,
__func__
,
rxw
);
/*
* Care about rx only if the transfer's original "rx" is
* not null
*/
/* Care about rx if the transfer's original "rx" is not null */
if
(
priv
->
rx_end
-
priv
->
len
)
{
if
(
priv
->
bits_per_word
==
8
)
*
(
u8
*
)(
priv
->
rx
)
=
rxw
;
...
...
@@ -315,24 +323,30 @@ static int dw_reader(struct dw_spi_priv *priv)
}
priv
->
rx
+=
priv
->
bits_per_word
>>
3
;
}
return
0
;
}
static
int
poll_transfer
(
struct
dw_spi_priv
*
priv
)
{
int
ret
;
do
{
dw_writer
(
priv
);
ret
=
dw_reader
(
priv
);
if
(
ret
<
0
)
return
ret
;
dw_reader
(
priv
);
}
while
(
priv
->
rx_end
>
priv
->
rx
);
return
0
;
}
static
void
external_cs_manage
(
struct
udevice
*
dev
,
bool
on
)
{
#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD)
struct
dw_spi_priv
*
priv
=
dev_get_priv
(
dev
->
parent
);
if
(
!
dm_gpio_is_valid
(
&
priv
->
cs_gpio
))
return
;
dm_gpio_set_value
(
&
priv
->
cs_gpio
,
on
?
1
:
0
);
#endif
}
static
int
dw_spi_xfer
(
struct
udevice
*
dev
,
unsigned
int
bitlen
,
const
void
*
dout
,
void
*
din
,
unsigned
long
flags
)
{
...
...
@@ -342,6 +356,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
u8
*
rx
=
din
;
int
ret
=
0
;
u32
cr0
=
0
;
u32
val
;
u32
cs
;
/* spi core configured to do 8 bit transfers */
...
...
@@ -350,6 +365,10 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
return
-
1
;
}
/* Start the transaction if necessary. */
if
(
flags
&
SPI_XFER_BEGIN
)
external_cs_manage
(
dev
,
false
);
cr0
=
(
priv
->
bits_per_word
-
1
)
|
(
priv
->
type
<<
SPI_FRF_OFFSET
)
|
(
priv
->
mode
<<
SPI_MODE_OFFSET
)
|
(
priv
->
tmode
<<
SPI_TMOD_OFFSET
);
...
...
@@ -359,7 +378,11 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
else
if
(
rx
)
priv
->
tmode
=
SPI_TMOD_RO
;
else
priv
->
tmode
=
SPI_TMOD_TO
;
/*
* In transmit only mode (SPI_TMOD_TO) input FIFO never gets
* any data which breaks our logic in poll_transfer() above.
*/
priv
->
tmode
=
SPI_TMOD_TR
;
cr0
&=
~
SPI_TMOD_MASK
;
cr0
|=
(
priv
->
tmode
<<
SPI_TMOD_OFFSET
);
...
...
@@ -377,8 +400,8 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
debug
(
"%s: cr0=%08x
\n
"
,
__func__
,
cr0
);
/* Reprogram cr0 only if changed */
if
(
dw_read
w
(
priv
,
DW_SPI_CTRL0
)
!=
cr0
)
dw_write
w
(
priv
,
DW_SPI_CTRL0
,
cr0
);
if
(
dw_read
(
priv
,
DW_SPI_CTRL0
)
!=
cr0
)
dw_write
(
priv
,
DW_SPI_CTRL0
,
cr0
);
/*
* Configure the desired SS (slave select 0...3) in the controller
...
...
@@ -386,7 +409,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
* automatically. So no cs_activate() etc is needed in this driver.
*/
cs
=
spi_chip_select
(
dev
);
dw_write
l
(
priv
,
DW_SPI_SER
,
1
<<
cs
);
dw_write
(
priv
,
DW_SPI_SER
,
1
<<
cs
);
/* Enable controller after writing control registers */
spi_enable_chip
(
priv
,
1
);
...
...
@@ -394,6 +417,23 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
/* Start transfer in a polling loop */
ret
=
poll_transfer
(
priv
);
/*
* Wait for current transmit operation to complete.
* Otherwise if some data still exists in Tx FIFO it can be
* silently flushed, i.e. dropped on disabling of the controller,
* which happens when writing 0 to DW_SPI_SSIENR which happens
* in the beginning of new transfer.
*/
if
(
readl_poll_timeout
(
priv
->
regs
+
DW_SPI_SR
,
val
,
!
(
val
&
SR_TF_EMPT
)
||
(
val
&
SR_BUSY
),
RX_TIMEOUT
*
1000
))
{
ret
=
-
ETIMEDOUT
;
}
/* Stop the transaction if necessary */
if
(
flags
&
SPI_XFER_END
)
external_cs_manage
(
dev
,
true
);
return
ret
;
}
...
...
@@ -412,7 +452,7 @@ static int dw_spi_set_speed(struct udevice *bus, uint speed)
/* clk_div doesn't support odd number */
clk_div
=
priv
->
bus_clk_rate
/
speed
;
clk_div
=
(
clk_div
+
1
)
&
0xfffe
;
dw_write
l
(
priv
,
DW_SPI_BAUDR
,
clk_div
);
dw_write
(
priv
,
DW_SPI_BAUDR
,
clk_div
);
/* Enable controller after writing control registers */
spi_enable_chip
(
priv
,
1
);
...
...
drivers/spi/omap3_spi.c
浏览文件 @
2dc5165e
...
...
@@ -630,8 +630,10 @@ static int omap3_spi_probe(struct udevice *dev)
(
struct
omap2_mcspi_platform_config
*
)
dev_get_driver_data
(
dev
);
priv
->
regs
=
(
struct
mcspi
*
)(
devfdt_get_addr
(
dev
)
+
data
->
regs_offset
);
priv
->
pin_dir
=
fdtdec_get_uint
(
blob
,
node
,
"ti,pindir-d0-out-d1-in"
,
MCSPI_PINDIR_D0_IN_D1_OUT
);
if
(
fdtdec_get_bool
(
blob
,
node
,
"ti,pindir-d0-out-d1-in"
))
priv
->
pin_dir
=
MCSPI_PINDIR_D0_OUT_D1_IN
;
else
priv
->
pin_dir
=
MCSPI_PINDIR_D0_IN_D1_OUT
;
priv
->
wordlen
=
SPI_DEFAULT_WORDLEN
;
return
0
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录