Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

Linux/drivers/mfd/tc6387xb.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us