Support Marvell Hercules-I/II SATA Controllers.

This commit is contained in:
kiyohara 2009-07-27 12:34:12 +00:00
parent fdc1dac9e9
commit ce1343fcd9
13 changed files with 4788 additions and 12 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1148 2009/07/25 16:22:59 mbalmer Exp $
# $NetBSD: mi,v 1.1149 2009/07/27 12:34:12 kiyohara Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -1216,6 +1216,7 @@
./usr/share/man/cat4/mvme68k/pcctwo.0 man-sys-catman .cat
./usr/share/man/cat4/mvme68k/wdsc.0 man-sys-catman .cat
./usr/share/man/cat4/mvme68k/zsc.0 man-sys-catman .cat
./usr/share/man/cat4/mvsata.0 man-sys-catman .cat
./usr/share/man/cat4/nadb.0 man-sys-catman .cat
./usr/share/man/cat4/nca.0 man-sys-catman .cat
./usr/share/man/cat4/ncr.0 man-obsolete obsolete
@ -3782,6 +3783,7 @@
./usr/share/man/html4/mvme68k/pcctwo.html man-sys-htmlman html
./usr/share/man/html4/mvme68k/wdsc.html man-sys-htmlman html
./usr/share/man/html4/mvme68k/zsc.html man-sys-htmlman html
./usr/share/man/html4/mvsata.html man-sys-htmlman html
./usr/share/man/html4/nadb.html man-sys-htmlman html
./usr/share/man/html4/nca.html man-sys-htmlman html
./usr/share/man/html4/ne.html man-sys-htmlman html
@ -6206,6 +6208,7 @@
./usr/share/man/man4/mvme68k/pcctwo.4 man-sys-man .man
./usr/share/man/man4/mvme68k/wdsc.4 man-sys-man .man
./usr/share/man/man4/mvme68k/zsc.4 man-sys-man .man
./usr/share/man/man4/mvsata.4 man-sys-man .man
./usr/share/man/man4/nadb.4 man-sys-man .man
./usr/share/man/man4/nca.4 man-sys-man .man
./usr/share/man/man4/ncr.4 man-obsolete obsolete

View File

@ -1,4 +1,4 @@
# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1260 $>
# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1261 $>
#
#
# [Note: This file does not mention every change made to the NetBSD source tree.
@ -340,3 +340,5 @@ Changes from NetBSD 5.0 to NetBSD 6.0:
[mbalmer 20090725]
secmodel_44bsd(9), secmodel_securelevel(9): Add provisions to control
acces to gpio(4) pins. [mbalmer 20090725]
mvsata(4): Support Marvell Hercules-I/II SATA Controllers
[kiyohara 20090615]

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.492 2009/06/05 07:21:14 hubertf Exp $
# $NetBSD: Makefile,v 1.493 2009/07/27 12:34:13 kiyohara Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \
@ -36,7 +36,7 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \
lc.4 ld.4 lii.4 lo.4 lxtphy.4 \
mainbus.4 makphy.4 mbe.4 mca.4 mcclock.4 md.4 mfb.4 mfi.4 mhzc.4 \
midi.4 mii.4 mk48txx.4 mlx.4 mly.4 mpt.4 mpu.4 mtd.4 mtio.4 \
multicast.4 \
multicast.4 mvsata.4 \
nadb.4 ne.4 neo.4 netintro.4 nfe.4 nfsmb.4 njata.4 njs.4 \
nsclpcsio.4 nsp.4 nsphy.4 nsphyter.4 ntwoc.4 null.4 nsmb.4 \
oak.4 oosiop.4 opl.4 options.4 optiide.4 osiop.4 \

87
share/man/man4/mvsata.4 Normal file
View File

@ -0,0 +1,87 @@
.\" $NetBSD: mvsata.4,v 1.1 2009/07/27 12:34:13 kiyohara Exp $
.\"
.\" Copyright (c) 2009 KIYOHARA Takashi
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd July 19, 2009
.Dt MVSATA 4
.Os
.Sh NAME
.Nm mvsata
.Nd Marvell Hercules-I and Hercules-II SATA controllers driver
.Sh SYNOPSIS
.Cd "mvsata* at pci? dev ? function ?"
.Sh DESCRIPTION
The
.Nm
driver supports the Marvell Hercules-I and Hercules-II family of SATA
controllers,
interfacing the hardware with the
.Xr ata 4
and
.Xr atapi 4
subsystems.
.Pp
The following controllers are supported by the
.Nm
driver:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It Marvell 88SX50xx Hercules-I
.It Marvell 88SX60xx Hercules-II
.It Adaptec RAID 1420SA
.It Marvell 88SX70xx Hercules-II
.It Adaptec RAID 1430SA
.It Triones Technologies RocketRAID 2310 RAID card
.El
.Pp
The 88SX60xx and later supports Native Command Queue. Also the 88SX70xx
supports ATAPI.
.Pp
.Sh SEE ALSO
.Xr ata 4 ,
.Xr atapi 4 ,
.Xr pci 4 ,
.Xr wd 4
.Sh HISTORY
The
.Nm
driver first appeared in
.Nx 6.0 .
.Sh AUTHORS
The
.Nm
driver was written by
.An KIYOHARA Takashi Aq kiyohara@kk.iij4u.or.jp .
.Sh BUGS
.Bl -tag -width Ds -compact
.It SATA Native Command Queuing is not yet supported .
.It Device hot swapping is not yet supported .
.It ATAPI is not yet tested .
.It Marvell's Software RAID is not yet supported by the
.Xr ataraid 4
driver.
.Xr raid 4
can be used instead.
.El

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.245 2009/07/19 06:28:08 kiyohara Exp $
# $NetBSD: GENERIC,v 1.246 2009/07/27 12:34:13 kiyohara Exp $
#
# GENERIC machine description file
#
@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "GENERIC-$Revision: 1.245 $"
#ident "GENERIC-$Revision: 1.246 $"
maxusers 64 # estimated number of users
@ -541,6 +541,7 @@ iteide* at pci? dev ? function ? # IT Express IDE controllers
ixpide* at pci? dev ? function ? # ATI IXP IDE controllers
jmide* at pci? dev ? function ? # JMicron PCI-e PATA/SATA controllers
ahcisata* at jmide?
mvsata* at pci? dev ? function ? # Marvell Hercules-I/II
optiide* at pci? dev ? function ? # Opti IDE controllers
piixide* at pci? dev ? function ? # Intel IDE controllers
pdcide* at pci? dev ? function ? # Promise IDE controllers

View File

@ -1,4 +1,4 @@
# $NetBSD: ALL,v 1.201 2009/07/25 19:04:41 cegger Exp $
# $NetBSD: ALL,v 1.202 2009/07/27 12:34:13 kiyohara Exp $
# From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
#
# ALL machine description file
@ -17,7 +17,7 @@ include "arch/i386/conf/std.i386"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "ALL-$Revision: 1.201 $"
#ident "ALL-$Revision: 1.202 $"
maxusers 32 # estimated number of users
@ -811,6 +811,7 @@ iteide* at pci? dev ? function ? # IT Express IDE controllers
ixpide* at pci? dev ? function ? # ATI IXP IDE controllers
jmide* at pci? dev ? function ? # JMicron PCI-e PATA/SATA controllers
ahcisata* at jmide?
mvsata* at pci? dev ? function ? # Marvell Hercules-I/II
optiide* at pci? dev ? function ? # Opti IDE controllers
piixide* at pci? dev ? function ? # Intel IDE controllers
pdcide* at pci? dev ? function ? # Promise IDE controllers

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.937 2009/07/19 06:28:08 kiyohara Exp $
# $NetBSD: GENERIC,v 1.938 2009/07/27 12:34:13 kiyohara Exp $
#
# GENERIC machine description file
#
@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "GENERIC-$Revision: 1.937 $"
#ident "GENERIC-$Revision: 1.938 $"
maxusers 64 # estimated number of users
@ -798,6 +798,7 @@ iteide* at pci? dev ? function ? # IT Express IDE controllers
ixpide* at pci? dev ? function ? # ATI IXP IDE controllers
jmide* at pci? dev ? function ? # JMicron PCI-e PATA/SATA controllers
ahcisata* at jmide?
mvsata* at pci? dev ? function ? # Marvell Hercules-I/II
optiide* at pci? dev ? function ? # Opti IDE controllers
piixide* at pci? dev ? function ? # Intel IDE controllers
pdcide* at pci? dev ? function ? # Promise IDE controllers

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.950 2009/07/18 16:31:42 reinoud Exp $
# $NetBSD: files,v 1.951 2009/07/27 12:34:13 kiyohara Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20090313
@ -940,6 +940,12 @@ define ahcisata_core
file dev/ic/ahcisata_core.c ahcisata_core
device ahcisata: ata, ata_dma, ata_udma, sata, sata_fis, ahcisata_core
# Mervell Serial-ATA Host Controller
define mvsata
file dev/ic/mvsata.c mvsata
device mvsata: ata, ata_dma, ata_udma, wdc_common, sata, mvsata
defflag opt_mvsata.h MVSATA_WITHOUTDMA
# DECchip 21x4x Ethernet controller family, and assorted clones.
#
device tlp: arp, ether, ifnet, mii, mii_bitbang

View File

@ -1,4 +1,4 @@
# $NetBSD: DEVNAMES,v 1.245 2009/02/19 00:55:48 jmcneill Exp $
# $NetBSD: DEVNAMES,v 1.246 2009/07/27 12:34:13 kiyohara Exp $
#
# This file contains all used device names and defined attributes in
# alphabetical order. New devices added to the system somewhere should first
@ -882,6 +882,7 @@ mtd MI
mtty MI
mu vax
mulaw MI Attribute
mvsata MI
nca MI
ncr5380sbc MI Attribute
ncr53c9x MI Attribute

3699
sys/dev/ic/mvsata.c Normal file

File diff suppressed because it is too large Load Diff

326
sys/dev/ic/mvsatareg.h Normal file
View File

@ -0,0 +1,326 @@
/* $NetBSD: mvsatareg.h,v 1.1 2009/07/27 12:34:14 kiyohara Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MVSATAREG_H_
#define _MVSATAREG_H_
/*
* SATAHC Arbiter Registers
*/
#define SATAHC_REGISTER_SIZE 0x10000
#define SATAHC(hc) ((hc) * SATAHC_REGISTER_SIZE)
#define SATAHC_C 0x000 /* Configuration */
#define SATAHC_C_TIMEOUT_MASK (0xff << 0)
#define SATAHC_C_TIMEOUTEN (1 << 16) /* Timer Enable */
#define SATAHC_C_COALDIS(p) (1 << ((p) + 24))/* Coalescing Disable*/
#define SATAHC_RQOP 0x004 /* Request Queue Out-Pointer */
#define SATAHC_RQIP 0x008 /* Response Queue In-Pointer */
#define SATAHC_RQP_ERPQP(p, x) (((x) >> ((p) * 8)) & 0x7f)
#define SATAHC_ICT 0x00c /* Interrupt Coalescing Threshold */
#define SATAHC_ICT_SAICOALT_MASK 0x000000ff
#define SATAHC_ITT 0x010 /* Interrupt Time Threshold */
#define SATAHC_ITT_SAITMTH 0x00ffffff
#define SATAHC_IC 0x014 /* Interrupt Cause */
#define SATAHC_IC_DONE(p) (1 << (p)) /* SaCrpb/DMA Done */
#define SATAHC_IC_SAINTCOAL (1 << 4) /* Intr Coalescing */
#define SATAHC_IC_SADEVINTERRUPT(p) (1 << ((p) + 8))/* Device Intr */
/*
* Physical Registers for Generation I
*/
#define SATAHC_I_R02(p) ((p) * 0x100 + 0x108)
#define SATAHC_I_PHYCONTROL(p) ((p) * 0x100 + 0x10c)
#define SATAHC_I_LTMODE(p) ((p) * 0x100 + 0x130)
#define SATAHC_I_PHYMODE(p) ((p) * 0x100 + 0x174)
/*
* EDMA Registers
*/
#define EDMA_REGISTERS_OFFSET 0x2000
#define EDMA_REGISTERS_SIZE 0x2000
#define EDMA_CFG 0x000 /* Configuration */
#define EDMA_CFG_RESERVED (0x1f << 0) /* Queue len ? */
#define EDMA_CFG_ESATANATVCMDQUE (1 << 5)
#define EDMA_CFG_ERDBSZ (1 << 8)
#define EDMA_CFG_EQUE (1 << 9)
#define EDMA_CFG_ERDBSZEXT (1 << 11)
#define EDMA_CFG_RESERVED2 (1 << 12)
#define EDMA_CFG_EWRBUFFERLEN (1 << 13)
#define EDMA_CFG_EDEVERR (1 << 14)
#define EDMA_CFG_EEDMAFBS (1 << 16)
#define EDMA_CFG_ECUTTHROUGHEN (1 << 17)
#define EDMA_CFG_EEARLYCOMPLETIONEN (1 << 18)
#define EDMA_CFG_EEDMAQUELEN (1 << 19)
#define EDMA_CFG_EHOSTQUEUECACHEEN (1 << 22)
#define EDMA_CFG_EMASKRXPM (1 << 23)
#define EDMA_CFG_RESUMEDIS (1 << 24)
#define EDMA_CFG_EDMAFBS (1 << 26)
#define EDMA_T 0x004 /* Timer */
#define EDMA_IEC 0x008 /* Interrupt Error Cause */
#define EDMA_IEM 0x00c /* Interrupt Error Mask */
#define EDMA_IE_EDEVERR (1 << 2) /* EDMA Device Error */
#define EDMA_IE_EDEVDIS (1 << 3) /* EDMA Dev Disconn */
#define EDMA_IE_EDEVCON (1 << 4) /* EDMA Dev Conn */
#define EDMA_IE_SERRINT (1 << 5)
#define EDMA_IE_ESELFDIS (1 << 7) /* EDMA Self Disable */
#define EDMA_IE_ETRANSINT (1 << 8) /* Transport Layer */
#define EDMA_IE_EIORDYERR (1 << 12) /* EDMA IORdy Error */
# define EDMA_IE_LINKXERR_SATACRC (1 << 0) /* SATA CRC error */
# define EDMA_IE_LINKXERR_INTERNALFIFO (1 << 1) /* internal FIFO err */
# define EDMA_IE_LINKXERR_LINKLAYERRESET (1 << 2)
/* Link Layer is reset by the reception of SYNC primitive from device */
# define EDMA_IE_LINKXERR_OTHERERRORS (1 << 3)
/*
* Link state errors, coding errors, or running disparity errors occur
* during FIS reception.
*/
# define EDMA_IE_LINKTXERR_FISTXABORTED (1 << 4) /* FIS Tx is aborted */
#define EDMA_IE_LINKCTLRXERR(x) ((x) << 13) /* Link Ctrl Recv Err */
#define EDMA_IE_LINKDATARXERR(x) ((x) << 17) /* Link Data Recv Err */
#define EDMA_IE_LINKCTLTXERR(x) ((x) << 21) /* Link Ctrl Tx Error */
#define EDMA_IE_LINKDATATXERR(x) ((x) << 26) /* Link Data Tx Error */
#define EDMA_IE_TRANSPROTERR (1 << 31) /* Transport Proto E */
#define EDMA_REQQBAH 0x010 /* Request Queue Base Address High */
#define EDMA_REQQIP 0x014 /* Request Queue In-Pointer */
#define EDMA_REQQOP 0x018 /* Request Queue Out-Pointer */
#define EDMA_REQQP_ERQQP_SHIFT 5
#define EDMA_REQQP_ERQQP_MASK 0x000003e0
#define EDMA_REQQP_ERQQBAP_MASK 0x00000c00
#define EDMA_REQQP_ERQQBA_MASK 0xfffff000
#define EDMA_RESQBAH 0x01c /* Response Queue Base Address High */
#define EDMA_RESQIP 0x020 /* Response Queue In-Pointer */
#define EDMA_RESQOP 0x024 /* Response Queue Out-Pointer */
#define EDMA_RESQP_ERPQP_SHIFT 3
#define EDMA_RESQP_ERPQP_MASK 0x000000f8
#define EDMA_RESQP_ERPQBAP_MASK 0x00000300
#define EDMA_RESQP_ERPQBA_MASK 0xfffffc00
#define EDMA_CMD 0x028 /* Command */
#define EDMA_CMD_EENEDMA (1 << 0) /* Enable EDMA */
#define EDMA_CMD_EDSEDMA (1 << 1) /* Disable EDMA */
#define EDMA_CMD_EATARST (1 << 2) /* ATA Device Reset */
#define EDMA_CMD_EEDMAFRZ (1 << 4) /* EDMA Freeze */
#define EDMA_TC 0x02c /* Test Control */
#define EDMA_S 0x030 /* Status */
#define EDMA_S_EDEVQUETAG(s) ((s) & 0x0000001f)
#define EDMA_S_EDEVDIR_WRITE (0 << 5)
#define EDMA_S_EDEVDIR_READ (1 << 5)
#define EDMA_S_ECACHEEMPTY (1 << 6)
#define EDMA_S_EDMAIDLE (1 << 7)
#define EDMA_S_ESTATE(s) (((s) & 0x0000ff00) >> 8)
#define EDMA_S_EIOID(s) (((s) & 0x003f0000) >> 16)
#define EDMA_IORT 0x034 /* IORdy Timeout */
#define EDMA_CDT 0x040 /* Command Delay Threshold */
#define EDMA_HC 0x060 /* Halt Condition */
#define EDMA_CQDCQOS(x) (0x090 + ((x) << 2)
/* NCQ Done/TCQ Outstanding Status */
/*
* Shadow Register Block Registers
*/
#define SHADOW_REG_BLOCK_OFFSET 0x100
#define SHADOW_REG_BLOCK_SIZE 0x100
#define SRB_PIOD 0x000 /* PIO Data */
#define SRB_FE 0x004 /* Feature/Error */
#define SRB_SC 0x008 /* Sector Count */
#define SRB_LBAL 0x00c /* LBA Low */
#define SRB_LBAM 0x010 /* LBA Mid */
#define SRB_LBAH 0x014 /* LBA High */
#define SRB_H 0x018 /* Head */
#define SRB_CS 0x01c /* Command/Status */
#define SRB_CAS 0x020 /* Control/Alternate Status */
/*
* Basic DMA Registers
* Does support for this registers only 88Sx6xxx?
*/
#define DMA_C 0x224 /* Basic DMA Command */
#define DMA_C_START (1 << 0)
#define DMA_C_READ (1 << 3)
#define DMA_C_DREGIONVALID (1 << 8)
#define DMA_C_DREGIONLAST (1 << 9)
#define DMA_C_CONTFROMPREV (1 << 10)
#define DMA_C_DRBC(n) (((n) & 0xffff) << 16)
#define DMA_S 0x228 /* Basic DMA Status */
#define DMA_DTLBA 0x22c /* Descriptor Table Low Base Address */
#define DMA_DTLBA_MASK 0xfffffff0
#define DMA_DTHBA 0x230 /* Descriptor Table High Base Address */
#define DMA_DRLA 0x234 /* Data Region Low Address */
#define DMA_DRHA 0x238 /* Data Region High Address */
/*
* Serial-ATA Registers
*/
#define SATA_SS 0x300 /* SStatus */
#define SATA_SE 0x304 /* SError */
#define SATA_SEIM 0x340 /* SError Interrupt Mask */
#define SATA_SC 0x308 /* SControl */
#define SATA_LTM 0x30c /* LTMode */
#define SATA_PHYM3 0x310 /* PHY Mode 3 */
#define SATA_PHYM4 0x314 /* PHY Mode 4 */
#define SATA_PHYM1 0x32c /* PHY Mode 1 */
#define SATA_PHYM2 0x330 /* PHY Mode 2 */
#define SATA_BISTC 0x334 /* BIST Control */
#define SATA_BISTDW1 0x338 /* BIST DW1 */
#define SATA_BISTDW2 0x33c /* BIST DW2 */
#define SATA_SATAICFG 0x050 /* Serial-ATA Interface Configuration */
#define SATA_SATAICFG_REFCLKCNF_20MHZ (0 < 0)
#define SATA_SATAICFG_REFCLKCNF_25MHZ (1 < 0)
#define SATA_SATAICFG_REFCLKCNF_30MHZ (2 < 0)
#define SATA_SATAICFG_REFCLKCNF_40MHZ (3 < 0)
#define SATA_SATAICFG_REFCLKCNF_MASK (3 < 0)
#define SATA_SATAICFG_REFCLKDIV_1 (0 < 2)
#define SATA_SATAICFG_REFCLKDIV_2 (1 < 2) /* Used 20 or 25MHz */
#define SATA_SATAICFG_REFCLKDIV_4 (2 < 2) /* Used 40MHz */
#define SATA_SATAICFG_REFCLKDIV_3 (3 < 2) /* Used 30MHz */
#define SATA_SATAICFG_REFCLKDIV_MASK (3 < 2)
#define SATA_SATAICFG_REFCLKFEEDDIV_50 (0 < 4) /* or 100, when Gen2En is 1 */
#define SATA_SATAICFG_REFCLKFEEDDIV_60 (1 < 4) /* or 120. Used 25MHz */
#define SATA_SATAICFG_REFCLKFEEDDIV_75 (2 < 4) /* or 150. Used 20MHz */
#define SATA_SATAICFG_REFCLKFEEDDIV_90 (3 < 4) /* or 180 */
#define SATA_SATAICFG_REFCLKFEEDDIV_MASK (3 < 4)
#define SATA_SATAICFG_PHYSSCEN (1 < 6)
#define SATA_SATAICFG_GEN2EN (1 < 7)
#define SATA_SATAICFG_COMMEN (1 < 8)
#define SATA_SATAICFG_PHYSHUTDOWN (1 < 9)
#define SATA_SATAICFG_TARGETMODE (1 < 10) /* 1 = Initiator */
#define SATA_SATAICFG_COMCHANNEL (1 < 11)
#define SATA_SATAICFG_IGNOREBSY (1 < 24)
#define SATA_SATAICFG_LINKRSTEN (1 < 25)
#define SATA_SATAICFG_CMDRETXDS (1 < 26)
#define SATA_SATAICTL 0x344 /* Serial-ATA Interface Control */
#define SATA_SATAITC 0x348 /* Serial-ATA Interface Test Control */
#define SATA_SATAIS 0x34c /* Serial-ATA Interface Status */
#define SATA_VU 0x35c /* Vendor Unique */
#define SATA_FISC 0x360 /* FIS Configuration */
#define SATA_FISC_FISWAIT4RDYEN_B0 (1 << 0) /* Device to Host FIS */
#define SATA_FISC_FISWAIT4RDYEN_B1 (1 << 1) /* SDB FIS rcv with <N>bit 0 */
#define SATA_FISC_FISWAIT4RDYEN_B2 (1 << 2) /* DMA Activate FIS */
#define SATA_FISC_FISWAIT4RDYEN_B3 (1 << 3) /* DMA Setup FIS */
#define SATA_FISC_FISWAIT4RDYEN_B4 (1 << 4) /* Data FIS first DW */
#define SATA_FISC_FISWAIT4RDYEN_B5 (1 << 5) /* Data FIS entire FIS */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B0 (1 << 8)
/* Device to Host FIS with <ERR> or <DF> */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B1 (1 << 9) /* SDB FIS rcv with <N>bit */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B2 (1 << 10) /* SDB FIS rcv with <ERR> */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B3 (1 << 11) /* BIST Acivate FIS */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B4 (1 << 12) /* PIO Setup FIS */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B5 (1 << 13) /* Data FIS with Link error */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B6 (1 << 14) /* Unrecognized FIS type */
#define SATA_FISC_FISWAIT4HOSTRDYEN_B7 (1 << 15) /* Any FIS */
#define SATA_FISC_FISDMAACTIVATESYNCRESP (1 << 16)
#define SATA_FISC_FISUNRECTYPECONT (1 << 17)
#define SATA_FISIC 0x364 /* FIS Interrupt Cause */
#define SATA_FISIM 0x368 /* FIS Interrupt Mask */
#define SATA_FISDW0 0x370 /* FIS DW0 */
#define SATA_FISDW1 0x374 /* FIS DW1 */
#define SATA_FISDW2 0x378 /* FIS DW2 */
#define SATA_FISDW3 0x37c /* FIS DW3 */
#define SATA_FISDW4 0x380 /* FIS DW4 */
#define SATA_FISDW5 0x384 /* FIS DW5 */
#define SATA_FISDW6 0x388 /* FIS DW6 */
/* EDMA Command Request Block (CRQB) Data */
struct crqb {
uint32_t cprdbl; /* cPRD Desriptor Table Base Low Address */
uint32_t cprdbh; /* cPRD Desriptor Table Base High Address */
uint16_t ctrlflg; /* Control Flags */
uint16_t atacommand[11];
} __packed;
struct crqb_gen2e {
uint32_t cprdbl; /* cPRD Desriptor Table Base Low Address */
uint32_t cprdbh; /* cPRD Desriptor Table Base High Address */
uint32_t ctrlflg; /* Control Flags */
uint32_t drbc; /* Data Region Byte Count */
uint32_t atacommand[4];
} __packed;
#define CRQB_CRQBL_EPRD_MASK 0xfffffff0
#define CRQB_CRQBL_SDR_MASK 0xfffffffe /* Single data region mask */
/* Control Flags */
#define CRQB_CDIR_WRITE (0 << 0)
#define CRQB_CDIR_READ (1 << 0)
#define CRQB_CDEVICEQUETAG(x) (((x) & 0x1f) << 1) /* CRQB Dev Queue Tag */
#define CRQB_CHOSTQUETAG(x) (((x) & 0x7f) << 1) /* CRQB Host Q Tag */
#define CRQB_CPMPORT(x) (((x) & 0xf) << 12) /* PM Port Transmit */
#define CRQB_CPRDMODE_EPRD (0 << 16) /* PRD table */
#define CRQB_CPRDMODE_SDR (1 << 16) /* Single data region */
#define CRQB_CHOSTQUETAG_GEN2(x) (((x) & 0x7f) << 17) /* CRQB Host Q Tag G2 */
/* Data Region Byte Count */
#define CRQB_CDRBC(x) (((x) & 0xfffe) << 0)
#define CRQB_ATACOMMAND(reg, val) \
((reg << 8) | (val & 0xff))
#define CRQB_ATACOMMAND_LAST (1 << 15)
#define CRQB_ATACOMMAND_REG(reg) (((reg) >> 2) + 0x10)
#define CRQB_ATACOMMAND_FEATURES CRQB_ATACOMMAND_REG(SRB_FE)
#define CRQB_ATACOMMAND_SECTORCOUNT CRQB_ATACOMMAND_REG(SRB_SC)
#define CRQB_ATACOMMAND_LBALOW CRQB_ATACOMMAND_REG(SRB_LBAL)
#define CRQB_ATACOMMAND_LBAMID CRQB_ATACOMMAND_REG(SRB_LBAM)
#define CRQB_ATACOMMAND_LBAHIGH CRQB_ATACOMMAND_REG(SRB_LBAH)
#define CRQB_ATACOMMAND_DEVICE CRQB_ATACOMMAND_REG(SRB_H)
#define CRQB_ATACOMMAND_COMMAND CRQB_ATACOMMAND_REG(SRB_CS)
/* EDMA Phisical Region Descriptors (ePRD) Table Data Structure */
struct eprd {
uint32_t prdbal; /* address bits[31:1] */
uint16_t bytecount; /* Byte Count */
uint16_t eot; /* End Of Table */
uint32_t prdbah; /* address bits[63:32] */
uint32_t resv;
} __packed;
#define EPRD_PRDBAL_MASK 0xfffffffe /* phy memory region mask */
#define EPRD_BYTECOUNT(x) (((x) & 0xffff) << 0)
#define EPRD_EOT (1 << 15) /* End Of Table */
/* EDMA Command Response Block (CRPB) Data */
struct crpb {
uint16_t id; /* CRPB ID */
uint16_t rspflg; /* CPRB Response Flags */
uint32_t ts; /* CPRB Time Stamp */
} __packed;
/* ID */
#define CRPB_CHOSTQUETAG(x) (((x) >> 0) & 0x7f) /* CRPB Host Q Tag */
/* Response Flags */
#define CRPB_CEDMASTS(x) (((x) >> 0) & 0x7f) /* CRPB EDMA Status */
#define CRPB_CDEVSTS(x) (((x) >> 8) & 0xff) /* CRPB Device Status */
#endif /* _MVSATAREG_H_ */

137
sys/dev/ic/mvsatavar.h Normal file
View File

@ -0,0 +1,137 @@
/* $NetBSD: mvsatavar.h,v 1.1 2009/07/27 12:34:14 kiyohara Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MVSATAVAR_H_
#define _MVSATAVAR_H_
#define MVSATA_EDMAQ_LEN 32 /* keep compatibility to gen1 */
#define MVSATA_EDMAQ_INC(i) ((i) = ((i) + 1) % MVSATA_EDMAQ_LEN)
#define MVSATA_HC_MAX 2
#define MVSATA_PORT_MAX 4
#define MVSATA_CHANNEL_MAX (MVSATA_HC_MAX * MVSATA_PORT_MAX)
struct mvsata_port;
union mvsata_crqb {
struct crqb crqb;
struct crqb_gen2e crqb_gen2e;
};
struct _fix_phy_param {
uint32_t pre_amps; /* Pre/SignalAmps */
void (*_fix_phy)(struct mvsata_port *);
};
struct mvsata_port {
struct ata_channel port_ata_channel;
int port;
struct mvsata_hc *port_hc;
enum {
nodma,
dma,
queued,
ncq,
} port_edmamode;
int port_quetagidx; /* Host Queue Tag valiable */
int port_prev_erqqop; /* previous Req Queue Out-Pointer */
bus_dma_tag_t port_dmat;
union mvsata_crqb *port_crqb; /* EDMA Command Request Block */
bus_dmamap_t port_crqb_dmamap;
struct crpb *port_crpb; /* EDMA Command Response Block */
bus_dmamap_t port_crpb_dmamap;
struct eprd *port_eprd; /* EDMA Phy Region Description Table */
bus_dmamap_t port_eprd_dmamap;
struct {
struct ata_xfer *xfer; /* queued xfer */
bus_dmamap_t data_dmamap; /* DMA data buffer */
bus_size_t eprd_offset; /* offset of ePRD buffer */
struct eprd *eprd; /* ePRD buffer */
} port_reqtbl[MVSATA_EDMAQ_LEN];
bus_space_tag_t port_iot;
bus_space_handle_t port_ioh;
bus_space_handle_t port_sata_scontrol; /* SATA Interface control reg */
bus_space_handle_t port_sata_serror; /* SATA Interface error reg */
bus_space_handle_t port_sata_sstatus; /* SATA Interface status reg */
struct ata_queue port_ata_queue;
struct _fix_phy_param _fix_phy_param;
};
struct mvsata_hc {
int hc;
struct mvsata_softc *hc_sc;
bus_space_tag_t hc_iot; /* Tag for SATAHC Arbiter */
bus_space_handle_t hc_ioh; /* Handle for SATAHC Arbiter */
struct mvsata_port *hc_ports[MVSATA_CHANNEL_MAX];
};
struct mvsata_softc {
struct wdc_softc sc_wdcdev; /* common wdc definitions */
int sc_model;
int sc_rev;
enum {
gen_unknown = 0,
gen1,
gen2,
gen2e
} sc_gen; /* Generation for LSI */
int sc_hc; /* number of host controller */
int sc_port; /* number of port/host */
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
bus_dma_tag_t sc_dmat;
struct wdc_regs *sc_wdc_regs;
struct ata_channel *sc_ata_channels[MVSATA_CHANNEL_MAX];
struct mvsata_hc sc_hcs[MVSATA_HC_MAX];
int sc_flags;
#define MVSATA_FLAGS_PCIE (1 << 0)
void (*sc_edma_setup_crqb)(struct mvsata_port *, int, int,
struct ata_bio *);
void (*sc_enable_intr)(struct mvsata_port *, int);
};
int mvsata_attach(struct mvsata_softc *,
int (*mvsata_sreset)(struct mvsata_softc *),
int (*mvsata_misc_reset)(struct mvsata_softc *), int);
int mvsata_intr(struct mvsata_hc *);
int mvsata_error(struct mvsata_port *);
#endif /* _MVSATAVAR_H_ */

512
sys/dev/pci/mvsata_pci.c Normal file
View File

@ -0,0 +1,512 @@
/* $NetBSD: mvsata_pci.c,v 1.1 2009/07/27 12:34:14 kiyohara Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mvsata_pci.c,v 1.1 2009/07/27 12:34:14 kiyohara Exp $");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/pmf.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>
#include <dev/ic/mvsatareg.h>
#include <dev/ic/mvsatavar.h>
#define MVSATA_PCI_HCARBITER_SPACE_OFFSET 0x20000
#define MVSATA_PCI_COMMAND 0x00c00
#define MVSATA_PCI_COMMAND_MWRITECOMBINE (1 << 4)
#define MVSATA_PCI_COMMAND_MREADCOMBINE (1 << 5)
#define MVSATA_PCI_SERRMASK 0x00c28
#define MVSATA_PCI_MSITRIGGER 0x00c38
#define MVSATA_PCI_MODE 0x00d00
#define MVSATA_PCI_DISCTIMER 0x00d04
#define MVSATA_PCI_EROMBAR 0x00d2c
#define MVSATA_PCI_MAINCS 0x00d30
#define MVSATA_PCI_MAINCS_SPM (1 << 2) /* stop pci master */
#define MVSATA_PCI_MAINCS_PME (1 << 3) /* pci master empty */
#define MVSATA_PCI_MAINCS_GSR (1 << 4) /* glab soft reset */
#define MVSATA_PCI_E_IRQCAUSE 0x01900
#define MVSATA_PCI_E_IRQMASK 0x01910
#define MVSATA_PCI_XBARTIMEOUT 0x01d04
#define MVSATA_PCI_ERRLOWADDR 0x01d40
#define MVSATA_PCI_ERRHIGHADDR 0x01d44
#define MVSATA_PCI_ERRATTRIBUTE 0x01d48
#define MVSATA_PCI_ERRCOMMAND 0x01d50
#define MVSATA_PCI_IRQCAUSE 0x01d58
#define MVSATA_PCI_IRQMASK 0x01d5c
#define MVSATA_PCI_MAINIRQCAUSE 0x01d60
#define MVSATA_PCI_MAINIRQMASK 0x01d64
#define MVSATA_PCI_MAINIRQ_SATAERR(hc, port) \
(1 << (((port) << 1) + (hc) * 9))
#define MVSATA_PCI_MAINIRQ_SATADONE(hc, port) \
(1 << (((port) << 1) + (hc) * 9 + 1))
#define MVSATA_PCI_MAINIRQ_SATACOALDONE(hc) (1 << ((hc) * 9 + 8))
#define MVSATA_PCI_MAINIRQ_PCI (1 << 18)
#define MVSATA_PCI_FLASHCTL 0x1046c
#define MVSATA_PCI_GPIOPORTCTL 0x104f0
#define MVSATA_PCI_RESETCFG 0x180d8
#define MVSATA_PCI_DEV(psc) (psc->psc_sc.sc_wdcdev.sc_atac.atac_dev)
struct mvsata_pci_softc {
struct mvsata_softc psc_sc;
pci_chipset_tag_t psc_pc;
pcitag_t psc_tag;
bus_space_tag_t psc_iot;
bus_space_handle_t psc_ioh;
void *psc_ih;
};
static int mvsata_pci_match(device_t, struct cfdata *, void *);
static void mvsata_pci_attach(device_t, device_t, void *);
static int mvsata_pci_detach(device_t, int);
static int mvsata_pci_intr(void *);
static bool mvsata_pci_resume(device_t PMF_FN_ARGS);
static int mvsata_pci_sreset(struct mvsata_softc *);
static int mvsata_pci_misc_reset(struct mvsata_softc *);
static void mvsata_pci_enable_intr(struct mvsata_port *, int);
CFATTACH_DECL_NEW(mvsata_pci, sizeof(struct mvsata_pci_softc),
mvsata_pci_match, mvsata_pci_attach, mvsata_pci_detach, NULL);
/*
* mvsata_pci_match()
* This function returns 2, because mvsata is high priority more than pciide.
*/
static int
mvsata_pci_match(device_t parent, struct cfdata *match, void *aux)
{
struct pci_attach_args *pa = aux;
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_MARVELL)
switch (PCI_PRODUCT(pa->pa_id)) {
case PCI_PRODUCT_MARVELL_88SX5040:
case PCI_PRODUCT_MARVELL_88SX5041:
case PCI_PRODUCT_MARVELL_88SX5080:
case PCI_PRODUCT_MARVELL_88SX5081:
case PCI_PRODUCT_MARVELL_88SX6040:
case PCI_PRODUCT_MARVELL_88SX6041:
case PCI_PRODUCT_MARVELL_88SX6042:
case PCI_PRODUCT_MARVELL_88SX6080:
case PCI_PRODUCT_MARVELL_88SX6081:
case PCI_PRODUCT_MARVELL_88SX7042:
return 2;
}
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ADP2)
switch (PCI_PRODUCT(pa->pa_id)) {
case PCI_PRODUCT_ADP2_1420SA:
case PCI_PRODUCT_ADP2_1430SA:
return 2;
}
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TRIONES &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TRIONES_ROCKETRAID_2310)
return 2;
return 0;
}
static void
mvsata_pci_attach(device_t parent, device_t self, void *aux)
{
struct pci_attach_args *pa = aux;
struct mvsata_pci_softc *psc = device_private(self);
struct mvsata_softc *sc = &psc->psc_sc;
pci_intr_handle_t intrhandle;
pcireg_t csr;
bus_size_t size;
uint32_t reg, mask;
int read_pre_amps, hc, port, rv;
char devinfo[256];
const char *intrstr;
sc->sc_wdcdev.sc_atac.atac_dev = self;
sc->sc_model = PCI_PRODUCT(pa->pa_id);
sc->sc_rev = PCI_REVISION(pa->pa_class);
sc->sc_dmat = pa->pa_dmat;
sc->sc_enable_intr = mvsata_pci_enable_intr;
pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
aprint_naive(": Marvell Serial-ATA Host Controller\n");
aprint_normal(": %s\n", devinfo);
/* Map I/O register */
if (pci_mapreg_map(pa, PCI_MAPREG_START,
PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
&psc->psc_iot, &psc->psc_ioh, NULL, &size) != 0) {
aprint_error_dev(self, "can't map registers\n");
return;
}
psc->psc_pc = pa->pa_pc;
psc->psc_tag = pa->pa_tag;
if (bus_space_subregion(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_HCARBITER_SPACE_OFFSET,
size - MVSATA_PCI_HCARBITER_SPACE_OFFSET, &sc->sc_ioh)) {
aprint_error_dev(self, "can't subregion registers\n");
return;
}
sc->sc_iot = psc->psc_iot;
/* Enable device */
csr = pci_conf_read(psc->psc_pc, psc->psc_tag, PCI_COMMAND_STATUS_REG);
csr |= PCI_COMMAND_MASTER_ENABLE;
pci_conf_write(psc->psc_pc, psc->psc_tag, PCI_COMMAND_STATUS_REG, csr);
if (pci_intr_map(pa, &intrhandle) != 0) {
aprint_error_dev(self, "couldn't map interrupt\n");
return;
}
intrstr = pci_intr_string(psc->psc_pc, intrhandle);
psc->psc_ih = pci_intr_establish(psc->psc_pc, intrhandle, IPL_BIO,
mvsata_pci_intr, sc);
if (psc->psc_ih == NULL) {
aprint_error_dev(self, "couldn't establish interrupt\n");
return;
}
aprint_normal_dev(self, "interrupting at %s\n",
intrstr ? intrstr : "unknown interrupt");
/*
* Check if TWSI serial ROM initialization was triggered.
* If so, then PRE/AMP configuration probably are set after
* reset by serial ROM. If not then override the PRE/AMP
* values.
*/
reg = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_RESETCFG);
read_pre_amps = (reg & 0x00000001) ? 1 : 0;
rv = mvsata_attach(sc, mvsata_pci_sreset, mvsata_pci_misc_reset,
read_pre_amps);
if (rv != 0) {
pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
return;
}
mask = MVSATA_PCI_MAINIRQ_PCI;
for (hc = 0; hc < sc->sc_hc; hc++)
for (port = 0; port < sc->sc_port; port++)
mask |=
MVSATA_PCI_MAINIRQ_SATAERR(hc, port) |
MVSATA_PCI_MAINIRQ_SATADONE(hc, port);
bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINIRQMASK,
mask);
if (!pmf_device_register(self, NULL, mvsata_pci_resume))
aprint_error_dev(self, "couldn't establish power handler\n");
}
static int
mvsata_pci_detach(device_t self, int flags)
{
struct mvsata_pci_softc *psc = device_private(self);
/* XXXX: needs reset ? */
pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
pmf_device_deregister(self);
return 0;
}
static int
mvsata_pci_intr(void *arg)
{
struct mvsata_pci_softc *psc = (struct mvsata_pci_softc *)arg;
struct mvsata_softc *sc = &psc->psc_sc;
uint32_t cause;
int hc, port, handled = 0;
cause = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MAINIRQCAUSE);
for (hc = 0; hc < sc->sc_hc; hc++)
for (port = 0; port < sc->sc_port; port++)
if (cause & MVSATA_PCI_MAINIRQ_SATAERR(hc, port)) {
struct mvsata_port *mvport;
mvport = sc->sc_hcs[hc].hc_ports[port];
handled |= mvsata_error(mvport);
}
for (hc = 0; hc < sc->sc_hc; hc++)
if (cause &
(MVSATA_PCI_MAINIRQ_SATADONE(hc, 0) |
MVSATA_PCI_MAINIRQ_SATADONE(hc, 1) |
MVSATA_PCI_MAINIRQ_SATADONE(hc, 2) |
MVSATA_PCI_MAINIRQ_SATADONE(hc, 3)))
handled |= mvsata_intr(&sc->sc_hcs[hc]);
if (cause & MVSATA_PCI_MAINIRQ_PCI) {
uint32_t pe_cause;
if (sc->sc_flags & MVSATA_FLAGS_PCIE) {
pe_cause = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_E_IRQCAUSE);
aprint_error_dev(MVSATA_PCI_DEV(psc),
"PCIe error: 0x%x\n", pe_cause);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_E_IRQCAUSE, ~pe_cause);
} else {
pe_cause = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_IRQCAUSE);
aprint_error_dev(MVSATA_PCI_DEV(psc),
"PCI error: 0x%x\n", pe_cause);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_IRQCAUSE, ~pe_cause);
}
handled = 1; /* XXXXX */
}
return handled;
}
static bool
mvsata_pci_resume(device_t dev PMF_FN_ARGS)
{
/* not yet... */
return true;
}
static int
mvsata_pci_sreset(struct mvsata_softc *sc)
{
struct mvsata_pci_softc *psc = (struct mvsata_pci_softc *)sc;
uint32_t val;
int i;
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS);
val |= MVSATA_PCI_MAINCS_SPM;
bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS, val);
for (i = 0; i < 1000; i++) {
delay(1);
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MAINCS);
if (val & MVSATA_PCI_MAINCS_PME)
break;
}
if (!(val & MVSATA_PCI_MAINCS_PME)) {
aprint_error_dev(MVSATA_PCI_DEV(psc),
"PCI master won't flush\n");
return -1;
}
/* reset */
bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS,
val | MVSATA_PCI_MAINCS_GSR);
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS);
delay(5);
if (!(val & MVSATA_PCI_MAINCS_GSR)) {
aprint_error_dev(MVSATA_PCI_DEV(psc),
"can't set global reset\n");
return -1;
}
/* clear reset and *reenable the PCI master* (not mentioned in spec) */
val &= ~(MVSATA_PCI_MAINCS_GSR | MVSATA_PCI_MAINCS_SPM);
bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS, val);
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS);
delay(5);
if (val & MVSATA_PCI_MAINCS_GSR) {
aprint_error_dev(MVSATA_PCI_DEV(psc),
"can't set global reset\n");
return -1;
}
return 0;
}
static int
mvsata_pci_misc_reset(struct mvsata_softc *sc)
{
struct mvsata_pci_softc *psc = (struct mvsata_pci_softc *)sc;
#define MVSATA_PCI_COMMAND_DEFAULT 0x0107e371
#define MVSATA_PCI_COMMAND_PCI_CONVENTIONAL_ONLY 0x800003e0
uint32_t val, pci_command = MVSATA_PCI_COMMAND_DEFAULT;
bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_FLASHCTL,
0x0fcfffff);
if (sc->sc_gen == gen2 || sc->sc_gen == gen2e) {
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_GPIOPORTCTL);
val &= 0x3;
#if 0
val |= 0x00000060;
#else /* XXXX */
val |= 0x00000070;
#endif
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_GPIOPORTCTL, val);
}
if (sc->sc_gen == gen1) {
/* Expansion ROM BAR Enable */
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_EROMBAR);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_EROMBAR, val | 0x00000001);
}
if (sc->sc_flags & MVSATA_FLAGS_PCIE) {
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MAINIRQMASK, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_E_IRQCAUSE, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_E_IRQMASK, 0);
} else {
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MODE);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MODE, val & 0xff00ffff);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_DISCTIMER, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MSITRIGGER, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_XBARTIMEOUT, 0x000100ff);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MAINIRQMASK, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_SERRMASK, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_IRQCAUSE, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_IRQMASK, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_ERRLOWADDR, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_ERRHIGHADDR, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_ERRATTRIBUTE, 0);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_ERRCOMMAND, 0);
}
/* Enable LED */
if (sc->sc_gen == gen1) {
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_GPIOPORTCTL, 0);
/* XXXX: 50xxB2 errata ? */
#if 0
if (sc->sc_rev == 3) {
int port;
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_GPIOPORTCTL);
/* XXXX: check HDD connected */
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_GPIOPORTCTL, val);
}
#endif
/* Disable Flash controller clock */
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_EROMBAR);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_EROMBAR, val & ~0x00000001);
} else
#if 0
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_GPIOPORTCTL, 0x00000060);
#else /* XXXX */
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_GPIOPORTCTL, 0x00000070);
#endif
if (sc->sc_flags & MVSATA_FLAGS_PCIE)
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_E_IRQMASK, 0x0000070a);
else {
val = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MODE);
if ((val & 0x30) >> 4) { /* PCI-X */
int mv60x1b2 =
((sc->sc_model == PCI_PRODUCT_MARVELL_88SX6041 ||
sc->sc_model == PCI_PRODUCT_MARVELL_88SX6081) &&
sc->sc_rev == 7);
pci_command &=
~MVSATA_PCI_COMMAND_PCI_CONVENTIONAL_ONLY;
if (sc->sc_gen == gen1 || mv60x1b2)
pci_command &=
~MVSATA_PCI_COMMAND_MWRITECOMBINE;
} else
if (sc->sc_gen == gen1)
pci_command &=
~(MVSATA_PCI_COMMAND_MWRITECOMBINE |
MVSATA_PCI_COMMAND_MREADCOMBINE);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_COMMAND, pci_command);
#define MVSATA_PCI_INTERRUPT_MASK 0x00d77fe6
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_SERRMASK, MVSATA_PCI_INTERRUPT_MASK);
bus_space_write_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_IRQMASK, MVSATA_PCI_INTERRUPT_MASK);
}
return 0;
}
static void
mvsata_pci_enable_intr(struct mvsata_port *mvport, int on)
{
struct mvsata_pci_softc *psc =
device_private(mvport->port_ata_channel.ch_atac->atac_dev);
uint32_t mask;
int hc = mvport->port_hc->hc, port = mvport->port;
mask = bus_space_read_4(psc->psc_iot, psc->psc_ioh,
MVSATA_PCI_MAINIRQMASK);
if (on)
mask |= MVSATA_PCI_MAINIRQ_SATADONE(hc, port);
else
mask &= ~MVSATA_PCI_MAINIRQ_SATADONE(hc, port);
bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINIRQMASK,
mask);
}