misc: hisi_hikey_usb: add support for hikey970
Signed-off-by: chenyu <chenyu56@huawei.com>
This commit is contained in:
+106
-38
@@ -18,6 +18,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define DEVICE_DRIVER_NAME "hisi_hikey_usb"
|
||||
|
||||
@@ -39,6 +40,8 @@ struct gpio_hub_info {
|
||||
int typec_vbus_gpio;
|
||||
int typec_vbus_enable_val;
|
||||
int hub_vbus_gpio;
|
||||
int hub_reset_en_gpio;
|
||||
struct regulator *hub_regu;
|
||||
};
|
||||
|
||||
static struct gpio_hub_info gpio_hub_driver_info = {
|
||||
@@ -46,28 +49,43 @@ static struct gpio_hub_info gpio_hub_driver_info = {
|
||||
.typec_vbus_gpio = -1,
|
||||
.typec_vbus_enable_val = -1,
|
||||
.hub_vbus_gpio = -1,
|
||||
.hub_regu = NULL,
|
||||
};
|
||||
|
||||
void gpio_hub_power_off(void)
|
||||
{
|
||||
if (gpio_is_valid(gpio_hub_driver_info.hub_vbus_gpio)) {
|
||||
gpio_set_value(gpio_hub_driver_info.hub_vbus_gpio,
|
||||
GPIO_HUB_VBUS_NO_POWER);
|
||||
int gpio = gpio_hub_driver_info.hub_vbus_gpio;
|
||||
int ret;
|
||||
|
||||
if (gpio_is_valid(gpio)) {
|
||||
gpio_set_value(gpio, GPIO_HUB_VBUS_NO_POWER);
|
||||
pr_info("%s: gpio hub hub vbus no power set success",
|
||||
__func__);
|
||||
} else
|
||||
pr_err("%s: gpio hub hub vbus no power set err",
|
||||
__func__);
|
||||
}
|
||||
|
||||
if (gpio_hub_driver_info.hub_regu &&
|
||||
regulator_is_enabled(gpio_hub_driver_info.hub_regu)) {
|
||||
ret = regulator_disable(gpio_hub_driver_info.hub_regu);
|
||||
if (ret)
|
||||
pr_err("disable hub regulator failed");
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_hub_power_on(void)
|
||||
{
|
||||
if (gpio_is_valid(gpio_hub_driver_info.hub_vbus_gpio))
|
||||
gpio_set_value(gpio_hub_driver_info.hub_vbus_gpio,
|
||||
GPIO_HUB_VBUS_POWER);
|
||||
else
|
||||
pr_err("%s: gpio hub hub vbus set err", __func__);
|
||||
int gpio = gpio_hub_driver_info.hub_vbus_gpio;
|
||||
int ret;
|
||||
|
||||
if (gpio_is_valid(gpio))
|
||||
gpio_set_value(gpio, GPIO_HUB_VBUS_POWER);
|
||||
|
||||
if (gpio_hub_driver_info.hub_regu &&
|
||||
!regulator_is_enabled(gpio_hub_driver_info.hub_regu)) {
|
||||
pr_err("%s:regulator_enable\n", __func__);
|
||||
ret = regulator_enable(gpio_hub_driver_info.hub_regu);
|
||||
if (ret)
|
||||
pr_err("enable hub regulator failed");
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_hub_switch_to_hub(void)
|
||||
@@ -147,24 +165,64 @@ static int gpio_hub_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
struct device_node *root = pdev->dev.of_node;
|
||||
struct gpio_hub_info *info = &gpio_hub_driver_info;
|
||||
struct regulator *hub_regu;
|
||||
|
||||
pr_info("%s: step in\n", __func__);
|
||||
|
||||
info->pdev = pdev;
|
||||
info->hub_vbus_gpio = of_get_named_gpio(root, "hub_vdd33_en_gpio", 0);
|
||||
if (!gpio_is_valid(info->hub_vbus_gpio)) {
|
||||
pr_err("%s: hub_vbus_gpio is err\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = gpio_request(info->hub_vbus_gpio, "hub_vbus_int_gpio");
|
||||
if (ret) {
|
||||
pr_err("%s: request hub_vbus_gpio err\n", __func__);
|
||||
return ret;
|
||||
if (!pdev)
|
||||
return -EBUSY;
|
||||
|
||||
if (of_device_is_compatible(root, "hisilicon,kirin970_hikey_usbhub")) {
|
||||
hub_regu = devm_regulator_get(&pdev->dev, "hub-vdd");
|
||||
if (IS_ERR(hub_regu)) {
|
||||
dev_err(&pdev->dev, "get hub-vdd-supply failed\n");
|
||||
return PTR_ERR(hub_regu);
|
||||
}
|
||||
info->hub_regu = hub_regu;
|
||||
ret = regulator_set_voltage(info->hub_regu, 3300000, 3300000);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "set hub-vdd-supply voltage failed\n");
|
||||
|
||||
info->hub_reset_en_gpio = of_get_named_gpio(root, "hub_reset_en_gpio", 0);
|
||||
if (!gpio_is_valid(info->hub_reset_en_gpio)) {
|
||||
pr_err("%s: hub_reset_en_gpio is err\n", __func__);
|
||||
return info->hub_reset_en_gpio;
|
||||
}
|
||||
|
||||
ret = gpio_request(info->hub_reset_en_gpio, "hub_reset_en_gpio");
|
||||
if (ret) {
|
||||
pr_err("%s: request hub_reset_en_gpio err\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
ret = gpio_direction_output(info->hub_reset_en_gpio, 1);
|
||||
if (ret) {
|
||||
pr_err("%s: set hub_reset_en_gpio 1 err\n", __func__);
|
||||
goto free_gpio1;
|
||||
}
|
||||
} else {
|
||||
info->hub_vbus_gpio = of_get_named_gpio(root, "hub_vdd33_en_gpio", 0);
|
||||
if (!gpio_is_valid(info->hub_vbus_gpio)) {
|
||||
pr_err("%s: hub_vbus_gpio is err\n", __func__);
|
||||
return info->hub_vbus_gpio;
|
||||
}
|
||||
|
||||
ret = gpio_request(info->hub_vbus_gpio, "hub_vbus_int_gpio");
|
||||
if (ret) {
|
||||
pr_err("%s: request hub_vbus_gpio err\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(info->hub_vbus_gpio, GPIO_HUB_VBUS_POWER);
|
||||
if (ret) {
|
||||
pr_err("%s: power on hub vbus err\n", __func__);
|
||||
goto free_gpio1;
|
||||
}
|
||||
}
|
||||
|
||||
info->typec_vbus_gpio = of_get_named_gpio(root,
|
||||
"typc_vbus_int_gpio,typec-gpios", 0);
|
||||
if (!gpio_is_valid(info->hub_vbus_gpio)) {
|
||||
if (!gpio_is_valid(info->typec_vbus_gpio)) {
|
||||
pr_err("%s: typec_vbus_gpio is err\n", __func__);
|
||||
ret = info->typec_vbus_gpio;
|
||||
goto free_gpio1;
|
||||
@@ -181,21 +239,9 @@ static int gpio_hub_probe(struct platform_device *pdev)
|
||||
pr_err("%s: typc_vbus_enable_val can't get\n", __func__);
|
||||
goto free_gpio2;
|
||||
}
|
||||
|
||||
info->typec_vbus_enable_val = !!info->typec_vbus_enable_val;
|
||||
|
||||
/* only for v2 */
|
||||
info->otg_switch_gpio = of_get_named_gpio(root, "otg_gpio", 0);
|
||||
if (!gpio_is_valid(info->otg_switch_gpio)) {
|
||||
pr_info("%s: otg_switch_gpio is err\n", __func__);
|
||||
info->otg_switch_gpio = -1;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(info->hub_vbus_gpio, GPIO_HUB_VBUS_POWER);
|
||||
if (ret) {
|
||||
pr_err("%s: power on hub vbus err\n", __func__);
|
||||
goto free_gpio2;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(info->typec_vbus_gpio,
|
||||
info->typec_vbus_enable_val);
|
||||
if (ret) {
|
||||
@@ -203,19 +249,40 @@ static int gpio_hub_probe(struct platform_device *pdev)
|
||||
goto free_gpio2;
|
||||
}
|
||||
|
||||
if (!of_device_is_compatible(root, "hisilicon,gpio_hubv1")) {
|
||||
info->otg_switch_gpio = of_get_named_gpio(root, "otg_gpio", 0);
|
||||
if (!gpio_is_valid(info->otg_switch_gpio)) {
|
||||
pr_info("%s: otg_switch_gpio is err\n", __func__);
|
||||
info->otg_switch_gpio = -1;
|
||||
}
|
||||
|
||||
ret = gpio_request(info->otg_switch_gpio, "otg_switch_gpio");
|
||||
if (ret) {
|
||||
pr_err("%s: request typec_vbus_gpio err\n", __func__);
|
||||
goto free_gpio2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_gpio2:
|
||||
gpio_free(info->typec_vbus_gpio);
|
||||
info->typec_vbus_gpio = -1;
|
||||
free_gpio1:
|
||||
gpio_free(info->hub_vbus_gpio);
|
||||
info->hub_vbus_gpio = -1;
|
||||
if (gpio_is_valid(info->hub_vbus_gpio)) {
|
||||
gpio_free(info->hub_vbus_gpio);
|
||||
info->hub_vbus_gpio = -1;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(info->hub_reset_en_gpio)) {
|
||||
gpio_free(info->hub_reset_en_gpio);
|
||||
info->hub_reset_en_gpio= -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_hub_remove(struct platform_device *pdev)
|
||||
static int gpio_hub_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_hub_info *info = &gpio_hub_driver_info;
|
||||
|
||||
@@ -239,6 +306,7 @@ static int gpio_hub_remove(struct platform_device *pdev)
|
||||
static const struct of_device_id id_table_for_gpio_hub[] = {
|
||||
{.compatible = "hisilicon,gpio_hubv1"},
|
||||
{.compatible = "hisilicon,gpio_hubv2"},
|
||||
{.compatible = "hisilicon,kirin970_hikey_usbhub"},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -269,5 +337,5 @@ module_init(gpio_hub_init);
|
||||
module_exit(gpio_hub_exit);
|
||||
|
||||
MODULE_AUTHOR("wangbinghui<wangbinghui@hisilicon.com>");
|
||||
MODULE_DESCRIPTION("HUB GPIO FOR OTG ID driver");
|
||||
MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
Reference in New Issue
Block a user