Blame view

drivers/rtc/rtc-ep93xx.c 5.29 KB
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * A driver for the RTC embedded in the Cirrus Logic EP93XX processors
   * Copyright (c) 2006 Tower Technologies
   *
   * Author: Alessandro Zummo <a.zummo@towertech.it>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  
  #include <linux/module.h>
  #include <linux/rtc.h>
  #include <linux/platform_device.h>
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
15
  #include <linux/io.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/gfp.h>
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
  #define EP93XX_RTC_DATA			0x000
  #define EP93XX_RTC_MATCH		0x004
  #define EP93XX_RTC_STATUS		0x008
  #define  EP93XX_RTC_STATUS_INTR		 (1<<0)
  #define EP93XX_RTC_LOAD			0x00C
  #define EP93XX_RTC_CONTROL		0x010
  #define  EP93XX_RTC_CONTROL_MIE		 (1<<0)
  #define EP93XX_RTC_SWCOMP		0x108
  #define  EP93XX_RTC_SWCOMP_DEL_MASK	 0x001f0000
  #define  EP93XX_RTC_SWCOMP_DEL_SHIFT	 16
  #define  EP93XX_RTC_SWCOMP_INT_MASK	 0x0000ffff
  #define  EP93XX_RTC_SWCOMP_INT_SHIFT	 0
  
  #define DRV_VERSION "0.3"
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
32

38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
33
34
35
36
37
38
  /*
   * struct device dev.platform_data is used to store our private data
   * because struct rtc_device does not have a variable to hold it.
   */
  struct ep93xx_rtc {
  	void __iomem	*mmio_base;
bf6ed027b   Axel Lin   rtc: ep93xx: Fix ...
39
  	struct rtc_device *rtc;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
40
  };
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
41

38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
42
  static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
43
44
  				unsigned short *delete)
  {
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
45
46
47
48
  	struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
  	unsigned long comp;
  
  	comp = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
49
50
  
  	if (preload)
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
51
52
  		*preload = (comp & EP93XX_RTC_SWCOMP_INT_MASK)
  				>> EP93XX_RTC_SWCOMP_INT_SHIFT;
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
53
54
  
  	if (delete)
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
55
56
  		*delete = (comp & EP93XX_RTC_SWCOMP_DEL_MASK)
  				>> EP93XX_RTC_SWCOMP_DEL_SHIFT;
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
57
58
59
60
61
62
  
  	return 0;
  }
  
  static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
  {
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
63
64
65
66
  	struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
  	unsigned long time;
  
  	 time = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
67
68
69
70
71
72
73
  
  	rtc_time_to_tm(time, tm);
  	return 0;
  }
  
  static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
  {
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
74
75
76
  	struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
  
  	__raw_writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
77
78
  	return 0;
  }
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
79
80
81
  static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
  {
  	unsigned short preload, delete;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
82
  	ep93xx_rtc_get_swcomp(dev, &preload, &delete);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
83

fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
84
85
86
87
88
89
90
  	seq_printf(seq, "preload\t\t: %d
  ", preload);
  	seq_printf(seq, "delete\t\t: %d
  ", delete);
  
  	return 0;
  }
ff8371ac9   David Brownell   [PATCH] constify ...
91
  static const struct rtc_class_ops ep93xx_rtc_ops = {
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
92
  	.read_time	= ep93xx_rtc_read_time,
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
93
94
95
  	.set_mmss	= ep93xx_rtc_set_mmss,
  	.proc		= ep93xx_rtc_proc,
  };
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
96
  static ssize_t ep93xx_rtc_show_comp_preload(struct device *dev,
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
97
98
99
  			struct device_attribute *attr, char *buf)
  {
  	unsigned short preload;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
100
  	ep93xx_rtc_get_swcomp(dev, &preload, NULL);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
101
102
103
104
  
  	return sprintf(buf, "%d
  ", preload);
  }
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
105
  static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_rtc_show_comp_preload, NULL);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
106

38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
107
  static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev,
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
108
109
110
  			struct device_attribute *attr, char *buf)
  {
  	unsigned short delete;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
111
  	ep93xx_rtc_get_swcomp(dev, NULL, &delete);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
112
113
114
115
  
  	return sprintf(buf, "%d
  ", delete);
  }
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
116
  static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
117

b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
118
119
120
121
122
123
124
125
126
  static struct attribute *ep93xx_rtc_attrs[] = {
  	&dev_attr_comp_preload.attr,
  	&dev_attr_comp_delete.attr,
  	NULL
  };
  
  static const struct attribute_group ep93xx_rtc_sysfs_files = {
  	.attrs	= ep93xx_rtc_attrs,
  };
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
127

38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
128
  static int __init ep93xx_rtc_probe(struct platform_device *pdev)
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
129
  {
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
130
131
  	struct ep93xx_rtc *ep93xx_rtc;
  	struct resource *res;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
132
  	int err;
b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
133
134
  	ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL);
  	if (!ep93xx_rtc)
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
135
136
137
  		return -ENOMEM;
  
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
138
139
  	if (!res)
  		return -ENXIO;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
140

b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
141
142
143
  	if (!devm_request_mem_region(&pdev->dev, res->start,
  				     resource_size(res), pdev->name))
  		return -EBUSY;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
144

b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
145
146
147
148
  	ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start,
  					     resource_size(res));
  	if (!ep93xx_rtc->mmio_base)
  		return -ENXIO;
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
149

38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
150
  	pdev->dev.platform_data = ep93xx_rtc;
bf6ed027b   Axel Lin   rtc: ep93xx: Fix ...
151
  	platform_set_drvdata(pdev, ep93xx_rtc);
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
152

bf6ed027b   Axel Lin   rtc: ep93xx: Fix ...
153
  	ep93xx_rtc->rtc = rtc_device_register(pdev->name,
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
154
  				&pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
bf6ed027b   Axel Lin   rtc: ep93xx: Fix ...
155
156
  	if (IS_ERR(ep93xx_rtc->rtc)) {
  		err = PTR_ERR(ep93xx_rtc->rtc);
b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
157
  		goto exit;
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
158
  	}
b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
159
  	err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
160
161
  	if (err)
  		goto fail;
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
162
163
  
  	return 0;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
164
165
  
  fail:
bf6ed027b   Axel Lin   rtc: ep93xx: Fix ...
166
  	rtc_device_unregister(ep93xx_rtc->rtc);
b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
167
  exit:
92d921c5d   Wolfram Sang   rtc: ep93xx: Init...
168
  	platform_set_drvdata(pdev, NULL);
b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
169
  	pdev->dev.platform_data = NULL;
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
170
  	return err;
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
171
  }
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
172
  static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
173
  {
bf6ed027b   Axel Lin   rtc: ep93xx: Fix ...
174
  	struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev);
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
175

b4877d2b3   H Hartley Sweeten   rtc-ep93xx.c: cle...
176
177
  	sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
  	platform_set_drvdata(pdev, NULL);
bf6ed027b   Axel Lin   rtc: ep93xx: Fix ...
178
  	rtc_device_unregister(ep93xx_rtc->rtc);
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
179
  	pdev->dev.platform_data = NULL;
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
180

fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
181
182
  	return 0;
  }
ad28a07bc   Kay Sievers   rtc: fix platform...
183
184
  /* work with hotplug and coldplug */
  MODULE_ALIAS("platform:ep93xx-rtc");
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
185
  static struct platform_driver ep93xx_rtc_driver = {
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
186
187
188
189
  	.driver		= {
  		.name	= "ep93xx-rtc",
  		.owner	= THIS_MODULE,
  	},
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
190
  	.remove		= __exit_p(ep93xx_rtc_remove),
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
191
192
193
194
  };
  
  static int __init ep93xx_rtc_init(void)
  {
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
195
          return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
196
197
198
199
  }
  
  static void __exit ep93xx_rtc_exit(void)
  {
38f7b009a   Hartley Sweeten   [ARM] 5452/1: ep9...
200
  	platform_driver_unregister(&ep93xx_rtc_driver);
fd507e2ff   Alessandro Zummo   [PATCH] RTC subsy...
201
202
203
204
205
206
207
208
209
  }
  
  MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
  MODULE_DESCRIPTION("EP93XX RTC driver");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);
  
  module_init(ep93xx_rtc_init);
  module_exit(ep93xx_rtc_exit);