aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorVinayak Holikatti <vinholikatti@gmail.com>2013-02-25 11:14:33 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-02-25 11:56:32 -0500
commite0eca63e342124cff4307eafb43908cab5b3cf88 (patch)
tree3e5c881c16ba56157905fdc492029a7ad2ddfbcc /drivers/scsi
parent3b1d05807a9a68c6d0580e9248247a774a4d3be6 (diff)
[SCSI] ufs: Separate PCI code into glue driver
This patch separates PCI code from ufshcd.c and makes it as a core driver module and adds a new file ufshcd-pci.c as PCI glue driver. [jejb: strip __devinit and devexit_p()] Reviewed-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com> Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org> Tested-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com> Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ufs/Kconfig26
-rw-r--r--drivers/scsi/ufs/Makefile1
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c211
-rw-r--r--drivers/scsi/ufs/ufshcd.c327
-rw-r--r--drivers/scsi/ufs/ufshcd.h202
5 files changed, 440 insertions, 327 deletions
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 8ee40dff3dfb..0371047c5922 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -33,7 +33,27 @@
33# this program. 33# this program.
34 34
35config SCSI_UFSHCD 35config SCSI_UFSHCD
36 tristate "Universal Flash Storage host controller driver" 36 tristate "Universal Flash Storage Controller Driver Core"
37 depends on PCI && SCSI 37 depends on SCSI
38 ---help--- 38 ---help---
39 This is a generic driver which supports PCIe UFS Host controllers. 39 This selects the support for UFS devices in Linux, say Y and make
40 sure that you know the name of your UFS host adapter (the card
41 inside your computer that "speaks" the UFS protocol, also
42 called UFS Host Controller), because you will be asked for it.
43 The module will be called ufshcd.
44
45 To compile this driver as a module, choose M here and read
46 <file:Documentation/scsi/ufs.txt>.
47 However, do not compile this as a module if your root file system
48 (the one containing the directory /) is located on a UFS device.
49
50config SCSI_UFSHCD_PCI
51 tristate "PCI bus based UFS Controller support"
52 depends on SCSI_UFSHCD && PCI
53 ---help---
54 This selects the PCI UFS Host Controller Interface. Select this if
55 you have UFS Host Controller with PCI Interface.
56
57 If you have a controller with this interface, say Y or M here.
58
59 If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index adf7895a6a91..9eda0dfbd6df 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,2 +1,3 @@
1# UFSHCD makefile 1# UFSHCD makefile
2obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o 2obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
3obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
new file mode 100644
index 000000000000..5cb1d75f5868
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -0,0 +1,211 @@
1/*
2 * Universal Flash Storage Host controller PCI glue driver
3 *
4 * This code is based on drivers/scsi/ufs/ufshcd-pci.c
5 * Copyright (C) 2011-2013 Samsung India Software Operations
6 *
7 * Authors:
8 * Santosh Yaraganavi <santosh.sy@samsung.com>
9 * Vinayak Holikatti <h.vinayak@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 * See the COPYING file in the top-level directory or visit
16 * <http://www.gnu.org/licenses/gpl-2.0.html>
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * This program is provided "AS IS" and "WITH ALL FAULTS" and
24 * without warranty of any kind. You are solely responsible for
25 * determining the appropriateness of using and distributing
26 * the program and assume all risks associated with your exercise
27 * of rights with respect to the program, including but not limited
28 * to infringement of third party rights, the risks and costs of
29 * program errors, damage to or loss of data, programs or equipment,
30 * and unavailability or interruption of operations. Under no
31 * circumstances will the contributor of this Program be liable for
32 * any damages of any kind arising from your use or distribution of
33 * this program.
34 */
35
36#include "ufshcd.h"
37#include <linux/pci.h>
38
39#ifdef CONFIG_PM
40/**
41 * ufshcd_pci_suspend - suspend power management function
42 * @pdev: pointer to PCI device handle
43 * @state: power state
44 *
45 * Returns -ENOSYS
46 */
47static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
48{
49 /*
50 * TODO:
51 * 1. Call ufshcd_suspend
52 * 2. Do bus specific power management
53 */
54
55 return -ENOSYS;
56}
57
58/**
59 * ufshcd_pci_resume - resume power management function
60 * @pdev: pointer to PCI device handle
61 *
62 * Returns -ENOSYS
63 */
64static int ufshcd_pci_resume(struct pci_dev *pdev)
65{
66 /*
67 * TODO:
68 * 1. Call ufshcd_resume.
69 * 2. Do bus specific wake up
70 */
71
72 return -ENOSYS;
73}
74#endif /* CONFIG_PM */
75
76/**
77 * ufshcd_pci_shutdown - main function to put the controller in reset state
78 * @pdev: pointer to PCI device handle
79 */
80static void ufshcd_pci_shutdown(struct pci_dev *pdev)
81{
82 ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
83}
84
85/**
86 * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
87 * data structure memory
88 * @pdev - pointer to PCI handle
89 */
90static void ufshcd_pci_remove(struct pci_dev *pdev)
91{
92 struct ufs_hba *hba = pci_get_drvdata(pdev);
93
94 disable_irq(pdev->irq);
95 free_irq(pdev->irq, hba);
96 ufshcd_remove(hba);
97 pci_release_regions(pdev);
98 pci_set_drvdata(pdev, NULL);
99 pci_clear_master(pdev);
100 pci_disable_device(pdev);
101}
102
103/**
104 * ufshcd_set_dma_mask - Set dma mask based on the controller
105 * addressing capability
106 * @pdev: PCI device structure
107 *
108 * Returns 0 for success, non-zero for failure
109 */
110static int ufshcd_set_dma_mask(struct pci_dev *pdev)
111{
112 int err;
113
114 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
115 && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
116 return 0;
117 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
118 if (!err)
119 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
120 return err;
121}
122
123/**
124 * ufshcd_pci_probe - probe routine of the driver
125 * @pdev: pointer to PCI device handle
126 * @id: PCI device id
127 *
128 * Returns 0 on success, non-zero value on failure
129 */
130static int
131ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
132{
133 struct ufs_hba *hba;
134 void __iomem *mmio_base;
135 int err;
136
137 err = pci_enable_device(pdev);
138 if (err) {
139 dev_err(&pdev->dev, "pci_enable_device failed\n");
140 goto out_error;
141 }
142
143 pci_set_master(pdev);
144
145
146 err = pci_request_regions(pdev, UFSHCD);
147 if (err < 0) {
148 dev_err(&pdev->dev, "request regions failed\n");
149 goto out_disable;
150 }
151
152 mmio_base = pci_ioremap_bar(pdev, 0);
153 if (!mmio_base) {
154 dev_err(&pdev->dev, "memory map failed\n");
155 err = -ENOMEM;
156 goto out_release_regions;
157 }
158
159 err = ufshcd_set_dma_mask(pdev);
160 if (err) {
161 dev_err(&pdev->dev, "set dma mask failed\n");
162 goto out_iounmap;
163 }
164
165 err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
166 if (err) {
167 dev_err(&pdev->dev, "Initialization failed\n");
168 goto out_iounmap;
169 }
170
171 pci_set_drvdata(pdev, hba);
172
173 return 0;
174
175out_iounmap:
176 iounmap(mmio_base);
177out_release_regions:
178 pci_release_regions(pdev);
179out_disable:
180 pci_clear_master(pdev);
181 pci_disable_device(pdev);
182out_error:
183 return err;
184}
185
186static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
187 { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
188 { } /* terminate list */
189};
190
191MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
192
193static struct pci_driver ufshcd_pci_driver = {
194 .name = UFSHCD,
195 .id_table = ufshcd_pci_tbl,
196 .probe = ufshcd_pci_probe,
197 .remove = ufshcd_pci_remove,
198 .shutdown = ufshcd_pci_shutdown,
199#ifdef CONFIG_PM
200 .suspend = ufshcd_pci_suspend,
201 .resume = ufshcd_pci_resume,
202#endif
203};
204
205module_pci_driver(ufshcd_pci_driver);
206
207MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
208MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
209MODULE_DESCRIPTION("UFS host controller PCI glue driver");
210MODULE_LICENSE("GPL");
211MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5f7c0173d8a0..60fd40c4e4c2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Universal Flash Storage Host controller driver 2 * Universal Flash Storage Host controller driver Core
3 * 3 *
4 * This code is based on drivers/scsi/ufs/ufshcd.c 4 * This code is based on drivers/scsi/ufs/ufshcd.c
5 * Copyright (C) 2011-2013 Samsung India Software Operations 5 * Copyright (C) 2011-2013 Samsung India Software Operations
@@ -33,35 +33,7 @@
33 * this program. 33 * this program.
34 */ 34 */
35 35
36#include <linux/module.h> 36#include "ufshcd.h"
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/pci.h>
40#include <linux/interrupt.h>
41#include <linux/io.h>
42#include <linux/delay.h>
43#include <linux/slab.h>
44#include <linux/spinlock.h>
45#include <linux/workqueue.h>
46#include <linux/errno.h>
47#include <linux/types.h>
48#include <linux/wait.h>
49#include <linux/bitops.h>
50
51#include <asm/irq.h>
52#include <asm/byteorder.h>
53#include <scsi/scsi.h>
54#include <scsi/scsi_cmnd.h>
55#include <scsi/scsi_host.h>
56#include <scsi/scsi_tcq.h>
57#include <scsi/scsi_dbg.h>
58#include <scsi/scsi_eh.h>
59
60#include "ufs.h"
61#include "ufshci.h"
62
63#define UFSHCD "ufshcd"
64#define UFSHCD_DRIVER_VERSION "0.1"
65 37
66enum { 38enum {
67 UFSHCD_MAX_CHANNEL = 0, 39 UFSHCD_MAX_CHANNEL = 0,
@@ -92,124 +64,6 @@ enum {
92}; 64};
93 65
94/** 66/**
95 * struct uic_command - UIC command structure
96 * @command: UIC command
97 * @argument1: UIC command argument 1
98 * @argument2: UIC command argument 2
99 * @argument3: UIC command argument 3
100 * @cmd_active: Indicate if UIC command is outstanding
101 * @result: UIC command result
102 */
103struct uic_command {
104 u32 command;
105 u32 argument1;
106 u32 argument2;
107 u32 argument3;
108 int cmd_active;
109 int result;
110};
111
112/**
113 * struct ufs_hba - per adapter private structure
114 * @mmio_base: UFSHCI base register address
115 * @ucdl_base_addr: UFS Command Descriptor base address
116 * @utrdl_base_addr: UTP Transfer Request Descriptor base address
117 * @utmrdl_base_addr: UTP Task Management Descriptor base address
118 * @ucdl_dma_addr: UFS Command Descriptor DMA address
119 * @utrdl_dma_addr: UTRDL DMA address
120 * @utmrdl_dma_addr: UTMRDL DMA address
121 * @host: Scsi_Host instance of the driver
122 * @dev: device handle
123 * @lrb: local reference block
124 * @outstanding_tasks: Bits representing outstanding task requests
125 * @outstanding_reqs: Bits representing outstanding transfer requests
126 * @capabilities: UFS Controller Capabilities
127 * @nutrs: Transfer Request Queue depth supported by controller
128 * @nutmrs: Task Management Queue depth supported by controller
129 * @ufs_version: UFS Version to which controller complies
130 * @irq: Irq number of the controller
131 * @active_uic_cmd: handle of active UIC command
132 * @ufshcd_tm_wait_queue: wait queue for task management
133 * @tm_condition: condition variable for task management
134 * @ufshcd_state: UFSHCD states
135 * @int_enable_mask: Interrupt Mask Bits
136 * @uic_workq: Work queue for UIC completion handling
137 * @feh_workq: Work queue for fatal controller error handling
138 * @errors: HBA errors
139 */
140struct ufs_hba {
141 void __iomem *mmio_base;
142
143 /* Virtual memory reference */
144 struct utp_transfer_cmd_desc *ucdl_base_addr;
145 struct utp_transfer_req_desc *utrdl_base_addr;
146 struct utp_task_req_desc *utmrdl_base_addr;
147
148 /* DMA memory reference */
149 dma_addr_t ucdl_dma_addr;
150 dma_addr_t utrdl_dma_addr;
151 dma_addr_t utmrdl_dma_addr;
152
153 struct Scsi_Host *host;
154 struct device *dev;
155
156 struct ufshcd_lrb *lrb;
157
158 unsigned long outstanding_tasks;
159 unsigned long outstanding_reqs;
160
161 u32 capabilities;
162 int nutrs;
163 int nutmrs;
164 u32 ufs_version;
165 unsigned int irq;
166
167 struct uic_command active_uic_cmd;
168 wait_queue_head_t ufshcd_tm_wait_queue;
169 unsigned long tm_condition;
170
171 u32 ufshcd_state;
172 u32 int_enable_mask;
173
174 /* Work Queues */
175 struct work_struct uic_workq;
176 struct work_struct feh_workq;
177
178 /* HBA Errors */
179 u32 errors;
180};
181
182/**
183 * struct ufshcd_lrb - local reference block
184 * @utr_descriptor_ptr: UTRD address of the command
185 * @ucd_cmd_ptr: UCD address of the command
186 * @ucd_rsp_ptr: Response UPIU address for this command
187 * @ucd_prdt_ptr: PRDT address of the command
188 * @cmd: pointer to SCSI command
189 * @sense_buffer: pointer to sense buffer address of the SCSI command
190 * @sense_bufflen: Length of the sense buffer
191 * @scsi_status: SCSI status of the command
192 * @command_type: SCSI, UFS, Query.
193 * @task_tag: Task tag of the command
194 * @lun: LUN of the command
195 */
196struct ufshcd_lrb {
197 struct utp_transfer_req_desc *utr_descriptor_ptr;
198 struct utp_upiu_cmd *ucd_cmd_ptr;
199 struct utp_upiu_rsp *ucd_rsp_ptr;
200 struct ufshcd_sg_entry *ucd_prdt_ptr;
201
202 struct scsi_cmnd *cmd;
203 u8 *sense_buffer;
204 unsigned int sense_bufflen;
205 int scsi_status;
206
207 int command_type;
208 int task_tag;
209 unsigned int lun;
210};
211
212/**
213 * ufshcd_get_ufs_version - Get the UFS version supported by the HBA 67 * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
214 * @hba - Pointer to adapter instance 68 * @hba - Pointer to adapter instance
215 * 69 *
@@ -422,15 +276,6 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
422} 276}
423 277
424/** 278/**
425 * ufshcd_hba_stop - Send controller to reset state
426 * @hba: per adapter instance
427 */
428static inline void ufshcd_hba_stop(struct ufs_hba *hba)
429{
430 writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
431}
432
433/**
434 * ufshcd_hba_start - Start controller initialization sequence 279 * ufshcd_hba_start - Start controller initialization sequence
435 * @hba: per adapter instance 280 * @hba: per adapter instance
436 */ 281 */
@@ -1681,15 +1526,6 @@ static struct scsi_host_template ufshcd_driver_template = {
1681}; 1526};
1682 1527
1683/** 1528/**
1684 * ufshcd_pci_shutdown - main function to put the controller in reset state
1685 * @pdev: pointer to PCI device handle
1686 */
1687static void ufshcd_pci_shutdown(struct pci_dev *pdev)
1688{
1689 ufshcd_hba_stop((struct ufs_hba *)pci_get_drvdata(pdev));
1690}
1691
1692/**
1693 * ufshcd_suspend - suspend power management function 1529 * ufshcd_suspend - suspend power management function
1694 * @hba: per adapter instance 1530 * @hba: per adapter instance
1695 * @state: power state 1531 * @state: power state
@@ -1732,43 +1568,6 @@ int ufshcd_resume(struct ufs_hba *hba)
1732} 1568}
1733EXPORT_SYMBOL_GPL(ufshcd_resume); 1569EXPORT_SYMBOL_GPL(ufshcd_resume);
1734 1570
1735#ifdef CONFIG_PM
1736/**
1737 * ufshcd_pci_suspend - suspend power management function
1738 * @pdev: pointer to PCI device handle
1739 * @state: power state
1740 *
1741 * Returns -ENOSYS
1742 */
1743static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
1744{
1745 /*
1746 * TODO:
1747 * 1. Call ufshcd_suspend
1748 * 2. Do bus specific power management
1749 */
1750
1751 return -ENOSYS;
1752}
1753
1754/**
1755 * ufshcd_pci_resume - resume power management function
1756 * @pdev: pointer to PCI device handle
1757 *
1758 * Returns -ENOSYS
1759 */
1760static int ufshcd_pci_resume(struct pci_dev *pdev)
1761{
1762 /*
1763 * TODO:
1764 * 1. Call ufshcd_resume
1765 * 2. Do bus specific wake up
1766 */
1767
1768 return -ENOSYS;
1769}
1770#endif /* CONFIG_PM */
1771
1772/** 1571/**
1773 * ufshcd_hba_free - free allocated memory for 1572 * ufshcd_hba_free - free allocated memory for
1774 * host memory space data structures 1573 * host memory space data structures
@@ -1799,44 +1598,6 @@ void ufshcd_remove(struct ufs_hba *hba)
1799EXPORT_SYMBOL_GPL(ufshcd_remove); 1598EXPORT_SYMBOL_GPL(ufshcd_remove);
1800 1599
1801/** 1600/**
1802 * ufshcd_pci_remove - de-allocate PCI/SCSI host and host memory space
1803 * data structure memory
1804 * @pdev - pointer to PCI handle
1805 */
1806static void ufshcd_pci_remove(struct pci_dev *pdev)
1807{
1808 struct ufs_hba *hba = pci_get_drvdata(pdev);
1809
1810 disable_irq(pdev->irq);
1811 free_irq(pdev->irq, hba);
1812 ufshcd_remove(hba);
1813 pci_release_regions(pdev);
1814 pci_set_drvdata(pdev, NULL);
1815 pci_clear_master(pdev);
1816 pci_disable_device(pdev);
1817}
1818
1819/**
1820 * ufshcd_set_dma_mask - Set dma mask based on the controller
1821 * addressing capability
1822 * @pdev: PCI device structure
1823 *
1824 * Returns 0 for success, non-zero for failure
1825 */
1826static int ufshcd_set_dma_mask(struct pci_dev *pdev)
1827{
1828 int err;
1829
1830 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1831 && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
1832 return 0;
1833 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
1834 if (!err)
1835 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
1836 return err;
1837}
1838
1839/**
1840 * ufshcd_init - Driver initialization routine 1601 * ufshcd_init - Driver initialization routine
1841 * @dev: pointer to device handle 1602 * @dev: pointer to device handle
1842 * @hba_handle: driver private handle 1603 * @hba_handle: driver private handle
@@ -1952,90 +1713,8 @@ out_error:
1952} 1713}
1953EXPORT_SYMBOL_GPL(ufshcd_init); 1714EXPORT_SYMBOL_GPL(ufshcd_init);
1954 1715
1955/**
1956 * ufshcd_pci_probe - probe routine of the driver
1957 * @pdev: pointer to PCI device handle
1958 * @id: PCI device id
1959 *
1960 * Returns 0 on success, non-zero value on failure
1961 */
1962static int ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1963{
1964 struct ufs_hba *hba;
1965 void __iomem *mmio_base;
1966 int err;
1967
1968 err = pci_enable_device(pdev);
1969 if (err) {
1970 dev_err(&pdev->dev, "pci_enable_device failed\n");
1971 goto out_error;
1972 }
1973
1974 pci_set_master(pdev);
1975
1976 err = pci_request_regions(pdev, UFSHCD);
1977 if (err < 0) {
1978 dev_err(&pdev->dev, "request regions failed\n");
1979 goto out_disable;
1980 }
1981
1982 mmio_base = pci_ioremap_bar(pdev, 0);
1983 if (!mmio_base) {
1984 dev_err(&pdev->dev, "memory map failed\n");
1985 err = -ENOMEM;
1986 goto out_release_regions;
1987 }
1988
1989 err = ufshcd_set_dma_mask(pdev);
1990 if (err) {
1991 dev_err(&pdev->dev, "set dma mask failed\n");
1992 goto out_iounmap;
1993 }
1994
1995 err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
1996 if (err) {
1997 dev_err(&pdev->dev, "Initialization failed\n");
1998 goto out_iounmap;
1999 }
2000
2001 pci_set_drvdata(pdev, hba);
2002
2003 return 0;
2004
2005out_iounmap:
2006 iounmap(mmio_base);
2007out_release_regions:
2008 pci_release_regions(pdev);
2009out_disable:
2010 pci_clear_master(pdev);
2011 pci_disable_device(pdev);
2012out_error:
2013 return err;
2014}
2015
2016static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
2017 { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
2018 { } /* terminate list */
2019};
2020
2021MODULE_DEVICE_TABLE(pci, ufshcd_pci_tbl);
2022
2023static struct pci_driver ufshcd_pci_driver = {
2024 .name = UFSHCD,
2025 .id_table = ufshcd_pci_tbl,
2026 .probe = ufshcd_pci_probe,
2027 .remove = ufshcd_pci_remove,
2028 .shutdown = ufshcd_pci_shutdown,
2029#ifdef CONFIG_PM
2030 .suspend = ufshcd_pci_suspend,
2031 .resume = ufshcd_pci_resume,
2032#endif
2033};
2034
2035module_pci_driver(ufshcd_pci_driver);
2036
2037MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>"); 1716MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
2038MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>"); 1717MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
2039MODULE_DESCRIPTION("Generic UFS host controller driver"); 1718MODULE_DESCRIPTION("Generic UFS host controller driver Core");
2040MODULE_LICENSE("GPL"); 1719MODULE_LICENSE("GPL");
2041MODULE_VERSION(UFSHCD_DRIVER_VERSION); 1720MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
new file mode 100644
index 000000000000..6b99a42f5819
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -0,0 +1,202 @@
1/*
2 * Universal Flash Storage Host controller driver
3 *
4 * This code is based on drivers/scsi/ufs/ufshcd.h
5 * Copyright (C) 2011-2013 Samsung India Software Operations
6 *
7 * Authors:
8 * Santosh Yaraganavi <santosh.sy@samsung.com>
9 * Vinayak Holikatti <h.vinayak@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 * See the COPYING file in the top-level directory or visit
16 * <http://www.gnu.org/licenses/gpl-2.0.html>
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * This program is provided "AS IS" and "WITH ALL FAULTS" and
24 * without warranty of any kind. You are solely responsible for
25 * determining the appropriateness of using and distributing
26 * the program and assume all risks associated with your exercise
27 * of rights with respect to the program, including but not limited
28 * to infringement of third party rights, the risks and costs of
29 * program errors, damage to or loss of data, programs or equipment,
30 * and unavailability or interruption of operations. Under no
31 * circumstances will the contributor of this Program be liable for
32 * any damages of any kind arising from your use or distribution of
33 * this program.
34 */
35
36#ifndef _UFSHCD_H
37#define _UFSHCD_H
38
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/interrupt.h>
43#include <linux/io.h>
44#include <linux/delay.h>
45#include <linux/slab.h>
46#include <linux/spinlock.h>
47#include <linux/workqueue.h>
48#include <linux/errno.h>
49#include <linux/types.h>
50#include <linux/wait.h>
51#include <linux/bitops.h>
52#include <linux/pm_runtime.h>
53#include <linux/clk.h>
54
55#include <asm/irq.h>
56#include <asm/byteorder.h>
57#include <scsi/scsi.h>
58#include <scsi/scsi_cmnd.h>
59#include <scsi/scsi_host.h>
60#include <scsi/scsi_tcq.h>
61#include <scsi/scsi_dbg.h>
62#include <scsi/scsi_eh.h>
63
64#include "ufs.h"
65#include "ufshci.h"
66
67#define UFSHCD "ufshcd"
68#define UFSHCD_DRIVER_VERSION "0.2"
69
70/**
71 * struct uic_command - UIC command structure
72 * @command: UIC command
73 * @argument1: UIC command argument 1
74 * @argument2: UIC command argument 2
75 * @argument3: UIC command argument 3
76 * @cmd_active: Indicate if UIC command is outstanding
77 * @result: UIC command result
78 */
79struct uic_command {
80 u32 command;
81 u32 argument1;
82 u32 argument2;
83 u32 argument3;
84 int cmd_active;
85 int result;
86};
87
88/**
89 * struct ufshcd_lrb - local reference block
90 * @utr_descriptor_ptr: UTRD address of the command
91 * @ucd_cmd_ptr: UCD address of the command
92 * @ucd_rsp_ptr: Response UPIU address for this command
93 * @ucd_prdt_ptr: PRDT address of the command
94 * @cmd: pointer to SCSI command
95 * @sense_buffer: pointer to sense buffer address of the SCSI command
96 * @sense_bufflen: Length of the sense buffer
97 * @scsi_status: SCSI status of the command
98 * @command_type: SCSI, UFS, Query.
99 * @task_tag: Task tag of the command
100 * @lun: LUN of the command
101 */
102struct ufshcd_lrb {
103 struct utp_transfer_req_desc *utr_descriptor_ptr;
104 struct utp_upiu_cmd *ucd_cmd_ptr;
105 struct utp_upiu_rsp *ucd_rsp_ptr;
106 struct ufshcd_sg_entry *ucd_prdt_ptr;
107
108 struct scsi_cmnd *cmd;
109 u8 *sense_buffer;
110 unsigned int sense_bufflen;
111 int scsi_status;
112
113 int command_type;
114 int task_tag;
115 unsigned int lun;
116};
117
118
119/**
120 * struct ufs_hba - per adapter private structure
121 * @mmio_base: UFSHCI base register address
122 * @ucdl_base_addr: UFS Command Descriptor base address
123 * @utrdl_base_addr: UTP Transfer Request Descriptor base address
124 * @utmrdl_base_addr: UTP Task Management Descriptor base address
125 * @ucdl_dma_addr: UFS Command Descriptor DMA address
126 * @utrdl_dma_addr: UTRDL DMA address
127 * @utmrdl_dma_addr: UTMRDL DMA address
128 * @host: Scsi_Host instance of the driver
129 * @dev: device handle
130 * @lrb: local reference block
131 * @outstanding_tasks: Bits representing outstanding task requests
132 * @outstanding_reqs: Bits representing outstanding transfer requests
133 * @capabilities: UFS Controller Capabilities
134 * @nutrs: Transfer Request Queue depth supported by controller
135 * @nutmrs: Task Management Queue depth supported by controller
136 * @ufs_version: UFS Version to which controller complies
137 * @irq: Irq number of the controller
138 * @active_uic_cmd: handle of active UIC command
139 * @ufshcd_tm_wait_queue: wait queue for task management
140 * @tm_condition: condition variable for task management
141 * @ufshcd_state: UFSHCD states
142 * @int_enable_mask: Interrupt Mask Bits
143 * @uic_workq: Work queue for UIC completion handling
144 * @feh_workq: Work queue for fatal controller error handling
145 * @errors: HBA errors
146 */
147struct ufs_hba {
148 void __iomem *mmio_base;
149
150 /* Virtual memory reference */
151 struct utp_transfer_cmd_desc *ucdl_base_addr;
152 struct utp_transfer_req_desc *utrdl_base_addr;
153 struct utp_task_req_desc *utmrdl_base_addr;
154
155 /* DMA memory reference */
156 dma_addr_t ucdl_dma_addr;
157 dma_addr_t utrdl_dma_addr;
158 dma_addr_t utmrdl_dma_addr;
159
160 struct Scsi_Host *host;
161 struct device *dev;
162
163 struct ufshcd_lrb *lrb;
164
165 unsigned long outstanding_tasks;
166 unsigned long outstanding_reqs;
167
168 u32 capabilities;
169 int nutrs;
170 int nutmrs;
171 u32 ufs_version;
172 unsigned int irq;
173
174 struct uic_command active_uic_cmd;
175 wait_queue_head_t ufshcd_tm_wait_queue;
176 unsigned long tm_condition;
177
178 u32 ufshcd_state;
179 u32 int_enable_mask;
180
181 /* Work Queues */
182 struct work_struct uic_workq;
183 struct work_struct feh_workq;
184
185 /* HBA Errors */
186 u32 errors;
187};
188
189int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
190 unsigned int);
191void ufshcd_remove(struct ufs_hba *);
192
193/**
194 * ufshcd_hba_stop - Send controller to reset state
195 * @hba: per adapter instance
196 */
197static inline void ufshcd_hba_stop(struct ufs_hba *hba)
198{
199 writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
200}
201
202#endif /* End of Header */