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
bc1f1afe
Commit
bc1f1afe
authored
Jun 05, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/gregkh/linux/i2c-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
3ac7f581
31f68121
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
182 additions
and
134 deletions
+182
-134
drivers/i2c/chips/w83781d.c
drivers/i2c/chips/w83781d.c
+171
-129
drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.c
+4
-5
include/linux/i2c-id.h
include/linux/i2c-id.h
+7
-0
No files found.
drivers/i2c/chips/w83781d.c
View file @
bc1f1afe
...
...
@@ -1031,27 +1031,129 @@ w83781d_attach_adapter(struct i2c_adapter *adapter)
return
i2c_detect
(
adapter
,
&
addr_data
,
w83781d_detect
);
}
/* Assumes that adapter is of I2C, not ISA variety.
* OTHERWISE DON'T CALL THIS
*/
static
int
w83781d_detect_subclients
(
struct
i2c_adapter
*
adapter
,
int
address
,
int
kind
,
struct
i2c_client
*
new_client
)
{
int
i
,
val1
=
0
,
id
;
int
err
;
const
char
*
client_name
;
struct
w83781d_data
*
data
=
i2c_get_clientdata
(
new_client
);
if
(
!
(
data
->
lm75
=
kmalloc
(
2
*
sizeof
(
struct
i2c_client
),
GFP_KERNEL
)))
{
err
=
-
ENOMEM
;
goto
ERROR_SC_0
;
}
memset
(
data
->
lm75
,
0x00
,
2
*
sizeof
(
struct
i2c_client
));
id
=
i2c_adapter_id
(
adapter
);
if
(
force_subclients
[
0
]
==
id
&&
force_subclients
[
1
]
==
address
)
{
for
(
i
=
2
;
i
<=
3
;
i
++
)
{
if
(
force_subclients
[
i
]
<
0x48
||
force_subclients
[
i
]
>
0x4f
)
{
dev_err
(
&
new_client
->
dev
,
"Invalid subclient "
"address %d; must be 0x48-0x4f
\n
"
,
force_subclients
[
i
]);
err
=
-
EINVAL
;
goto
ERROR_SC_1
;
}
}
w83781d_write_value
(
new_client
,
W83781D_REG_I2C_SUBADDR
,
(
force_subclients
[
2
]
&
0x07
)
|
((
force_subclients
[
3
]
&
0x07
)
<<
4
));
data
->
lm75
[
0
].
addr
=
force_subclients
[
2
];
}
else
{
val1
=
w83781d_read_value
(
new_client
,
W83781D_REG_I2C_SUBADDR
);
data
->
lm75
[
0
].
addr
=
0x48
+
(
val1
&
0x07
);
}
if
(
kind
!=
w83783s
)
{
if
(
force_subclients
[
0
]
==
id
&&
force_subclients
[
1
]
==
address
)
{
data
->
lm75
[
1
].
addr
=
force_subclients
[
3
];
}
else
{
data
->
lm75
[
1
].
addr
=
0x48
+
((
val1
>>
4
)
&
0x07
);
}
if
(
data
->
lm75
[
0
].
addr
==
data
->
lm75
[
1
].
addr
)
{
dev_err
(
&
new_client
->
dev
,
"Duplicate addresses 0x%x for subclients.
\n
"
,
data
->
lm75
[
0
].
addr
);
err
=
-
EBUSY
;
goto
ERROR_SC_1
;
}
}
if
(
kind
==
w83781d
)
client_name
=
"W83781D subclient"
;
else
if
(
kind
==
w83782d
)
client_name
=
"W83782D subclient"
;
else
if
(
kind
==
w83783s
)
client_name
=
"W83783S subclient"
;
else
if
(
kind
==
w83627hf
)
client_name
=
"W83627HF subclient"
;
else
if
(
kind
==
as99127f
)
client_name
=
"AS99127F subclient"
;
else
client_name
=
"unknown subclient?"
;
for
(
i
=
0
;
i
<=
1
;
i
++
)
{
/* store all data in w83781d */
i2c_set_clientdata
(
&
data
->
lm75
[
i
],
NULL
);
data
->
lm75
[
i
].
adapter
=
adapter
;
data
->
lm75
[
i
].
driver
=
&
w83781d_driver
;
data
->
lm75
[
i
].
flags
=
0
;
strlcpy
(
data
->
lm75
[
i
].
dev
.
name
,
client_name
,
DEVICE_NAME_SIZE
);
if
((
err
=
i2c_attach_client
(
&
(
data
->
lm75
[
i
]))))
{
dev_err
(
&
new_client
->
dev
,
"Subclient %d "
"registration at address 0x%x "
"failed.
\n
"
,
i
,
data
->
lm75
[
i
].
addr
);
if
(
i
==
1
)
goto
ERROR_SC_2
;
goto
ERROR_SC_1
;
}
if
(
kind
==
w83783s
)
break
;
}
return
0
;
/* Undo inits in case of errors */
ERROR_SC_2:
i2c_detach_client
(
&
(
data
->
lm75
[
0
]));
ERROR_SC_1:
kfree
(
data
->
lm75
);
ERROR_SC_0:
return
err
;
}
static
int
w83781d_detect
(
struct
i2c_adapter
*
adapter
,
int
address
,
int
kind
)
{
int
i
=
0
,
val1
=
0
,
val2
,
id
;
int
i
=
0
,
val1
=
0
,
val2
;
struct
i2c_client
*
new_client
;
struct
w83781d_data
*
data
;
int
err
=
0
;
const
char
*
type_name
=
""
;
int
err
;
const
char
*
client_name
=
""
;
int
is_isa
=
i2c_is_isa_adapter
(
adapter
);
enum
vendor
{
winbond
,
asus
}
vendid
;
if
(
!
is_isa
&&
!
i2c_check_functionality
(
adapter
,
I2C_FUNC_SMBUS_BYTE_DATA
))
&&
!
i2c_check_functionality
(
adapter
,
I2C_FUNC_SMBUS_BYTE_DATA
))
{
err
=
-
EINVAL
;
goto
ERROR0
;
}
if
(
is_isa
)
{
if
(
!
request_region
(
address
,
W83781D_EXTENT
,
"w83781d"
))
if
(
is_isa
)
if
(
!
request_region
(
address
,
W83781D_EXTENT
,
"w83781d"
))
{
err
=
-
EBUSY
;
goto
ERROR0
;
release_region
(
address
,
W83781D_EXTENT
);
}
}
/* Probe whether there is anything available on this address. Already
done for SMBus clients */
...
...
@@ -1059,15 +1161,21 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if
(
is_isa
)
{
#define REALLY_SLOW_IO
/* We need the timeouts for at least some LM78-like
chips. But only
if we read 'undefined' registers. */
/* We need the timeouts for at least some LM78-like
chips. But only
if we read 'undefined' registers. */
i
=
inb_p
(
address
+
1
);
if
(
inb_p
(
address
+
2
)
!=
i
)
goto
ERROR0
;
if
(
inb_p
(
address
+
3
)
!=
i
)
goto
ERROR0
;
if
(
inb_p
(
address
+
7
)
!=
i
)
goto
ERROR0
;
if
(
inb_p
(
address
+
2
)
!=
i
)
{
err
=
-
ENODEV
;
goto
ERROR1
;
}
if
(
inb_p
(
address
+
3
)
!=
i
)
{
err
=
-
ENODEV
;
goto
ERROR1
;
}
if
(
inb_p
(
address
+
7
)
!=
i
)
{
err
=
-
ENODEV
;
goto
ERROR1
;
}
#undef REALLY_SLOW_IO
/* Let's just hope nothing breaks here */
...
...
@@ -1075,7 +1183,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
outb_p
(
~
i
&
0x7f
,
address
+
5
);
if
((
inb_p
(
address
+
5
)
&
0x7f
)
!=
(
~
i
&
0x7f
))
{
outb_p
(
i
,
address
+
5
);
return
0
;
err
=
-
ENODEV
;
goto
ERROR1
;
}
}
}
...
...
@@ -1087,7 +1196,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if
(
!
(
new_client
=
kmalloc
(
sizeof
(
struct
i2c_client
)
+
sizeof
(
struct
w83781d_data
),
GFP_KERNEL
)))
{
err
=
-
ENOMEM
;
goto
ERROR
0
;
goto
ERROR
1
;
}
memset
(
new_client
,
0x00
,
sizeof
(
struct
i2c_client
)
+
...
...
@@ -1108,8 +1217,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
force_*=... parameter, and the Winbond will be reset to the right
bank. */
if
(
kind
<
0
)
{
if
(
w83781d_read_value
(
new_client
,
W83781D_REG_CONFIG
)
&
0x80
)
goto
ERROR1
;
if
(
w83781d_read_value
(
new_client
,
W83781D_REG_CONFIG
)
&
0x80
){
err
=
-
ENODEV
;
goto
ERROR2
;
}
val1
=
w83781d_read_value
(
new_client
,
W83781D_REG_BANK
);
val2
=
w83781d_read_value
(
new_client
,
W83781D_REG_CHIPMAN
);
/* Check for Winbond or Asus ID if in bank 0 */
...
...
@@ -1117,14 +1228,19 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
(((
!
(
val1
&
0x80
))
&&
(
val2
!=
0xa3
)
&&
(
val2
!=
0xc3
)
&&
(
val2
!=
0x94
))
||
((
val1
&
0x80
)
&&
(
val2
!=
0x5c
)
&&
(
val2
!=
0x12
)
&&
(
val2
!=
0x06
))))
goto
ERROR1
;
/* If Winbond SMBus, check address at 0x48. Asus doesn't support */
&&
(
val2
!=
0x06
))))
{
err
=
-
ENODEV
;
goto
ERROR2
;
}
/* If Winbond SMBus, check address at 0x48.
Asus doesn't support */
if
((
!
is_isa
)
&&
(((
!
(
val1
&
0x80
))
&&
(
val2
==
0xa3
))
||
((
val1
&
0x80
)
&&
(
val2
==
0x5c
))))
{
if
(
w83781d_read_value
(
new_client
,
W83781D_REG_I2C_ADDR
)
!=
address
)
goto
ERROR1
;
(
new_client
,
W83781D_REG_I2C_ADDR
)
!=
address
)
{
err
=
-
ENODEV
;
goto
ERROR2
;
}
}
}
...
...
@@ -1143,8 +1259,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
vendid
=
winbond
;
else
if
((
val2
==
0x12
)
||
(
val2
==
0x06
))
vendid
=
asus
;
else
goto
ERROR1
;
else
{
err
=
-
ENODEV
;
goto
ERROR2
;
}
/* mask off lower bit, not reliable */
val1
=
w83781d_read_value
(
new_client
,
W83781D_REG_WCHIPID
)
&
0xfe
;
...
...
@@ -1166,38 +1285,31 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
"Ignoring 'force' parameter for unknown chip at"
"adapter %d, address 0x%02x
\n
"
,
i2c_adapter_id
(
adapter
),
address
);
goto
ERROR1
;
err
=
-
EINVAL
;
goto
ERROR2
;
}
}
if
(
kind
==
w83781d
)
{
type_name
=
"w83781d"
;
client_name
=
"W83781D chip"
;
}
else
if
(
kind
==
w83782d
)
{
type_name
=
"w83782d"
;
client_name
=
"W83782D chip"
;
}
else
if
(
kind
==
w83783s
)
{
type_name
=
"w83783s"
;
client_name
=
"W83783S chip"
;
}
else
if
(
kind
==
w83627hf
)
{
type_name
=
"w83627hf"
;
client_name
=
"W83627HF chip"
;
}
else
if
(
kind
==
as99127f
)
{
type_name
=
"as99127f"
;
client_name
=
"AS99127F chip"
;
}
else
if
(
kind
==
w83697hf
)
{
type_name
=
"w83697hf"
;
client_name
=
"W83697HF chip"
;
}
else
{
dev_err
(
&
new_client
->
dev
,
"Internal error: unknown kind (%d)?!?"
,
kind
);
goto
ERROR1
;
dev_err
(
&
new_client
->
dev
,
"Internal error: unknown "
"kind (%d)?!?"
,
kind
);
err
=
-
ENODEV
;
goto
ERROR2
;
}
/* Reserve the ISA region */
if
(
is_isa
)
request_region
(
address
,
W83781D_EXTENT
,
type_name
);
/* Fill in the remaining client fields and put it into the global list */
/* Fill in the remaining client fields and put into the global list */
strlcpy
(
new_client
->
dev
.
name
,
client_name
,
DEVICE_NAME_SIZE
);
data
->
type
=
kind
;
...
...
@@ -1206,76 +1318,13 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
/* Tell the I2C layer a new client has arrived */
if
((
err
=
i2c_attach_client
(
new_client
)))
goto
ERROR
3
;
goto
ERROR
2
;
/* attach secondary i2c lm75-like clients */
if
(
!
is_isa
)
{
if
(
!
(
data
->
lm75
=
kmalloc
(
2
*
sizeof
(
struct
i2c_client
),
GFP_KERNEL
)))
{
err
=
-
ENOMEM
;
goto
ERROR4
;
}
memset
(
data
->
lm75
,
0x00
,
2
*
sizeof
(
struct
i2c_client
));
id
=
i2c_adapter_id
(
adapter
);
if
(
force_subclients
[
0
]
==
id
&&
force_subclients
[
1
]
==
address
)
{
for
(
i
=
2
;
i
<=
3
;
i
++
)
{
if
(
force_subclients
[
i
]
<
0x48
||
force_subclients
[
i
]
>
0x4f
)
{
dev_err
(
&
new_client
->
dev
,
"Invalid subclient address %d; must be 0x48-0x4f
\n
"
,
force_subclients
[
i
]);
goto
ERROR5
;
}
}
w83781d_write_value
(
new_client
,
W83781D_REG_I2C_SUBADDR
,
(
force_subclients
[
2
]
&
0x07
)
|
((
force_subclients
[
3
]
&
0x07
)
<<
4
));
data
->
lm75
[
0
].
addr
=
force_subclients
[
2
];
}
else
{
val1
=
w83781d_read_value
(
new_client
,
W83781D_REG_I2C_SUBADDR
);
data
->
lm75
[
0
].
addr
=
0x48
+
(
val1
&
0x07
);
}
if
(
kind
!=
w83783s
)
{
if
(
force_subclients
[
0
]
==
id
&&
force_subclients
[
1
]
==
address
)
{
data
->
lm75
[
1
].
addr
=
force_subclients
[
3
];
}
else
{
data
->
lm75
[
1
].
addr
=
0x48
+
((
val1
>>
4
)
&
0x07
);
}
if
(
data
->
lm75
[
0
].
addr
==
data
->
lm75
[
1
].
addr
)
{
dev_err
(
&
new_client
->
dev
,
"Duplicate addresses 0x%x for subclients.
\n
"
,
data
->
lm75
[
0
].
addr
);
goto
ERROR5
;
}
}
if
(
kind
==
w83781d
)
client_name
=
"W83781D subclient"
;
else
if
(
kind
==
w83782d
)
client_name
=
"W83782D subclient"
;
else
if
(
kind
==
w83783s
)
client_name
=
"W83783S subclient"
;
else
if
(
kind
==
w83627hf
)
client_name
=
"W83627HF subclient"
;
else
if
(
kind
==
as99127f
)
client_name
=
"AS99127F subclient"
;
for
(
i
=
0
;
i
<=
1
;
i
++
)
{
i2c_set_clientdata
(
&
data
->
lm75
[
i
],
NULL
);
/* store all data in w83781d */
data
->
lm75
[
i
].
adapter
=
adapter
;
data
->
lm75
[
i
].
driver
=
&
w83781d_driver
;
data
->
lm75
[
i
].
flags
=
0
;
strlcpy
(
data
->
lm75
[
i
].
dev
.
name
,
client_name
,
DEVICE_NAME_SIZE
);
if
(
kind
==
w83783s
)
break
;
}
if
((
err
=
w83781d_detect_subclients
(
adapter
,
address
,
kind
,
new_client
)))
goto
ERROR3
;
}
else
{
data
->
lm75
=
NULL
;
}
...
...
@@ -1346,24 +1395,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
w83781d_init_client
(
new_client
);
return
0
;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
ERROR5:
if
(
!
is_isa
)
{
i2c_detach_client
(
&
data
->
lm75
[
0
]);
if
(
data
->
type
!=
w83783s
)
i2c_detach_client
(
&
data
->
lm75
[
1
]);
kfree
(
data
->
lm75
);
}
ERROR4:
ERROR3:
i2c_detach_client
(
new_client
);
ERROR3:
ERROR2:
kfree
(
new_client
);
ERROR1:
if
(
is_isa
)
release_region
(
address
,
W83781D_EXTENT
);
ERROR1:
kfree
(
new_client
);
ERROR0:
ERROR0:
return
err
;
}
...
...
@@ -1373,12 +1412,7 @@ w83781d_detach_client(struct i2c_client *client)
struct
w83781d_data
*
data
=
i2c_get_clientdata
(
client
);
int
err
;
if
((
err
=
i2c_detach_client
(
client
)))
{
dev_err
(
&
client
->
dev
,
"Client deregistration failed, client not detached.
\n
"
);
return
err
;
}
/* release ISA region or I2C subclients first */
if
(
i2c_is_isa_client
(
client
))
{
release_region
(
client
->
addr
,
W83781D_EXTENT
);
}
else
{
...
...
@@ -1387,6 +1421,14 @@ w83781d_detach_client(struct i2c_client *client)
i2c_detach_client
(
&
data
->
lm75
[
1
]);
kfree
(
data
->
lm75
);
}
/* now it's safe to scrap the rest */
if
((
err
=
i2c_detach_client
(
client
)))
{
dev_err
(
&
client
->
dev
,
"Client deregistration failed, client not detached.
\n
"
);
return
err
;
}
kfree
(
client
);
return
0
;
...
...
drivers/i2c/i2c-core.c
View file @
bc1f1afe
...
...
@@ -124,7 +124,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
int
i2c_del_adapter
(
struct
i2c_adapter
*
adap
)
{
struct
list_head
*
item
;
struct
list_head
*
item
,
*
_n
;
struct
i2c_driver
*
driver
;
struct
i2c_client
*
client
;
int
res
=
0
;
...
...
@@ -144,7 +144,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* detach any active clients. This must be done first, because
* it can fail; in which case we give upp. */
list_for_each
(
item
,
&
adap
->
clients
)
{
list_for_each
_safe
(
item
,
_n
,
&
adap
->
clients
)
{
client
=
list_entry
(
item
,
struct
i2c_client
,
list
);
/* detaching devices is unconditional of the set notify
...
...
@@ -215,8 +215,7 @@ int i2c_add_driver(struct i2c_driver *driver)
int
i2c_del_driver
(
struct
i2c_driver
*
driver
)
{
struct
list_head
*
item1
;
struct
list_head
*
item2
;
struct
list_head
*
item1
,
*
item2
,
*
_n
;
struct
i2c_client
*
client
;
struct
i2c_adapter
*
adap
;
...
...
@@ -245,7 +244,7 @@ int i2c_del_driver(struct i2c_driver *driver)
goto
out_unlock
;
}
}
else
{
list_for_each
(
item2
,
&
adap
->
clients
)
{
list_for_each
_safe
(
item2
,
_n
,
&
adap
->
clients
)
{
client
=
list_entry
(
item2
,
struct
i2c_client
,
list
);
if
(
client
->
driver
!=
driver
)
continue
;
...
...
include/linux/i2c-id.h
View file @
bc1f1afe
...
...
@@ -98,6 +98,7 @@
#define I2C_DRIVERID_ZR36120 50
/* Zoran 36120 video encoder */
#define I2C_DRIVERID_24LC32A 51
/* Microchip 24LC32A 32k EEPROM */
#define I2C_DRIVERID_STM41T00 52
/* real time clock */
#define I2C_DRIVERID_UDA1342 53
/* UDA1342 audio codec */
...
...
@@ -178,6 +179,7 @@
#define I2C_ALGO_MPC8XX 0x110000
/* MPC8xx PowerPC I2C algorithm */
#define I2C_ALGO_OCP 0x120000
/* IBM or otherwise On-chip I2C algorithm */
#define I2C_ALGO_BITHS 0x130000
/* enhanced bit style adapters */
#define I2C_ALGO_OCP_IOP3XX 0x140000
/* XSCALE IOP3XX On-chip I2C alg */
#define I2C_ALGO_EXP 0x800000
/* experimental */
...
...
@@ -213,6 +215,9 @@
#define I2C_HW_B_FRODO 0x13
/* 2d3D, Inc. SA-1110 Development Board */
#define I2C_HW_B_OMAHA 0x14
/* Omaha I2C interface (ARM) */
#define I2C_HW_B_GUIDE 0x15
/* Guide bit-basher */
#define I2C_HW_B_IXP2000 0x16
/* GPIO on IXP2000 systems */
#define I2C_HW_B_IXP425 0x17
/* GPIO on IXP425 systems */
#define I2C_HW_B_S3VIA 0x18
/* S3Via ProSavage adapter */
/* --- PCF 8584 based algorithms */
#define I2C_HW_P_LP 0x00
/* Parallel port interface */
...
...
@@ -234,6 +239,8 @@
/* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x00
/* IBM on-chip I2C adapter */
/* --- XSCALE on-chip adapters */
#define I2C_HW_IOP321 0x00
/* --- SMBus only adapters */
#define I2C_HW_SMBUS_PIIX4 0x00
...
...
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