cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phy-qcom-usb-hsic.c (3790B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2016 Linaro Ltd
      4 */
      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		0x30
     15#define ULPI_HSIC_IO_CAL	0x33
     16
     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		return PTR_ERR(pins_default);
     59
     60	ret = pinctrl_select_state(uphy->pctl, pins_default);
     61	if (ret)
     62		goto err_ulpi;
     63
     64	 /* Enable HSIC mode in HSIC_CFG register */
     65	ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01);
     66	if (ret)
     67		goto err_ulpi;
     68
     69	/* Disable auto-resume */
     70	ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL),
     71			 ULPI_IFC_CTRL_AUTORESUME);
     72	if (ret)
     73		goto err_ulpi;
     74
     75	return ret;
     76err_ulpi:
     77	clk_disable_unprepare(uphy->cal_sleep_clk);
     78err_sleep:
     79	clk_disable_unprepare(uphy->cal_clk);
     80err_cal:
     81	clk_disable_unprepare(uphy->phy_clk);
     82	return ret;
     83}
     84
     85static int qcom_usb_hsic_phy_power_off(struct phy *phy)
     86{
     87	struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
     88
     89	clk_disable_unprepare(uphy->cal_sleep_clk);
     90	clk_disable_unprepare(uphy->cal_clk);
     91	clk_disable_unprepare(uphy->phy_clk);
     92
     93	return 0;
     94}
     95
     96static const struct phy_ops qcom_usb_hsic_phy_ops = {
     97	.power_on = qcom_usb_hsic_phy_power_on,
     98	.power_off = qcom_usb_hsic_phy_power_off,
     99	.owner = THIS_MODULE,
    100};
    101
    102static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi)
    103{
    104	struct qcom_usb_hsic_phy *uphy;
    105	struct phy_provider *p;
    106	struct clk *clk;
    107
    108	uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
    109	if (!uphy)
    110		return -ENOMEM;
    111	ulpi_set_drvdata(ulpi, uphy);
    112
    113	uphy->ulpi = ulpi;
    114	uphy->pctl = devm_pinctrl_get(&ulpi->dev);
    115	if (IS_ERR(uphy->pctl))
    116		return PTR_ERR(uphy->pctl);
    117
    118	uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy");
    119	if (IS_ERR(clk))
    120		return PTR_ERR(clk);
    121
    122	uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal");
    123	if (IS_ERR(clk))
    124		return PTR_ERR(clk);
    125
    126	uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
    127	if (IS_ERR(clk))
    128		return PTR_ERR(clk);
    129
    130	uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
    131				    &qcom_usb_hsic_phy_ops);
    132	if (IS_ERR(uphy->phy))
    133		return PTR_ERR(uphy->phy);
    134	phy_set_drvdata(uphy->phy, uphy);
    135
    136	p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
    137	return PTR_ERR_OR_ZERO(p);
    138}
    139
    140static const struct of_device_id qcom_usb_hsic_phy_match[] = {
    141	{ .compatible = "qcom,usb-hsic-phy", },
    142	{ }
    143};
    144MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match);
    145
    146static struct ulpi_driver qcom_usb_hsic_phy_driver = {
    147	.probe = qcom_usb_hsic_phy_probe,
    148	.driver = {
    149		.name = "qcom_usb_hsic_phy",
    150		.of_match_table = qcom_usb_hsic_phy_match,
    151	},
    152};
    153module_ulpi_driver(qcom_usb_hsic_phy_driver);
    154
    155MODULE_DESCRIPTION("Qualcomm USB HSIC phy");
    156MODULE_LICENSE("GPL v2");