misc: hisi_hikey_usb: add support for hikey970

Signed-off-by: chenyu <chenyu56@huawei.com>
This commit is contained in:
Yu Chen
2018-02-10 16:26:42 +08:00
committed by Guodong Xu
parent 4d2515a2ba
commit cc157f58ba
+106 -38
View File
@@ -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");