Source
x
/**
* Copyright (C) 2016 Linaro Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
struct qcom_usb_hsic_phy {
struct ulpi *ulpi;
struct phy *phy;
struct pinctrl *pctl;
struct clk *phy_clk;
struct clk *cal_clk;
struct clk *cal_sleep_clk;
};
static int qcom_usb_hsic_phy_power_on(struct phy *phy)
{
struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
struct ulpi *ulpi = uphy->ulpi;
struct pinctrl_state *pins_default;
int ret;
ret = clk_prepare_enable(uphy->phy_clk);
if (ret)
return ret;
ret = clk_prepare_enable(uphy->cal_clk);
if (ret)
goto err_cal;
ret = clk_prepare_enable(uphy->cal_sleep_clk);
if (ret)
goto err_sleep;
/* Set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
ret = ulpi_write(ulpi, ULPI_HSIC_IO_CAL, 0xff);
if (ret)
goto err_ulpi;
/* Enable periodic IO calibration in HSIC_CFG register */
ret = ulpi_write(ulpi, ULPI_HSIC_CFG, 0xa8);
if (ret)
goto err_ulpi;
/* Configure pins for HSIC functionality */
pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);
if (IS_ERR(pins_default))
return PTR_ERR(pins_default);
ret = pinctrl_select_state(uphy->pctl, pins_default);
if (ret)
goto err_ulpi;
/* Enable HSIC mode in HSIC_CFG register */
ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01);
if (ret)
goto err_ulpi;
/* Disable auto-resume */
ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL),
ULPI_IFC_CTRL_AUTORESUME);
if (ret)
goto err_ulpi;
return ret;
err_ulpi:
clk_disable_unprepare(uphy->cal_sleep_clk);
err_sleep:
clk_disable_unprepare(uphy->cal_clk);
err_cal:
clk_disable_unprepare(uphy->phy_clk);
return ret;
}
static int qcom_usb_hsic_phy_power_off(struct phy *phy)
{
struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
clk_disable_unprepare(uphy->cal_sleep_clk);