Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)  * USB cluster support for Armada 375 platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2014 Marvell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Gregory CLEMENT <gregory.clement@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Armada 375 comes with an USB2 host and device controller and an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * USB3 controller. The USB cluster control register allows to manage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * common features of both USB controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <dt-bindings/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define USB2_PHY_CONFIG_DISABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) struct armada375_cluster_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	bool use_usb3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	int phy_provided;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static int armada375_usb_phy_init(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	struct armada375_cluster_phy *cluster_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	cluster_phy = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	if (!cluster_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	reg = readl(cluster_phy->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	if (cluster_phy->use_usb3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		reg |= USB2_PHY_CONFIG_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		reg &= ~USB2_PHY_CONFIG_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	writel(reg, cluster_phy->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static const struct phy_ops armada375_usb_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	.init = armada375_usb_phy_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	.owner = THIS_MODULE,
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * Only one controller can use this PHY. We shouldn't have the case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * when two controllers want to use this PHY. But if this case occurs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * then we provide a phy to the first one and return an error for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * next one. This error has also to be an error returned by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * devm_phy_optional_get() so different from ENODEV for USB2. In the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * USB3 case it still optional and we use ENODEV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) static struct phy *armada375_usb_phy_xlate(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 					struct of_phandle_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	struct armada375_cluster_phy *cluster_phy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	if (!cluster_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		return  ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	 * Either the phy had never been requested and then the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	 * usb claiming it can get it, or it had already been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	 * requested in this case, we only allow to use it with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	 * same configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	if (WARN_ON((cluster_phy->phy_provided != PHY_NONE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			(cluster_phy->phy_provided != args->args[0]))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		dev_err(dev, "This PHY has already been provided!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		dev_err(dev, "Check your device tree, only one controller can use it\n.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		if (args->args[0] == PHY_TYPE_USB2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			return ERR_PTR(-EBUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	if (args->args[0] == PHY_TYPE_USB2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		cluster_phy->use_usb3 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	else if (args->args[0] == PHY_TYPE_USB3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		cluster_phy->use_usb3 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		dev_err(dev, "Invalid PHY mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	/* Store which phy mode is used for next test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	cluster_phy->phy_provided = args->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	return cluster_phy->phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int armada375_usb_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	void __iomem *usb_cluster_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	struct armada375_cluster_phy *cluster_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	cluster_phy = devm_kzalloc(dev, sizeof(*cluster_phy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (!cluster_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		return  -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	usb_cluster_base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (IS_ERR(usb_cluster_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		return PTR_ERR(usb_cluster_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (IS_ERR(phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		dev_err(dev, "failed to create PHY\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return PTR_ERR(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	cluster_phy->phy = phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	cluster_phy->reg = usb_cluster_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	dev_set_drvdata(dev, cluster_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	phy_set_drvdata(phy, cluster_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	phy_provider = devm_of_phy_provider_register(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 						     armada375_usb_phy_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	return PTR_ERR_OR_ZERO(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct of_device_id of_usb_cluster_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	{ .compatible = "marvell,armada-375-usb-cluster", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	{ /* end of list */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct platform_driver armada375_usb_phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	.probe	= armada375_usb_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		.of_match_table	= of_usb_cluster_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		.name  = "armada-375-usb-cluster",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) builtin_platform_driver(armada375_usb_phy_driver);