aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_mv.c
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2008-05-02 02:11:45 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-05-06 11:37:40 -0400
commit00f42eabb204c68fa64ef72de834e74aca15c81f (patch)
tree01a1383b2356c5a03f1af43b960596b923bed2aa /drivers/ata/sata_mv.c
parentdd2890f60f8e15f14c8eb132779b2f15c49d1203 (diff)
sata_mv rearrange mv_config_fbs
Rearrange mv_config_fbs() to more closely follow the (corrected) datasheet recommendations for NCQ and FIS-based switching (FBS). Also, maintain a port flag to let us know when FBS is enabled. We will make more use of that flag later in this patch series. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r--drivers/ata/sata_mv.c60
1 files changed, 39 insertions, 21 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index fbccf215d501..e4d411cec79a 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -366,6 +366,7 @@ enum {
366 /* Port private flags (pp_flags) */ 366 /* Port private flags (pp_flags) */
367 MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ 367 MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
368 MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ 368 MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */
369 MV_PP_FLAG_FBS_EN = (1 << 2), /* is EDMA set up for FBS? */
369}; 370};
370 371
371#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I) 372#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
@@ -1129,26 +1130,31 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
1129 return ATA_DEFER_PORT; 1130 return ATA_DEFER_PORT;
1130} 1131}
1131 1132
1132static void mv_config_fbs(void __iomem *port_mmio, int enable_fbs) 1133static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs)
1133{ 1134{
1134 u32 old_fiscfg, new_fiscfg, old_ltmode, new_ltmode; 1135 u32 new_fiscfg, old_fiscfg;
1135 /* 1136 u32 new_ltmode, old_ltmode;
1136 * Various bit settings required for operation 1137 u32 new_haltcond, old_haltcond;
1137 * in FIS-based switching (fbs) mode on GenIIe: 1138
1138 */ 1139 old_fiscfg = readl(port_mmio + FISCFG_OFS);
1139 old_fiscfg = readl(port_mmio + FISCFG_OFS); 1140 old_ltmode = readl(port_mmio + LTMODE_OFS);
1140 old_ltmode = readl(port_mmio + LTMODE_OFS); 1141 old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS);
1141 if (enable_fbs) { 1142
1142 new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC; 1143 new_fiscfg = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR);
1143 new_ltmode = old_ltmode | LTMODE_BIT8; 1144 new_ltmode = old_ltmode & ~LTMODE_BIT8;
1144 } else { /* disable fbs */ 1145 new_haltcond = old_haltcond | EDMA_ERR_DEV;
1145 new_fiscfg = old_fiscfg & ~FISCFG_SINGLE_SYNC; 1146
1146 new_ltmode = old_ltmode & ~LTMODE_BIT8; 1147 if (want_fbs) {
1148 new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC;
1149 new_ltmode = old_ltmode | LTMODE_BIT8;
1147 } 1150 }
1151
1148 if (new_fiscfg != old_fiscfg) 1152 if (new_fiscfg != old_fiscfg)
1149 writelfl(new_fiscfg, port_mmio + FISCFG_OFS); 1153 writelfl(new_fiscfg, port_mmio + FISCFG_OFS);
1150 if (new_ltmode != old_ltmode) 1154 if (new_ltmode != old_ltmode)
1151 writelfl(new_ltmode, port_mmio + LTMODE_OFS); 1155 writelfl(new_ltmode, port_mmio + LTMODE_OFS);
1156 if (new_haltcond != old_haltcond)
1157 writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS);
1152} 1158}
1153 1159
1154static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) 1160static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq)
@@ -1175,6 +1181,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
1175 1181
1176 /* set up non-NCQ EDMA configuration */ 1182 /* set up non-NCQ EDMA configuration */
1177 cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ 1183 cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */
1184 pp->pp_flags &= ~MV_PP_FLAG_FBS_EN;
1178 1185
1179 if (IS_GEN_I(hpriv)) 1186 if (IS_GEN_I(hpriv))
1180 cfg |= (1 << 8); /* enab config burst size mask */ 1187 cfg |= (1 << 8); /* enab config burst size mask */
@@ -1184,19 +1191,30 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
1184 mv_60x1_errata_sata25(ap, want_ncq); 1191 mv_60x1_errata_sata25(ap, want_ncq);
1185 1192
1186 } else if (IS_GEN_IIE(hpriv)) { 1193 } else if (IS_GEN_IIE(hpriv)) {
1194 int want_fbs = sata_pmp_attached(ap);
1195 /*
1196 * Possible future enhancement:
1197 *
1198 * The chip can use FBS with non-NCQ, if we allow it,
1199 * But first we need to have the error handling in place
1200 * for this mode (datasheet section 7.3.15.4.2.3).
1201 * So disallow non-NCQ FBS for now.
1202 */
1203 want_fbs &= want_ncq;
1204
1205 mv_config_fbs(port_mmio, want_ncq, want_fbs);
1206
1207 if (want_fbs) {
1208 pp->pp_flags |= MV_PP_FLAG_FBS_EN;
1209 cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
1210 }
1211
1187 cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ 1212 cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
1188 cfg |= (1 << 22); /* enab 4-entry host queue cache */ 1213 cfg |= (1 << 22); /* enab 4-entry host queue cache */
1189 if (HAS_PCI(ap->host)) 1214 if (HAS_PCI(ap->host))
1190 cfg |= (1 << 18); /* enab early completion */ 1215 cfg |= (1 << 18); /* enab early completion */
1191 if (hpriv->hp_flags & MV_HP_CUT_THROUGH) 1216 if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
1192 cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ 1217 cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
1193
1194 if (want_ncq && sata_pmp_attached(ap)) {
1195 cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
1196 mv_config_fbs(port_mmio, 1);
1197 } else {
1198 mv_config_fbs(port_mmio, 0);
1199 }
1200 } 1218 }
1201 1219
1202 if (want_ncq) { 1220 if (want_ncq) {