diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 19:33:59 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 19:33:59 -0800 |
commit | 8c930204ce76eddeb2e1af66a75f0ab2506c76e2 (patch) | |
tree | cdc3f5ac1b799efd1d54200e08848ccf2bfedb41 /drivers/ata/ahci_brcmstb.c | |
parent | 367262c1be4bbf23938175a93eb573b289a00027 (diff) | |
parent | e39b2bb3b72b999a04e8d295882be3255aca5ade (diff) | |
download | blackbird-op-linux-8c930204ce76eddeb2e1af66a75f0ab2506c76e2.tar.gz blackbird-op-linux-8c930204ce76eddeb2e1af66a75f0ab2506c76e2.zip |
Merge branch 'for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata updates from Tejun Heo:
"Mostly low level driver specific changes.
Two changes are somewhat noteworthy. First, Dan's patchset to support
per-port msix interrupt handling for ahci, which was tried last cycle
but had to be backed out due to a couple issues, is back and seems to
be working fine. Second, libata exception handling now uses
usleep_range() instead of msleep() for sleeps < 20ms which can make
things snappier in some corner cases"
* 'for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
libata: skip debounce delay on link resume
ata: ahci_brcmstb: disable DIPM support
ata: ahci_brcmstb: enable support for ALPM
drivers: libata-core: Use usleep_range() instead of msleep() for short sleeps (<20 ms)
sata_sx4: correctly handling failed allocation
ata: ahci_brcmstb: add support for MIPS-based platforms
ahci: qoriq: Adjust the default register values on ls1021a
ahci: qoriq: Update the default Rx watermark value
ahci: qoriq: Adjust the default register values on ls1043a
ahci: compile out msi/msix infrastructure
ata: core: fix irq description on AHCI single irq systems
ata: ahci_brcmstb: remove unused definitions
ata: ahci_brcmstb: add a quirk for MIPS-based platforms
ata: ahci_brcmstb: disable NCQ for MIPS-based platforms
ata: sata_rcar: Remove obsolete platform_device_id entries
sata_rcar: Add compatible string for r8a7795
ahci: kill 'intr_status'
ahci: switch from 'threaded' to 'hardirq' interrupt handling
ahci: per-port msix support
Diffstat (limited to 'drivers/ata/ahci_brcmstb.c')
-rw-r--r-- | drivers/ata/ahci_brcmstb.c | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/drivers/ata/ahci_brcmstb.c b/drivers/ata/ahci_brcmstb.c index 14b7305d2ba0..b36cae2fd04b 100644 --- a/drivers/ata/ahci_brcmstb.c +++ b/drivers/ata/ahci_brcmstb.c @@ -52,8 +52,10 @@ #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14) #define SATA_TOP_CTRL_PHY_OFFS 0x8 #define SATA_TOP_MAX_PHYS 2 -#define SATA_TOP_CTRL_SATA_TP_OUT 0x1c -#define SATA_TOP_CTRL_CLIENT_INIT_CTRL 0x20 + +#define SATA_FIRST_PORT_CTRL 0x700 +#define SATA_NEXT_PORT_CTRL_OFFSET 0x80 +#define SATA_PORT_PCTRL6(reg_base) (reg_base + 0x18) /* On big-endian MIPS, buses are reversed to big endian, so switch them back */ #if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN) @@ -69,14 +71,21 @@ (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \ (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT)) +enum brcm_ahci_quirks { + BRCM_AHCI_QUIRK_NO_NCQ = BIT(0), + BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1), +}; + struct brcm_ahci_priv { struct device *dev; void __iomem *top_ctrl; u32 port_mask; + u32 quirks; }; static const struct ata_port_info ahci_brcm_port_info = { - .flags = AHCI_FLAG_COMMON, + .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, + .link_flags = ATA_LFLAG_NO_DB_DELAY, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_platform_ops, @@ -107,6 +116,34 @@ static inline void brcm_sata_writereg(u32 val, void __iomem *addr) writel_relaxed(val, addr); } +static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv) +{ + struct brcm_ahci_priv *priv = hpriv->plat_data; + u32 bus_ctrl, port_ctrl, host_caps; + int i; + + /* Enable support for ALPM */ + bus_ctrl = brcm_sata_readreg(priv->top_ctrl + + SATA_TOP_CTRL_BUS_CTRL); + brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT, + priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); + host_caps = readl(hpriv->mmio + HOST_CAP); + writel(host_caps | HOST_CAP_ALPM, hpriv->mmio); + brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); + + /* + * Adjust timeout to allow PLL sufficient time to lock while waking + * up from slumber mode. + */ + for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL; + i < SATA_TOP_MAX_PHYS; + i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) { + if (priv->port_mask & BIT(i)) + writel(0xff1003fc, + hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl)); + } +} + static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port) { void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL + @@ -114,6 +151,9 @@ static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port) void __iomem *p; u32 reg; + if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE) + return; + /* clear PHY_DEFAULT_POWER_STATE */ p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1; reg = brcm_sata_readreg(p); @@ -143,6 +183,9 @@ static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port) void __iomem *p; u32 reg; + if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE) + return; + /* power-off the PHY digital logic */ p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2; reg = brcm_sata_readreg(p); @@ -230,6 +273,7 @@ static int brcm_ahci_resume(struct device *dev) brcm_sata_init(priv); brcm_sata_phys_enable(priv); + brcm_sata_alpm_init(hpriv); return ahci_platform_resume(dev); } #endif @@ -256,6 +300,11 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (IS_ERR(priv->top_ctrl)) return PTR_ERR(priv->top_ctrl); + if (of_device_is_compatible(dev->of_node, "brcm,bcm7425-ahci")) { + priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ; + priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE; + } + brcm_sata_init(priv); priv->port_mask = brcm_ahci_get_portmask(pdev, priv); @@ -269,10 +318,15 @@ static int brcm_ahci_probe(struct platform_device *pdev) return PTR_ERR(hpriv); hpriv->plat_data = priv; + brcm_sata_alpm_init(hpriv); + ret = ahci_platform_enable_resources(hpriv); if (ret) return ret; + if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ) + hpriv->flags |= AHCI_HFLAG_NO_NCQ; + ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info, &ahci_platform_sht); if (ret) @@ -300,6 +354,7 @@ static int brcm_ahci_remove(struct platform_device *pdev) } static const struct of_device_id ahci_of_match[] = { + {.compatible = "brcm,bcm7425-ahci"}, {.compatible = "brcm,bcm7445-ahci"}, {}, }; |