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 /* setup and register ChipIdea HDRC device */ 87 udc->data.name = "tegra-udc"; 88 udc->data.flags = soc->flags; 89 udc->data.usb_phy = udc->phy; 90 udc->data.capoffset = DEF_CAPOFFSET; 91 92 udc->dev = ci_hdrc_add_device(&pdev->dev, pdev->resource, 93 pdev->num_resources, &udc->data); 94 if (IS_ERR(udc->dev)) { 95 err = PTR_ERR(udc->dev); 96 dev_err(&pdev->dev, "failed to add HDRC device: %d\n", err); 97 goto fail_power_off; 98 } 99 100 platform_set_drvdata(pdev, udc); 101 102 return 0; 103 104 fail_power_off: 105 clk_disable_unprepare(udc->clk); 106 return err; 107 } 108 109 static int tegra_udc_remove(struct platform_device *pdev) 110 { 111 struct tegra_udc *udc = platform_get_drvdata(pdev); 112 113 ci_hdrc_remove_device(udc->dev); 114 clk_disable_unprepare(udc->clk); 115 116 return 0; 117 } 118 119 static struct platform_driver tegra_udc_driver = { 120 .driver = { 121 .name = "tegra-udc", 122 .of_match_table = tegra_udc_of_match, 123 }, 124 .probe = tegra_udc_probe, 125 .remove = tegra_udc_remove, 126 }; 127 module_platform_driver(tegra_udc_driver); 128 129 MODULE_DESCRIPTION("NVIDIA Tegra USB device mode driver"); 130 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 131 MODULE_ALIAS("platform:tegra-udc"); 132 MODULE_LICENSE("GPL v2"); 133