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
d61b814a
Commit
d61b814a
authored
Jan 03, 2018
by
Chanwoo Choi
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ib-extcon-mfd-4.16' into extcon-next
parents
447641eb
9bf317e9
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
159 additions
and
44 deletions
+159
-44
drivers/extcon/extcon-axp288.c
drivers/extcon/extcon-axp288.c
+4
-35
drivers/extcon/extcon-usbc-cros-ec.c
drivers/extcon/extcon-usbc-cros-ec.c
+138
-4
include/linux/mfd/axp20x.h
include/linux/mfd/axp20x.h
+0
-5
include/linux/mfd/cros_ec_commands.h
include/linux/mfd/cros_ec_commands.h
+17
-0
No files found.
drivers/extcon/extcon-axp288.c
View file @
d61b814a
...
...
@@ -24,8 +24,6 @@
#include <linux/notifier.h>
#include <linux/extcon-provider.h>
#include <linux/regmap.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/mfd/axp20x.h>
/* Power source status register */
...
...
@@ -79,11 +77,6 @@ enum axp288_extcon_reg {
AXP288_BC_DET_STAT_REG
=
0x2f
,
};
enum
axp288_mux_select
{
EXTCON_GPIO_MUX_SEL_PMIC
=
0
,
EXTCON_GPIO_MUX_SEL_SOC
,
};
enum
axp288_extcon_irq
{
VBUS_FALLING_IRQ
=
0
,
VBUS_RISING_IRQ
,
...
...
@@ -104,10 +97,8 @@ struct axp288_extcon_info {
struct
device
*
dev
;
struct
regmap
*
regmap
;
struct
regmap_irq_chip_data
*
regmap_irqc
;
struct
gpio_desc
*
gpio_mux_cntl
;
int
irq
[
EXTCON_IRQ_END
];
struct
extcon_dev
*
edev
;
struct
notifier_block
extcon_nb
;
unsigned
int
previous_cable
;
};
...
...
@@ -197,15 +188,6 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
}
no_vbus:
/*
* If VBUS is absent Connect D+/D- lines to PMIC for BC
* detection. Else connect them to SOC for USB communication.
*/
if
(
info
->
gpio_mux_cntl
)
gpiod_set_value
(
info
->
gpio_mux_cntl
,
vbus_attach
?
EXTCON_GPIO_MUX_SEL_SOC
:
EXTCON_GPIO_MUX_SEL_PMIC
);
extcon_set_state_sync
(
info
->
edev
,
info
->
previous_cable
,
false
);
if
(
info
->
previous_cable
==
EXTCON_CHG_USB_SDP
)
extcon_set_state_sync
(
info
->
edev
,
EXTCON_USB
,
false
);
...
...
@@ -253,8 +235,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
{
struct
axp288_extcon_info
*
info
;
struct
axp20x_dev
*
axp20x
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
struct
axp288_extcon_pdata
*
pdata
=
pdev
->
dev
.
platform_data
;
int
ret
,
i
,
pirq
,
gpio
;
int
ret
,
i
,
pirq
;
info
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
info
),
GFP_KERNEL
);
if
(
!
info
)
...
...
@@ -264,8 +245,6 @@ static int axp288_extcon_probe(struct platform_device *pdev)
info
->
regmap
=
axp20x
->
regmap
;
info
->
regmap_irqc
=
axp20x
->
regmap_irqc
;
info
->
previous_cable
=
EXTCON_NONE
;
if
(
pdata
)
info
->
gpio_mux_cntl
=
pdata
->
gpio_mux_cntl
;
platform_set_drvdata
(
pdev
,
info
);
...
...
@@ -286,21 +265,11 @@ static int axp288_extcon_probe(struct platform_device *pdev)
return
ret
;
}
/* Set up gpio control for USB Mux */
if
(
info
->
gpio_mux_cntl
)
{
gpio
=
desc_to_gpio
(
info
->
gpio_mux_cntl
);
ret
=
devm_gpio_request
(
&
pdev
->
dev
,
gpio
,
"USB_MUX"
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request the gpio=%d
\n
"
,
gpio
);
return
ret
;
}
gpiod_direction_output
(
info
->
gpio_mux_cntl
,
EXTCON_GPIO_MUX_SEL_PMIC
);
}
for
(
i
=
0
;
i
<
EXTCON_IRQ_END
;
i
++
)
{
pirq
=
platform_get_irq
(
pdev
,
i
);
if
(
pirq
<
0
)
return
pirq
;
info
->
irq
[
i
]
=
regmap_irq_get_virq
(
info
->
regmap_irqc
,
pirq
);
if
(
info
->
irq
[
i
]
<
0
)
{
dev_err
(
&
pdev
->
dev
,
...
...
drivers/extcon/extcon-usbc-cros-ec.c
View file @
d61b814a
...
...
@@ -34,16 +34,26 @@ struct cros_ec_extcon_info {
struct
notifier_block
notifier
;
unsigned
int
dr
;
/* data role */
bool
pr
;
/* power role (true if VBUS enabled) */
bool
dp
;
/* DisplayPort enabled */
bool
mux
;
/* SuperSpeed (usb3) enabled */
unsigned
int
power_type
;
};
static
const
unsigned
int
usb_type_c_cable
[]
=
{
EXTCON_USB
,
EXTCON_USB_HOST
,
EXTCON_DISP_DP
,
EXTCON_NONE
,
};
enum
usb_data_roles
{
DR_NONE
,
DR_HOST
,
DR_DEVICE
,
};
/**
* cros_ec_pd_command() - Send a command to the EC.
* @info: pointer to struct cros_ec_extcon_info
...
...
@@ -150,6 +160,7 @@ static int cros_ec_usb_get_role(struct cros_ec_extcon_info *info,
pd_control
.
port
=
info
->
port_id
;
pd_control
.
role
=
USB_PD_CTRL_ROLE_NO_CHANGE
;
pd_control
.
mux
=
USB_PD_CTRL_MUX_NO_CHANGE
;
pd_control
.
swap
=
USB_PD_CTRL_SWAP_NONE
;
ret
=
cros_ec_pd_command
(
info
,
EC_CMD_USB_PD_CONTROL
,
1
,
&
pd_control
,
sizeof
(
pd_control
),
&
resp
,
sizeof
(
resp
));
...
...
@@ -183,11 +194,72 @@ static int cros_ec_pd_get_num_ports(struct cros_ec_extcon_info *info)
return
resp
.
num_ports
;
}
static
const
char
*
cros_ec_usb_role_string
(
unsigned
int
role
)
{
return
role
==
DR_NONE
?
"DISCONNECTED"
:
(
role
==
DR_HOST
?
"DFP"
:
"UFP"
);
}
static
const
char
*
cros_ec_usb_power_type_string
(
unsigned
int
type
)
{
switch
(
type
)
{
case
USB_CHG_TYPE_NONE
:
return
"USB_CHG_TYPE_NONE"
;
case
USB_CHG_TYPE_PD
:
return
"USB_CHG_TYPE_PD"
;
case
USB_CHG_TYPE_PROPRIETARY
:
return
"USB_CHG_TYPE_PROPRIETARY"
;
case
USB_CHG_TYPE_C
:
return
"USB_CHG_TYPE_C"
;
case
USB_CHG_TYPE_BC12_DCP
:
return
"USB_CHG_TYPE_BC12_DCP"
;
case
USB_CHG_TYPE_BC12_CDP
:
return
"USB_CHG_TYPE_BC12_CDP"
;
case
USB_CHG_TYPE_BC12_SDP
:
return
"USB_CHG_TYPE_BC12_SDP"
;
case
USB_CHG_TYPE_OTHER
:
return
"USB_CHG_TYPE_OTHER"
;
case
USB_CHG_TYPE_VBUS
:
return
"USB_CHG_TYPE_VBUS"
;
case
USB_CHG_TYPE_UNKNOWN
:
return
"USB_CHG_TYPE_UNKNOWN"
;
default:
return
"USB_CHG_TYPE_UNKNOWN"
;
}
}
static
bool
cros_ec_usb_power_type_is_wall_wart
(
unsigned
int
type
,
unsigned
int
role
)
{
switch
(
type
)
{
/* FIXME : Guppy, Donnettes, and other chargers will be miscategorized
* because they identify with USB_CHG_TYPE_C, but we can't return true
* here from that code because that breaks Suzy-Q and other kinds of
* USB Type-C cables and peripherals.
*/
case
USB_CHG_TYPE_PROPRIETARY
:
case
USB_CHG_TYPE_BC12_DCP
:
return
true
;
case
USB_CHG_TYPE_PD
:
case
USB_CHG_TYPE_C
:
case
USB_CHG_TYPE_BC12_CDP
:
case
USB_CHG_TYPE_BC12_SDP
:
case
USB_CHG_TYPE_OTHER
:
case
USB_CHG_TYPE_VBUS
:
case
USB_CHG_TYPE_UNKNOWN
:
case
USB_CHG_TYPE_NONE
:
default:
return
false
;
}
}
static
int
extcon_cros_ec_detect_cable
(
struct
cros_ec_extcon_info
*
info
,
bool
force
)
{
struct
device
*
dev
=
info
->
dev
;
int
role
,
power_type
;
unsigned
int
dr
=
DR_NONE
;
bool
pr
=
false
;
bool
polarity
=
false
;
bool
dp
=
false
;
bool
mux
=
false
;
...
...
@@ -206,9 +278,12 @@ static int extcon_cros_ec_detect_cable(struct cros_ec_extcon_info *info,
dev_err
(
dev
,
"failed getting role err = %d
\n
"
,
role
);
return
role
;
}
dev_dbg
(
dev
,
"disconnected
\n
"
);
}
else
{
int
pd_mux_state
;
dr
=
(
role
&
PD_CTRL_RESP_ROLE_DATA
)
?
DR_HOST
:
DR_DEVICE
;
pr
=
(
role
&
PD_CTRL_RESP_ROLE_POWER
);
pd_mux_state
=
cros_ec_usb_get_pd_mux_state
(
info
);
if
(
pd_mux_state
<
0
)
pd_mux_state
=
USB_PD_MUX_USB_ENABLED
;
...
...
@@ -216,20 +291,62 @@ static int extcon_cros_ec_detect_cable(struct cros_ec_extcon_info *info,
dp
=
pd_mux_state
&
USB_PD_MUX_DP_ENABLED
;
mux
=
pd_mux_state
&
USB_PD_MUX_USB_ENABLED
;
hpd
=
pd_mux_state
&
USB_PD_MUX_HPD_IRQ
;
}
if
(
force
||
info
->
dp
!=
dp
||
info
->
mux
!=
mux
||
info
->
power_type
!=
power_type
)
{
dev_dbg
(
dev
,
"connected role 0x%x pwr type %d dr %d pr %d pol %d mux %d dp %d hpd %d
\n
"
,
role
,
power_type
,
dr
,
pr
,
polarity
,
mux
,
dp
,
hpd
);
}
/*
* When there is no USB host (e.g. USB PD charger),
* we are not really a UFP for the AP.
*/
if
(
dr
==
DR_DEVICE
&&
cros_ec_usb_power_type_is_wall_wart
(
power_type
,
role
))
dr
=
DR_NONE
;
if
(
force
||
info
->
dr
!=
dr
||
info
->
pr
!=
pr
||
info
->
dp
!=
dp
||
info
->
mux
!=
mux
||
info
->
power_type
!=
power_type
)
{
bool
host_connected
=
false
,
device_connected
=
false
;
dev_dbg
(
dev
,
"Type/Role switch! type = %s role = %s
\n
"
,
cros_ec_usb_power_type_string
(
power_type
),
cros_ec_usb_role_string
(
dr
));
info
->
dr
=
dr
;
info
->
pr
=
pr
;
info
->
dp
=
dp
;
info
->
mux
=
mux
;
info
->
power_type
=
power_type
;
extcon_set_state
(
info
->
edev
,
EXTCON_DISP_DP
,
dp
);
if
(
dr
==
DR_DEVICE
)
device_connected
=
true
;
else
if
(
dr
==
DR_HOST
)
host_connected
=
true
;
extcon_set_state
(
info
->
edev
,
EXTCON_USB
,
device_connected
);
extcon_set_state
(
info
->
edev
,
EXTCON_USB_HOST
,
host_connected
);
extcon_set_state
(
info
->
edev
,
EXTCON_DISP_DP
,
dp
);
extcon_set_property
(
info
->
edev
,
EXTCON_USB
,
EXTCON_PROP_USB_VBUS
,
(
union
extcon_property_value
)(
int
)
pr
);
extcon_set_property
(
info
->
edev
,
EXTCON_USB_HOST
,
EXTCON_PROP_USB_VBUS
,
(
union
extcon_property_value
)(
int
)
pr
);
extcon_set_property
(
info
->
edev
,
EXTCON_USB
,
EXTCON_PROP_USB_TYPEC_POLARITY
,
(
union
extcon_property_value
)(
int
)
polarity
);
extcon_set_property
(
info
->
edev
,
EXTCON_USB_HOST
,
EXTCON_PROP_USB_TYPEC_POLARITY
,
(
union
extcon_property_value
)(
int
)
polarity
);
extcon_set_property
(
info
->
edev
,
EXTCON_DISP_DP
,
EXTCON_PROP_USB_TYPEC_POLARITY
,
(
union
extcon_property_value
)(
int
)
polarity
);
extcon_set_property
(
info
->
edev
,
EXTCON_USB
,
EXTCON_PROP_USB_SS
,
(
union
extcon_property_value
)(
int
)
mux
);
extcon_set_property
(
info
->
edev
,
EXTCON_USB_HOST
,
EXTCON_PROP_USB_SS
,
(
union
extcon_property_value
)(
int
)
mux
);
extcon_set_property
(
info
->
edev
,
EXTCON_DISP_DP
,
EXTCON_PROP_USB_SS
,
(
union
extcon_property_value
)(
int
)
mux
);
...
...
@@ -237,6 +354,8 @@ static int extcon_cros_ec_detect_cable(struct cros_ec_extcon_info *info,
EXTCON_PROP_DISP_HPD
,
(
union
extcon_property_value
)(
int
)
hpd
);
extcon_sync
(
info
->
edev
,
EXTCON_USB
);
extcon_sync
(
info
->
edev
,
EXTCON_USB_HOST
);
extcon_sync
(
info
->
edev
,
EXTCON_DISP_DP
);
}
else
if
(
hpd
)
{
...
...
@@ -322,13 +441,28 @@ static int extcon_cros_ec_probe(struct platform_device *pdev)
return
ret
;
}
extcon_set_property_capability
(
info
->
edev
,
EXTCON_USB
,
EXTCON_PROP_USB_VBUS
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_USB_HOST
,
EXTCON_PROP_USB_VBUS
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_USB
,
EXTCON_PROP_USB_TYPEC_POLARITY
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_USB_HOST
,
EXTCON_PROP_USB_TYPEC_POLARITY
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_DISP_DP
,
EXTCON_PROP_USB_TYPEC_POLARITY
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_USB
,
EXTCON_PROP_USB_SS
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_USB_HOST
,
EXTCON_PROP_USB_SS
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_DISP_DP
,
EXTCON_PROP_USB_SS
);
extcon_set_property_capability
(
info
->
edev
,
EXTCON_DISP_DP
,
EXTCON_PROP_DISP_HPD
);
info
->
dr
=
DR_NONE
;
info
->
pr
=
false
;
platform_set_drvdata
(
pdev
,
info
);
/* Get PD events from the EC */
...
...
include/linux/mfd/axp20x.h
View file @
d61b814a
...
...
@@ -645,11 +645,6 @@ struct axp20x_dev {
const
struct
regmap_irq_chip
*
regmap_irq_chip
;
};
struct
axp288_extcon_pdata
{
/* GPIO pin control to switch D+/D- lines b/w PMIC and SOC */
struct
gpio_desc
*
gpio_mux_cntl
;
};
/* generic helper function for reading 9-16 bit wide regs */
static
inline
int
axp20x_read_variable_width
(
struct
regmap
*
regmap
,
unsigned
int
reg
,
unsigned
int
width
)
...
...
include/linux/mfd/cros_ec_commands.h
View file @
d61b814a
...
...
@@ -2904,16 +2904,33 @@ enum usb_pd_control_mux {
USB_PD_CTRL_MUX_AUTO
=
5
,
};
enum
usb_pd_control_swap
{
USB_PD_CTRL_SWAP_NONE
=
0
,
USB_PD_CTRL_SWAP_DATA
=
1
,
USB_PD_CTRL_SWAP_POWER
=
2
,
USB_PD_CTRL_SWAP_VCONN
=
3
,
USB_PD_CTRL_SWAP_COUNT
};
struct
ec_params_usb_pd_control
{
uint8_t
port
;
uint8_t
role
;
uint8_t
mux
;
uint8_t
swap
;
}
__packed
;
#define PD_CTRL_RESP_ENABLED_COMMS (1 << 0)
/* Communication enabled */
#define PD_CTRL_RESP_ENABLED_CONNECTED (1 << 1)
/* Device connected */
#define PD_CTRL_RESP_ENABLED_PD_CAPABLE (1 << 2)
/* Partner is PD capable */
#define PD_CTRL_RESP_ROLE_POWER BIT(0)
/* 0=SNK/1=SRC */
#define PD_CTRL_RESP_ROLE_DATA BIT(1)
/* 0=UFP/1=DFP */
#define PD_CTRL_RESP_ROLE_VCONN BIT(2)
/* Vconn status */
#define PD_CTRL_RESP_ROLE_DR_POWER BIT(3)
/* Partner is dualrole power */
#define PD_CTRL_RESP_ROLE_DR_DATA BIT(4)
/* Partner is dualrole data */
#define PD_CTRL_RESP_ROLE_USB_COMM BIT(5)
/* Partner USB comm capable */
#define PD_CTRL_RESP_ROLE_EXT_POWERED BIT(6)
/* Partner externally powerd */
struct
ec_response_usb_pd_control_v1
{
uint8_t
enabled
;
uint8_t
role
;
...
...
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