hd3ss3220
dev_err(hd3ss3220->dev, "bad port type: %d\n", type);
err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
dev_err(hd3ss3220->dev, "Failed to disable port for mode change: %d\n", err);
err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
dev_err(hd3ss3220->dev, "Failed to change mode: %d\n", err);
regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
dev_err(hd3ss3220->dev, "Failed to re-enable port after mode change: %d\n", err);
static int hd3ss3220_set_source_pref(struct hd3ss3220 *hd3ss3220, int prefer_role)
dev_err(hd3ss3220->dev, "bad role preference: %d\n", prefer_role);
return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
static enum usb_role hd3ss3220_get_attached_state(struct hd3ss3220 *hd3ss3220)
ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL,
struct hd3ss3220 *hd3ss3220 = typec_get_drvdata(port);
return hd3ss3220_set_source_pref(hd3ss3220, role);
struct hd3ss3220 *hd3ss3220 = typec_get_drvdata(port);
return hd3ss3220_set_port_type(hd3ss3220, type);
static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on)
if (regulator_is_enabled(hd3ss3220->vbus) == on)
ret = regulator_enable(hd3ss3220->vbus);
ret = regulator_disable(hd3ss3220->vbus);
dev_err(hd3ss3220->dev,
static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220)
enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
usb_role_switch_set_role(hd3ss3220->role_sw, role_state);
typec_set_data_role(hd3ss3220->port, TYPEC_HOST);
typec_set_data_role(hd3ss3220->port, TYPEC_DEVICE);
if (hd3ss3220->vbus && !hd3ss3220->id_gpiod)
hd3ss3220_regulator_control(hd3ss3220, role_state == USB_ROLE_HOST);
hd3ss3220->role_state = role_state;
struct hd3ss3220 *hd3ss3220 = container_of(delayed_work,
struct hd3ss3220,
enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
if (hd3ss3220->role_state != role_state)
hd3ss3220_set_role(hd3ss3220);
schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
static irqreturn_t hd3ss3220_irq(struct hd3ss3220 *hd3ss3220)
hd3ss3220_set_role(hd3ss3220);
err = regmap_write_bits(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL,
struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
return hd3ss3220_irq(hd3ss3220);
static int hd3ss3220_configure_power_opmode(struct hd3ss3220 *hd3ss3220,
return hd3ss3220_set_power_opmode(hd3ss3220, power_opmode);
static int hd3ss3220_configure_port_type(struct hd3ss3220 *hd3ss3220,
return hd3ss3220_set_port_type(hd3ss3220, cap->type);
static int hd3ss3220_configure_source_pref(struct hd3ss3220 *hd3ss3220,
return hd3ss3220_set_source_pref(hd3ss3220, cap->prefer_role);
struct hd3ss3220 *hd3ss3220 = dev_id;
id = gpiod_get_value_cansleep(hd3ss3220->id_gpiod);
hd3ss3220_regulator_control(hd3ss3220, !id);
struct hd3ss3220 *hd3ss3220;
hd3ss3220 = devm_kzalloc(&client->dev, sizeof(struct hd3ss3220),
if (!hd3ss3220)
i2c_set_clientdata(client, hd3ss3220);
hd3ss3220->dev = &client->dev;
hd3ss3220->regmap = devm_regmap_init_i2c(client, &config);
if (IS_ERR(hd3ss3220->regmap))
return PTR_ERR(hd3ss3220->regmap);
connector = device_get_named_child_node(hd3ss3220->dev, "connector");
hd3ss3220->role_sw = fwnode_usb_role_switch_get(connector);
ep = fwnode_graph_get_next_endpoint(dev_fwnode(hd3ss3220->dev), NULL);
hd3ss3220->role_sw = usb_role_switch_get(hd3ss3220->dev);
if (IS_ERR(hd3ss3220->role_sw)) {
ret = PTR_ERR(hd3ss3220->role_sw);
vbus = devm_of_regulator_get_optional(hd3ss3220->dev,
dev_err(hd3ss3220->dev, "failed to get vbus: %d", ret);
hd3ss3220->vbus = (vbus == ERR_PTR(-ENODEV) ? NULL : vbus);
if (hd3ss3220->vbus) {
hd3ss3220->id_gpiod = devm_gpiod_get_optional(hd3ss3220->dev,
if (IS_ERR(hd3ss3220->id_gpiod)) {
ret = PTR_ERR(hd3ss3220->id_gpiod);
if (hd3ss3220->id_gpiod) {
hd3ss3220->id_irq = gpiod_to_irq(hd3ss3220->id_gpiod);
if (hd3ss3220->id_irq < 0) {
ret = hd3ss3220->id_irq;
dev_err(hd3ss3220->dev,
hd3ss3220->id_irq);
ret = devm_request_threaded_irq(hd3ss3220->dev,
hd3ss3220->id_irq, NULL,
dev_name(hd3ss3220->dev), hd3ss3220);
dev_err(hd3ss3220->dev, "failed to get ID irq: %d\n", ret);
typec_cap.driver_data = hd3ss3220;
ret = hd3ss3220_configure_source_pref(hd3ss3220, connector, &typec_cap);
ret = hd3ss3220_configure_port_type(hd3ss3220, connector, &typec_cap);
hd3ss3220->port = typec_register_port(&client->dev, &typec_cap);
if (IS_ERR(hd3ss3220->port)) {
ret = PTR_ERR(hd3ss3220->port);
ret = hd3ss3220_configure_power_opmode(hd3ss3220, connector);
hd3ss3220_set_role(hd3ss3220);
ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, &data);
ret = regmap_write(hd3ss3220->regmap,
INIT_DELAYED_WORK(&hd3ss3220->output_poll_work, output_poll_execute);
hd3ss3220->poll = true;
if (hd3ss3220->poll)
schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
typec_unregister_port(hd3ss3220->port);
usb_role_switch_put(hd3ss3220->role_sw);
struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
if (hd3ss3220->poll)
cancel_delayed_work_sync(&hd3ss3220->output_poll_work);
typec_unregister_port(hd3ss3220->port);
usb_role_switch_put(hd3ss3220->role_sw);
static int hd3ss3220_set_power_opmode(struct hd3ss3220 *hd3ss3220, int power_opmode)
dev_err(hd3ss3220->dev, "bad power operation mode: %d\n", power_opmode);
return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT,
static int hd3ss3220_set_port_type(struct hd3ss3220 *hd3ss3220, int type)