Blame view

drivers/rtc/rtc-pl030.c 3.49 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
a190901c6   Russell King   [RTC] rtc-pl030: ...
2
3
4
5
  /*
   *  linux/drivers/rtc/rtc-pl030.c
   *
   *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
a190901c6   Russell King   [RTC] rtc-pl030: ...
6
7
8
9
10
11
12
   */
  #include <linux/module.h>
  #include <linux/rtc.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/amba/bus.h>
  #include <linux/io.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
a190901c6   Russell King   [RTC] rtc-pl030: ...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  
  #define RTC_DR		(0)
  #define RTC_MR		(4)
  #define RTC_STAT	(8)
  #define RTC_EOI		(8)
  #define RTC_LR		(12)
  #define RTC_CR		(16)
  #define RTC_CR_MIE	(1 << 0)
  
  struct pl030_rtc {
  	struct rtc_device	*rtc;
  	void __iomem		*base;
  };
  
  static irqreturn_t pl030_interrupt(int irq, void *dev_id)
  {
  	struct pl030_rtc *rtc = dev_id;
  	writel(0, rtc->base + RTC_EOI);
  	return IRQ_HANDLED;
  }
a190901c6   Russell King   [RTC] rtc-pl030: ...
34
35
36
  static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
  	struct pl030_rtc *rtc = dev_get_drvdata(dev);
c33c4713c   Alexandre Belloni   rtc: pl030: switc...
37
  	rtc_time64_to_tm(readl(rtc->base + RTC_MR), &alrm->time);
a190901c6   Russell King   [RTC] rtc-pl030: ...
38
39
40
41
42
43
  	return 0;
  }
  
  static int pl030_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
  	struct pl030_rtc *rtc = dev_get_drvdata(dev);
a190901c6   Russell King   [RTC] rtc-pl030: ...
44

c33c4713c   Alexandre Belloni   rtc: pl030: switc...
45
46
47
  	writel(rtc_tm_to_time64(&alrm->time), rtc->base + RTC_MR);
  
  	return 0;
a190901c6   Russell King   [RTC] rtc-pl030: ...
48
49
50
51
52
  }
  
  static int pl030_read_time(struct device *dev, struct rtc_time *tm)
  {
  	struct pl030_rtc *rtc = dev_get_drvdata(dev);
c33c4713c   Alexandre Belloni   rtc: pl030: switc...
53
  	rtc_time64_to_tm(readl(rtc->base + RTC_DR), tm);
a190901c6   Russell King   [RTC] rtc-pl030: ...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  
  	return 0;
  }
  
  /*
   * Set the RTC time.  Unfortunately, we can't accurately set
   * the point at which the counter updates.
   *
   * Also, since RTC_LR is transferred to RTC_CR on next rising
   * edge of the 1Hz clock, we must write the time one second
   * in advance.
   */
  static int pl030_set_time(struct device *dev, struct rtc_time *tm)
  {
  	struct pl030_rtc *rtc = dev_get_drvdata(dev);
a190901c6   Russell King   [RTC] rtc-pl030: ...
69

c33c4713c   Alexandre Belloni   rtc: pl030: switc...
70
  	writel(rtc_tm_to_time64(tm) + 1, rtc->base + RTC_LR);
a190901c6   Russell King   [RTC] rtc-pl030: ...
71

c33c4713c   Alexandre Belloni   rtc: pl030: switc...
72
  	return 0;
a190901c6   Russell King   [RTC] rtc-pl030: ...
73
74
75
  }
  
  static const struct rtc_class_ops pl030_ops = {
a190901c6   Russell King   [RTC] rtc-pl030: ...
76
77
78
79
80
  	.read_time	= pl030_read_time,
  	.set_time	= pl030_set_time,
  	.read_alarm	= pl030_read_alarm,
  	.set_alarm	= pl030_set_alarm,
  };
aa25afad2   Russell King   ARM: amba: make p...
81
  static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
a190901c6   Russell King   [RTC] rtc-pl030: ...
82
83
84
85
86
87
88
  {
  	struct pl030_rtc *rtc;
  	int ret;
  
  	ret = amba_request_regions(dev, NULL);
  	if (ret)
  		goto err_req;
58c181c82   Sangjung Woo   drivers/rtc/rtc-p...
89
  	rtc = devm_kzalloc(&dev->dev, sizeof(*rtc), GFP_KERNEL);
a190901c6   Russell King   [RTC] rtc-pl030: ...
90
91
92
93
  	if (!rtc) {
  		ret = -ENOMEM;
  		goto err_rtc;
  	}
c778ec858   Alexandre Belloni   rtc: pl030: fix p...
94
95
96
97
98
99
100
  	rtc->rtc = devm_rtc_allocate_device(&dev->dev);
  	if (IS_ERR(rtc->rtc)) {
  		ret = PTR_ERR(rtc->rtc);
  		goto err_rtc;
  	}
  
  	rtc->rtc->ops = &pl030_ops;
9896169a1   Alexandre Belloni   rtc: pl030: set r...
101
  	rtc->rtc->range_max = U32_MAX;
dc890c2dc   Linus Walleij   [ARM] 5544/1: Tru...
102
  	rtc->base = ioremap(dev->res.start, resource_size(&dev->res));
a190901c6   Russell King   [RTC] rtc-pl030: ...
103
104
  	if (!rtc->base) {
  		ret = -ENOMEM;
58c181c82   Sangjung Woo   drivers/rtc/rtc-p...
105
  		goto err_rtc;
a190901c6   Russell King   [RTC] rtc-pl030: ...
106
107
108
109
110
111
  	}
  
  	__raw_writel(0, rtc->base + RTC_CR);
  	__raw_writel(0, rtc->base + RTC_EOI);
  
  	amba_set_drvdata(dev, rtc);
2f6e5f945   Yong Zhang   drivers/rtc: remo...
112
  	ret = request_irq(dev->irq[0], pl030_interrupt, 0,
a190901c6   Russell King   [RTC] rtc-pl030: ...
113
114
115
  			  "rtc-pl030", rtc);
  	if (ret)
  		goto err_irq;
c778ec858   Alexandre Belloni   rtc: pl030: fix p...
116
117
  	ret = rtc_register_device(rtc->rtc);
  	if (ret)
a190901c6   Russell King   [RTC] rtc-pl030: ...
118
  		goto err_reg;
a190901c6   Russell King   [RTC] rtc-pl030: ...
119
120
121
122
123
124
125
  
  	return 0;
  
   err_reg:
  	free_irq(dev->irq[0], rtc);
   err_irq:
  	iounmap(rtc->base);
a190901c6   Russell King   [RTC] rtc-pl030: ...
126
127
128
129
130
131
132
133
134
   err_rtc:
  	amba_release_regions(dev);
   err_req:
  	return ret;
  }
  
  static int pl030_remove(struct amba_device *dev)
  {
  	struct pl030_rtc *rtc = amba_get_drvdata(dev);
a190901c6   Russell King   [RTC] rtc-pl030: ...
135
136
137
  	writel(0, rtc->base + RTC_CR);
  
  	free_irq(dev->irq[0], rtc);
a190901c6   Russell King   [RTC] rtc-pl030: ...
138
  	iounmap(rtc->base);
a190901c6   Russell King   [RTC] rtc-pl030: ...
139
140
141
142
143
144
145
146
147
148
149
150
  	amba_release_regions(dev);
  
  	return 0;
  }
  
  static struct amba_id pl030_ids[] = {
  	{
  		.id	= 0x00041030,
  		.mask	= 0x000fffff,
  	},
  	{ 0, 0 },
  };
66bce5916   Dave Martin   rtc: pl030: Enabl...
151
  MODULE_DEVICE_TABLE(amba, pl030_ids);
a190901c6   Russell King   [RTC] rtc-pl030: ...
152
153
154
155
156
157
158
159
  static struct amba_driver pl030_driver = {
  	.drv		= {
  		.name	= "rtc-pl030",
  	},
  	.probe		= pl030_probe,
  	.remove		= pl030_remove,
  	.id_table	= pl030_ids,
  };
9e5ed094c   viresh kumar   ARM: 7362/1: AMBA...
160
  module_amba_driver(pl030_driver);
a190901c6   Russell King   [RTC] rtc-pl030: ...
161
162
163
164
  
  MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  MODULE_DESCRIPTION("ARM AMBA PL030 RTC Driver");
  MODULE_LICENSE("GPL");