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
9ed1d862
Commit
9ed1d862
authored
Mar 14, 2015
by
Wolfram Sang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'i2c/quirks' into i2c/for-4.1
Signed-off-by:
Wolfram Sang
<
wsa@the-dreams.de
>
parents
58b59e0f
bf070380
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
192 additions
and
110 deletions
+192
-110
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-at91.c
+11
-21
drivers/i2c/busses/i2c-axxia.c
drivers/i2c/busses/i2c-axxia.c
+6
-5
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-bcm-iproc.c
+7
-8
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-cpm.c
+9
-11
drivers/i2c/busses/i2c-dln2.c
drivers/i2c/busses/i2c-dln2.c
+6
-6
drivers/i2c/busses/i2c-opal.c
drivers/i2c/busses/i2c-opal.c
+12
-12
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-pmcmsp.c
+16
-26
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-powermac.c
+4
-6
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-qup.c
+10
-11
drivers/i2c/busses/i2c-viperboard.c
drivers/i2c/busses/i2c-viperboard.c
+6
-4
drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.c
+62
-0
include/linux/i2c.h
include/linux/i2c.h
+43
-0
No files found.
drivers/i2c/busses/i2c-at91.c
View file @
9ed1d862
...
...
@@ -487,30 +487,10 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
if
(
ret
<
0
)
goto
out
;
/*
* The hardware can handle at most two messages concatenated by a
* repeated start via it's internal address feature.
*/
if
(
num
>
2
)
{
dev_err
(
dev
->
dev
,
"cannot handle more than two concatenated messages.
\n
"
);
ret
=
0
;
goto
out
;
}
else
if
(
num
==
2
)
{
if
(
num
==
2
)
{
int
internal_address
=
0
;
int
i
;
if
(
msg
->
flags
&
I2C_M_RD
)
{
dev_err
(
dev
->
dev
,
"first transfer must be write.
\n
"
);
ret
=
-
EINVAL
;
goto
out
;
}
if
(
msg
->
len
>
3
)
{
dev_err
(
dev
->
dev
,
"first message size must be <= 3.
\n
"
);
ret
=
-
EINVAL
;
goto
out
;
}
/* 1st msg is put into the internal address, start with 2nd */
m_start
=
&
msg
[
1
];
for
(
i
=
0
;
i
<
msg
->
len
;
++
i
)
{
...
...
@@ -540,6 +520,15 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
return
ret
;
}
/*
* The hardware can handle at most two messages concatenated by a
* repeated start via it's internal address feature.
*/
static
struct
i2c_adapter_quirks
at91_twi_quirks
=
{
.
flags
=
I2C_AQ_COMB
|
I2C_AQ_COMB_WRITE_FIRST
|
I2C_AQ_COMB_SAME_ADDR
,
.
max_comb_1st_msg_len
=
3
,
};
static
u32
at91_twi_func
(
struct
i2c_adapter
*
adapter
)
{
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
...
...
@@ -777,6 +766,7 @@ static int at91_twi_probe(struct platform_device *pdev)
dev
->
adapter
.
owner
=
THIS_MODULE
;
dev
->
adapter
.
class
=
I2C_CLASS_DEPRECATED
;
dev
->
adapter
.
algo
=
&
at91_twi_algorithm
;
dev
->
adapter
.
quirks
=
&
at91_twi_quirks
;
dev
->
adapter
.
dev
.
parent
=
dev
->
dev
;
dev
->
adapter
.
nr
=
pdev
->
id
;
dev
->
adapter
.
timeout
=
AT91_I2C_TIMEOUT
;
...
...
drivers/i2c/busses/i2c-axxia.c
View file @
9ed1d862
...
...
@@ -336,11 +336,6 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
u32
addr_1
,
addr_2
;
int
ret
;
if
(
msg
->
len
>
255
)
{
dev_warn
(
idev
->
dev
,
"unsupported length %u
\n
"
,
msg
->
len
);
return
-
EINVAL
;
}
idev
->
msg
=
msg
;
idev
->
msg_xfrd
=
0
;
idev
->
msg_err
=
0
;
...
...
@@ -454,6 +449,11 @@ static const struct i2c_algorithm axxia_i2c_algo = {
.
functionality
=
axxia_i2c_func
,
};
static
struct
i2c_adapter_quirks
axxia_i2c_quirks
=
{
.
max_read_len
=
255
,
.
max_write_len
=
255
,
};
static
int
axxia_i2c_probe
(
struct
platform_device
*
pdev
)
{
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
...
...
@@ -511,6 +511,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
strlcpy
(
idev
->
adapter
.
name
,
pdev
->
name
,
sizeof
(
idev
->
adapter
.
name
));
idev
->
adapter
.
owner
=
THIS_MODULE
;
idev
->
adapter
.
algo
=
&
axxia_i2c_algo
;
idev
->
adapter
.
quirks
=
&
axxia_i2c_quirks
;
idev
->
adapter
.
dev
.
parent
=
&
pdev
->
dev
;
idev
->
adapter
.
dev
.
of_node
=
pdev
->
dev
.
of_node
;
...
...
drivers/i2c/busses/i2c-bcm-iproc.c
View file @
9ed1d862
...
...
@@ -160,14 +160,6 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c,
u32
val
;
unsigned
long
time_left
=
msecs_to_jiffies
(
I2C_TIMEOUT_MESC
);
/* need to reserve one byte in the FIFO for the slave address */
if
(
msg
->
len
>
M_TX_RX_FIFO_SIZE
-
1
)
{
dev_err
(
iproc_i2c
->
device
,
"only support data length up to %u bytes
\n
"
,
M_TX_RX_FIFO_SIZE
-
1
);
return
-
EOPNOTSUPP
;
}
/* check if bus is busy */
if
(
!!
(
readl
(
iproc_i2c
->
base
+
M_CMD_OFFSET
)
&
BIT
(
M_CMD_START_BUSY_SHIFT
)))
{
...
...
@@ -287,6 +279,12 @@ static const struct i2c_algorithm bcm_iproc_algo = {
.
functionality
=
bcm_iproc_i2c_functionality
,
};
static
struct
i2c_adapter_quirks
bcm_iproc_i2c_quirks
=
{
/* need to reserve one byte in the FIFO for the slave address */
.
max_read_len
=
M_TX_RX_FIFO_SIZE
-
1
,
.
max_write_len
=
M_TX_RX_FIFO_SIZE
-
1
,
};
static
int
bcm_iproc_i2c_cfg_speed
(
struct
bcm_iproc_i2c_dev
*
iproc_i2c
)
{
unsigned
int
bus_speed
;
...
...
@@ -413,6 +411,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata
(
adap
,
iproc_i2c
);
strlcpy
(
adap
->
name
,
"Broadcom iProc I2C adapter"
,
sizeof
(
adap
->
name
));
adap
->
algo
=
&
bcm_iproc_algo
;
adap
->
quirks
=
&
bcm_iproc_i2c_quirks
;
adap
->
dev
.
parent
=
&
pdev
->
dev
;
adap
->
dev
.
of_node
=
pdev
->
dev
.
of_node
;
...
...
drivers/i2c/busses/i2c-cpm.c
View file @
9ed1d862
...
...
@@ -308,22 +308,12 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
struct
i2c_reg
__iomem
*
i2c_reg
=
cpm
->
i2c_reg
;
struct
i2c_ram
__iomem
*
i2c_ram
=
cpm
->
i2c_ram
;
struct
i2c_msg
*
pmsg
;
int
ret
,
i
;
int
ret
;
int
tptr
;
int
rptr
;
cbd_t
__iomem
*
tbdf
;
cbd_t
__iomem
*
rbdf
;
if
(
num
>
CPM_MAXBD
)
return
-
EINVAL
;
/* Check if we have any oversized READ requests */
for
(
i
=
0
;
i
<
num
;
i
++
)
{
pmsg
=
&
msgs
[
i
];
if
(
pmsg
->
len
>=
CPM_MAX_READ
)
return
-
EINVAL
;
}
/* Reset to use first buffer */
out_be16
(
&
i2c_ram
->
rbptr
,
in_be16
(
&
i2c_ram
->
rbase
));
out_be16
(
&
i2c_ram
->
tbptr
,
in_be16
(
&
i2c_ram
->
tbase
));
...
...
@@ -424,10 +414,18 @@ static const struct i2c_algorithm cpm_i2c_algo = {
.
functionality
=
cpm_i2c_func
,
};
/* CPM_MAX_READ is also limiting writes according to the code! */
static
struct
i2c_adapter_quirks
cpm_i2c_quirks
=
{
.
max_num_msgs
=
CPM_MAXBD
,
.
max_read_len
=
CPM_MAX_READ
,
.
max_write_len
=
CPM_MAX_READ
,
};
static
const
struct
i2c_adapter
cpm_ops
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"i2c-cpm"
,
.
algo
=
&
cpm_i2c_algo
,
.
quirks
=
&
cpm_i2c_quirks
,
};
static
int
cpm_i2c_setup
(
struct
cpm_i2c
*
cpm
)
...
...
drivers/i2c/busses/i2c-dln2.c
View file @
9ed1d862
...
...
@@ -144,7 +144,6 @@ static int dln2_i2c_xfer(struct i2c_adapter *adapter,
{
struct
dln2_i2c
*
dln2
=
i2c_get_adapdata
(
adapter
);
struct
i2c_msg
*
pmsg
;
struct
device
*
dev
=
&
dln2
->
adapter
.
dev
;
int
i
;
for
(
i
=
0
;
i
<
num
;
i
++
)
{
...
...
@@ -152,11 +151,6 @@ static int dln2_i2c_xfer(struct i2c_adapter *adapter,
pmsg
=
&
msgs
[
i
];
if
(
pmsg
->
len
>
DLN2_I2C_MAX_XFER_SIZE
)
{
dev_warn
(
dev
,
"maximum transfer size exceeded
\n
"
);
return
-
EOPNOTSUPP
;
}
if
(
pmsg
->
flags
&
I2C_M_RD
)
{
ret
=
dln2_i2c_read
(
dln2
,
pmsg
->
addr
,
pmsg
->
buf
,
pmsg
->
len
);
...
...
@@ -187,6 +181,11 @@ static const struct i2c_algorithm dln2_i2c_usb_algorithm = {
.
functionality
=
dln2_i2c_func
,
};
static
struct
i2c_adapter_quirks
dln2_i2c_quirks
=
{
.
max_read_len
=
DLN2_I2C_MAX_XFER_SIZE
,
.
max_write_len
=
DLN2_I2C_MAX_XFER_SIZE
,
};
static
int
dln2_i2c_probe
(
struct
platform_device
*
pdev
)
{
int
ret
;
...
...
@@ -209,6 +208,7 @@ static int dln2_i2c_probe(struct platform_device *pdev)
dln2
->
adapter
.
owner
=
THIS_MODULE
;
dln2
->
adapter
.
class
=
I2C_CLASS_HWMON
;
dln2
->
adapter
.
algo
=
&
dln2_i2c_usb_algorithm
;
dln2
->
adapter
.
quirks
=
&
dln2_i2c_quirks
;
dln2
->
adapter
.
dev
.
parent
=
dev
;
i2c_set_adapdata
(
&
dln2
->
adapter
,
dln2
);
snprintf
(
dln2
->
adapter
.
name
,
sizeof
(
dln2
->
adapter
.
name
),
"%s-%s-%d"
,
...
...
drivers/i2c/busses/i2c-opal.c
View file @
9ed1d862
...
...
@@ -104,18 +104,8 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
req
.
buffer_ra
=
cpu_to_be64
(
__pa
(
msgs
[
0
].
buf
));
break
;
case
2
:
/* For two messages, we basically support only simple
* smbus transactions of a write plus a read. We might
* want to allow also two writes but we'd have to bounce
* the data into a single buffer.
*/
if
((
msgs
[
0
].
flags
&
I2C_M_RD
)
||
!
(
msgs
[
1
].
flags
&
I2C_M_RD
))
return
-
EOPNOTSUPP
;
if
(
msgs
[
0
].
len
>
4
)
return
-
EOPNOTSUPP
;
if
(
msgs
[
0
].
addr
!=
msgs
[
1
].
addr
)
return
-
EOPNOTSUPP
;
req
.
type
=
OPAL_I2C_SM_READ
;
req
.
type
=
(
msgs
[
1
].
flags
&
I2C_M_RD
)
?
OPAL_I2C_SM_READ
:
OPAL_I2C_SM_WRITE
;
req
.
addr
=
cpu_to_be16
(
msgs
[
0
].
addr
);
req
.
subaddr_sz
=
msgs
[
0
].
len
;
for
(
i
=
0
;
i
<
msgs
[
0
].
len
;
i
++
)
...
...
@@ -210,6 +200,15 @@ static const struct i2c_algorithm i2c_opal_algo = {
.
functionality
=
i2c_opal_func
,
};
/*
* For two messages, we basically support simple smbus transactions of a
* write-then-anything.
*/
static
struct
i2c_adapter_quirks
i2c_opal_quirks
=
{
.
flags
=
I2C_AQ_COMB
|
I2C_AQ_COMB_WRITE_FIRST
|
I2C_AQ_COMB_SAME_ADDR
,
.
max_comb_1st_msg_len
=
4
,
};
static
int
i2c_opal_probe
(
struct
platform_device
*
pdev
)
{
struct
i2c_adapter
*
adapter
;
...
...
@@ -232,6 +231,7 @@ static int i2c_opal_probe(struct platform_device *pdev)
adapter
->
algo
=
&
i2c_opal_algo
;
adapter
->
algo_data
=
(
void
*
)(
unsigned
long
)
opal_id
;
adapter
->
quirks
=
&
i2c_opal_quirks
;
adapter
->
dev
.
parent
=
&
pdev
->
dev
;
adapter
->
dev
.
of_node
=
of_node_get
(
pdev
->
dev
.
of_node
);
pname
=
of_get_property
(
pdev
->
dev
.
of_node
,
"ibm,port-name"
,
NULL
);
...
...
drivers/i2c/busses/i2c-pmcmsp.c
View file @
9ed1d862
...
...
@@ -456,14 +456,6 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
return
-
EINVAL
;
}
if
(
cmd
->
read_len
>
MSP_MAX_BYTES_PER_RW
||
cmd
->
write_len
>
MSP_MAX_BYTES_PER_RW
)
{
dev_err
(
&
pmcmsptwi_adapter
.
dev
,
"%s: Cannot transfer more than %d bytes
\n
"
,
__func__
,
MSP_MAX_BYTES_PER_RW
);
return
-
EINVAL
;
}
mutex_lock
(
&
data
->
lock
);
dev_dbg
(
&
pmcmsptwi_adapter
.
dev
,
"Setting address to 0x%04x
\n
"
,
cmd
->
addr
);
...
...
@@ -520,25 +512,14 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
struct
pmcmsptwi_cfg
oldcfg
,
newcfg
;
int
ret
;
if
(
num
>
2
)
{
dev_dbg
(
&
adap
->
dev
,
"%d messages unsupported
\n
"
,
num
);
return
-
EINVAL
;
}
else
if
(
num
==
2
)
{
/* Check for a dual write-then-read command */
if
(
num
==
2
)
{
struct
i2c_msg
*
nextmsg
=
msg
+
1
;
if
(
!
(
msg
->
flags
&
I2C_M_RD
)
&&
(
nextmsg
->
flags
&
I2C_M_RD
)
&&
msg
->
addr
==
nextmsg
->
addr
)
{
cmd
.
type
=
MSP_TWI_CMD_WRITE_READ
;
cmd
.
write_len
=
msg
->
len
;
cmd
.
write_data
=
msg
->
buf
;
cmd
.
read_len
=
nextmsg
->
len
;
cmd
.
read_data
=
nextmsg
->
buf
;
}
else
{
dev_dbg
(
&
adap
->
dev
,
"Non write-read dual messages unsupported
\n
"
);
return
-
EINVAL
;
}
cmd
.
type
=
MSP_TWI_CMD_WRITE_READ
;
cmd
.
write_len
=
msg
->
len
;
cmd
.
write_data
=
msg
->
buf
;
cmd
.
read_len
=
nextmsg
->
len
;
cmd
.
read_data
=
nextmsg
->
buf
;
}
else
if
(
msg
->
flags
&
I2C_M_RD
)
{
cmd
.
type
=
MSP_TWI_CMD_READ
;
cmd
.
read_len
=
msg
->
len
;
...
...
@@ -598,6 +579,14 @@ static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_WORD_DATA
|
I2C_FUNC_SMBUS_PROC_CALL
;
}
static
struct
i2c_adapter_quirks
pmcmsptwi_i2c_quirks
=
{
.
flags
=
I2C_AQ_COMB_WRITE_THEN_READ
,
.
max_write_len
=
MSP_MAX_BYTES_PER_RW
,
.
max_read_len
=
MSP_MAX_BYTES_PER_RW
,
.
max_comb_1st_msg_len
=
MSP_MAX_BYTES_PER_RW
,
.
max_comb_2nd_msg_len
=
MSP_MAX_BYTES_PER_RW
,
};
/* -- Initialization -- */
static
struct
i2c_algorithm
pmcmsptwi_algo
=
{
...
...
@@ -609,6 +598,7 @@ static struct i2c_adapter pmcmsptwi_adapter = {
.
owner
=
THIS_MODULE
,
.
class
=
I2C_CLASS_HWMON
|
I2C_CLASS_SPD
,
.
algo
=
&
pmcmsptwi_algo
,
.
quirks
=
&
pmcmsptwi_i2c_quirks
,
.
name
=
DRV_NAME
,
};
...
...
drivers/i2c/busses/i2c-powermac.c
View file @
9ed1d862
...
...
@@ -153,12 +153,6 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
int
read
;
int
addrdir
;
if
(
num
!=
1
)
{
dev_err
(
&
adap
->
dev
,
"Multi-message I2C transactions not supported
\n
"
);
return
-
EOPNOTSUPP
;
}
if
(
msgs
->
flags
&
I2C_M_TEN
)
return
-
EINVAL
;
read
=
(
msgs
->
flags
&
I2C_M_RD
)
!=
0
;
...
...
@@ -205,6 +199,9 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
.
functionality
=
i2c_powermac_func
,
};
static
struct
i2c_adapter_quirks
i2c_powermac_quirks
=
{
.
max_num_msgs
=
1
,
};
static
int
i2c_powermac_remove
(
struct
platform_device
*
dev
)
{
...
...
@@ -434,6 +431,7 @@ static int i2c_powermac_probe(struct platform_device *dev)
platform_set_drvdata
(
dev
,
adapter
);
adapter
->
algo
=
&
i2c_powermac_algorithm
;
adapter
->
quirks
=
&
i2c_powermac_quirks
;
i2c_set_adapdata
(
adapter
,
bus
);
adapter
->
dev
.
parent
=
&
dev
->
dev
;
...
...
drivers/i2c/busses/i2c-qup.c
View file @
9ed1d862
...
...
@@ -412,17 +412,6 @@ static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg)
unsigned
long
left
;
int
ret
;
/*
* The QUP block will issue a NACK and STOP on the bus when reaching
* the end of the read, the length of the read is specified as one byte
* which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
*/
if
(
msg
->
len
>
QUP_READ_LIMIT
)
{
dev_err
(
qup
->
dev
,
"HW not capable of reads over %d bytes
\n
"
,
QUP_READ_LIMIT
);
return
-
EINVAL
;
}
qup
->
msg
=
msg
;
qup
->
pos
=
0
;
...
...
@@ -534,6 +523,15 @@ static const struct i2c_algorithm qup_i2c_algo = {
.
functionality
=
qup_i2c_func
,
};
/*
* The QUP block will issue a NACK and STOP on the bus when reaching
* the end of the read, the length of the read is specified as one byte
* which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
*/
static
struct
i2c_adapter_quirks
qup_i2c_quirks
=
{
.
max_read_len
=
QUP_READ_LIMIT
,
};
static
void
qup_i2c_enable_clocks
(
struct
qup_i2c_dev
*
qup
)
{
clk_prepare_enable
(
qup
->
clk
);
...
...
@@ -670,6 +668,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata
(
&
qup
->
adap
,
qup
);
qup
->
adap
.
algo
=
&
qup_i2c_algo
;
qup
->
adap
.
quirks
=
&
qup_i2c_quirks
;
qup
->
adap
.
dev
.
parent
=
qup
->
dev
;
qup
->
adap
.
dev
.
of_node
=
pdev
->
dev
.
of_node
;
strlcpy
(
qup
->
adap
.
name
,
"QUP I2C adapter"
,
sizeof
(
qup
->
adap
.
name
));
...
...
drivers/i2c/busses/i2c-viperboard.c
View file @
9ed1d862
...
...
@@ -288,10 +288,6 @@ static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs,
i
,
pmsg
->
flags
&
I2C_M_RD
?
"read"
:
"write"
,
pmsg
->
flags
,
pmsg
->
len
,
pmsg
->
addr
);
/* msgs longer than 2048 bytes are not supported by adapter */
if
(
pmsg
->
len
>
2048
)
return
-
EINVAL
;
mutex_lock
(
&
vb
->
lock
);
/* directly send the message */
if
(
pmsg
->
flags
&
I2C_M_RD
)
{
...
...
@@ -358,6 +354,11 @@ static const struct i2c_algorithm vprbrd_algorithm = {
.
functionality
=
vprbrd_i2c_func
,
};
static
struct
i2c_adapter_quirks
vprbrd_quirks
=
{
.
max_read_len
=
2048
,
.
max_write_len
=
2048
,
};
static
int
vprbrd_i2c_probe
(
struct
platform_device
*
pdev
)
{
struct
vprbrd
*
vb
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
...
...
@@ -373,6 +374,7 @@ static int vprbrd_i2c_probe(struct platform_device *pdev)
vb_i2c
->
i2c
.
owner
=
THIS_MODULE
;
vb_i2c
->
i2c
.
class
=
I2C_CLASS_HWMON
;
vb_i2c
->
i2c
.
algo
=
&
vprbrd_algorithm
;
vb_i2c
->
i2c
.
quirks
=
&
vprbrd_quirks
;
vb_i2c
->
i2c
.
algo_data
=
vb
;
/* save the param in usb capabable memory */
vb_i2c
->
bus_freq_param
=
i2c_bus_param
;
...
...
drivers/i2c/i2c-core.c
View file @
9ed1d862
...
...
@@ -1929,6 +1929,65 @@ module_exit(i2c_exit);
* ----------------------------------------------------
*/
/* Check if val is exceeding the quirk IFF quirk is non 0 */
#define i2c_quirk_exceeded(val, quirk) ((quirk) && ((val) > (quirk)))
static
int
i2c_quirk_error
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msg
,
char
*
err_msg
)
{
dev_err_ratelimited
(
&
adap
->
dev
,
"adapter quirk: %s (addr 0x%04x, size %u, %s)
\n
"
,
err_msg
,
msg
->
addr
,
msg
->
len
,
msg
->
flags
&
I2C_M_RD
?
"read"
:
"write"
);
return
-
EOPNOTSUPP
;
}
static
int
i2c_check_for_quirks
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msgs
,
int
num
)
{
const
struct
i2c_adapter_quirks
*
q
=
adap
->
quirks
;
int
max_num
=
q
->
max_num_msgs
,
i
;
bool
do_len_check
=
true
;
if
(
q
->
flags
&
I2C_AQ_COMB
)
{
max_num
=
2
;
/* special checks for combined messages */
if
(
num
==
2
)
{
if
(
q
->
flags
&
I2C_AQ_COMB_WRITE_FIRST
&&
msgs
[
0
].
flags
&
I2C_M_RD
)
return
i2c_quirk_error
(
adap
,
&
msgs
[
0
],
"1st comb msg must be write"
);
if
(
q
->
flags
&
I2C_AQ_COMB_READ_SECOND
&&
!
(
msgs
[
1
].
flags
&
I2C_M_RD
))
return
i2c_quirk_error
(
adap
,
&
msgs
[
1
],
"2nd comb msg must be read"
);
if
(
q
->
flags
&
I2C_AQ_COMB_SAME_ADDR
&&
msgs
[
0
].
addr
!=
msgs
[
1
].
addr
)
return
i2c_quirk_error
(
adap
,
&
msgs
[
0
],
"comb msg only to same addr"
);
if
(
i2c_quirk_exceeded
(
msgs
[
0
].
len
,
q
->
max_comb_1st_msg_len
))
return
i2c_quirk_error
(
adap
,
&
msgs
[
0
],
"msg too long"
);
if
(
i2c_quirk_exceeded
(
msgs
[
1
].
len
,
q
->
max_comb_2nd_msg_len
))
return
i2c_quirk_error
(
adap
,
&
msgs
[
1
],
"msg too long"
);
do_len_check
=
false
;
}
}
if
(
i2c_quirk_exceeded
(
num
,
max_num
))
return
i2c_quirk_error
(
adap
,
&
msgs
[
0
],
"too many messages"
);
for
(
i
=
0
;
i
<
num
;
i
++
)
{
u16
len
=
msgs
[
i
].
len
;
if
(
msgs
[
i
].
flags
&
I2C_M_RD
)
{
if
(
do_len_check
&&
i2c_quirk_exceeded
(
len
,
q
->
max_read_len
))
return
i2c_quirk_error
(
adap
,
&
msgs
[
i
],
"msg too long"
);
}
else
{
if
(
do_len_check
&&
i2c_quirk_exceeded
(
len
,
q
->
max_write_len
))
return
i2c_quirk_error
(
adap
,
&
msgs
[
i
],
"msg too long"
);
}
}
return
0
;
}
/**
* __i2c_transfer - unlocked flavor of i2c_transfer
* @adap: Handle to I2C bus
...
...
@@ -1946,6 +2005,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
unsigned
long
orig_jiffies
;
int
ret
,
try
;
if
(
adap
->
quirks
&&
i2c_check_for_quirks
(
adap
,
msgs
,
num
))
return
-
EOPNOTSUPP
;
/* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets
* enabled. This is an efficient way of keeping the for-loop from
* being executed when not needed.
...
...
include/linux/i2c.h
View file @
9ed1d862
...
...
@@ -449,6 +449,48 @@ int i2c_recover_bus(struct i2c_adapter *adap);
int
i2c_generic_gpio_recovery
(
struct
i2c_adapter
*
adap
);
int
i2c_generic_scl_recovery
(
struct
i2c_adapter
*
adap
);
/**
* struct i2c_adapter_quirks - describe flaws of an i2c adapter
* @flags: see I2C_AQ_* for possible flags and read below
* @max_num_msgs: maximum number of messages per transfer
* @max_write_len: maximum length of a write message
* @max_read_len: maximum length of a read message
* @max_comb_1st_msg_len: maximum length of the first msg in a combined message
* @max_comb_2nd_msg_len: maximum length of the second msg in a combined message
*
* Note about combined messages: Some I2C controllers can only send one message
* per transfer, plus something called combined message or write-then-read.
* This is (usually) a small write message followed by a read message and
* barely enough to access register based devices like EEPROMs. There is a flag
* to support this mode. It implies max_num_msg = 2 and does the length checks
* with max_comb_*_len because combined message mode usually has its own
* limitations. Because of HW implementations, some controllers can actually do
* write-then-anything or other variants. To support that, write-then-read has
* been broken out into smaller bits like write-first and read-second which can
* be combined as needed.
*/
struct
i2c_adapter_quirks
{
u64
flags
;
int
max_num_msgs
;
u16
max_write_len
;
u16
max_read_len
;
u16
max_comb_1st_msg_len
;
u16
max_comb_2nd_msg_len
;
};
/* enforce max_num_msgs = 2 and use max_comb_*_len for length checks */
#define I2C_AQ_COMB BIT(0)
/* first combined message must be write */
#define I2C_AQ_COMB_WRITE_FIRST BIT(1)
/* second combined message must be read */
#define I2C_AQ_COMB_READ_SECOND BIT(2)
/* both combined messages must have the same target address */
#define I2C_AQ_COMB_SAME_ADDR BIT(3)
/* convenience macro for typical write-then read case */
#define I2C_AQ_COMB_WRITE_THEN_READ (I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \
I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR)
/*
* i2c_adapter is the structure used to identify a physical i2c bus along
* with the access algorithms necessary to access it.
...
...
@@ -474,6 +516,7 @@ struct i2c_adapter {
struct
list_head
userspace_clients
;
struct
i2c_bus_recovery_info
*
bus_recovery_info
;
const
struct
i2c_adapter_quirks
*
quirks
;
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
...
...
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