Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OS
U-Boot.Mirror
提交
1a7cdb88
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,发现更多精彩内容 >>
提交
1a7cdb88
编写于
4月 11, 2018
作者:
T
Tom Rini
浏览文件
操作
浏览文件
下载
差异文件
Merge
git://git.denx.de/u-boot-i2c
上级
d79dfd45
e5c762f5
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
154 addition
and
35 deletion
+154
-35
doc/device-tree-bindings/i2c/i2c.txt
doc/device-tree-bindings/i2c/i2c.txt
+13
-0
drivers/i2c/fsl_i2c.c
drivers/i2c/fsl_i2c.c
+8
-5
drivers/i2c/i2c-uclass.c
drivers/i2c/i2c-uclass.c
+109
-9
drivers/i2c/ihs_i2c.c
drivers/i2c/ihs_i2c.c
+24
-21
未找到文件。
doc/device-tree-bindings/i2c/i2c.txt
浏览文件 @
1a7cdb88
...
...
@@ -12,6 +12,11 @@ property which allows the chip offset length to be selected.
Optional properties:
- u-boot,i2c-offset-len - length of chip offset in bytes. If omitted the
default value of 1 is used.
- gpios = <sda ...>, <scl ...>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c_xfer>;
pinctrl-1 = <&i2c_gpio>;
Pin description for I2C bus software deblocking.
Example
...
...
@@ -26,3 +31,11 @@ i2c4: i2c@12ca0000 {
ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
};
};
&i2c1 {
pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c1_xfer>;
pinctrl-1 = <&i2c1_gpio>;
gpios = <&gpio1 26 GPIO_ACTIVE_LOW>, /* SDA */
<&gpio1 27 GPIO_ACTIVE_LOW>; /* SCL */
};
drivers/i2c/fsl_i2c.c
浏览文件 @
1a7cdb88
...
...
@@ -12,6 +12,7 @@
#include <i2c.h>
/* Functional interface */
#include <asm/io.h>
#include <asm/fsl_i2c.h>
/* HW definitions */
#include <clk.h>
#include <dm.h>
#include <mapmem.h>
...
...
@@ -573,11 +574,9 @@ static int fsl_i2c_set_bus_speed(struct udevice *bus, uint speed)
static
int
fsl_i2c_ofdata_to_platdata
(
struct
udevice
*
bus
)
{
struct
fsl_i2c_dev
*
dev
=
dev_get_priv
(
bus
);
fdt_addr_t
addr
;
struct
clk
clock
;
addr
=
dev_read_u32_default
(
bus
,
"reg"
,
-
1
);
dev
->
base
=
map_sysmem
(
CONFIG_SYS_IMMR
+
addr
,
sizeof
(
struct
fsl_i2c_base
));
dev
->
base
=
map_sysmem
(
dev_read_addr
(
bus
),
sizeof
(
struct
fsl_i2c_base
));
if
(
!
dev
->
base
)
return
-
ENOMEM
;
...
...
@@ -587,7 +586,11 @@ static int fsl_i2c_ofdata_to_platdata(struct udevice *bus)
0x7f
);
dev
->
speed
=
dev_read_u32_default
(
bus
,
"clock-frequency"
,
400000
);
dev
->
i2c_clk
=
dev
->
index
?
gd
->
arch
.
i2c2_clk
:
gd
->
arch
.
i2c1_clk
;
if
(
!
clk_get_by_index
(
bus
,
0
,
&
clock
))
dev
->
i2c_clk
=
clk_get_rate
(
&
clock
);
else
dev
->
i2c_clk
=
dev
->
index
?
gd
->
arch
.
i2c2_clk
:
gd
->
arch
.
i2c1_clk
;
return
0
;
}
...
...
drivers/i2c/i2c-uclass.c
浏览文件 @
1a7cdb88
...
...
@@ -11,9 +11,19 @@
#include <malloc.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/pinctrl.h>
#ifdef CONFIG_DM_GPIO
#include <asm/gpio.h>
#endif
#define I2C_MAX_OFFSET_LEN 4
enum
{
PIN_SDA
=
0
,
PIN_SCL
,
PIN_COUNT
,
};
/* Useful debugging function */
void
i2c_dump_msgs
(
struct
i2c_msg
*
msg
,
int
nmsgs
)
{
...
...
@@ -445,20 +455,110 @@ int i2c_get_chip_offset_len(struct udevice *dev)
return
chip
->
offset_len
;
}
#ifdef CONFIG_DM_GPIO
static
void
i2c_gpio_set_pin
(
struct
gpio_desc
*
pin
,
int
bit
)
{
if
(
bit
)
dm_gpio_set_dir_flags
(
pin
,
GPIOD_IS_IN
);
else
dm_gpio_set_dir_flags
(
pin
,
GPIOD_IS_OUT
|
GPIOD_ACTIVE_LOW
|
GPIOD_IS_OUT_ACTIVE
);
}
static
int
i2c_gpio_get_pin
(
struct
gpio_desc
*
pin
)
{
return
dm_gpio_get_value
(
pin
);
}
static
int
i2c_deblock_gpio_loop
(
struct
gpio_desc
*
sda_pin
,
struct
gpio_desc
*
scl_pin
)
{
int
counter
=
9
;
int
ret
=
0
;
i2c_gpio_set_pin
(
sda_pin
,
1
);
i2c_gpio_set_pin
(
scl_pin
,
1
);
udelay
(
5
);
/* Toggle SCL until slave release SDA */
while
(
counter
--
>=
0
)
{
i2c_gpio_set_pin
(
scl_pin
,
1
);
udelay
(
5
);
i2c_gpio_set_pin
(
scl_pin
,
0
);
udelay
(
5
);
if
(
i2c_gpio_get_pin
(
sda_pin
))
break
;
}
/* Then, send I2C stop */
i2c_gpio_set_pin
(
sda_pin
,
0
);
udelay
(
5
);
i2c_gpio_set_pin
(
scl_pin
,
1
);
udelay
(
5
);
i2c_gpio_set_pin
(
sda_pin
,
1
);
udelay
(
5
);
if
(
!
i2c_gpio_get_pin
(
sda_pin
)
||
!
i2c_gpio_get_pin
(
scl_pin
))
ret
=
-
EREMOTEIO
;
return
ret
;
}
static
int
i2c_deblock_gpio
(
struct
udevice
*
bus
)
{
struct
gpio_desc
gpios
[
PIN_COUNT
];
int
ret
,
ret0
;
ret
=
gpio_request_list_by_name
(
bus
,
"gpios"
,
gpios
,
ARRAY_SIZE
(
gpios
),
GPIOD_IS_IN
);
if
(
ret
!=
ARRAY_SIZE
(
gpios
))
{
debug
(
"%s: I2C Node '%s' has no 'gpios' property %s
\n
"
,
__func__
,
dev_read_name
(
bus
),
bus
->
name
);
if
(
ret
>=
0
)
{
gpio_free_list
(
bus
,
gpios
,
ret
);
ret
=
-
ENOENT
;
}
goto
out
;
}
ret
=
pinctrl_select_state
(
bus
,
"gpio"
);
if
(
ret
)
{
debug
(
"%s: I2C Node '%s' has no 'gpio' pinctrl state. %s
\n
"
,
__func__
,
dev_read_name
(
bus
),
bus
->
name
);
goto
out_no_pinctrl
;
}
ret0
=
i2c_deblock_gpio_loop
(
&
gpios
[
PIN_SDA
],
&
gpios
[
PIN_SCL
]);
ret
=
pinctrl_select_state
(
bus
,
"default"
);
if
(
ret
)
{
debug
(
"%s: I2C Node '%s' has no 'default' pinctrl state. %s
\n
"
,
__func__
,
dev_read_name
(
bus
),
bus
->
name
);
}
ret
=
!
ret
?
ret0
:
ret
;
out_no_pinctrl:
gpio_free_list
(
bus
,
gpios
,
ARRAY_SIZE
(
gpios
));
out:
return
ret
;
}
#else
static
int
i2c_deblock_gpio
(
struct
udevice
*
bus
)
{
return
-
ENOSYS
;
}
#endif // CONFIG_DM_GPIO
int
i2c_deblock
(
struct
udevice
*
bus
)
{
struct
dm_i2c_ops
*
ops
=
i2c_get_ops
(
bus
);
/*
* We could implement a software deblocking here if we could get
* access to the GPIOs used by I2C, and switch them to GPIO mode
* and then back to I2C. This is somewhat beyond our powers in
* driver model at present, so for now just fail.
*
* See https://patchwork.ozlabs.org/patch/399040/
*/
if
(
!
ops
->
deblock
)
return
-
ENOSYS
;
return
i2c_deblock_gpio
(
bus
)
;
return
ops
->
deblock
(
bus
);
}
...
...
drivers/i2c/ihs_i2c.c
浏览文件 @
1a7cdb88
...
...
@@ -99,7 +99,8 @@ static int wait_for_int(bool read)
#endif
#ifdef CONFIG_DM_I2C
fpgamap_read16
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
&
val
);
fpgamap_read
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
&
val
,
FPGAMAP_SIZE_16
);
#else
I2C_GET_REG
(
interrupt_status
,
&
val
);
#endif
...
...
@@ -110,7 +111,8 @@ static int wait_for_int(bool read)
if
(
ctr
++
>
5000
)
return
1
;
#ifdef CONFIG_DM_I2C
fpgamap_read16
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
&
val
);
fpgamap_read
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
&
val
,
FPGAMAP_SIZE_16
);
#else
I2C_GET_REG
(
interrupt_status
,
&
val
);
#endif
...
...
@@ -128,6 +130,7 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read,
#endif
{
u16
val
;
u16
data
;
#ifdef CONFIG_DM_I2C
struct
ihs_i2c_priv
*
priv
=
dev_get_priv
(
dev
);
struct
udevice
*
fpga
;
...
...
@@ -136,13 +139,14 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read,
#endif
/* Clear interrupt status */
data
=
I2CINT_ERROR_EV
|
I2CINT_RECEIVE_EV
|
I2CINT_TRANSMIT_EV
;
#ifdef CONFIG_DM_I2C
fpgamap_write16
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
I2CINT_ERROR_EV
|
I2CINT_RECEIVE_EV
|
I2CINT_TRANSMIT_EV
);
fpgamap_read16
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
&
val
);
fpgamap_write
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
&
data
,
FPGAMAP_SIZE_16
);
fpgamap_read
(
fpga
,
priv
->
addr
+
REG_INTERRUPT_STATUS
,
&
val
,
FPGAMAP_SIZE_16
);
#else
I2C_SET_REG
(
interrupt_status
,
I2CINT_ERROR_EV
|
I2CINT_RECEIVE_EV
|
I2CINT_TRANSMIT_EV
);
I2C_SET_REG
(
interrupt_status
,
data
);
I2C_GET_REG
(
interrupt_status
,
&
val
);
#endif
...
...
@@ -153,26 +157,24 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read,
if
(
len
>
1
)
val
|=
buffer
[
1
]
<<
8
;
#ifdef CONFIG_DM_I2C
fpgamap_write16
(
fpga
,
priv
->
addr
+
REG_WRITE_MAILBOX_EXT
,
val
);
fpgamap_write
(
fpga
,
priv
->
addr
+
REG_WRITE_MAILBOX_EXT
,
&
val
,
FPGAMAP_SIZE_16
);
#else
I2C_SET_REG
(
write_mailbox_ext
,
val
);
#endif
}
data
=
I2CMB_NATIVE
|
(
read
?
0
:
I2CMB_WRITE
)
|
(
chip
<<
1
)
|
((
len
>
1
)
?
I2CMB_2BYTE
:
0
)
|
(
is_last
?
0
:
I2CMB_HOLD_BUS
);
#ifdef CONFIG_DM_I2C
fpgamap_write16
(
fpga
,
priv
->
addr
+
REG_WRITE_MAILBOX
,
I2CMB_NATIVE
|
(
read
?
I2CMB_READ
:
I2CMB_WRITE
)
|
(
chip
<<
1
)
|
((
len
>
1
)
?
I2CMB_2BYTE
:
I2CMB_1BYTE
)
|
(
!
is_last
?
I2CMB_HOLD_BUS
:
I2CMB_DONT_HOLD_BUS
));
fpgamap_write
(
fpga
,
priv
->
addr
+
REG_WRITE_MAILBOX
,
&
data
,
FPGAMAP_SIZE_16
);
#else
I2C_SET_REG
(
write_mailbox
,
I2CMB_NATIVE
|
(
read
?
0
:
I2CMB_WRITE
)
|
(
chip
<<
1
)
|
((
len
>
1
)
?
I2CMB_2BYTE
:
0
)
|
(
is_last
?
0
:
I2CMB_HOLD_BUS
));
I2C_SET_REG
(
write_mailbox
,
data
);
#endif
#ifdef CONFIG_DM_I2C
...
...
@@ -185,7 +187,8 @@ static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read,
/* If we want to read, get the bytes from the mailbox */
if
(
read
)
{
#ifdef CONFIG_DM_I2C
fpgamap_read16
(
fpga
,
priv
->
addr
+
REG_READ_MAILBOX_EXT
,
&
val
);
fpgamap_read
(
fpga
,
priv
->
addr
+
REG_READ_MAILBOX_EXT
,
&
val
,
FPGAMAP_SIZE_16
);
#else
I2C_GET_REG
(
read_mailbox_ext
,
&
val
);
#endif
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录