linux/drivers/ata/ahci_imx.c
<<
>>
Prefs
   1/*
   2 * copyright (c) 2013 Freescale Semiconductor, Inc.
   3 * Freescale IMX AHCI SATA platform driver
   4 *
   5 * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms and conditions of the GNU General Public License,
   9 * version 2, as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program. If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <linux/kernel.h>
  21#include <linux/module.h>
  22#include <linux/platform_device.h>
  23#include <linux/regmap.h>
  24#include <linux/ahci_platform.h>
  25#include <linux/of_device.h>
  26#include <linux/mfd/syscon.h>
  27#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
  28#include <linux/libata.h>
  29#include "ahci.h"
  30
  31enum {
  32        PORT_PHY_CTL = 0x178,                   /* Port0 PHY Control */
  33        PORT_PHY_CTL_PDDQ_LOC = 0x100000,       /* PORT_PHY_CTL bits */
  34        HOST_TIMER1MS = 0xe0,                   /* Timer 1-ms */
  35};
  36
  37enum ahci_imx_type {
  38        AHCI_IMX53,
  39        AHCI_IMX6Q,
  40};
  41
  42struct imx_ahci_priv {
  43        struct platform_device *ahci_pdev;
  44        enum ahci_imx_type type;
  45
  46        /* i.MX53 clock */
  47        struct clk *sata_gate_clk;
  48        /* Common clock */
  49        struct clk *sata_ref_clk;
  50        struct clk *ahb_clk;
  51
  52        struct regmap *gpr;
  53        bool no_device;
  54        bool first_time;
  55};
  56
  57static int ahci_imx_hotplug;
  58module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
  59MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
  60
  61static int imx_sata_clock_enable(struct device *dev)
  62{
  63        struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
  64        int ret;
  65
  66        if (imxpriv->type == AHCI_IMX53) {
  67                ret = clk_prepare_enable(imxpriv->sata_gate_clk);
  68                if (ret < 0) {
  69                        dev_err(dev, "prepare-enable sata_gate clock err:%d\n",
  70                                ret);
  71                        return ret;
  72                }
  73        }
  74
  75        ret = clk_prepare_enable(imxpriv->sata_ref_clk);
  76        if (ret < 0) {
  77                dev_err(dev, "prepare-enable sata_ref clock err:%d\n",
  78                        ret);
  79                goto clk_err;
  80        }
  81
  82        if (imxpriv->type == AHCI_IMX6Q) {
  83                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
  84                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
  85                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
  86        }
  87
  88        usleep_range(1000, 2000);
  89
  90        return 0;
  91
  92clk_err:
  93        if (imxpriv->type == AHCI_IMX53)
  94                clk_disable_unprepare(imxpriv->sata_gate_clk);
  95        return ret;
  96}
  97
  98static void imx_sata_clock_disable(struct device *dev)
  99{
 100        struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 101
 102        if (imxpriv->type == AHCI_IMX6Q) {
 103                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
 104                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
 105                                   !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
 106        }
 107
 108        clk_disable_unprepare(imxpriv->sata_ref_clk);
 109
 110        if (imxpriv->type == AHCI_IMX53)
 111                clk_disable_unprepare(imxpriv->sata_gate_clk);
 112}
 113
 114static void ahci_imx_error_handler(struct ata_port *ap)
 115{
 116        u32 reg_val;
 117        struct ata_device *dev;
 118        struct ata_host *host = dev_get_drvdata(ap->dev);
 119        struct ahci_host_priv *hpriv = host->private_data;
 120        void __iomem *mmio = hpriv->mmio;
 121        struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
 122
 123        ahci_error_handler(ap);
 124
 125        if (!(imxpriv->first_time) || ahci_imx_hotplug)
 126                return;
 127
 128        imxpriv->first_time = false;
 129
 130        ata_for_each_dev(dev, &ap->link, ENABLED)
 131                return;
 132        /*
 133         * Disable link to save power.  An imx ahci port can't be recovered
 134         * without full reset once the pddq mode is enabled making it
 135         * impossible to use as part of libata LPM.
 136         */
 137        reg_val = readl(mmio + PORT_PHY_CTL);
 138        writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
 139        imx_sata_clock_disable(ap->dev);
 140        imxpriv->no_device = true;
 141}
 142
 143static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
 144                       unsigned long deadline)
 145{
 146        struct ata_port *ap = link->ap;
 147        struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
 148        int ret = -EIO;
 149
 150        if (imxpriv->type == AHCI_IMX53)
 151                ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline);
 152        else if (imxpriv->type == AHCI_IMX6Q)
 153                ret = ahci_ops.softreset(link, class, deadline);
 154
 155        return ret;
 156}
 157
 158static struct ata_port_operations ahci_imx_ops = {
 159        .inherits       = &ahci_platform_ops,
 160        .error_handler  = ahci_imx_error_handler,
 161        .softreset      = ahci_imx_softreset,
 162};
 163
 164static const struct ata_port_info ahci_imx_port_info = {
 165        .flags          = AHCI_FLAG_COMMON,
 166        .pio_mask       = ATA_PIO4,
 167        .udma_mask      = ATA_UDMA6,
 168        .port_ops       = &ahci_imx_ops,
 169};
 170
 171static int imx_sata_init(struct device *dev, void __iomem *mmio)
 172{
 173        int ret = 0;
 174        unsigned int reg_val;
 175        struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 176
 177        ret = imx_sata_clock_enable(dev);
 178        if (ret < 0)
 179                return ret;
 180
 181        /*
 182         * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
 183         * and IP vendor specific register HOST_TIMER1MS.
 184         * Configure CAP_SSS (support stagered spin up).
 185         * Implement the port0.
 186         * Get the ahb clock rate, and configure the TIMER1MS register.
 187         */
 188        reg_val = readl(mmio + HOST_CAP);
 189        if (!(reg_val & HOST_CAP_SSS)) {
 190                reg_val |= HOST_CAP_SSS;
 191                writel(reg_val, mmio + HOST_CAP);
 192        }
 193        reg_val = readl(mmio + HOST_PORTS_IMPL);
 194        if (!(reg_val & 0x1)) {
 195                reg_val |= 0x1;
 196                writel(reg_val, mmio + HOST_PORTS_IMPL);
 197        }
 198
 199        reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
 200        writel(reg_val, mmio + HOST_TIMER1MS);
 201
 202        return 0;
 203}
 204
 205static void imx_sata_exit(struct device *dev)
 206{
 207        imx_sata_clock_disable(dev);
 208}
 209
 210static int imx_ahci_suspend(struct device *dev)
 211{
 212        struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
 213
 214        /*
 215         * If no_device is set, The CLKs had been gated off in the
 216         * initialization so don't do it again here.
 217         */
 218        if (!imxpriv->no_device)
 219                imx_sata_clock_disable(dev);
 220
 221        return 0;
 222}
 223
 224static int imx_ahci_resume(struct device *dev)
 225{
 226        struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
 227        int ret = 0;
 228
 229        if (!imxpriv->no_device)
 230                ret = imx_sata_clock_enable(dev);
 231
 232        return ret;
 233}
 234
 235static struct ahci_platform_data imx_sata_pdata = {
 236        .init           = imx_sata_init,
 237        .exit           = imx_sata_exit,
 238        .ata_port_info  = &ahci_imx_port_info,
 239        .suspend        = imx_ahci_suspend,
 240        .resume         = imx_ahci_resume,
 241
 242};
 243
 244static const struct of_device_id imx_ahci_of_match[] = {
 245        { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
 246        { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
 247        {},
 248};
 249MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
 250
 251static int imx_ahci_probe(struct platform_device *pdev)
 252{
 253        struct device *dev = &pdev->dev;
 254        struct resource *mem, *irq, res[2];
 255        const struct of_device_id *of_id;
 256        enum ahci_imx_type type;
 257        const struct ahci_platform_data *pdata = NULL;
 258        struct imx_ahci_priv *imxpriv;
 259        struct device *ahci_dev;
 260        struct platform_device *ahci_pdev;
 261        int ret;
 262
 263        of_id = of_match_device(imx_ahci_of_match, dev);
 264        if (!of_id)
 265                return -EINVAL;
 266
 267        type = (enum ahci_imx_type)of_id->data;
 268        pdata = &imx_sata_pdata;
 269
 270        imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
 271        if (!imxpriv) {
 272                dev_err(dev, "can't alloc ahci_host_priv\n");
 273                return -ENOMEM;
 274        }
 275
 276        ahci_pdev = platform_device_alloc("ahci", -1);
 277        if (!ahci_pdev)
 278                return -ENODEV;
 279
 280        ahci_dev = &ahci_pdev->dev;
 281        ahci_dev->parent = dev;
 282
 283        imxpriv->no_device = false;
 284        imxpriv->first_time = true;
 285        imxpriv->type = type;
 286
 287        imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
 288        if (IS_ERR(imxpriv->ahb_clk)) {
 289                dev_err(dev, "can't get ahb clock.\n");
 290                ret = PTR_ERR(imxpriv->ahb_clk);
 291                goto err_out;
 292        }
 293
 294        if (type == AHCI_IMX53) {
 295                imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate");
 296                if (IS_ERR(imxpriv->sata_gate_clk)) {
 297                        dev_err(dev, "can't get sata_gate clock.\n");
 298                        ret = PTR_ERR(imxpriv->sata_gate_clk);
 299                        goto err_out;
 300                }
 301        }
 302
 303        imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
 304        if (IS_ERR(imxpriv->sata_ref_clk)) {
 305                dev_err(dev, "can't get sata_ref clock.\n");
 306                ret = PTR_ERR(imxpriv->sata_ref_clk);
 307                goto err_out;
 308        }
 309
 310        imxpriv->ahci_pdev = ahci_pdev;
 311        platform_set_drvdata(pdev, imxpriv);
 312
 313        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 314        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 315        if (!mem || !irq) {
 316                dev_err(dev, "no mmio/irq resource\n");
 317                ret = -ENOMEM;
 318                goto err_out;
 319        }
 320
 321        res[0] = *mem;
 322        res[1] = *irq;
 323
 324        ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32);
 325        ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
 326        ahci_dev->of_node = dev->of_node;
 327
 328        if (type == AHCI_IMX6Q) {
 329                imxpriv->gpr = syscon_regmap_lookup_by_compatible(
 330                                                        "fsl,imx6q-iomuxc-gpr");
 331                if (IS_ERR(imxpriv->gpr)) {
 332                        dev_err(dev,
 333                                "failed to find fsl,imx6q-iomux-gpr regmap\n");
 334                        ret = PTR_ERR(imxpriv->gpr);
 335                        goto err_out;
 336                }
 337
 338                /*
 339                 * Set PHY Paremeters, two steps to configure the GPR13,
 340                 * one write for rest of parameters, mask of first write
 341                 * is 0x07fffffe, and the other one write for setting
 342                 * the mpll_clk_en happens in imx_sata_clock_enable().
 343                 */
 344                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
 345                                   IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
 346                                   IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
 347                                   IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
 348                                   IMX6Q_GPR13_SATA_SPD_MODE_MASK |
 349                                   IMX6Q_GPR13_SATA_MPLL_SS_EN |
 350                                   IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
 351                                   IMX6Q_GPR13_SATA_TX_BOOST_MASK |
 352                                   IMX6Q_GPR13_SATA_TX_LVL_MASK |
 353                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
 354                                   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
 355                                   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
 356                                   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
 357                                   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
 358                                   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
 359                                   IMX6Q_GPR13_SATA_MPLL_SS_EN |
 360                                   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
 361                                   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
 362                                   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
 363        }
 364
 365        ret = platform_device_add_resources(ahci_pdev, res, 2);
 366        if (ret)
 367                goto err_out;
 368
 369        ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata));
 370        if (ret)
 371                goto err_out;
 372
 373        ret = platform_device_add(ahci_pdev);
 374        if (ret) {
 375err_out:
 376                platform_device_put(ahci_pdev);
 377                return ret;
 378        }
 379
 380        return 0;
 381}
 382
 383static int imx_ahci_remove(struct platform_device *pdev)
 384{
 385        struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev);
 386        struct platform_device *ahci_pdev = imxpriv->ahci_pdev;
 387
 388        platform_device_unregister(ahci_pdev);
 389        return 0;
 390}
 391
 392static struct platform_driver imx_ahci_driver = {
 393        .probe = imx_ahci_probe,
 394        .remove = imx_ahci_remove,
 395        .driver = {
 396                .name = "ahci-imx",
 397                .owner = THIS_MODULE,
 398                .of_match_table = imx_ahci_of_match,
 399        },
 400};
 401module_platform_driver(imx_ahci_driver);
 402
 403MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver");
 404MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>");
 405MODULE_LICENSE("GPL");
 406MODULE_ALIAS("ahci:imx");
 407