This patch adds ATAPI DMA support for HT1000 (aka BCM5785) & HT1100 (aka BCM11000) SATA Controller. Signed-off-by: Anantha Subramanyam <ananth@xxxxxxxxxxxx> --- --- linux-2.6.23.11/drivers/ata/sata_svw.c.orig 2008-01-07 05:22:29.000000000 -0800 +++ linux-2.6.23.11/drivers/ata/sata_svw.c 2008-01-08 03:23:31.000000000 -0800 @@ -45,6 +45,8 @@ #include <linux/interrupt.h> #include <linux/device.h> #include <scsi/scsi_host.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi.h> #include <linux/libata.h> #ifdef CONFIG_PPC_OF @@ -53,12 +55,13 @@ #endif /* CONFIG_PPC_OF */ #define DRV_NAME "sata_svw" -#define DRV_VERSION "2.3" +#define DRV_VERSION "2.3.1" enum { /* ap->flags bits */ K2_FLAG_SATA_8_PORTS = (1 << 24), K2_FLAG_NO_ATAPI_DMA = (1 << 25), + K2_FLAG_BAR_POS_3 = (1 << 26), /* Taskfile registers offsets */ K2_SATA_TF_CMD_OFFSET = 0x00, @@ -88,17 +91,216 @@ enum { /* Port stride */ K2_SATA_PORT_OFFSET = 0x100, - board_svw4 = 0, - board_svw8 = 1, +// ATAPI QDMA start + K2_ATAPI_FEAT_DMA_BIT = 0x01, + + /* qdma reg offsets */ + K2_SATA_QAL_OFFSET = 0xA0, + K2_SATA_QAU_OFFSET = 0xA4, + K2_SATA_QPI_OFFSET = 0xA8, + K2_SATA_QCI_OFFSET = 0xAC, + K2_SATA_QCR_OFFSET = 0xB0, + K2_SATA_QDR_OFFSET = 0xB4, + K2_SATA_QSR_OFFSET = 0xB8, + K2_SATA_QMR_OFFSET = 0xBC, + + K2_SATA_GLB_CTL_OFFSET = 0x1000, + K2_SATA_GLB_STS_OFFSET = 0x1004, + + K2_SATA_ENABLE_INTRS = 0x21, // 0x3F, want only done & common error + K2_SATA_CLEAR_ALL_INTRS = 0xFFFFFFFF, + + K2_SATA_NUM_DESCRIPTORS = 4, // min 2 for ATAPI, but min 4 for our hw + K2_SATA_QDMA_MODE_ON = 1, + K2_SATA_QDMA_ENABLE = 0x01, + + K2_SATA_QDMA_PORT_RESET = 0x08, + K2_SATA_QDMA_PORT_ABORT = 0x04, + K2_SATA_QDMA_PORT_PAUSE = 0x02, + K2_SATA_CLEAR_QDMA_QPI_REG = 0x00, + + K2_SATA_INTR_CMD_ERROR = 0x00000020, + K2_SATA_INTR_DEV_CHANGE = 0x10, + K2_SATA_INTR_RESET_ACK = 0x08, + K2_SATA_INTR_ABORT_ACK = 0x04, + K2_SATA_INTR_PAUSE_ACK = 0x02, + K2_SATA_INTR_CMD_DONE = 0x00000001, + + K2_SATA_DESC_TYPE = 0x00, + K2_SATA_DESC_PIO_DATA = 0x00, + K2_SATA_DESC_PIO_NON_DATA = 0x02, + + K2_SATA_CTRL_FLAG_PIO_BIT = 0x80, // PIO bit + K2_SATA_CTRL_FLAG_ATAPI = 0x40, // ATAPI bit + K2_SATA_CTRL_FLAG_SKIP = 0x10, // SKIP bit + K2_SATA_CTRL_FLAG_IGNR = 0x08, // IGNR bit + K2_SATA_CTRL_FLAG_RD_DIR_BIT = 0x02, // READ Dir bit + K2_SATA_CTRL_FLAG_EIN_BIT = 0x01, // Enable Interrupt bit + + K2_SATA_DESC_D_BIT = 0x01, + K2_CMD_ONLY_FRM = 0x010, /* No data associated with command */ + + K2_ATAPI_CDB_BUFSZ = ATAPI_CDB_LEN, + + K2_SATA_SELECT_DEV0 = 0xA0, + K2_SATA_CMD_DEVICE_RESET = 0x08, + K2_SATA_STS_BSY = 0x80, // busy + + K2_SATA_SCR2_RESET_PHY = 0x00000001, + K2_SATA_SCR2_CLEAR_REG = 0x00000000, + + K2_SATA_DET_MASK = 0x000F, + K2_SATA_INTF_MASK = 0x0F00, + K2_DEV_DET_PHY_RDY = 0x3, + K2_SATA_INFT_ACTIVE = 0x1, + + K2_SATA_10MS_WAIT = 10000, + K2_SATA_100MS_WAIT = 100000, + K2_SATA_PAUSE_ACK_TIME = 100, + K2_SATA_CLEAR_ALL_ERRORS = 0xffffffff, + K2_SATA_COM_RESET_WAIT = 1500, //1.5ms + + K2_SATA_QSR_PCI_MASTER_ABORT = (1<<21), + K2_SATA_QSR_DATA_CRC_ERR = (1<<20), + K2_SATA_QSR_UNDER_FLOW = (1<<19), + K2_SATA_QSR_OVER_FLOW = (1<<18), + K2_SATA_QSR_ATA_CMD_ERR = (1<<17), + K2_SATA_QSR_PCI_BUS_MASTER_ERR = (1<<16), + K2_SATA_QSR_SATA_INTF_ERR = (1<<6), + K2_SATA_QSR_ATAPI_UNDERRUN = (1<<22), + + chip_svw4 = 0, + chip_svw8 = 1, + chip_svwx = 2, + chip_svw41 = 3, +// ATAPI QDMA end + +// HT1100 additions + K2_SATA_SATADBGREG = 0xF0, + // K2_SATA_LEDENREG = 0x5000, + K2_SATA_TESTCTRLREG = 0x10f0, + K2_SATA_MDIOCTRLREG = 0x8c, + // K2_SATA_PLLCTRLREG = 0x84, + + K2_SATA_PLL_WAIT = 990,//100000,//90000, + K2_SATA_LED_ENABLE_VALUE = 0x00000002, + K2_SATA_TEST_CTRL_VALUE = 0x40000001, + K2_SATA_PLL_CTRL_VALUE = 0x08000000, + K2_SATA_PLL_1P5_GIG = 0, + K2_SATA_PLL_3P0_GIG = 1, + K2_SATA_RESET_PHY_DELAY = 0x3000, + + // phy vals + BCM_SATA_PHY_TXCNT_1G5 = 0x7830, + BCM_SATA_PHY_TXCNT_3G0 = 0xF620, + BCM_SATA_PHY_RXCNT_1G5 = 0x0180, + BCM_SATA_PHY_RXCNT_3G0 = 0x0190, + + chip_svw42 = 4, // HT1100 bar 3 + chip_svw43 = 5, // HT1100 bar 5 + // HT1100 addns end + }; +/* SATA Command Descriptor Structure */ + +typedef struct _k2_sata_cmd_desc_s { +#ifdef __BIG_ENDIAN + u8 ss_Rsvd3; + u8 ss_PortMul; + u8 ss_CtrlFlags; + u8 ss_DescType; + u16 sw_Tag; + u16 sw_HostMemDataBuffAddr; + u32 sl_PrdTblBaseLow; + u16 sw_PrdCount; + u16 sw_PrdTblBaseHigh; + u16 sw_Features; + u8 ss_DevHead; + u8 ss_SataCmd; + u32 sl_LbaLow; + u16 sw_SectorCount; + u16 sw_LbaHigh; + u32 sl_Rsvd1c; +#else + u8 ss_DescType; + u8 ss_CtrlFlags; + u8 ss_PortMul; + u8 ss_Rsvd3; + u16 sw_HostMemDataBuffAddr; + u16 sw_Tag; + u32 sl_PrdTblBaseLow; + u16 sw_PrdTblBaseHigh; + u16 sw_PrdCount; + u8 ss_SataCmd; + u8 ss_DevHead; + u16 sw_Features; + u32 sl_LbaLow; + u16 sw_LbaHigh; + u16 sw_SectorCount; + u32 sl_Rsvd1c; +#endif +} k2_sata_cmd_desc_t; + + +typedef struct _k2_sata_port_info_s { + u8 qpi; + u8 qci; + u8 qdma_mode; + u32 qcr_local; + + // qdma related addrs + void __iomem *qal_addr; + void __iomem *qau_addr; + void __iomem *qpi_addr; + void __iomem *qci_addr; + void __iomem *qcr_addr; + void __iomem *qdr_addr; + void __iomem *qsr_addr; + void __iomem *qmr_addr; + + // desc area and addresses + dma_addr_t cmd_desc_addr; + k2_sata_cmd_desc_t* pcmd_desc; + + dma_addr_t cdb_phy_addr; + u8 *pcdb_cpybuf; + + u8 needs_reset; + + // atapi related + u8 is_atapi_device; + u32 qsr_saved; + u32 atapi_reset_cnt; + u32 atapi_capabilities; + +} k2_sata_port_info; + + +int skip_init = 0; +module_param(skip_init, int, 0444); +MODULE_PARM_DESC( skip_init, "Initialization done by BIOS"); + + static u8 k2_stat_check_status(struct ata_port *ap); static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc) { + u8 command = qc->scsicmd->cmnd[0]; + if (qc->ap->flags & K2_FLAG_NO_ATAPI_DMA) return -1; /* ATAPI DMA not supported */ + else + { + // DMA is for only read or write commands + if( (command == READ_10) || (command == READ_16) || (command == READ_12) + || (command == WRITE_10) || (command == WRITE_16) || (command == WRITE_12)) + // TODO may need to check the dynamic flag in pspi rather than unconditional ok + return 0; + else + return -1; + } return 0; } @@ -305,6 +507,612 @@ static int k2_sata_proc_info(struct Scsi } #endif /* CONFIG_PPC_OF */ +// ATAPI QDMA start + +#define K2_IS_SATA_STS_GOOD(sata_sts) \ + (((sata_sts & K2_SATA_DET_MASK) == K2_DEV_DET_PHY_RDY) && (((sata_sts & K2_SATA_INTF_MASK)>>8) == K2_SATA_INFT_ACTIVE)) + + +void k2_ht1x_qdma_disable(struct ata_port *ap); + + +int k2_ht1x_port_start (struct ata_port *ap) +{ + struct device *dev = ap->dev; + int rc; + k2_sata_port_info* pspi; + ap->private_data = NULL; + + rc = ata_port_start( ap); + if( rc) + return rc; + + // do our qdma descriptor space alloc, we use prd from ata port itself + pspi = kmalloc(sizeof(k2_sata_port_info), GFP_KERNEL); + if (pspi == NULL) { + rc = -ENOMEM; + goto start_err_out; + } + + ap->private_data = pspi; + + pspi->pcmd_desc = dma_alloc_coherent(dev, sizeof( k2_sata_cmd_desc_t) * K2_SATA_NUM_DESCRIPTORS, &pspi->cmd_desc_addr, GFP_KERNEL); + if (pspi->pcmd_desc == NULL) { + kfree( pspi); + rc = -ENOMEM; + goto start_err_out; + } + + pspi->pcdb_cpybuf = dma_alloc_coherent(dev, K2_ATAPI_CDB_BUFSZ, &pspi->cdb_phy_addr, GFP_KERNEL); + if (pspi->pcdb_cpybuf == NULL) + { + dma_free_coherent(dev, sizeof( k2_sata_cmd_desc_t) * K2_SATA_NUM_DESCRIPTORS, pspi->pcmd_desc, pspi->cmd_desc_addr); + kfree( pspi); + rc = -ENOMEM; + goto start_err_out; + } + + // data_addr is at 0 offset + pspi->qal_addr = ap->ioaddr.data_addr + K2_SATA_QAL_OFFSET; + pspi->qau_addr = ap->ioaddr.data_addr + K2_SATA_QAU_OFFSET; + pspi->qpi_addr = ap->ioaddr.data_addr + K2_SATA_QPI_OFFSET; + pspi->qci_addr = ap->ioaddr.data_addr + K2_SATA_QCI_OFFSET; + pspi->qcr_addr = ap->ioaddr.data_addr + K2_SATA_QCR_OFFSET; + pspi->qdr_addr = ap->ioaddr.data_addr + K2_SATA_QDR_OFFSET; + pspi->qsr_addr = ap->ioaddr.data_addr + K2_SATA_QSR_OFFSET; + pspi->qmr_addr = ap->ioaddr.data_addr + K2_SATA_QMR_OFFSET; + + VPRINTK("svw qal 0x%x qsr addr 0x%x ioaddr 0x%x\n", pspi->qal_addr, pspi->qsr_addr, ap->ioaddr.data_addr); + + // init our stuff + pspi->qpi = 0; + pspi->qci = 0; + pspi->qdma_mode = 0; + + writeb( 0, pspi->qci_addr); + writeb( 0, pspi->qpi_addr); + pspi->qcr_local = 0; + writel( pspi->qcr_local, pspi->qcr_addr); + writel( K2_SATA_CLEAR_ALL_INTRS, pspi->qsr_addr); + + // writel( K2_SATA_ENABLE_INTRS, pspi->qmr_addr); + writel( K2_SATA_NUM_DESCRIPTORS - 1, pspi->qdr_addr); + + pspi->needs_reset = 0; + pspi->is_atapi_device = 0; // will be set anytime we get a atapi cmd on the port + pspi->atapi_reset_cnt = 0; + pspi->atapi_capabilities = 0; // if v need to disable dma on the fly becoz of too many errors etc + + return 0; + +start_err_out: + + return rc; +} + +void k2_ht1x_port_stop (struct ata_port *ap) +{ + struct device *dev = ap->dev; + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + if( pspi == NULL) + return; + + k2_ht1x_qdma_disable( ap); + + // free our private data first, then call generic + dma_free_coherent(dev, sizeof( k2_sata_cmd_desc_t) * K2_SATA_NUM_DESCRIPTORS, pspi->pcmd_desc, pspi->cmd_desc_addr); + dma_free_coherent(dev, K2_ATAPI_CDB_BUFSZ, pspi->pcdb_cpybuf, pspi->cdb_phy_addr); + kfree( pspi); + +} + +/* + Some helper functions +*/ + +void k2_ht1x_qdma_enable(struct ata_port *ap) +{ + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + pspi->qpi = 0; + pspi->qci = 0; + + pspi->qcr_local = K2_SATA_QDMA_ENABLE; + + writel( cpu_to_le32(pspi->cmd_desc_addr & 0xffffffff), pspi->qal_addr); + + // our dma mask is 32bit, so v assume 0 for upper bits + // similar to what libata does for prd addresses + // as below causes grief in 32bit single CPU flavour + // writel( cpu_to_le32( (pspi->cmd_desc_addr >> 32) & 0xffff), pspi->qau_addr); + writel( 0, pspi->qau_addr); + + writeb( 0, pspi->qci_addr); + writeb( 0, pspi->qpi_addr); + writel( K2_SATA_CLEAR_ALL_INTRS, pspi->qsr_addr); + writel( K2_SATA_NUM_DESCRIPTORS - 1, pspi->qdr_addr); + + writel( K2_SATA_ENABLE_INTRS, pspi->qmr_addr); + writel( pspi->qcr_local, pspi->qcr_addr); + + +} + +void k2_ht1x_qdma_disable(struct ata_port *ap) +{ + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + // disable qdma first + pspi->qcr_local = 0; + writel( pspi->qcr_local, pspi->qcr_addr); + + pspi->qpi = 0; + pspi->qci = 0; + pspi->qdma_mode = 0; + + writeb( 0, pspi->qci_addr); + writeb( 0, pspi->qpi_addr); + writel( K2_SATA_CLEAR_ALL_INTRS, pspi->qsr_addr); + writel( 0, pspi->qmr_addr); + writel( 0, pspi->qdr_addr); + +} + +int k2_ht1x_qdma_pause(struct ata_port *ap, int pause) +{ + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + u32 qsr; + volatile int i = 0; + + // if qdma is not enabled nothing todo, pause or unpause + if( !(pspi->qcr_local & K2_SATA_QDMA_ENABLE) ) + return 0; + + // pause qdma first, + // disable intr on pause ack, we will poll for it as we don't q cmds + if( !(pspi->qcr_local & K2_SATA_QDMA_PORT_PAUSE) && pause) + { + pspi->qcr_local |= K2_SATA_QDMA_PORT_PAUSE; + writel( pspi->qcr_local, pspi->qcr_addr); + + // wait for pause ack + while( i++ < 200) + { + udelay( 5); + + if( (qsr = readl( pspi->qsr_addr)) & K2_SATA_INTR_PAUSE_ACK) + { + writel( qsr, pspi->qsr_addr); + break; + } + } + + if( i == 200) + { + pspi->qcr_local &= ~K2_SATA_QDMA_PORT_PAUSE; + return -1; // we couldn't pause in 10 msecs, we have problems..... + } + + } + else + // we need to unpause + if( (pspi->qcr_local & K2_SATA_QDMA_PORT_PAUSE) && !pause) + { + + pspi->qcr_local &= ~K2_SATA_QDMA_PORT_PAUSE; + writel( pspi->qcr_local, pspi->qcr_addr); + } + + return 0; +} + + +int k2_build_atapi_cmd_desc(struct ata_queued_cmd *qc, k2_sata_cmd_desc_t *desc, u8 flags) +{ + struct ata_port *ap = qc->ap; + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + memset(desc, 0, sizeof(k2_sata_cmd_desc_t)); + + desc->ss_CtrlFlags = flags; + desc->ss_SataCmd = 0xA0; // ATAPI Pkt Cmd + desc->ss_DevHead = 0xA0; + + // as per libata atapi_xlat func, this is set for only pio + desc->sl_LbaLow = 0; + desc->sw_LbaHigh = 0; + + if (flags & K2_SATA_CTRL_FLAG_ATAPI) + { + // ATAPI CDB Packet Transfer + // Set the CDB pad to zero + memset(pspi->pcdb_cpybuf, 0, K2_ATAPI_CDB_BUFSZ); + memcpy(pspi->pcdb_cpybuf, qc->cdb, qc->dev->cdb_len); + + desc->sl_PrdTblBaseLow = cpu_to_le32( pspi->cdb_phy_addr | 0x01); + desc->sw_PrdTblBaseHigh = 0; + desc->sw_PrdCount = qc->dev->cdb_len; + desc->sw_Features = K2_ATAPI_FEAT_DMA_BIT; + } + else // it is the data desc + { + // libata does not update this field when splitting prd's for 64kb crossover + // so examine eot bit in first prd element to confirm + // if(qc->n_elem == 1) { + if( (ap->prd[0].flags_len & cpu_to_le32(ATA_PRD_EOT) ) != 0) { + desc->sl_PrdTblBaseLow = ap->prd[0].addr | 0x01; // already in le format + desc->sw_PrdTblBaseHigh = 0; // revisit to add >4GB support, ata_fill_sg can't be used then + desc->sw_PrdCount = ap->prd[0].flags_len & 0xFFFF; + + } + else + { + desc->sl_PrdTblBaseLow = cpu_to_le32(ap->prd_dma); + desc->sw_PrdTblBaseHigh = 0; // v reuse same prd table everytime + } + + } + + return 0; +} + +void k2_ht1x_qdma_post_atapi(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + u8 flags = 0; + + k2_sata_cmd_desc_t* pcdesc = pspi->pcmd_desc + pspi->qpi; + + flags = K2_SATA_CTRL_FLAG_ATAPI | K2_SATA_CTRL_FLAG_PIO_BIT; // | K2_SATA_CTRL_FLAG_EIN_BIT; + k2_build_atapi_cmd_desc( qc, pcdesc, flags); + + flags = K2_SATA_CTRL_FLAG_EIN_BIT; + + if( !(qc->tf.flags & ATA_TFLAG_WRITE) ) + flags |= K2_SATA_CTRL_FLAG_RD_DIR_BIT; + pcdesc++; + k2_build_atapi_cmd_desc( qc, pcdesc, flags); + + pspi->qpi = (pspi->qpi + 2) % K2_SATA_NUM_DESCRIPTORS; + + writel( pspi->qpi, pspi->qpi_addr); + + +} + + +/* +later version of libata (kernel 2.6.18 & later) have a elaborate +error handling mech that includes multilevel of resets (soft, hard, post...) +so we plug into that + +*/ +int k2_ht1x_atapi_soft_reset(struct ata_port *ap, unsigned int *class) +{ + u8 dev_sts; + struct ata_ioports *ioaddr = &ap->ioaddr; + int count = 5; + + writel( K2_SATA_SELECT_DEV0, ioaddr->device_addr ); + udelay( 500); + writel( K2_SATA_CMD_DEVICE_RESET, ioaddr->command_addr ); + + // this can take upto 5 secs + do + { + dev_sts = ata_busy_wait( ap, 100000, K2_SATA_STS_BSY); + count--; + } while( ( dev_sts & K2_SATA_STS_BSY) && (count > 0) ); + + if (dev_sts & K2_SATA_STS_BSY) { + printk("sata_svw : Busy still set after soft reset dev_sts=%x\n", dev_sts); + return -EIO; + } + + *class = ata_dev_try_classify(ap, 0, NULL); + return 0; +} + + +int k2_ht1x_atapi_reset(struct ata_port *ap, unsigned int *class) +{ + u32 dev_sts, sata_sts, qsr, i; + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + int ret = 0; + + + // if (port->atapi.capabilities & ELR_ATAPI_QDMA) + { + k2_ht1x_qdma_disable( ap); + + // Do a PHY reset + // Power Down Phy + k2_sata_scr_write( ap, (K2_SATA_SCR_CONTROL_OFFSET - K2_SATA_SCR_STATUS_OFFSET), K2_SATA_SCR2_RESET_PHY ); + // Delay 1.5ms + udelay( K2_SATA_COM_RESET_WAIT); + // Power Up Phy + k2_sata_scr_write( ap, (K2_SATA_SCR_CONTROL_OFFSET - K2_SATA_SCR_STATUS_OFFSET), K2_SATA_SCR2_CLEAR_REG ); + // Delay 1ms : Most drives should be ready within 1ms + udelay( K2_SATA_COM_RESET_WAIT); + // delay up to 2 seconds, this should be ok for SATA I and SATA II drives + for (i = 0; i < 20; i++) { + // check if drive exist again + k2_sata_scr_read( ap, 0, &sata_sts ); + dev_sts = k2_stat_check_status( ap); + // drive exist and ready + if (K2_IS_SATA_STS_GOOD(sata_sts) && (!(dev_sts & K2_SATA_STS_BSY))) { + // Initialize Registers + k2_sata_scr_write( ap, (K2_SATA_SCR_ERROR_OFFSET - K2_SATA_SCR_STATUS_OFFSET), K2_SATA_CLEAR_ALL_ERRORS ); + qsr = readl( pspi->qsr_addr); + writel( qsr, pspi->qsr_addr); + + VPRINTK( "PHY Reset on Port[%x] i=%x DrvSts=%x SataSts=%x SUCCESSFULLY Completed\n", + ap->port_no, i, dev_sts, sata_sts); + break; + } + // check every 1 milli second, most of the drive will be ready in a milli second + msleep( K2_SATA_100MS_WAIT / 1000); + } + if (i == 20) { + DPRINTK("\n\nPHY Reset on Port[%x] DrvSts=%x SataSts=%x FAILED\n\n", + ap->port_no, dev_sts, sata_sts); + ret = -EIO; + } + + // QDMA Reset + writel( (K2_SATA_QDMA_PORT_RESET|K2_SATA_QDMA_ENABLE), pspi->qcr_addr); + // Wait for the Reset ack + for (i = 0; i < K2_SATA_PAUSE_ACK_TIME; i++) { + qsr = readl( pspi->qsr_addr); + if (qsr & K2_SATA_INTR_RESET_ACK) break; + udelay( K2_SATA_10MS_WAIT); + } + if (i == K2_SATA_PAUSE_ACK_TIME) { + printk("sata_svw : Port[%x] ATAPI Reset FAILED QSR=%x\n", ap->port_no, qsr); + ret = -EIO; + } + + qsr = readl( pspi->qsr_addr); + writel( qsr, pspi->qsr_addr); + // Clear bit 5 in QSR if set + if (qsr & K2_SATA_INTR_CMD_ERROR) + writel( qsr, pspi->qsr_addr); + k2_sata_scr_write( ap, (K2_SATA_SCR_ERROR_OFFSET - K2_SATA_SCR_STATUS_OFFSET), K2_SATA_CLEAR_ALL_ERRORS ); + } + + if( ret != 0) + return ret; + + + // Enable QDMA + k2_ht1x_qdma_enable( ap); + + *class = ata_dev_try_classify(ap, 0, NULL); + return 0; +} + + +inline unsigned int k2_ht1x_handle_qdma_error (struct ata_port *ap, + struct ata_queued_cmd *qc, u32 qsr) +{ + u8 status; + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + k2_ht1x_qdma_pause( ap, 1); + DPRINTK("qdma atapi error 0x%x\n", qsr); + + // all tf registers specifically sts maintain their contents, so fall into libata's complete fn + if( qsr & K2_SATA_QSR_PCI_BUS_MASTER_ERR) + { + qc->err_mask |= AC_ERR_HOST_BUS; + ap->hsm_task_state = HSM_ST_ERR; + } + + status = k2_stat_check_status( ap); + + if( (qsr & K2_SATA_QSR_OVER_FLOW) || ( pspi->qci != pspi->qpi) ) + { + printk( "sata_svw needs_reset=1 qsr 0x%x\n", qsr); + pspi->qsr_saved = qsr; + pspi->needs_reset = 1; + qc->err_mask |= AC_ERR_HSM; + // this will freeze the port & ops->error_handler is then invoked to thaw the port + // and do other bad things like reset (hard, soft) etc + } + + ata_hsm_move( ap, qc, status, 0); + return 0; + +} + +inline unsigned int k2_ht1x_qdma_intr (struct ata_port *ap, + struct ata_queued_cmd *qc) +{ + u32 qsr; + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + VPRINTK("ata%u: protocol %d task_state %d\n", + ap->id, qc->tf.protocol, ap->hsm_task_state); + + /* Check whether we are expecting interrupt in this state */ + switch (ap->hsm_task_state) { + case HSM_ST_LAST: + if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) + { + + // do some qdma qsr processing here + qsr = readl( pspi->qsr_addr); + + // check if there is an error, if not make sure it is the done for the 2nd cmd + writel( qsr, pspi->qsr_addr); + pspi->qci = readl( pspi->qci_addr); + if( qsr & K2_SATA_INTR_CMD_ERROR) + { + // clear qsr common error bit + writel( qsr, pspi->qsr_addr); + + k2_ht1x_handle_qdma_error( ap, qc, qsr); + return 1; /* irq handled */ + } + else + { + if( pspi->qci != pspi->qpi) + { + printk("sata_svw STOP stuck without error qsr 0x%x\n", qsr); + return 0; + } + + + // yay! v got a normal completion, let us finish it + ap->hsm_task_state = HSM_ST_IDLE; + + // for now just clear tf read flag, hopefully it is used only in error path + qc->flags &= ~ATA_QCFLAG_RESULT_TF; + ata_qc_complete( qc); + return 1; /* irq handled */ + } + } + else + printk("wrong protocol, we shouldn't hv been here %d \n", qc->tf.protocol); + break; + + + default: + break; // goto idle_irq; + } + + return 0; /* irq not handled */ +} + + +irqreturn_t k2_ht1x_interrupt (int irq, void *dev_instance) +{ + struct ata_host *host = dev_instance; + unsigned int i; + unsigned int handled = 0; + unsigned long flags; + k2_sata_port_info* pspi; + u32 glbsts; + struct ata_port *ap; + struct ata_queued_cmd *qc; + + /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ + spin_lock_irqsave(&host->lock, flags); + + ap = host->ports[0]; + glbsts = readl( ap->ioaddr.data_addr + K2_SATA_GLB_STS_OFFSET); + for (i = 0; i < host->n_ports; i++) + { + if( glbsts & (1 << i) ) + // '1' bit indicates no interrupt on this port, keep moving + continue; + + ap = host->ports[i]; + + if (ap && + !(ap->flags & ATA_FLAG_DISABLED)) { + pspi = (k2_sata_port_info*)ap->private_data; + if( !pspi) + { + VPRINTK("pspi not set port %d \n", i); + continue; + } + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && + (qc->flags & ATA_QCFLAG_ACTIVE)) + { + if( (pspi->qcr_local & K2_SATA_QDMA_ENABLE) && + !(pspi->qcr_local & K2_SATA_QDMA_PORT_PAUSE) ) + handled |= k2_ht1x_qdma_intr( ap, qc); + else + if( !(qc->tf.flags & ATA_TFLAG_POLLING)) + // let libata's nice handler take care of it + handled |= ata_host_intr(ap, qc); + } + + } + } + + spin_unlock_irqrestore(&host->lock, flags); + + return IRQ_RETVAL(handled); +} + +unsigned int k2_ht1x_qc_issue_prot(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + /* start the command */ + switch (qc->tf.protocol) { + + // ATA stuff fall through to libata + case ATA_PROT_NODATA: + case ATA_PROT_PIO: + case ATA_PROT_DMA: + pspi->is_atapi_device = 0; + return ata_qc_issue_prot( qc); + break; + + case ATA_PROT_ATAPI: + case ATA_PROT_ATAPI_NODATA: + pspi->is_atapi_device = 1; + if( (pspi->qcr_local & K2_SATA_QDMA_ENABLE) && + !(pspi->qcr_local & K2_SATA_QDMA_PORT_PAUSE) ) + k2_ht1x_qdma_pause( ap, 1); + + return ata_qc_issue_prot( qc); + break; + + + case ATA_PROT_ATAPI_DMA: + WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); + pspi->is_atapi_device = 1; + + if( !(pspi->qcr_local & K2_SATA_QDMA_ENABLE) ) + k2_ht1x_qdma_enable( ap); + else + // unpause if needed + if( pspi->qcr_local & K2_SATA_QDMA_PORT_PAUSE) + k2_ht1x_qdma_pause( ap, 0); + + k2_ht1x_qdma_post_atapi( qc); + + ap->hsm_task_state = HSM_ST_LAST; + break; + + default: + WARN_ON(1); + return AC_ERR_SYSTEM; + } + + return 0; +} + +void k2_sata_error_handler(struct ata_port *ap) +{ + k2_sata_port_info* pspi = (k2_sata_port_info*)ap->private_data; + + if( !pspi->is_atapi_device) + { + // let libata do all the hard work + ata_bmdma_error_handler( ap); + return; + } + + // if we have atapi then likely we used qdma and hung on that + // so we use our soft & hardresets + ata_bmdma_drive_eh(ap, ata_std_prereset, k2_ht1x_atapi_soft_reset, k2_ht1x_atapi_reset, + ata_std_postreset); + +} + +// ATAPI QDMA end + static struct scsi_host_template k2_sata_sht = { .module = THIS_MODULE, @@ -346,6 +1154,7 @@ static const struct ata_port_operations .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, .error_handler = ata_bmdma_error_handler, + .irq_handler = ata_interrupt, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_clear = ata_bmdma_irq_clear, .irq_on = ata_irq_on, @@ -355,8 +1164,42 @@ static const struct ata_port_operations .port_start = ata_port_start, }; +// ATAPI QDMA start + +static const struct ata_port_operations k2_ht1x_ops = { + .port_disable = ata_port_disable, + .tf_load = k2_sata_tf_load, + .tf_read = k2_sata_tf_read, + .check_status = k2_stat_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + .check_atapi_dma = k2_sata_check_atapi_dma, + .bmdma_setup = k2_bmdma_setup_mmio, + .bmdma_start = k2_bmdma_start_mmio, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = k2_ht1x_qc_issue_prot, + .data_xfer = ata_data_xfer, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = k2_sata_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .irq_handler = k2_ht1x_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .irq_on = ata_irq_on, + .irq_ack = ata_irq_ack, + .scr_read = k2_sata_scr_read, + .scr_write = k2_sata_scr_write, + .port_start = k2_ht1x_port_start, + .port_stop = k2_ht1x_port_stop, +}; + +// ATAPI QDMA end + + static const struct ata_port_info k2_port_info[] = { - /* board_svw4 */ + /* chip_svw4 */ { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA, @@ -365,7 +1208,7 @@ static const struct ata_port_info k2_por .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, - /* board_svw8 */ + /* chip_svw8 */ { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA | @@ -375,8 +1218,156 @@ static const struct ata_port_info k2_por .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, + /* chip_svwx */ + { + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = ATA_UDMA6, + .port_ops = &k2_ht1x_ops, + }, + /* chip_svw41 */ + { + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = ATA_UDMA6, + .port_ops = &k2_ht1x_ops, + }, + /* chip_svw42 */ + { + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = ATA_UDMA6, + .port_ops = &k2_sata_ops, + }, + /* chip_svw43 */ + { + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = ATA_UDMA6, + .port_ops = &k2_sata_ops, + }, }; +// HT1100 addns +inline void k2_lnx_sleep( u32 usec_delay) +{ + (usec_delay > 1000) ? mdelay(usec_delay/1000 + 1): udelay(usec_delay); +} + + +#define K2_SATA_WAIT_MDIO_DONE(reg) \ +{ \ + u32 tmp_reg, to = 1000; \ + while (to) { \ + tmp_reg = cpu_to_le32( readl(reg) ); \ + if (tmp_reg & (1 << 15)) { \ + break; \ + } \ + k2_lnx_sleep( 10); \ + to--; \ + } \ +} + +#define K2_IS_SATA_STS_GOOD(sata_sts) \ + (((sata_sts & K2_SATA_DET_MASK) == K2_DEV_DET_PHY_RDY) && (((sata_sts & K2_SATA_INTF_MASK)>>8) == K2_SATA_INFT_ACTIVE)) + + +inline void k2_sata_port_reset_phy_start_oob( void __iomem *mmio_port_base, u32 ul_satainitval) +{ + u32 oob_try = 0, sata_sts; + + writel( ul_satainitval, (mmio_port_base + K2_SATA_SATADBGREG) ); + k2_lnx_sleep( K2_SATA_RESET_PHY_DELAY); + + // Retry oob up to 5 times + do { + writel( K2_SATA_SCR2_RESET_PHY, (mmio_port_base + K2_SATA_SCR_CONTROL_OFFSET) ); + k2_lnx_sleep( K2_SATA_RESET_PHY_DELAY); + + writel( K2_SATA_SCR2_CLEAR_REG, (mmio_port_base + K2_SATA_SCR_CONTROL_OFFSET) ); + k2_lnx_sleep( K2_SATA_RESET_PHY_DELAY); + + sata_sts = readl( mmio_port_base + K2_SATA_SCR_STATUS_OFFSET); + } while ((!K2_IS_SATA_STS_GOOD(sata_sts)) && (++oob_try < 5)); + +} + + +inline void k2_sata_pll_init(void __iomem *mmio_base, u32 link_rate, u32 portnum) +{ + u32 ul_PortSelect=0; + u32 ul_initval, ul_voltval, mdioctrl; + + + /* MDIO access is accessible only through Port 0, so we take mmio base as input */ + + // Enable MDIO Space + writel( K2_SATA_TEST_CTRL_VALUE, ( mmio_base + K2_SATA_TESTCTRLREG) ); + k2_lnx_sleep( K2_SATA_PLL_WAIT); + + /* mdio reg: 31:16 - r/w data + * 15 - done + * 14:13 - r(10) w(01) + * 12:8 - device address + * 7:5 - res + * 4:0 - reg addr + */ + + // pll workaround + writel( 0x4002, (mmio_base + K2_SATA_MDIOCTRLREG)); + K2_SATA_WAIT_MDIO_DONE(mmio_base + K2_SATA_MDIOCTRLREG); + mdioctrl = readl( mmio_base + K2_SATA_MDIOCTRLREG) >> 16; + // clear bit 2 + mdioctrl &= ~0x04; + mdioctrl = mdioctrl << 16; + writel( mdioctrl | 0x2002, (mmio_base + K2_SATA_MDIOCTRLREG)); + K2_SATA_WAIT_MDIO_DONE(mmio_base + K2_SATA_MDIOCTRLREG); + + + ul_PortSelect = (((1 << portnum) << 16) | (0x2007)); + + if (link_rate == K2_SATA_PLL_1P5_GIG) + { + //550 mV (Main Driver), 0% pre-emphasis, 0% Bias for SATA 1.5G : voltval=0x7830 + ul_voltval = (BCM_SATA_PHY_TXCNT_1G5 << 16) | 0x200a; + ul_initval = (BCM_SATA_PHY_RXCNT_1G5 << 16) | 0x2008; + } + else + { + //750 mV (Main Driver), 20% pre-emphasis, 0% Bias for 3G : voltval=0xF620 + ul_voltval = (BCM_SATA_PHY_TXCNT_3G0 << 16) | 0x200a; + ul_initval = (BCM_SATA_PHY_RXCNT_3G0 << 16) | 0x2008; + } + + writel( ul_PortSelect, (mmio_base + K2_SATA_MDIOCTRLREG)); + K2_SATA_WAIT_MDIO_DONE(mmio_base + K2_SATA_MDIOCTRLREG); + + writel( ul_initval, (mmio_base + K2_SATA_MDIOCTRLREG)); + K2_SATA_WAIT_MDIO_DONE(mmio_base + K2_SATA_MDIOCTRLREG); + + writel( ul_voltval, (mmio_base + K2_SATA_MDIOCTRLREG)); + K2_SATA_WAIT_MDIO_DONE(mmio_base + K2_SATA_MDIOCTRLREG); + + // Disable MDIO Access + mdioctrl = readl( mmio_base + K2_SATA_TESTCTRLREG); + mdioctrl &= (~K2_SATA_TEST_CTRL_VALUE); + writel( mdioctrl | 0x01, (mmio_base + K2_SATA_TESTCTRLREG) ); + k2_lnx_sleep( K2_SATA_PLL_WAIT); + +} + +// HT1100 end + + + static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base) { port->cmd_addr = base + K2_SATA_TF_CMD_OFFSET; @@ -399,12 +1390,12 @@ static void k2_sata_setup_port(struct at static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version; + static int printed_version = 0; const struct ata_port_info *ppi[] = { &k2_port_info[ent->driver_data], NULL }; struct ata_host *host; void __iomem *mmio_base; - int n_ports, i, rc; + int n_ports, i, rc, bar_pos; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -418,6 +1409,10 @@ static int k2_sata_init_one (struct pci_ if (!host) return -ENOMEM; + bar_pos = 5; + if (ppi[0]->flags & K2_FLAG_BAR_POS_3) + bar_pos = 3; + /* * If this driver happens to only be useful on Apple's K2, then * we should check that here as it has a normal Serverworks ID @@ -430,25 +1425,51 @@ static int k2_sata_init_one (struct pci_ * Check if we have resources mapped at all (second function may * have been disabled by firmware) */ - if (pci_resource_len(pdev, 5) == 0) + if (pci_resource_len(pdev, bar_pos) == 0) return -ENODEV; /* Request and iomap PCI regions */ - rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); + // rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); + rc = pcim_iomap_regions(pdev, 1 << bar_pos, DRV_NAME); if (rc == -EBUSY) pcim_pin_device(pdev); if (rc) return rc; host->iomap = pcim_iomap_table(pdev); - mmio_base = host->iomap[5]; + mmio_base = host->iomap[bar_pos]; /* different controllers have different number of ports - currently 4 or 8 */ /* All ports are on the same function. Multi-function device is no * longer available. This should not be seen in any system. */ for (i = 0; i < host->n_ports; i++) + { +// HT1100 addns start + if( ent->device == 0x0410) + { + if( !skip_init) + { + // set mode, phy vals etc + // ht1100 needs a global phy enable bit, so we do that for port zero iteration + if( i == 0) + writel( readl( mmio_base + 0x10F0) | 0x01, (mmio_base + 0x10F0) ); + + k2_sata_pll_init( mmio_base, K2_SATA_PLL_1P5_GIG, i); + + k2_sata_port_reset_phy_start_oob( mmio_base + (i * K2_SATA_PORT_OFFSET), 0x10100 ); + + } + + writel( readl( mmio_base + (i * K2_SATA_PORT_OFFSET) + 0x84) | 0x2000f800, (mmio_base + (i * K2_SATA_PORT_OFFSET) + 0x84) ); + writel( readl( mmio_base + (i * K2_SATA_PORT_OFFSET) + 0xE0) | 0x2, (mmio_base + (i * K2_SATA_PORT_OFFSET) + 0xE0) ); + } +// HT1100 addns end + k2_sata_setup_port(&host->ports[i]->ioaddr, mmio_base + i * K2_SATA_PORT_OFFSET); + } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) return rc; @@ -468,7 +1489,7 @@ static int k2_sata_init_one (struct pci_ writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); pci_set_master(pdev); - return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, + return ata_host_activate(host, pdev->irq, ppi[0]->port_ops->irq_handler, IRQF_SHARED, &k2_sata_sht); } @@ -477,14 +1498,19 @@ static int k2_sata_init_one (struct pci_ * 0x242 is device ID for Serverworks Frodo8 * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA * controller + * 0x41x is device ID for HT1100 southbridge integrated SATA storage controller * */ static const struct pci_device_id k2_sata_pci_tbl[] = { - { PCI_VDEVICE(SERVERWORKS, 0x0240), board_svw4 }, - { PCI_VDEVICE(SERVERWORKS, 0x0241), board_svw4 }, - { PCI_VDEVICE(SERVERWORKS, 0x0242), board_svw8 }, - { PCI_VDEVICE(SERVERWORKS, 0x024a), board_svw4 }, - { PCI_VDEVICE(SERVERWORKS, 0x024b), board_svw4 }, - + { PCI_VDEVICE(SERVERWORKS, 0x0240), chip_svw4 }, + { PCI_VDEVICE(SERVERWORKS, 0x0241), chip_svw4 }, + { PCI_VDEVICE(SERVERWORKS, 0x0242), chip_svw8 }, +// ATAPI QDMA start + { PCI_VDEVICE(SERVERWORKS, 0x024a), chip_svw41 }, + { PCI_VDEVICE(SERVERWORKS, 0x024b), chip_svw41 }, + { PCI_VDEVICE(SERVERWORKS, 0x024c), chip_svw4 }, +// ATAPI QDMA end + { PCI_VDEVICE(SERVERWORKS, 0x0410), chip_svw42 }, + { PCI_VDEVICE(SERVERWORKS, 0x0411), chip_svw43 }, { } }; - To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html