2009-01-06 19:21:01 +03:00
/*
*
* BRIEF MODULE DESCRIPTION
* IT8172 IDE controller support
*
* Copyright ( C ) 2000 MontaVista Software Inc .
* Copyright ( C ) 2008 Shane McDonald
*
* 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 .
*
* THIS SOFTWARE IS PROVIDED ` ` 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 .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/ioport.h>
# include <linux/pci.h>
# include <linux/ide.h>
# include <linux/init.h>
# define DRV_NAME "IT8172"
2010-01-19 12:44:41 +03:00
static void it8172_set_pio_mode ( ide_hwif_t * hwif , ide_drive_t * drive )
2009-01-06 19:21:01 +03:00
{
struct pci_dev * dev = to_pci_dev ( hwif - > dev ) ;
u16 drive_enables ;
u32 drive_timing ;
2010-01-19 12:44:41 +03:00
const u8 pio = drive - > pio_mode - XFER_PIO_0 ;
2009-01-06 19:21:01 +03:00
/*
* The highest value of DIOR / DIOW pulse width and recovery time
* that can be set in the IT8172 is 8 PCI clock cycles . As a result ,
* it cannot be configured for PIO mode 0. This table sets these
* parameters to the maximum supported by the IT8172 .
*/
static const u8 timings [ ] = { 0x3f , 0x3c , 0x1b , 0x12 , 0x0a } ;
pci_read_config_word ( dev , 0x40 , & drive_enables ) ;
pci_read_config_dword ( dev , 0x44 , & drive_timing ) ;
/*
* Enable port 0x44 . The IT8172 spec is confused ; it calls
* this register the " Slave IDE Timing Register " , but in fact ,
* it controls timing for both master and slave drives .
*/
drive_enables | = 0x4000 ;
drive_enables & = drive - > dn ? 0xc006 : 0xc060 ;
if ( drive - > media = = ide_disk )
/* enable prefetch */
drive_enables | = 0x0004 < < ( drive - > dn * 4 ) ;
2009-06-15 20:52:53 +04:00
if ( ide_pio_need_iordy ( drive , pio ) )
2009-01-06 19:21:01 +03:00
/* enable IORDY sample-point */
drive_enables | = 0x0002 < < ( drive - > dn * 4 ) ;
drive_timing & = drive - > dn ? 0x00003f00 : 0x000fc000 ;
drive_timing | = timings [ pio ] < < ( drive - > dn * 6 + 8 ) ;
pci_write_config_word ( dev , 0x40 , drive_enables ) ;
pci_write_config_dword ( dev , 0x44 , drive_timing ) ;
}
2010-01-19 12:45:29 +03:00
static void it8172_set_dma_mode ( ide_hwif_t * hwif , ide_drive_t * drive )
2009-01-06 19:21:01 +03:00
{
struct pci_dev * dev = to_pci_dev ( hwif - > dev ) ;
int a_speed = 3 < < ( drive - > dn * 4 ) ;
int u_flag = 1 < < drive - > dn ;
int u_speed = 0 ;
u8 reg48 , reg4a ;
2010-01-19 12:45:29 +03:00
const u8 speed = drive - > dma_mode ;
2009-01-06 19:21:01 +03:00
pci_read_config_byte ( dev , 0x48 , & reg48 ) ;
pci_read_config_byte ( dev , 0x4a , & reg4a ) ;
if ( speed > = XFER_UDMA_0 ) {
u8 udma = speed - XFER_UDMA_0 ;
u_speed = udma < < ( drive - > dn * 4 ) ;
pci_write_config_byte ( dev , 0x48 , reg48 | u_flag ) ;
reg4a & = ~ a_speed ;
pci_write_config_byte ( dev , 0x4a , reg4a | u_speed ) ;
} else {
const u8 mwdma_to_pio [ ] = { 0 , 3 , 4 } ;
pci_write_config_byte ( dev , 0x48 , reg48 & ~ u_flag ) ;
pci_write_config_byte ( dev , 0x4a , reg4a & ~ a_speed ) ;
2010-01-19 12:44:41 +03:00
drive - > pio_mode =
mwdma_to_pio [ speed - XFER_MW_DMA_0 ] + XFER_PIO_0 ;
2009-01-06 19:21:01 +03:00
2010-01-19 12:44:41 +03:00
it8172_set_pio_mode ( hwif , drive ) ;
2009-01-06 19:21:01 +03:00
}
}
static const struct ide_port_ops it8172_port_ops = {
. set_pio_mode = it8172_set_pio_mode ,
. set_dma_mode = it8172_set_dma_mode ,
} ;
2012-12-22 01:21:03 +04:00
static const struct ide_port_info it8172_port_info = {
2009-01-06 19:21:01 +03:00
. name = DRV_NAME ,
. port_ops = & it8172_port_ops ,
. enablebits = { { 0x41 , 0x80 , 0x80 } , { 0x00 , 0x00 , 0x00 } } ,
. host_flags = IDE_HFLAG_SINGLE ,
. pio_mask = ATA_PIO4 & ~ ATA_PIO0 ,
. mwdma_mask = ATA_MWDMA2 ,
. udma_mask = ATA_UDMA2 ,
} ;
2012-12-22 01:21:03 +04:00
static int it8172_init_one ( struct pci_dev * dev , const struct pci_device_id * id )
2009-01-06 19:21:01 +03:00
{
if ( ( dev - > class > > 8 ) ! = PCI_CLASS_STORAGE_IDE )
return - ENODEV ; /* IT8172 is more than an IDE controller */
return ide_pci_init_one ( dev , & it8172_port_info , NULL ) ;
}
static struct pci_device_id it8172_pci_tbl [ ] = {
{ PCI_VDEVICE ( ITE , PCI_DEVICE_ID_ITE_8172 ) , 0 } ,
{ 0 , } ,
} ;
MODULE_DEVICE_TABLE ( pci , it8172_pci_tbl ) ;
static struct pci_driver it8172_pci_driver = {
. name = " IT8172_IDE " ,
. id_table = it8172_pci_tbl ,
. probe = it8172_init_one ,
. remove = ide_pci_remove ,
. suspend = ide_pci_suspend ,
. resume = ide_pci_resume ,
} ;
static int __init it8172_ide_init ( void )
{
return ide_pci_register_driver ( & it8172_pci_driver ) ;
}
static void __exit it8172_ide_exit ( void )
{
pci_unregister_driver ( & it8172_pci_driver ) ;
}
module_init ( it8172_ide_init ) ;
module_exit ( it8172_ide_exit ) ;
MODULE_AUTHOR ( " Steve Longerbeam " ) ;
MODULE_DESCRIPTION ( " PCI driver module for ITE 8172 IDE " ) ;
MODULE_LICENSE ( " GPL " ) ;