588 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Broadcom SATA3 AHCI Controller Driver4 *5 * Copyright © 2009-2015 Broadcom Corporation6 */7 8#include <linux/ahci_platform.h>9#include <linux/compiler.h>10#include <linux/device.h>11#include <linux/init.h>12#include <linux/interrupt.h>13#include <linux/io.h>14#include <linux/kernel.h>15#include <linux/libata.h>16#include <linux/module.h>17#include <linux/of.h>18#include <linux/platform_device.h>19#include <linux/reset.h>20#include <linux/string.h>21 22#include "ahci.h"23 24#define DRV_NAME "brcm-ahci"25 26#define SATA_TOP_CTRL_VERSION 0x027#define SATA_TOP_CTRL_BUS_CTRL 0x428 #define MMIO_ENDIAN_SHIFT 0 /* CPU->AHCI */29 #define DMADESC_ENDIAN_SHIFT 2 /* AHCI->DDR */30 #define DMADATA_ENDIAN_SHIFT 4 /* AHCI->DDR */31 #define PIODATA_ENDIAN_SHIFT 632 #define ENDIAN_SWAP_NONE 033 #define ENDIAN_SWAP_FULL 234#define SATA_TOP_CTRL_TP_CTRL 0x835#define SATA_TOP_CTRL_PHY_CTRL 0xc36 #define SATA_TOP_CTRL_PHY_CTRL_1 0x037 #define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE BIT(14)38 #define SATA_TOP_CTRL_PHY_CTRL_2 0x439 #define SATA_TOP_CTRL_2_SW_RST_MDIOREG BIT(0)40 #define SATA_TOP_CTRL_2_SW_RST_OOB BIT(1)41 #define SATA_TOP_CTRL_2_SW_RST_RX BIT(2)42 #define SATA_TOP_CTRL_2_SW_RST_TX BIT(3)43 #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14)44 #define SATA_TOP_CTRL_PHY_OFFS 0x845 #define SATA_TOP_MAX_PHYS 246 47#define SATA_FIRST_PORT_CTRL 0x70048#define SATA_NEXT_PORT_CTRL_OFFSET 0x8049#define SATA_PORT_PCTRL6(reg_base) (reg_base + 0x18)50 51/* On big-endian MIPS, buses are reversed to big endian, so switch them back */52#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)53#define DATA_ENDIAN 2 /* AHCI->DDR inbound accesses */54#define MMIO_ENDIAN 2 /* CPU->AHCI outbound accesses */55#else56#define DATA_ENDIAN 057#define MMIO_ENDIAN 058#endif59 60#define BUS_CTRL_ENDIAN_CONF \61 ((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) | \62 (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \63 (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))64 65#define BUS_CTRL_ENDIAN_NSP_CONF \66 (0x02 << DMADATA_ENDIAN_SHIFT | 0x02 << DMADESC_ENDIAN_SHIFT)67 68#define BUS_CTRL_ENDIAN_CONF_MASK \69 (0x3 << MMIO_ENDIAN_SHIFT | 0x3 << DMADESC_ENDIAN_SHIFT | \70 0x3 << DMADATA_ENDIAN_SHIFT | 0x3 << PIODATA_ENDIAN_SHIFT)71 72enum brcm_ahci_version {73 BRCM_SATA_BCM7425 = 1,74 BRCM_SATA_BCM7445,75 BRCM_SATA_NSP,76 BRCM_SATA_BCM7216,77};78 79enum brcm_ahci_quirks {80 BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(0),81};82 83struct brcm_ahci_priv {84 struct device *dev;85 void __iomem *top_ctrl;86 u32 port_mask;87 u32 quirks;88 enum brcm_ahci_version version;89 struct reset_control *rcdev_rescal;90 struct reset_control *rcdev_ahci;91};92 93static inline u32 brcm_sata_readreg(void __iomem *addr)94{95 /*96 * MIPS endianness is configured by boot strap, which also reverses all97 * bus endianness (i.e., big-endian CPU + big endian bus ==> native98 * endian I/O).99 *100 * Other architectures (e.g., ARM) either do not support big endian, or101 * else leave I/O in little endian mode.102 */103 if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))104 return __raw_readl(addr);105 else106 return readl_relaxed(addr);107}108 109static inline void brcm_sata_writereg(u32 val, void __iomem *addr)110{111 /* See brcm_sata_readreg() comments */112 if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))113 __raw_writel(val, addr);114 else115 writel_relaxed(val, addr);116}117 118static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)119{120 struct brcm_ahci_priv *priv = hpriv->plat_data;121 u32 port_ctrl, host_caps;122 int i;123 124 /* Enable support for ALPM */125 host_caps = readl(hpriv->mmio + HOST_CAP);126 if (!(host_caps & HOST_CAP_ALPM))127 hpriv->flags |= AHCI_HFLAG_YES_ALPM;128 129 /*130 * Adjust timeout to allow PLL sufficient time to lock while waking131 * up from slumber mode.132 */133 for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL;134 i < SATA_TOP_MAX_PHYS;135 i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) {136 if (priv->port_mask & BIT(i))137 writel(0xff1003fc,138 hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl));139 }140}141 142static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)143{144 void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +145 (port * SATA_TOP_CTRL_PHY_OFFS);146 void __iomem *p;147 u32 reg;148 149 if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)150 return;151 152 /* clear PHY_DEFAULT_POWER_STATE */153 p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;154 reg = brcm_sata_readreg(p);155 reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;156 brcm_sata_writereg(reg, p);157 158 /* reset the PHY digital logic */159 p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;160 reg = brcm_sata_readreg(p);161 reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |162 SATA_TOP_CTRL_2_SW_RST_RX);163 reg |= SATA_TOP_CTRL_2_SW_RST_TX;164 brcm_sata_writereg(reg, p);165 reg = brcm_sata_readreg(p);166 reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;167 brcm_sata_writereg(reg, p);168 reg = brcm_sata_readreg(p);169 reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;170 brcm_sata_writereg(reg, p);171 (void)brcm_sata_readreg(p);172}173 174static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port)175{176 void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +177 (port * SATA_TOP_CTRL_PHY_OFFS);178 void __iomem *p;179 u32 reg;180 181 if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)182 return;183 184 /* power-off the PHY digital logic */185 p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;186 reg = brcm_sata_readreg(p);187 reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |188 SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX |189 SATA_TOP_CTRL_2_PHY_GLOBAL_RESET);190 brcm_sata_writereg(reg, p);191 192 /* set PHY_DEFAULT_POWER_STATE */193 p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;194 reg = brcm_sata_readreg(p);195 reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;196 brcm_sata_writereg(reg, p);197}198 199static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv)200{201 int i;202 203 for (i = 0; i < SATA_TOP_MAX_PHYS; i++)204 if (priv->port_mask & BIT(i))205 brcm_sata_phy_enable(priv, i);206}207 208static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)209{210 int i;211 212 for (i = 0; i < SATA_TOP_MAX_PHYS; i++)213 if (priv->port_mask & BIT(i))214 brcm_sata_phy_disable(priv, i);215}216 217static u32 brcm_ahci_get_portmask(struct ahci_host_priv *hpriv,218 struct brcm_ahci_priv *priv)219{220 u32 impl;221 222 impl = readl(hpriv->mmio + HOST_PORTS_IMPL);223 224 if (fls(impl) > SATA_TOP_MAX_PHYS)225 dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",226 impl);227 else if (!impl)228 dev_info(priv->dev, "no ports found\n");229 230 return impl;231}232 233static void brcm_sata_init(struct brcm_ahci_priv *priv)234{235 void __iomem *ctrl = priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL;236 u32 data;237 238 /* Configure endianness */239 data = brcm_sata_readreg(ctrl);240 data &= ~BUS_CTRL_ENDIAN_CONF_MASK;241 if (priv->version == BRCM_SATA_NSP)242 data |= BUS_CTRL_ENDIAN_NSP_CONF;243 else244 data |= BUS_CTRL_ENDIAN_CONF;245 brcm_sata_writereg(data, ctrl);246}247 248static unsigned int brcm_ahci_read_id(struct ata_device *dev,249 struct ata_taskfile *tf, __le16 *id)250{251 struct ata_port *ap = dev->link->ap;252 struct ata_host *host = ap->host;253 struct ahci_host_priv *hpriv = host->private_data;254 struct brcm_ahci_priv *priv = hpriv->plat_data;255 void __iomem *mmio = hpriv->mmio;256 unsigned int err_mask;257 unsigned long flags;258 int i, rc;259 u32 ctl;260 261 /* Try to read the device ID and, if this fails, proceed with the262 * recovery sequence below263 */264 err_mask = ata_do_dev_read_id(dev, tf, id);265 if (likely(!err_mask))266 return err_mask;267 268 /* Disable host interrupts */269 spin_lock_irqsave(&host->lock, flags);270 ctl = readl(mmio + HOST_CTL);271 ctl &= ~HOST_IRQ_EN;272 writel(ctl, mmio + HOST_CTL);273 readl(mmio + HOST_CTL); /* flush */274 spin_unlock_irqrestore(&host->lock, flags);275 276 /* Perform the SATA PHY reset sequence */277 brcm_sata_phy_disable(priv, ap->port_no);278 279 /* Reset the SATA clock */280 ahci_platform_disable_clks(hpriv);281 msleep(10);282 283 ahci_platform_enable_clks(hpriv);284 msleep(10);285 286 /* Bring the PHY back on */287 brcm_sata_phy_enable(priv, ap->port_no);288 289 /* Re-initialize and calibrate the PHY */290 for (i = 0; i < hpriv->nports; i++) {291 rc = phy_init(hpriv->phys[i]);292 if (rc)293 goto disable_phys;294 295 rc = phy_calibrate(hpriv->phys[i]);296 if (rc) {297 phy_exit(hpriv->phys[i]);298 goto disable_phys;299 }300 }301 302 /* Re-enable host interrupts */303 spin_lock_irqsave(&host->lock, flags);304 ctl = readl(mmio + HOST_CTL);305 ctl |= HOST_IRQ_EN;306 writel(ctl, mmio + HOST_CTL);307 readl(mmio + HOST_CTL); /* flush */308 spin_unlock_irqrestore(&host->lock, flags);309 310 return ata_do_dev_read_id(dev, tf, id);311 312disable_phys:313 while (--i >= 0) {314 phy_power_off(hpriv->phys[i]);315 phy_exit(hpriv->phys[i]);316 }317 318 return AC_ERR_OTHER;319}320 321static void brcm_ahci_host_stop(struct ata_host *host)322{323 struct ahci_host_priv *hpriv = host->private_data;324 325 ahci_platform_disable_resources(hpriv);326}327 328static struct ata_port_operations ahci_brcm_platform_ops = {329 .inherits = &ahci_ops,330 .host_stop = brcm_ahci_host_stop,331 .read_id = brcm_ahci_read_id,332};333 334static const struct ata_port_info ahci_brcm_port_info = {335 .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,336 .link_flags = ATA_LFLAG_NO_DEBOUNCE_DELAY,337 .pio_mask = ATA_PIO4,338 .udma_mask = ATA_UDMA6,339 .port_ops = &ahci_brcm_platform_ops,340};341 342static int brcm_ahci_suspend(struct device *dev)343{344 struct ata_host *host = dev_get_drvdata(dev);345 struct ahci_host_priv *hpriv = host->private_data;346 struct brcm_ahci_priv *priv = hpriv->plat_data;347 int ret;348 349 brcm_sata_phys_disable(priv);350 351 if (IS_ENABLED(CONFIG_PM_SLEEP))352 ret = ahci_platform_suspend(dev);353 else354 ret = 0;355 356 reset_control_assert(priv->rcdev_ahci);357 reset_control_rearm(priv->rcdev_rescal);358 359 return ret;360}361 362static int __maybe_unused brcm_ahci_resume(struct device *dev)363{364 struct ata_host *host = dev_get_drvdata(dev);365 struct ahci_host_priv *hpriv = host->private_data;366 struct brcm_ahci_priv *priv = hpriv->plat_data;367 int ret = 0;368 369 ret = reset_control_deassert(priv->rcdev_ahci);370 if (ret)371 return ret;372 ret = reset_control_reset(priv->rcdev_rescal);373 if (ret)374 return ret;375 376 /* Make sure clocks are turned on before re-configuration */377 ret = ahci_platform_enable_clks(hpriv);378 if (ret)379 return ret;380 381 ret = ahci_platform_enable_regulators(hpriv);382 if (ret)383 goto out_disable_clks;384 385 brcm_sata_init(priv);386 brcm_sata_phys_enable(priv);387 brcm_sata_alpm_init(hpriv);388 389 /* Since we had to enable clocks earlier on, we cannot use390 * ahci_platform_resume() as-is since a second call to391 * ahci_platform_enable_resources() would bump up the resources392 * (regulators, clocks, PHYs) count artificially so we copy the part393 * after ahci_platform_enable_resources().394 */395 ret = ahci_platform_enable_phys(hpriv);396 if (ret)397 goto out_disable_phys;398 399 ret = ahci_platform_resume_host(dev);400 if (ret)401 goto out_disable_platform_phys;402 403 /* We resumed so update PM runtime state */404 pm_runtime_disable(dev);405 pm_runtime_set_active(dev);406 pm_runtime_enable(dev);407 408 return 0;409 410out_disable_platform_phys:411 ahci_platform_disable_phys(hpriv);412out_disable_phys:413 brcm_sata_phys_disable(priv);414 ahci_platform_disable_regulators(hpriv);415out_disable_clks:416 ahci_platform_disable_clks(hpriv);417 return ret;418}419 420static const struct scsi_host_template ahci_platform_sht = {421 AHCI_SHT(DRV_NAME),422};423 424static const struct of_device_id ahci_of_match[] = {425 {.compatible = "brcm,bcm7425-ahci", .data = (void *)BRCM_SATA_BCM7425},426 {.compatible = "brcm,bcm7445-ahci", .data = (void *)BRCM_SATA_BCM7445},427 {.compatible = "brcm,bcm63138-ahci", .data = (void *)BRCM_SATA_BCM7445},428 {.compatible = "brcm,bcm-nsp-ahci", .data = (void *)BRCM_SATA_NSP},429 {.compatible = "brcm,bcm7216-ahci", .data = (void *)BRCM_SATA_BCM7216},430 { /* sentinel */ }431};432MODULE_DEVICE_TABLE(of, ahci_of_match);433 434static int brcm_ahci_probe(struct platform_device *pdev)435{436 const struct of_device_id *of_id;437 struct device *dev = &pdev->dev;438 struct brcm_ahci_priv *priv;439 struct ahci_host_priv *hpriv;440 int ret;441 442 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);443 if (!priv)444 return -ENOMEM;445 446 of_id = of_match_node(ahci_of_match, pdev->dev.of_node);447 if (!of_id)448 return -ENODEV;449 450 priv->version = (unsigned long)of_id->data;451 priv->dev = dev;452 453 priv->top_ctrl = devm_platform_ioremap_resource_byname(pdev, "top-ctrl");454 if (IS_ERR(priv->top_ctrl))455 return PTR_ERR(priv->top_ctrl);456 457 if (priv->version == BRCM_SATA_BCM7216) {458 priv->rcdev_rescal = devm_reset_control_get_optional_shared(459 &pdev->dev, "rescal");460 if (IS_ERR(priv->rcdev_rescal))461 return PTR_ERR(priv->rcdev_rescal);462 }463 priv->rcdev_ahci = devm_reset_control_get_optional(&pdev->dev, "ahci");464 if (IS_ERR(priv->rcdev_ahci))465 return PTR_ERR(priv->rcdev_ahci);466 467 hpriv = ahci_platform_get_resources(pdev, 0);468 if (IS_ERR(hpriv))469 return PTR_ERR(hpriv);470 471 hpriv->plat_data = priv;472 hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;473 474 switch (priv->version) {475 case BRCM_SATA_BCM7425:476 hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;477 fallthrough;478 case BRCM_SATA_NSP:479 hpriv->flags |= AHCI_HFLAG_NO_NCQ;480 priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;481 break;482 default:483 break;484 }485 486 ret = reset_control_reset(priv->rcdev_rescal);487 if (ret)488 return ret;489 ret = reset_control_deassert(priv->rcdev_ahci);490 if (ret)491 return ret;492 493 ret = ahci_platform_enable_clks(hpriv);494 if (ret)495 goto out_reset;496 497 ret = ahci_platform_enable_regulators(hpriv);498 if (ret)499 goto out_disable_clks;500 501 /* Must be first so as to configure endianness including that502 * of the standard AHCI register space.503 */504 brcm_sata_init(priv);505 506 /* Initializes priv->port_mask which is used below */507 priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);508 if (!priv->port_mask) {509 ret = -ENODEV;510 goto out_disable_regulators;511 }512 513 /* Must be done before ahci_platform_enable_phys() */514 brcm_sata_phys_enable(priv);515 516 brcm_sata_alpm_init(hpriv);517 518 ret = ahci_platform_enable_phys(hpriv);519 if (ret)520 goto out_disable_phys;521 522 ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,523 &ahci_platform_sht);524 if (ret)525 goto out_disable_platform_phys;526 527 dev_info(dev, "Broadcom AHCI SATA3 registered\n");528 529 return 0;530 531out_disable_platform_phys:532 ahci_platform_disable_phys(hpriv);533out_disable_phys:534 brcm_sata_phys_disable(priv);535out_disable_regulators:536 ahci_platform_disable_regulators(hpriv);537out_disable_clks:538 ahci_platform_disable_clks(hpriv);539out_reset:540 reset_control_assert(priv->rcdev_ahci);541 reset_control_rearm(priv->rcdev_rescal);542 return ret;543}544 545static void brcm_ahci_remove(struct platform_device *pdev)546{547 struct ata_host *host = dev_get_drvdata(&pdev->dev);548 struct ahci_host_priv *hpriv = host->private_data;549 struct brcm_ahci_priv *priv = hpriv->plat_data;550 551 brcm_sata_phys_disable(priv);552 553 ata_platform_remove_one(pdev);554}555 556static void brcm_ahci_shutdown(struct platform_device *pdev)557{558 int ret;559 560 /* All resources releasing happens via devres, but our device, unlike a561 * proper remove is not disappearing, therefore using562 * brcm_ahci_suspend() here which does explicit power management is563 * appropriate.564 */565 ret = brcm_ahci_suspend(&pdev->dev);566 if (ret)567 dev_err(&pdev->dev, "failed to shutdown\n");568}569 570static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);571 572static struct platform_driver brcm_ahci_driver = {573 .probe = brcm_ahci_probe,574 .remove_new = brcm_ahci_remove,575 .shutdown = brcm_ahci_shutdown,576 .driver = {577 .name = DRV_NAME,578 .of_match_table = ahci_of_match,579 .pm = &ahci_brcm_pm_ops,580 },581};582module_platform_driver(brcm_ahci_driver);583 584MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver");585MODULE_AUTHOR("Brian Norris");586MODULE_LICENSE("GPL");587MODULE_ALIAS("platform:sata-brcmstb");588