linux/drivers/ata/ahci_da850.c
<<
>>
Prefs
   1/*
   2 * DaVinci DA850 AHCI SATA platform driver
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2, or (at your option)
   7 * any later version.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/pm.h>
  13#include <linux/device.h>
  14#include <linux/platform_device.h>
  15#include <linux/libata.h>
  16#include <linux/ahci_platform.h>
  17#include "ahci.h"
  18
  19#define DRV_NAME "ahci_da850"
  20
  21/* SATA PHY Control Register offset from AHCI base */
  22#define SATA_P0PHYCR_REG        0x178
  23
  24#define SATA_PHY_MPY(x)         ((x) << 0)
  25#define SATA_PHY_LOS(x)         ((x) << 6)
  26#define SATA_PHY_RXCDR(x)       ((x) << 10)
  27#define SATA_PHY_RXEQ(x)        ((x) << 13)
  28#define SATA_PHY_TXSWING(x)     ((x) << 19)
  29#define SATA_PHY_ENPLL(x)       ((x) << 31)
  30
  31/*
  32 * The multiplier needed for 1.5GHz PLL output.
  33 *
  34 * NOTE: This is currently hardcoded to be suitable for 100MHz crystal
  35 * frequency (which is used by DA850 EVM board) and may need to be changed
  36 * if you would like to use this driver on some other board.
  37 */
  38#define DA850_SATA_CLK_MULTIPLIER       7
  39
  40static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
  41                            void __iomem *ahci_base)
  42{
  43        unsigned int val;
  44
  45        /* Enable SATA clock receiver */
  46        val = readl(pwrdn_reg);
  47        val &= ~BIT(0);
  48        writel(val, pwrdn_reg);
  49
  50        val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) |
  51              SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) |
  52              SATA_PHY_ENPLL(1);
  53
  54        writel(val, ahci_base + SATA_P0PHYCR_REG);
  55}
  56
  57static const struct ata_port_info ahci_da850_port_info = {
  58        .flags          = AHCI_FLAG_COMMON,
  59        .pio_mask       = ATA_PIO4,
  60        .udma_mask      = ATA_UDMA6,
  61        .port_ops       = &ahci_platform_ops,
  62};
  63
  64static struct scsi_host_template ahci_platform_sht = {
  65        AHCI_SHT(DRV_NAME),
  66};
  67
  68static int ahci_da850_probe(struct platform_device *pdev)
  69{
  70        struct device *dev = &pdev->dev;
  71        struct ahci_host_priv *hpriv;
  72        struct resource *res;
  73        void __iomem *pwrdn_reg;
  74        int rc;
  75
  76        hpriv = ahci_platform_get_resources(pdev);
  77        if (IS_ERR(hpriv))
  78                return PTR_ERR(hpriv);
  79
  80        rc = ahci_platform_enable_resources(hpriv);
  81        if (rc)
  82                return rc;
  83
  84        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  85        if (!res)
  86                goto disable_resources;
  87
  88        pwrdn_reg = devm_ioremap(dev, res->start, resource_size(res));
  89        if (!pwrdn_reg)
  90                goto disable_resources;
  91
  92        da850_sata_init(dev, pwrdn_reg, hpriv->mmio);
  93
  94        rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info,
  95                                     &ahci_platform_sht);
  96        if (rc)
  97                goto disable_resources;
  98
  99        return 0;
 100disable_resources:
 101        ahci_platform_disable_resources(hpriv);
 102        return rc;
 103}
 104
 105static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend,
 106                         ahci_platform_resume);
 107
 108static struct platform_driver ahci_da850_driver = {
 109        .probe = ahci_da850_probe,
 110        .remove = ata_platform_remove_one,
 111        .driver = {
 112                .name = DRV_NAME,
 113                .pm = &ahci_da850_pm_ops,
 114        },
 115};
 116module_platform_driver(ahci_da850_driver);
 117
 118MODULE_DESCRIPTION("DaVinci DA850 AHCI SATA platform driver");
 119MODULE_AUTHOR("Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>");
 120MODULE_LICENSE("GPL");
 121