1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2016, NVIDIA Corporation 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/module.h> 8 #include <linux/of_device.h> 9 #include <linux/reset.h> 10 11 #include <linux/usb/chipidea.h> 12 13 #include "ci.h" 14 15 struct tegra_udc { 16 struct ci_hdrc_platform_data data; 17 struct platform_device *dev; 18 19 struct usb_phy *phy; 20 struct clk *clk; 21 }; 22 23 struct tegra_udc_soc_info { 24 unsigned long flags; 25 }; 26 27 static const struct tegra_udc_soc_info tegra_udc_soc_info = { 28 .flags = CI_HDRC_REQUIRES_ALIGNED_DMA, 29 }; 30 31 static const struct of_device_id tegra_udc_of_match[] = { 32 { 33 .compatible = "nvidia,tegra20-udc", 34 .data = &tegra_udc_soc_info, 35 }, { 36 .compatible = "nvidia,tegra30-udc", 37 .data = &tegra_udc_soc_info, 38 }, { 39 .compatible = "nvidia,tegra114-udc", 40 .data = &tegra_udc_soc_info, 41 }, { 42 .compatible = "nvidia,tegra124-udc", 43 .data = &tegra_udc_soc_info, 44 }, { 45 /* sentinel */ 46 } 47 }; 48 MODULE_DEVICE_TABLE(of, tegra_udc_of_match); 49 50 static int tegra_udc_probe(struct platform_device *pdev) 51 { 52 const struct tegra_udc_soc_info *soc; 53 struct tegra_udc *udc; 54 int err; 55 56 udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL); 57 if (!udc) 58 return -ENOMEM; 59 60 soc = of_device_get_match_data(&pdev->dev); 61 if (!soc) { 62 dev_err(&pdev->dev, "failed to match OF data\n"); 63 return -EINVAL; 64 } 65 66 udc->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); 67 if (IS_ERR(udc->phy)) { 68 err = PTR_ERR(udc->phy); 69 dev_err(&pdev->dev, "failed to get PHY: %d\n", err); 70 return err; 71 } 72 73 udc->clk = devm_clk_get(&pdev->dev, NULL); 74 if (IS_ERR(udc->clk)) { 75 err = PTR_ERR(udc->clk); 76 dev_err(&pdev->dev, "failed to get clock: %d\n", err); 77 return err; 78 } 79 80 err = clk_prepare_enable(udc->clk); 81 if (err < 0) { 82 dev_err(&pdev->dev, "failed to enable clock: %d\n", err); 83 return err; 84 } 85 86 /* 87 * Tegra's USB PHY driver doesn't implement optional phy_init() 88 * hook, so we have to power on UDC controller before ChipIdea 89 * driver initialization kicks in. 90 */ 91 usb_phy_set_suspend(udc->phy, 0); 92 93 /* setup and register ChipIdea HDRC device */ 94 udc->data.name = "tegra-udc"; 95 udc->data.flags = soc->flags; 96 udc->data.usb_phy = udc->phy; 97 udc->data.capoffset = DEF_CAPOFFSET; 98 99 udc->dev = ci_hdrc_add_device(&pdev->dev, pdev->resource, 100 pdev->num_resources, &udc->data); 101 if (IS_ERR(udc->dev)) { 102 err = PTR_ERR(udc->dev); 103 dev_err(&pdev->dev, "failed to add HDRC device: %d\n", err); 104 goto fail_power_off; 105 } 106 107 platform_set_drvdata(pdev, udc); 108 109 return 0; 110 111 fail_power_off: 112 usb_phy_set_suspend(udc->phy, 1); 113 clk_disable_unprepare(udc->clk); 114 return err; 115 } 116 117 static int tegra_udc_remove(struct platform_device *pdev) 118 { 119 struct tegra_udc *udc = platform_get_drvdata(pdev); 120 121 ci_hdrc_remove_device(udc->dev); 122 usb_phy_set_suspend(udc->phy, 1); 123 clk_disable_unprepare(udc->clk); 124 125 return 0; 126 } 127 128 static struct platform_driver tegra_udc_driver = { 129 .driver = { 130 .name = "tegra-udc", 131 .of_match_table = tegra_udc_of_match, 132 }, 133 .probe = tegra_udc_probe, 134 .remove = tegra_udc_remove, 135 }; 136 module_platform_driver(tegra_udc_driver); 137 138 MODULE_DESCRIPTION("NVIDIA Tegra USB device mode driver"); 139 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 140 MODULE_ALIAS("platform:tegra-udc"); 141 MODULE_LICENSE("GPL v2"); 142