162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Link Layer for Samsung S3FWRN5 NCI based Driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2015 Samsung Electrnoics
662306a36Sopenharmony_ci * Robert Baldyga <r.baldyga@samsung.com>
762306a36Sopenharmony_ci * Copyright (C) 2020 Samsung Electrnoics
862306a36Sopenharmony_ci * Bongsu Jeon <bongsu.jeon@samsung.com>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/gpio.h>
1262306a36Sopenharmony_ci#include <linux/delay.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "phy_common.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_civoid s3fwrn5_phy_set_wake(void *phy_id, bool wake)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	struct phy_common *phy = phy_id;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	mutex_lock(&phy->mutex);
2262306a36Sopenharmony_ci	gpio_set_value(phy->gpio_fw_wake, wake);
2362306a36Sopenharmony_ci	if (wake)
2462306a36Sopenharmony_ci		msleep(S3FWRN5_EN_WAIT_TIME);
2562306a36Sopenharmony_ci	mutex_unlock(&phy->mutex);
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ciEXPORT_SYMBOL(s3fwrn5_phy_set_wake);
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cibool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	if (phy->mode == mode)
3262306a36Sopenharmony_ci		return false;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	phy->mode = mode;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	gpio_set_value(phy->gpio_en, 1);
3762306a36Sopenharmony_ci	gpio_set_value(phy->gpio_fw_wake, 0);
3862306a36Sopenharmony_ci	if (mode == S3FWRN5_MODE_FW)
3962306a36Sopenharmony_ci		gpio_set_value(phy->gpio_fw_wake, 1);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (mode != S3FWRN5_MODE_COLD) {
4262306a36Sopenharmony_ci		msleep(S3FWRN5_EN_WAIT_TIME);
4362306a36Sopenharmony_ci		gpio_set_value(phy->gpio_en, 0);
4462306a36Sopenharmony_ci		msleep(S3FWRN5_EN_WAIT_TIME);
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	return true;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ciEXPORT_SYMBOL(s3fwrn5_phy_power_ctrl);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_civoid s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct phy_common *phy = phy_id;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	mutex_lock(&phy->mutex);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	s3fwrn5_phy_power_ctrl(phy, mode);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	mutex_unlock(&phy->mutex);
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ciEXPORT_SYMBOL(s3fwrn5_phy_set_mode);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cienum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct phy_common *phy = phy_id;
6662306a36Sopenharmony_ci	enum s3fwrn5_mode mode;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	mutex_lock(&phy->mutex);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	mode = phy->mode;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	mutex_unlock(&phy->mutex);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	return mode;
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ciEXPORT_SYMBOL(s3fwrn5_phy_get_mode);
77