brintos

brintos / linux-shallow public Read only

0
0
Text · 3.7 KiB · 20f6dd3 Raw
159 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2016 Linaro Ltd4 */5#include <linux/module.h>6#include <linux/ulpi/driver.h>7#include <linux/ulpi/regs.h>8#include <linux/phy/phy.h>9#include <linux/pinctrl/consumer.h>10#include <linux/pinctrl/pinctrl-state.h>11#include <linux/delay.h>12#include <linux/clk.h>13 14#define ULPI_HSIC_CFG		0x3015#define ULPI_HSIC_IO_CAL	0x3316 17struct qcom_usb_hsic_phy {18	struct ulpi *ulpi;19	struct phy *phy;20	struct pinctrl *pctl;21	struct clk *phy_clk;22	struct clk *cal_clk;23	struct clk *cal_sleep_clk;24};25 26static int qcom_usb_hsic_phy_power_on(struct phy *phy)27{28	struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);29	struct ulpi *ulpi = uphy->ulpi;30	struct pinctrl_state *pins_default;31	int ret;32 33	ret = clk_prepare_enable(uphy->phy_clk);34	if (ret)35		return ret;36 37	ret = clk_prepare_enable(uphy->cal_clk);38	if (ret)39		goto err_cal;40 41	ret = clk_prepare_enable(uphy->cal_sleep_clk);42	if (ret)43		goto err_sleep;44 45	/* Set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */46	ret = ulpi_write(ulpi, ULPI_HSIC_IO_CAL, 0xff);47	if (ret)48		goto err_ulpi;49 50	/* Enable periodic IO calibration in HSIC_CFG register */51	ret = ulpi_write(ulpi, ULPI_HSIC_CFG, 0xa8);52	if (ret)53		goto err_ulpi;54 55	/* Configure pins for HSIC functionality */56	pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);57	if (IS_ERR(pins_default)) {58		ret = PTR_ERR(pins_default);59		goto err_ulpi;60	}61 62	ret = pinctrl_select_state(uphy->pctl, pins_default);63	if (ret)64		goto err_ulpi;65 66	 /* Enable HSIC mode in HSIC_CFG register */67	ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01);68	if (ret)69		goto err_ulpi;70 71	/* Disable auto-resume */72	ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL),73			 ULPI_IFC_CTRL_AUTORESUME);74	if (ret)75		goto err_ulpi;76 77	return ret;78err_ulpi:79	clk_disable_unprepare(uphy->cal_sleep_clk);80err_sleep:81	clk_disable_unprepare(uphy->cal_clk);82err_cal:83	clk_disable_unprepare(uphy->phy_clk);84	return ret;85}86 87static int qcom_usb_hsic_phy_power_off(struct phy *phy)88{89	struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);90 91	clk_disable_unprepare(uphy->cal_sleep_clk);92	clk_disable_unprepare(uphy->cal_clk);93	clk_disable_unprepare(uphy->phy_clk);94 95	return 0;96}97 98static const struct phy_ops qcom_usb_hsic_phy_ops = {99	.power_on = qcom_usb_hsic_phy_power_on,100	.power_off = qcom_usb_hsic_phy_power_off,101	.owner = THIS_MODULE,102};103 104static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi)105{106	struct qcom_usb_hsic_phy *uphy;107	struct phy_provider *p;108	struct clk *clk;109 110	uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);111	if (!uphy)112		return -ENOMEM;113	ulpi_set_drvdata(ulpi, uphy);114 115	uphy->ulpi = ulpi;116	uphy->pctl = devm_pinctrl_get(&ulpi->dev);117	if (IS_ERR(uphy->pctl))118		return PTR_ERR(uphy->pctl);119 120	uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy");121	if (IS_ERR(clk))122		return PTR_ERR(clk);123 124	uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal");125	if (IS_ERR(clk))126		return PTR_ERR(clk);127 128	uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");129	if (IS_ERR(clk))130		return PTR_ERR(clk);131 132	uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,133				    &qcom_usb_hsic_phy_ops);134	if (IS_ERR(uphy->phy))135		return PTR_ERR(uphy->phy);136	phy_set_drvdata(uphy->phy, uphy);137 138	p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);139	return PTR_ERR_OR_ZERO(p);140}141 142static const struct of_device_id qcom_usb_hsic_phy_match[] = {143	{ .compatible = "qcom,usb-hsic-phy", },144	{ }145};146MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match);147 148static struct ulpi_driver qcom_usb_hsic_phy_driver = {149	.probe = qcom_usb_hsic_phy_probe,150	.driver = {151		.name = "qcom_usb_hsic_phy",152		.of_match_table = qcom_usb_hsic_phy_match,153	},154};155module_ulpi_driver(qcom_usb_hsic_phy_driver);156 157MODULE_DESCRIPTION("Qualcomm USB HSIC phy");158MODULE_LICENSE("GPL v2");159