From aff05ed5d103524bd69bd9d7b621c5c8a6c63198 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 30 Jul 2012 14:41:34 -0700 Subject: rtc: pl031: encapsulate per-vendor ops Move the per-vendor operations for this RTC into a encapsulating struct so we can have more per-vendor variables than just the ops. Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pl031.c | 61 +++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 22 deletions(-) (limited to 'drivers/rtc/rtc-pl031.c') diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index cc0533994f6e..575fbbf966db 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -68,7 +68,16 @@ #define RTC_TIMER_FREQ 32768 +/** + * struct pl031_vendor_data - per-vendor variations + * @ops: the vendor-specific operations used on this silicon version + */ +struct pl031_vendor_data { + struct rtc_class_ops ops; +}; + struct pl031_local { + struct pl031_vendor_data *vendor; struct rtc_device *rtc; void __iomem *base; u8 hw_designer; @@ -303,7 +312,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 +325,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)); @@ -383,48 +394,54 @@ 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, + }, }; /* 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, + }, }; /* 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, + }, }; 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}, }; -- cgit v1.2.3 From 1bb457fc9268bb75156af8db78b72a4463baaec4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 30 Jul 2012 14:41:36 -0700 Subject: rtc: pl031: use per-vendor variables for special init Instead of hard-checking for certain vendor codes, follow the pattern of other AMBA (PrimeCell) drivers and use variables in the vendor data. Get rid of the locally cached vendor and hardware revision since we already have the nice vendor data variable in the state. Signed-off-by: Linus Walleij Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pl031.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/rtc/rtc-pl031.c') diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 575fbbf966db..e66afb816d61 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -71,17 +71,21 @@ /** * 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 */ struct pl031_vendor_data { struct rtc_class_ops ops; + bool clockwatch; + bool st_weekday; }; 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, @@ -336,14 +340,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); @@ -351,7 +352,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 & @@ -413,6 +414,8 @@ static struct pl031_vendor_data stv1_pl031 = { .set_alarm = pl031_set_alarm, .alarm_irq_enable = pl031_alarm_irq_enable, }, + .clockwatch = true, + .st_weekday = true, }; /* And the second ST derivative */ @@ -424,6 +427,8 @@ static struct pl031_vendor_data stv2_pl031 = { .set_alarm = pl031_stv2_set_alarm, .alarm_irq_enable = pl031_alarm_irq_enable, }, + .clockwatch = true, + .st_weekday = true, }; static struct amba_id pl031_ids[] = { -- cgit v1.2.3 From 559a6fc0508392a665a26d93db9ff875bfdc6540 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Mon, 30 Jul 2012 14:41:39 -0700 Subject: rtc: pl031: fix up IRQ flags The pl031 interrupt is shared between the timer part and the clockwatch part of the same HW block on the ux500, so mark it IRQF_SHARED on this variant. This patch also adds the IRQF_NO_SUSPEND flag to the rtc irq on all variants as we don't want this pretty important IRQ to be disabled in suspend. Signed-off-by: Mattias Wallin Signed-off-by: Linus Walleij Reviewed-by: Rickard Andersson Reviewed-by: Jonas Aberg Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pl031.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/rtc/rtc-pl031.c') diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index e66afb816d61..08378e3cc21c 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -75,11 +75,13 @@ * 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 { @@ -373,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; } @@ -403,6 +405,7 @@ static struct pl031_vendor_data arm_pl031 = { .set_alarm = pl031_set_alarm, .alarm_irq_enable = pl031_alarm_irq_enable, }, + .irqflags = IRQF_NO_SUSPEND, }; /* The First ST derivative */ @@ -416,6 +419,7 @@ static struct pl031_vendor_data stv1_pl031 = { }, .clockwatch = true, .st_weekday = true, + .irqflags = IRQF_NO_SUSPEND, }; /* And the second ST derivative */ @@ -429,6 +433,11 @@ static struct pl031_vendor_data stv2_pl031 = { }, .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[] = { -- cgit v1.2.3