1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Synopsys G210 Test Chip driver |
4 | * |
5 | * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com) |
6 | * |
7 | * Authors: Joao Pinto <jpinto@synopsys.com> |
8 | */ |
9 | |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/platform_device.h> |
13 | #include <linux/of.h> |
14 | #include <linux/delay.h> |
15 | #include <linux/pm_runtime.h> |
16 | |
17 | #include "ufshcd-pltfrm.h" |
18 | #include "ufshcd-dwc.h" |
19 | #include "tc-dwc-g210.h" |
20 | |
21 | /* |
22 | * UFS DWC specific variant operations |
23 | */ |
24 | static struct ufs_hba_variant_ops tc_dwc_g210_20bit_pltfm_hba_vops = { |
25 | .name = "tc-dwc-g210-pltfm" , |
26 | .link_startup_notify = ufshcd_dwc_link_startup_notify, |
27 | .phy_initialization = tc_dwc_g210_config_20_bit, |
28 | }; |
29 | |
30 | static struct ufs_hba_variant_ops tc_dwc_g210_40bit_pltfm_hba_vops = { |
31 | .name = "tc-dwc-g210-pltfm" , |
32 | .link_startup_notify = ufshcd_dwc_link_startup_notify, |
33 | .phy_initialization = tc_dwc_g210_config_40_bit, |
34 | }; |
35 | |
36 | static const struct of_device_id tc_dwc_g210_pltfm_match[] = { |
37 | { |
38 | .compatible = "snps,g210-tc-6.00-20bit" , |
39 | .data = &tc_dwc_g210_20bit_pltfm_hba_vops, |
40 | }, |
41 | { |
42 | .compatible = "snps,g210-tc-6.00-40bit" , |
43 | .data = &tc_dwc_g210_40bit_pltfm_hba_vops, |
44 | }, |
45 | { }, |
46 | }; |
47 | MODULE_DEVICE_TABLE(of, tc_dwc_g210_pltfm_match); |
48 | |
49 | /** |
50 | * tc_dwc_g210_pltfm_probe() |
51 | * @pdev: pointer to platform device structure |
52 | * |
53 | */ |
54 | static int tc_dwc_g210_pltfm_probe(struct platform_device *pdev) |
55 | { |
56 | int err; |
57 | const struct of_device_id *of_id; |
58 | struct ufs_hba_variant_ops *vops; |
59 | struct device *dev = &pdev->dev; |
60 | |
61 | of_id = of_match_node(matches: tc_dwc_g210_pltfm_match, node: dev->of_node); |
62 | vops = (struct ufs_hba_variant_ops *)of_id->data; |
63 | |
64 | /* Perform generic probe */ |
65 | err = ufshcd_pltfrm_init(pdev, vops); |
66 | if (err) |
67 | dev_err(dev, "ufshcd_pltfrm_init() failed %d\n" , err); |
68 | |
69 | return err; |
70 | } |
71 | |
72 | /** |
73 | * tc_dwc_g210_pltfm_remove() |
74 | * @pdev: pointer to platform device structure |
75 | * |
76 | */ |
77 | static void tc_dwc_g210_pltfm_remove(struct platform_device *pdev) |
78 | { |
79 | struct ufs_hba *hba = platform_get_drvdata(pdev); |
80 | |
81 | pm_runtime_get_sync(dev: &(pdev)->dev); |
82 | ufshcd_remove(hba); |
83 | } |
84 | |
85 | static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = { |
86 | SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume) |
87 | SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL) |
88 | }; |
89 | |
90 | static struct platform_driver tc_dwc_g210_pltfm_driver = { |
91 | .probe = tc_dwc_g210_pltfm_probe, |
92 | .remove_new = tc_dwc_g210_pltfm_remove, |
93 | .driver = { |
94 | .name = "tc-dwc-g210-pltfm" , |
95 | .pm = &tc_dwc_g210_pltfm_pm_ops, |
96 | .of_match_table = of_match_ptr(tc_dwc_g210_pltfm_match), |
97 | }, |
98 | }; |
99 | |
100 | module_platform_driver(tc_dwc_g210_pltfm_driver); |
101 | |
102 | MODULE_ALIAS("platform:tc-dwc-g210-pltfm" ); |
103 | MODULE_DESCRIPTION("Synopsys Test Chip G210 platform glue driver" ); |
104 | MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>" ); |
105 | MODULE_LICENSE("Dual BSD/GPL" ); |
106 | |