Commit bd756dde authored by Shun Fu's avatar Shun Fu Committed by James Bottomley
Browse files

[SCSI] mvumi: Add support for Marvell SAS/SATA RAID-on-Chip(ROC) 88RC9580



[jejb: fix up for spelling correction patch]
Signed-off-by: default avatarShun Fu <fushun@marvell.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 08bc166d
Loading
Loading
Loading
Loading
+916 −177

File changed.

Preview size limit exceeded, changes collapsed.

+152 −83
Original line number Diff line number Diff line
@@ -34,8 +34,12 @@
#define MV_DRIVER_NAME			"mvumi"
#define PCI_VENDOR_ID_MARVELL_2		0x1b4b
#define PCI_DEVICE_ID_MARVELL_MV9143	0x9143
#define PCI_DEVICE_ID_MARVELL_MV9580	0x9580

#define MVUMI_INTERNAL_CMD_WAIT_TIME	45
#define MVUMI_INQUIRY_LENGTH		44
#define MVUMI_INQUIRY_UUID_OFF		36
#define MVUMI_INQUIRY_UUID_LEN		8

#define IS_DMA64			(sizeof(dma_addr_t) == 8)

@@ -44,41 +48,73 @@ enum mvumi_qc_result {
	MV_QUEUE_COMMAND_RESULT_NO_RESOURCE,
};

enum {
	/*******************************************/

	/* ARM Mbus Registers Map	*/

	/*******************************************/
	CPU_MAIN_INT_CAUSE_REG	= 0x20200,
	CPU_MAIN_IRQ_MASK_REG	= 0x20204,
	CPU_MAIN_FIQ_MASK_REG	= 0x20208,
	CPU_ENPOINTA_MASK_REG	= 0x2020C,
	CPU_ENPOINTB_MASK_REG	= 0x20210,

	INT_MAP_COMAERR		= 1 << 6,
	INT_MAP_COMAIN		= 1 << 7,
	INT_MAP_COMAOUT		= 1 << 8,
	INT_MAP_COMBERR		= 1 << 9,
	INT_MAP_COMBIN		= 1 << 10,
	INT_MAP_COMBOUT		= 1 << 11,

	INT_MAP_COMAINT	= (INT_MAP_COMAOUT | INT_MAP_COMAERR),
	INT_MAP_COMBINT	= (INT_MAP_COMBOUT | INT_MAP_COMBIN | INT_MAP_COMBERR),

	INT_MAP_DL_PCIEA2CPU	= 1 << 0,
	INT_MAP_DL_CPU2PCIEA	= 1 << 1,

	/***************************************/
struct mvumi_hw_regs {
	/* For CPU */
	void *main_int_cause_reg;
	void *enpointa_mask_reg;
	void *enpointb_mask_reg;
	void *rstoutn_en_reg;
	void *ctrl_sts_reg;
	void *rstoutn_mask_reg;
	void *sys_soft_rst_reg;

	/* For Doorbell */
	void *pciea_to_arm_drbl_reg;
	void *arm_to_pciea_drbl_reg;
	void *arm_to_pciea_mask_reg;
	void *pciea_to_arm_msg0;
	void *pciea_to_arm_msg1;
	void *arm_to_pciea_msg0;
	void *arm_to_pciea_msg1;

	/* reset register */
	void *reset_request;
	void *reset_enable;

	/* For Message Unit */
	void *inb_list_basel;
	void *inb_list_baseh;
	void *inb_aval_count_basel;
	void *inb_aval_count_baseh;
	void *inb_write_pointer;
	void *inb_read_pointer;
	void *outb_list_basel;
	void *outb_list_baseh;
	void *outb_copy_basel;
	void *outb_copy_baseh;
	void *outb_copy_pointer;
	void *outb_read_pointer;
	void *inb_isr_cause;
	void *outb_isr_cause;
	void *outb_coal_cfg;
	void *outb_coal_timeout;

	/* Bit setting for HW */
	u32 int_comaout;
	u32 int_comaerr;
	u32 int_dl_cpu2pciea;
	u32 int_mu;
	u32 int_drbl_int_mask;
	u32 int_main_int_mask;
	u32 cl_pointer_toggle;
	u32 cl_slot_num_mask;
	u32 clic_irq;
	u32 clic_in_err;
	u32 clic_out_err;
};

	/* ARM Doorbell Registers Map		*/
struct mvumi_dyn_list_entry {
	u32 src_low_addr;
	u32 src_high_addr;
	u32 if_length;
	u32 reserve;
};

	/***************************************/
	CPU_PCIEA_TO_ARM_DRBL_REG	= 0x20400,
	CPU_PCIEA_TO_ARM_MASK_REG	= 0x20404,
	CPU_ARM_TO_PCIEA_DRBL_REG	= 0x20408,
	CPU_ARM_TO_PCIEA_MASK_REG	= 0x2040C,
#define SCSI_CMD_MARVELL_SPECIFIC	0xE1
#define CDB_CORE_MODULE			0x1
#define CDB_CORE_SHUTDOWN		0xB

enum {
	DRBL_HANDSHAKE			= 1 << 0,
	DRBL_SOFT_RESET			= 1 << 1,
	DRBL_BUS_CHANGE			= 1 << 2,
@@ -86,46 +122,6 @@ enum {
	DRBL_MU_RESET			= 1 << 4,
	DRBL_HANDSHAKE_ISR		= DRBL_HANDSHAKE,

	CPU_PCIEA_TO_ARM_MSG0		= 0x20430,
	CPU_PCIEA_TO_ARM_MSG1		= 0x20434,
	CPU_ARM_TO_PCIEA_MSG0		= 0x20438,
	CPU_ARM_TO_PCIEA_MSG1		= 0x2043C,

	/*******************************************/

	/* ARM Communication List Registers Map    */

	/*******************************************/
	CLA_INB_LIST_BASEL		= 0x500,
	CLA_INB_LIST_BASEH		= 0x504,
	CLA_INB_AVAL_COUNT_BASEL	= 0x508,
	CLA_INB_AVAL_COUNT_BASEH	= 0x50C,
	CLA_INB_DESTI_LIST_BASEL	= 0x510,
	CLA_INB_DESTI_LIST_BASEH	= 0x514,
	CLA_INB_WRITE_POINTER		= 0x518,
	CLA_INB_READ_POINTER		= 0x51C,

	CLA_OUTB_LIST_BASEL		= 0x530,
	CLA_OUTB_LIST_BASEH		= 0x534,
	CLA_OUTB_SOURCE_LIST_BASEL	= 0x538,
	CLA_OUTB_SOURCE_LIST_BASEH	= 0x53C,
	CLA_OUTB_COPY_POINTER		= 0x544,
	CLA_OUTB_READ_POINTER		= 0x548,

	CLA_ISR_CAUSE			= 0x560,
	CLA_ISR_MASK			= 0x564,

	INT_MAP_MU		= (INT_MAP_DL_CPU2PCIEA | INT_MAP_COMAINT),

	CL_POINTER_TOGGLE		= 1 << 12,

	CLIC_IN_IRQ			= 1 << 0,
	CLIC_OUT_IRQ			= 1 << 1,
	CLIC_IN_ERR_IRQ			= 1 << 8,
	CLIC_OUT_ERR_IRQ		= 1 << 12,

	CL_SLOT_NUM_MASK		= 0xFFF,

	/*
	* Command flag is the flag for the CDB command itself
	*/
@@ -137,15 +133,23 @@ enum {
	CMD_FLAG_DATA_IN		= 1 << 3,
	/* 1-host write data */
	CMD_FLAG_DATA_OUT		= 1 << 4,

	SCSI_CMD_MARVELL_SPECIFIC	= 0xE1,
	CDB_CORE_SHUTDOWN		= 0xB,
	CMD_FLAG_PRDT_IN_HOST		= 1 << 5,
};

#define APICDB0_EVENT			0xF4
#define APICDB1_EVENT_GETEVENT		0
#define APICDB1_HOST_GETEVENT		1
#define MAX_EVENTS_RETURNED		6

#define DEVICE_OFFLINE	0
#define DEVICE_ONLINE	1

struct mvumi_hotplug_event {
	u16 size;
	u8 dummy[2];
	u8 bitmap[0];
};

struct mvumi_driver_event {
	u32	time_stamp;
	u32	sequence_no;
@@ -172,8 +176,14 @@ struct mvumi_events_wq {
	void *param;
};

#define HS_CAPABILITY_SUPPORT_COMPACT_SG	(1U << 4)
#define HS_CAPABILITY_SUPPORT_PRD_HOST		(1U << 5)
#define HS_CAPABILITY_SUPPORT_DYN_SRC		(1U << 6)
#define HS_CAPABILITY_NEW_PAGE_IO_DEPTH_DEF	(1U << 14)

#define MVUMI_MAX_SG_ENTRY	32
#define SGD_EOT			(1L << 27)
#define SGD_EOT_CP		(1L << 22)

struct mvumi_sgl {
	u32	baseaddr_l;
@@ -181,6 +191,39 @@ struct mvumi_sgl {
	u32	flags;
	u32	size;
};
struct mvumi_compact_sgl {
	u32	baseaddr_l;
	u32	baseaddr_h;
	u32	flags;
};

#define GET_COMPACT_SGD_SIZE(sgd)	\
	((((struct mvumi_compact_sgl *)(sgd))->flags) & 0x3FFFFFL)

#define SET_COMPACT_SGD_SIZE(sgd, sz) do {			\
	(((struct mvumi_compact_sgl *)(sgd))->flags) &= ~0x3FFFFFL;	\
	(((struct mvumi_compact_sgl *)(sgd))->flags) |= (sz);		\
} while (0)
#define sgd_getsz(_mhba, sgd, sz) do {				\
	if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG)	\
		(sz) = GET_COMPACT_SGD_SIZE(sgd);	\
	else \
		(sz) = (sgd)->size;			\
} while (0)

#define sgd_setsz(_mhba, sgd, sz) do {				\
	if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG)	\
		SET_COMPACT_SGD_SIZE(sgd, sz);		\
	else \
		(sgd)->size = (sz);			\
} while (0)

#define sgd_inc(_mhba, sgd) do {	\
	if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG)	\
		sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 12); \
	else \
		sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 16); \
} while (0)

struct mvumi_res {
	struct list_head entry;
@@ -197,7 +240,7 @@ enum resource_type {
};

struct mvumi_sense_data {
	u8 error_eode:7;
	u8 error_code:7;
	u8 valid:1;
	u8 segment_number;
	u8 sense_key:4;
@@ -220,6 +263,7 @@ struct mvumi_sense_data {
struct mvumi_cmd {
	struct list_head queue_pointer;
	struct mvumi_msg_frame *frame;
	dma_addr_t frame_phys;
	struct scsi_cmnd *scmd;
	atomic_t sync_cmd;
	void *data_buf;
@@ -393,7 +437,8 @@ struct mvumi_hs_page2 {
	u16 frame_length;

	u8 host_type;
	u8 reserved[3];
	u8 host_cap;
	u8 reserved[2];
	struct version_info host_ver;
	u32 system_io_bus;
	u32 slot_number;
@@ -435,8 +480,17 @@ struct mvumi_tag {
	unsigned short size;
};

struct mvumi_device {
	struct list_head list;
	struct scsi_device *sdev;
	u64	wwid;
	u8	dev_type;
	int	id;
};

struct mvumi_hba {
	void *base_addr[MAX_BASE_ADDRESS];
	u32 pci_base[MAX_BASE_ADDRESS];
	void *mmio;
	struct list_head cmd_pool;
	struct Scsi_Host *shost;
@@ -449,6 +503,9 @@ struct mvumi_hba {
	void *ib_list;
	dma_addr_t ib_list_phys;

	void *ib_frame;
	dma_addr_t ib_frame_phys;

	void *ob_list;
	dma_addr_t ob_list_phys;

@@ -477,12 +534,14 @@ struct mvumi_hba {
	unsigned char hba_total_pages;
	unsigned char fw_flag;
	unsigned char request_id_enabled;
	unsigned char eot_flag;
	unsigned short hba_capability;
	unsigned short io_seq;

	unsigned int ib_cur_slot;
	unsigned int ob_cur_slot;
	unsigned int fw_state;
	struct mutex sas_discovery_mutex;

	struct list_head ob_data_list;
	struct list_head free_ob_list;
@@ -491,14 +550,24 @@ struct mvumi_hba {

	struct mvumi_tag tag_pool;
	struct mvumi_cmd **tag_cmd;
	struct mvumi_hw_regs *regs;
	struct mutex device_lock;
	struct list_head mhba_dev_list;
	struct list_head shost_dev_list;
	struct task_struct *dm_thread;
	atomic_t pnp_count;
};

struct mvumi_instance_template {
	void (*fire_cmd) (struct mvumi_hba *, struct mvumi_cmd *);
	void (*enable_intr)(void *) ;
	void (*disable_intr)(void *);
	void (*enable_intr) (struct mvumi_hba *);
	void (*disable_intr) (struct mvumi_hba *);
	int (*clear_intr) (void *);
	unsigned int (*read_fw_status_reg)(void *);
	unsigned int (*read_fw_status_reg) (struct mvumi_hba *);
	unsigned int (*check_ib_list) (struct mvumi_hba *);
	int (*check_ob_list) (struct mvumi_hba *, unsigned int *,
			      unsigned int *);
	int (*reset_host) (struct mvumi_hba *);
};

extern struct timezone sys_tz;