2013-02-25 21:44:33 +05:30
/*
* Universal Flash Storage Host controller driver
*
* This code is based on drivers / scsi / ufs / ufshcd . h
* Copyright ( C ) 2011 - 2013 Samsung India Software Operations
*
* Authors :
* Santosh Yaraganavi < santosh . sy @ samsung . com >
* Vinayak Holikatti < h . vinayak @ samsung . com >
*
* 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 .
* See the COPYING file in the top - level directory or visit
* < http : //www.gnu.org/licenses/gpl-2.0.html>
*
* 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 .
*
* This program is provided " AS IS " and " WITH ALL FAULTS " and
* without warranty of any kind . You are solely responsible for
* determining the appropriateness of using and distributing
* the program and assume all risks associated with your exercise
* of rights with respect to the program , including but not limited
* to infringement of third party rights , the risks and costs of
* program errors , damage to or loss of data , programs or equipment ,
* and unavailability or interruption of operations . Under no
* circumstances will the contributor of this Program be liable for
* any damages of any kind arising from your use or distribution of
* this program .
*/
# ifndef _UFSHCD_H
# define _UFSHCD_H
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/delay.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
# include <linux/workqueue.h>
# include <linux/errno.h>
# include <linux/types.h>
# include <linux/wait.h>
# include <linux/bitops.h>
# include <linux/pm_runtime.h>
# include <linux/clk.h>
2013-06-26 22:39:29 +05:30
# include <linux/completion.h>
2013-02-25 21:44:33 +05:30
# include <asm/irq.h>
# include <asm/byteorder.h>
# include <scsi/scsi.h>
# include <scsi/scsi_cmnd.h>
# include <scsi/scsi_host.h>
# include <scsi/scsi_tcq.h>
# include <scsi/scsi_dbg.h>
# include <scsi/scsi_eh.h>
# include "ufs.h"
# include "ufshci.h"
# define UFSHCD "ufshcd"
# define UFSHCD_DRIVER_VERSION "0.2"
2014-09-25 15:32:21 +03:00
struct ufs_hba ;
2013-07-30 00:35:57 +05:30
enum dev_cmd_type {
DEV_CMD_TYPE_NOP = 0x0 ,
2013-07-30 00:35:58 +05:30
DEV_CMD_TYPE_QUERY = 0x1 ,
2013-07-30 00:35:57 +05:30
} ;
2013-02-25 21:44:33 +05:30
/**
* 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
2013-06-26 22:39:29 +05:30
* @ done : UIC command completion
2013-02-25 21:44:33 +05:30
*/
struct uic_command {
u32 command ;
u32 argument1 ;
u32 argument2 ;
u32 argument3 ;
int cmd_active ;
int result ;
2013-06-26 22:39:29 +05:30
struct completion done ;
2013-02-25 21:44:33 +05:30
} ;
/**
* struct ufshcd_lrb - local reference block
* @ utr_descriptor_ptr : UTRD address of the command
2013-07-30 00:35:57 +05:30
* @ ucd_req_ptr : UCD address of the command
2013-02-25 21:44:33 +05:30
* @ ucd_rsp_ptr : Response UPIU address for this command
* @ ucd_prdt_ptr : PRDT address of the command
* @ cmd : pointer to SCSI command
* @ sense_buffer : pointer to sense buffer address of the SCSI command
* @ sense_bufflen : Length of the sense buffer
* @ scsi_status : SCSI status of the command
* @ command_type : SCSI , UFS , Query .
* @ task_tag : Task tag of the command
* @ lun : LUN of the command
2013-07-30 00:35:57 +05:30
* @ intr_cmd : Interrupt command ( doesn ' t participate in interrupt aggregation )
2013-02-25 21:44:33 +05:30
*/
struct ufshcd_lrb {
struct utp_transfer_req_desc * utr_descriptor_ptr ;
2013-07-30 00:35:57 +05:30
struct utp_upiu_req * ucd_req_ptr ;
2013-02-25 21:44:33 +05:30
struct utp_upiu_rsp * ucd_rsp_ptr ;
struct ufshcd_sg_entry * ucd_prdt_ptr ;
struct scsi_cmnd * cmd ;
u8 * sense_buffer ;
unsigned int sense_bufflen ;
int scsi_status ;
int command_type ;
int task_tag ;
unsigned int lun ;
2013-07-30 00:35:57 +05:30
bool intr_cmd ;
2013-02-25 21:44:33 +05:30
} ;
2013-07-30 00:35:58 +05:30
/**
* struct ufs_query - holds relevent data structures for query request
* @ request : request upiu and function
* @ descriptor : buffer for sending / receiving descriptor
* @ response : response upiu and response
*/
struct ufs_query {
struct ufs_query_req request ;
u8 * descriptor ;
struct ufs_query_res response ;
} ;
2013-07-30 00:35:57 +05:30
/**
* struct ufs_dev_cmd - all assosiated fields with device management commands
* @ type : device management command type - Query , NOP OUT
* @ lock : lock to allow one command at a time
* @ complete : internal commands completion
* @ tag_wq : wait queue until free command slot is available
*/
struct ufs_dev_cmd {
enum dev_cmd_type type ;
struct mutex lock ;
struct completion * complete ;
wait_queue_head_t tag_wq ;
2013-07-30 00:35:58 +05:30
struct ufs_query query ;
2013-07-30 00:35:57 +05:30
} ;
2013-02-25 21:44:33 +05:30
2014-09-25 15:32:21 +03:00
# define PRE_CHANGE 0
# define POST_CHANGE 1
/**
* struct ufs_hba_variant_ops - variant specific callbacks
* @ name : variant name
* @ init : called when the driver is initialized
* @ exit : called to cleanup everything done in init
* @ setup_clocks : called before touching any of the controller registers
* @ setup_regulators : called before accessing the host controller
* @ hce_enable_notify : called before and after HCE enable bit is set to allow
* variant specific Uni - Pro initialization .
* @ link_startup_notify : called before and after Link startup is carried out
* to allow variant specific Uni - Pro initialization .
*/
struct ufs_hba_variant_ops {
const char * name ;
int ( * init ) ( struct ufs_hba * ) ;
void ( * exit ) ( struct ufs_hba * ) ;
int ( * setup_clocks ) ( struct ufs_hba * , bool ) ;
int ( * setup_regulators ) ( struct ufs_hba * , bool ) ;
int ( * hce_enable_notify ) ( struct ufs_hba * , bool ) ;
int ( * link_startup_notify ) ( struct ufs_hba * , bool ) ;
} ;
2013-02-25 21:44:33 +05:30
/**
* 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
2013-07-30 00:35:57 +05:30
* @ lrb_in_use : lrb in use
2013-02-25 21:44:33 +05:30
* @ 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
* @ ufs_version : UFS Version to which controller complies
2014-09-25 15:32:21 +03:00
* @ vops : pointer to variant specific operations
* @ priv : pointer to variant specific private data
2013-02-25 21:44:33 +05:30
* @ irq : Irq number of the controller
* @ active_uic_cmd : handle of active UIC command
2013-06-26 22:39:29 +05:30
* @ uic_cmd_mutex : mutex for uic command
2014-05-26 10:59:12 +05:30
* @ tm_wq : wait queue for task management
* @ tm_tag_wq : wait queue for free task management slots
* @ tm_slots_in_use : bit map of task management request slots in use
2013-08-31 21:40:22 +05:30
* @ pwr_done : completion for power mode change
2013-02-25 21:44:33 +05:30
* @ tm_condition : condition variable for task management
* @ ufshcd_state : UFSHCD states
2014-05-26 10:59:14 +05:30
* @ eh_flags : Error handling flags
2013-06-26 22:39:27 +05:30
* @ intr_mask : Interrupt Mask Bits
2013-07-30 00:35:59 +05:30
* @ ee_ctrl_mask : Exception event control mask
2014-05-26 10:59:15 +05:30
* @ eh_work : Worker to handle UFS errors that require s / w attention
2013-07-30 00:35:59 +05:30
* @ eeh_work : Worker to handle exception events
2013-02-25 21:44:33 +05:30
* @ errors : HBA errors
2014-05-26 10:59:15 +05:30
* @ uic_error : UFS interconnect layer error status
* @ saved_err : sticky error mask
* @ saved_uic_err : sticky UIC error mask
2013-07-30 00:35:57 +05:30
* @ dev_cmd : ufs device management command information
2013-07-30 00:35:59 +05:30
* @ auto_bkops_enabled : to track whether bkops is enabled in device
2013-02-25 21:44:33 +05:30
*/
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 ;
2013-07-30 00:35:57 +05:30
unsigned long lrb_in_use ;
2013-02-25 21:44:33 +05:30
unsigned long outstanding_tasks ;
unsigned long outstanding_reqs ;
u32 capabilities ;
int nutrs ;
int nutmrs ;
u32 ufs_version ;
2014-09-25 15:32:21 +03:00
struct ufs_hba_variant_ops * vops ;
void * priv ;
2013-02-25 21:44:33 +05:30
unsigned int irq ;
2013-06-26 22:39:29 +05:30
struct uic_command * active_uic_cmd ;
struct mutex uic_cmd_mutex ;
2014-05-26 10:59:12 +05:30
wait_queue_head_t tm_wq ;
wait_queue_head_t tm_tag_wq ;
2013-02-25 21:44:33 +05:30
unsigned long tm_condition ;
2014-05-26 10:59:12 +05:30
unsigned long tm_slots_in_use ;
2013-02-25 21:44:33 +05:30
2013-08-31 21:40:22 +05:30
struct completion * pwr_done ;
2013-02-25 21:44:33 +05:30
u32 ufshcd_state ;
2014-05-26 10:59:14 +05:30
u32 eh_flags ;
2013-06-26 22:39:27 +05:30
u32 intr_mask ;
2013-07-30 00:35:59 +05:30
u16 ee_ctrl_mask ;
2013-02-25 21:44:33 +05:30
/* Work Queues */
2014-05-26 10:59:15 +05:30
struct work_struct eh_work ;
2013-07-30 00:35:59 +05:30
struct work_struct eeh_work ;
2013-02-25 21:44:33 +05:30
/* HBA Errors */
u32 errors ;
2014-05-26 10:59:15 +05:30
u32 uic_error ;
u32 saved_err ;
u32 saved_uic_err ;
2013-07-30 00:35:57 +05:30
/* Device management request data */
struct ufs_dev_cmd dev_cmd ;
2013-07-30 00:35:59 +05:30
bool auto_bkops_enabled ;
2013-02-25 21:44:33 +05:30
} ;
2013-06-26 22:39:26 +05:30
# define ufshcd_writel(hba, val, reg) \
writel ( ( val ) , ( hba ) - > mmio_base + ( reg ) )
# define ufshcd_readl(hba, reg) \
readl ( ( hba ) - > mmio_base + ( reg ) )
2014-09-25 15:32:21 +03:00
int ufshcd_alloc_host ( struct device * , struct ufs_hba * * ) ;
int ufshcd_init ( struct ufs_hba * , void __iomem * , unsigned int ) ;
2013-02-25 21:44:33 +05:30
void ufshcd_remove ( struct ufs_hba * ) ;
/**
* ufshcd_hba_stop - Send controller to reset state
* @ hba : per adapter instance
*/
static inline void ufshcd_hba_stop ( struct ufs_hba * hba )
{
2013-06-26 22:39:26 +05:30
ufshcd_writel ( hba , CONTROLLER_DISABLE , REG_CONTROLLER_ENABLE ) ;
2013-02-25 21:44:33 +05:30
}
2013-07-30 00:35:58 +05:30
static inline void check_upiu_size ( void )
{
BUILD_BUG_ON ( ALIGNED_UPIU_SIZE <
GENERAL_UPIU_REQUEST_SIZE + QUERY_DESC_MAX_SIZE ) ;
}
2014-05-26 10:59:11 +05:30
extern int ufshcd_suspend ( struct ufs_hba * hba , pm_message_t state ) ;
extern int ufshcd_resume ( struct ufs_hba * hba ) ;
2013-07-30 00:35:59 +05:30
extern int ufshcd_runtime_suspend ( struct ufs_hba * hba ) ;
extern int ufshcd_runtime_resume ( struct ufs_hba * hba ) ;
extern int ufshcd_runtime_idle ( struct ufs_hba * hba ) ;
2013-08-31 21:40:21 +05:30
extern int ufshcd_dme_set_attr ( struct ufs_hba * hba , u32 attr_sel ,
u8 attr_set , u32 mib_val , u8 peer ) ;
extern int ufshcd_dme_get_attr ( struct ufs_hba * hba , u32 attr_sel ,
u32 * mib_val , u8 peer ) ;
/* UIC command interfaces for DME primitives */
# define DME_LOCAL 0
# define DME_PEER 1
# define ATTR_SET_NOR 0 /* NORMAL */
# define ATTR_SET_ST 1 /* STATIC */
static inline int ufshcd_dme_set ( struct ufs_hba * hba , u32 attr_sel ,
u32 mib_val )
{
return ufshcd_dme_set_attr ( hba , attr_sel , ATTR_SET_NOR ,
mib_val , DME_LOCAL ) ;
}
static inline int ufshcd_dme_st_set ( struct ufs_hba * hba , u32 attr_sel ,
u32 mib_val )
{
return ufshcd_dme_set_attr ( hba , attr_sel , ATTR_SET_ST ,
mib_val , DME_LOCAL ) ;
}
static inline int ufshcd_dme_peer_set ( struct ufs_hba * hba , u32 attr_sel ,
u32 mib_val )
{
return ufshcd_dme_set_attr ( hba , attr_sel , ATTR_SET_NOR ,
mib_val , DME_PEER ) ;
}
static inline int ufshcd_dme_peer_st_set ( struct ufs_hba * hba , u32 attr_sel ,
u32 mib_val )
{
return ufshcd_dme_set_attr ( hba , attr_sel , ATTR_SET_ST ,
mib_val , DME_PEER ) ;
}
static inline int ufshcd_dme_get ( struct ufs_hba * hba ,
u32 attr_sel , u32 * mib_val )
{
return ufshcd_dme_get_attr ( hba , attr_sel , mib_val , DME_LOCAL ) ;
}
static inline int ufshcd_dme_peer_get ( struct ufs_hba * hba ,
u32 attr_sel , u32 * mib_val )
{
return ufshcd_dme_get_attr ( hba , attr_sel , mib_val , DME_PEER ) ;
}
2013-02-25 21:44:33 +05:30
# endif /* End of Header */