diff options
author | Yuvaraj Kumar C D <yuvaraj.cd@gmail.com> | 2013-05-17 15:56:24 +0530 |
---|---|---|
committer | Andrey Konovalov <andrey.konovalov@linaro.org> | 2014-04-16 23:51:34 +0400 |
commit | 6f7f0bd9ad62bda74b48a950418aa676b6884f2b (patch) | |
tree | f4942f403eb0f6f9effad5cae821257f098bd862 /drivers/ata/sata_phy.c | |
parent | 4c6484650554ca333492b7b4ed190a5c748cfd2b (diff) |
ata: samsung: Rebase as per 3.10-rc1
This patchset integrate the SATA patches submitted by Vasanth Ananthan.
In addition to that SATA and SATA PHY driver will use common clock
framework API.
Signed-off-by: Vasanth Ananthan <vasanth.a@samsung.com>
Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>
Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
Diffstat (limited to 'drivers/ata/sata_phy.c')
-rw-r--r-- | drivers/ata/sata_phy.c | 107 |
1 files changed, 75 insertions, 32 deletions
diff --git a/drivers/ata/sata_phy.c b/drivers/ata/sata_phy.c index e5631a97951..53d441775d7 100644 --- a/drivers/ata/sata_phy.c +++ b/drivers/ata/sata_phy.c @@ -2,7 +2,14 @@ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * EXYNOS - SATA utility framework. + * SATA PHY framework. + * + * This file provides a set of functions/interfaces for establishing + * communication between SATA controller and the PHY controller. A + * PHY controller driver registers call backs for its initialization and + * shutdown. The SATA controller driver finds the appropriate PHYs for + * its implemented ports and initialize/shutdown PHYs through the + * call backs provided. * * 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 @@ -20,47 +27,59 @@ static LIST_HEAD(phy_list); static DEFINE_SPINLOCK(phy_lock); -struct sata_phy *sata_get_phy(enum sata_phy_type type) +struct sata_phy *sata_get_phy(struct device_node *phy_np) { - struct sata_phy *x = NULL; + struct sata_phy *phy; unsigned long flag; - if (list_empty(&phy_list)) - return x; - spin_lock_irqsave(&phy_lock, flag); - list_for_each_entry(x, &phy_list, head) { - if (x->type == type) { - get_device(x->dev); - break; + if (list_empty(&phy_list)) { + spin_unlock_irqrestore(&phy_lock, flag); + return ERR_PTR(-ENODEV); + } + + list_for_each_entry(phy, &phy_list, head) { + if (phy->dev->of_node == phy_np) { + if (phy->status == IN_USE) { + pr_info(KERN_INFO + "PHY already in use\n"); + spin_unlock_irqrestore(&phy_lock, flag); + return ERR_PTR(-EBUSY); + } + + get_device(phy->dev); + phy->status = IN_USE; + spin_unlock_irqrestore(&phy_lock, flag); + return phy; } } spin_unlock_irqrestore(&phy_lock, flag); - return x; + return ERR_PTR(-ENODEV); } EXPORT_SYMBOL(sata_get_phy); -int sata_add_phy(struct sata_phy *phy, enum sata_phy_type type) +int sata_add_phy(struct sata_phy *sataphy) { unsigned long flag; unsigned int ret = -EINVAL; - struct sata_phy *x; + struct sata_phy *phy; - spin_lock_irqsave(&phy_lock, flag); - - if (!phy) + if (!sataphy) return ret; - list_for_each_entry(x, &phy_list, head) { - if (x->type == type) { - dev_err(phy->dev, "transceiver type already exists\n"); + spin_lock_irqsave(&phy_lock, flag); + + list_for_each_entry(phy, &phy_list, head) { + if (phy->dev->of_node == sataphy->dev->of_node) { + dev_err(sataphy->dev, "PHY already exists in the list\n"); goto out; } } - phy->type = type; - list_add_tail(&phy->head, &phy_list); + + sataphy->status = NOT_IN_USE; + list_add_tail(&sataphy->head, &phy_list); ret = 0; out: @@ -69,18 +88,24 @@ int sata_add_phy(struct sata_phy *phy, enum sata_phy_type type) } EXPORT_SYMBOL(sata_add_phy); -void sata_remove_phy(struct sata_phy *phy) +void sata_remove_phy(struct sata_phy *sataphy) { unsigned long flag; - struct sata_phy *x; + struct sata_phy *phy; - spin_lock_irqsave(&phy_lock, flag); + if (!sataphy) + return; - if (!phy) + if (sataphy->status == IN_USE) { + pr_info(KERN_INFO + "PHY in use, cannot be removed\n"); return; + } + + spin_lock_irqsave(&phy_lock, flag); - list_for_each_entry(x, &phy_list, head) { - if (x->type == phy->type) + list_for_each_entry(phy, &phy_list, head) { + if (phy->dev->of_node == sataphy->dev->of_node) list_del(&phy->head); } @@ -88,17 +113,35 @@ void sata_remove_phy(struct sata_phy *phy) } EXPORT_SYMBOL(sata_remove_phy); -void sata_put_phy(struct sata_phy *phy) +void sata_put_phy(struct sata_phy *sataphy) { unsigned long flag; + if (!sataphy) + return; + spin_lock_irqsave(&phy_lock, flag); - if (!phy) - return; + put_device(sataphy->dev); + sataphy->status = NOT_IN_USE; - put_device(phy->dev); spin_unlock_irqrestore(&phy_lock, flag); - } EXPORT_SYMBOL(sata_put_phy); + +int sata_init_phy(struct sata_phy *sataphy) +{ + if (sataphy && sataphy->init) + return sataphy->init(sataphy); + + return -EINVAL; +} +EXPORT_SYMBOL(sata_init_phy); + +void sata_shutdown_phy(struct sata_phy *sataphy) +{ + if (sataphy && sataphy->shutdown) + sataphy->shutdown(sataphy); +} +EXPORT_SYMBOL(sata_shutdown_phy); + |