* [RFC V3 0/2] Add support for pci/non-pci probing for UFS
@ 2012-05-21 6:31 Girish K S
2012-05-21 6:31 ` [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules Girish K S
2012-05-21 6:31 ` [RFC V3 2/2] SCSI: UFS: Add platform support for ufs host controller Girish K S
0 siblings, 2 replies; 9+ messages in thread
From: Girish K S @ 2012-05-21 6:31 UTC (permalink / raw)
To: linux-scsi
Cc: james.bottomley, vinholikatti, santoshsy, hch, patches, svenkatr,
Girish K S
The existing UFS driver is tightly bound to only pci specific devices.
It cannot work for non-pci devices.
"SCSI: UFS: Create separate UFS core and pci modules" patch splits the
ufs driver into core driver and pci probe driver.
"SCSI: UFS: Add platform support for ufs host controller" patch adds
support for the platform probing for non-pci devices
changes in v3:
-Modified the ufshcd.c ufshcd-pci.c ufshcd0pltfm.c to follow the
driver module initialization standard. suggested by venkatraman.
changes in v2:
Reduced the number of patches from 4 to 2. merged the core and
pci probing modules as single patch. suggested by Christoph Hellwig.
changes in v1:
Changes suggested by Namjae to split the existing driver as 3 independent
modules and retain the author's name in the files created by me.
Girish K S (2):
SCSI: UFS: Create separate UFS core and pci modules
SCSI: UFS: Add platform support for ufs host controller
drivers/scsi/ufs/Kconfig | 32 +++-
drivers/scsi/ufs/Makefile | 2 +
drivers/scsi/ufs/ufs.h | 103 +++++++++++
drivers/scsi/ufs/ufshcd-pci.c | 206 ++++++++++++++++++++++
drivers/scsi/ufs/ufshcd-pltfm.c | 180 +++++++++++++++++++
drivers/scsi/ufs/ufshcd.c | 370 ++++++++++-----------------------------
6 files changed, 615 insertions(+), 278 deletions(-)
create mode 100644 drivers/scsi/ufs/ufshcd-pci.c
create mode 100644 drivers/scsi/ufs/ufshcd-pltfm.c
--
1.7.4.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules
2012-05-21 6:31 [RFC V3 0/2] Add support for pci/non-pci probing for UFS Girish K S
@ 2012-05-21 6:31 ` Girish K S
2012-05-22 5:29 ` S, Venkatraman
2012-05-21 6:31 ` [RFC V3 2/2] SCSI: UFS: Add platform support for ufs host controller Girish K S
1 sibling, 1 reply; 9+ messages in thread
From: Girish K S @ 2012-05-21 6:31 UTC (permalink / raw)
To: linux-scsi
Cc: james.bottomley, vinholikatti, santoshsy, hch, patches, svenkatr,
Girish K S
The existing driver was pci specific. This patch removes the
pci specific code from the core driver. Irrespective of the
pci or non-pci probe, the same core driver can be re-used.
It also creates 2 separate modules of core and pci driver
Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
---
drivers/scsi/ufs/Kconfig | 19 ++-
drivers/scsi/ufs/Makefile | 1 +
drivers/scsi/ufs/ufs.h | 103 ++++++++++++
drivers/scsi/ufs/ufshcd-pci.c | 206 +++++++++++++++++++++++
drivers/scsi/ufs/ufshcd.c | 370 +++++++++++------------------------------
5 files changed, 421 insertions(+), 278 deletions(-)
create mode 100644 drivers/scsi/ufs/ufshcd-pci.c
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 8f27f9d..2a70972 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -44,6 +44,19 @@
config SCSI_UFSHCD
tristate "Universal Flash Storage host controller driver"
- depends on PCI && SCSI
- ---help---
- This is a generic driver which supports PCIe UFS Host controllers.
+ depends on SCSI
+ help
+ This is a generic driver which supports UFS Host controllers.
+ This option is selected automatically if the SCSI option is
+ selected. This is a core ufs driver.
+
+config SCSI_UFSHCD_PCI
+ tristate "Universal Flash Storage host support on PCI bus"
+ depends on SCSI_UFSHCD && PCI
+ help
+ This selects the PCI bus for the Universal Flash Storage IP.
+ Select this option if the IP is present on PCI platform.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index adf7895..9eda0df 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,2 +1,3 @@
# UFSHCD makefile
obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index b207529..dc36793 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -46,6 +46,8 @@
#ifndef _UFS_H
#define _UFS_H
+#define ufs_hostname(x) (dev_name(&(x)->dev))
+
#define MAX_CDB_SIZE 16
#define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
@@ -204,4 +206,105 @@ struct utp_upiu_task_rsp {
u32 reserved[3];
};
+/**
+ * struct uic_command - UIC command structure
+ * @command: UIC command
+ * @argument1: UIC command argument 1
+ * @argument2: UIC command argument 2
+ * @argument3: UIC command argument 3
+ * @cmd_active: Indicate if UIC command is outstanding
+ * @result: UIC command result
+ */
+struct uic_command {
+ u32 command;
+ u32 argument1;
+ u32 argument2;
+ u32 argument3;
+ int cmd_active;
+ int result;
+};
+
+struct ufs_pdata {
+ /* TODO */
+ u32 quirks; /* Quirk flags */
+};
+
+/**
+ * struct ufs_hba - per adapter private structure
+ * @mmio_base: UFSHCI base register address
+ * @ucdl_base_addr: UFS Command Descriptor base address
+ * @utrdl_base_addr: UTP Transfer Request Descriptor base address
+ * @utmrdl_base_addr: UTP Task Management Descriptor base address
+ * @ucdl_dma_addr: UFS Command Descriptor DMA address
+ * @utrdl_dma_addr: UTRDL DMA address
+ * @utmrdl_dma_addr: UTMRDL DMA address
+ * @host: Scsi_Host instance of the driver
+ * @dev: device handle
+ * @lrb: local reference block
+ * @outstanding_tasks: Bits representing outstanding task requests
+ * @outstanding_reqs: Bits representing outstanding transfer requests
+ * @capabilities: UFS Controller Capabilities
+ * @nutrs: Transfer Request Queue depth supported by controller
+ * @nutmrs: Task Management Queue depth supported by controller
+ * @active_uic_cmd: handle of active UIC command
+ * @ufshcd_tm_wait_queue: wait queue for task management
+ * @tm_condition: condition variable for task management
+ * @ufshcd_state: UFSHCD states
+ * @int_enable_mask: Interrupt Mask Bits
+ * @uic_workq: Work queue for UIC completion handling
+ * @feh_workq: Work queue for fatal controller error handling
+ * @errors: HBA errors
+ */
+struct ufs_hba {
+ void __iomem *mmio_base;
+
+ /* Virtual memory reference */
+ struct utp_transfer_cmd_desc *ucdl_base_addr;
+ struct utp_transfer_req_desc *utrdl_base_addr;
+ struct utp_task_req_desc *utmrdl_base_addr;
+
+ /* DMA memory reference */
+ dma_addr_t ucdl_dma_addr;
+ dma_addr_t utrdl_dma_addr;
+ dma_addr_t utmrdl_dma_addr;
+
+ struct Scsi_Host *host;
+ struct device dev;
+
+ struct ufshcd_lrb *lrb;
+
+ unsigned long outstanding_tasks;
+ unsigned long outstanding_reqs;
+
+ u32 capabilities;
+ int nutrs;
+ int nutmrs;
+ u32 ufs_version;
+
+ struct uic_command active_uic_cmd;
+ wait_queue_head_t ufshcd_tm_wait_queue;
+ unsigned long tm_condition;
+
+ u32 ufshcd_state;
+ u32 int_enable_mask;
+
+ /* Work Queues */
+ struct work_struct uic_workq;
+ struct work_struct feh_workq;
+
+ /* HBA Errors */
+ u32 errors;
+
+ unsigned int irq;
+};
+
+extern int ufshcd_initialize_hba(struct ufs_hba *hba);
+extern int ufshcd_drv_init(struct ufs_hba **hostdat, struct device *dev,
+ int irq_no, void __iomem *mmio_base);
+extern void ufshcd_drv_exit(struct ufs_hba *hba);
+#ifdef CONFIG_PM
+extern int ufshcd_suspend(struct ufs_hba *hba);
+extern int ufshcd_resume(struct ufs_hba *hba);
+#endif /* CONFIG_PM */
+
#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
new file mode 100644
index 0000000..e306573
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -0,0 +1,206 @@
+/*
+ * Universal Flash Storage Host controller driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd.c
+ * Copyright (C) 2011-2012 Samsung India Software Operations
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <scsi/scsi_host.h>
+
+#include "ufs.h"
+#include "ufshci.h"
+
+/**
+ * ufshcd_pci_set_dma_mask - Set dma mask based on the controller
+ * addressing capability
+ * @ihba: pointer to host platform data
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_pci_set_dma_mask(struct pci_dev *pdev)
+{
+ int err;
+ u64 dma_mask;
+
+ /*
+ * If controller supports 64 bit addressing mode, then set the DMA
+ * mask to 64-bit, else set the DMA mask to 32-bit
+ */
+ dma_mask = DMA_BIT_MASK(64);
+ err = pci_set_dma_mask(pdev, dma_mask);
+ if (err) {
+ dma_mask = DMA_BIT_MASK(32);
+ err = pci_set_dma_mask(pdev, dma_mask);
+ }
+
+ if (err)
+ return err;
+
+ err = pci_set_consistent_dma_mask(pdev, dma_mask);
+
+ return err;
+}
+
+static int __devinit ufshcd_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *entries)
+{
+ struct ufs_hba *uninitialized_var(hba);
+ int err;
+ void __iomem *mmio_base;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_device failed\n");
+ goto err_return;
+ }
+
+ pci_set_master(pdev);
+
+ err = pci_request_regions(pdev, "ufshcd-pci");
+ if (err < 0) {
+ dev_err(&pdev->dev, "request regions failed\n");
+ goto err_disable;
+ }
+
+ mmio_base = pci_ioremap_bar(pdev, 0);
+ if (!mmio_base) {
+ dev_err(&pdev->dev, "memory map failed\n");
+ err = -ENOMEM;
+ goto err_release;
+ }
+
+ err = ufshcd_pci_set_dma_mask(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "set dma mask failed\n");
+ goto err_iounmap;
+ }
+
+ err = ufshcd_drv_init(&hba, &pdev->dev, pdev->irq, mmio_base);
+ if (err)
+ goto err_iounmap;
+
+ pci_set_drvdata(pdev, hba);
+
+ /* Initialization routine */
+ err = ufshcd_initialize_hba(hba);
+ if (err) {
+ dev_err(&hba->dev, "Initialization failed\n");
+ goto err_remove;
+ }
+
+ return err;
+
+err_remove:
+ ufshcd_drv_exit(hba);
+err_iounmap:
+ iounmap(hba->mmio_base);
+err_release:
+ pci_release_regions(pdev);
+err_disable:
+ pci_clear_master(pdev);
+ pci_disable_device(pdev);
+err_return:
+ return err;
+}
+
+static void __devexit ufshcd_pci_remove(struct pci_dev *pdev)
+{
+ struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+ ufshcd_drv_exit(hba);
+ iounmap(hba->mmio_base);
+ pci_set_drvdata(pdev, NULL);
+ pci_clear_master(pdev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int ufshcd_pci_suspend(struct device *dev)
+{
+ int ret;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+ ret = ufshcd_suspend(hba);
+ return ret;
+}
+
+static int ufshcd_pci_resume(struct device *dev)
+{
+ int ret;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+ ret = ufshcd_resume(hba);
+ return ret;
+}
+#else
+#define ufshcd_pci_suspend NULL
+#define ufshcd_pci_resume NULL
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(ufshcd_pci_pmops,
+ ufshcd_pci_suspend,
+ ufshcd_pci_resume);
+
+static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_id) = {
+ { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(pci, ufshcd_pci_id);
+
+static struct pci_driver ufshcd_pci_driver = {
+ .name = "ufshcd-pci",
+ .id_table = ufshcd_pci_id,
+ .probe = ufshcd_pci_probe,
+ .remove = __devexit_p(ufshcd_pci_remove),
+ .driver = {
+ .pm = &ufshcd_pci_pmops
+ },
+};
+
+module_pci_driver(ufshcd_pci_driver);
+
+MODULE_DESCRIPTION("UFS Host Controller PCI Interface driver");
+MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e47a0da..4cfbfc5 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -46,7 +46,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/delay.h>
@@ -102,91 +101,6 @@ enum {
};
/**
- * struct uic_command - UIC command structure
- * @command: UIC command
- * @argument1: UIC command argument 1
- * @argument2: UIC command argument 2
- * @argument3: UIC command argument 3
- * @cmd_active: Indicate if UIC command is outstanding
- * @result: UIC command result
- */
-struct uic_command {
- u32 command;
- u32 argument1;
- u32 argument2;
- u32 argument3;
- int cmd_active;
- int result;
-};
-
-/**
- * struct ufs_hba - per adapter private structure
- * @mmio_base: UFSHCI base register address
- * @ucdl_base_addr: UFS Command Descriptor base address
- * @utrdl_base_addr: UTP Transfer Request Descriptor base address
- * @utmrdl_base_addr: UTP Task Management Descriptor base address
- * @ucdl_dma_addr: UFS Command Descriptor DMA address
- * @utrdl_dma_addr: UTRDL DMA address
- * @utmrdl_dma_addr: UTMRDL DMA address
- * @host: Scsi_Host instance of the driver
- * @pdev: PCI device handle
- * @lrb: local reference block
- * @outstanding_tasks: Bits representing outstanding task requests
- * @outstanding_reqs: Bits representing outstanding transfer requests
- * @capabilities: UFS Controller Capabilities
- * @nutrs: Transfer Request Queue depth supported by controller
- * @nutmrs: Task Management Queue depth supported by controller
- * @active_uic_cmd: handle of active UIC command
- * @ufshcd_tm_wait_queue: wait queue for task management
- * @tm_condition: condition variable for task management
- * @ufshcd_state: UFSHCD states
- * @int_enable_mask: Interrupt Mask Bits
- * @uic_workq: Work queue for UIC completion handling
- * @feh_workq: Work queue for fatal controller error handling
- * @errors: HBA errors
- */
-struct ufs_hba {
- void __iomem *mmio_base;
-
- /* Virtual memory reference */
- struct utp_transfer_cmd_desc *ucdl_base_addr;
- struct utp_transfer_req_desc *utrdl_base_addr;
- struct utp_task_req_desc *utmrdl_base_addr;
-
- /* DMA memory reference */
- dma_addr_t ucdl_dma_addr;
- dma_addr_t utrdl_dma_addr;
- dma_addr_t utmrdl_dma_addr;
-
- struct Scsi_Host *host;
- struct pci_dev *pdev;
-
- struct ufshcd_lrb *lrb;
-
- unsigned long outstanding_tasks;
- unsigned long outstanding_reqs;
-
- u32 capabilities;
- int nutrs;
- int nutmrs;
- u32 ufs_version;
-
- struct uic_command active_uic_cmd;
- wait_queue_head_t ufshcd_tm_wait_queue;
- unsigned long tm_condition;
-
- u32 ufshcd_state;
- u32 int_enable_mask;
-
- /* Work Queues */
- struct work_struct uic_workq;
- struct work_struct feh_workq;
-
- /* HBA Errors */
- u32 errors;
-};
-
-/**
* struct ufshcd_lrb - local reference block
* @utr_descriptor_ptr: UTRD address of the command
* @ucd_cmd_ptr: UCD address of the command
@@ -335,21 +249,21 @@ static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
if (hba->utmrdl_base_addr) {
utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
- dma_free_coherent(&hba->pdev->dev, utmrdl_size,
+ dma_free_coherent(&hba->dev, utmrdl_size,
hba->utmrdl_base_addr, hba->utmrdl_dma_addr);
}
if (hba->utrdl_base_addr) {
utrdl_size =
(sizeof(struct utp_transfer_req_desc) * hba->nutrs);
- dma_free_coherent(&hba->pdev->dev, utrdl_size,
+ dma_free_coherent(&hba->dev, utrdl_size,
hba->utrdl_base_addr, hba->utrdl_dma_addr);
}
if (hba->ucdl_base_addr) {
ucdl_size =
(sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
- dma_free_coherent(&hba->pdev->dev, ucdl_size,
+ dma_free_coherent(&hba->dev, ucdl_size,
hba->ucdl_base_addr, hba->ucdl_dma_addr);
}
}
@@ -724,7 +638,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/* Allocate memory for UTP command descriptors */
ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
- hba->ucdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
+ hba->ucdl_base_addr = dma_alloc_coherent(&hba->dev,
ucdl_size,
&hba->ucdl_dma_addr,
GFP_KERNEL);
@@ -737,7 +651,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
*/
if (!hba->ucdl_base_addr ||
WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Command Descriptor Memory allocation failed\n");
goto out;
}
@@ -747,13 +661,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
* UFSHCI requires 1024 byte alignment of UTRD
*/
utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
- hba->utrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
+ hba->utrdl_base_addr = dma_alloc_coherent(&hba->dev,
utrdl_size,
&hba->utrdl_dma_addr,
GFP_KERNEL);
if (!hba->utrdl_base_addr ||
WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Transfer Descriptor Memory allocation failed\n");
goto out;
}
@@ -763,13 +677,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
* UFSHCI requires 1024 byte alignment of UTMRD
*/
utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
- hba->utmrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
+ hba->utmrdl_base_addr = dma_alloc_coherent(&hba->dev,
utmrdl_size,
&hba->utmrdl_dma_addr,
GFP_KERNEL);
if (!hba->utmrdl_base_addr ||
WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Task Management Descriptor Memory allocation failed\n");
goto out;
}
@@ -777,7 +691,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/* Allocate memory for local reference block */
hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL);
if (!hba->lrb) {
- dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n");
+ dev_err(&hba->dev, "LRB Memory allocation failed\n");
goto out;
}
return 0;
@@ -867,7 +781,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
/* check if controller is ready to accept UIC commands */
if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
UIC_COMMAND_READY) == 0x0) {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Controller not ready"
" to accept UIC commands\n");
return -EIO;
@@ -912,7 +826,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
/* check if device present */
reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
if (!ufshcd_is_device_present(reg)) {
- dev_err(&hba->pdev->dev, "cc: Device not present\n");
+ dev_err(&hba->dev, "cc: Device not present\n");
err = -ENXIO;
goto out;
}
@@ -924,7 +838,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
if (!(ufshcd_get_lists_status(reg))) {
ufshcd_enable_run_stop_reg(hba);
} else {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Host controller not ready to process requests");
err = -EIO;
goto out;
@@ -1005,7 +919,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
if (retry) {
retry--;
} else {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Controller enable failed\n");
return -EIO;
}
@@ -1015,37 +929,6 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
}
/**
- * ufshcd_initialize_hba - start the initialization process
- * @hba: per adapter instance
- *
- * 1. Enable the controller via ufshcd_hba_enable.
- * 2. Program the Transfer Request List Address with the starting address of
- * UTRDL.
- * 3. Program the Task Management Request List Address with starting address
- * of UTMRDL.
- *
- * Returns 0 on success, non-zero value on failure.
- */
-static int ufshcd_initialize_hba(struct ufs_hba *hba)
-{
- if (ufshcd_hba_enable(hba))
- return -EIO;
-
- /* Configure UTRL and UTMRL base address registers */
- writel(lower_32_bits(hba->utrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
- writel(upper_32_bits(hba->utrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
- writel(lower_32_bits(hba->utmrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
- writel(upper_32_bits(hba->utmrdl_dma_addr),
- (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
-
- /* Initialize unipro link startup procedure */
- return ufshcd_dme_link_startup(hba);
-}
-
-/**
* ufshcd_do_reset - reset the host controller
* @hba: per adapter instance
*
@@ -1084,7 +967,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
/* start the initialization process */
if (ufshcd_initialize_hba(hba)) {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Reset: Controller initialization failed\n");
return FAILED;
}
@@ -1167,7 +1050,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
task_result = SUCCESS;
} else {
task_result = FAILED;
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"trc: Invalid ocs = %x\n", ocs_value);
}
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -1281,7 +1164,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
/* check if the returned transfer response is valid */
result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
if (result) {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Invalid response = %x\n", result);
break;
}
@@ -1310,7 +1193,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
case OCS_FATAL_ERROR:
default:
result |= DID_ERROR << 16;
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"OCS error from controller = %x\n", ocs);
break;
} /* end of switch */
@@ -1374,7 +1257,7 @@ static void ufshcd_uic_cc_handler (struct work_struct *work)
!(ufshcd_get_uic_cmd_result(hba))) {
if (ufshcd_make_hba_operational(hba))
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"cc: hba not operational state\n");
return;
}
@@ -1509,7 +1392,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
free_slot = ufshcd_get_tm_free_slot(hba);
if (free_slot >= hba->nutmrs) {
spin_unlock_irqrestore(host->host_lock, flags);
- dev_err(&hba->pdev->dev, "Task management queue full\n");
+ dev_err(&hba->dev, "Task management queue full\n");
err = FAILED;
goto out;
}
@@ -1552,7 +1435,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
&hba->tm_condition) != 0),
60 * HZ);
if (!err) {
- dev_err(&hba->pdev->dev,
+ dev_err(&hba->dev,
"Task management command timed-out\n");
err = FAILED;
goto out;
@@ -1688,23 +1571,46 @@ static struct scsi_host_template ufshcd_driver_template = {
};
/**
- * ufshcd_shutdown - main function to put the controller in reset state
- * @pdev: pointer to PCI device handle
+ * ufshcd_initialize_hba - start the initialization process
+ * @hba: per adapter instance
+ *
+ * 1. Enable the controller via ufshcd_hba_enable.
+ * 2. Program the Transfer Request List Address with the starting address of
+ * UTRDL.
+ * 3. Program the Task Management Request List Address with starting address
+ * of UTMRDL.
+ *
+ * Returns 0 on success, non-zero value on failure.
*/
-static void ufshcd_shutdown(struct pci_dev *pdev)
+int ufshcd_initialize_hba(struct ufs_hba *hba)
{
- ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
+ if (ufshcd_hba_enable(hba))
+ return -EIO;
+
+ /* Configure UTRL and UTMRL base address registers */
+ writel(hba->utrdl_dma_addr,
+ (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
+ writel(lower_32_bits(hba->utrdl_dma_addr),
+ (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
+ writel(hba->utmrdl_dma_addr,
+ (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
+ writel(upper_32_bits(hba->utmrdl_dma_addr),
+ (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
+
+ /* Initialize unipro link startup procedure */
+ return ufshcd_dme_link_startup(hba);
}
+EXPORT_SYMBOL(ufshcd_initialize_hba);
#ifdef CONFIG_PM
/**
* ufshcd_suspend - suspend power management function
- * @pdev: pointer to PCI device handle
+ * @hba: pointer to host controller platform data
* @state: power state
*
* Returns -ENOSYS
*/
-static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
+int ufshcd_suspend(struct ufs_hba *hba)
{
/*
* TODO:
@@ -1717,14 +1623,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
return -ENOSYS;
}
+EXPORT_SYMBOL(ufshcd_suspend);
/**
* ufshcd_resume - resume power management function
- * @pdev: pointer to PCI device handle
+ * @hba: pointer to host controller platform data
*
* Returns -ENOSYS
*/
-static int ufshcd_resume(struct pci_dev *pdev)
+int ufshcd_resume(struct ufs_hba *hba)
{
/*
* TODO:
@@ -1737,119 +1644,55 @@ static int ufshcd_resume(struct pci_dev *pdev)
return -ENOSYS;
}
-#endif /* CONFIG_PM */
+EXPORT_SYMBOL(ufshcd_resume);
-/**
- * ufshcd_hba_free - free allocated memory for
- * host memory space data structures
- * @hba: per adapter instance
- */
-static void ufshcd_hba_free(struct ufs_hba *hba)
-{
- iounmap(hba->mmio_base);
- ufshcd_free_hba_memory(hba);
- pci_release_regions(hba->pdev);
-}
+#endif /* CONFIG_PM */
/**
- * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
+ * ufshcd_drv_exit - de-allocate SCSI host and host memory space
* data structure memory
- * @pdev - pointer to PCI handle
+ * @dev - pointer to host platform data
*/
-static void ufshcd_remove(struct pci_dev *pdev)
+void ufshcd_drv_exit(struct ufs_hba *hba)
{
- struct ufs_hba *hba = pci_get_drvdata(pdev);
-
/* disable interrupts */
ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
- free_irq(pdev->irq, hba);
+ free_irq(hba->irq, hba);
ufshcd_hba_stop(hba);
- ufshcd_hba_free(hba);
+ ufshcd_free_hba_memory(hba);
scsi_remove_host(hba->host);
scsi_host_put(hba->host);
- pci_set_drvdata(pdev, NULL);
- pci_clear_master(pdev);
- pci_disable_device(pdev);
}
+EXPORT_SYMBOL(ufshcd_drv_exit);
/**
- * ufshcd_set_dma_mask - Set dma mask based on the controller
- * addressing capability
- * @pdev: PCI device structure
- *
- * Returns 0 for success, non-zero for failure
- */
-static int ufshcd_set_dma_mask(struct ufs_hba *hba)
-{
- int err;
- u64 dma_mask;
-
- /*
- * If controller supports 64 bit addressing mode, then set the DMA
- * mask to 64-bit, else set the DMA mask to 32-bit
- */
- if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
- dma_mask = DMA_BIT_MASK(64);
- else
- dma_mask = DMA_BIT_MASK(32);
-
- err = pci_set_dma_mask(hba->pdev, dma_mask);
- if (err)
- return err;
-
- err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
-
- return err;
-}
-
-/**
- * ufshcd_probe - probe routine of the driver
- * @pdev: pointer to PCI device handle
- * @id: PCI device id
+ * ufshcd_drv_init - generic init routine of the driver
+ * @hba: pointer to platform data
*
* Returns 0 on success, non-zero value on failure
*/
-static int __devinit
-ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int ufshcd_drv_init(struct ufs_hba **hostdata, struct device *dev,
+ int irq_no, void __iomem *mmio_base)
{
struct Scsi_Host *host;
- struct ufs_hba *hba;
int err;
-
- err = pci_enable_device(pdev);
- if (err) {
- dev_err(&pdev->dev, "pci_enable_device failed\n");
- goto out_error;
- }
-
- pci_set_master(pdev);
+ struct ufs_hba *hba;
host = scsi_host_alloc(&ufshcd_driver_template,
sizeof(struct ufs_hba));
if (!host) {
- dev_err(&pdev->dev, "scsi_host_alloc failed\n");
+ dev_err(&hba->dev, "scsi_host_alloc failed\n");
err = -ENOMEM;
goto out_disable;
}
hba = shost_priv(host);
-
- err = pci_request_regions(pdev, UFSHCD);
- if (err < 0) {
- dev_err(&pdev->dev, "request regions failed\n");
- goto out_disable;
- }
-
- hba->mmio_base = pci_ioremap_bar(pdev, 0);
- if (!hba->mmio_base) {
- dev_err(&pdev->dev, "memory map failed\n");
- err = -ENOMEM;
- goto out_release_regions;
- }
-
+ hba->dev = *dev;
hba->host = host;
- hba->pdev = pdev;
+ hba->irq = irq_no;
+ hba->mmio_base = mmio_base;
+ *hostdata = hba;
/* Read capabilities registers */
ufshcd_hba_capabilities(hba);
@@ -1857,17 +1700,11 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Get UFS version supported by the controller */
hba->ufs_version = ufshcd_get_ufs_version(hba);
- err = ufshcd_set_dma_mask(hba);
- if (err) {
- dev_err(&pdev->dev, "set dma mask failed\n");
- goto out_iounmap;
- }
-
/* Allocate memory for host memory space */
err = ufshcd_memory_alloc(hba);
if (err) {
- dev_err(&pdev->dev, "Memory allocation failed\n");
- goto out_iounmap;
+ dev_err(&hba->dev, "Memory allocation failed\n");
+ goto out_disable;
}
/* Configure LRB */
@@ -1889,72 +1726,55 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
/* IRQ registration */
- err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+ err = request_irq(hba->irq, ufshcd_intr, IRQF_SHARED,
+ ufs_hostname(hba), hba);
if (err) {
- dev_err(&pdev->dev, "request irq failed\n");
+ dev_err(&hba->dev, "request irq failed\n");
goto out_lrb_free;
}
/* Enable SCSI tag mapping */
err = scsi_init_shared_tag_map(host, host->can_queue);
if (err) {
- dev_err(&pdev->dev, "init shared queue failed\n");
- goto out_free_irq;
- }
-
- pci_set_drvdata(pdev, hba);
-
- err = scsi_add_host(host, &pdev->dev);
- if (err) {
- dev_err(&pdev->dev, "scsi_add_host failed\n");
+ dev_err(&hba->dev, "init shared queue failed\n");
goto out_free_irq;
}
- /* Initialization routine */
- err = ufshcd_initialize_hba(hba);
+ err = scsi_add_host(host, &hba->dev);
if (err) {
- dev_err(&pdev->dev, "Initialization failed\n");
+ dev_err(&hba->dev, "scsi_add_host failed\n");
goto out_free_irq;
}
return 0;
out_free_irq:
- free_irq(pdev->irq, hba);
+ free_irq(hba->irq, hba);
out_lrb_free:
ufshcd_free_hba_memory(hba);
-out_iounmap:
- iounmap(hba->mmio_base);
-out_release_regions:
- pci_release_regions(pdev);
out_disable:
scsi_host_put(host);
- pci_clear_master(pdev);
- pci_disable_device(pdev);
-out_error:
return err;
}
+EXPORT_SYMBOL(ufshcd_drv_init);
-static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
- { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { } /* terminate list */
-};
+static int __init ufshcd_probe(void)
+{
+ pr_info(UFSHCD
+ ": Generic UFS host controller driver\n");
+ pr_info(UFSHCD ": Copyright(c) Samsung India Software Operations\n");
-MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
+ return 0;
+}
-static struct pci_driver ufshcd_pci_driver = {
- .name = UFSHCD,
- .id_table = ufshcd_pci_tbl,
- .probe = ufshcd_probe,
- .remove = __devexit_p(ufshcd_remove),
- .shutdown = ufshcd_shutdown,
-#ifdef CONFIG_PM
- .suspend = ufshcd_suspend,
- .resume = ufshcd_resume,
-#endif
-};
+static void __exit ufshcd_remove(void)
+{
+ pr_info(UFSHCD
+ ": Generic UFS host controller driver removed\n");
+}
-module_pci_driver(ufshcd_pci_driver);
+module_init(ufshcd_probe);
+module_exit(ufshcd_remove);
MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
"Vinayak Holikatti <h.vinayak@samsung.com>");
--
1.7.4.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC V3 2/2] SCSI: UFS: Add platform support for ufs host controller
2012-05-21 6:31 [RFC V3 0/2] Add support for pci/non-pci probing for UFS Girish K S
2012-05-21 6:31 ` [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules Girish K S
@ 2012-05-21 6:31 ` Girish K S
2012-05-22 5:37 ` S, Venkatraman
1 sibling, 1 reply; 9+ messages in thread
From: Girish K S @ 2012-05-21 6:31 UTC (permalink / raw)
To: linux-scsi
Cc: james.bottomley, vinholikatti, santoshsy, hch, patches, svenkatr,
Girish K S
This patch adds platform support for ufs host controller
The SoC's that use non-pci probing should use this option.
Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
---
drivers/scsi/ufs/Kconfig | 13 +++
drivers/scsi/ufs/Makefile | 1 +
drivers/scsi/ufs/ufshcd-pltfm.c | 180 +++++++++++++++++++++++++++++++++++++++
3 files changed, 194 insertions(+), 0 deletions(-)
create mode 100644 drivers/scsi/ufs/ufshcd-pltfm.c
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 2a70972..dae5428 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -60,3 +60,16 @@ config SCSI_UFSHCD_PCI
If you have a controller with this interface, say Y or M here.
If unsure, say N.
+
+config SCSI_UFSHCD_PLTFM
+ tristate "Universal Flash Storage host support as platform device"
+ depends on SCSI_UFSHCD
+ help
+ This selects the common helper functions support for Host Controller
+ Interface based platform driver. Please select this option if the IP
+ is present as a platform device. This is the common interface for the
+ UFS Host Controller IP.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 9eda0df..fc56471 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,3 +1,4 @@
# UFSHCD makefile
obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
+obj-$(CONFIG_SCSI_UFSHCD_PLTFM) += ufshcd-pltfm.o
diff --git a/drivers/scsi/ufs/ufshcd-pltfm.c b/drivers/scsi/ufs/ufshcd-pltfm.c
new file mode 100644
index 0000000..7558210
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pltfm.c
@@ -0,0 +1,180 @@
+/*
+ * Universal Flash Storage Host controller driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd.c
+ * Copyright (C) 2011-2012 Samsung India Software Operations
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <scsi/scsi_host.h>
+
+#include "ufs.h"
+#include "ufshci.h"
+
+/**
+ * ufshcd_pltfmset_dma_mask - Set dma mask based on the controller
+ * addressing capability
+ * @ihba: pointer to host platform data
+ *
+ * Returns 0 for success, non-zero for failure
+ */
+static int ufshcd_pltfm_set_dma_mask(struct platform_device *pdev)
+{
+ int err;
+ u64 dma_mask;
+
+ dma_mask = DMA_BIT_MASK(64);
+ err = dma_set_coherent_mask(&pdev->dev, dma_mask);
+ if (err) {
+ dma_mask = DMA_BIT_MASK(32);
+ err = dma_set_coherent_mask(&pdev->dev, dma_mask);
+ }
+
+ return err;
+}
+
+static int __devinit ufshcd_pltfm_probe(struct platform_device *pdev)
+{
+ struct ufs_hba *uninitialized_var(hba);
+ struct resource *regs;
+ int err, irq;
+ void __iomem *mmio_base;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs)
+ return -ENXIO;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ mmio_base = ioremap(regs->start, resource_size(regs));
+ if (!mmio_base)
+ return -ENOMEM;
+
+ err = ufshcd_pltfm_set_dma_mask(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "set dma mask failed\n");
+ goto err_iounmap;
+ }
+
+ err = ufshcd_drv_init(&hba, &pdev->dev, irq, mmio_base);
+ if (err)
+ goto err_iounmap;
+
+ platform_set_drvdata(pdev, hba);
+
+ /* Initialization routine */
+ err = ufshcd_initialize_hba(hba);
+ if (err) {
+ dev_err(&hba->dev, "Initialization failed\n");
+ goto err_remove;
+ }
+
+ return err;
+
+err_remove:
+ ufshcd_drv_exit(hba);
+err_iounmap:
+ iounmap(hba->mmio_base);
+ return err;
+}
+
+static int __devexit ufshcd_pltfm_remove(struct platform_device *pdev)
+{
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ ufshcd_drv_exit(hba);
+ iounmap(hba->mmio_base);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ufshcd_pltfm_suspend(struct device *dev)
+{
+ int ret;
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ ret = ufshcd_suspend(hba);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ufshcd_pltfm_resume(struct device *dev)
+{
+ int ret;
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ ret = ufshcd_resume(hba);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+#else
+#define ufshcd_pltfm_suspend NULL
+#define ufshcd_pltfm_resume NULL
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(ufshcd_pltfm_pmops,
+ ufshcd_pltfm_suspend,
+ ufshcd_pltfm_resume);
+
+static struct platform_driver ufshcd_pltfm_driver = {
+ .probe = ufshcd_pltfm_probe,
+ .remove = __devexit_p(ufshcd_pltfm_remove),
+ .driver = {
+ .name = "ufshcd-pltfm",
+ .pm = &ufshcd_pltfm_pmops,
+ },
+};
+
+module_platform_driver(ufshcd_pltfm_driver);
+
+MODULE_DESCRIPTION("UFS Host Controller platform Interface driver");
+MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
+MODULE_LICENSE("GPL");
--
1.7.4.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules
2012-05-21 6:31 ` [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules Girish K S
@ 2012-05-22 5:29 ` S, Venkatraman
2012-05-22 7:22 ` Girish K S
2012-05-22 7:34 ` James Bottomley
0 siblings, 2 replies; 9+ messages in thread
From: S, Venkatraman @ 2012-05-22 5:29 UTC (permalink / raw)
To: Girish K S
Cc: linux-scsi, james.bottomley, vinholikatti, santoshsy, hch, patches
On Mon, May 21, 2012 at 12:01 PM, Girish K S
<girish.shivananjappa@linaro.org> wrote:
> The existing driver was pci specific. This patch removes the
> pci specific code from the core driver. Irrespective of the
> pci or non-pci probe, the same core driver can be re-used.
>
> It also creates 2 separate modules of core and pci driver
>
> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> ---
> drivers/scsi/ufs/Kconfig | 19 ++-
> drivers/scsi/ufs/Makefile | 1 +
> drivers/scsi/ufs/ufs.h | 103 ++++++++++++
> drivers/scsi/ufs/ufshcd-pci.c | 206 +++++++++++++++++++++++
> drivers/scsi/ufs/ufshcd.c | 370 +++++++++++------------------------------
> 5 files changed, 421 insertions(+), 278 deletions(-)
> create mode 100644 drivers/scsi/ufs/ufshcd-pci.c
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index 8f27f9d..2a70972 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -44,6 +44,19 @@
>
> config SCSI_UFSHCD
> tristate "Universal Flash Storage host controller driver"
> - depends on PCI && SCSI
> - ---help---
> - This is a generic driver which supports PCIe UFS Host controllers.
> + depends on SCSI
> + help
> + This is a generic driver which supports UFS Host controllers.
> + This option is selected automatically if the SCSI option is
> + selected. This is a core ufs driver.
> +
> +config SCSI_UFSHCD_PCI
> + tristate "Universal Flash Storage host support on PCI bus"
> + depends on SCSI_UFSHCD && PCI
> + help
> + This selects the PCI bus for the Universal Flash Storage IP.
> + Select this option if the IP is present on PCI platform.
> +
> + If you have a controller with this interface, say Y or M here.
> +
> + If unsure, say N.
> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index adf7895..9eda0df 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -1,2 +1,3 @@
> # UFSHCD makefile
> obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> +obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index b207529..dc36793 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -46,6 +46,8 @@
> #ifndef _UFS_H
> #define _UFS_H
>
> +#define ufs_hostname(x) (dev_name(&(x)->dev))
> +
> #define MAX_CDB_SIZE 16
>
> #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
> @@ -204,4 +206,105 @@ struct utp_upiu_task_rsp {
> u32 reserved[3];
> };
>
> +/**
> + * struct uic_command - UIC command structure
> + * @command: UIC command
> + * @argument1: UIC command argument 1
> + * @argument2: UIC command argument 2
> + * @argument3: UIC command argument 3
> + * @cmd_active: Indicate if UIC command is outstanding
> + * @result: UIC command result
> + */
> +struct uic_command {
> + u32 command;
> + u32 argument1;
> + u32 argument2;
> + u32 argument3;
> + int cmd_active;
> + int result;
> +};
> +
> +struct ufs_pdata {
> + /* TODO */
> + u32 quirks; /* Quirk flags */
> +};
> +
> +/**
> + * struct ufs_hba - per adapter private structure
> + * @mmio_base: UFSHCI base register address
> + * @ucdl_base_addr: UFS Command Descriptor base address
> + * @utrdl_base_addr: UTP Transfer Request Descriptor base address
> + * @utmrdl_base_addr: UTP Task Management Descriptor base address
> + * @ucdl_dma_addr: UFS Command Descriptor DMA address
> + * @utrdl_dma_addr: UTRDL DMA address
> + * @utmrdl_dma_addr: UTMRDL DMA address
> + * @host: Scsi_Host instance of the driver
> + * @dev: device handle
> + * @lrb: local reference block
> + * @outstanding_tasks: Bits representing outstanding task requests
> + * @outstanding_reqs: Bits representing outstanding transfer requests
> + * @capabilities: UFS Controller Capabilities
> + * @nutrs: Transfer Request Queue depth supported by controller
> + * @nutmrs: Task Management Queue depth supported by controller
> + * @active_uic_cmd: handle of active UIC command
> + * @ufshcd_tm_wait_queue: wait queue for task management
> + * @tm_condition: condition variable for task management
> + * @ufshcd_state: UFSHCD states
> + * @int_enable_mask: Interrupt Mask Bits
> + * @uic_workq: Work queue for UIC completion handling
> + * @feh_workq: Work queue for fatal controller error handling
> + * @errors: HBA errors
> + */
> +struct ufs_hba {
> + void __iomem *mmio_base;
> +
> + /* Virtual memory reference */
> + struct utp_transfer_cmd_desc *ucdl_base_addr;
> + struct utp_transfer_req_desc *utrdl_base_addr;
> + struct utp_task_req_desc *utmrdl_base_addr;
> +
> + /* DMA memory reference */
> + dma_addr_t ucdl_dma_addr;
> + dma_addr_t utrdl_dma_addr;
> + dma_addr_t utmrdl_dma_addr;
> +
> + struct Scsi_Host *host;
> + struct device dev;
> +
> + struct ufshcd_lrb *lrb;
> +
> + unsigned long outstanding_tasks;
> + unsigned long outstanding_reqs;
> +
> + u32 capabilities;
> + int nutrs;
> + int nutmrs;
> + u32 ufs_version;
> +
> + struct uic_command active_uic_cmd;
> + wait_queue_head_t ufshcd_tm_wait_queue;
> + unsigned long tm_condition;
> +
> + u32 ufshcd_state;
> + u32 int_enable_mask;
> +
> + /* Work Queues */
> + struct work_struct uic_workq;
> + struct work_struct feh_workq;
> +
> + /* HBA Errors */
> + u32 errors;
> +
> + unsigned int irq;
> +};
> +
> +extern int ufshcd_initialize_hba(struct ufs_hba *hba);
> +extern int ufshcd_drv_init(struct ufs_hba **hostdat, struct device *dev,
> + int irq_no, void __iomem *mmio_base);
> +extern void ufshcd_drv_exit(struct ufs_hba *hba);
> +#ifdef CONFIG_PM
> +extern int ufshcd_suspend(struct ufs_hba *hba);
> +extern int ufshcd_resume(struct ufs_hba *hba);
> +#endif /* CONFIG_PM */
> +
> #endif /* End of Header */
> diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
> new file mode 100644
> index 0000000..e306573
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufshcd-pci.c
> @@ -0,0 +1,206 @@
> +/*
> + * Universal Flash Storage Host controller driver
> + *
> + * This code is based on drivers/scsi/ufs/ufshcd.c
> + * Copyright (C) 2011-2012 Samsung India Software Operations
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * NO WARRANTY
> + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
> + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
> + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
> + * solely responsible for determining the appropriateness of using and
> + * distributing the Program and assumes all risks associated with its
> + * exercise of rights under this Agreement, including but not limited to
> + * the risks and costs of program errors, damage to or loss of data,
> + * programs or equipment, and unavailability or interruption of operations.
> +
> + * DISCLAIMER OF LIABILITY
> + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
> + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
> +
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
> + * USA.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <linux/pci.h>
> +#include <scsi/scsi_host.h>
> +
> +#include "ufs.h"
> +#include "ufshci.h"
> +
> +/**
> + * ufshcd_pci_set_dma_mask - Set dma mask based on the controller
> + * addressing capability
> + * @ihba: pointer to host platform data
> + *
> + * Returns 0 for success, non-zero for failure
> + */
> +static int ufshcd_pci_set_dma_mask(struct pci_dev *pdev)
> +{
> + int err;
> + u64 dma_mask;
> +
> + /*
> + * If controller supports 64 bit addressing mode, then set the DMA
> + * mask to 64-bit, else set the DMA mask to 32-bit
> + */
> + dma_mask = DMA_BIT_MASK(64);
> + err = pci_set_dma_mask(pdev, dma_mask);
> + if (err) {
> + dma_mask = DMA_BIT_MASK(32);
> + err = pci_set_dma_mask(pdev, dma_mask);
> + }
> +
> + if (err)
> + return err;
> +
> + err = pci_set_consistent_dma_mask(pdev, dma_mask);
> +
> + return err;
> +}
> +
> +static int __devinit ufshcd_pci_probe(struct pci_dev *pdev,
> + const struct pci_device_id *entries)
> +{
> + struct ufs_hba *uninitialized_var(hba);
> + int err;
> + void __iomem *mmio_base;
> +
> + err = pci_enable_device(pdev);
> + if (err) {
> + dev_err(&pdev->dev, "pci_enable_device failed\n");
> + goto err_return;
> + }
> +
> + pci_set_master(pdev);
> +
> + err = pci_request_regions(pdev, "ufshcd-pci");
> + if (err < 0) {
> + dev_err(&pdev->dev, "request regions failed\n");
> + goto err_disable;
> + }
> +
> + mmio_base = pci_ioremap_bar(pdev, 0);
> + if (!mmio_base) {
> + dev_err(&pdev->dev, "memory map failed\n");
> + err = -ENOMEM;
> + goto err_release;
> + }
> +
> + err = ufshcd_pci_set_dma_mask(pdev);
> + if (err) {
> + dev_err(&pdev->dev, "set dma mask failed\n");
> + goto err_iounmap;
> + }
> +
> + err = ufshcd_drv_init(&hba, &pdev->dev, pdev->irq, mmio_base);
> + if (err)
> + goto err_iounmap;
> +
> + pci_set_drvdata(pdev, hba);
> +
> + /* Initialization routine */
> + err = ufshcd_initialize_hba(hba);
> + if (err) {
> + dev_err(&hba->dev, "Initialization failed\n");
> + goto err_remove;
> + }
> +
> + return err;
> +
> +err_remove:
> + ufshcd_drv_exit(hba);
> +err_iounmap:
> + iounmap(hba->mmio_base);
> +err_release:
> + pci_release_regions(pdev);
> +err_disable:
> + pci_clear_master(pdev);
> + pci_disable_device(pdev);
> +err_return:
> + return err;
> +}
> +
> +static void __devexit ufshcd_pci_remove(struct pci_dev *pdev)
> +{
> + struct ufs_hba *hba = pci_get_drvdata(pdev);
> +
> + ufshcd_drv_exit(hba);
> + iounmap(hba->mmio_base);
> + pci_set_drvdata(pdev, NULL);
> + pci_clear_master(pdev);
> + pci_release_regions(pdev);
> + pci_disable_device(pdev);
> +}
> +
> +#ifdef CONFIG_PM
> +static int ufshcd_pci_suspend(struct device *dev)
> +{
> + int ret;
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct ufs_hba *hba = pci_get_drvdata(pdev);
> +
> + ret = ufshcd_suspend(hba);
> + return ret;
> +}
> +
> +static int ufshcd_pci_resume(struct device *dev)
> +{
> + int ret;
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct ufs_hba *hba = pci_get_drvdata(pdev);
> +
> + ret = ufshcd_resume(hba);
> + return ret;
> +}
> +#else
> +#define ufshcd_pci_suspend NULL
> +#define ufshcd_pci_resume NULL
> +#endif /* CONFIG_PM */
> +
> +static SIMPLE_DEV_PM_OPS(ufshcd_pci_pmops,
> + ufshcd_pci_suspend,
> + ufshcd_pci_resume);
> +
> +static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_id) = {
> + { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(pci, ufshcd_pci_id);
> +
> +static struct pci_driver ufshcd_pci_driver = {
> + .name = "ufshcd-pci",
> + .id_table = ufshcd_pci_id,
> + .probe = ufshcd_pci_probe,
> + .remove = __devexit_p(ufshcd_pci_remove),
> + .driver = {
> + .pm = &ufshcd_pci_pmops
> + },
> +};
> +
> +module_pci_driver(ufshcd_pci_driver);
> +
> +MODULE_DESCRIPTION("UFS Host Controller PCI Interface driver");
> +MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index e47a0da..4cfbfc5 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -46,7 +46,6 @@
> #include <linux/module.h>
> #include <linux/kernel.h>
> #include <linux/init.h>
> -#include <linux/pci.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> #include <linux/delay.h>
> @@ -102,91 +101,6 @@ enum {
> };
>
> /**
> - * struct uic_command - UIC command structure
> - * @command: UIC command
> - * @argument1: UIC command argument 1
> - * @argument2: UIC command argument 2
> - * @argument3: UIC command argument 3
> - * @cmd_active: Indicate if UIC command is outstanding
> - * @result: UIC command result
> - */
> -struct uic_command {
> - u32 command;
> - u32 argument1;
> - u32 argument2;
> - u32 argument3;
> - int cmd_active;
> - int result;
> -};
> -
> -/**
> - * struct ufs_hba - per adapter private structure
> - * @mmio_base: UFSHCI base register address
> - * @ucdl_base_addr: UFS Command Descriptor base address
> - * @utrdl_base_addr: UTP Transfer Request Descriptor base address
> - * @utmrdl_base_addr: UTP Task Management Descriptor base address
> - * @ucdl_dma_addr: UFS Command Descriptor DMA address
> - * @utrdl_dma_addr: UTRDL DMA address
> - * @utmrdl_dma_addr: UTMRDL DMA address
> - * @host: Scsi_Host instance of the driver
> - * @pdev: PCI device handle
> - * @lrb: local reference block
> - * @outstanding_tasks: Bits representing outstanding task requests
> - * @outstanding_reqs: Bits representing outstanding transfer requests
> - * @capabilities: UFS Controller Capabilities
> - * @nutrs: Transfer Request Queue depth supported by controller
> - * @nutmrs: Task Management Queue depth supported by controller
> - * @active_uic_cmd: handle of active UIC command
> - * @ufshcd_tm_wait_queue: wait queue for task management
> - * @tm_condition: condition variable for task management
> - * @ufshcd_state: UFSHCD states
> - * @int_enable_mask: Interrupt Mask Bits
> - * @uic_workq: Work queue for UIC completion handling
> - * @feh_workq: Work queue for fatal controller error handling
> - * @errors: HBA errors
> - */
> -struct ufs_hba {
> - void __iomem *mmio_base;
> -
> - /* Virtual memory reference */
> - struct utp_transfer_cmd_desc *ucdl_base_addr;
> - struct utp_transfer_req_desc *utrdl_base_addr;
> - struct utp_task_req_desc *utmrdl_base_addr;
> -
> - /* DMA memory reference */
> - dma_addr_t ucdl_dma_addr;
> - dma_addr_t utrdl_dma_addr;
> - dma_addr_t utmrdl_dma_addr;
> -
> - struct Scsi_Host *host;
> - struct pci_dev *pdev;
> -
> - struct ufshcd_lrb *lrb;
> -
> - unsigned long outstanding_tasks;
> - unsigned long outstanding_reqs;
> -
> - u32 capabilities;
> - int nutrs;
> - int nutmrs;
> - u32 ufs_version;
> -
> - struct uic_command active_uic_cmd;
> - wait_queue_head_t ufshcd_tm_wait_queue;
> - unsigned long tm_condition;
> -
> - u32 ufshcd_state;
> - u32 int_enable_mask;
> -
> - /* Work Queues */
> - struct work_struct uic_workq;
> - struct work_struct feh_workq;
> -
> - /* HBA Errors */
> - u32 errors;
> -};
> -
> -/**
> * struct ufshcd_lrb - local reference block
> * @utr_descriptor_ptr: UTRD address of the command
> * @ucd_cmd_ptr: UCD address of the command
> @@ -335,21 +249,21 @@ static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
>
> if (hba->utmrdl_base_addr) {
> utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
> - dma_free_coherent(&hba->pdev->dev, utmrdl_size,
> + dma_free_coherent(&hba->dev, utmrdl_size,
> hba->utmrdl_base_addr, hba->utmrdl_dma_addr);
> }
>
> if (hba->utrdl_base_addr) {
> utrdl_size =
> (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
> - dma_free_coherent(&hba->pdev->dev, utrdl_size,
> + dma_free_coherent(&hba->dev, utrdl_size,
> hba->utrdl_base_addr, hba->utrdl_dma_addr);
> }
>
> if (hba->ucdl_base_addr) {
> ucdl_size =
> (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
> - dma_free_coherent(&hba->pdev->dev, ucdl_size,
> + dma_free_coherent(&hba->dev, ucdl_size,
> hba->ucdl_base_addr, hba->ucdl_dma_addr);
> }
> }
> @@ -724,7 +638,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>
> /* Allocate memory for UTP command descriptors */
> ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
> - hba->ucdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
> + hba->ucdl_base_addr = dma_alloc_coherent(&hba->dev,
> ucdl_size,
> &hba->ucdl_dma_addr,
> GFP_KERNEL);
> @@ -737,7 +651,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
> */
> if (!hba->ucdl_base_addr ||
> WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Command Descriptor Memory allocation failed\n");
> goto out;
> }
> @@ -747,13 +661,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
> * UFSHCI requires 1024 byte alignment of UTRD
> */
> utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
> - hba->utrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
> + hba->utrdl_base_addr = dma_alloc_coherent(&hba->dev,
> utrdl_size,
> &hba->utrdl_dma_addr,
> GFP_KERNEL);
> if (!hba->utrdl_base_addr ||
> WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Transfer Descriptor Memory allocation failed\n");
> goto out;
> }
> @@ -763,13 +677,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
> * UFSHCI requires 1024 byte alignment of UTMRD
> */
> utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
> - hba->utmrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
> + hba->utmrdl_base_addr = dma_alloc_coherent(&hba->dev,
> utmrdl_size,
> &hba->utmrdl_dma_addr,
> GFP_KERNEL);
> if (!hba->utmrdl_base_addr ||
> WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Task Management Descriptor Memory allocation failed\n");
> goto out;
> }
> @@ -777,7 +691,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
> /* Allocate memory for local reference block */
> hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL);
> if (!hba->lrb) {
> - dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n");
> + dev_err(&hba->dev, "LRB Memory allocation failed\n");
> goto out;
> }
> return 0;
> @@ -867,7 +781,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
> /* check if controller is ready to accept UIC commands */
> if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
> UIC_COMMAND_READY) == 0x0) {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Controller not ready"
> " to accept UIC commands\n");
> return -EIO;
> @@ -912,7 +826,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
> /* check if device present */
> reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
> if (!ufshcd_is_device_present(reg)) {
> - dev_err(&hba->pdev->dev, "cc: Device not present\n");
> + dev_err(&hba->dev, "cc: Device not present\n");
> err = -ENXIO;
> goto out;
> }
> @@ -924,7 +838,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
> if (!(ufshcd_get_lists_status(reg))) {
> ufshcd_enable_run_stop_reg(hba);
> } else {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Host controller not ready to process requests");
> err = -EIO;
> goto out;
> @@ -1005,7 +919,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
> if (retry) {
> retry--;
> } else {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Controller enable failed\n");
> return -EIO;
> }
> @@ -1015,37 +929,6 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
> }
>
> /**
> - * ufshcd_initialize_hba - start the initialization process
> - * @hba: per adapter instance
> - *
> - * 1. Enable the controller via ufshcd_hba_enable.
> - * 2. Program the Transfer Request List Address with the starting address of
> - * UTRDL.
> - * 3. Program the Task Management Request List Address with starting address
> - * of UTMRDL.
> - *
> - * Returns 0 on success, non-zero value on failure.
> - */
> -static int ufshcd_initialize_hba(struct ufs_hba *hba)
> -{
> - if (ufshcd_hba_enable(hba))
> - return -EIO;
> -
> - /* Configure UTRL and UTMRL base address registers */
> - writel(lower_32_bits(hba->utrdl_dma_addr),
> - (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
> - writel(upper_32_bits(hba->utrdl_dma_addr),
> - (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
> - writel(lower_32_bits(hba->utmrdl_dma_addr),
> - (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
> - writel(upper_32_bits(hba->utmrdl_dma_addr),
> - (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
> -
> - /* Initialize unipro link startup procedure */
> - return ufshcd_dme_link_startup(hba);
> -}
> -
> -/**
> * ufshcd_do_reset - reset the host controller
> * @hba: per adapter instance
> *
> @@ -1084,7 +967,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
>
> /* start the initialization process */
> if (ufshcd_initialize_hba(hba)) {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Reset: Controller initialization failed\n");
> return FAILED;
> }
> @@ -1167,7 +1050,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
> task_result = SUCCESS;
> } else {
> task_result = FAILED;
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "trc: Invalid ocs = %x\n", ocs_value);
> }
> spin_unlock_irqrestore(hba->host->host_lock, flags);
> @@ -1281,7 +1164,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
> /* check if the returned transfer response is valid */
> result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
> if (result) {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Invalid response = %x\n", result);
> break;
> }
> @@ -1310,7 +1193,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
> case OCS_FATAL_ERROR:
> default:
> result |= DID_ERROR << 16;
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "OCS error from controller = %x\n", ocs);
> break;
> } /* end of switch */
> @@ -1374,7 +1257,7 @@ static void ufshcd_uic_cc_handler (struct work_struct *work)
> !(ufshcd_get_uic_cmd_result(hba))) {
>
> if (ufshcd_make_hba_operational(hba))
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "cc: hba not operational state\n");
> return;
> }
> @@ -1509,7 +1392,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
> free_slot = ufshcd_get_tm_free_slot(hba);
> if (free_slot >= hba->nutmrs) {
> spin_unlock_irqrestore(host->host_lock, flags);
> - dev_err(&hba->pdev->dev, "Task management queue full\n");
> + dev_err(&hba->dev, "Task management queue full\n");
> err = FAILED;
> goto out;
> }
> @@ -1552,7 +1435,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
> &hba->tm_condition) != 0),
> 60 * HZ);
> if (!err) {
> - dev_err(&hba->pdev->dev,
> + dev_err(&hba->dev,
> "Task management command timed-out\n");
> err = FAILED;
> goto out;
> @@ -1688,23 +1571,46 @@ static struct scsi_host_template ufshcd_driver_template = {
> };
>
> /**
> - * ufshcd_shutdown - main function to put the controller in reset state
> - * @pdev: pointer to PCI device handle
> + * ufshcd_initialize_hba - start the initialization process
> + * @hba: per adapter instance
> + *
> + * 1. Enable the controller via ufshcd_hba_enable.
> + * 2. Program the Transfer Request List Address with the starting address of
> + * UTRDL.
> + * 3. Program the Task Management Request List Address with starting address
> + * of UTMRDL.
> + *
> + * Returns 0 on success, non-zero value on failure.
> */
> -static void ufshcd_shutdown(struct pci_dev *pdev)
> +int ufshcd_initialize_hba(struct ufs_hba *hba)
> {
> - ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
> + if (ufshcd_hba_enable(hba))
> + return -EIO;
> +
> + /* Configure UTRL and UTMRL base address registers */
> + writel(hba->utrdl_dma_addr,
> + (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
> + writel(lower_32_bits(hba->utrdl_dma_addr),
> + (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
> + writel(hba->utmrdl_dma_addr,
> + (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
> + writel(upper_32_bits(hba->utmrdl_dma_addr),
> + (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
> +
> + /* Initialize unipro link startup procedure */
> + return ufshcd_dme_link_startup(hba);
> }
> +EXPORT_SYMBOL(ufshcd_initialize_hba);
>
> #ifdef CONFIG_PM
> /**
> * ufshcd_suspend - suspend power management function
> - * @pdev: pointer to PCI device handle
> + * @hba: pointer to host controller platform data
> * @state: power state
> *
> * Returns -ENOSYS
> */
> -static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
> +int ufshcd_suspend(struct ufs_hba *hba)
> {
> /*
> * TODO:
> @@ -1717,14 +1623,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
>
> return -ENOSYS;
> }
> +EXPORT_SYMBOL(ufshcd_suspend);
>
> /**
> * ufshcd_resume - resume power management function
> - * @pdev: pointer to PCI device handle
> + * @hba: pointer to host controller platform data
> *
> * Returns -ENOSYS
> */
> -static int ufshcd_resume(struct pci_dev *pdev)
> +int ufshcd_resume(struct ufs_hba *hba)
> {
> /*
> * TODO:
> @@ -1737,119 +1644,55 @@ static int ufshcd_resume(struct pci_dev *pdev)
>
> return -ENOSYS;
> }
> -#endif /* CONFIG_PM */
> +EXPORT_SYMBOL(ufshcd_resume);
>
> -/**
> - * ufshcd_hba_free - free allocated memory for
> - * host memory space data structures
> - * @hba: per adapter instance
> - */
> -static void ufshcd_hba_free(struct ufs_hba *hba)
> -{
> - iounmap(hba->mmio_base);
> - ufshcd_free_hba_memory(hba);
> - pci_release_regions(hba->pdev);
> -}
> +#endif /* CONFIG_PM */
>
> /**
> - * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
> + * ufshcd_drv_exit - de-allocate SCSI host and host memory space
> * data structure memory
> - * @pdev - pointer to PCI handle
> + * @dev - pointer to host platform data
> */
> -static void ufshcd_remove(struct pci_dev *pdev)
> +void ufshcd_drv_exit(struct ufs_hba *hba)
> {
> - struct ufs_hba *hba = pci_get_drvdata(pdev);
> -
> /* disable interrupts */
> ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
> - free_irq(pdev->irq, hba);
> + free_irq(hba->irq, hba);
>
> ufshcd_hba_stop(hba);
> - ufshcd_hba_free(hba);
> + ufshcd_free_hba_memory(hba);
>
> scsi_remove_host(hba->host);
> scsi_host_put(hba->host);
> - pci_set_drvdata(pdev, NULL);
> - pci_clear_master(pdev);
> - pci_disable_device(pdev);
> }
> +EXPORT_SYMBOL(ufshcd_drv_exit);
>
> /**
> - * ufshcd_set_dma_mask - Set dma mask based on the controller
> - * addressing capability
> - * @pdev: PCI device structure
> - *
> - * Returns 0 for success, non-zero for failure
> - */
> -static int ufshcd_set_dma_mask(struct ufs_hba *hba)
> -{
> - int err;
> - u64 dma_mask;
> -
> - /*
> - * If controller supports 64 bit addressing mode, then set the DMA
> - * mask to 64-bit, else set the DMA mask to 32-bit
> - */
> - if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
> - dma_mask = DMA_BIT_MASK(64);
> - else
> - dma_mask = DMA_BIT_MASK(32);
> -
> - err = pci_set_dma_mask(hba->pdev, dma_mask);
> - if (err)
> - return err;
> -
> - err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
> -
> - return err;
> -}
> -
> -/**
> - * ufshcd_probe - probe routine of the driver
> - * @pdev: pointer to PCI device handle
> - * @id: PCI device id
> + * ufshcd_drv_init - generic init routine of the driver
> + * @hba: pointer to platform data
> *
> * Returns 0 on success, non-zero value on failure
> */
> -static int __devinit
> -ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +int ufshcd_drv_init(struct ufs_hba **hostdata, struct device *dev,
> + int irq_no, void __iomem *mmio_base)
> {
> struct Scsi_Host *host;
> - struct ufs_hba *hba;
> int err;
> -
> - err = pci_enable_device(pdev);
> - if (err) {
> - dev_err(&pdev->dev, "pci_enable_device failed\n");
> - goto out_error;
> - }
> -
> - pci_set_master(pdev);
> + struct ufs_hba *hba;
>
> host = scsi_host_alloc(&ufshcd_driver_template,
> sizeof(struct ufs_hba));
> if (!host) {
> - dev_err(&pdev->dev, "scsi_host_alloc failed\n");
> + dev_err(&hba->dev, "scsi_host_alloc failed\n");
> err = -ENOMEM;
> goto out_disable;
> }
> hba = shost_priv(host);
> -
> - err = pci_request_regions(pdev, UFSHCD);
> - if (err < 0) {
> - dev_err(&pdev->dev, "request regions failed\n");
> - goto out_disable;
> - }
> -
> - hba->mmio_base = pci_ioremap_bar(pdev, 0);
> - if (!hba->mmio_base) {
> - dev_err(&pdev->dev, "memory map failed\n");
> - err = -ENOMEM;
> - goto out_release_regions;
> - }
> -
> + hba->dev = *dev;
It doesn't look like you need to copy the entire device data into hba.
Why isn't a reference not sufficient ?
> hba->host = host;
> - hba->pdev = pdev;
> + hba->irq = irq_no;
> + hba->mmio_base = mmio_base;
> + *hostdata = hba;
>
> /* Read capabilities registers */
> ufshcd_hba_capabilities(hba);
> @@ -1857,17 +1700,11 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> /* Get UFS version supported by the controller */
> hba->ufs_version = ufshcd_get_ufs_version(hba);
>
> - err = ufshcd_set_dma_mask(hba);
> - if (err) {
> - dev_err(&pdev->dev, "set dma mask failed\n");
> - goto out_iounmap;
> - }
> -
> /* Allocate memory for host memory space */
> err = ufshcd_memory_alloc(hba);
> if (err) {
> - dev_err(&pdev->dev, "Memory allocation failed\n");
> - goto out_iounmap;
> + dev_err(&hba->dev, "Memory allocation failed\n");
> + goto out_disable;
> }
>
> /* Configure LRB */
> @@ -1889,72 +1726,55 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
>
> /* IRQ registration */
> - err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
> + err = request_irq(hba->irq, ufshcd_intr, IRQF_SHARED,
> + ufs_hostname(hba), hba);
> if (err) {
> - dev_err(&pdev->dev, "request irq failed\n");
> + dev_err(&hba->dev, "request irq failed\n");
> goto out_lrb_free;
> }
>
> /* Enable SCSI tag mapping */
> err = scsi_init_shared_tag_map(host, host->can_queue);
> if (err) {
> - dev_err(&pdev->dev, "init shared queue failed\n");
> - goto out_free_irq;
> - }
> -
> - pci_set_drvdata(pdev, hba);
> -
> - err = scsi_add_host(host, &pdev->dev);
> - if (err) {
> - dev_err(&pdev->dev, "scsi_add_host failed\n");
> + dev_err(&hba->dev, "init shared queue failed\n");
> goto out_free_irq;
> }
>
> - /* Initialization routine */
> - err = ufshcd_initialize_hba(hba);
> + err = scsi_add_host(host, &hba->dev);
> if (err) {
> - dev_err(&pdev->dev, "Initialization failed\n");
> + dev_err(&hba->dev, "scsi_add_host failed\n");
> goto out_free_irq;
> }
>
> return 0;
>
> out_free_irq:
> - free_irq(pdev->irq, hba);
> + free_irq(hba->irq, hba);
> out_lrb_free:
> ufshcd_free_hba_memory(hba);
> -out_iounmap:
> - iounmap(hba->mmio_base);
> -out_release_regions:
> - pci_release_regions(pdev);
> out_disable:
> scsi_host_put(host);
> - pci_clear_master(pdev);
> - pci_disable_device(pdev);
> -out_error:
> return err;
> }
> +EXPORT_SYMBOL(ufshcd_drv_init);
>
> -static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
> - { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> - { } /* terminate list */
> -};
> +static int __init ufshcd_probe(void)
> +{
> + pr_info(UFSHCD
> + ": Generic UFS host controller driver\n");
> + pr_info(UFSHCD ": Copyright(c) Samsung India Software Operations\n");
>
Is it really necessary to assert the copyright on probe ? I haven't
seen this practice anywhere..
> -MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
> + return 0;
> +}
>
> -static struct pci_driver ufshcd_pci_driver = {
> - .name = UFSHCD,
> - .id_table = ufshcd_pci_tbl,
> - .probe = ufshcd_probe,
> - .remove = __devexit_p(ufshcd_remove),
> - .shutdown = ufshcd_shutdown,
> -#ifdef CONFIG_PM
> - .suspend = ufshcd_suspend,
> - .resume = ufshcd_resume,
> -#endif
> -};
> +static void __exit ufshcd_remove(void)
> +{
> + pr_info(UFSHCD
> + ": Generic UFS host controller driver removed\n");
> +}
>
> -module_pci_driver(ufshcd_pci_driver);
> +module_init(ufshcd_probe);
> +module_exit(ufshcd_remove);
>
> MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
> "Vinayak Holikatti <h.vinayak@samsung.com>");
> --
> 1.7.4.1
>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC V3 2/2] SCSI: UFS: Add platform support for ufs host controller
2012-05-21 6:31 ` [RFC V3 2/2] SCSI: UFS: Add platform support for ufs host controller Girish K S
@ 2012-05-22 5:37 ` S, Venkatraman
2012-05-22 7:29 ` Girish K S
0 siblings, 1 reply; 9+ messages in thread
From: S, Venkatraman @ 2012-05-22 5:37 UTC (permalink / raw)
To: Girish K S
Cc: linux-scsi, james.bottomley, vinholikatti, santoshsy, hch, patches
On Mon, May 21, 2012 at 12:01 PM, Girish K S
<girish.shivananjappa@linaro.org> wrote:
> This patch adds platform support for ufs host controller
> The SoC's that use non-pci probing should use this option.
>
> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> ---
> drivers/scsi/ufs/Kconfig | 13 +++
> drivers/scsi/ufs/Makefile | 1 +
> drivers/scsi/ufs/ufshcd-pltfm.c | 180 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 194 insertions(+), 0 deletions(-)
> create mode 100644 drivers/scsi/ufs/ufshcd-pltfm.c
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index 2a70972..dae5428 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -60,3 +60,16 @@ config SCSI_UFSHCD_PCI
> If you have a controller with this interface, say Y or M here.
>
> If unsure, say N.
> +
> +config SCSI_UFSHCD_PLTFM
> + tristate "Universal Flash Storage host support as platform device"
> + depends on SCSI_UFSHCD
> + help
> + This selects the common helper functions support for Host Controller
> + Interface based platform driver. Please select this option if the IP
> + is present as a platform device. This is the common interface for the
> + UFS Host Controller IP.
> +
> + If you have a controller with this interface, say Y or M here.
> +
> + If unsure, say N.
> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index 9eda0df..fc56471 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -1,3 +1,4 @@
> # UFSHCD makefile
> obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> +obj-$(CONFIG_SCSI_UFSHCD_PLTFM) += ufshcd-pltfm.o
> diff --git a/drivers/scsi/ufs/ufshcd-pltfm.c b/drivers/scsi/ufs/ufshcd-pltfm.c
> new file mode 100644
> index 0000000..7558210
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufshcd-pltfm.c
> @@ -0,0 +1,180 @@
> +/*
> + * Universal Flash Storage Host controller driver
> + *
> + * This code is based on drivers/scsi/ufs/ufshcd.c
> + * Copyright (C) 2011-2012 Samsung India Software Operations
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * NO WARRANTY
> + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
> + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
> + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
> + * solely responsible for determining the appropriateness of using and
> + * distributing the Program and assumes all risks associated with its
> + * exercise of rights under this Agreement, including but not limited to
> + * the risks and costs of program errors, damage to or loss of data,
> + * programs or equipment, and unavailability or interruption of operations.
> +
> + * DISCLAIMER OF LIABILITY
> + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
> + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
> +
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
> + * USA.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/dma-mapping.h>
> +#include <scsi/scsi_host.h>
> +
> +#include "ufs.h"
> +#include "ufshci.h"
> +
> +/**
> + * ufshcd_pltfmset_dma_mask - Set dma mask based on the controller
> + * addressing capability
> + * @ihba: pointer to host platform data
> + *
> + * Returns 0 for success, non-zero for failure
> + */
> +static int ufshcd_pltfm_set_dma_mask(struct platform_device *pdev)
> +{
> + int err;
> + u64 dma_mask;
> +
> + dma_mask = DMA_BIT_MASK(64);
> + err = dma_set_coherent_mask(&pdev->dev, dma_mask);
> + if (err) {
> + dma_mask = DMA_BIT_MASK(32);
> + err = dma_set_coherent_mask(&pdev->dev, dma_mask);
> + }
> +
> + return err;
> +}
> +
> +static int __devinit ufshcd_pltfm_probe(struct platform_device *pdev)
> +{
> + struct ufs_hba *uninitialized_var(hba);
> + struct resource *regs;
> + int err, irq;
> + void __iomem *mmio_base;
> +
> + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!regs)
> + return -ENXIO;
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return irq;
> +
> + mmio_base = ioremap(regs->start, resource_size(regs));
> + if (!mmio_base)
> + return -ENOMEM;
> +
> + err = ufshcd_pltfm_set_dma_mask(pdev);
> + if (err) {
> + dev_err(&pdev->dev, "set dma mask failed\n");
> + goto err_iounmap;
> + }
> +
> + err = ufshcd_drv_init(&hba, &pdev->dev, irq, mmio_base);
> + if (err)
> + goto err_iounmap;
> +
> + platform_set_drvdata(pdev, hba);
> +
> + /* Initialization routine */
> + err = ufshcd_initialize_hba(hba);
> + if (err) {
> + dev_err(&hba->dev, "Initialization failed\n");
> + goto err_remove;
> + }
> +
> + return err;
> +
> +err_remove:
> + ufshcd_drv_exit(hba);
> +err_iounmap:
> + iounmap(hba->mmio_base);
> + return err;
> +}
> +
> +static int __devexit ufshcd_pltfm_remove(struct platform_device *pdev)
> +{
> + struct ufs_hba *hba = platform_get_drvdata(pdev);
> +
> + ufshcd_drv_exit(hba);
> + iounmap(hba->mmio_base);
> + platform_set_drvdata(pdev, NULL);
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int ufshcd_pltfm_suspend(struct device *dev)
> +{
> + int ret;
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> +
> + ret = ufshcd_suspend(hba);
> + if (ret)
> + return ret;
The above 2 lines are redundant...
> +
> + return 0;
.. if you simply do a "return ret" here...
> +}
> +
> +static int ufshcd_pltfm_resume(struct device *dev)
> +{
> + int ret;
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> +
> + ret = ufshcd_resume(hba);
> + if (ret)
> + return ret;
.. ditto
> +
> + return 0;
> +}
> +#else
> +#define ufshcd_pltfm_suspend NULL
> +#define ufshcd_pltfm_resume NULL
> +#endif /* CONFIG_PM */
> +
> +static SIMPLE_DEV_PM_OPS(ufshcd_pltfm_pmops,
> + ufshcd_pltfm_suspend,
> + ufshcd_pltfm_resume);
> +
> +static struct platform_driver ufshcd_pltfm_driver = {
> + .probe = ufshcd_pltfm_probe,
> + .remove = __devexit_p(ufshcd_pltfm_remove),
> + .driver = {
> + .name = "ufshcd-pltfm",
> + .pm = &ufshcd_pltfm_pmops,
> + },
> +};
> +
> +module_platform_driver(ufshcd_pltfm_driver);
> +
> +MODULE_DESCRIPTION("UFS Host Controller platform Interface driver");
> +MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
> +MODULE_LICENSE("GPL");
> --
> 1.7.4.1
>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules
2012-05-22 5:29 ` S, Venkatraman
@ 2012-05-22 7:22 ` Girish K S
2012-05-22 7:34 ` James Bottomley
1 sibling, 0 replies; 9+ messages in thread
From: Girish K S @ 2012-05-22 7:22 UTC (permalink / raw)
To: S, Venkatraman
Cc: linux-scsi, james.bottomley, vinholikatti, santoshsy, hch, patches
On 22 May 2012 10:59, S, Venkatraman <svenkatr@ti.com> wrote:
> On Mon, May 21, 2012 at 12:01 PM, Girish K S
> <girish.shivananjappa@linaro.org> wrote:
>> The existing driver was pci specific. This patch removes the
>> pci specific code from the core driver. Irrespective of the
>> pci or non-pci probe, the same core driver can be re-used.
>>
>> It also creates 2 separate modules of core and pci driver
>>
>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> ---
>> drivers/scsi/ufs/Kconfig | 19 ++-
>> drivers/scsi/ufs/Makefile | 1 +
>> drivers/scsi/ufs/ufs.h | 103 ++++++++++++
>> drivers/scsi/ufs/ufshcd-pci.c | 206 +++++++++++++++++++++++
>> drivers/scsi/ufs/ufshcd.c | 370 +++++++++++------------------------------
>> 5 files changed, 421 insertions(+), 278 deletions(-)
>> create mode 100644 drivers/scsi/ufs/ufshcd-pci.c
>>
>> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
>> index 8f27f9d..2a70972 100644
>> --- a/drivers/scsi/ufs/Kconfig
>> +++ b/drivers/scsi/ufs/Kconfig
>> @@ -44,6 +44,19 @@
>>
>> config SCSI_UFSHCD
>> tristate "Universal Flash Storage host controller driver"
>> - depends on PCI && SCSI
>> - ---help---
>> - This is a generic driver which supports PCIe UFS Host controllers.
>> + depends on SCSI
>> + help
>> + This is a generic driver which supports UFS Host controllers.
>> + This option is selected automatically if the SCSI option is
>> + selected. This is a core ufs driver.
>> +
>> +config SCSI_UFSHCD_PCI
>> + tristate "Universal Flash Storage host support on PCI bus"
>> + depends on SCSI_UFSHCD && PCI
>> + help
>> + This selects the PCI bus for the Universal Flash Storage IP.
>> + Select this option if the IP is present on PCI platform.
>> +
>> + If you have a controller with this interface, say Y or M here.
>> +
>> + If unsure, say N.
>> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
>> index adf7895..9eda0df 100644
>> --- a/drivers/scsi/ufs/Makefile
>> +++ b/drivers/scsi/ufs/Makefile
>> @@ -1,2 +1,3 @@
>> # UFSHCD makefile
>> obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
>> +obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
>> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
>> index b207529..dc36793 100644
>> --- a/drivers/scsi/ufs/ufs.h
>> +++ b/drivers/scsi/ufs/ufs.h
>> @@ -46,6 +46,8 @@
>> #ifndef _UFS_H
>> #define _UFS_H
>>
>> +#define ufs_hostname(x) (dev_name(&(x)->dev))
>> +
>> #define MAX_CDB_SIZE 16
>>
>> #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
>> @@ -204,4 +206,105 @@ struct utp_upiu_task_rsp {
>> u32 reserved[3];
>> };
>>
>> +/**
>> + * struct uic_command - UIC command structure
>> + * @command: UIC command
>> + * @argument1: UIC command argument 1
>> + * @argument2: UIC command argument 2
>> + * @argument3: UIC command argument 3
>> + * @cmd_active: Indicate if UIC command is outstanding
>> + * @result: UIC command result
>> + */
>> +struct uic_command {
>> + u32 command;
>> + u32 argument1;
>> + u32 argument2;
>> + u32 argument3;
>> + int cmd_active;
>> + int result;
>> +};
>> +
>> +struct ufs_pdata {
>> + /* TODO */
>> + u32 quirks; /* Quirk flags */
>> +};
>> +
>> +/**
>> + * struct ufs_hba - per adapter private structure
>> + * @mmio_base: UFSHCI base register address
>> + * @ucdl_base_addr: UFS Command Descriptor base address
>> + * @utrdl_base_addr: UTP Transfer Request Descriptor base address
>> + * @utmrdl_base_addr: UTP Task Management Descriptor base address
>> + * @ucdl_dma_addr: UFS Command Descriptor DMA address
>> + * @utrdl_dma_addr: UTRDL DMA address
>> + * @utmrdl_dma_addr: UTMRDL DMA address
>> + * @host: Scsi_Host instance of the driver
>> + * @dev: device handle
>> + * @lrb: local reference block
>> + * @outstanding_tasks: Bits representing outstanding task requests
>> + * @outstanding_reqs: Bits representing outstanding transfer requests
>> + * @capabilities: UFS Controller Capabilities
>> + * @nutrs: Transfer Request Queue depth supported by controller
>> + * @nutmrs: Task Management Queue depth supported by controller
>> + * @active_uic_cmd: handle of active UIC command
>> + * @ufshcd_tm_wait_queue: wait queue for task management
>> + * @tm_condition: condition variable for task management
>> + * @ufshcd_state: UFSHCD states
>> + * @int_enable_mask: Interrupt Mask Bits
>> + * @uic_workq: Work queue for UIC completion handling
>> + * @feh_workq: Work queue for fatal controller error handling
>> + * @errors: HBA errors
>> + */
>> +struct ufs_hba {
>> + void __iomem *mmio_base;
>> +
>> + /* Virtual memory reference */
>> + struct utp_transfer_cmd_desc *ucdl_base_addr;
>> + struct utp_transfer_req_desc *utrdl_base_addr;
>> + struct utp_task_req_desc *utmrdl_base_addr;
>> +
>> + /* DMA memory reference */
>> + dma_addr_t ucdl_dma_addr;
>> + dma_addr_t utrdl_dma_addr;
>> + dma_addr_t utmrdl_dma_addr;
>> +
>> + struct Scsi_Host *host;
>> + struct device dev;
>> +
>> + struct ufshcd_lrb *lrb;
>> +
>> + unsigned long outstanding_tasks;
>> + unsigned long outstanding_reqs;
>> +
>> + u32 capabilities;
>> + int nutrs;
>> + int nutmrs;
>> + u32 ufs_version;
>> +
>> + struct uic_command active_uic_cmd;
>> + wait_queue_head_t ufshcd_tm_wait_queue;
>> + unsigned long tm_condition;
>> +
>> + u32 ufshcd_state;
>> + u32 int_enable_mask;
>> +
>> + /* Work Queues */
>> + struct work_struct uic_workq;
>> + struct work_struct feh_workq;
>> +
>> + /* HBA Errors */
>> + u32 errors;
>> +
>> + unsigned int irq;
>> +};
>> +
>> +extern int ufshcd_initialize_hba(struct ufs_hba *hba);
>> +extern int ufshcd_drv_init(struct ufs_hba **hostdat, struct device *dev,
>> + int irq_no, void __iomem *mmio_base);
>> +extern void ufshcd_drv_exit(struct ufs_hba *hba);
>> +#ifdef CONFIG_PM
>> +extern int ufshcd_suspend(struct ufs_hba *hba);
>> +extern int ufshcd_resume(struct ufs_hba *hba);
>> +#endif /* CONFIG_PM */
>> +
>> #endif /* End of Header */
>> diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
>> new file mode 100644
>> index 0000000..e306573
>> --- /dev/null
>> +++ b/drivers/scsi/ufs/ufshcd-pci.c
>> @@ -0,0 +1,206 @@
>> +/*
>> + * Universal Flash Storage Host controller driver
>> + *
>> + * This code is based on drivers/scsi/ufs/ufshcd.c
>> + * Copyright (C) 2011-2012 Samsung India Software Operations
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version 2
>> + * of the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * NO WARRANTY
>> + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>> + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>> + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>> + * solely responsible for determining the appropriateness of using and
>> + * distributing the Program and assumes all risks associated with its
>> + * exercise of rights under this Agreement, including but not limited to
>> + * the risks and costs of program errors, damage to or loss of data,
>> + * programs or equipment, and unavailability or interruption of operations.
>> +
>> + * DISCLAIMER OF LIABILITY
>> + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
>> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
>> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
>> + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>> +
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
>> + * USA.
>> + */
>> +
>> +#include <linux/interrupt.h>
>> +#include <linux/module.h>
>> +#include <linux/io.h>
>> +#include <linux/pci.h>
>> +#include <scsi/scsi_host.h>
>> +
>> +#include "ufs.h"
>> +#include "ufshci.h"
>> +
>> +/**
>> + * ufshcd_pci_set_dma_mask - Set dma mask based on the controller
>> + * addressing capability
>> + * @ihba: pointer to host platform data
>> + *
>> + * Returns 0 for success, non-zero for failure
>> + */
>> +static int ufshcd_pci_set_dma_mask(struct pci_dev *pdev)
>> +{
>> + int err;
>> + u64 dma_mask;
>> +
>> + /*
>> + * If controller supports 64 bit addressing mode, then set the DMA
>> + * mask to 64-bit, else set the DMA mask to 32-bit
>> + */
>> + dma_mask = DMA_BIT_MASK(64);
>> + err = pci_set_dma_mask(pdev, dma_mask);
>> + if (err) {
>> + dma_mask = DMA_BIT_MASK(32);
>> + err = pci_set_dma_mask(pdev, dma_mask);
>> + }
>> +
>> + if (err)
>> + return err;
>> +
>> + err = pci_set_consistent_dma_mask(pdev, dma_mask);
>> +
>> + return err;
>> +}
>> +
>> +static int __devinit ufshcd_pci_probe(struct pci_dev *pdev,
>> + const struct pci_device_id *entries)
>> +{
>> + struct ufs_hba *uninitialized_var(hba);
>> + int err;
>> + void __iomem *mmio_base;
>> +
>> + err = pci_enable_device(pdev);
>> + if (err) {
>> + dev_err(&pdev->dev, "pci_enable_device failed\n");
>> + goto err_return;
>> + }
>> +
>> + pci_set_master(pdev);
>> +
>> + err = pci_request_regions(pdev, "ufshcd-pci");
>> + if (err < 0) {
>> + dev_err(&pdev->dev, "request regions failed\n");
>> + goto err_disable;
>> + }
>> +
>> + mmio_base = pci_ioremap_bar(pdev, 0);
>> + if (!mmio_base) {
>> + dev_err(&pdev->dev, "memory map failed\n");
>> + err = -ENOMEM;
>> + goto err_release;
>> + }
>> +
>> + err = ufshcd_pci_set_dma_mask(pdev);
>> + if (err) {
>> + dev_err(&pdev->dev, "set dma mask failed\n");
>> + goto err_iounmap;
>> + }
>> +
>> + err = ufshcd_drv_init(&hba, &pdev->dev, pdev->irq, mmio_base);
>> + if (err)
>> + goto err_iounmap;
>> +
>> + pci_set_drvdata(pdev, hba);
>> +
>> + /* Initialization routine */
>> + err = ufshcd_initialize_hba(hba);
>> + if (err) {
>> + dev_err(&hba->dev, "Initialization failed\n");
>> + goto err_remove;
>> + }
>> +
>> + return err;
>> +
>> +err_remove:
>> + ufshcd_drv_exit(hba);
>> +err_iounmap:
>> + iounmap(hba->mmio_base);
>> +err_release:
>> + pci_release_regions(pdev);
>> +err_disable:
>> + pci_clear_master(pdev);
>> + pci_disable_device(pdev);
>> +err_return:
>> + return err;
>> +}
>> +
>> +static void __devexit ufshcd_pci_remove(struct pci_dev *pdev)
>> +{
>> + struct ufs_hba *hba = pci_get_drvdata(pdev);
>> +
>> + ufshcd_drv_exit(hba);
>> + iounmap(hba->mmio_base);
>> + pci_set_drvdata(pdev, NULL);
>> + pci_clear_master(pdev);
>> + pci_release_regions(pdev);
>> + pci_disable_device(pdev);
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int ufshcd_pci_suspend(struct device *dev)
>> +{
>> + int ret;
>> + struct pci_dev *pdev = to_pci_dev(dev);
>> + struct ufs_hba *hba = pci_get_drvdata(pdev);
>> +
>> + ret = ufshcd_suspend(hba);
>> + return ret;
>> +}
>> +
>> +static int ufshcd_pci_resume(struct device *dev)
>> +{
>> + int ret;
>> + struct pci_dev *pdev = to_pci_dev(dev);
>> + struct ufs_hba *hba = pci_get_drvdata(pdev);
>> +
>> + ret = ufshcd_resume(hba);
>> + return ret;
>> +}
>> +#else
>> +#define ufshcd_pci_suspend NULL
>> +#define ufshcd_pci_resume NULL
>> +#endif /* CONFIG_PM */
>> +
>> +static SIMPLE_DEV_PM_OPS(ufshcd_pci_pmops,
>> + ufshcd_pci_suspend,
>> + ufshcd_pci_resume);
>> +
>> +static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_id) = {
>> + { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(pci, ufshcd_pci_id);
>> +
>> +static struct pci_driver ufshcd_pci_driver = {
>> + .name = "ufshcd-pci",
>> + .id_table = ufshcd_pci_id,
>> + .probe = ufshcd_pci_probe,
>> + .remove = __devexit_p(ufshcd_pci_remove),
>> + .driver = {
>> + .pm = &ufshcd_pci_pmops
>> + },
>> +};
>> +
>> +module_pci_driver(ufshcd_pci_driver);
>> +
>> +MODULE_DESCRIPTION("UFS Host Controller PCI Interface driver");
>> +MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index e47a0da..4cfbfc5 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -46,7 +46,6 @@
>> #include <linux/module.h>
>> #include <linux/kernel.h>
>> #include <linux/init.h>
>> -#include <linux/pci.h>
>> #include <linux/interrupt.h>
>> #include <linux/io.h>
>> #include <linux/delay.h>
>> @@ -102,91 +101,6 @@ enum {
>> };
>>
>> /**
>> - * struct uic_command - UIC command structure
>> - * @command: UIC command
>> - * @argument1: UIC command argument 1
>> - * @argument2: UIC command argument 2
>> - * @argument3: UIC command argument 3
>> - * @cmd_active: Indicate if UIC command is outstanding
>> - * @result: UIC command result
>> - */
>> -struct uic_command {
>> - u32 command;
>> - u32 argument1;
>> - u32 argument2;
>> - u32 argument3;
>> - int cmd_active;
>> - int result;
>> -};
>> -
>> -/**
>> - * struct ufs_hba - per adapter private structure
>> - * @mmio_base: UFSHCI base register address
>> - * @ucdl_base_addr: UFS Command Descriptor base address
>> - * @utrdl_base_addr: UTP Transfer Request Descriptor base address
>> - * @utmrdl_base_addr: UTP Task Management Descriptor base address
>> - * @ucdl_dma_addr: UFS Command Descriptor DMA address
>> - * @utrdl_dma_addr: UTRDL DMA address
>> - * @utmrdl_dma_addr: UTMRDL DMA address
>> - * @host: Scsi_Host instance of the driver
>> - * @pdev: PCI device handle
>> - * @lrb: local reference block
>> - * @outstanding_tasks: Bits representing outstanding task requests
>> - * @outstanding_reqs: Bits representing outstanding transfer requests
>> - * @capabilities: UFS Controller Capabilities
>> - * @nutrs: Transfer Request Queue depth supported by controller
>> - * @nutmrs: Task Management Queue depth supported by controller
>> - * @active_uic_cmd: handle of active UIC command
>> - * @ufshcd_tm_wait_queue: wait queue for task management
>> - * @tm_condition: condition variable for task management
>> - * @ufshcd_state: UFSHCD states
>> - * @int_enable_mask: Interrupt Mask Bits
>> - * @uic_workq: Work queue for UIC completion handling
>> - * @feh_workq: Work queue for fatal controller error handling
>> - * @errors: HBA errors
>> - */
>> -struct ufs_hba {
>> - void __iomem *mmio_base;
>> -
>> - /* Virtual memory reference */
>> - struct utp_transfer_cmd_desc *ucdl_base_addr;
>> - struct utp_transfer_req_desc *utrdl_base_addr;
>> - struct utp_task_req_desc *utmrdl_base_addr;
>> -
>> - /* DMA memory reference */
>> - dma_addr_t ucdl_dma_addr;
>> - dma_addr_t utrdl_dma_addr;
>> - dma_addr_t utmrdl_dma_addr;
>> -
>> - struct Scsi_Host *host;
>> - struct pci_dev *pdev;
>> -
>> - struct ufshcd_lrb *lrb;
>> -
>> - unsigned long outstanding_tasks;
>> - unsigned long outstanding_reqs;
>> -
>> - u32 capabilities;
>> - int nutrs;
>> - int nutmrs;
>> - u32 ufs_version;
>> -
>> - struct uic_command active_uic_cmd;
>> - wait_queue_head_t ufshcd_tm_wait_queue;
>> - unsigned long tm_condition;
>> -
>> - u32 ufshcd_state;
>> - u32 int_enable_mask;
>> -
>> - /* Work Queues */
>> - struct work_struct uic_workq;
>> - struct work_struct feh_workq;
>> -
>> - /* HBA Errors */
>> - u32 errors;
>> -};
>> -
>> -/**
>> * struct ufshcd_lrb - local reference block
>> * @utr_descriptor_ptr: UTRD address of the command
>> * @ucd_cmd_ptr: UCD address of the command
>> @@ -335,21 +249,21 @@ static inline void ufshcd_free_hba_memory(struct ufs_hba *hba)
>>
>> if (hba->utmrdl_base_addr) {
>> utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
>> - dma_free_coherent(&hba->pdev->dev, utmrdl_size,
>> + dma_free_coherent(&hba->dev, utmrdl_size,
>> hba->utmrdl_base_addr, hba->utmrdl_dma_addr);
>> }
>>
>> if (hba->utrdl_base_addr) {
>> utrdl_size =
>> (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
>> - dma_free_coherent(&hba->pdev->dev, utrdl_size,
>> + dma_free_coherent(&hba->dev, utrdl_size,
>> hba->utrdl_base_addr, hba->utrdl_dma_addr);
>> }
>>
>> if (hba->ucdl_base_addr) {
>> ucdl_size =
>> (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
>> - dma_free_coherent(&hba->pdev->dev, ucdl_size,
>> + dma_free_coherent(&hba->dev, ucdl_size,
>> hba->ucdl_base_addr, hba->ucdl_dma_addr);
>> }
>> }
>> @@ -724,7 +638,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>>
>> /* Allocate memory for UTP command descriptors */
>> ucdl_size = (sizeof(struct utp_transfer_cmd_desc) * hba->nutrs);
>> - hba->ucdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
>> + hba->ucdl_base_addr = dma_alloc_coherent(&hba->dev,
>> ucdl_size,
>> &hba->ucdl_dma_addr,
>> GFP_KERNEL);
>> @@ -737,7 +651,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>> */
>> if (!hba->ucdl_base_addr ||
>> WARN_ON(hba->ucdl_dma_addr & (PAGE_SIZE - 1))) {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Command Descriptor Memory allocation failed\n");
>> goto out;
>> }
>> @@ -747,13 +661,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>> * UFSHCI requires 1024 byte alignment of UTRD
>> */
>> utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
>> - hba->utrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
>> + hba->utrdl_base_addr = dma_alloc_coherent(&hba->dev,
>> utrdl_size,
>> &hba->utrdl_dma_addr,
>> GFP_KERNEL);
>> if (!hba->utrdl_base_addr ||
>> WARN_ON(hba->utrdl_dma_addr & (PAGE_SIZE - 1))) {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Transfer Descriptor Memory allocation failed\n");
>> goto out;
>> }
>> @@ -763,13 +677,13 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>> * UFSHCI requires 1024 byte alignment of UTMRD
>> */
>> utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
>> - hba->utmrdl_base_addr = dma_alloc_coherent(&hba->pdev->dev,
>> + hba->utmrdl_base_addr = dma_alloc_coherent(&hba->dev,
>> utmrdl_size,
>> &hba->utmrdl_dma_addr,
>> GFP_KERNEL);
>> if (!hba->utmrdl_base_addr ||
>> WARN_ON(hba->utmrdl_dma_addr & (PAGE_SIZE - 1))) {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Task Management Descriptor Memory allocation failed\n");
>> goto out;
>> }
>> @@ -777,7 +691,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
>> /* Allocate memory for local reference block */
>> hba->lrb = kcalloc(hba->nutrs, sizeof(struct ufshcd_lrb), GFP_KERNEL);
>> if (!hba->lrb) {
>> - dev_err(&hba->pdev->dev, "LRB Memory allocation failed\n");
>> + dev_err(&hba->dev, "LRB Memory allocation failed\n");
>> goto out;
>> }
>> return 0;
>> @@ -867,7 +781,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
>> /* check if controller is ready to accept UIC commands */
>> if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
>> UIC_COMMAND_READY) == 0x0) {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Controller not ready"
>> " to accept UIC commands\n");
>> return -EIO;
>> @@ -912,7 +826,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
>> /* check if device present */
>> reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
>> if (!ufshcd_is_device_present(reg)) {
>> - dev_err(&hba->pdev->dev, "cc: Device not present\n");
>> + dev_err(&hba->dev, "cc: Device not present\n");
>> err = -ENXIO;
>> goto out;
>> }
>> @@ -924,7 +838,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
>> if (!(ufshcd_get_lists_status(reg))) {
>> ufshcd_enable_run_stop_reg(hba);
>> } else {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Host controller not ready to process requests");
>> err = -EIO;
>> goto out;
>> @@ -1005,7 +919,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>> if (retry) {
>> retry--;
>> } else {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Controller enable failed\n");
>> return -EIO;
>> }
>> @@ -1015,37 +929,6 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>> }
>>
>> /**
>> - * ufshcd_initialize_hba - start the initialization process
>> - * @hba: per adapter instance
>> - *
>> - * 1. Enable the controller via ufshcd_hba_enable.
>> - * 2. Program the Transfer Request List Address with the starting address of
>> - * UTRDL.
>> - * 3. Program the Task Management Request List Address with starting address
>> - * of UTMRDL.
>> - *
>> - * Returns 0 on success, non-zero value on failure.
>> - */
>> -static int ufshcd_initialize_hba(struct ufs_hba *hba)
>> -{
>> - if (ufshcd_hba_enable(hba))
>> - return -EIO;
>> -
>> - /* Configure UTRL and UTMRL base address registers */
>> - writel(lower_32_bits(hba->utrdl_dma_addr),
>> - (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
>> - writel(upper_32_bits(hba->utrdl_dma_addr),
>> - (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
>> - writel(lower_32_bits(hba->utmrdl_dma_addr),
>> - (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
>> - writel(upper_32_bits(hba->utmrdl_dma_addr),
>> - (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
>> -
>> - /* Initialize unipro link startup procedure */
>> - return ufshcd_dme_link_startup(hba);
>> -}
>> -
>> -/**
>> * ufshcd_do_reset - reset the host controller
>> * @hba: per adapter instance
>> *
>> @@ -1084,7 +967,7 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
>>
>> /* start the initialization process */
>> if (ufshcd_initialize_hba(hba)) {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Reset: Controller initialization failed\n");
>> return FAILED;
>> }
>> @@ -1167,7 +1050,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
>> task_result = SUCCESS;
>> } else {
>> task_result = FAILED;
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "trc: Invalid ocs = %x\n", ocs_value);
>> }
>> spin_unlock_irqrestore(hba->host->host_lock, flags);
>> @@ -1281,7 +1164,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
>> /* check if the returned transfer response is valid */
>> result = ufshcd_is_valid_req_rsp(lrbp->ucd_rsp_ptr);
>> if (result) {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Invalid response = %x\n", result);
>> break;
>> }
>> @@ -1310,7 +1193,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
>> case OCS_FATAL_ERROR:
>> default:
>> result |= DID_ERROR << 16;
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "OCS error from controller = %x\n", ocs);
>> break;
>> } /* end of switch */
>> @@ -1374,7 +1257,7 @@ static void ufshcd_uic_cc_handler (struct work_struct *work)
>> !(ufshcd_get_uic_cmd_result(hba))) {
>>
>> if (ufshcd_make_hba_operational(hba))
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "cc: hba not operational state\n");
>> return;
>> }
>> @@ -1509,7 +1392,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>> free_slot = ufshcd_get_tm_free_slot(hba);
>> if (free_slot >= hba->nutmrs) {
>> spin_unlock_irqrestore(host->host_lock, flags);
>> - dev_err(&hba->pdev->dev, "Task management queue full\n");
>> + dev_err(&hba->dev, "Task management queue full\n");
>> err = FAILED;
>> goto out;
>> }
>> @@ -1552,7 +1435,7 @@ ufshcd_issue_tm_cmd(struct ufs_hba *hba,
>> &hba->tm_condition) != 0),
>> 60 * HZ);
>> if (!err) {
>> - dev_err(&hba->pdev->dev,
>> + dev_err(&hba->dev,
>> "Task management command timed-out\n");
>> err = FAILED;
>> goto out;
>> @@ -1688,23 +1571,46 @@ static struct scsi_host_template ufshcd_driver_template = {
>> };
>>
>> /**
>> - * ufshcd_shutdown - main function to put the controller in reset state
>> - * @pdev: pointer to PCI device handle
>> + * ufshcd_initialize_hba - start the initialization process
>> + * @hba: per adapter instance
>> + *
>> + * 1. Enable the controller via ufshcd_hba_enable.
>> + * 2. Program the Transfer Request List Address with the starting address of
>> + * UTRDL.
>> + * 3. Program the Task Management Request List Address with starting address
>> + * of UTMRDL.
>> + *
>> + * Returns 0 on success, non-zero value on failure.
>> */
>> -static void ufshcd_shutdown(struct pci_dev *pdev)
>> +int ufshcd_initialize_hba(struct ufs_hba *hba)
>> {
>> - ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
>> + if (ufshcd_hba_enable(hba))
>> + return -EIO;
>> +
>> + /* Configure UTRL and UTMRL base address registers */
>> + writel(hba->utrdl_dma_addr,
>> + (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
>> + writel(lower_32_bits(hba->utrdl_dma_addr),
>> + (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
>> + writel(hba->utmrdl_dma_addr,
>> + (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
>> + writel(upper_32_bits(hba->utmrdl_dma_addr),
>> + (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
>> +
>> + /* Initialize unipro link startup procedure */
>> + return ufshcd_dme_link_startup(hba);
>> }
>> +EXPORT_SYMBOL(ufshcd_initialize_hba);
>>
>> #ifdef CONFIG_PM
>> /**
>> * ufshcd_suspend - suspend power management function
>> - * @pdev: pointer to PCI device handle
>> + * @hba: pointer to host controller platform data
>> * @state: power state
>> *
>> * Returns -ENOSYS
>> */
>> -static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
>> +int ufshcd_suspend(struct ufs_hba *hba)
>> {
>> /*
>> * TODO:
>> @@ -1717,14 +1623,15 @@ static int ufshcd_suspend(struct pci_dev *pdev, pm_message_t state)
>>
>> return -ENOSYS;
>> }
>> +EXPORT_SYMBOL(ufshcd_suspend);
>>
>> /**
>> * ufshcd_resume - resume power management function
>> - * @pdev: pointer to PCI device handle
>> + * @hba: pointer to host controller platform data
>> *
>> * Returns -ENOSYS
>> */
>> -static int ufshcd_resume(struct pci_dev *pdev)
>> +int ufshcd_resume(struct ufs_hba *hba)
>> {
>> /*
>> * TODO:
>> @@ -1737,119 +1644,55 @@ static int ufshcd_resume(struct pci_dev *pdev)
>>
>> return -ENOSYS;
>> }
>> -#endif /* CONFIG_PM */
>> +EXPORT_SYMBOL(ufshcd_resume);
>>
>> -/**
>> - * ufshcd_hba_free - free allocated memory for
>> - * host memory space data structures
>> - * @hba: per adapter instance
>> - */
>> -static void ufshcd_hba_free(struct ufs_hba *hba)
>> -{
>> - iounmap(hba->mmio_base);
>> - ufshcd_free_hba_memory(hba);
>> - pci_release_regions(hba->pdev);
>> -}
>> +#endif /* CONFIG_PM */
>>
>> /**
>> - * ufshcd_remove - de-allocate PCI/SCSI host and host memory space
>> + * ufshcd_drv_exit - de-allocate SCSI host and host memory space
>> * data structure memory
>> - * @pdev - pointer to PCI handle
>> + * @dev - pointer to host platform data
>> */
>> -static void ufshcd_remove(struct pci_dev *pdev)
>> +void ufshcd_drv_exit(struct ufs_hba *hba)
>> {
>> - struct ufs_hba *hba = pci_get_drvdata(pdev);
>> -
>> /* disable interrupts */
>> ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
>> - free_irq(pdev->irq, hba);
>> + free_irq(hba->irq, hba);
>>
>> ufshcd_hba_stop(hba);
>> - ufshcd_hba_free(hba);
>> + ufshcd_free_hba_memory(hba);
>>
>> scsi_remove_host(hba->host);
>> scsi_host_put(hba->host);
>> - pci_set_drvdata(pdev, NULL);
>> - pci_clear_master(pdev);
>> - pci_disable_device(pdev);
>> }
>> +EXPORT_SYMBOL(ufshcd_drv_exit);
>>
>> /**
>> - * ufshcd_set_dma_mask - Set dma mask based on the controller
>> - * addressing capability
>> - * @pdev: PCI device structure
>> - *
>> - * Returns 0 for success, non-zero for failure
>> - */
>> -static int ufshcd_set_dma_mask(struct ufs_hba *hba)
>> -{
>> - int err;
>> - u64 dma_mask;
>> -
>> - /*
>> - * If controller supports 64 bit addressing mode, then set the DMA
>> - * mask to 64-bit, else set the DMA mask to 32-bit
>> - */
>> - if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT)
>> - dma_mask = DMA_BIT_MASK(64);
>> - else
>> - dma_mask = DMA_BIT_MASK(32);
>> -
>> - err = pci_set_dma_mask(hba->pdev, dma_mask);
>> - if (err)
>> - return err;
>> -
>> - err = pci_set_consistent_dma_mask(hba->pdev, dma_mask);
>> -
>> - return err;
>> -}
>> -
>> -/**
>> - * ufshcd_probe - probe routine of the driver
>> - * @pdev: pointer to PCI device handle
>> - * @id: PCI device id
>> + * ufshcd_drv_init - generic init routine of the driver
>> + * @hba: pointer to platform data
>> *
>> * Returns 0 on success, non-zero value on failure
>> */
>> -static int __devinit
>> -ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> +int ufshcd_drv_init(struct ufs_hba **hostdata, struct device *dev,
>> + int irq_no, void __iomem *mmio_base)
>> {
>> struct Scsi_Host *host;
>> - struct ufs_hba *hba;
>> int err;
>> -
>> - err = pci_enable_device(pdev);
>> - if (err) {
>> - dev_err(&pdev->dev, "pci_enable_device failed\n");
>> - goto out_error;
>> - }
>> -
>> - pci_set_master(pdev);
>> + struct ufs_hba *hba;
>>
>> host = scsi_host_alloc(&ufshcd_driver_template,
>> sizeof(struct ufs_hba));
>> if (!host) {
>> - dev_err(&pdev->dev, "scsi_host_alloc failed\n");
>> + dev_err(&hba->dev, "scsi_host_alloc failed\n");
>> err = -ENOMEM;
>> goto out_disable;
>> }
>> hba = shost_priv(host);
>> -
>> - err = pci_request_regions(pdev, UFSHCD);
>> - if (err < 0) {
>> - dev_err(&pdev->dev, "request regions failed\n");
>> - goto out_disable;
>> - }
>> -
>> - hba->mmio_base = pci_ioremap_bar(pdev, 0);
>> - if (!hba->mmio_base) {
>> - dev_err(&pdev->dev, "memory map failed\n");
>> - err = -ENOMEM;
>> - goto out_release_regions;
>> - }
>> -
>> + hba->dev = *dev;
> It doesn't look like you need to copy the entire device data into hba.
Will change it to only have the address.
> Why isn't a reference not sufficient ?
>
>
>> hba->host = host;
>> - hba->pdev = pdev;
>> + hba->irq = irq_no;
>> + hba->mmio_base = mmio_base;
>> + *hostdata = hba;
>>
>> /* Read capabilities registers */
>> ufshcd_hba_capabilities(hba);
>> @@ -1857,17 +1700,11 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> /* Get UFS version supported by the controller */
>> hba->ufs_version = ufshcd_get_ufs_version(hba);
>>
>> - err = ufshcd_set_dma_mask(hba);
>> - if (err) {
>> - dev_err(&pdev->dev, "set dma mask failed\n");
>> - goto out_iounmap;
>> - }
>> -
>> /* Allocate memory for host memory space */
>> err = ufshcd_memory_alloc(hba);
>> if (err) {
>> - dev_err(&pdev->dev, "Memory allocation failed\n");
>> - goto out_iounmap;
>> + dev_err(&hba->dev, "Memory allocation failed\n");
>> + goto out_disable;
>> }
>>
>> /* Configure LRB */
>> @@ -1889,72 +1726,55 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
>>
>> /* IRQ registration */
>> - err = request_irq(pdev->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
>> + err = request_irq(hba->irq, ufshcd_intr, IRQF_SHARED,
>> + ufs_hostname(hba), hba);
>> if (err) {
>> - dev_err(&pdev->dev, "request irq failed\n");
>> + dev_err(&hba->dev, "request irq failed\n");
>> goto out_lrb_free;
>> }
>>
>> /* Enable SCSI tag mapping */
>> err = scsi_init_shared_tag_map(host, host->can_queue);
>> if (err) {
>> - dev_err(&pdev->dev, "init shared queue failed\n");
>> - goto out_free_irq;
>> - }
>> -
>> - pci_set_drvdata(pdev, hba);
>> -
>> - err = scsi_add_host(host, &pdev->dev);
>> - if (err) {
>> - dev_err(&pdev->dev, "scsi_add_host failed\n");
>> + dev_err(&hba->dev, "init shared queue failed\n");
>> goto out_free_irq;
>> }
>>
>> - /* Initialization routine */
>> - err = ufshcd_initialize_hba(hba);
>> + err = scsi_add_host(host, &hba->dev);
>> if (err) {
>> - dev_err(&pdev->dev, "Initialization failed\n");
>> + dev_err(&hba->dev, "scsi_add_host failed\n");
>> goto out_free_irq;
>> }
>>
>> return 0;
>>
>> out_free_irq:
>> - free_irq(pdev->irq, hba);
>> + free_irq(hba->irq, hba);
>> out_lrb_free:
>> ufshcd_free_hba_memory(hba);
>> -out_iounmap:
>> - iounmap(hba->mmio_base);
>> -out_release_regions:
>> - pci_release_regions(pdev);
>> out_disable:
>> scsi_host_put(host);
>> - pci_clear_master(pdev);
>> - pci_disable_device(pdev);
>> -out_error:
>> return err;
>> }
>> +EXPORT_SYMBOL(ufshcd_drv_init);
>>
>> -static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
>> - { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
>> - { } /* terminate list */
>> -};
>> +static int __init ufshcd_probe(void)
>> +{
>> + pr_info(UFSHCD
>> + ": Generic UFS host controller driver\n");
>> + pr_info(UFSHCD ": Copyright(c) Samsung India Software Operations\n");
>>
> Is it really necessary to assert the copyright on probe ? I haven't
> seen this practice anywhere..
You can find one in driver/mmc/host/sdhci.c
>
>> -MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
>> + return 0;
>> +}
>>
>> -static struct pci_driver ufshcd_pci_driver = {
>> - .name = UFSHCD,
>> - .id_table = ufshcd_pci_tbl,
>> - .probe = ufshcd_probe,
>> - .remove = __devexit_p(ufshcd_remove),
>> - .shutdown = ufshcd_shutdown,
>> -#ifdef CONFIG_PM
>> - .suspend = ufshcd_suspend,
>> - .resume = ufshcd_resume,
>> -#endif
>> -};
>> +static void __exit ufshcd_remove(void)
>> +{
>> + pr_info(UFSHCD
>> + ": Generic UFS host controller driver removed\n");
>> +}
>>
>> -module_pci_driver(ufshcd_pci_driver);
>> +module_init(ufshcd_probe);
>> +module_exit(ufshcd_remove);
>>
>> MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>, "
>> "Vinayak Holikatti <h.vinayak@samsung.com>");
>> --
>> 1.7.4.1
>>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC V3 2/2] SCSI: UFS: Add platform support for ufs host controller
2012-05-22 5:37 ` S, Venkatraman
@ 2012-05-22 7:29 ` Girish K S
0 siblings, 0 replies; 9+ messages in thread
From: Girish K S @ 2012-05-22 7:29 UTC (permalink / raw)
To: S, Venkatraman
Cc: linux-scsi, james.bottomley, vinholikatti, santoshsy, hch, patches
On 22 May 2012 11:07, S, Venkatraman <svenkatr@ti.com> wrote:
> On Mon, May 21, 2012 at 12:01 PM, Girish K S
> <girish.shivananjappa@linaro.org> wrote:
>> This patch adds platform support for ufs host controller
>> The SoC's that use non-pci probing should use this option.
>>
>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> ---
>> drivers/scsi/ufs/Kconfig | 13 +++
>> drivers/scsi/ufs/Makefile | 1 +
>> drivers/scsi/ufs/ufshcd-pltfm.c | 180 +++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 194 insertions(+), 0 deletions(-)
>> create mode 100644 drivers/scsi/ufs/ufshcd-pltfm.c
>>
>> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
>> index 2a70972..dae5428 100644
>> --- a/drivers/scsi/ufs/Kconfig
>> +++ b/drivers/scsi/ufs/Kconfig
>> @@ -60,3 +60,16 @@ config SCSI_UFSHCD_PCI
>> If you have a controller with this interface, say Y or M here.
>>
>> If unsure, say N.
>> +
>> +config SCSI_UFSHCD_PLTFM
>> + tristate "Universal Flash Storage host support as platform device"
>> + depends on SCSI_UFSHCD
>> + help
>> + This selects the common helper functions support for Host Controller
>> + Interface based platform driver. Please select this option if the IP
>> + is present as a platform device. This is the common interface for the
>> + UFS Host Controller IP.
>> +
>> + If you have a controller with this interface, say Y or M here.
>> +
>> + If unsure, say N.
>> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
>> index 9eda0df..fc56471 100644
>> --- a/drivers/scsi/ufs/Makefile
>> +++ b/drivers/scsi/ufs/Makefile
>> @@ -1,3 +1,4 @@
>> # UFSHCD makefile
>> obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
>> obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
>> +obj-$(CONFIG_SCSI_UFSHCD_PLTFM) += ufshcd-pltfm.o
>> diff --git a/drivers/scsi/ufs/ufshcd-pltfm.c b/drivers/scsi/ufs/ufshcd-pltfm.c
>> new file mode 100644
>> index 0000000..7558210
>> --- /dev/null
>> +++ b/drivers/scsi/ufs/ufshcd-pltfm.c
>> @@ -0,0 +1,180 @@
>> +/*
>> + * Universal Flash Storage Host controller driver
>> + *
>> + * This code is based on drivers/scsi/ufs/ufshcd.c
>> + * Copyright (C) 2011-2012 Samsung India Software Operations
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version 2
>> + * of the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * NO WARRANTY
>> + * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
>> + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
>> + * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
>> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
>> + * solely responsible for determining the appropriateness of using and
>> + * distributing the Program and assumes all risks associated with its
>> + * exercise of rights under this Agreement, including but not limited to
>> + * the risks and costs of program errors, damage to or loss of data,
>> + * programs or equipment, and unavailability or interruption of operations.
>> +
>> + * DISCLAIMER OF LIABILITY
>> + * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
>> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> + * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
>> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
>> + * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
>> + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
>> +
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
>> + * USA.
>> + */
>> +
>> +#include <linux/interrupt.h>
>> +#include <linux/module.h>
>> +#include <linux/io.h>
>> +#include <linux/irq.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/dma-mapping.h>
>> +#include <scsi/scsi_host.h>
>> +
>> +#include "ufs.h"
>> +#include "ufshci.h"
>> +
>> +/**
>> + * ufshcd_pltfmset_dma_mask - Set dma mask based on the controller
>> + * addressing capability
>> + * @ihba: pointer to host platform data
>> + *
>> + * Returns 0 for success, non-zero for failure
>> + */
>> +static int ufshcd_pltfm_set_dma_mask(struct platform_device *pdev)
>> +{
>> + int err;
>> + u64 dma_mask;
>> +
>> + dma_mask = DMA_BIT_MASK(64);
>> + err = dma_set_coherent_mask(&pdev->dev, dma_mask);
>> + if (err) {
>> + dma_mask = DMA_BIT_MASK(32);
>> + err = dma_set_coherent_mask(&pdev->dev, dma_mask);
>> + }
>> +
>> + return err;
>> +}
>> +
>> +static int __devinit ufshcd_pltfm_probe(struct platform_device *pdev)
>> +{
>> + struct ufs_hba *uninitialized_var(hba);
>> + struct resource *regs;
>> + int err, irq;
>> + void __iomem *mmio_base;
>> +
>> + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + if (!regs)
>> + return -ENXIO;
>> +
>> + irq = platform_get_irq(pdev, 0);
>> + if (irq < 0)
>> + return irq;
>> +
>> + mmio_base = ioremap(regs->start, resource_size(regs));
>> + if (!mmio_base)
>> + return -ENOMEM;
>> +
>> + err = ufshcd_pltfm_set_dma_mask(pdev);
>> + if (err) {
>> + dev_err(&pdev->dev, "set dma mask failed\n");
>> + goto err_iounmap;
>> + }
>> +
>> + err = ufshcd_drv_init(&hba, &pdev->dev, irq, mmio_base);
>> + if (err)
>> + goto err_iounmap;
>> +
>> + platform_set_drvdata(pdev, hba);
>> +
>> + /* Initialization routine */
>> + err = ufshcd_initialize_hba(hba);
>> + if (err) {
>> + dev_err(&hba->dev, "Initialization failed\n");
>> + goto err_remove;
>> + }
>> +
>> + return err;
>> +
>> +err_remove:
>> + ufshcd_drv_exit(hba);
>> +err_iounmap:
>> + iounmap(hba->mmio_base);
>> + return err;
>> +}
>> +
>> +static int __devexit ufshcd_pltfm_remove(struct platform_device *pdev)
>> +{
>> + struct ufs_hba *hba = platform_get_drvdata(pdev);
>> +
>> + ufshcd_drv_exit(hba);
>> + iounmap(hba->mmio_base);
>> + platform_set_drvdata(pdev, NULL);
>> + return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int ufshcd_pltfm_suspend(struct device *dev)
>> +{
>> + int ret;
>> + struct ufs_hba *hba = dev_get_drvdata(dev);
>> +
>> + ret = ufshcd_suspend(hba);
>> + if (ret)
>> + return ret;
> The above 2 lines are redundant...
agreed.
>> +
>> + return 0;
> .. if you simply do a "return ret" here...
>
>> +}
>> +
>> +static int ufshcd_pltfm_resume(struct device *dev)
>> +{
>> + int ret;
>> + struct ufs_hba *hba = dev_get_drvdata(dev);
>> +
>> + ret = ufshcd_resume(hba);
>> + if (ret)
>> + return ret;
>
> .. ditto
>> +
>> + return 0;
>> +}
>> +#else
>> +#define ufshcd_pltfm_suspend NULL
>> +#define ufshcd_pltfm_resume NULL
>> +#endif /* CONFIG_PM */
>> +
>> +static SIMPLE_DEV_PM_OPS(ufshcd_pltfm_pmops,
>> + ufshcd_pltfm_suspend,
>> + ufshcd_pltfm_resume);
>> +
>> +static struct platform_driver ufshcd_pltfm_driver = {
>> + .probe = ufshcd_pltfm_probe,
>> + .remove = __devexit_p(ufshcd_pltfm_remove),
>> + .driver = {
>> + .name = "ufshcd-pltfm",
>> + .pm = &ufshcd_pltfm_pmops,
>> + },
>> +};
>> +
>> +module_platform_driver(ufshcd_pltfm_driver);
>> +
>> +MODULE_DESCRIPTION("UFS Host Controller platform Interface driver");
>> +MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
>> +MODULE_LICENSE("GPL");
>> --
>> 1.7.4.1
>>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules
2012-05-22 5:29 ` S, Venkatraman
2012-05-22 7:22 ` Girish K S
@ 2012-05-22 7:34 ` James Bottomley
2012-05-22 8:46 ` Girish K S
1 sibling, 1 reply; 9+ messages in thread
From: James Bottomley @ 2012-05-22 7:34 UTC (permalink / raw)
To: S, Venkatraman
Cc: Girish K S, linux-scsi, vinholikatti, santoshsy, hch, patches
On Tue, 2012-05-22 at 10:59 +0530, S, Venkatraman wrote:
[...]
trimming your reply to give only the relevant part would be greatly
appreciated so we don't have to go through hundreds of lines to find the
useful bits.
> > +static int __init ufshcd_probe(void)
> > +{
> > + pr_info(UFSHCD
> > + ": Generic UFS host controller driver\n");
> > + pr_info(UFSHCD ": Copyright(c) Samsung India Software Operations\n");
> Is it really necessary to assert the copyright on probe ? I haven't
> seen this practice anywhere..
It has been done before, but it's now frowned upon because if everyone
did it, the kernel would be more verbose than a guilty politician before
the ethics committee, so please just remove it.
James
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules
2012-05-22 7:34 ` James Bottomley
@ 2012-05-22 8:46 ` Girish K S
0 siblings, 0 replies; 9+ messages in thread
From: Girish K S @ 2012-05-22 8:46 UTC (permalink / raw)
To: James Bottomley
Cc: S, Venkatraman, linux-scsi, vinholikatti, santoshsy, hch, patches
On 22 May 2012 13:04, James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
> On Tue, 2012-05-22 at 10:59 +0530, S, Venkatraman wrote:
> [...]
>
> trimming your reply to give only the relevant part would be greatly
> appreciated so we don't have to go through hundreds of lines to find the
> useful bits.
>
>> > +static int __init ufshcd_probe(void)
>> > +{
>> > + pr_info(UFSHCD
>> > + ": Generic UFS host controller driver\n");
>> > + pr_info(UFSHCD ": Copyright(c) Samsung India Software Operations\n");
>
>> Is it really necessary to assert the copyright on probe ? I haven't
>> seen this practice anywhere..
>
> It has been done before, but it's now frowned upon because if everyone
> did it, the kernel would be more verbose than a guilty politician before
> the ethics committee, so please just remove it.
OK will remove it.
>
> James
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-05-22 8:46 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-21 6:31 [RFC V3 0/2] Add support for pci/non-pci probing for UFS Girish K S
2012-05-21 6:31 ` [RFC V3 1/2] SCSI: UFS: Create separate UFS core and pci modules Girish K S
2012-05-22 5:29 ` S, Venkatraman
2012-05-22 7:22 ` Girish K S
2012-05-22 7:34 ` James Bottomley
2012-05-22 8:46 ` Girish K S
2012-05-21 6:31 ` [RFC V3 2/2] SCSI: UFS: Add platform support for ufs host controller Girish K S
2012-05-22 5:37 ` S, Venkatraman
2012-05-22 7:29 ` Girish K S
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.