Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
2cc6e2e0
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看板
提交
2cc6e2e0
编写于
10月 11, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'spi/topic/s3c64xx' into spi-loop
上级
b158935f
ebd805cc
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
98 addition
and
50 deletion
+98
-50
Documentation/driver-model/devres.txt
Documentation/driver-model/devres.txt
+3
-0
drivers/spi/Kconfig
drivers/spi/Kconfig
+1
-1
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-s3c64xx.c
+57
-49
drivers/spi/spi.c
drivers/spi/spi.c
+35
-0
include/linux/spi/spi.h
include/linux/spi/spi.h
+2
-0
未找到文件。
Documentation/driver-model/devres.txt
浏览文件 @
2cc6e2e0
...
@@ -302,3 +302,6 @@ PHY
...
@@ -302,3 +302,6 @@ PHY
SLAVE DMA ENGINE
SLAVE DMA ENGINE
devm_acpi_dma_controller_register()
devm_acpi_dma_controller_register()
SPI
devm_spi_register_master()
drivers/spi/Kconfig
浏览文件 @
2cc6e2e0
...
@@ -393,7 +393,7 @@ config SPI_S3C24XX_FIQ
...
@@ -393,7 +393,7 @@ config SPI_S3C24XX_FIQ
config SPI_S3C64XX
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
tristate "Samsung S3C64XX series type SPI"
depends on
(ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)
depends on
PLAT_SAMSUNG
select S3C64XX_DMA if ARCH_S3C64XX
select S3C64XX_DMA if ARCH_S3C64XX
help
help
SPI driver for Samsung S3C64XX and newer SoCs.
SPI driver for Samsung S3C64XX and newer SoCs.
...
...
drivers/spi/spi-s3c64xx.c
浏览文件 @
2cc6e2e0
...
@@ -205,7 +205,6 @@ struct s3c64xx_spi_driver_data {
...
@@ -205,7 +205,6 @@ struct s3c64xx_spi_driver_data {
#endif
#endif
struct
s3c64xx_spi_port_config
*
port_conf
;
struct
s3c64xx_spi_port_config
*
port_conf
;
unsigned
int
port_id
;
unsigned
int
port_id
;
unsigned
long
gpios
[
4
];
bool
cs_gpio
;
bool
cs_gpio
;
};
};
...
@@ -559,25 +558,18 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
...
@@ -559,25 +558,18 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
static
inline
void
enable_cs
(
struct
s3c64xx_spi_driver_data
*
sdd
,
static
inline
void
enable_cs
(
struct
s3c64xx_spi_driver_data
*
sdd
,
struct
spi_device
*
spi
)
struct
spi_device
*
spi
)
{
{
struct
s3c64xx_spi_csinfo
*
cs
;
if
(
sdd
->
tgl_spi
!=
NULL
)
{
/* If last device toggled after mssg */
if
(
sdd
->
tgl_spi
!=
NULL
)
{
/* If last device toggled after mssg */
if
(
sdd
->
tgl_spi
!=
spi
)
{
/* if last mssg on diff device */
if
(
sdd
->
tgl_spi
!=
spi
)
{
/* if last mssg on diff device */
/* Deselect the last toggled device */
/* Deselect the last toggled device */
cs
=
sdd
->
tgl_spi
->
controller_data
;
if
(
spi
->
cs_gpio
>=
0
)
if
(
sdd
->
cs_gpio
)
gpio_set_value
(
spi
->
cs_gpio
,
gpio_set_value
(
cs
->
line
,
spi
->
mode
&
SPI_CS_HIGH
?
0
:
1
);
spi
->
mode
&
SPI_CS_HIGH
?
0
:
1
);
}
}
sdd
->
tgl_spi
=
NULL
;
sdd
->
tgl_spi
=
NULL
;
}
}
cs
=
spi
->
controller_data
;
if
(
spi
->
cs_gpio
>=
0
)
if
(
sdd
->
cs_gpio
)
gpio_set_value
(
spi
->
cs_gpio
,
spi
->
mode
&
SPI_CS_HIGH
?
1
:
0
);
gpio_set_value
(
cs
->
line
,
spi
->
mode
&
SPI_CS_HIGH
?
1
:
0
);
/* Start the signals */
writel
(
0
,
sdd
->
regs
+
S3C64XX_SPI_SLAVE_SEL
);
}
}
static
u32
s3c64xx_spi_wait_for_timeout
(
struct
s3c64xx_spi_driver_data
*
sdd
,
static
u32
s3c64xx_spi_wait_for_timeout
(
struct
s3c64xx_spi_driver_data
*
sdd
,
...
@@ -702,16 +694,11 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
...
@@ -702,16 +694,11 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
static
inline
void
disable_cs
(
struct
s3c64xx_spi_driver_data
*
sdd
,
static
inline
void
disable_cs
(
struct
s3c64xx_spi_driver_data
*
sdd
,
struct
spi_device
*
spi
)
struct
spi_device
*
spi
)
{
{
struct
s3c64xx_spi_csinfo
*
cs
=
spi
->
controller_data
;
if
(
sdd
->
tgl_spi
==
spi
)
if
(
sdd
->
tgl_spi
==
spi
)
sdd
->
tgl_spi
=
NULL
;
sdd
->
tgl_spi
=
NULL
;
if
(
sdd
->
cs_gpio
)
if
(
spi
->
cs_gpio
>=
0
)
gpio_set_value
(
cs
->
line
,
spi
->
mode
&
SPI_CS_HIGH
?
0
:
1
);
gpio_set_value
(
spi
->
cs_gpio
,
spi
->
mode
&
SPI_CS_HIGH
?
0
:
1
);
/* Quiese the signals */
writel
(
S3C64XX_SPI_SLAVE_SIG_INACT
,
sdd
->
regs
+
S3C64XX_SPI_SLAVE_SEL
);
}
}
static
void
s3c64xx_spi_config
(
struct
s3c64xx_spi_driver_data
*
sdd
)
static
void
s3c64xx_spi_config
(
struct
s3c64xx_spi_driver_data
*
sdd
)
...
@@ -927,6 +914,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
...
@@ -927,6 +914,9 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
s3c64xx_spi_config
(
sdd
);
s3c64xx_spi_config
(
sdd
);
}
}
/* Slave Select */
enable_cs
(
sdd
,
spi
);
/* Polling method for xfers not bigger than FIFO capacity */
/* Polling method for xfers not bigger than FIFO capacity */
use_dma
=
0
;
use_dma
=
0
;
if
(
!
is_polling
(
sdd
)
&&
if
(
!
is_polling
(
sdd
)
&&
...
@@ -942,8 +932,11 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
...
@@ -942,8 +932,11 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
enable_datapath
(
sdd
,
spi
,
xfer
,
use_dma
);
enable_datapath
(
sdd
,
spi
,
xfer
,
use_dma
);
/* Slave Select */
/* Start the signals */
enable_cs
(
sdd
,
spi
);
writel
(
0
,
sdd
->
regs
+
S3C64XX_SPI_SLAVE_SEL
);
/* Start the signals */
writel
(
0
,
sdd
->
regs
+
S3C64XX_SPI_SLAVE_SEL
);
spin_unlock_irqrestore
(
&
sdd
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
sdd
->
lock
,
flags
);
...
@@ -968,6 +961,8 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
...
@@ -968,6 +961,8 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
goto
out
;
goto
out
;
}
}
flush_fifo
(
sdd
);
if
(
xfer
->
delay_usecs
)
if
(
xfer
->
delay_usecs
)
udelay
(
xfer
->
delay_usecs
);
udelay
(
xfer
->
delay_usecs
);
...
@@ -980,15 +975,17 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
...
@@ -980,15 +975,17 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
}
}
msg
->
actual_length
+=
xfer
->
len
;
msg
->
actual_length
+=
xfer
->
len
;
flush_fifo
(
sdd
);
}
}
out:
out:
if
(
!
cs_toggle
||
status
)
if
(
!
cs_toggle
||
status
)
{
/* Quiese the signals */
writel
(
S3C64XX_SPI_SLAVE_SIG_INACT
,
sdd
->
regs
+
S3C64XX_SPI_SLAVE_SEL
);
disable_cs
(
sdd
,
spi
);
disable_cs
(
sdd
,
spi
);
else
}
else
{
sdd
->
tgl_spi
=
spi
;
sdd
->
tgl_spi
=
spi
;
}
s3c64xx_spi_unmap_mssg
(
sdd
,
msg
);
s3c64xx_spi_unmap_mssg
(
sdd
,
msg
);
...
@@ -1089,6 +1086,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
...
@@ -1089,6 +1086,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
cs
->
line
,
err
);
cs
->
line
,
err
);
goto
err_gpio_req
;
goto
err_gpio_req
;
}
}
spi
->
cs_gpio
=
cs
->
line
;
}
}
spi_set_ctldata
(
spi
,
cs
);
spi_set_ctldata
(
spi
,
cs
);
...
@@ -1135,11 +1134,13 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
...
@@ -1135,11 +1134,13 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
}
}
pm_runtime_put
(
&
sdd
->
pdev
->
dev
);
pm_runtime_put
(
&
sdd
->
pdev
->
dev
);
writel
(
S3C64XX_SPI_SLAVE_SIG_INACT
,
sdd
->
regs
+
S3C64XX_SPI_SLAVE_SEL
);
disable_cs
(
sdd
,
spi
);
disable_cs
(
sdd
,
spi
);
return
0
;
return
0
;
setup_exit:
setup_exit:
/* setup() returns with device de-selected */
/* setup() returns with device de-selected */
writel
(
S3C64XX_SPI_SLAVE_SIG_INACT
,
sdd
->
regs
+
S3C64XX_SPI_SLAVE_SEL
);
disable_cs
(
sdd
,
spi
);
disable_cs
(
sdd
,
spi
);
gpio_free
(
cs
->
line
);
gpio_free
(
cs
->
line
);
...
@@ -1158,8 +1159,8 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi)
...
@@ -1158,8 +1159,8 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi)
struct
s3c64xx_spi_driver_data
*
sdd
;
struct
s3c64xx_spi_driver_data
*
sdd
;
sdd
=
spi_master_get_devdata
(
spi
->
master
);
sdd
=
spi_master_get_devdata
(
spi
->
master
);
if
(
cs
&&
sdd
->
cs_gpio
)
{
if
(
spi
->
cs_gpio
)
{
gpio_free
(
cs
->
line
);
gpio_free
(
spi
->
cs_gpio
);
if
(
spi
->
dev
.
of_node
)
if
(
spi
->
dev
.
of_node
)
kfree
(
cs
);
kfree
(
cs
);
}
}
...
@@ -1448,9 +1449,11 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
...
@@ -1448,9 +1449,11 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
S3C64XX_SPI_INT_TX_OVERRUN_EN
|
S3C64XX_SPI_INT_TX_UNDERRUN_EN
,
S3C64XX_SPI_INT_TX_OVERRUN_EN
|
S3C64XX_SPI_INT_TX_UNDERRUN_EN
,
sdd
->
regs
+
S3C64XX_SPI_INT_EN
);
sdd
->
regs
+
S3C64XX_SPI_INT_EN
);
if
(
spi_register_master
(
master
))
{
pm_runtime_enable
(
&
pdev
->
dev
);
dev_err
(
&
pdev
->
dev
,
"cannot register SPI master
\n
"
);
ret
=
-
EBUSY
;
ret
=
devm_spi_register_master
(
&
pdev
->
dev
,
master
);
if
(
ret
!=
0
)
{
dev_err
(
&
pdev
->
dev
,
"cannot register SPI master: %d
\n
"
,
ret
);
goto
err3
;
goto
err3
;
}
}
...
@@ -1460,8 +1463,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
...
@@ -1460,8 +1463,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
mem_res
,
mem_res
,
sdd
->
rx_dma
.
dmach
,
sdd
->
tx_dma
.
dmach
);
sdd
->
rx_dma
.
dmach
,
sdd
->
tx_dma
.
dmach
);
pm_runtime_enable
(
&
pdev
->
dev
);
return
0
;
return
0
;
err3:
err3:
...
@@ -1481,16 +1482,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
...
@@ -1481,16 +1482,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
pm_runtime_disable
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
spi_unregister_master
(
master
);
writel
(
0
,
sdd
->
regs
+
S3C64XX_SPI_INT_EN
);
writel
(
0
,
sdd
->
regs
+
S3C64XX_SPI_INT_EN
);
clk_disable_unprepare
(
sdd
->
src_clk
);
clk_disable_unprepare
(
sdd
->
src_clk
);
clk_disable_unprepare
(
sdd
->
clk
);
clk_disable_unprepare
(
sdd
->
clk
);
spi_master_put
(
master
);
return
0
;
return
0
;
}
}
...
@@ -1548,9 +1545,17 @@ static int s3c64xx_spi_runtime_resume(struct device *dev)
...
@@ -1548,9 +1545,17 @@ static int s3c64xx_spi_runtime_resume(struct device *dev)
{
{
struct
spi_master
*
master
=
dev_get_drvdata
(
dev
);
struct
spi_master
*
master
=
dev_get_drvdata
(
dev
);
struct
s3c64xx_spi_driver_data
*
sdd
=
spi_master_get_devdata
(
master
);
struct
s3c64xx_spi_driver_data
*
sdd
=
spi_master_get_devdata
(
master
);
int
ret
;
clk_prepare_enable
(
sdd
->
src_clk
);
ret
=
clk_prepare_enable
(
sdd
->
src_clk
);
clk_prepare_enable
(
sdd
->
clk
);
if
(
ret
!=
0
)
return
ret
;
ret
=
clk_prepare_enable
(
sdd
->
clk
);
if
(
ret
!=
0
)
{
clk_disable_unprepare
(
sdd
->
src_clk
);
return
ret
;
}
return
0
;
return
0
;
}
}
...
@@ -1636,6 +1641,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = {
...
@@ -1636,6 +1641,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = {
};
};
static
const
struct
of_device_id
s3c64xx_spi_dt_match
[]
=
{
static
const
struct
of_device_id
s3c64xx_spi_dt_match
[]
=
{
{
.
compatible
=
"samsung,s3c2443-spi"
,
.
data
=
(
void
*
)
&
s3c2443_spi_port_config
,
},
{
.
compatible
=
"samsung,s3c6410-spi"
,
.
data
=
(
void
*
)
&
s3c6410_spi_port_config
,
},
{
.
compatible
=
"samsung,s5pc100-spi"
,
.
data
=
(
void
*
)
&
s5pc100_spi_port_config
,
},
{
.
compatible
=
"samsung,s5pv210-spi"
,
.
data
=
(
void
*
)
&
s5pv210_spi_port_config
,
},
{
.
compatible
=
"samsung,exynos4210-spi"
,
{
.
compatible
=
"samsung,exynos4210-spi"
,
.
data
=
(
void
*
)
&
exynos4_spi_port_config
,
.
data
=
(
void
*
)
&
exynos4_spi_port_config
,
},
},
...
@@ -1653,22 +1670,13 @@ static struct platform_driver s3c64xx_spi_driver = {
...
@@ -1653,22 +1670,13 @@ static struct platform_driver s3c64xx_spi_driver = {
.
pm
=
&
s3c64xx_spi_pm
,
.
pm
=
&
s3c64xx_spi_pm
,
.
of_match_table
=
of_match_ptr
(
s3c64xx_spi_dt_match
),
.
of_match_table
=
of_match_ptr
(
s3c64xx_spi_dt_match
),
},
},
.
probe
=
s3c64xx_spi_probe
,
.
remove
=
s3c64xx_spi_remove
,
.
remove
=
s3c64xx_spi_remove
,
.
id_table
=
s3c64xx_spi_driver_ids
,
.
id_table
=
s3c64xx_spi_driver_ids
,
};
};
MODULE_ALIAS
(
"platform:s3c64xx-spi"
);
MODULE_ALIAS
(
"platform:s3c64xx-spi"
);
static
int
__init
s3c64xx_spi_init
(
void
)
module_platform_driver
(
s3c64xx_spi_driver
);
{
return
platform_driver_probe
(
&
s3c64xx_spi_driver
,
s3c64xx_spi_probe
);
}
subsys_initcall
(
s3c64xx_spi_init
);
static
void
__exit
s3c64xx_spi_exit
(
void
)
{
platform_driver_unregister
(
&
s3c64xx_spi_driver
);
}
module_exit
(
s3c64xx_spi_exit
);
MODULE_AUTHOR
(
"Jaswinder Singh <jassi.brar@samsung.com>"
);
MODULE_AUTHOR
(
"Jaswinder Singh <jassi.brar@samsung.com>"
);
MODULE_DESCRIPTION
(
"S3C64XX SPI Controller Driver"
);
MODULE_DESCRIPTION
(
"S3C64XX SPI Controller Driver"
);
...
...
drivers/spi/spi.c
浏览文件 @
2cc6e2e0
...
@@ -1370,6 +1370,41 @@ int spi_register_master(struct spi_master *master)
...
@@ -1370,6 +1370,41 @@ int spi_register_master(struct spi_master *master)
}
}
EXPORT_SYMBOL_GPL
(
spi_register_master
);
EXPORT_SYMBOL_GPL
(
spi_register_master
);
static
void
devm_spi_unregister
(
struct
device
*
dev
,
void
*
res
)
{
spi_unregister_master
(
*
(
struct
spi_master
**
)
res
);
}
/**
* dev_spi_register_master - register managed SPI master controller
* @dev: device managing SPI master
* @master: initialized master, originally from spi_alloc_master()
* Context: can sleep
*
* Register a SPI device as with spi_register_master() which will
* automatically be unregister
*/
int
devm_spi_register_master
(
struct
device
*
dev
,
struct
spi_master
*
master
)
{
struct
spi_master
**
ptr
;
int
ret
;
ptr
=
devres_alloc
(
devm_spi_unregister
,
sizeof
(
*
ptr
),
GFP_KERNEL
);
if
(
!
ptr
)
return
-
ENOMEM
;
ret
=
spi_register_master
(
master
);
if
(
ret
!=
0
)
{
*
ptr
=
master
;
devres_add
(
dev
,
ptr
);
}
else
{
devres_free
(
ptr
);
}
return
ret
;
}
EXPORT_SYMBOL_GPL
(
devm_spi_register_master
);
static
int
__unregister
(
struct
device
*
dev
,
void
*
null
)
static
int
__unregister
(
struct
device
*
dev
,
void
*
null
)
{
{
spi_unregister_device
(
to_spi_device
(
dev
));
spi_unregister_device
(
to_spi_device
(
dev
));
...
...
include/linux/spi/spi.h
浏览文件 @
2cc6e2e0
...
@@ -462,6 +462,8 @@ extern struct spi_master *
...
@@ -462,6 +462,8 @@ extern struct spi_master *
spi_alloc_master
(
struct
device
*
host
,
unsigned
size
);
spi_alloc_master
(
struct
device
*
host
,
unsigned
size
);
extern
int
spi_register_master
(
struct
spi_master
*
master
);
extern
int
spi_register_master
(
struct
spi_master
*
master
);
extern
int
devm_spi_register_master
(
struct
device
*
dev
,
struct
spi_master
*
master
);
extern
void
spi_unregister_master
(
struct
spi_master
*
master
);
extern
void
spi_unregister_master
(
struct
spi_master
*
master
);
extern
struct
spi_master
*
spi_busnum_to_master
(
u16
busnum
);
extern
struct
spi_master
*
spi_busnum_to_master
(
u16
busnum
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录