18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-1.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Renesas USB driver R-Car Gen. 2 initialization and power control
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Ulrich Hecht
68c2ecf20Sopenharmony_ci * Copyright (C) 2019 Renesas Electronics Corporation
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/phy/phy.h>
108c2ecf20Sopenharmony_ci#include "common.h"
118c2ecf20Sopenharmony_ci#include "rcar2.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic int usbhs_rcar2_hardware_init(struct platform_device *pdev)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_GENERIC_PHY)) {
188c2ecf20Sopenharmony_ci		struct phy *phy = phy_get(&pdev->dev, "usb");
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci		if (IS_ERR(phy))
218c2ecf20Sopenharmony_ci			return PTR_ERR(phy);
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci		priv->phy = phy;
248c2ecf20Sopenharmony_ci		return 0;
258c2ecf20Sopenharmony_ci	}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	return -ENXIO;
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic int usbhs_rcar2_hardware_exit(struct platform_device *pdev)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	if (priv->phy) {
358c2ecf20Sopenharmony_ci		phy_put(&pdev->dev, priv->phy);
368c2ecf20Sopenharmony_ci		priv->phy = NULL;
378c2ecf20Sopenharmony_ci	}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	return 0;
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic int usbhs_rcar2_power_ctrl(struct platform_device *pdev,
438c2ecf20Sopenharmony_ci				void __iomem *base, int enable)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
468c2ecf20Sopenharmony_ci	int retval = -ENODEV;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (priv->phy) {
498c2ecf20Sopenharmony_ci		if (enable) {
508c2ecf20Sopenharmony_ci			retval = phy_init(priv->phy);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci			if (!retval)
538c2ecf20Sopenharmony_ci				retval = phy_power_on(priv->phy);
548c2ecf20Sopenharmony_ci		} else {
558c2ecf20Sopenharmony_ci			phy_power_off(priv->phy);
568c2ecf20Sopenharmony_ci			phy_exit(priv->phy);
578c2ecf20Sopenharmony_ci			retval = 0;
588c2ecf20Sopenharmony_ci		}
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	return retval;
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ciconst struct renesas_usbhs_platform_info usbhs_rcar_gen2_plat_info = {
658c2ecf20Sopenharmony_ci	.platform_callback = {
668c2ecf20Sopenharmony_ci		.hardware_init = usbhs_rcar2_hardware_init,
678c2ecf20Sopenharmony_ci		.hardware_exit = usbhs_rcar2_hardware_exit,
688c2ecf20Sopenharmony_ci		.power_ctrl = usbhs_rcar2_power_ctrl,
698c2ecf20Sopenharmony_ci		.get_id = usbhs_get_id_as_gadget,
708c2ecf20Sopenharmony_ci	},
718c2ecf20Sopenharmony_ci	.driver_param = {
728c2ecf20Sopenharmony_ci		.has_usb_dmac = 1,
738c2ecf20Sopenharmony_ci		.has_new_pipe_configs = 1,
748c2ecf20Sopenharmony_ci	},
758c2ecf20Sopenharmony_ci};
76