162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Platform UFS Host driver for Cadence controller
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2018 Cadence Design Systems, Inc.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Authors:
862306a36Sopenharmony_ci *	Jan Kotas <jank@cadence.com>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/clk.h>
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/platform_device.h>
1662306a36Sopenharmony_ci#include <linux/of.h>
1762306a36Sopenharmony_ci#include <linux/time.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "ufshcd-pltfrm.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define CDNS_UFS_REG_HCLKDIV	0xFC
2262306a36Sopenharmony_ci#define CDNS_UFS_REG_PHY_XCFGD1	0x113C
2362306a36Sopenharmony_ci#define CDNS_UFS_MAX_L4_ATTRS 12
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct cdns_ufs_host {
2662306a36Sopenharmony_ci	/**
2762306a36Sopenharmony_ci	 * cdns_ufs_dme_attr_val - for storing L4 attributes
2862306a36Sopenharmony_ci	 */
2962306a36Sopenharmony_ci	u32 cdns_ufs_dme_attr_val[CDNS_UFS_MAX_L4_ATTRS];
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/**
3362306a36Sopenharmony_ci * cdns_ufs_get_l4_attr - get L4 attributes on local side
3462306a36Sopenharmony_ci * @hba: per adapter instance
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_cistatic void cdns_ufs_get_l4_attr(struct ufs_hba *hba)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	struct cdns_ufs_host *host = ufshcd_get_variant(hba);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_PEERDEVICEID),
4262306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[0]);
4362306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_PEERCPORTID),
4462306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[1]);
4562306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_TRAFFICCLASS),
4662306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[2]);
4762306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_PROTOCOLID),
4862306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[3]);
4962306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_CPORTFLAGS),
5062306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[4]);
5162306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_TXTOKENVALUE),
5262306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[5]);
5362306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_RXTOKENVALUE),
5462306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[6]);
5562306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_LOCALBUFFERSPACE),
5662306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[7]);
5762306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_PEERBUFFERSPACE),
5862306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[8]);
5962306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_CREDITSTOSEND),
6062306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[9]);
6162306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_CPORTMODE),
6262306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[10]);
6362306a36Sopenharmony_ci	ufshcd_dme_get(hba, UIC_ARG_MIB(T_CONNECTIONSTATE),
6462306a36Sopenharmony_ci		       &host->cdns_ufs_dme_attr_val[11]);
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/**
6862306a36Sopenharmony_ci * cdns_ufs_set_l4_attr - set L4 attributes on local side
6962306a36Sopenharmony_ci * @hba: per adapter instance
7062306a36Sopenharmony_ci *
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_cistatic void cdns_ufs_set_l4_attr(struct ufs_hba *hba)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	struct cdns_ufs_host *host = ufshcd_get_variant(hba);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), 0);
7762306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID),
7862306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[0]);
7962306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERCPORTID),
8062306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[1]);
8162306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_TRAFFICCLASS),
8262306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[2]);
8362306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_PROTOCOLID),
8462306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[3]);
8562306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTFLAGS),
8662306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[4]);
8762306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_TXTOKENVALUE),
8862306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[5]);
8962306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_RXTOKENVALUE),
9062306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[6]);
9162306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_LOCALBUFFERSPACE),
9262306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[7]);
9362306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERBUFFERSPACE),
9462306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[8]);
9562306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_CREDITSTOSEND),
9662306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[9]);
9762306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTMODE),
9862306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[10]);
9962306a36Sopenharmony_ci	ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE),
10062306a36Sopenharmony_ci		       host->cdns_ufs_dme_attr_val[11]);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/**
10462306a36Sopenharmony_ci * cdns_ufs_set_hclkdiv() - set HCLKDIV register value based on the core_clk.
10562306a36Sopenharmony_ci * @hba: host controller instance
10662306a36Sopenharmony_ci *
10762306a36Sopenharmony_ci * Return: zero for success and non-zero for failure.
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_cistatic int cdns_ufs_set_hclkdiv(struct ufs_hba *hba)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	struct ufs_clk_info *clki;
11262306a36Sopenharmony_ci	struct list_head *head = &hba->clk_list_head;
11362306a36Sopenharmony_ci	unsigned long core_clk_rate = 0;
11462306a36Sopenharmony_ci	u32 core_clk_div = 0;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	if (list_empty(head))
11762306a36Sopenharmony_ci		return 0;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	list_for_each_entry(clki, head, list) {
12062306a36Sopenharmony_ci		if (IS_ERR_OR_NULL(clki->clk))
12162306a36Sopenharmony_ci			continue;
12262306a36Sopenharmony_ci		if (!strcmp(clki->name, "core_clk"))
12362306a36Sopenharmony_ci			core_clk_rate = clk_get_rate(clki->clk);
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (!core_clk_rate) {
12762306a36Sopenharmony_ci		dev_err(hba->dev, "%s: unable to find core_clk rate\n",
12862306a36Sopenharmony_ci			__func__);
12962306a36Sopenharmony_ci		return -EINVAL;
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	core_clk_div = core_clk_rate / USEC_PER_SEC;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	ufshcd_writel(hba, core_clk_div, CDNS_UFS_REG_HCLKDIV);
13562306a36Sopenharmony_ci	/**
13662306a36Sopenharmony_ci	 * Make sure the register was updated,
13762306a36Sopenharmony_ci	 * UniPro layer will not work with an incorrect value.
13862306a36Sopenharmony_ci	 */
13962306a36Sopenharmony_ci	mb();
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	return 0;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/**
14562306a36Sopenharmony_ci * cdns_ufs_hce_enable_notify() - set HCLKDIV register
14662306a36Sopenharmony_ci * @hba: host controller instance
14762306a36Sopenharmony_ci * @status: notify stage (pre, post change)
14862306a36Sopenharmony_ci *
14962306a36Sopenharmony_ci * Return: zero for success and non-zero for failure.
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic int cdns_ufs_hce_enable_notify(struct ufs_hba *hba,
15262306a36Sopenharmony_ci				      enum ufs_notify_change_status status)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	if (status != PRE_CHANGE)
15562306a36Sopenharmony_ci		return 0;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	return cdns_ufs_set_hclkdiv(hba);
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/**
16162306a36Sopenharmony_ci * cdns_ufs_hibern8_notify() - save and restore L4 attributes.
16262306a36Sopenharmony_ci * @hba: host controller instance
16362306a36Sopenharmony_ci * @cmd: UIC Command
16462306a36Sopenharmony_ci * @status: notify stage (pre, post change)
16562306a36Sopenharmony_ci */
16662306a36Sopenharmony_cistatic void cdns_ufs_hibern8_notify(struct ufs_hba *hba, enum uic_cmd_dme cmd,
16762306a36Sopenharmony_ci				    enum ufs_notify_change_status status)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	if (status == PRE_CHANGE && cmd == UIC_CMD_DME_HIBER_ENTER)
17062306a36Sopenharmony_ci		cdns_ufs_get_l4_attr(hba);
17162306a36Sopenharmony_ci	if (status == POST_CHANGE && cmd == UIC_CMD_DME_HIBER_EXIT)
17262306a36Sopenharmony_ci		cdns_ufs_set_l4_attr(hba);
17362306a36Sopenharmony_ci}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/**
17662306a36Sopenharmony_ci * cdns_ufs_link_startup_notify() - handle link startup.
17762306a36Sopenharmony_ci * @hba: host controller instance
17862306a36Sopenharmony_ci * @status: notify stage (pre, post change)
17962306a36Sopenharmony_ci *
18062306a36Sopenharmony_ci * Return: zero for success and non-zero for failure.
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_cistatic int cdns_ufs_link_startup_notify(struct ufs_hba *hba,
18362306a36Sopenharmony_ci					enum ufs_notify_change_status status)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	if (status != PRE_CHANGE)
18662306a36Sopenharmony_ci		return 0;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	/*
18962306a36Sopenharmony_ci	 * Some UFS devices have issues if LCC is enabled.
19062306a36Sopenharmony_ci	 * So we are setting PA_Local_TX_LCC_Enable to 0
19162306a36Sopenharmony_ci	 * before link startup which will make sure that both host
19262306a36Sopenharmony_ci	 * and device TX LCC are disabled once link startup is
19362306a36Sopenharmony_ci	 * completed.
19462306a36Sopenharmony_ci	 */
19562306a36Sopenharmony_ci	ufshcd_disable_host_tx_lcc(hba);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	/*
19862306a36Sopenharmony_ci	 * Disabling Autohibern8 feature in cadence UFS
19962306a36Sopenharmony_ci	 * to mask unexpected interrupt trigger.
20062306a36Sopenharmony_ci	 */
20162306a36Sopenharmony_ci	hba->ahit = 0;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	return 0;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/**
20762306a36Sopenharmony_ci * cdns_ufs_init - performs additional ufs initialization
20862306a36Sopenharmony_ci * @hba: host controller instance
20962306a36Sopenharmony_ci *
21062306a36Sopenharmony_ci * Return: status of initialization.
21162306a36Sopenharmony_ci */
21262306a36Sopenharmony_cistatic int cdns_ufs_init(struct ufs_hba *hba)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	int status = 0;
21562306a36Sopenharmony_ci	struct cdns_ufs_host *host;
21662306a36Sopenharmony_ci	struct device *dev = hba->dev;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (!host)
22162306a36Sopenharmony_ci		return -ENOMEM;
22262306a36Sopenharmony_ci	ufshcd_set_variant(hba, host);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	status = ufshcd_vops_phy_initialization(hba);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	return status;
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci/**
23062306a36Sopenharmony_ci * cdns_ufs_m31_16nm_phy_initialization - performs m31 phy initialization
23162306a36Sopenharmony_ci * @hba: host controller instance
23262306a36Sopenharmony_ci *
23362306a36Sopenharmony_ci * Return: 0 (success).
23462306a36Sopenharmony_ci */
23562306a36Sopenharmony_cistatic int cdns_ufs_m31_16nm_phy_initialization(struct ufs_hba *hba)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	u32 data;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	/* Increase RX_Advanced_Min_ActivateTime_Capability */
24062306a36Sopenharmony_ci	data = ufshcd_readl(hba, CDNS_UFS_REG_PHY_XCFGD1);
24162306a36Sopenharmony_ci	data |= BIT(24);
24262306a36Sopenharmony_ci	ufshcd_writel(hba, data, CDNS_UFS_REG_PHY_XCFGD1);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	return 0;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic const struct ufs_hba_variant_ops cdns_ufs_pltfm_hba_vops = {
24862306a36Sopenharmony_ci	.name = "cdns-ufs-pltfm",
24962306a36Sopenharmony_ci	.init = cdns_ufs_init,
25062306a36Sopenharmony_ci	.hce_enable_notify = cdns_ufs_hce_enable_notify,
25162306a36Sopenharmony_ci	.link_startup_notify = cdns_ufs_link_startup_notify,
25262306a36Sopenharmony_ci	.hibern8_notify = cdns_ufs_hibern8_notify,
25362306a36Sopenharmony_ci};
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic const struct ufs_hba_variant_ops cdns_ufs_m31_16nm_pltfm_hba_vops = {
25662306a36Sopenharmony_ci	.name = "cdns-ufs-pltfm",
25762306a36Sopenharmony_ci	.init = cdns_ufs_init,
25862306a36Sopenharmony_ci	.hce_enable_notify = cdns_ufs_hce_enable_notify,
25962306a36Sopenharmony_ci	.link_startup_notify = cdns_ufs_link_startup_notify,
26062306a36Sopenharmony_ci	.phy_initialization = cdns_ufs_m31_16nm_phy_initialization,
26162306a36Sopenharmony_ci	.hibern8_notify = cdns_ufs_hibern8_notify,
26262306a36Sopenharmony_ci};
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic const struct of_device_id cdns_ufs_of_match[] = {
26562306a36Sopenharmony_ci	{
26662306a36Sopenharmony_ci		.compatible = "cdns,ufshc",
26762306a36Sopenharmony_ci		.data =  &cdns_ufs_pltfm_hba_vops,
26862306a36Sopenharmony_ci	},
26962306a36Sopenharmony_ci	{
27062306a36Sopenharmony_ci		.compatible = "cdns,ufshc-m31-16nm",
27162306a36Sopenharmony_ci		.data =  &cdns_ufs_m31_16nm_pltfm_hba_vops,
27262306a36Sopenharmony_ci	},
27362306a36Sopenharmony_ci	{ },
27462306a36Sopenharmony_ci};
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, cdns_ufs_of_match);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci/**
27962306a36Sopenharmony_ci * cdns_ufs_pltfrm_probe - probe routine of the driver
28062306a36Sopenharmony_ci * @pdev: pointer to platform device handle
28162306a36Sopenharmony_ci *
28262306a36Sopenharmony_ci * Return: zero for success and non-zero for failure.
28362306a36Sopenharmony_ci */
28462306a36Sopenharmony_cistatic int cdns_ufs_pltfrm_probe(struct platform_device *pdev)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	int err;
28762306a36Sopenharmony_ci	const struct of_device_id *of_id;
28862306a36Sopenharmony_ci	struct ufs_hba_variant_ops *vops;
28962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	of_id = of_match_node(cdns_ufs_of_match, dev->of_node);
29262306a36Sopenharmony_ci	vops = (struct ufs_hba_variant_ops *)of_id->data;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	/* Perform generic probe */
29562306a36Sopenharmony_ci	err = ufshcd_pltfrm_init(pdev, vops);
29662306a36Sopenharmony_ci	if (err)
29762306a36Sopenharmony_ci		dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	return err;
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci/**
30362306a36Sopenharmony_ci * cdns_ufs_pltfrm_remove - removes the ufs driver
30462306a36Sopenharmony_ci * @pdev: pointer to platform device handle
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci * Return: 0 (success).
30762306a36Sopenharmony_ci */
30862306a36Sopenharmony_cistatic int cdns_ufs_pltfrm_remove(struct platform_device *pdev)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	struct ufs_hba *hba =  platform_get_drvdata(pdev);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	ufshcd_remove(hba);
31362306a36Sopenharmony_ci	return 0;
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
31762306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
31862306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
31962306a36Sopenharmony_ci	.prepare	 = ufshcd_suspend_prepare,
32062306a36Sopenharmony_ci	.complete	 = ufshcd_resume_complete,
32162306a36Sopenharmony_ci};
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_cistatic struct platform_driver cdns_ufs_pltfrm_driver = {
32462306a36Sopenharmony_ci	.probe	= cdns_ufs_pltfrm_probe,
32562306a36Sopenharmony_ci	.remove	= cdns_ufs_pltfrm_remove,
32662306a36Sopenharmony_ci	.driver	= {
32762306a36Sopenharmony_ci		.name   = "cdns-ufshcd",
32862306a36Sopenharmony_ci		.pm     = &cdns_ufs_dev_pm_ops,
32962306a36Sopenharmony_ci		.of_match_table = cdns_ufs_of_match,
33062306a36Sopenharmony_ci	},
33162306a36Sopenharmony_ci};
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cimodule_platform_driver(cdns_ufs_pltfrm_driver);
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ciMODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
33662306a36Sopenharmony_ciMODULE_DESCRIPTION("Cadence UFS host controller platform driver");
33762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
338