static DEFINE_SPINLOCK(cphy_lock); /* Each of the 6 phys can have up to 4 sata ports attached to i. Map 0-based * sata ports to their phys and then to their lanes within the phys
*/ struct phy_lane_info { void __iomem *phy_base;
u8 lane_mapping;
u8 phy_devs;
u8 tx_atten;
}; staticstruct phy_lane_info port_data[CPHY_PORT_COUNT];
/* * Tell the LED controller that the signal has changed by raising the clock * line for 50 uS and then lowering it for 50 uS.
*/ staticvoid ecx_led_cycle_clock(struct ecx_plat_data *pdata)
{
gpiod_set_value(pdata->sgpio_gpiod[SCLOCK], 1);
udelay(50);
gpiod_set_value(pdata->sgpio_gpiod[SCLOCK], 0);
udelay(50);
}
/* get the slot number from the message */
pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; if (pmp < EM_MAX_SLOTS)
emp = &pp->em_priv[pmp]; else return -EINVAL;
if (!(hpriv->em_msg_type & EM_MSG_TYPE_LED)) return size;
spin_lock_irqsave(&sgpio_lock, flags);
ecx_parse_sgpio(pdata, ap->port_no, state);
sgpio_out = pdata->sgpio_pattern; for (i = 0; i < pdata->pre_clocks; i++)
ecx_led_cycle_clock(pdata);
gpiod_set_value(pdata->sgpio_gpiod[SLOAD], 1);
ecx_led_cycle_clock(pdata);
gpiod_set_value(pdata->sgpio_gpiod[SLOAD], 0); /* * bit-bang out the SGPIO pattern, by consuming a bit and then * clocking it out.
*/ for (i = 0; i < (SGPIO_SIGNALS * pdata->n_ports); i++) {
gpiod_set_value(pdata->sgpio_gpiod[SDATA], sgpio_out & 1);
sgpio_out >>= 1;
ecx_led_cycle_clock(pdata);
} for (i = 0; i < pdata->post_clocks; i++)
ecx_led_cycle_clock(pdata);
/* save off new led state for port/slot */
emp->led_state = state;
do {
u32 tmp; struct of_phandle_args phy_data; if (of_parse_phandle_with_args(sata_node, "calxeda,port-phys", "#phy-cells",
port, &phy_data)) break; for (phy = 0; phy < phy_count; phy++) { if (phy_nodes[phy] == phy_data.np) break;
} if (phy_nodes[phy] == NULL) {
phy_nodes[phy] = phy_data.np;
cphy_base[phy] = of_iomap(phy_nodes[phy], 0); if (cphy_base[phy] == NULL) {
of_node_put(phy_data.np); return 0;
}
phy_count += 1;
}
port_data[port].lane_mapping = phy_data.args[0];
of_property_read_u32(phy_nodes[phy], "phydev", &tmp);
port_data[port].phy_devs = tmp;
port_data[port].phy_base = cphy_base[phy];
of_node_put(phy_data.np);
port += 1;
} while (port < CPHY_PORT_COUNT);
of_property_read_u32_array(sata_node, "calxeda,tx-atten",
tx_atten, port); for (i = 0; i < port; i++)
port_data[i].tx_atten = (u8) tx_atten[i]; return 0;
}
/* * The Calxeda SATA phy intermittently fails to bring up a link with Gen3 * Retrying the phy hard reset can work around the issue, but the drive * may fail again. In less than 150 out of 15000 test runs, it took more * than 10 tries for the link to be established (but never more than 35). * Triple the maximum observed retry count to provide plenty of margin for * rare events and to guarantee that the link is established. * * Also, the default 2 second time-out on a failed drive is too long in * this situation. The uboot implementation of the same driver function * uses a much shorter time-out period and never experiences a time out * issue. Reducing the time-out to 500ms improves the responsiveness. * The other timing constants were kept the same as the stock AHCI driver. * This change was also tested 15000 times on 24 drives and none of them * experienced a time out.
*/ staticint ahci_highbank_hardreset(struct ata_link *link, unsignedint *class, unsignedlong deadline)
{ staticconstunsignedint timing[] = { 5, 100, 500}; struct ata_port *ap = link->ap; struct ahci_port_priv *pp = ap->private_data; struct ahci_host_priv *hpriv = ap->host->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; struct ata_taskfile tf; bool online;
u32 sstatus; int rc; int retry = 100;
hpriv->stop_engine(ap);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(link->device, &tf);
tf.status = ATA_BUSY;
ata_tf_to_fis(&tf, 0, 0, d2h_fis);
/* If the status is 1, we are connected, but the link did not * come up. So retry resetting the link again.
*/ if (sata_scr_read(link, SCR_STATUS, &sstatus)) break; if (!(sstatus & 0x3)) break;
} while (!online && retry--);
if (hpriv->cap & HOST_CAP_PMP)
pi.flags |= ATA_FLAG_PMP;
if (hpriv->cap & HOST_CAP_64)
dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
/* CAP.NP sometimes indicate the index of the last enabled * port, at other times, that of the last possible port, so * determining the maximum port number requires looking at * both CAP.NP and port_map.
*/
n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.