diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 19:37:36 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 19:37:36 -0800 |
commit | 1289ace5b4f70f1e68ce785735b82c7e483de863 (patch) | |
tree | f616d22bb51c50f79daff2632b7960c46afb5168 /drivers/scsi/mvsas/mv_94xx.c | |
parent | d080827f850ba4df5b955d5ca8c8c0fc92fe18c0 (diff) | |
parent | abaee091a18c19ccd86feb1c8374585d82e96777 (diff) | |
download | blackbird-op-linux-1289ace5b4f70f1e68ce785735b82c7e483de863.tar.gz blackbird-op-linux-1289ace5b4f70f1e68ce785735b82c7e483de863.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley:
"This includes driver updates from the usual suspects (bfa, arcmsr,
scsi_dh_alua, lpfc, storvsc, cxlflash).
The major change is the addition of the hisi_sas driver, which is an
ARM platform device for SAS. The other change of note is an enormous
style transformation to the atp870u driver (which is our worst written
SCSI driver)"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (169 commits)
cxlflash: Enable device id for future IBM CXL adapter
cxlflash: Resolve oops in wait_port_offline
cxlflash: Fix to resolve cmd leak after host reset
cxlflash: Removed driver date print
cxlflash: Fix to avoid virtual LUN failover failure
cxlflash: Fix to escalate LINK_RESET also on port 1
storvsc: Tighten up the interrupt path
storvsc: Refactor the code in storvsc_channel_init()
storvsc: Properly support Fibre Channel devices
storvsc: Fix a bug in the layout of the hv_fc_wwn_packet
mvsas: Add SGPIO support to Marvell 94xx
mpt3sas: A correction in unmap_resources
hpsa: Add box and bay information for enclosure devices
hpsa: Change SAS transport devices to bus 0.
hpsa: fix path_info_show
cciss: print max outstanding commands as a hex value
scsi_debug: Increase the reported optimal transfer length
lpfc: Update version to 11.0.0.10 for upstream patch set
lpfc: Use kzalloc instead of kmalloc
lpfc: Delete unnecessary checks before the function call "mempool_destroy"
...
Diffstat (limited to 'drivers/scsi/mvsas/mv_94xx.c')
-rw-r--r-- | drivers/scsi/mvsas/mv_94xx.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 9270d15ff1a4..f6fc4a705924 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c @@ -330,6 +330,51 @@ static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id) mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff); } +static void mvs_94xx_sgpio_init(struct mvs_info *mvi) +{ + void __iomem *regs = mvi->regs_ex - 0x10200; + u32 tmp; + + tmp = mr32(MVS_HST_CHIP_CONFIG); + tmp |= 0x100; + mw32(MVS_HST_CHIP_CONFIG, tmp); + + mw32(MVS_SGPIO_CTRL + MVS_SGPIO_HOST_OFFSET * mvi->id, + MVS_SGPIO_CTRL_SDOUT_AUTO << MVS_SGPIO_CTRL_SDOUT_SHIFT); + + mw32(MVS_SGPIO_CFG1 + MVS_SGPIO_HOST_OFFSET * mvi->id, + 8 << MVS_SGPIO_CFG1_LOWA_SHIFT | + 8 << MVS_SGPIO_CFG1_HIA_SHIFT | + 4 << MVS_SGPIO_CFG1_LOWB_SHIFT | + 4 << MVS_SGPIO_CFG1_HIB_SHIFT | + 2 << MVS_SGPIO_CFG1_MAXACTON_SHIFT | + 1 << MVS_SGPIO_CFG1_FORCEACTOFF_SHIFT + ); + + mw32(MVS_SGPIO_CFG2 + MVS_SGPIO_HOST_OFFSET * mvi->id, + (300000 / 100) << MVS_SGPIO_CFG2_CLK_SHIFT | /* 100kHz clock */ + 66 << MVS_SGPIO_CFG2_BLINK_SHIFT /* (66 * 0,121 Hz?)*/ + ); + + mw32(MVS_SGPIO_CFG0 + MVS_SGPIO_HOST_OFFSET * mvi->id, + MVS_SGPIO_CFG0_ENABLE | + MVS_SGPIO_CFG0_BLINKA | + MVS_SGPIO_CFG0_BLINKB | + /* 3*4 data bits / PDU */ + (12 - 1) << MVS_SGPIO_CFG0_AUT_BITLEN_SHIFT + ); + + mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id, + DEFAULT_SGPIO_BITS); + + mw32(MVS_SGPIO_DSRC + MVS_SGPIO_HOST_OFFSET * mvi->id, + ((mvi->id * 4) + 3) << (8 * 3) | + ((mvi->id * 4) + 2) << (8 * 2) | + ((mvi->id * 4) + 1) << (8 * 1) | + ((mvi->id * 4) + 0) << (8 * 0)); + +} + static int mvs_94xx_init(struct mvs_info *mvi) { void __iomem *regs = mvi->regs; @@ -533,6 +578,8 @@ static int mvs_94xx_init(struct mvs_info *mvi) /* Enable SRS interrupt */ mw32(MVS_INT_MASK_SRS_0, 0xFFFF); + mvs_94xx_sgpio_init(mvi); + return 0; } @@ -1005,6 +1052,92 @@ static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time) } +static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv, + u8 reg_type, u8 reg_index, + u8 reg_count, u8 *write_data) +{ + int i; + + switch (reg_type) { + + case SAS_GPIO_REG_TX_GP: + if (reg_index == 0) + return -EINVAL; + + if (reg_count > 1) + return -EINVAL; + + if (reg_count == 0) + return 0; + + /* maximum supported bits = hosts * 4 drives * 3 bits */ + for (i = 0; i < mvs_prv->n_host * 4 * 3; i++) { + + /* select host */ + struct mvs_info *mvi = mvs_prv->mvi[i/(4*3)]; + + void __iomem *regs = mvi->regs_ex - 0x10200; + + int drive = (i/3) & (4-1); /* drive number on host */ + u32 block = mr32(MVS_SGPIO_DCTRL + + MVS_SGPIO_HOST_OFFSET * mvi->id); + + + /* + * if bit is set then create a mask with the first + * bit of the drive set in the mask ... + */ + u32 bit = (write_data[i/8] & (1 << (i&(8-1)))) ? + 1<<(24-drive*8) : 0; + + /* + * ... and then shift it to the right position based + * on the led type (activity/id/fail) + */ + switch (i%3) { + case 0: /* activity */ + block &= ~((0x7 << MVS_SGPIO_DCTRL_ACT_SHIFT) + << (24-drive*8)); + /* hardwire activity bit to SOF */ + block |= LED_BLINKA_SOF << ( + MVS_SGPIO_DCTRL_ACT_SHIFT + + (24-drive*8)); + break; + case 1: /* id */ + block &= ~((0x3 << MVS_SGPIO_DCTRL_LOC_SHIFT) + << (24-drive*8)); + block |= bit << MVS_SGPIO_DCTRL_LOC_SHIFT; + break; + case 2: /* fail */ + block &= ~((0x7 << MVS_SGPIO_DCTRL_ERR_SHIFT) + << (24-drive*8)); + block |= bit << MVS_SGPIO_DCTRL_ERR_SHIFT; + break; + } + + mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id, + block); + + } + + return reg_count; + + case SAS_GPIO_REG_TX: + if (reg_index + reg_count > mvs_prv->n_host) + return -EINVAL; + + for (i = 0; i < reg_count; i++) { + struct mvs_info *mvi = mvs_prv->mvi[i+reg_index]; + void __iomem *regs = mvi->regs_ex - 0x10200; + + mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id, + be32_to_cpu(((u32 *) write_data)[i])); + } + return reg_count; + } + return -ENOSYS; +} + const struct mvs_dispatch mvs_94xx_dispatch = { "mv94xx", mvs_94xx_init, @@ -1057,5 +1190,6 @@ const struct mvs_dispatch mvs_94xx_dispatch = { mvs_94xx_fix_dma, mvs_94xx_tune_interrupt, mvs_94xx_non_spec_ncq_error, + mvs_94xx_gpio_write, }; |