summaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-pl031.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 17:25:34 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 17:25:34 -0700
commit27c1ee3f929555b71fa39ec0d81a7e7185de1b16 (patch)
tree42e40bdfe4efac660d650658019391536ce67a42 /drivers/rtc/rtc-pl031.c
parent37cd9600a9e20359b0283983c9e3a55d84347168 (diff)
parent086ff4b3a7fb9cdf41e6a5d0ccd99b86d84633a1 (diff)
downloadtalos-op-linux-27c1ee3f929555b71fa39ec0d81a7e7185de1b16.tar.gz
talos-op-linux-27c1ee3f929555b71fa39ec0d81a7e7185de1b16.zip
Merge branch 'akpm' (Andrew's patch-bomb)
Merge Andrew's first set of patches: "Non-MM patches: - lots of misc bits - tree-wide have_clk() cleanups - quite a lot of printk tweaks. I draw your attention to "printk: convert the format for KERN_<LEVEL> to a 2 byte pattern" which looks a bit scary. But afaict it's solid. - backlight updates - lib/ feature work (notably the addition and use of memweight()) - checkpatch updates - rtc updates - nilfs updates - fatfs updates (partial, still waiting for acks) - kdump, proc, fork, IPC, sysctl, taskstats, pps, etc - new fault-injection feature work" * Merge emailed patches from Andrew Morton <akpm@linux-foundation.org>: (128 commits) drivers/misc/lkdtm.c: fix missing allocation failure check lib/scatterlist: do not re-write gfp_flags in __sg_alloc_table() fault-injection: add tool to run command with failslab or fail_page_alloc fault-injection: add selftests for cpu and memory hotplug powerpc: pSeries reconfig notifier error injection module memory: memory notifier error injection module PM: PM notifier error injection module cpu: rewrite cpu-notifier-error-inject module fault-injection: notifier error injection c/r: fcntl: add F_GETOWNER_UIDS option resource: make sure requested range is included in the root range include/linux/aio.h: cpp->C conversions fs: cachefiles: add support for large files in filesystem caching pps: return PTR_ERR on error in device_create taskstats: check nla_reserve() return sysctl: suppress kmemleak messages ipc: use Kconfig options for __ARCH_WANT_[COMPAT_]IPC_PARSE_VERSION ipc: compat: use signed size_t types for msgsnd and msgrcv ipc: allow compat IPC version field parsing if !ARCH_WANT_OLD_COMPAT_IPC ipc: add COMPAT_SHMLBA support ...
Diffstat (limited to 'drivers/rtc/rtc-pl031.c')
-rw-r--r--drivers/rtc/rtc-pl031.c95
1 files changed, 63 insertions, 32 deletions
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index cc0533994f6e..08378e3cc21c 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -68,11 +68,26 @@
#define RTC_TIMER_FREQ 32768
+/**
+ * struct pl031_vendor_data - per-vendor variations
+ * @ops: the vendor-specific operations used on this silicon version
+ * @clockwatch: if this is an ST Microelectronics silicon version with a
+ * clockwatch function
+ * @st_weekday: if this is an ST Microelectronics silicon version that need
+ * the weekday fix
+ * @irqflags: special IRQ flags per variant
+ */
+struct pl031_vendor_data {
+ struct rtc_class_ops ops;
+ bool clockwatch;
+ bool st_weekday;
+ unsigned long irqflags;
+};
+
struct pl031_local {
+ struct pl031_vendor_data *vendor;
struct rtc_device *rtc;
void __iomem *base;
- u8 hw_designer;
- u8 hw_revision:4;
};
static int pl031_alarm_irq_enable(struct device *dev,
@@ -303,7 +318,8 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret;
struct pl031_local *ldata;
- struct rtc_class_ops *ops = id->data;
+ struct pl031_vendor_data *vendor = id->data;
+ struct rtc_class_ops *ops = &vendor->ops;
unsigned long time;
ret = amba_request_regions(adev, NULL);
@@ -315,6 +331,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
ret = -ENOMEM;
goto out;
}
+ ldata->vendor = vendor;
ldata->base = ioremap(adev->res.start, resource_size(&adev->res));
@@ -325,14 +342,11 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, ldata);
- ldata->hw_designer = amba_manf(adev);
- ldata->hw_revision = amba_rev(adev);
-
- dev_dbg(&adev->dev, "designer ID = 0x%02x\n", ldata->hw_designer);
- dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision);
+ dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));
+ dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev));
/* Enable the clockwatch on ST Variants */
- if (ldata->hw_designer == AMBA_VENDOR_ST)
+ if (vendor->clockwatch)
writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
ldata->base + RTC_CR);
@@ -340,7 +354,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
* On ST PL031 variants, the RTC reset value does not provide correct
* weekday for 2000-01-01. Correct the erroneous sunday to saturday.
*/
- if (ldata->hw_designer == AMBA_VENDOR_ST) {
+ if (vendor->st_weekday) {
if (readl(ldata->base + RTC_YDR) == 0x2000) {
time = readl(ldata->base + RTC_DR);
if ((time &
@@ -361,7 +375,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
}
if (request_irq(adev->irq[0], pl031_interrupt,
- 0, "rtc-pl031", ldata)) {
+ vendor->irqflags, "rtc-pl031", ldata)) {
ret = -EIO;
goto out_no_irq;
}
@@ -383,48 +397,65 @@ err_req:
}
/* Operations for the original ARM version */
-static struct rtc_class_ops arm_pl031_ops = {
- .read_time = pl031_read_time,
- .set_time = pl031_set_time,
- .read_alarm = pl031_read_alarm,
- .set_alarm = pl031_set_alarm,
- .alarm_irq_enable = pl031_alarm_irq_enable,
+static struct pl031_vendor_data arm_pl031 = {
+ .ops = {
+ .read_time = pl031_read_time,
+ .set_time = pl031_set_time,
+ .read_alarm = pl031_read_alarm,
+ .set_alarm = pl031_set_alarm,
+ .alarm_irq_enable = pl031_alarm_irq_enable,
+ },
+ .irqflags = IRQF_NO_SUSPEND,
};
/* The First ST derivative */
-static struct rtc_class_ops stv1_pl031_ops = {
- .read_time = pl031_read_time,
- .set_time = pl031_set_time,
- .read_alarm = pl031_read_alarm,
- .set_alarm = pl031_set_alarm,
- .alarm_irq_enable = pl031_alarm_irq_enable,
+static struct pl031_vendor_data stv1_pl031 = {
+ .ops = {
+ .read_time = pl031_read_time,
+ .set_time = pl031_set_time,
+ .read_alarm = pl031_read_alarm,
+ .set_alarm = pl031_set_alarm,
+ .alarm_irq_enable = pl031_alarm_irq_enable,
+ },
+ .clockwatch = true,
+ .st_weekday = true,
+ .irqflags = IRQF_NO_SUSPEND,
};
/* And the second ST derivative */
-static struct rtc_class_ops stv2_pl031_ops = {
- .read_time = pl031_stv2_read_time,
- .set_time = pl031_stv2_set_time,
- .read_alarm = pl031_stv2_read_alarm,
- .set_alarm = pl031_stv2_set_alarm,
- .alarm_irq_enable = pl031_alarm_irq_enable,
+static struct pl031_vendor_data stv2_pl031 = {
+ .ops = {
+ .read_time = pl031_stv2_read_time,
+ .set_time = pl031_stv2_set_time,
+ .read_alarm = pl031_stv2_read_alarm,
+ .set_alarm = pl031_stv2_set_alarm,
+ .alarm_irq_enable = pl031_alarm_irq_enable,
+ },
+ .clockwatch = true,
+ .st_weekday = true,
+ /*
+ * This variant shares the IRQ with another block and must not
+ * suspend that IRQ line.
+ */
+ .irqflags = IRQF_SHARED | IRQF_NO_SUSPEND,
};
static struct amba_id pl031_ids[] = {
{
.id = 0x00041031,
.mask = 0x000fffff,
- .data = &arm_pl031_ops,
+ .data = &arm_pl031,
},
/* ST Micro variants */
{
.id = 0x00180031,
.mask = 0x00ffffff,
- .data = &stv1_pl031_ops,
+ .data = &stv1_pl031,
},
{
.id = 0x00280031,
.mask = 0x00ffffff,
- .data = &stv2_pl031_ops,
+ .data = &stv2_pl031,
},
{0, 0},
};
OpenPOWER on IntegriCloud