root/drivers/mfd/tc6387xb.c

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

DEFINITIONS

This source file includes following definitions.
  1. tc6387xb_suspend
  2. tc6387xb_resume
  3. tc6387xb_mmc_pwr
  4. tc6387xb_mmc_clk_div
  5. tc6387xb_mmc_enable
  6. tc6387xb_mmc_disable
  7. tc6387xb_probe
  8. tc6387xb_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Toshiba TC6387XB support
   4  * Copyright (c) 2005 Ian Molton
   5  *
   6  * This file contains TC6387XB base support.
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/platform_device.h>
  11 #include <linux/clk.h>
  12 #include <linux/err.h>
  13 #include <linux/mfd/core.h>
  14 #include <linux/mfd/tmio.h>
  15 #include <linux/mfd/tc6387xb.h>
  16 #include <linux/slab.h>
  17 
  18 enum {
  19         TC6387XB_CELL_MMC,
  20 };
  21 
  22 struct tc6387xb {
  23         void __iomem *scr;
  24         struct clk *clk32k;
  25         struct resource rscr;
  26 };
  27 
  28 static struct resource tc6387xb_mmc_resources[] = {
  29         {
  30                 .start = 0x800,
  31                 .end   = 0x9ff,
  32                 .flags = IORESOURCE_MEM,
  33         },
  34         {
  35                 .start = 0,
  36                 .end   = 0,
  37                 .flags = IORESOURCE_IRQ,
  38         },
  39 };
  40 
  41 /*--------------------------------------------------------------------------*/
  42 
  43 #ifdef CONFIG_PM
  44 static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
  45 {
  46         struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
  47         struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
  48 
  49         if (pdata && pdata->suspend)
  50                 pdata->suspend(dev);
  51         clk_disable_unprepare(tc6387xb->clk32k);
  52 
  53         return 0;
  54 }
  55 
  56 static int tc6387xb_resume(struct platform_device *dev)
  57 {
  58         struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
  59         struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
  60 
  61         clk_prepare_enable(tc6387xb->clk32k);
  62         if (pdata && pdata->resume)
  63                 pdata->resume(dev);
  64 
  65         tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0,
  66                 tc6387xb_mmc_resources[0].start & 0xfffe);
  67 
  68         return 0;
  69 }
  70 #else
  71 #define tc6387xb_suspend  NULL
  72 #define tc6387xb_resume   NULL
  73 #endif
  74 
  75 /*--------------------------------------------------------------------------*/
  76 
  77 static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state)
  78 {
  79         struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
  80 
  81         tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state);
  82 }
  83 
  84 static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state)
  85 {
  86         struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
  87 
  88         tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state);
  89 }
  90 
  91 
  92 static int tc6387xb_mmc_enable(struct platform_device *mmc)
  93 {
  94         struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
  95 
  96         clk_prepare_enable(tc6387xb->clk32k);
  97 
  98         tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
  99                 tc6387xb_mmc_resources[0].start & 0xfffe);
 100 
 101         return 0;
 102 }
 103 
 104 static int tc6387xb_mmc_disable(struct platform_device *mmc)
 105 {
 106         struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
 107 
 108         clk_disable_unprepare(tc6387xb->clk32k);
 109 
 110         return 0;
 111 }
 112 
 113 static struct tmio_mmc_data tc6387xb_mmc_data = {
 114         .hclk = 24000000,
 115         .set_pwr = tc6387xb_mmc_pwr,
 116         .set_clk_div = tc6387xb_mmc_clk_div,
 117 };
 118 
 119 /*--------------------------------------------------------------------------*/
 120 
 121 static const struct mfd_cell tc6387xb_cells[] = {
 122         [TC6387XB_CELL_MMC] = {
 123                 .name = "tmio-mmc",
 124                 .enable = tc6387xb_mmc_enable,
 125                 .disable = tc6387xb_mmc_disable,
 126                 .platform_data = &tc6387xb_mmc_data,
 127                 .pdata_size    = sizeof(tc6387xb_mmc_data),
 128                 .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
 129                 .resources = tc6387xb_mmc_resources,
 130         },
 131 };
 132 
 133 static int tc6387xb_probe(struct platform_device *dev)
 134 {
 135         struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 136         struct resource *iomem, *rscr;
 137         struct clk *clk32k;
 138         struct tc6387xb *tc6387xb;
 139         int irq, ret;
 140 
 141         iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 142         if (!iomem)
 143                 return -EINVAL;
 144 
 145         tc6387xb = kzalloc(sizeof(*tc6387xb), GFP_KERNEL);
 146         if (!tc6387xb)
 147                 return -ENOMEM;
 148 
 149         ret  = platform_get_irq(dev, 0);
 150         if (ret >= 0)
 151                 irq = ret;
 152         else
 153                 goto err_no_irq;
 154 
 155         clk32k = clk_get(&dev->dev, "CLK_CK32K");
 156         if (IS_ERR(clk32k)) {
 157                 ret = PTR_ERR(clk32k);
 158                 goto err_no_clk;
 159         }
 160 
 161         rscr = &tc6387xb->rscr;
 162         rscr->name = "tc6387xb-core";
 163         rscr->start = iomem->start;
 164         rscr->end = iomem->start + 0xff;
 165         rscr->flags = IORESOURCE_MEM;
 166 
 167         ret = request_resource(iomem, rscr);
 168         if (ret)
 169                 goto err_resource;
 170 
 171         tc6387xb->scr = ioremap(rscr->start, resource_size(rscr));
 172         if (!tc6387xb->scr) {
 173                 ret = -ENOMEM;
 174                 goto err_ioremap;
 175         }
 176 
 177         tc6387xb->clk32k = clk32k;
 178         platform_set_drvdata(dev, tc6387xb);
 179 
 180         if (pdata && pdata->enable)
 181                 pdata->enable(dev);
 182 
 183         dev_info(&dev->dev, "Toshiba tc6387xb initialised\n");
 184 
 185         ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
 186                               ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
 187 
 188         if (!ret)
 189                 return 0;
 190 
 191         iounmap(tc6387xb->scr);
 192 err_ioremap:
 193         release_resource(&tc6387xb->rscr);
 194 err_resource:
 195         clk_put(clk32k);
 196 err_no_clk:
 197 err_no_irq:
 198         kfree(tc6387xb);
 199         return ret;
 200 }
 201 
 202 static int tc6387xb_remove(struct platform_device *dev)
 203 {
 204         struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
 205 
 206         mfd_remove_devices(&dev->dev);
 207         iounmap(tc6387xb->scr);
 208         release_resource(&tc6387xb->rscr);
 209         clk_disable_unprepare(tc6387xb->clk32k);
 210         clk_put(tc6387xb->clk32k);
 211         kfree(tc6387xb);
 212 
 213         return 0;
 214 }
 215 
 216 
 217 static struct platform_driver tc6387xb_platform_driver = {
 218         .driver = {
 219                 .name           = "tc6387xb",
 220         },
 221         .probe          = tc6387xb_probe,
 222         .remove         = tc6387xb_remove,
 223         .suspend        = tc6387xb_suspend,
 224         .resume         = tc6387xb_resume,
 225 };
 226 
 227 module_platform_driver(tc6387xb_platform_driver);
 228 
 229 MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
 230 MODULE_LICENSE("GPL v2");
 231 MODULE_AUTHOR("Ian Molton");
 232 MODULE_ALIAS("platform:tc6387xb");
 233 

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