diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 17:25:34 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 17:25:34 -0700 |
commit | 27c1ee3f929555b71fa39ec0d81a7e7185de1b16 (patch) | |
tree | 42e40bdfe4efac660d650658019391536ce67a42 /drivers/rtc/rtc-pl031.c | |
parent | 37cd9600a9e20359b0283983c9e3a55d84347168 (diff) | |
parent | 086ff4b3a7fb9cdf41e6a5d0ccd99b86d84633a1 (diff) |
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.c | 95 |
1 files changed, 63 insertions, 32 deletions
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index cc0533994f6..08378e3cc21 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}, }; |