sata_via: load DEVICE register when CTL changes
PATCH 1/2 sata_via: load DEVICE register when CTL changes
VIA controllers clear DEVICE register when IEN changes. Make sure DEVICE is updated along with CTL.
This change is separated from Joseph Chan's larger patch.
http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640
---
These two patches are on top of
linus#master
+ [1] libata-eh-fix-slave-link-EH-action-mask-handling
+ [2] libata-transfer-EHI-control-flags-to-slave-ehc_i
+ [3] libata-set-device-class-to-NONE-if-phys_offline
[1] http://article.gmane.org/gmane.linux.ide/35390
[2] http://article.gmane.org/gmane.linux.ide/35393
[3] http://article.gmane.org/gmane.linux.ide/35436
and finally gets vt8251 working. I'll integrate this into the separate-sff-bmdma git tree. :-)
drivers/ata/sata_via.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-)
drivers/ata/sata_via.c +32 -3
@@ -70,6 +70,7 @@ enum {static int svia_init_one (struct pci_dev *pdev,const struct pci_device_id *ent);static int svia_scr_read (struct ata_link *link,unsigned int sc_reg,u32 *val);static int svia_scr_write (struct ata_link *link,unsigned int sc_reg,u32 val); +static void svia_tf_load (struct ata_port *ap,const struct ata_taskfile *tf);static void svia_noop_freeze (struct ata_port *ap);static int vt6420_prereset (struct ata_link *link,unsigned long deadline);static int vt6421_pata_cable_detect (struct ata_port *ap);
@@ -103,21 +104,26 @@ static struct scsi_host_template svia_sh ATA_BMDMA_SHT(DRV_NAME), }; -static struct ata_port_operations vt6420_sata_ops = { +static struct ata_port_operations svia_base_ops = { .inherits = &ata_bmdma_port_ops, + .sff_tf_load = svia_tf_load, +}; + +static struct ata_port_operations vt6420_sata_ops = { + .inherits = &svia_base_ops, .freeze = svia_noop_freeze, .prereset = vt6420_prereset, };static struct ata_port_operations vt6421_pata_ops = { - .inherits = &ata_bmdma_port_ops, + .inherits = &svia_base_ops, .cable_detect = vt6421_pata_cable_detect, .set_piomode = vt6421_set_pio_mode, .set_dmamode = vt6421_set_dma_mode, };static struct ata_port_operations vt6421_sata_ops = { - .inherits = &ata_bmdma_port_ops, + .inherits = &svia_base_ops, .scr_read = svia_scr_read, .scr_write = svia_scr_write, };
@@ -168,6 +174,29 @@ static int svia_scr_write(struct ata_linreturn 0 ; } +/** +* svia_tf_load - send taskfile registers to host controller +* @ap: Port to which output is sent +* @tf: ATA taskfile register set +* +* Outputs ATA taskfile to standard ATA host controller. +* +* This is to fix the internal bug of via chipsets, which will +* reset the device register after changing the IEN bit on ctl +* register. +*/ +static void svia_tf_load (struct ata_port *ap,const struct ata_taskfile *tf) +{ +struct ata_taskfile ttf; + +if (tf->ctl != ap->last_ctl) { + ttf = *tf; + ttf.flags |=ATA_TFLAG_DEVICE ; + tf = &ttf; + } +ata_sff_tf_load (ap, tf); +} +static void svia_noop_freeze (struct ata_port *ap) {/* Some VIA controllers choke if ATA_NIEN is manipulated in
PATCH 1/2 sata_via: fix support for 5287
5287 used to be treated as vt6420 but it didn't work. It's new family of controllers called vt8251 which hosts four SATA ports as M/S of the two ATA ports. This configuration is rather peculiar in that although the M/S devices are on the same port, each have its own SCR (or equivalent link status/control) registers which screws up the port-link-device hierarchy assumed by libata. Another controller which falls into this category is ata_piix w/ SIDPR access.
libata now has facility to deal with this class of controllers named slave_link. A low level driver for such controllers can just call ata_slave_link_init() on the respective ports and libata will handle all the difficult parts like following up with single SRST after hardresetting both ports.
This patch creates new controller class vt8251, implements slave_link aware init sequence and config space based SCR access for it and moves 5287 to the new class.
This patch is based on Joseph Chan's larger patch which was created before slave_link was implemented in libata.
http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640
--- drivers/ata/sata_via.c | 155 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 12 deletions(-)
drivers/ata/sata_via.c +143 -12
@@ -44,11 +44,16 @@#include <linux/libata.h> #define DRV_NAME "sata_via" -#define DRV_VERSION "2.3" +#define DRV_VERSION "2.4" +/* +* vt8251 is different from other sata controllers of VIA. It has two +* channels, each channel has both Master and Slave slot. +*/ enum board_ids_enum { vt6420, vt6421, + vt8251, };enum {
@@ -70,6 +75,8 @@ enum {static int svia_init_one (struct pci_dev *pdev,const struct pci_device_id *ent);static int svia_scr_read (struct ata_link *link,unsigned int sc_reg,u32 *val);static int svia_scr_write (struct ata_link *link,unsigned int sc_reg,u32 val); +static int vt8251_scr_read (struct ata_link *link,unsigned int scr,u32 *val); +static int vt8251_scr_write (struct ata_link *link,unsigned int scr,u32 val);static void svia_tf_load (struct ata_port *ap,const struct ata_taskfile *tf);static void svia_noop_freeze (struct ata_port *ap);static int vt6420_prereset (struct ata_link *link,unsigned long deadline);
@@ -79,12 +86,12 @@ static void vt6421_set_dma_mode(struct astatic const struct pci_device_id svia_pci_tbl[] = { {PCI_VDEVICE (VIA ,0x5337 ), vt6420 }, - {PCI_VDEVICE (VIA ,0x0591 ), vt6420 }, - {PCI_VDEVICE (VIA ,0x3149 ), vt6420 }, - {PCI_VDEVICE (VIA ,0x3249 ), vt6421 }, - {PCI_VDEVICE (VIA ,0x5287 ), vt6420 }, + {PCI_VDEVICE (VIA ,0x0591 ), vt6420 },/* 2 sata chnls (Master) */ + {PCI_VDEVICE (VIA ,0x3149 ), vt6420 },/* 2 sata chnls (Master) */ + {PCI_VDEVICE (VIA ,0x3249 ), vt6421 },/* 2 sata chnls, 1 pata chnl */ {PCI_VDEVICE (VIA ,0x5372 ), vt6420 }, {PCI_VDEVICE (VIA ,0x7372 ), vt6420 }, + {PCI_VDEVICE (VIA ,0x5287 ), vt8251 },/* 2 sata chnls (Master/Slave) */ { }/* terminate list */ };
@@ -128,6 +135,13 @@ static struct ata_port_operations vt6421 .scr_write = svia_scr_write, }; +static struct ata_port_operations vt8251_ops = { + .inherits = &svia_base_ops, + .hardreset = sata_std_hardreset, + .scr_read = vt8251_scr_read, + .scr_write = vt8251_scr_write, +}; +static const struct ata_port_info vt6420_port_info = { .flags =ATA_FLAG_SATA |ATA_FLAG_NO_LEGACY , .pio_mask =0x1f ,
@@ -152,6 +166,15 @@ static struct ata_port_info vt6421_pport .port_ops = &vt6421_pata_ops, }; +static struct ata_port_info vt8251_port_info = { + .flags =ATA_FLAG_SATA |ATA_FLAG_SLAVE_POSS | +ATA_FLAG_NO_LEGACY , + .pio_mask =0x1f , + .mwdma_mask =0x07 , + .udma_mask =ATA_UDMA6 , + .port_ops = &vt8251_ops, +}; +MODULE_AUTHOR ("Jeff Garzik" );MODULE_DESCRIPTION ("SCSI low-level driver for VIA SATA controllers" );MODULE_LICENSE ("GPL" );
@@ -174,6 +197,83 @@ static int svia_scr_write(struct ata_linreturn 0 ; } +static int vt8251_scr_read (struct ata_link *link,unsigned int scr,u32 *val) +{ +static const u8 ipm_tbl[] = {1 ,2 ,6 ,0 }; +struct pci_dev *pdev =to_pci_dev (link->ap->host->dev); +int slot =2 * link->ap->port_no + link->pmp; +u32 v =0 ; +u8 raw; + +switch (scr) { +case SCR_STATUS : +pci_read_config_byte (pdev,0xA0 + slot, &raw); + +/* read the DET field, bit0 and 1 of the config byte */ + v |= raw &0x03 ; + +/* read the SPD field, bit4 of the configure byte */ +if (raw & (1 <<4 )) + v |=0x02 <<4 ; +else + v |=0x01 <<4 ; + +/* read the IPM field, bit2 and 3 of the config byte */ + v |= ipm_tbl[(raw >>2 ) &0x3 ]; +break ; + +case SCR_ERROR : +/* devices other than 5287 uses 0xA8 as base */ +WARN_ON (pdev->device !=0x5287 ); +pci_read_config_dword (pdev,0xB0 + slot *4 , &v); +break ; + +case SCR_CONTROL : +pci_read_config_byte (pdev,0xA4 + slot, &raw); + +/* read the DET field, bit0 and bit1 */ + v |= ((raw &0x02 ) <<1 ) | (raw &0x01 ); + +/* read the IPM field, bit2 and bit3 */ + v |= ((raw >>2 ) &0x03 ) <<8 ; +break ; + +default : +return -EINVAL ; + } + + *val = v; +return 0 ; +} + +static int vt8251_scr_write (struct ata_link *link,unsigned int scr,u32 val) +{ +struct pci_dev *pdev =to_pci_dev (link->ap->host->dev); +int slot =2 * link->ap->port_no + link->pmp; +u32 v =0 ; + +switch (scr) { +case SCR_ERROR : +/* devices other than 5287 uses 0xA8 as base */ +WARN_ON (pdev->device !=0x5287 ); +pci_write_config_dword (pdev,0xB0 + slot *4 , val); +return 0 ; + +case SCR_CONTROL : +/* set the DET field */ + v |= ((val &0x4 ) >>1 ) | (val &0x1 ); + +/* set the IPM field */ + v |= ((val >>8 ) &0x3 ) <<2 ; + +pci_write_config_byte (pdev,0xA4 + slot, v); +return 0 ; + +default : +return -EINVAL ; + } +} +/** * svia_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent
@@ -396,6 +496,30 @@ static int vt6421_prepare_host(struct pcreturn 0 ; } +static int vt8251_prepare_host (struct pci_dev *pdev,struct ata_host **r_host) +{ +const struct ata_port_info *ppi[] = { &vt8251_port_info,NULL }; +struct ata_host *host; +int i, rc; + + rc =ata_pci_sff_prepare_host (pdev, ppi, &host); +if (rc) +return rc; + *r_host = host; + + rc =pcim_iomap_regions (pdev,1 <<5 ,DRV_NAME ); +if (rc) { +dev_printk (KERN_ERR , &pdev->dev,"failed to iomap PCI BAR 5\n" ); +return rc; + } + +/* 8251 hosts four sata ports as M/S of the two channels */ +for (i =0 ; i < host->n_ports; i++) +ata_slave_link_init (host->ports[i]); + +return 0 ; +} +static void svia_configure (struct pci_dev *pdev) {u8 tmp8;
@@ -451,10 +575,10 @@ static int svia_init_one(struct pci_devif (rc)return rc; -if (board_id == vt6420) - bar_sizes = &svia_bar_sizes[0 ]; -else +if (board_id == vt6421) bar_sizes = &vt6421_bar_sizes[0 ]; +else + bar_sizes = &svia_bar_sizes[0 ];for (i =0 ; i <ARRAY_SIZE (svia_bar_sizes); i++) if ((pci_resource_start(pdev, i) == 0) ||
@@ -467,12 +591,19 @@ static int svia_init_one(struct pci_devreturn -ENODEV ; } -if (board_id == vt6420) +switch (board_id) { +case vt6420: rc =vt6420_prepare_host (pdev, &host); -else +break ; +case vt6421: rc =vt6421_prepare_host (pdev, &host); -if (rc) -return rc; +break ; +case vt8251: + rc =vt8251_prepare_host (pdev, &host); +break ; +default : +return -EINVAL ; + }svia_configure (pdev);
Re: [PATCH 1/2 #upstream-fixes] sata_via: fix support for 5287
Quoted 18 lines · Tejun Heo
5287 used to be treated as vt6420 but it didn't work. It's new family of controllers called vt8251 which hosts four SATA ports as M/S of the two ATA ports. This configuration is rather peculiar in that although the M/S devices are on the same port, each have its own SCR (or equivalent link status/control) registers which screws up the port-link-device hierarchy assumed by libata. Another controller which falls into this category is
ata_piixw/ SIDPR access.libata now has facility to deal with this class of controllers named
slave_link. A low level driver for such controllers can just callata_slave_link_init()on the respective ports and libata will handle all the difficult parts like following up with single SRST after hardresetting both ports.This patch creates new controller class vt8251, implements
slave_linkaware init sequence and config space based SCR access for it and moves 5287 to the new class.
Quoted 7 lines
This patch is based on Joseph Chan's larger patch which was created before
slave_linkwas implemented in libata.http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640
Signed-off-by Tejun Heo <[email protected]>Cc Joseph Chan <[email protected]>
Jeff, this one should have been titled [PATCH 2/2 #upstream-fixes] and required for vt5287 support. This didn't appear on #upstream. Maybe you missed it due to the wrong title?
Thanks.
Signature · 1 line
tejun
Jeff Garzik
AppliedRe: [PATCH 1/2 #upstream-fixes] sata_via: fix support for 5287
In reply to Tejun HeoQuoted 21 lines · Tejun Heo
5287 used to be treated as vt6420 but it didn't work. It's new family of controllers called vt8251 which hosts four SATA ports as M/S of the two ATA ports. This configuration is rather peculiar in that although the M/S devices are on the same port, each have its own SCR (or equivalent link status/control) registers which screws up the port-link-device hierarchy assumed by libata. Another controller which falls into this category is
ata_piixw/ SIDPR access.libata now has facility to deal with this class of controllers named
slave_link. A low level driver for such controllers can just callata_slave_link_init()on the respective ports and libata will handle all the difficult parts like following up with single SRST after hardresetting both ports.This patch creates new controller class vt8251, implements
slave_linkaware init sequence and config space based SCR access for it and moves 5287 to the new class.This patch is based on Joseph Chan's larger patch which was created before
slave_linkwas implemented in libata.
Quoted 7 lines
http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640
Signed-off-by Tejun Heo <[email protected]>Cc Joseph Chan <[email protected]>--- drivers/ata/sata_via.c | 155 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 12 deletions(-)
applied
Jeff Garzik
AppliedQuoted 17 lines · Tejun Heo
VIA controllers clear DEVICE register when IEN changes. Make sure DEVICE is updated along with CTL.
This change is separated from Joseph Chan's larger patch.
http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640
Signed-off-by Tejun Heo <[email protected]>Cc Joseph Chan <[email protected]>---
These two patches are on top oflinus#master
+ [1] libata-eh-fix-slave-link-EH-action-mask-handling
+ [2] libata-transfer-EHI-control-flags-to-slave-ehc_i
+ [3] libata-set-device-class-to-NONE-if-phys_offline
Quoted 6 lines
[1] http://article.gmane.org/gmane.linux.ide/35390
[2] http://article.gmane.org/gmane.linux.ide/35393
[3] http://article.gmane.org/gmane.linux.ide/35436and finally gets vt8251 working. I'll integrate this into the separate-sff-bmdma git tree. :-)
applied