^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * phy-keystone - USB PHY, talking to dwc3 controller in Keystone.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Author: WingMan Kwok <w-kwok2@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/usb/usb_phy_generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "phy-generic.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) /* USB PHY control register offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define USB_PHY_CTL_UTMI		0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define USB_PHY_CTL_PIPE		0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define USB_PHY_CTL_PARAM_1		0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define USB_PHY_CTL_PARAM_2		0x000c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define USB_PHY_CTL_CLOCK		0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define USB_PHY_CTL_PLL			0x0014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define PHY_REF_SSP_EN			BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) struct keystone_usbphy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	struct usb_phy_generic	usb_phy_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	void __iomem			*phy_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static inline u32 keystone_usbphy_readl(void __iomem *base, u32 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	return readl(base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static inline void keystone_usbphy_writel(void __iomem *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 					  u32 offset, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	writel(value, base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static int keystone_usbphy_init(struct usb_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	val  = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 				val | PHY_REF_SSP_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static void keystone_usbphy_shutdown(struct usb_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	val  = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 				val &= ~PHY_REF_SSP_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static int keystone_usbphy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	struct device		*dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct keystone_usbphy	*k_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	k_phy = devm_kzalloc(dev, sizeof(*k_phy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (!k_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	k_phy->phy_ctrl = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	if (IS_ERR(k_phy->phy_ctrl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		return PTR_ERR(k_phy->phy_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	ret = usb_phy_gen_create_phy(dev, &k_phy->usb_phy_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	k_phy->usb_phy_gen.phy.init = keystone_usbphy_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	k_phy->usb_phy_gen.phy.shutdown = keystone_usbphy_shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	platform_set_drvdata(pdev, k_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	return usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) static int keystone_usbphy_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	struct keystone_usbphy *k_phy = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	usb_remove_phy(&k_phy->usb_phy_gen.phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static const struct of_device_id keystone_usbphy_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	{ .compatible = "ti,keystone-usbphy" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) MODULE_DEVICE_TABLE(of, keystone_usbphy_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static struct platform_driver keystone_usbphy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	.probe          = keystone_usbphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	.remove         = keystone_usbphy_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	.driver         = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		.name   = "keystone-usbphy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		.of_match_table = keystone_usbphy_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) module_platform_driver(keystone_usbphy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) MODULE_ALIAS("platform:keystone-usbphy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) MODULE_AUTHOR("Texas Instruments Inc.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) MODULE_DESCRIPTION("Keystone USB phy driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) MODULE_LICENSE("GPL v2");