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
411ef2be
Commit
411ef2be
authored
Jun 28, 2016
by
Sebastian Reichel
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'chanwoo-extcon/ib-extcon-powersupply-4.8' into psy-next
parents
2e05b518
830ae442
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
100 additions
and
258 deletions
+100
-258
drivers/extcon/extcon.c
drivers/extcon/extcon.c
+24
-177
drivers/power/axp288_charger.c
drivers/power/axp288_charger.c
+53
-24
include/linux/extcon.h
include/linux/extcon.h
+23
-57
No files found.
drivers/extcon/extcon.c
View file @
411ef2be
...
...
@@ -127,38 +127,6 @@ static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id
return
-
EINVAL
;
}
static
int
find_cable_id_by_name
(
struct
extcon_dev
*
edev
,
const
char
*
name
)
{
int
id
=
-
EINVAL
;
int
i
=
0
;
/* Find the id of extcon cable */
while
(
extcon_name
[
i
])
{
if
(
!
strncmp
(
extcon_name
[
i
],
name
,
CABLE_NAME_MAX
))
{
id
=
i
;
break
;
}
i
++
;
}
return
id
;
}
static
int
find_cable_index_by_name
(
struct
extcon_dev
*
edev
,
const
char
*
name
)
{
int
id
;
if
(
edev
->
max_supported
==
0
)
return
-
EINVAL
;
/* Find the the number of extcon cable */
id
=
find_cable_id_by_name
(
edev
,
name
);
if
(
id
<
0
)
return
id
;
return
find_cable_index_by_id
(
edev
,
id
);
}
static
bool
is_extcon_changed
(
u32
prev
,
u32
new
,
int
idx
,
bool
*
attached
)
{
if
(((
prev
>>
idx
)
&
0x1
)
!=
((
new
>>
idx
)
&
0x1
))
{
...
...
@@ -373,25 +341,6 @@ int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id)
}
EXPORT_SYMBOL_GPL
(
extcon_get_cable_state_
);
/**
* extcon_get_cable_state() - Get the status of a specific cable.
* @edev: the extcon device that has the cable.
* @cable_name: cable name.
*
* Note that this is slower than extcon_get_cable_state_.
*/
int
extcon_get_cable_state
(
struct
extcon_dev
*
edev
,
const
char
*
cable_name
)
{
int
id
;
id
=
find_cable_id_by_name
(
edev
,
cable_name
);
if
(
id
<
0
)
return
id
;
return
extcon_get_cable_state_
(
edev
,
id
);
}
EXPORT_SYMBOL_GPL
(
extcon_get_cable_state
);
/**
* extcon_set_cable_state_() - Set the status of a specific cable.
* @edev: the extcon device that has the cable.
...
...
@@ -421,28 +370,6 @@ int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
}
EXPORT_SYMBOL_GPL
(
extcon_set_cable_state_
);
/**
* extcon_set_cable_state() - Set the status of a specific cable.
* @edev: the extcon device that has the cable.
* @cable_name: cable name.
* @cable_state: the new cable status. The default semantics is
* true: attached / false: detached.
*
* Note that this is slower than extcon_set_cable_state_.
*/
int
extcon_set_cable_state
(
struct
extcon_dev
*
edev
,
const
char
*
cable_name
,
bool
cable_state
)
{
int
id
;
id
=
find_cable_id_by_name
(
edev
,
cable_name
);
if
(
id
<
0
)
return
id
;
return
extcon_set_cable_state_
(
edev
,
id
,
cable_state
);
}
EXPORT_SYMBOL_GPL
(
extcon_set_cable_state
);
/**
* extcon_get_extcon_dev() - Get the extcon device instance from the name
* @extcon_name: The extcon name provided with extcon_dev_register()
...
...
@@ -466,105 +393,6 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
}
EXPORT_SYMBOL_GPL
(
extcon_get_extcon_dev
);
/**
* extcon_register_interest() - Register a notifier for a state change of a
* specific cable, not an entier set of cables of a
* extcon device.
* @obj: an empty extcon_specific_cable_nb object to be returned.
* @extcon_name: the name of extcon device.
* if NULL, extcon_register_interest will register
* every cable with the target cable_name given.
* @cable_name: the target cable name.
* @nb: the notifier block to get notified.
*
* Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
* the struct for you.
*
* extcon_register_interest is a helper function for those who want to get
* notification for a single specific cable's status change. If a user wants
* to get notification for any changes of all cables of a extcon device,
* he/she should use the general extcon_register_notifier().
*
* Note that the second parameter given to the callback of nb (val) is
* "old_state", not the current state. The current state can be retrieved
* by looking at the third pameter (edev pointer)'s state value.
*/
int
extcon_register_interest
(
struct
extcon_specific_cable_nb
*
obj
,
const
char
*
extcon_name
,
const
char
*
cable_name
,
struct
notifier_block
*
nb
)
{
unsigned
long
flags
;
int
ret
;
if
(
!
obj
||
!
cable_name
||
!
nb
)
return
-
EINVAL
;
if
(
extcon_name
)
{
obj
->
edev
=
extcon_get_extcon_dev
(
extcon_name
);
if
(
!
obj
->
edev
)
return
-
ENODEV
;
obj
->
cable_index
=
find_cable_index_by_name
(
obj
->
edev
,
cable_name
);
if
(
obj
->
cable_index
<
0
)
return
obj
->
cable_index
;
obj
->
user_nb
=
nb
;
spin_lock_irqsave
(
&
obj
->
edev
->
lock
,
flags
);
ret
=
raw_notifier_chain_register
(
&
obj
->
edev
->
nh
[
obj
->
cable_index
],
obj
->
user_nb
);
spin_unlock_irqrestore
(
&
obj
->
edev
->
lock
,
flags
);
}
else
{
struct
class_dev_iter
iter
;
struct
extcon_dev
*
extd
;
struct
device
*
dev
;
if
(
!
extcon_class
)
return
-
ENODEV
;
class_dev_iter_init
(
&
iter
,
extcon_class
,
NULL
,
NULL
);
while
((
dev
=
class_dev_iter_next
(
&
iter
)))
{
extd
=
dev_get_drvdata
(
dev
);
if
(
find_cable_index_by_name
(
extd
,
cable_name
)
<
0
)
continue
;
class_dev_iter_exit
(
&
iter
);
return
extcon_register_interest
(
obj
,
extd
->
name
,
cable_name
,
nb
);
}
ret
=
-
ENODEV
;
}
return
ret
;
}
EXPORT_SYMBOL_GPL
(
extcon_register_interest
);
/**
* extcon_unregister_interest() - Unregister the notifier registered by
* extcon_register_interest().
* @obj: the extcon_specific_cable_nb object returned by
* extcon_register_interest().
*/
int
extcon_unregister_interest
(
struct
extcon_specific_cable_nb
*
obj
)
{
unsigned
long
flags
;
int
ret
;
if
(
!
obj
)
return
-
EINVAL
;
spin_lock_irqsave
(
&
obj
->
edev
->
lock
,
flags
);
ret
=
raw_notifier_chain_unregister
(
&
obj
->
edev
->
nh
[
obj
->
cable_index
],
obj
->
user_nb
);
spin_unlock_irqrestore
(
&
obj
->
edev
->
lock
,
flags
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
extcon_unregister_interest
);
/**
* extcon_register_notifier() - Register a notifiee to get notified by
* any attach status changes from the extcon.
...
...
@@ -582,14 +410,33 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
unsigned
long
flags
;
int
ret
,
idx
;
if
(
!
edev
||
!
nb
)
if
(
!
nb
)
return
-
EINVAL
;
idx
=
find_cable_index_by_id
(
edev
,
id
);
if
(
edev
)
{
idx
=
find_cable_index_by_id
(
edev
,
id
);
spin_lock_irqsave
(
&
edev
->
lock
,
flags
);
ret
=
raw_notifier_chain_register
(
&
edev
->
nh
[
idx
],
nb
);
spin_unlock_irqrestore
(
&
edev
->
lock
,
flags
);
spin_lock_irqsave
(
&
edev
->
lock
,
flags
);
ret
=
raw_notifier_chain_register
(
&
edev
->
nh
[
idx
],
nb
);
spin_unlock_irqrestore
(
&
edev
->
lock
,
flags
);
}
else
{
struct
extcon_dev
*
extd
;
mutex_lock
(
&
extcon_dev_list_lock
);
list_for_each_entry
(
extd
,
&
extcon_dev_list
,
entry
)
{
idx
=
find_cable_index_by_id
(
extd
,
id
);
if
(
idx
>=
0
)
break
;
}
mutex_unlock
(
&
extcon_dev_list_lock
);
if
(
idx
>=
0
)
{
edev
=
extd
;
return
extcon_register_notifier
(
extd
,
id
,
nb
);
}
else
{
ret
=
-
ENODEV
;
}
}
return
ret
;
}
...
...
drivers/power/axp288_charger.c
View file @
411ef2be
...
...
@@ -129,10 +129,6 @@
#define AXP288_EXTCON_DEV_NAME "axp288_extcon"
#define AXP288_EXTCON_SLOW_CHARGER "SLOW-CHARGER"
#define AXP288_EXTCON_DOWNSTREAM_CHARGER "CHARGE-DOWNSTREAM"
#define AXP288_EXTCON_FAST_CHARGER "FAST-CHARGER"
enum
{
VBUS_OV_IRQ
=
0
,
CHARGE_DONE_IRQ
,
...
...
@@ -158,7 +154,7 @@ struct axp288_chrg_info {
/* OTG/Host mode */
struct
{
struct
work_struct
work
;
struct
extcon_
specific_cable_nb
cable
;
struct
extcon_
dev
*
cable
;
struct
notifier_block
id_nb
;
bool
id_short
;
}
otg
;
...
...
@@ -586,17 +582,15 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work)
bool
old_connected
=
info
->
cable
.
connected
;
/* Determine cable/charger type */
if
(
extcon_get_cable_state
(
edev
,
AXP288_EXTCON_SLOW_CHARGER
)
>
0
)
{
if
(
extcon_get_cable_state
_
(
edev
,
EXTCON_CHG_USB_SDP
)
>
0
)
{
dev_dbg
(
&
info
->
pdev
->
dev
,
"USB SDP charger is connected"
);
info
->
cable
.
connected
=
true
;
info
->
cable
.
chg_type
=
POWER_SUPPLY_TYPE_USB
;
}
else
if
(
extcon_get_cable_state
(
edev
,
AXP288_EXTCON_DOWNSTREAM_CHARGER
)
>
0
)
{
}
else
if
(
extcon_get_cable_state_
(
edev
,
EXTCON_CHG_USB_CDP
)
>
0
)
{
dev_dbg
(
&
info
->
pdev
->
dev
,
"USB CDP charger is connected"
);
info
->
cable
.
connected
=
true
;
info
->
cable
.
chg_type
=
POWER_SUPPLY_TYPE_USB_CDP
;
}
else
if
(
extcon_get_cable_state
(
edev
,
AXP288_EXTCON_FAST_CHARGER
)
>
0
)
{
}
else
if
(
extcon_get_cable_state_
(
edev
,
EXTCON_CHG_USB_DCP
)
>
0
)
{
dev_dbg
(
&
info
->
pdev
->
dev
,
"USB DCP charger is connected"
);
info
->
cable
.
connected
=
true
;
info
->
cable
.
chg_type
=
POWER_SUPPLY_TYPE_USB_DCP
;
...
...
@@ -692,8 +686,8 @@ static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
{
struct
axp288_chrg_info
*
info
=
container_of
(
nb
,
struct
axp288_chrg_info
,
otg
.
id_nb
);
struct
extcon_dev
*
edev
=
param
;
int
usb_host
=
extcon_get_cable_state
(
edev
,
"USB-Host"
);
struct
extcon_dev
*
edev
=
info
->
otg
.
cable
;
int
usb_host
=
extcon_get_cable_state
_
(
edev
,
EXTCON_USB_HOST
);
dev_dbg
(
&
info
->
pdev
->
dev
,
"external connector USB-Host is %s
\n
"
,
usb_host
?
"attached"
:
"detached"
);
...
...
@@ -848,10 +842,33 @@ static int axp288_charger_probe(struct platform_device *pdev)
/* Register for extcon notification */
INIT_WORK
(
&
info
->
cable
.
work
,
axp288_charger_extcon_evt_worker
);
info
->
cable
.
nb
.
notifier_call
=
axp288_charger_handle_cable_evt
;
ret
=
extcon_register_notifier
(
info
->
cable
.
edev
,
EXTCON_NONE
,
&
info
->
cable
.
nb
);
ret
=
extcon_register_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_SDP
,
&
info
->
cable
.
nb
);
if
(
ret
)
{
dev_err
(
&
info
->
pdev
->
dev
,
"failed to register extcon notifier for SDP %d
\n
"
,
ret
);
return
ret
;
}
ret
=
extcon_register_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_CDP
,
&
info
->
cable
.
nb
);
if
(
ret
)
{
dev_err
(
&
info
->
pdev
->
dev
,
"failed to register extcon notifier for CDP %d
\n
"
,
ret
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_SDP
,
&
info
->
cable
.
nb
);
return
ret
;
}
ret
=
extcon_register_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_DCP
,
&
info
->
cable
.
nb
);
if
(
ret
)
{
dev_err
(
&
info
->
pdev
->
dev
,
"failed to register extcon notifier %d
\n
"
,
ret
);
"failed to register extcon notifier for DCP %d
\n
"
,
ret
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_SDP
,
&
info
->
cable
.
nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_CDP
,
&
info
->
cable
.
nb
);
return
ret
;
}
...
...
@@ -871,14 +888,14 @@ static int axp288_charger_probe(struct platform_device *pdev)
/* Register for OTG notification */
INIT_WORK
(
&
info
->
otg
.
work
,
axp288_charger_otg_evt_worker
);
info
->
otg
.
id_nb
.
notifier_call
=
axp288_charger_handle_otg_evt
;
ret
=
extcon_register_
interest
(
&
info
->
otg
.
cable
,
NULL
,
"USB-Host"
,
ret
=
extcon_register_
notifier
(
info
->
otg
.
cable
,
EXTCON_USB_HOST
,
&
info
->
otg
.
id_nb
);
if
(
ret
)
dev_warn
(
&
pdev
->
dev
,
"failed to register otg notifier
\n
"
);
if
(
info
->
otg
.
cable
.
edev
)
info
->
otg
.
id_short
=
extcon_get_cable_state
(
info
->
otg
.
cable
.
edev
,
"USB-Host"
);
if
(
info
->
otg
.
cable
)
info
->
otg
.
id_short
=
extcon_get_cable_state
_
(
info
->
otg
.
cable
,
EXTCON_USB_HOST
);
/* Register charger interrupts */
for
(
i
=
0
;
i
<
CHRG_INTR_END
;
i
++
)
{
...
...
@@ -905,11 +922,17 @@ static int axp288_charger_probe(struct platform_device *pdev)
return
0
;
intr_reg_failed:
if
(
info
->
otg
.
cable
.
edev
)
extcon_unregister_interest
(
&
info
->
otg
.
cable
);
if
(
info
->
otg
.
cable
)
extcon_unregister_notifier
(
info
->
otg
.
cable
,
EXTCON_USB_HOST
,
&
info
->
otg
.
id_nb
);
power_supply_unregister
(
info
->
psy_usb
);
psy_reg_failed:
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_NONE
,
&
info
->
cable
.
nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_SDP
,
&
info
->
cable
.
nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_CDP
,
&
info
->
cable
.
nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_DCP
,
&
info
->
cable
.
nb
);
return
ret
;
}
...
...
@@ -917,10 +940,16 @@ static int axp288_charger_remove(struct platform_device *pdev)
{
struct
axp288_chrg_info
*
info
=
dev_get_drvdata
(
&
pdev
->
dev
);
if
(
info
->
otg
.
cable
.
edev
)
extcon_unregister_interest
(
&
info
->
otg
.
cable
);
if
(
info
->
otg
.
cable
)
extcon_unregister_notifier
(
info
->
otg
.
cable
,
EXTCON_USB_HOST
,
&
info
->
otg
.
id_nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_NONE
,
&
info
->
cable
.
nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_SDP
,
&
info
->
cable
.
nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_CDP
,
&
info
->
cable
.
nb
);
extcon_unregister_notifier
(
info
->
cable
.
edev
,
EXTCON_CHG_USB_DCP
,
&
info
->
cable
.
nb
);
power_supply_unregister
(
info
->
psy_usb
);
return
0
;
...
...
include/linux/extcon.h
View file @
411ef2be
...
...
@@ -146,22 +146,6 @@ struct extcon_cable {
struct
attribute
*
attrs
[
3
];
/* to be fed to attr_g.attrs */
};
/**
* struct extcon_specific_cable_nb - An internal data for
* extcon_register_interest().
* @user_nb: user provided notifier block for events from
* a specific cable.
* @cable_index: the target cable.
* @edev: the target extcon device.
* @previous_value: the saved previous event value.
*/
struct
extcon_specific_cable_nb
{
struct
notifier_block
*
user_nb
;
int
cable_index
;
struct
extcon_dev
*
edev
;
unsigned
long
previous_value
;
};
#if IS_ENABLED(CONFIG_EXTCON)
/*
...
...
@@ -207,23 +191,6 @@ extern int extcon_get_cable_state_(struct extcon_dev *edev, unsigned int id);
extern
int
extcon_set_cable_state_
(
struct
extcon_dev
*
edev
,
unsigned
int
id
,
bool
cable_state
);
extern
int
extcon_get_cable_state
(
struct
extcon_dev
*
edev
,
const
char
*
cable_name
);
extern
int
extcon_set_cable_state
(
struct
extcon_dev
*
edev
,
const
char
*
cable_name
,
bool
cable_state
);
/*
* Following APIs are for notifiees (those who want to be notified)
* to register a callback for events from a specific cable of the extcon.
* Notifiees are the connected device drivers wanting to get notified by
* a specific external port of a connection device.
*/
extern
int
extcon_register_interest
(
struct
extcon_specific_cable_nb
*
obj
,
const
char
*
extcon_name
,
const
char
*
cable_name
,
struct
notifier_block
*
nb
);
extern
int
extcon_unregister_interest
(
struct
extcon_specific_cable_nb
*
nb
);
/*
* Following APIs are to monitor every action of a notifier.
* Registrar gets notified for every external port of a connection device.
...
...
@@ -246,6 +213,7 @@ extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
/* Following API to get information of extcon device */
extern
const
char
*
extcon_get_edev_name
(
struct
extcon_dev
*
edev
);
#else
/* CONFIG_EXTCON */
static
inline
int
extcon_dev_register
(
struct
extcon_dev
*
edev
)
{
...
...
@@ -306,18 +274,6 @@ static inline int extcon_set_cable_state_(struct extcon_dev *edev,
return
0
;
}
static
inline
int
extcon_get_cable_state
(
struct
extcon_dev
*
edev
,
const
char
*
cable_name
)
{
return
0
;
}
static
inline
int
extcon_set_cable_state
(
struct
extcon_dev
*
edev
,
const
char
*
cable_name
,
int
state
)
{
return
0
;
}
static
inline
struct
extcon_dev
*
extcon_get_extcon_dev
(
const
char
*
extcon_name
)
{
return
NULL
;
...
...
@@ -337,24 +293,34 @@ static inline int extcon_unregister_notifier(struct extcon_dev *edev,
return
0
;
}
static
inline
int
extcon_register_interest
(
struct
extcon_specific_cable_nb
*
obj
,
const
char
*
extcon_name
,
const
char
*
cable_name
,
struct
notifier_block
*
nb
)
static
inline
struct
extcon_dev
*
extcon_get_edev_by_phandle
(
struct
device
*
dev
,
int
index
)
{
return
0
;
return
ERR_PTR
(
-
ENODEV
)
;
}
#endif
/* CONFIG_EXTCON */
static
inline
int
extcon_unregister_interest
(
struct
extcon_specific_cable_nb
*
obj
)
/*
* Following structure and API are deprecated. EXTCON remains the function
* definition to prevent the build break.
*/
struct
extcon_specific_cable_nb
{
struct
notifier_block
*
user_nb
;
int
cable_index
;
struct
extcon_dev
*
edev
;
unsigned
long
previous_value
;
};
static
inline
int
extcon_register_interest
(
struct
extcon_specific_cable_nb
*
obj
,
const
char
*
extcon_name
,
const
char
*
cable_name
,
struct
notifier_block
*
nb
)
{
return
0
;
return
-
EINVAL
;
}
static
inline
struct
extcon_dev
*
extcon_get_edev_by_phandle
(
struct
device
*
dev
,
int
index
)
static
inline
int
extcon_unregister_interest
(
struct
extcon_specific_cable_nb
*
obj
)
{
return
ERR_PTR
(
-
ENODEV
)
;
return
-
EINVAL
;
}
#endif
/* CONFIG_EXTCON */
#endif
/* __LINUX_EXTCON_H__ */
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