2006-08-30 02:12:40 +04:00
/*
* Promise PATA TX2 / TX4 / TX2000 / 133 IDE driver for pdc20268 to pdc20277 .
*
* 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 .
*
* Ported to libata by :
* Albert Lee < albertcc @ tw . ibm . com > IBM Corporation
*
* Copyright ( C ) 1998 - 2002 Andre Hedrick < andre @ linux - ide . org >
* Portions Copyright ( C ) 1999 Promise Technology , Inc .
*
* Author : Frank Tiernan ( frankt @ promise . com )
* Released under terms of General Public License
*
*
* libata documentation is available via ' make { ps | pdf } docs ' ,
* as Documentation / DocBook / libata . *
*
* Hardware information only available under NDA .
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/init.h>
# include <linux/blkdev.h>
# include <linux/delay.h>
# include <linux/device.h>
# include <scsi/scsi.h>
# include <scsi/scsi_host.h>
# include <scsi/scsi_cmnd.h>
# include <linux/libata.h>
# include <asm/io.h>
# define DRV_NAME "pata_pdc2027x"
2006-09-26 20:53:38 +04:00
# define DRV_VERSION "0.74-ac5"
2006-08-30 02:12:40 +04:00
# undef PDC_DEBUG
# ifdef PDC_DEBUG
# define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
# else
# define PDPRINTK(fmt, args...)
# endif
enum {
PDC_UDMA_100 = 0 ,
PDC_UDMA_133 = 1 ,
PDC_100_MHZ = 100000000 ,
PDC_133_MHZ = 133333333 ,
PDC_SYS_CTL = 0x1100 ,
PDC_ATA_CTL = 0x1104 ,
PDC_GLOBAL_CTL = 0x1108 ,
PDC_CTCR0 = 0x110C ,
PDC_CTCR1 = 0x1110 ,
PDC_BYTE_COUNT = 0x1120 ,
PDC_PLL_CTL = 0x1202 ,
} ;
static int pdc2027x_init_one ( struct pci_dev * pdev , const struct pci_device_id * ent ) ;
static void pdc2027x_remove_one ( struct pci_dev * pdev ) ;
static void pdc2027x_error_handler ( struct ata_port * ap ) ;
static void pdc2027x_set_piomode ( struct ata_port * ap , struct ata_device * adev ) ;
static void pdc2027x_set_dmamode ( struct ata_port * ap , struct ata_device * adev ) ;
static void pdc2027x_post_set_mode ( struct ata_port * ap ) ;
static int pdc2027x_check_atapi_dma ( struct ata_queued_cmd * qc ) ;
/*
* ATA Timing Tables based on 133 MHz controller clock .
* These tables are only used when the controller is in 133 MHz clock .
* If the controller is in 100 MHz clock , the ASIC hardware will
* set the timing registers automatically when " set feature " command
* is issued to the device . However , if the controller clock is 133 MHz ,
* the following tables must be used .
*/
static struct pdc2027x_pio_timing {
u8 value0 , value1 , value2 ;
} pdc2027x_pio_timing_tbl [ ] = {
{ 0xfb , 0x2b , 0xac } , /* PIO mode 0 */
{ 0x46 , 0x29 , 0xa4 } , /* PIO mode 1 */
{ 0x23 , 0x26 , 0x64 } , /* PIO mode 2 */
{ 0x27 , 0x0d , 0x35 } , /* PIO mode 3, IORDY on, Prefetch off */
{ 0x23 , 0x09 , 0x25 } , /* PIO mode 4, IORDY on, Prefetch off */
} ;
static struct pdc2027x_mdma_timing {
u8 value0 , value1 ;
} pdc2027x_mdma_timing_tbl [ ] = {
{ 0xdf , 0x5f } , /* MDMA mode 0 */
{ 0x6b , 0x27 } , /* MDMA mode 1 */
{ 0x69 , 0x25 } , /* MDMA mode 2 */
} ;
static struct pdc2027x_udma_timing {
u8 value0 , value1 , value2 ;
} pdc2027x_udma_timing_tbl [ ] = {
{ 0x4a , 0x0f , 0xd5 } , /* UDMA mode 0 */
{ 0x3a , 0x0a , 0xd0 } , /* UDMA mode 1 */
{ 0x2a , 0x07 , 0xcd } , /* UDMA mode 2 */
{ 0x1a , 0x05 , 0xcd } , /* UDMA mode 3 */
{ 0x1a , 0x03 , 0xcd } , /* UDMA mode 4 */
{ 0x1a , 0x02 , 0xcb } , /* UDMA mode 5 */
{ 0x1a , 0x01 , 0xcb } , /* UDMA mode 6 */
} ;
static const struct pci_device_id pdc2027x_pci_tbl [ ] = {
2006-09-29 04:21:59 +04:00
{ PCI_VDEVICE ( PROMISE , PCI_DEVICE_ID_PROMISE_20268 ) , PDC_UDMA_100 } ,
{ PCI_VDEVICE ( PROMISE , PCI_DEVICE_ID_PROMISE_20269 ) , PDC_UDMA_133 } ,
{ PCI_VDEVICE ( PROMISE , PCI_DEVICE_ID_PROMISE_20270 ) , PDC_UDMA_100 } ,
{ PCI_VDEVICE ( PROMISE , PCI_DEVICE_ID_PROMISE_20271 ) , PDC_UDMA_133 } ,
{ PCI_VDEVICE ( PROMISE , PCI_DEVICE_ID_PROMISE_20275 ) , PDC_UDMA_133 } ,
{ PCI_VDEVICE ( PROMISE , PCI_DEVICE_ID_PROMISE_20276 ) , PDC_UDMA_133 } ,
{ PCI_VDEVICE ( PROMISE , PCI_DEVICE_ID_PROMISE_20277 ) , PDC_UDMA_133 } ,
2006-08-30 02:12:40 +04:00
{ } /* terminate list */
} ;
static struct pci_driver pdc2027x_pci_driver = {
. name = DRV_NAME ,
. id_table = pdc2027x_pci_tbl ,
. probe = pdc2027x_init_one ,
. remove = __devexit_p ( pdc2027x_remove_one ) ,
} ;
static struct scsi_host_template pdc2027x_sht = {
. module = THIS_MODULE ,
. name = DRV_NAME ,
. ioctl = ata_scsi_ioctl ,
. queuecommand = ata_scsi_queuecmd ,
. can_queue = ATA_DEF_QUEUE ,
. this_id = ATA_SHT_THIS_ID ,
. sg_tablesize = LIBATA_MAX_PRD ,
. cmd_per_lun = ATA_SHT_CMD_PER_LUN ,
. emulated = ATA_SHT_EMULATED ,
. use_clustering = ATA_SHT_USE_CLUSTERING ,
. proc_name = DRV_NAME ,
. dma_boundary = ATA_DMA_BOUNDARY ,
. slave_configure = ata_scsi_slave_config ,
2006-11-29 05:26:47 +03:00
. slave_destroy = ata_scsi_slave_destroy ,
2006-08-30 02:12:40 +04:00
. bios_param = ata_std_bios_param ,
} ;
static struct ata_port_operations pdc2027x_pata100_ops = {
. port_disable = ata_port_disable ,
. tf_load = ata_tf_load ,
. tf_read = ata_tf_read ,
. check_status = ata_check_status ,
. exec_command = ata_exec_command ,
. dev_select = ata_std_dev_select ,
. check_atapi_dma = pdc2027x_check_atapi_dma ,
. bmdma_setup = ata_bmdma_setup ,
. bmdma_start = ata_bmdma_start ,
. bmdma_stop = ata_bmdma_stop ,
. bmdma_status = ata_bmdma_status ,
. qc_prep = ata_qc_prep ,
. qc_issue = ata_qc_issue_prot ,
. data_xfer = ata_mmio_data_xfer ,
. freeze = ata_bmdma_freeze ,
. thaw = ata_bmdma_thaw ,
. error_handler = pdc2027x_error_handler ,
. post_internal_cmd = ata_bmdma_post_internal_cmd ,
. irq_handler = ata_interrupt ,
. irq_clear = ata_bmdma_irq_clear ,
. port_start = ata_port_start ,
. port_stop = ata_port_stop ,
. host_stop = ata_pci_host_stop ,
} ;
static struct ata_port_operations pdc2027x_pata133_ops = {
. port_disable = ata_port_disable ,
. set_piomode = pdc2027x_set_piomode ,
. set_dmamode = pdc2027x_set_dmamode ,
. post_set_mode = pdc2027x_post_set_mode ,
. tf_load = ata_tf_load ,
. tf_read = ata_tf_read ,
. check_status = ata_check_status ,
. exec_command = ata_exec_command ,
. dev_select = ata_std_dev_select ,
. check_atapi_dma = pdc2027x_check_atapi_dma ,
. bmdma_setup = ata_bmdma_setup ,
. bmdma_start = ata_bmdma_start ,
. bmdma_stop = ata_bmdma_stop ,
. bmdma_status = ata_bmdma_status ,
. qc_prep = ata_qc_prep ,
. qc_issue = ata_qc_issue_prot ,
. data_xfer = ata_mmio_data_xfer ,
. freeze = ata_bmdma_freeze ,
. thaw = ata_bmdma_thaw ,
. error_handler = pdc2027x_error_handler ,
. post_internal_cmd = ata_bmdma_post_internal_cmd ,
. irq_handler = ata_interrupt ,
. irq_clear = ata_bmdma_irq_clear ,
. port_start = ata_port_start ,
. port_stop = ata_port_stop ,
. host_stop = ata_pci_host_stop ,
} ;
static struct ata_port_info pdc2027x_port_info [ ] = {
/* PDC_UDMA_100 */
{
. sht = & pdc2027x_sht ,
. flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_MMIO ,
. pio_mask = 0x1f , /* pio0-4 */
. mwdma_mask = 0x07 , /* mwdma0-2 */
. udma_mask = ATA_UDMA5 , /* udma0-5 */
. port_ops = & pdc2027x_pata100_ops ,
} ,
/* PDC_UDMA_133 */
{
. sht = & pdc2027x_sht ,
. flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_MMIO ,
. pio_mask = 0x1f , /* pio0-4 */
. mwdma_mask = 0x07 , /* mwdma0-2 */
. udma_mask = ATA_UDMA6 , /* udma0-6 */
. port_ops = & pdc2027x_pata133_ops ,
} ,
} ;
MODULE_AUTHOR ( " Andre Hedrick, Frank Tiernan, Albert Lee " ) ;
MODULE_DESCRIPTION ( " libata driver module for Promise PDC20268 to PDC20277 " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_VERSION ( DRV_VERSION ) ;
MODULE_DEVICE_TABLE ( pci , pdc2027x_pci_tbl ) ;
/**
* port_mmio - Get the MMIO address of PDC2027x extended registers
* @ ap : Port
* @ offset : offset from mmio base
*/
2006-09-25 05:57:57 +04:00
static inline void __iomem * port_mmio ( struct ata_port * ap , unsigned int offset )
2006-08-30 02:12:40 +04:00
{
return ap - > host - > mmio_base + ap - > port_no * 0x100 + offset ;
}
/**
* dev_mmio - Get the MMIO address of PDC2027x extended registers
* @ ap : Port
* @ adev : device
* @ offset : offset from mmio base
*/
2006-09-25 05:57:57 +04:00
static inline void __iomem * dev_mmio ( struct ata_port * ap , struct ata_device * adev , unsigned int offset )
2006-08-30 02:12:40 +04:00
{
u8 adj = ( adev - > devno ) ? 0x08 : 0x00 ;
return port_mmio ( ap , offset ) + adj ;
}
/**
* pdc2027x_pata_cbl_detect - Probe host controller cable detect info
* @ ap : Port for which cable detect info is desired
*
* Read 80 c cable indicator from Promise extended register .
* This register is latched when the system is reset .
*
* LOCKING :
* None ( inherited from caller ) .
*/
static void pdc2027x_cbl_detect ( struct ata_port * ap )
{
u32 cgcr ;
/* check cable detect results */
cgcr = readl ( port_mmio ( ap , PDC_GLOBAL_CTL ) ) ;
if ( cgcr & ( 1 < < 26 ) )
goto cbl40 ;
PDPRINTK ( " No cable or 80-conductor cable on port %d \n " , ap - > port_no ) ;
ap - > cbl = ATA_CBL_PATA80 ;
return ;
cbl40 :
printk ( KERN_INFO DRV_NAME " : 40-conductor cable detected on port %d \n " , ap - > port_no ) ;
ap - > cbl = ATA_CBL_PATA40 ;
ap - > udma_mask & = ATA_UDMA_MASK_40C ;
}
/**
* pdc2027x_port_enabled - Check PDC ATA control register to see whether the port is enabled .
* @ ap : Port to check
*/
static inline int pdc2027x_port_enabled ( struct ata_port * ap )
{
return readb ( port_mmio ( ap , PDC_ATA_CTL ) ) & 0x02 ;
}
/**
* pdc2027x_prereset - prereset for PATA host controller
* @ ap : Target port
*
* Probeinit including cable detection .
*
* LOCKING :
* None ( inherited from caller ) .
*/
static int pdc2027x_prereset ( struct ata_port * ap )
{
/* Check whether port enabled */
2006-09-26 20:53:38 +04:00
if ( ! pdc2027x_port_enabled ( ap ) )
return - ENOENT ;
2006-08-30 02:12:40 +04:00
pdc2027x_cbl_detect ( ap ) ;
return ata_std_prereset ( ap ) ;
}
/**
* pdc2027x_error_handler - Perform reset on PATA port and classify
* @ ap : Port to reset
*
* Reset PATA phy and classify attached devices .
*
* LOCKING :
* None ( inherited from caller ) .
*/
static void pdc2027x_error_handler ( struct ata_port * ap )
{
ata_bmdma_drive_eh ( ap , pdc2027x_prereset , ata_std_softreset , NULL , ata_std_postreset ) ;
}
/**
* pdc2027x_set_piomode - Initialize host controller PATA PIO timings
* @ ap : Port to configure
* @ adev : um
* @ pio : PIO mode , 0 - 4
*
* Set PIO mode for device .
*
* LOCKING :
* None ( inherited from caller ) .
*/
static void pdc2027x_set_piomode ( struct ata_port * ap , struct ata_device * adev )
{
unsigned int pio = adev - > pio_mode - XFER_PIO_0 ;
u32 ctcr0 , ctcr1 ;
PDPRINTK ( " adev->pio_mode[%X] \n " , adev - > pio_mode ) ;
/* Sanity check */
if ( pio > 4 ) {
printk ( KERN_ERR DRV_NAME " : Unknown pio mode [%d] ignored \n " , pio ) ;
return ;
}
/* Set the PIO timing registers using value table for 133MHz */
PDPRINTK ( " Set pio regs... \n " ) ;
ctcr0 = readl ( dev_mmio ( ap , adev , PDC_CTCR0 ) ) ;
ctcr0 & = 0xffff0000 ;
ctcr0 | = pdc2027x_pio_timing_tbl [ pio ] . value0 |
( pdc2027x_pio_timing_tbl [ pio ] . value1 < < 8 ) ;
writel ( ctcr0 , dev_mmio ( ap , adev , PDC_CTCR0 ) ) ;
ctcr1 = readl ( dev_mmio ( ap , adev , PDC_CTCR1 ) ) ;
ctcr1 & = 0x00ffffff ;
ctcr1 | = ( pdc2027x_pio_timing_tbl [ pio ] . value2 < < 24 ) ;
writel ( ctcr1 , dev_mmio ( ap , adev , PDC_CTCR1 ) ) ;
PDPRINTK ( " Set pio regs done \n " ) ;
PDPRINTK ( " Set to pio mode[%u] \n " , pio ) ;
}
/**
* pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings
* @ ap : Port to configure
* @ adev : um
* @ udma : udma mode , XFER_UDMA_0 to XFER_UDMA_6
*
* Set UDMA mode for device .
*
* LOCKING :
* None ( inherited from caller ) .
*/
static void pdc2027x_set_dmamode ( struct ata_port * ap , struct ata_device * adev )
{
unsigned int dma_mode = adev - > dma_mode ;
u32 ctcr0 , ctcr1 ;
if ( ( dma_mode > = XFER_UDMA_0 ) & &
( dma_mode < = XFER_UDMA_6 ) ) {
/* Set the UDMA timing registers with value table for 133MHz */
unsigned int udma_mode = dma_mode & 0x07 ;
if ( dma_mode = = XFER_UDMA_2 ) {
/*
* Turn off tHOLD .
* If tHOLD is ' 1 ' , the hardware will add half clock for data hold time .
* This code segment seems to be no effect . tHOLD will be overwritten below .
*/
ctcr1 = readl ( dev_mmio ( ap , adev , PDC_CTCR1 ) ) ;
writel ( ctcr1 & ~ ( 1 < < 7 ) , dev_mmio ( ap , adev , PDC_CTCR1 ) ) ;
}
PDPRINTK ( " Set udma regs... \n " ) ;
ctcr1 = readl ( dev_mmio ( ap , adev , PDC_CTCR1 ) ) ;
ctcr1 & = 0xff000000 ;
ctcr1 | = pdc2027x_udma_timing_tbl [ udma_mode ] . value0 |
( pdc2027x_udma_timing_tbl [ udma_mode ] . value1 < < 8 ) |
( pdc2027x_udma_timing_tbl [ udma_mode ] . value2 < < 16 ) ;
writel ( ctcr1 , dev_mmio ( ap , adev , PDC_CTCR1 ) ) ;
PDPRINTK ( " Set udma regs done \n " ) ;
PDPRINTK ( " Set to udma mode[%u] \n " , udma_mode ) ;
} else if ( ( dma_mode > = XFER_MW_DMA_0 ) & &
( dma_mode < = XFER_MW_DMA_2 ) ) {
/* Set the MDMA timing registers with value table for 133MHz */
unsigned int mdma_mode = dma_mode & 0x07 ;
PDPRINTK ( " Set mdma regs... \n " ) ;
ctcr0 = readl ( dev_mmio ( ap , adev , PDC_CTCR0 ) ) ;
ctcr0 & = 0x0000ffff ;
ctcr0 | = ( pdc2027x_mdma_timing_tbl [ mdma_mode ] . value0 < < 16 ) |
( pdc2027x_mdma_timing_tbl [ mdma_mode ] . value1 < < 24 ) ;
writel ( ctcr0 , dev_mmio ( ap , adev , PDC_CTCR0 ) ) ;
PDPRINTK ( " Set mdma regs done \n " ) ;
PDPRINTK ( " Set to mdma mode[%u] \n " , mdma_mode ) ;
} else {
printk ( KERN_ERR DRV_NAME " : Unknown dma mode [%u] ignored \n " , dma_mode ) ;
}
}
/**
* pdc2027x_post_set_mode - Set the timing registers back to correct values .
* @ ap : Port to configure
*
* The pdc2027x hardware will look at " SET FEATURES " and change the timing registers
* automatically . The values set by the hardware might be incorrect , under 133 Mhz PLL .
* This function overwrites the possibly incorrect values set by the hardware to be correct .
*/
static void pdc2027x_post_set_mode ( struct ata_port * ap )
{
int i ;
for ( i = 0 ; i < ATA_MAX_DEVICES ; i + + ) {
struct ata_device * dev = & ap - > device [ i ] ;
if ( ata_dev_enabled ( dev ) ) {
pdc2027x_set_piomode ( ap , dev ) ;
/*
* Enable prefetch if the device support PIO only .
*/
if ( dev - > xfer_shift = = ATA_SHIFT_PIO ) {
u32 ctcr1 = readl ( dev_mmio ( ap , dev , PDC_CTCR1 ) ) ;
ctcr1 | = ( 1 < < 25 ) ;
writel ( ctcr1 , dev_mmio ( ap , dev , PDC_CTCR1 ) ) ;
PDPRINTK ( " Turn on prefetch \n " ) ;
} else {
pdc2027x_set_dmamode ( ap , dev ) ;
}
}
}
}
/**
* pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command
* @ qc : Metadata associated with taskfile to check
*
* LOCKING :
* None ( inherited from caller ) .
*
* RETURNS : 0 when ATAPI DMA can be used
* 1 otherwise
*/
static int pdc2027x_check_atapi_dma ( struct ata_queued_cmd * qc )
{
struct scsi_cmnd * cmd = qc - > scsicmd ;
u8 * scsicmd = cmd - > cmnd ;
int rc = 1 ; /* atapi dma off by default */
/*
* This workaround is from Promise ' s GPL driver .
* If ATAPI DMA is used for commands not in the
* following white list , say MODE_SENSE and REQUEST_SENSE ,
* pdc2027x might hit the irq lost problem .
*/
switch ( scsicmd [ 0 ] ) {
case READ_10 :
case WRITE_10 :
case READ_12 :
case WRITE_12 :
case READ_6 :
case WRITE_6 :
case 0xad : /* READ_DVD_STRUCTURE */
case 0xbe : /* READ_CD */
/* ATAPI DMA is ok */
rc = 0 ;
break ;
default :
;
}
return rc ;
}
/**
* pdc_read_counter - Read the ctr counter
* @ probe_ent : for the port address
*/
static long pdc_read_counter ( struct ata_probe_ent * probe_ent )
{
long counter ;
int retry = 1 ;
u32 bccrl , bccrh , bccrlv , bccrhv ;
retry :
bccrl = readl ( probe_ent - > mmio_base + PDC_BYTE_COUNT ) & 0xffff ;
bccrh = readl ( probe_ent - > mmio_base + PDC_BYTE_COUNT + 0x100 ) & 0xffff ;
rmb ( ) ;
/* Read the counter values again for verification */
bccrlv = readl ( probe_ent - > mmio_base + PDC_BYTE_COUNT ) & 0xffff ;
bccrhv = readl ( probe_ent - > mmio_base + PDC_BYTE_COUNT + 0x100 ) & 0xffff ;
rmb ( ) ;
counter = ( bccrh < < 15 ) | bccrl ;
PDPRINTK ( " bccrh [%X] bccrl [%X] \n " , bccrh , bccrl ) ;
PDPRINTK ( " bccrhv[%X] bccrlv[%X] \n " , bccrhv , bccrlv ) ;
/*
* The 30 - bit decreasing counter are read by 2 pieces .
* Incorrect value may be read when both bccrh and bccrl are changing .
* Ex . When 7900 decrease to 78FF , wrong value 7800 might be read .
*/
if ( retry & & ! ( bccrh = = bccrhv & & bccrl > = bccrlv ) ) {
retry - - ;
PDPRINTK ( " rereading counter \n " ) ;
goto retry ;
}
return counter ;
}
/**
* adjust_pll - Adjust the PLL input clock in Hz .
*
* @ pdc_controller : controller specific information
* @ probe_ent : For the port address
* @ pll_clock : The input of PLL in HZ
*/
static void pdc_adjust_pll ( struct ata_probe_ent * probe_ent , long pll_clock , unsigned int board_idx )
{
u16 pll_ctl ;
long pll_clock_khz = pll_clock / 1000 ;
long pout_required = board_idx ? PDC_133_MHZ : PDC_100_MHZ ;
long ratio = pout_required / pll_clock_khz ;
int F , R ;
/* Sanity check */
if ( unlikely ( pll_clock_khz < 5000L | | pll_clock_khz > 70000L ) ) {
printk ( KERN_ERR DRV_NAME " : Invalid PLL input clock %ldkHz, give up! \n " , pll_clock_khz ) ;
return ;
}
# ifdef PDC_DEBUG
PDPRINTK ( " pout_required is %ld \n " , pout_required ) ;
/* Show the current clock value of PLL control register
* ( maybe already configured by the firmware )
*/
pll_ctl = readw ( probe_ent - > mmio_base + PDC_PLL_CTL ) ;
PDPRINTK ( " pll_ctl[%X] \n " , pll_ctl ) ;
# endif
/*
* Calculate the ratio of F , R and OD
* POUT = ( F + 2 ) / ( ( R + 2 ) * NO )
*/
if ( ratio < 8600L ) { /* 8.6x */
/* Using NO = 0x01, R = 0x0D */
R = 0x0d ;
} else if ( ratio < 12900L ) { /* 12.9x */
/* Using NO = 0x01, R = 0x08 */
R = 0x08 ;
} else if ( ratio < 16100L ) { /* 16.1x */
/* Using NO = 0x01, R = 0x06 */
R = 0x06 ;
} else if ( ratio < 64000L ) { /* 64x */
R = 0x00 ;
} else {
/* Invalid ratio */
printk ( KERN_ERR DRV_NAME " : Invalid ratio %ld, give up! \n " , ratio ) ;
return ;
}
F = ( ratio * ( R + 2 ) ) / 1000 - 2 ;
if ( unlikely ( F < 0 | | F > 127 ) ) {
/* Invalid F */
printk ( KERN_ERR DRV_NAME " : F[%d] invalid! \n " , F ) ;
return ;
}
PDPRINTK ( " F[%d] R[%d] ratio*1000[%ld] \n " , F , R , ratio ) ;
pll_ctl = ( R < < 8 ) | F ;
PDPRINTK ( " Writing pll_ctl[%X] \n " , pll_ctl ) ;
writew ( pll_ctl , probe_ent - > mmio_base + PDC_PLL_CTL ) ;
readw ( probe_ent - > mmio_base + PDC_PLL_CTL ) ; /* flush */
/* Wait the PLL circuit to be stable */
mdelay ( 30 ) ;
# ifdef PDC_DEBUG
/*
* Show the current clock value of PLL control register
* ( maybe configured by the firmware )
*/
pll_ctl = readw ( probe_ent - > mmio_base + PDC_PLL_CTL ) ;
PDPRINTK ( " pll_ctl[%X] \n " , pll_ctl ) ;
# endif
return ;
}
/**
* detect_pll_input_clock - Detect the PLL input clock in Hz .
* @ probe_ent : for the port address
* Ex . 16949000 on 33 MHz PCI bus for pdc20275 .
* Half of the PCI clock .
*/
static long pdc_detect_pll_input_clock ( struct ata_probe_ent * probe_ent )
{
u32 scr ;
long start_count , end_count ;
long pll_clock ;
/* Read current counter value */
start_count = pdc_read_counter ( probe_ent ) ;
/* Start the test mode */
scr = readl ( probe_ent - > mmio_base + PDC_SYS_CTL ) ;
PDPRINTK ( " scr[%X] \n " , scr ) ;
writel ( scr | ( 0x01 < < 14 ) , probe_ent - > mmio_base + PDC_SYS_CTL ) ;
readl ( probe_ent - > mmio_base + PDC_SYS_CTL ) ; /* flush */
/* Let the counter run for 100 ms. */
mdelay ( 100 ) ;
/* Read the counter values again */
end_count = pdc_read_counter ( probe_ent ) ;
/* Stop the test mode */
scr = readl ( probe_ent - > mmio_base + PDC_SYS_CTL ) ;
PDPRINTK ( " scr[%X] \n " , scr ) ;
writel ( scr & ~ ( 0x01 < < 14 ) , probe_ent - > mmio_base + PDC_SYS_CTL ) ;
readl ( probe_ent - > mmio_base + PDC_SYS_CTL ) ; /* flush */
/* calculate the input clock in Hz */
pll_clock = ( start_count - end_count ) * 10 ;
PDPRINTK ( " start[%ld] end[%ld] \n " , start_count , end_count ) ;
PDPRINTK ( " PLL input clock[%ld]Hz \n " , pll_clock ) ;
return pll_clock ;
}
/**
* pdc_hardware_init - Initialize the hardware .
* @ pdev : instance of pci_dev found
* @ pdc_controller : controller specific information
* @ pe : for the port address
*/
static int pdc_hardware_init ( struct pci_dev * pdev , struct ata_probe_ent * pe , unsigned int board_idx )
{
long pll_clock ;
/*
* Detect PLL input clock rate .
* On some system , where PCI bus is running at non - standard clock rate .
* Ex . 25 MHz or 40 MHz , we have to adjust the cycle_time .
* The pdc20275 controller employs PLL circuit to help correct timing registers setting .
*/
pll_clock = pdc_detect_pll_input_clock ( pe ) ;
if ( pll_clock < 0 ) /* counter overflow? Try again. */
pll_clock = pdc_detect_pll_input_clock ( pe ) ;
dev_printk ( KERN_INFO , & pdev - > dev , " PLL input clock %ld kHz \n " , pll_clock / 1000 ) ;
/* Adjust PLL control register */
pdc_adjust_pll ( pe , pll_clock , board_idx ) ;
return 0 ;
}
/**
* pdc_ata_setup_port - setup the mmio address
* @ port : ata ioports to setup
* @ base : base address
*/
static void pdc_ata_setup_port ( struct ata_ioports * port , unsigned long base )
{
port - > cmd_addr =
port - > data_addr = base ;
port - > feature_addr =
port - > error_addr = base + 0x05 ;
port - > nsect_addr = base + 0x0a ;
port - > lbal_addr = base + 0x0f ;
port - > lbam_addr = base + 0x10 ;
port - > lbah_addr = base + 0x15 ;
port - > device_addr = base + 0x1a ;
port - > command_addr =
port - > status_addr = base + 0x1f ;
port - > altstatus_addr =
port - > ctl_addr = base + 0x81a ;
}
/**
* pdc2027x_init_one - PCI probe function
* Called when an instance of PCI adapter is inserted .
* This function checks whether the hardware is supported ,
* initialize hardware and register an instance of ata_host to
* libata by providing struct ata_probe_ent and ata_device_add ( ) .
* ( implements struct pci_driver . probe ( ) )
*
* @ pdev : instance of pci_dev found
* @ ent : matching entry in the id_tbl [ ]
*/
static int __devinit pdc2027x_init_one ( struct pci_dev * pdev , const struct pci_device_id * ent )
{
static int printed_version ;
unsigned int board_idx = ( unsigned int ) ent - > driver_data ;
struct ata_probe_ent * probe_ent = NULL ;
unsigned long base ;
2006-09-25 05:57:57 +04:00
void __iomem * mmio_base ;
2006-08-30 02:12:40 +04:00
int rc ;
if ( ! printed_version + + )
dev_printk ( KERN_DEBUG , & pdev - > dev , " version " DRV_VERSION " \n " ) ;
rc = pci_enable_device ( pdev ) ;
if ( rc )
return rc ;
rc = pci_request_regions ( pdev , DRV_NAME ) ;
if ( rc )
goto err_out ;
rc = pci_set_dma_mask ( pdev , ATA_DMA_MASK ) ;
if ( rc )
goto err_out_regions ;
rc = pci_set_consistent_dma_mask ( pdev , ATA_DMA_MASK ) ;
if ( rc )
goto err_out_regions ;
/* Prepare the probe entry */
probe_ent = kzalloc ( sizeof ( * probe_ent ) , GFP_KERNEL ) ;
if ( probe_ent = = NULL ) {
rc = - ENOMEM ;
goto err_out_regions ;
}
probe_ent - > dev = pci_dev_to_dev ( pdev ) ;
INIT_LIST_HEAD ( & probe_ent - > node ) ;
mmio_base = pci_iomap ( pdev , 5 , 0 ) ;
if ( ! mmio_base ) {
rc = - ENOMEM ;
goto err_out_free_ent ;
}
base = ( unsigned long ) mmio_base ;
probe_ent - > sht = pdc2027x_port_info [ board_idx ] . sht ;
probe_ent - > port_flags = pdc2027x_port_info [ board_idx ] . flags ;
probe_ent - > pio_mask = pdc2027x_port_info [ board_idx ] . pio_mask ;
probe_ent - > mwdma_mask = pdc2027x_port_info [ board_idx ] . mwdma_mask ;
probe_ent - > udma_mask = pdc2027x_port_info [ board_idx ] . udma_mask ;
probe_ent - > port_ops = pdc2027x_port_info [ board_idx ] . port_ops ;
probe_ent - > irq = pdev - > irq ;
probe_ent - > irq_flags = SA_SHIRQ ;
probe_ent - > mmio_base = mmio_base ;
pdc_ata_setup_port ( & probe_ent - > port [ 0 ] , base + 0x17c0 ) ;
probe_ent - > port [ 0 ] . bmdma_addr = base + 0x1000 ;
pdc_ata_setup_port ( & probe_ent - > port [ 1 ] , base + 0x15c0 ) ;
probe_ent - > port [ 1 ] . bmdma_addr = base + 0x1008 ;
probe_ent - > n_ports = 2 ;
pci_set_master ( pdev ) ;
//pci_enable_intx(pdev);
/* initialize adapter */
if ( pdc_hardware_init ( pdev , probe_ent , board_idx ) ! = 0 )
goto err_out_free_ent ;
ata_device_add ( probe_ent ) ;
kfree ( probe_ent ) ;
return 0 ;
err_out_free_ent :
kfree ( probe_ent ) ;
err_out_regions :
pci_release_regions ( pdev ) ;
err_out :
pci_disable_device ( pdev ) ;
return rc ;
}
/**
* pdc2027x_remove_one - Called to remove a single instance of the
* adapter .
*
* @ dev : The PCI device to remove .
* FIXME : module load / unload not working yet
*/
static void __devexit pdc2027x_remove_one ( struct pci_dev * pdev )
{
ata_pci_remove_one ( pdev ) ;
}
/**
* pdc2027x_init - Called after this module is loaded into the kernel .
*/
static int __init pdc2027x_init ( void )
{
2006-10-11 01:29:24 +04:00
return pci_register_driver ( & pdc2027x_pci_driver ) ;
2006-08-30 02:12:40 +04:00
}
/**
* pdc2027x_exit - Called before this module unloaded from the kernel
*/
static void __exit pdc2027x_exit ( void )
{
pci_unregister_driver ( & pdc2027x_pci_driver ) ;
}
module_init ( pdc2027x_init ) ;
module_exit ( pdc2027x_exit ) ;