Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 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

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 
154         tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
155         if (!tc6387xb)
156                 return -ENOMEM;
157 
158         ret  = platform_get_irq(dev, 0);
159         if (ret >= 0)
160                 irq = ret;
161         else
162                 goto err_no_irq;
163 
164         clk32k = clk_get(&dev->dev, "CLK_CK32K");
165         if (IS_ERR(clk32k)) {
166                 ret = PTR_ERR(clk32k);
167                 goto err_no_clk;
168         }
169 
170         rscr = &tc6387xb->rscr;
171         rscr->name = "tc6387xb-core";
172         rscr->start = iomem->start;
173         rscr->end = iomem->start + 0xff;
174         rscr->flags = IORESOURCE_MEM;
175 
176         ret = request_resource(iomem, rscr);
177         if (ret)
178                 goto err_resource;
179 
180         tc6387xb->scr = ioremap(rscr->start, resource_size(rscr));
181         if (!tc6387xb->scr) {
182                 ret = -ENOMEM;
183                 goto err_ioremap;
184         }
185 
186         tc6387xb->clk32k = clk32k;
187         platform_set_drvdata(dev, tc6387xb);
188 
189         if (pdata && pdata->enable)
190                 pdata->enable(dev);
191 
192         printk(KERN_INFO "Toshiba tc6387xb initialised\n");
193 
194         ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
195                               ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
196 
197         if (!ret)
198                 return 0;
199 
200         iounmap(tc6387xb->scr);
201 err_ioremap:
202         release_resource(&tc6387xb->rscr);
203 err_resource:
204         clk_put(clk32k);
205 err_no_clk:
206 err_no_irq:
207         kfree(tc6387xb);
208         return ret;
209 }
210 
211 static int tc6387xb_remove(struct platform_device *dev)
212 {
213         struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
214 
215         mfd_remove_devices(&dev->dev);
216         iounmap(tc6387xb->scr);
217         release_resource(&tc6387xb->rscr);
218         clk_disable(tc6387xb->clk32k);
219         clk_put(tc6387xb->clk32k);
220         kfree(tc6387xb);
221 
222         return 0;
223 }
224 
225 
226 static struct platform_driver tc6387xb_platform_driver = {
227         .driver = {
228                 .name           = "tc6387xb",
229         },
230         .probe          = tc6387xb_probe,
231         .remove         = tc6387xb_remove,
232         .suspend        = tc6387xb_suspend,
233         .resume         = tc6387xb_resume,
234 };
235 
236 module_platform_driver(tc6387xb_platform_driver);
237 
238 MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
239 MODULE_LICENSE("GPL v2");
240 MODULE_AUTHOR("Ian Molton");
241 MODULE_ALIAS("platform:tc6387xb");
242 
243 

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