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
nexedi
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