Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * TX4939 internal RTC driver
  3  * Based on RBTX49xx patch from CELF patch archive.
  4  *
  5  * This file is subject to the terms and conditions of the GNU General Public
  6  * License.  See the file "COPYING" in the main directory of this archive
  7  * for more details.
  8  *
  9  * (C) Copyright TOSHIBA CORPORATION 2005-2007
 10  */
 11 #include <linux/rtc.h>
 12 #include <linux/platform_device.h>
 13 #include <linux/interrupt.h>
 14 #include <linux/io.h>
 15 #include <asm/txx9/tx4939.h>
 16 
 17 struct tx4939rtc_plat_data {
 18         struct rtc_device *rtc;
 19         struct tx4939_rtc_reg __iomem *rtcreg;
 20 };
 21 
 22 static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev)
 23 {
 24         return platform_get_drvdata(to_platform_device(dev));
 25 }
 26 
 27 static int tx4939_rtc_cmd(struct tx4939_rtc_reg __iomem *rtcreg, int cmd)
 28 {
 29         int i = 0;
 30 
 31         __raw_writel(cmd, &rtcreg->ctl);
 32         /* This might take 30us (next 32.768KHz clock) */
 33         while (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_BUSY) {
 34                 /* timeout on approx. 100us (@ GBUS200MHz) */
 35                 if (i++ > 200 * 100)
 36                         return -EBUSY;
 37                 cpu_relax();
 38         }
 39         return 0;
 40 }
 41 
 42 static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs)
 43 {
 44         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 45         struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 46         int i, ret;
 47         unsigned char buf[6];
 48 
 49         buf[0] = 0;
 50         buf[1] = 0;
 51         buf[2] = secs;
 52         buf[3] = secs >> 8;
 53         buf[4] = secs >> 16;
 54         buf[5] = secs >> 24;
 55         spin_lock_irq(&pdata->rtc->irq_lock);
 56         __raw_writel(0, &rtcreg->adr);
 57         for (i = 0; i < 6; i++)
 58                 __raw_writel(buf[i], &rtcreg->dat);
 59         ret = tx4939_rtc_cmd(rtcreg,
 60                              TX4939_RTCCTL_COMMAND_SETTIME |
 61                              (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
 62         spin_unlock_irq(&pdata->rtc->irq_lock);
 63         return ret;
 64 }
 65 
 66 static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm)
 67 {
 68         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 69         struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 70         int i, ret;
 71         unsigned long sec;
 72         unsigned char buf[6];
 73 
 74         spin_lock_irq(&pdata->rtc->irq_lock);
 75         ret = tx4939_rtc_cmd(rtcreg,
 76                              TX4939_RTCCTL_COMMAND_GETTIME |
 77                              (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
 78         if (ret) {
 79                 spin_unlock_irq(&pdata->rtc->irq_lock);
 80                 return ret;
 81         }
 82         __raw_writel(2, &rtcreg->adr);
 83         for (i = 2; i < 6; i++)
 84                 buf[i] = __raw_readl(&rtcreg->dat);
 85         spin_unlock_irq(&pdata->rtc->irq_lock);
 86         sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
 87         rtc_time_to_tm(sec, tm);
 88         return rtc_valid_tm(tm);
 89 }
 90 
 91 static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 92 {
 93         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 94         struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 95         int i, ret;
 96         unsigned long sec;
 97         unsigned char buf[6];
 98 
 99         if (alrm->time.tm_sec < 0 ||
100             alrm->time.tm_min < 0 ||
101             alrm->time.tm_hour < 0 ||
102             alrm->time.tm_mday < 0 ||
103             alrm->time.tm_mon < 0 ||
104             alrm->time.tm_year < 0)
105                 return -EINVAL;
106         rtc_tm_to_time(&alrm->time, &sec);
107         buf[0] = 0;
108         buf[1] = 0;
109         buf[2] = sec;
110         buf[3] = sec >> 8;
111         buf[4] = sec >> 16;
112         buf[5] = sec >> 24;
113         spin_lock_irq(&pdata->rtc->irq_lock);
114         __raw_writel(0, &rtcreg->adr);
115         for (i = 0; i < 6; i++)
116                 __raw_writel(buf[i], &rtcreg->dat);
117         ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM |
118                              (alrm->enabled ? TX4939_RTCCTL_ALME : 0));
119         spin_unlock_irq(&pdata->rtc->irq_lock);
120         return ret;
121 }
122 
123 static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
124 {
125         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
126         struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
127         int i, ret;
128         unsigned long sec;
129         unsigned char buf[6];
130         u32 ctl;
131 
132         spin_lock_irq(&pdata->rtc->irq_lock);
133         ret = tx4939_rtc_cmd(rtcreg,
134                              TX4939_RTCCTL_COMMAND_GETALARM |
135                              (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
136         if (ret) {
137                 spin_unlock_irq(&pdata->rtc->irq_lock);
138                 return ret;
139         }
140         __raw_writel(2, &rtcreg->adr);
141         for (i = 2; i < 6; i++)
142                 buf[i] = __raw_readl(&rtcreg->dat);
143         ctl = __raw_readl(&rtcreg->ctl);
144         alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
145         alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
146         spin_unlock_irq(&pdata->rtc->irq_lock);
147         sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
148         rtc_time_to_tm(sec, &alrm->time);
149         return rtc_valid_tm(&alrm->time);
150 }
151 
152 static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
153 {
154         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
155 
156         spin_lock_irq(&pdata->rtc->irq_lock);
157         tx4939_rtc_cmd(pdata->rtcreg,
158                        TX4939_RTCCTL_COMMAND_NOP |
159                        (enabled ? TX4939_RTCCTL_ALME : 0));
160         spin_unlock_irq(&pdata->rtc->irq_lock);
161         return 0;
162 }
163 
164 static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id)
165 {
166         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev_id);
167         struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
168         unsigned long events = RTC_IRQF;
169 
170         spin_lock(&pdata->rtc->irq_lock);
171         if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) {
172                 events |= RTC_AF;
173                 tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP);
174         }
175         spin_unlock(&pdata->rtc->irq_lock);
176         rtc_update_irq(pdata->rtc, 1, events);
177         return IRQ_HANDLED;
178 }
179 
180 static const struct rtc_class_ops tx4939_rtc_ops = {
181         .read_time              = tx4939_rtc_read_time,
182         .read_alarm             = tx4939_rtc_read_alarm,
183         .set_alarm              = tx4939_rtc_set_alarm,
184         .set_mmss               = tx4939_rtc_set_mmss,
185         .alarm_irq_enable       = tx4939_rtc_alarm_irq_enable,
186 };
187 
188 static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj,
189                                      struct bin_attribute *bin_attr,
190                                      char *buf, loff_t pos, size_t size)
191 {
192         struct device *dev = container_of(kobj, struct device, kobj);
193         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
194         struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
195         ssize_t count;
196 
197         spin_lock_irq(&pdata->rtc->irq_lock);
198         for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
199              count++, size--) {
200                 __raw_writel(pos++, &rtcreg->adr);
201                 *buf++ = __raw_readl(&rtcreg->dat);
202         }
203         spin_unlock_irq(&pdata->rtc->irq_lock);
204         return count;
205 }
206 
207 static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj,
208                                       struct bin_attribute *bin_attr,
209                                       char *buf, loff_t pos, size_t size)
210 {
211         struct device *dev = container_of(kobj, struct device, kobj);
212         struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
213         struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
214         ssize_t count;
215 
216         spin_lock_irq(&pdata->rtc->irq_lock);
217         for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
218              count++, size--) {
219                 __raw_writel(pos++, &rtcreg->adr);
220                 __raw_writel(*buf++, &rtcreg->dat);
221         }
222         spin_unlock_irq(&pdata->rtc->irq_lock);
223         return count;
224 }
225 
226 static struct bin_attribute tx4939_rtc_nvram_attr = {
227         .attr = {
228                 .name = "nvram",
229                 .mode = S_IRUGO | S_IWUSR,
230         },
231         .size = TX4939_RTC_REG_RAMSIZE,
232         .read = tx4939_rtc_nvram_read,
233         .write = tx4939_rtc_nvram_write,
234 };
235 
236 static int __init tx4939_rtc_probe(struct platform_device *pdev)
237 {
238         struct rtc_device *rtc;
239         struct tx4939rtc_plat_data *pdata;
240         struct resource *res;
241         int irq, ret;
242 
243         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
244         if (!res)
245                 return -ENODEV;
246         irq = platform_get_irq(pdev, 0);
247         if (irq < 0)
248                 return -ENODEV;
249         pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
250         if (!pdata)
251                 return -ENOMEM;
252         platform_set_drvdata(pdev, pdata);
253 
254         if (!devm_request_mem_region(&pdev->dev, res->start,
255                                      resource_size(res), pdev->name))
256                 return -EBUSY;
257         pdata->rtcreg = devm_ioremap(&pdev->dev, res->start,
258                                      resource_size(res));
259         if (!pdata->rtcreg)
260                 return -EBUSY;
261 
262         tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
263         if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt,
264                              IRQF_DISABLED, pdev->name, &pdev->dev) < 0)
265                 return -EBUSY;
266         rtc = rtc_device_register(pdev->name, &pdev->dev,
267                                   &tx4939_rtc_ops, THIS_MODULE);
268         if (IS_ERR(rtc))
269                 return PTR_ERR(rtc);
270         pdata->rtc = rtc;
271         ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
272         if (ret)
273                 rtc_device_unregister(rtc);
274         return ret;
275 }
276 
277 static int __exit tx4939_rtc_remove(struct platform_device *pdev)
278 {
279         struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev);
280         struct rtc_device *rtc = pdata->rtc;
281 
282         spin_lock_irq(&rtc->irq_lock);
283         tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
284         spin_unlock_irq(&rtc->irq_lock);
285         sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
286         rtc_device_unregister(rtc);
287         platform_set_drvdata(pdev, NULL);
288         return 0;
289 }
290 
291 static struct platform_driver tx4939_rtc_driver = {
292         .remove         = __exit_p(tx4939_rtc_remove),
293         .driver         = {
294                 .name   = "tx4939rtc",
295                 .owner  = THIS_MODULE,
296         },
297 };
298 
299 static int __init tx4939rtc_init(void)
300 {
301         return platform_driver_probe(&tx4939_rtc_driver, tx4939_rtc_probe);
302 }
303 
304 static void __exit tx4939rtc_exit(void)
305 {
306         platform_driver_unregister(&tx4939_rtc_driver);
307 }
308 
309 module_init(tx4939rtc_init);
310 module_exit(tx4939rtc_exit);
311 
312 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
313 MODULE_DESCRIPTION("TX4939 internal RTC driver");
314 MODULE_LICENSE("GPL");
315 MODULE_ALIAS("platform:tx4939rtc");
316 
  This page was automatically generated by the LXR engine.