| /* | 
 |  * Synopsys G210 Test Chip driver | 
 |  * | 
 |  * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com) | 
 |  * | 
 |  * Authors: Joao Pinto <jpinto@synopsys.com> | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or modify | 
 |  * it under the terms of the GNU General Public License version 2 as | 
 |  * published by the Free Software Foundation. | 
 |  */ | 
 |  | 
 | #include <linux/kernel.h> | 
 | #include <linux/module.h> | 
 | #include <linux/platform_device.h> | 
 | #include <linux/of.h> | 
 | #include <linux/delay.h> | 
 |  | 
 | #include "ufshcd-pltfrm.h" | 
 | #include "ufshcd-dwc.h" | 
 | #include "tc-dwc-g210.h" | 
 |  | 
 | /* | 
 |  * UFS DWC specific variant operations | 
 |  */ | 
 | static struct ufs_hba_variant_ops tc_dwc_g210_20bit_pltfm_hba_vops = { | 
 | 	.name                   = "tc-dwc-g210-pltfm", | 
 | 	.link_startup_notify	= ufshcd_dwc_link_startup_notify, | 
 | 	.phy_initialization = tc_dwc_g210_config_20_bit, | 
 | }; | 
 |  | 
 | static struct ufs_hba_variant_ops tc_dwc_g210_40bit_pltfm_hba_vops = { | 
 | 	.name                   = "tc-dwc-g210-pltfm", | 
 | 	.link_startup_notify	= ufshcd_dwc_link_startup_notify, | 
 | 	.phy_initialization = tc_dwc_g210_config_40_bit, | 
 | }; | 
 |  | 
 | static const struct of_device_id tc_dwc_g210_pltfm_match[] = { | 
 | 	{ | 
 | 		.compatible = "snps,g210-tc-6.00-20bit", | 
 | 		.data = &tc_dwc_g210_20bit_pltfm_hba_vops, | 
 | 	}, | 
 | 	{ | 
 | 		.compatible = "snps,g210-tc-6.00-40bit", | 
 | 		.data = &tc_dwc_g210_40bit_pltfm_hba_vops, | 
 | 	}, | 
 | 	{ }, | 
 | }; | 
 | MODULE_DEVICE_TABLE(of, tc_dwc_g210_pltfm_match); | 
 |  | 
 | /** | 
 |  * tc_dwc_g210_pltfm_probe() | 
 |  * @pdev: pointer to platform device structure | 
 |  * | 
 |  */ | 
 | static int tc_dwc_g210_pltfm_probe(struct platform_device *pdev) | 
 | { | 
 | 	int err; | 
 | 	const struct of_device_id *of_id; | 
 | 	struct ufs_hba_variant_ops *vops; | 
 | 	struct device *dev = &pdev->dev; | 
 |  | 
 | 	of_id = of_match_node(tc_dwc_g210_pltfm_match, dev->of_node); | 
 | 	vops = (struct ufs_hba_variant_ops *)of_id->data; | 
 |  | 
 | 	/* Perform generic probe */ | 
 | 	err = ufshcd_pltfrm_init(pdev, vops); | 
 | 	if (err) | 
 | 		dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); | 
 |  | 
 | 	return err; | 
 | } | 
 |  | 
 | /** | 
 |  * tc_dwc_g210_pltfm_remove() | 
 |  * @pdev: pointer to platform device structure | 
 |  * | 
 |  */ | 
 | static int tc_dwc_g210_pltfm_remove(struct platform_device *pdev) | 
 | { | 
 | 	struct ufs_hba *hba =  platform_get_drvdata(pdev); | 
 |  | 
 | 	pm_runtime_get_sync(&(pdev)->dev); | 
 | 	ufshcd_remove(hba); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = { | 
 | 	.suspend	= ufshcd_pltfrm_suspend, | 
 | 	.resume		= ufshcd_pltfrm_resume, | 
 | 	.runtime_suspend = ufshcd_pltfrm_runtime_suspend, | 
 | 	.runtime_resume  = ufshcd_pltfrm_runtime_resume, | 
 | 	.runtime_idle    = ufshcd_pltfrm_runtime_idle, | 
 | }; | 
 |  | 
 | static struct platform_driver tc_dwc_g210_pltfm_driver = { | 
 | 	.probe		= tc_dwc_g210_pltfm_probe, | 
 | 	.remove		= tc_dwc_g210_pltfm_remove, | 
 | 	.shutdown = ufshcd_pltfrm_shutdown, | 
 | 	.driver		= { | 
 | 		.name	= "tc-dwc-g210-pltfm", | 
 | 		.pm	= &tc_dwc_g210_pltfm_pm_ops, | 
 | 		.of_match_table	= of_match_ptr(tc_dwc_g210_pltfm_match), | 
 | 	}, | 
 | }; | 
 |  | 
 | module_platform_driver(tc_dwc_g210_pltfm_driver); | 
 |  | 
 | MODULE_ALIAS("platform:tc-dwc-g210-pltfm"); | 
 | MODULE_DESCRIPTION("Synopsys Test Chip G210 platform glue driver"); | 
 | MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>"); | 
 | MODULE_LICENSE("Dual BSD/GPL"); |