root/drivers/ata/ahci_mtk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mtk_ahci_platform_resets
  2. mtk_ahci_parse_property
  3. mtk_ahci_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * MediaTek AHCI SATA driver
   4  *
   5  * Copyright (c) 2017 MediaTek Inc.
   6  * Author: Ryder Lee <ryder.lee@mediatek.com>
   7  */
   8 
   9 #include <linux/ahci_platform.h>
  10 #include <linux/kernel.h>
  11 #include <linux/libata.h>
  12 #include <linux/mfd/syscon.h>
  13 #include <linux/module.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/pm.h>
  16 #include <linux/regmap.h>
  17 #include <linux/reset.h>
  18 #include "ahci.h"
  19 
  20 #define DRV_NAME                "ahci-mtk"
  21 
  22 #define SYS_CFG                 0x14
  23 #define SYS_CFG_SATA_MSK        GENMASK(31, 30)
  24 #define SYS_CFG_SATA_EN         BIT(31)
  25 
  26 struct mtk_ahci_plat {
  27         struct regmap *mode;
  28         struct reset_control *axi_rst;
  29         struct reset_control *sw_rst;
  30         struct reset_control *reg_rst;
  31 };
  32 
  33 static const struct ata_port_info ahci_port_info = {
  34         .flags          = AHCI_FLAG_COMMON,
  35         .pio_mask       = ATA_PIO4,
  36         .udma_mask      = ATA_UDMA6,
  37         .port_ops       = &ahci_platform_ops,
  38 };
  39 
  40 static struct scsi_host_template ahci_platform_sht = {
  41         AHCI_SHT(DRV_NAME),
  42 };
  43 
  44 static int mtk_ahci_platform_resets(struct ahci_host_priv *hpriv,
  45                                     struct device *dev)
  46 {
  47         struct mtk_ahci_plat *plat = hpriv->plat_data;
  48         int err;
  49 
  50         /* reset AXI bus and PHY part */
  51         plat->axi_rst = devm_reset_control_get_optional_exclusive(dev, "axi");
  52         if (PTR_ERR(plat->axi_rst) == -EPROBE_DEFER)
  53                 return PTR_ERR(plat->axi_rst);
  54 
  55         plat->sw_rst = devm_reset_control_get_optional_exclusive(dev, "sw");
  56         if (PTR_ERR(plat->sw_rst) == -EPROBE_DEFER)
  57                 return PTR_ERR(plat->sw_rst);
  58 
  59         plat->reg_rst = devm_reset_control_get_optional_exclusive(dev, "reg");
  60         if (PTR_ERR(plat->reg_rst) == -EPROBE_DEFER)
  61                 return PTR_ERR(plat->reg_rst);
  62 
  63         err = reset_control_assert(plat->axi_rst);
  64         if (err) {
  65                 dev_err(dev, "failed to assert AXI bus\n");
  66                 return err;
  67         }
  68 
  69         err = reset_control_assert(plat->sw_rst);
  70         if (err) {
  71                 dev_err(dev, "failed to assert PHY digital part\n");
  72                 return err;
  73         }
  74 
  75         err = reset_control_assert(plat->reg_rst);
  76         if (err) {
  77                 dev_err(dev, "failed to assert PHY register part\n");
  78                 return err;
  79         }
  80 
  81         err = reset_control_deassert(plat->reg_rst);
  82         if (err) {
  83                 dev_err(dev, "failed to deassert PHY register part\n");
  84                 return err;
  85         }
  86 
  87         err = reset_control_deassert(plat->sw_rst);
  88         if (err) {
  89                 dev_err(dev, "failed to deassert PHY digital part\n");
  90                 return err;
  91         }
  92 
  93         err = reset_control_deassert(plat->axi_rst);
  94         if (err) {
  95                 dev_err(dev, "failed to deassert AXI bus\n");
  96                 return err;
  97         }
  98 
  99         return 0;
 100 }
 101 
 102 static int mtk_ahci_parse_property(struct ahci_host_priv *hpriv,
 103                                    struct device *dev)
 104 {
 105         struct mtk_ahci_plat *plat = hpriv->plat_data;
 106         struct device_node *np = dev->of_node;
 107 
 108         /* enable SATA function if needed */
 109         if (of_find_property(np, "mediatek,phy-mode", NULL)) {
 110                 plat->mode = syscon_regmap_lookup_by_phandle(
 111                                         np, "mediatek,phy-mode");
 112                 if (IS_ERR(plat->mode)) {
 113                         dev_err(dev, "missing phy-mode phandle\n");
 114                         return PTR_ERR(plat->mode);
 115                 }
 116 
 117                 regmap_update_bits(plat->mode, SYS_CFG, SYS_CFG_SATA_MSK,
 118                                    SYS_CFG_SATA_EN);
 119         }
 120 
 121         of_property_read_u32(np, "ports-implemented", &hpriv->force_port_map);
 122 
 123         return 0;
 124 }
 125 
 126 static int mtk_ahci_probe(struct platform_device *pdev)
 127 {
 128         struct device *dev = &pdev->dev;
 129         struct mtk_ahci_plat *plat;
 130         struct ahci_host_priv *hpriv;
 131         int err;
 132 
 133         plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
 134         if (!plat)
 135                 return -ENOMEM;
 136 
 137         hpriv = ahci_platform_get_resources(pdev, 0);
 138         if (IS_ERR(hpriv))
 139                 return PTR_ERR(hpriv);
 140 
 141         hpriv->plat_data = plat;
 142 
 143         err = mtk_ahci_parse_property(hpriv, dev);
 144         if (err)
 145                 return err;
 146 
 147         err = mtk_ahci_platform_resets(hpriv, dev);
 148         if (err)
 149                 return err;
 150 
 151         err = ahci_platform_enable_resources(hpriv);
 152         if (err)
 153                 return err;
 154 
 155         err = ahci_platform_init_host(pdev, hpriv, &ahci_port_info,
 156                                       &ahci_platform_sht);
 157         if (err)
 158                 goto disable_resources;
 159 
 160         return 0;
 161 
 162 disable_resources:
 163         ahci_platform_disable_resources(hpriv);
 164         return err;
 165 }
 166 
 167 static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
 168                          ahci_platform_resume);
 169 
 170 static const struct of_device_id ahci_of_match[] = {
 171         { .compatible = "mediatek,mtk-ahci", },
 172         {},
 173 };
 174 MODULE_DEVICE_TABLE(of, ahci_of_match);
 175 
 176 static struct platform_driver mtk_ahci_driver = {
 177         .probe = mtk_ahci_probe,
 178         .remove = ata_platform_remove_one,
 179         .driver = {
 180                 .name = DRV_NAME,
 181                 .of_match_table = ahci_of_match,
 182                 .pm = &ahci_pm_ops,
 183         },
 184 };
 185 module_platform_driver(mtk_ahci_driver);
 186 
 187 MODULE_DESCRIPTION("MediaTek SATA AHCI Driver");
 188 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */