162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Synopsys G210 Test Chip driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Authors: Joao Pinto <jpinto@synopsys.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <linux/of.h>
1462306a36Sopenharmony_ci#include <linux/delay.h>
1562306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "ufshcd-pltfrm.h"
1862306a36Sopenharmony_ci#include "ufshcd-dwc.h"
1962306a36Sopenharmony_ci#include "tc-dwc-g210.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * UFS DWC specific variant operations
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_cistatic struct ufs_hba_variant_ops tc_dwc_g210_20bit_pltfm_hba_vops = {
2562306a36Sopenharmony_ci	.name                   = "tc-dwc-g210-pltfm",
2662306a36Sopenharmony_ci	.link_startup_notify	= ufshcd_dwc_link_startup_notify,
2762306a36Sopenharmony_ci	.phy_initialization = tc_dwc_g210_config_20_bit,
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic struct ufs_hba_variant_ops tc_dwc_g210_40bit_pltfm_hba_vops = {
3162306a36Sopenharmony_ci	.name                   = "tc-dwc-g210-pltfm",
3262306a36Sopenharmony_ci	.link_startup_notify	= ufshcd_dwc_link_startup_notify,
3362306a36Sopenharmony_ci	.phy_initialization = tc_dwc_g210_config_40_bit,
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic const struct of_device_id tc_dwc_g210_pltfm_match[] = {
3762306a36Sopenharmony_ci	{
3862306a36Sopenharmony_ci		.compatible = "snps,g210-tc-6.00-20bit",
3962306a36Sopenharmony_ci		.data = &tc_dwc_g210_20bit_pltfm_hba_vops,
4062306a36Sopenharmony_ci	},
4162306a36Sopenharmony_ci	{
4262306a36Sopenharmony_ci		.compatible = "snps,g210-tc-6.00-40bit",
4362306a36Sopenharmony_ci		.data = &tc_dwc_g210_40bit_pltfm_hba_vops,
4462306a36Sopenharmony_ci	},
4562306a36Sopenharmony_ci	{ },
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, tc_dwc_g210_pltfm_match);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/**
5062306a36Sopenharmony_ci * tc_dwc_g210_pltfm_probe()
5162306a36Sopenharmony_ci * @pdev: pointer to platform device structure
5262306a36Sopenharmony_ci *
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_cistatic int tc_dwc_g210_pltfm_probe(struct platform_device *pdev)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	int err;
5762306a36Sopenharmony_ci	const struct of_device_id *of_id;
5862306a36Sopenharmony_ci	struct ufs_hba_variant_ops *vops;
5962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	of_id = of_match_node(tc_dwc_g210_pltfm_match, dev->of_node);
6262306a36Sopenharmony_ci	vops = (struct ufs_hba_variant_ops *)of_id->data;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	/* Perform generic probe */
6562306a36Sopenharmony_ci	err = ufshcd_pltfrm_init(pdev, vops);
6662306a36Sopenharmony_ci	if (err)
6762306a36Sopenharmony_ci		dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return err;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/**
7362306a36Sopenharmony_ci * tc_dwc_g210_pltfm_remove()
7462306a36Sopenharmony_ci * @pdev: pointer to platform device structure
7562306a36Sopenharmony_ci *
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_cistatic int tc_dwc_g210_pltfm_remove(struct platform_device *pdev)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	struct ufs_hba *hba =  platform_get_drvdata(pdev);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	pm_runtime_get_sync(&(pdev)->dev);
8262306a36Sopenharmony_ci	ufshcd_remove(hba);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	return 0;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = {
8862306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
8962306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic struct platform_driver tc_dwc_g210_pltfm_driver = {
9362306a36Sopenharmony_ci	.probe		= tc_dwc_g210_pltfm_probe,
9462306a36Sopenharmony_ci	.remove		= tc_dwc_g210_pltfm_remove,
9562306a36Sopenharmony_ci	.driver		= {
9662306a36Sopenharmony_ci		.name	= "tc-dwc-g210-pltfm",
9762306a36Sopenharmony_ci		.pm	= &tc_dwc_g210_pltfm_pm_ops,
9862306a36Sopenharmony_ci		.of_match_table	= of_match_ptr(tc_dwc_g210_pltfm_match),
9962306a36Sopenharmony_ci	},
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cimodule_platform_driver(tc_dwc_g210_pltfm_driver);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciMODULE_ALIAS("platform:tc-dwc-g210-pltfm");
10562306a36Sopenharmony_ciMODULE_DESCRIPTION("Synopsys Test Chip G210 platform glue driver");
10662306a36Sopenharmony_ciMODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
10762306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
108