/** * struct sata_gemini - a state container for a Gemini SATA bridge * @dev: the containing device * @base: remapped I/O memory base * @muxmode: the current muxing mode * @ide_pins: if the device is using the plain IDE interface pins * @sata_bridge: if the device enables the SATA bridge * @sata0_pclk: SATA0 PCLK handler * @sata1_pclk: SATA1 PCLK handler
*/ struct sata_gemini { struct device *dev; void __iomem *base; enum gemini_muxmode muxmode; bool ide_pins; bool sata_bridge; struct clk *sata0_pclk; struct clk *sata1_pclk;
};
/* Miscellaneous Control Register */ #define GEMINI_GLOBAL_MISC_CTRL 0x30 /* * Values of IDE IOMUX bits in the misc control register * * Bits 26:24 are "IDE IO Select", which decides what SATA * adapters are connected to which of the two IDE/ATA * controllers in the Gemini. We can connect the two IDE blocks * to one SATA adapter each, both acting as master, or one IDE * blocks to two SATA adapters so the IDE block can act in a * master/slave configuration. * * We also bring out different blocks on the actual IDE * pins (not SATA pins) if (and only if) these are muxed in. * * 111-100 - Reserved * Mode 0: 000 - ata0 master <-> sata0 * ata1 master <-> sata1 * ata0 slave interface brought out on IDE pads * Mode 1: 001 - ata0 master <-> sata0 * ata1 master <-> sata1 * ata1 slave interface brought out on IDE pads * Mode 2: 010 - ata1 master <-> sata1 * ata1 slave <-> sata0 * ata0 master and slave interfaces brought out * on IDE pads * Mode 3: 011 - ata0 master <-> sata0 * ata1 slave <-> sata1 * ata1 master and slave interfaces brought out * on IDE pads
*/ #define GEMINI_IDE_IOMUX_MASK (7 << 24) #define GEMINI_IDE_IOMUX_MODE0 (0 << 24) #define GEMINI_IDE_IOMUX_MODE1 (1 << 24) #define GEMINI_IDE_IOMUX_MODE2 (2 << 24) #define GEMINI_IDE_IOMUX_MODE3 (3 << 24) #define GEMINI_IDE_IOMUX_SHIFT (24)
/* * There is only ever one instance of this bridge on a system, * so create a singleton so that the FTIDE010 instances can grab * a reference to it.
*/ staticstruct sata_gemini *sg_singleton;
bool gemini_sata_bridge_enabled(struct sata_gemini *sg, bool is_ata1)
{ if (!sg->sata_bridge) returnfalse; /* * In muxmode 2 and 3 one of the ATA controllers is * actually not connected to any SATA bridge.
*/ if ((sg->muxmode == GEMINI_MUXMODE_2) &&
!is_ata1) returnfalse; if ((sg->muxmode == GEMINI_MUXMODE_3) &&
is_ata1) returnfalse;
if (bridge == 0) {
val = GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN | GEMINI_SATA_CTRL_EN; /* SATA0 slave mode is only used in muxmode 2 */ if (sg->muxmode == GEMINI_MUXMODE_2)
val |= GEMINI_SATA_CTRL_SLAVE_EN;
writel(val, sg->base + GEMINI_SATA0_CTRL);
} else {
val = GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN | GEMINI_SATA_CTRL_EN; /* SATA1 slave mode is only used in muxmode 3 */ if (sg->muxmode == GEMINI_MUXMODE_3)
val |= GEMINI_SATA_CTRL_SLAVE_EN;
writel(val, sg->base + GEMINI_SATA1_CTRL);
}
/* Vendor code waits 10 ms here */
msleep(10);
/* Wait for PHY to become ready */ do {
msleep(100);
if (bridge == 0)
val = readl(sg->base + GEMINI_SATA0_STATUS); else
val = readl(sg->base + GEMINI_SATA1_STATUS); if (val & GEMINI_SATA_STATUS_PHY_READY) break;
} while (time_before(jiffies, timeout));
sg->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sg->base)) return PTR_ERR(sg->base);
map = syscon_regmap_lookup_by_phandle(np, "syscon"); if (IS_ERR(map)) {
dev_err(dev, "no global syscon\n"); return PTR_ERR(map);
}
/* Set up the SATA bridge if need be */ if (of_property_read_bool(np, "cortina,gemini-enable-sata-bridge")) {
ret = gemini_sata_bridge_init(sg); if (ret) return ret;
}
if (of_property_read_bool(np, "cortina,gemini-enable-ide-pins"))
sg->ide_pins = true;
if (!sg->sata_bridge && !sg->ide_pins) {
dev_err(dev, "neither SATA bridge or IDE output enabled\n");
ret = -EINVAL; goto out_unprep_clk;
}
ret = of_property_read_u32(np, "cortina,gemini-ata-muxmode", &muxmode); if (ret) {
dev_err(dev, "could not parse ATA muxmode\n"); goto out_unprep_clk;
} if (muxmode > GEMINI_MUXMODE_3) {
dev_err(dev, "illegal muxmode %d\n", muxmode);
ret = -EINVAL; goto out_unprep_clk;
}
sg->muxmode = muxmode;
gmask = GEMINI_IDE_IOMUX_MASK;
gmode = (muxmode << GEMINI_IDE_IOMUX_SHIFT);
ret = regmap_update_bits(map, GEMINI_GLOBAL_MISC_CTRL, gmask, gmode); if (ret) {
dev_err(dev, "unable to set up IDE muxing\n");
ret = -ENODEV; goto out_unprep_clk;
}
/* * Route out the IDE pins if desired. * This is done by looking up a special pin control state called * "ide" that will route out the IDE pins.
*/ if (sg->ide_pins) {
ret = gemini_setup_ide_pins(dev); if (ret) return ret;
}
dev_info(dev, "set up the Gemini IDE/SATA nexus\n");
platform_set_drvdata(pdev, sg);
sg_singleton = sg;
return 0;
out_unprep_clk: if (sg->sata_bridge) {
clk_unprepare(sg->sata1_pclk);
clk_unprepare(sg->sata0_pclk);
} return ret;
}
MODULE_DESCRIPTION("low level driver for Cortina Systems Gemini SATA bridge");
MODULE_AUTHOR("Linus Walleij ");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
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.