Commit 03b1781aa978aab345b5a85d8596f8615281ba89

Authored by Vinayak Holikatti
Committed by James Bottomley
1 parent 39c60a0948

[SCSI] ufs: Add Platform glue driver for ufshcd

This patch adds Platform glue driver for ufshcd.

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Namjae Jeon <linkinjeon@gmail.com>
Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org>
Reviewed-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
Tested-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Vinayak Holikatti <vinholikatti@gmail.com>
Signed-off-by: Santosh Yaraganavi <santoshsy@gmail.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

Showing 3 changed files with 229 additions and 0 deletions Side-by-side Diff

drivers/scsi/ufs/Kconfig
... ... @@ -57,4 +57,15 @@
57 57 If you have a controller with this interface, say Y or M here.
58 58  
59 59 If unsure, say N.
  60 +
  61 +config SCSI_UFSHCD_PLATFORM
  62 + tristate "Platform bus based UFS Controller support"
  63 + depends on SCSI_UFSHCD
  64 + ---help---
  65 + This selects the UFS host controller support. Select this if
  66 + you have an UFS controller on Platform bus.
  67 +
  68 + If you have a controller with this interface, say Y or M here.
  69 +
  70 + If unsure, say N.
drivers/scsi/ufs/Makefile
1 1 # UFSHCD makefile
2 2 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
3 3 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
  4 +obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
drivers/scsi/ufs/ufshcd-pltfrm.c
  1 +/*
  2 + * Universal Flash Storage Host controller Platform bus based glue driver
  3 + *
  4 + * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
  5 + * Copyright (C) 2011-2013 Samsung India Software Operations
  6 + *
  7 + * Authors:
  8 + * Santosh Yaraganavi <santosh.sy@samsung.com>
  9 + * Vinayak Holikatti <h.vinayak@samsung.com>
  10 + *
  11 + * This program is free software; you can redistribute it and/or
  12 + * modify it under the terms of the GNU General Public License
  13 + * as published by the Free Software Foundation; either version 2
  14 + * of the License, or (at your option) any later version.
  15 + * See the COPYING file in the top-level directory or visit
  16 + * <http://www.gnu.org/licenses/gpl-2.0.html>
  17 + *
  18 + * This program is distributed in the hope that it will be useful,
  19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21 + * GNU General Public License for more details.
  22 + *
  23 + * This program is provided "AS IS" and "WITH ALL FAULTS" and
  24 + * without warranty of any kind. You are solely responsible for
  25 + * determining the appropriateness of using and distributing
  26 + * the program and assume all risks associated with your exercise
  27 + * of rights with respect to the program, including but not limited
  28 + * to infringement of third party rights, the risks and costs of
  29 + * program errors, damage to or loss of data, programs or equipment,
  30 + * and unavailability or interruption of operations. Under no
  31 + * circumstances will the contributor of this Program be liable for
  32 + * any damages of any kind arising from your use or distribution of
  33 + * this program.
  34 + */
  35 +
  36 +#include "ufshcd.h"
  37 +#include <linux/platform_device.h>
  38 +
  39 +#ifdef CONFIG_PM
  40 +/**
  41 + * ufshcd_pltfrm_suspend - suspend power management function
  42 + * @dev: pointer to device handle
  43 + *
  44 + *
  45 + * Returns 0
  46 + */
  47 +static int ufshcd_pltfrm_suspend(struct device *dev)
  48 +{
  49 + struct platform_device *pdev = to_platform_device(dev);
  50 + struct ufs_hba *hba = platform_get_drvdata(pdev);
  51 +
  52 + /*
  53 + * TODO:
  54 + * 1. Call ufshcd_suspend
  55 + * 2. Do bus specific power management
  56 + */
  57 +
  58 + disable_irq(hba->irq);
  59 +
  60 + return 0;
  61 +}
  62 +
  63 +/**
  64 + * ufshcd_pltfrm_resume - resume power management function
  65 + * @dev: pointer to device handle
  66 + *
  67 + * Returns 0
  68 + */
  69 +static int ufshcd_pltfrm_resume(struct device *dev)
  70 +{
  71 + struct platform_device *pdev = to_platform_device(dev);
  72 + struct ufs_hba *hba = platform_get_drvdata(pdev);
  73 +
  74 + /*
  75 + * TODO:
  76 + * 1. Call ufshcd_resume.
  77 + * 2. Do bus specific wake up
  78 + */
  79 +
  80 + enable_irq(hba->irq);
  81 +
  82 + return 0;
  83 +}
  84 +#else
  85 +#define ufshcd_pltfrm_suspend NULL
  86 +#define ufshcd_pltfrm_resume NULL
  87 +#endif
  88 +
  89 +/**
  90 + * ufshcd_pltfrm_probe - probe routine of the driver
  91 + * @pdev: pointer to Platform device handle
  92 + *
  93 + * Returns 0 on success, non-zero value on failure
  94 + */
  95 +static int ufshcd_pltfrm_probe(struct platform_device *pdev)
  96 +{
  97 + struct ufs_hba *hba;
  98 + void __iomem *mmio_base;
  99 + struct resource *mem_res;
  100 + struct resource *irq_res;
  101 + resource_size_t mem_size;
  102 + int err;
  103 + struct device *dev = &pdev->dev;
  104 +
  105 + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  106 + if (!mem_res) {
  107 + dev_err(&pdev->dev,
  108 + "Memory resource not available\n");
  109 + err = -ENODEV;
  110 + goto out_error;
  111 + }
  112 +
  113 + mem_size = resource_size(mem_res);
  114 + if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
  115 + dev_err(&pdev->dev,
  116 + "Cannot reserve the memory resource\n");
  117 + err = -EBUSY;
  118 + goto out_error;
  119 + }
  120 +
  121 + mmio_base = ioremap_nocache(mem_res->start, mem_size);
  122 + if (!mmio_base) {
  123 + dev_err(&pdev->dev, "memory map failed\n");
  124 + err = -ENOMEM;
  125 + goto out_release_regions;
  126 + }
  127 +
  128 + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  129 + if (!irq_res) {
  130 + dev_err(&pdev->dev, "IRQ resource not available\n");
  131 + err = -ENODEV;
  132 + goto out_iounmap;
  133 + }
  134 +
  135 + err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
  136 + if (err) {
  137 + dev_err(&pdev->dev, "set dma mask failed\n");
  138 + goto out_iounmap;
  139 + }
  140 +
  141 + err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
  142 + if (err) {
  143 + dev_err(&pdev->dev, "Intialization failed\n");
  144 + goto out_iounmap;
  145 + }
  146 +
  147 + platform_set_drvdata(pdev, hba);
  148 +
  149 + return 0;
  150 +
  151 +out_iounmap:
  152 + iounmap(mmio_base);
  153 +out_release_regions:
  154 + release_mem_region(mem_res->start, mem_size);
  155 +out_error:
  156 + return err;
  157 +}
  158 +
  159 +/**
  160 + * ufshcd_pltfrm_remove - remove platform driver routine
  161 + * @pdev: pointer to platform device handle
  162 + *
  163 + * Returns 0 on success, non-zero value on failure
  164 + */
  165 +static int ufshcd_pltfrm_remove(struct platform_device *pdev)
  166 +{
  167 + struct resource *mem_res;
  168 + resource_size_t mem_size;
  169 + struct ufs_hba *hba = platform_get_drvdata(pdev);
  170 +
  171 + disable_irq(hba->irq);
  172 +
  173 + /* Some buggy controllers raise interrupt after
  174 + * the resources are removed. So first we unregister the
  175 + * irq handler and then the resources used by driver
  176 + */
  177 +
  178 + free_irq(hba->irq, hba);
  179 + ufshcd_remove(hba);
  180 + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  181 + if (!mem_res)
  182 + dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
  183 + else {
  184 + mem_size = resource_size(mem_res);
  185 + release_mem_region(mem_res->start, mem_size);
  186 + }
  187 + platform_set_drvdata(pdev, NULL);
  188 + return 0;
  189 +}
  190 +
  191 +static const struct of_device_id ufs_of_match[] = {
  192 + { .compatible = "jedec,ufs-1.1"},
  193 +};
  194 +
  195 +static const struct dev_pm_ops ufshcd_dev_pm_ops = {
  196 + .suspend = ufshcd_pltfrm_suspend,
  197 + .resume = ufshcd_pltfrm_resume,
  198 +};
  199 +
  200 +static struct platform_driver ufshcd_pltfrm_driver = {
  201 + .probe = ufshcd_pltfrm_probe,
  202 + .remove = ufshcd_pltfrm_remove,
  203 + .driver = {
  204 + .name = "ufshcd",
  205 + .owner = THIS_MODULE,
  206 + .pm = &ufshcd_dev_pm_ops,
  207 + .of_match_table = ufs_of_match,
  208 + },
  209 +};
  210 +
  211 +module_platform_driver(ufshcd_pltfrm_driver);
  212 +
  213 +MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
  214 +MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
  215 +MODULE_DESCRIPTION("UFS host controller Pltform bus based glue driver");
  216 +MODULE_LICENSE("GPL");
  217 +MODULE_VERSION(UFSHCD_DRIVER_VERSION);