in ahci_brcm.c [434:545]
static int brcm_ahci_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
struct device *dev = &pdev->dev;
struct brcm_ahci_priv *priv;
struct ahci_host_priv *hpriv;
struct resource *res;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
of_id = of_match_node(ahci_of_match, pdev->dev.of_node);
if (!of_id)
return -ENODEV;
priv->version = (enum brcm_ahci_version)of_id->data;
priv->dev = dev;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl");
priv->top_ctrl = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->top_ctrl))
return PTR_ERR(priv->top_ctrl);
if (priv->version == BRCM_SATA_BCM7216) {
priv->rcdev_rescal = devm_reset_control_get_optional_shared(
&pdev->dev, "rescal");
if (IS_ERR(priv->rcdev_rescal))
return PTR_ERR(priv->rcdev_rescal);
}
priv->rcdev_ahci = devm_reset_control_get_optional(&pdev->dev, "ahci");
if (IS_ERR(priv->rcdev_ahci))
return PTR_ERR(priv->rcdev_ahci);
hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
hpriv->plat_data = priv;
hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;
switch (priv->version) {
case BRCM_SATA_BCM7425:
hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;
fallthrough;
case BRCM_SATA_NSP:
hpriv->flags |= AHCI_HFLAG_NO_NCQ;
priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
break;
default:
break;
}
ret = reset_control_reset(priv->rcdev_rescal);
if (ret)
return ret;
ret = reset_control_deassert(priv->rcdev_ahci);
if (ret)
return ret;
ret = ahci_platform_enable_clks(hpriv);
if (ret)
goto out_reset;
ret = ahci_platform_enable_regulators(hpriv);
if (ret)
goto out_disable_clks;
/* Must be first so as to configure endianness including that
* of the standard AHCI register space.
*/
brcm_sata_init(priv);
/* Initializes priv->port_mask which is used below */
priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);
if (!priv->port_mask) {
ret = -ENODEV;
goto out_disable_regulators;
}
/* Must be done before ahci_platform_enable_phys() */
brcm_sata_phys_enable(priv);
brcm_sata_alpm_init(hpriv);
ret = ahci_platform_enable_phys(hpriv);
if (ret)
goto out_disable_phys;
ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
&ahci_platform_sht);
if (ret)
goto out_disable_platform_phys;
dev_info(dev, "Broadcom AHCI SATA3 registered\n");
return 0;
out_disable_platform_phys:
ahci_platform_disable_phys(hpriv);
out_disable_phys:
brcm_sata_phys_disable(priv);
out_disable_regulators:
ahci_platform_disable_regulators(hpriv);
out_disable_clks:
ahci_platform_disable_clks(hpriv);
out_reset:
reset_control_assert(priv->rcdev_ahci);
reset_control_rearm(priv->rcdev_rescal);
return ret;
}