* [PATCH v2 0/6] ARM: sunxi: RTC support for A31/A23 @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Hi everyone, This is v2 of the sun6i RTC series. This series adds support for the RTC in A31 and A23 SoCs. The series applies to sunxi-next. The A31 has a new RTC block that is separate from the timer block. It has separate interrupts for each of the alarms, and a different format for the counter alarm. The driver has been tested on the A31 Hummingbird, and the A23 tablet I'm using to work on sun8i support. Patch 1 adds the driver for the RTC. Patch 2 is a minor cleanup. This makes rtc-sunxi depend on sun4i or sun7i, the 2 platforms the driver is actually used on. Patch 3 adds the RTC device node to the sun6i DTSI. Patch 4 adds the RTC device node to the sun8i DTSI. Patch 5 adds enables rtc-sun6i in the sunxi defconfig. Patch 6 adds enables rtc-sun6i in the multi_v7 defconfig. This patch applies to arm-soc/next/defconfig (e9a86d96) Changes since v1: - Enable rtc-sun6i in multi_v7_defconfig - Cleanup the time/date GET/SET macros - Use GENMASK for control register mask - Change Kconfig option to show 'A31' - Remove leftover comment from rtc-sun4i - Remove extra newline Cheers ChenYu Chen-Yu Tsai (6): rtc: sun6i: Add sun6i RTC driver rtc: sunxi: Depend on platforms sun4i/sun7i that actually have the rtc ARM: dts: sun6i: add rtc device node ARM: dts: sun8i: add rtc device node ARM: sunxi: Add A31 RTC driver to sunxi_defconfig ARM: sunxi: Add A31 RTC driver to multi_v7_defconfig .../devicetree/bindings/rtc/sun6i-rtc.txt | 17 + arch/arm/boot/dts/sun6i-a31.dtsi | 6 + arch/arm/boot/dts/sun8i-a23.dtsi | 6 + arch/arm/configs/multi_v7_defconfig | 1 + arch/arm/configs/sunxi_defconfig | 1 + drivers/rtc/Kconfig | 9 +- drivers/rtc/Makefile | 1 + drivers/rtc/rtc-sun6i.c | 448 +++++++++++++++++++++ 8 files changed, 488 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/rtc/sun6i-rtc.txt create mode 100644 drivers/rtc/rtc-sun6i.c -- 2.0.1 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 0/6] ARM: sunxi: RTC support for A31/A23 @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: linux-arm-kernel Hi everyone, This is v2 of the sun6i RTC series. This series adds support for the RTC in A31 and A23 SoCs. The series applies to sunxi-next. The A31 has a new RTC block that is separate from the timer block. It has separate interrupts for each of the alarms, and a different format for the counter alarm. The driver has been tested on the A31 Hummingbird, and the A23 tablet I'm using to work on sun8i support. Patch 1 adds the driver for the RTC. Patch 2 is a minor cleanup. This makes rtc-sunxi depend on sun4i or sun7i, the 2 platforms the driver is actually used on. Patch 3 adds the RTC device node to the sun6i DTSI. Patch 4 adds the RTC device node to the sun8i DTSI. Patch 5 adds enables rtc-sun6i in the sunxi defconfig. Patch 6 adds enables rtc-sun6i in the multi_v7 defconfig. This patch applies to arm-soc/next/defconfig (e9a86d96) Changes since v1: - Enable rtc-sun6i in multi_v7_defconfig - Cleanup the time/date GET/SET macros - Use GENMASK for control register mask - Change Kconfig option to show 'A31' - Remove leftover comment from rtc-sun4i - Remove extra newline Cheers ChenYu Chen-Yu Tsai (6): rtc: sun6i: Add sun6i RTC driver rtc: sunxi: Depend on platforms sun4i/sun7i that actually have the rtc ARM: dts: sun6i: add rtc device node ARM: dts: sun8i: add rtc device node ARM: sunxi: Add A31 RTC driver to sunxi_defconfig ARM: sunxi: Add A31 RTC driver to multi_v7_defconfig .../devicetree/bindings/rtc/sun6i-rtc.txt | 17 + arch/arm/boot/dts/sun6i-a31.dtsi | 6 + arch/arm/boot/dts/sun8i-a23.dtsi | 6 + arch/arm/configs/multi_v7_defconfig | 1 + arch/arm/configs/sunxi_defconfig | 1 + drivers/rtc/Kconfig | 9 +- drivers/rtc/Makefile | 1 + drivers/rtc/rtc-sun6i.c | 448 +++++++++++++++++++++ 8 files changed, 488 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/rtc/sun6i-rtc.txt create mode 100644 drivers/rtc/rtc-sun6i.c -- 2.0.1 ^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <1406126338-15062-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>]
* [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver 2014-07-23 14:38 ` Chen-Yu Tsai @ 2014-07-23 14:38 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw This patch introduces the driver for the RTC in the Allwinner A31 and A23 SoCs. Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the RTC in A31/A23 are a separate hardware block, which also contain a few controls for the RTC block hardware (a regulator and RTC block GPIO pin latches), while also having separate interrupts for the alarms. The hardware is different enough to make a different driver for it. Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> --- .../devicetree/bindings/rtc/sun6i-rtc.txt | 17 + drivers/rtc/Kconfig | 7 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-sun6i.c | 448 +++++++++++++++++++++ 4 files changed, 473 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/sun6i-rtc.txt create mode 100644 drivers/rtc/rtc-sun6i.c diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt new file mode 100644 index 0000000..b18927c --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt @@ -0,0 +1,17 @@ +* sun6i Real Time Clock + +RTC controller for the Allwinner A31 + +Required properties: +- compatible : Should be "allwinner,sun6i-a31-rtc" +- reg: physical base address of the controller and length of memory mapped + region. +- interrupts: IRQ line for the RTC alarm 0. + +Example: + +rtc: rtc@01f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = <0 40 4>; +}; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 0754f5c..dde2b57 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1167,6 +1167,13 @@ config RTC_DRV_SUN4V If you say Y here you will get support for the Hypervisor based RTC on SUN4V systems. +config RTC_DRV_SUN6I + tristate "Allwinner A31 RTC" + depends on MACH_SUN6I || MACH_SUN8I + help + If you say Y here you will get support for the RTC found on + Allwinner A31. + config RTC_DRV_SUNXI tristate "Allwinner sun4i/sun7i RTC" depends on ARCH_SUNXI diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 70347d0..a47df29 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -123,6 +123,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o +obj-$(CONFIG_RTC_DRV_SUN6I) += rtc-sun6i.o obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c new file mode 100644 index 0000000..069e8f9 --- /dev/null +++ b/drivers/rtc/rtc-sun6i.c @@ -0,0 +1,448 @@ +/* + * An RTC driver for Allwinner A31/A23 + * + * Copyright (c) 2014, Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> + * + * based on rtc-sunxi.c + * + * An RTC driver for Allwinner A10/A20 + * + * Copyright (c) 2013, Carlo Caione <carlo.caione-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/types.h> + +/* Control register */ +#define SUN6I_LOSC_CTRL 0x0000 +#define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) +#define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) +#define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) +#define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) + +/* RTC */ +#define SUN6I_RTC_YMD 0x0010 +#define SUN6I_RTC_HMS 0x0014 + +/* Alarm 0 (counter) */ +#define SUN6I_ALRM_COUNTER 0x0020 +#define SUN6I_ALRM_CUR_VAL 0x0024 +#define SUN6I_ALRM_EN 0x0028 +#define SUN6I_ALRM_EN_CNT_EN BIT(0) +#define SUN6I_ALRM_IRQ_EN 0x002c +#define SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN BIT(0) +#define SUN6I_ALRM_IRQ_STA 0x0030 +#define SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND BIT(0) + +/* Alarm 1 (wall clock) */ +#define SUN6I_ALRM1_EN 0x0044 +#define SUN6I_ALRM1_IRQ_EN 0x0048 +#define SUN6I_ALRM1_IRQ_STA 0x004c +#define SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND BIT(0) + +/* Alarm config */ +#define SUN6I_ALARM_CONFIG 0x0050 +#define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) + +/* + * Get date values + */ +#define SUN6I_DATE_GET_DAY_VALUE(x) ((x) & 0x0000001f) +#define SUN6I_DATE_GET_MON_VALUE(x) (((x) & 0x00000f00) >> 8) +#define SUN6I_DATE_GET_YEAR_VALUE(x) (((x) & 0x003f0000) >> 16) +#define SUN6I_LEAP_GET_VALUE(x) (((x) & 0x00400000) >> 22) + +/* + * Get time values + */ +#define SUN6I_TIME_GET_SEC_VALUE(x) ((x) & 0x0000003f) +#define SUN6I_TIME_GET_MIN_VALUE(x) (((x) & 0x00003f00) >> 8) +#define SUN6I_TIME_GET_HOUR_VALUE(x) (((x) & 0x001f0000) >> 16) + +/* + * Set date values + */ +#define SUN6I_DATE_SET_DAY_VALUE(x) ((x) & 0x0000001f) +#define SUN6I_DATE_SET_MON_VALUE(x) ((x) << 8 & 0x00000f00) +#define SUN6I_DATE_SET_YEAR_VALUE(x) ((x) << 16 & 0x003f0000) +#define SUN6I_LEAP_SET_VALUE(x) ((x) << 22 & 0x00400000) + +/* + * Set time values + */ +#define SUN6I_TIME_SET_SEC_VALUE(x) ((x) & 0x0000003f) +#define SUN6I_TIME_SET_MIN_VALUE(x) ((x) << 8 & 0x00003f00) +#define SUN6I_TIME_SET_HOUR_VALUE(x) ((x) << 16 & 0x001f0000) + +/* + * The year parameter passed to the driver is usually an offset relative to + * the year 1900. This macro is used to convert this offset to another one + * relative to the minimum year allowed by the hardware. + * + * The year range is 1970 - 2033. This range is selected to match Allwinner's + * driver, even though it is somewhat limited. + */ +#define SUN6I_YEAR_MIN 1970 +#define SUN6I_YEAR_MAX 2033 +#define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900) + +struct sun6i_rtc_dev { + struct rtc_device *rtc; + struct device *dev; + void __iomem *base; + int irq; + unsigned long alarm; +}; + +static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) +{ + struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; + u32 val; + + val = readl(chip->base + SUN6I_ALRM_IRQ_STA); + + if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { + val |= SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND; + writel(val, chip->base + SUN6I_ALRM_IRQ_STA); + + rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) +{ + u32 alrm_val = 0; + u32 alrm_irq_val = 0; + u32 alrm_wake_val = 0; + + if (to) { + alrm_val = SUN6I_ALRM_EN_CNT_EN; + alrm_irq_val = SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN; + alrm_wake_val = SUN6I_ALARM_CONFIG_WAKEUP; + } else { + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, + chip->base + SUN6I_ALRM_IRQ_STA); + } + + writel(alrm_val, chip->base + SUN6I_ALRM_EN); + writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); + writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); +} + +static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + u32 date, time; + + /* + * read again in case it changes + */ + do { + date = readl(chip->base + SUN6I_RTC_YMD); + time = readl(chip->base + SUN6I_RTC_HMS); + } while ((date != readl(chip->base + SUN6I_RTC_YMD)) || + (time != readl(chip->base + SUN6I_RTC_HMS))); + + rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time); + rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); + rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); + + rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); + rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date); + rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); + + rtc_tm->tm_mon -= 1; + + /* + * switch from (data_year->min)-relative offset to + * a (1900)-relative one + */ + rtc_tm->tm_year += SUN6I_YEAR_OFF; + + return rtc_valid_tm(rtc_tm); +} + +static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + u32 alrm_st; + u32 alrm_en; + + alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); + alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); + wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); + wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); + rtc_time_to_tm(chip->alarm, &wkalrm->time); + + return 0; +} + +static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + struct rtc_time *alrm_tm = &wkalrm->time; + struct rtc_time tm_now; + unsigned long time_now = 0; + unsigned long time_set = 0; + unsigned long time_gap = 0; + int ret = 0; + + ret = sun6i_rtc_gettime(dev, &tm_now); + if (ret < 0) { + dev_err(dev, "Error in getting time\n"); + return -EINVAL; + } + + rtc_tm_to_time(alrm_tm, &time_set); + rtc_tm_to_time(&tm_now, &time_now); + if (time_set <= time_now) { + dev_err(dev, "Date to set in the past\n"); + return -EINVAL; + } + + time_gap = time_set - time_now; + + if (time_gap > U32_MAX) { + dev_err(dev, "Date too far in the future\n"); + return -EINVAL; + } + + sun6i_rtc_setaie(0, chip); + writel(0, chip->base + SUN6I_ALRM_COUNTER); + usleep_range(100, 300); + + writel(time_gap, chip->base + SUN6I_ALRM_COUNTER); + chip->alarm = time_set; + + sun6i_rtc_setaie(wkalrm->enabled, chip); + + return 0; +} + +static int sun6i_rtc_wait(struct sun6i_rtc_dev *chip, int offset, + unsigned int mask, unsigned int ms_timeout) +{ + const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout); + u32 reg; + + do { + reg = readl(chip->base + offset); + reg &= mask; + + if (!reg) + return 0; + + } while (time_before(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + u32 date = 0; + u32 time = 0; + int year; + + year = rtc_tm->tm_year + 1900; + if (year < SUN6I_YEAR_MIN || year > SUN6I_YEAR_MAX) { + dev_err(dev, "rtc only supports year in range %d - %d\n", + SUN6I_YEAR_MIN, SUN6I_YEAR_MAX); + return -EINVAL; + } + + rtc_tm->tm_year -= SUN6I_YEAR_OFF; + rtc_tm->tm_mon += 1; + + date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | + SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | + SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); + + if (is_leap_year(year)) + date |= SUN6I_LEAP_SET_VALUE(1); + + time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | + SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | + SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); + + /* Check whether registers are writable */ + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, + SUN6I_LOSC_CTRL_ACC_MASK, 50)) { + dev_err(dev, "rtc is still busy.\n"); + return -EBUSY; + } + + writel(time, chip->base + SUN6I_RTC_HMS); + + /* + * After writing the RTC HH-MM-SS register, the + * SUN6I_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not + * be cleared until the real writing operation is finished + */ + + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, + SUN6I_LOSC_CTRL_RTC_HMS_ACC, 50)) { + dev_err(dev, "Failed to set rtc time.\n"); + return -ETIMEDOUT; + } + + writel(date, chip->base + SUN6I_RTC_YMD); + + /* + * After writing the RTC YY-MM-DD register, the + * SUN6I_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not + * be cleared until the real writing operation is finished + */ + + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, + SUN6I_LOSC_CTRL_RTC_YMD_ACC, 50)) { + dev_err(dev, "Failed to set rtc time.\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int sun6i_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + + if (!enabled) + sun6i_rtc_setaie(enabled, chip); + + return 0; +} + +static const struct rtc_class_ops sun6i_rtc_ops = { + .read_time = sun6i_rtc_gettime, + .set_time = sun6i_rtc_settime, + .read_alarm = sun6i_rtc_getalarm, + .set_alarm = sun6i_rtc_setalarm, + .alarm_irq_enable = sun6i_rtc_alarm_irq_enable +}; + +static int sun6i_rtc_probe(struct platform_device *pdev) +{ + struct sun6i_rtc_dev *chip; + struct resource *res; + int ret; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + platform_set_drvdata(pdev, chip); + chip->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + chip->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(chip->base)) + return PTR_ERR(chip->base); + + chip->irq = platform_get_irq(pdev, 0); + if (chip->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); + return chip->irq; + } + + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, + 0, dev_name(&pdev->dev), chip); + if (ret) { + dev_err(&pdev->dev, "Could not request IRQ\n"); + return ret; + } + + /* clear the alarm counter value */ + writel(0, chip->base + SUN6I_ALRM_COUNTER); + + /* disable counter alarm */ + writel(0, chip->base + SUN6I_ALRM_EN); + + /* disable counter alarm interrupt */ + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); + + /* disable week alarm */ + writel(0, chip->base + SUN6I_ALRM1_EN); + + /* disable week alarm interrupt */ + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); + + /* clear counter alarm pending interrupts */ + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + + SUN6I_ALRM_IRQ_STA); + + /* clear week alarm pending interrupts */ + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + + SUN6I_ALRM1_IRQ_STA); + + /* disable alarm wakeup */ + writel(0, chip->base + SUN6I_ALARM_CONFIG); + + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, + &sun6i_rtc_ops, THIS_MODULE); + if (IS_ERR(chip->rtc)) { + dev_err(&pdev->dev, "unable to register device\n"); + return PTR_ERR(chip->rtc); + } + + dev_info(&pdev->dev, "RTC enabled\n"); + + return 0; +} + +static int sun6i_rtc_remove(struct platform_device *pdev) +{ + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); + + rtc_device_unregister(chip->rtc); + + return 0; +} + +static const struct of_device_id sun6i_rtc_dt_ids[] = { + { .compatible = "allwinner,sun6i-a31-rtc" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); + +static struct platform_driver sun6i_rtc_driver = { + .probe = sun6i_rtc_probe, + .remove = sun6i_rtc_remove, + .driver = { + .name = "sun6i-rtc", + .owner = THIS_MODULE, + .of_match_table = sun6i_rtc_dt_ids, + }, +}; + +module_platform_driver(sun6i_rtc_driver); + +MODULE_DESCRIPTION("sun6i RTC driver"); +MODULE_AUTHOR("Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>"); +MODULE_LICENSE("GPL"); -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: linux-arm-kernel This patch introduces the driver for the RTC in the Allwinner A31 and A23 SoCs. Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the RTC in A31/A23 are a separate hardware block, which also contain a few controls for the RTC block hardware (a regulator and RTC block GPIO pin latches), while also having separate interrupts for the alarms. The hardware is different enough to make a different driver for it. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- .../devicetree/bindings/rtc/sun6i-rtc.txt | 17 + drivers/rtc/Kconfig | 7 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-sun6i.c | 448 +++++++++++++++++++++ 4 files changed, 473 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/sun6i-rtc.txt create mode 100644 drivers/rtc/rtc-sun6i.c diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt new file mode 100644 index 0000000..b18927c --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt @@ -0,0 +1,17 @@ +* sun6i Real Time Clock + +RTC controller for the Allwinner A31 + +Required properties: +- compatible : Should be "allwinner,sun6i-a31-rtc" +- reg: physical base address of the controller and length of memory mapped + region. +- interrupts: IRQ line for the RTC alarm 0. + +Example: + +rtc: rtc at 01f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = <0 40 4>; +}; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 0754f5c..dde2b57 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1167,6 +1167,13 @@ config RTC_DRV_SUN4V If you say Y here you will get support for the Hypervisor based RTC on SUN4V systems. +config RTC_DRV_SUN6I + tristate "Allwinner A31 RTC" + depends on MACH_SUN6I || MACH_SUN8I + help + If you say Y here you will get support for the RTC found on + Allwinner A31. + config RTC_DRV_SUNXI tristate "Allwinner sun4i/sun7i RTC" depends on ARCH_SUNXI diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 70347d0..a47df29 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -123,6 +123,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o +obj-$(CONFIG_RTC_DRV_SUN6I) += rtc-sun6i.o obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c new file mode 100644 index 0000000..069e8f9 --- /dev/null +++ b/drivers/rtc/rtc-sun6i.c @@ -0,0 +1,448 @@ +/* + * An RTC driver for Allwinner A31/A23 + * + * Copyright (c) 2014, Chen-Yu Tsai <wens@csie.org> + * + * based on rtc-sunxi.c + * + * An RTC driver for Allwinner A10/A20 + * + * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/types.h> + +/* Control register */ +#define SUN6I_LOSC_CTRL 0x0000 +#define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) +#define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) +#define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) +#define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) + +/* RTC */ +#define SUN6I_RTC_YMD 0x0010 +#define SUN6I_RTC_HMS 0x0014 + +/* Alarm 0 (counter) */ +#define SUN6I_ALRM_COUNTER 0x0020 +#define SUN6I_ALRM_CUR_VAL 0x0024 +#define SUN6I_ALRM_EN 0x0028 +#define SUN6I_ALRM_EN_CNT_EN BIT(0) +#define SUN6I_ALRM_IRQ_EN 0x002c +#define SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN BIT(0) +#define SUN6I_ALRM_IRQ_STA 0x0030 +#define SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND BIT(0) + +/* Alarm 1 (wall clock) */ +#define SUN6I_ALRM1_EN 0x0044 +#define SUN6I_ALRM1_IRQ_EN 0x0048 +#define SUN6I_ALRM1_IRQ_STA 0x004c +#define SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND BIT(0) + +/* Alarm config */ +#define SUN6I_ALARM_CONFIG 0x0050 +#define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) + +/* + * Get date values + */ +#define SUN6I_DATE_GET_DAY_VALUE(x) ((x) & 0x0000001f) +#define SUN6I_DATE_GET_MON_VALUE(x) (((x) & 0x00000f00) >> 8) +#define SUN6I_DATE_GET_YEAR_VALUE(x) (((x) & 0x003f0000) >> 16) +#define SUN6I_LEAP_GET_VALUE(x) (((x) & 0x00400000) >> 22) + +/* + * Get time values + */ +#define SUN6I_TIME_GET_SEC_VALUE(x) ((x) & 0x0000003f) +#define SUN6I_TIME_GET_MIN_VALUE(x) (((x) & 0x00003f00) >> 8) +#define SUN6I_TIME_GET_HOUR_VALUE(x) (((x) & 0x001f0000) >> 16) + +/* + * Set date values + */ +#define SUN6I_DATE_SET_DAY_VALUE(x) ((x) & 0x0000001f) +#define SUN6I_DATE_SET_MON_VALUE(x) ((x) << 8 & 0x00000f00) +#define SUN6I_DATE_SET_YEAR_VALUE(x) ((x) << 16 & 0x003f0000) +#define SUN6I_LEAP_SET_VALUE(x) ((x) << 22 & 0x00400000) + +/* + * Set time values + */ +#define SUN6I_TIME_SET_SEC_VALUE(x) ((x) & 0x0000003f) +#define SUN6I_TIME_SET_MIN_VALUE(x) ((x) << 8 & 0x00003f00) +#define SUN6I_TIME_SET_HOUR_VALUE(x) ((x) << 16 & 0x001f0000) + +/* + * The year parameter passed to the driver is usually an offset relative to + * the year 1900. This macro is used to convert this offset to another one + * relative to the minimum year allowed by the hardware. + * + * The year range is 1970 - 2033. This range is selected to match Allwinner's + * driver, even though it is somewhat limited. + */ +#define SUN6I_YEAR_MIN 1970 +#define SUN6I_YEAR_MAX 2033 +#define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900) + +struct sun6i_rtc_dev { + struct rtc_device *rtc; + struct device *dev; + void __iomem *base; + int irq; + unsigned long alarm; +}; + +static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) +{ + struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; + u32 val; + + val = readl(chip->base + SUN6I_ALRM_IRQ_STA); + + if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { + val |= SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND; + writel(val, chip->base + SUN6I_ALRM_IRQ_STA); + + rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) +{ + u32 alrm_val = 0; + u32 alrm_irq_val = 0; + u32 alrm_wake_val = 0; + + if (to) { + alrm_val = SUN6I_ALRM_EN_CNT_EN; + alrm_irq_val = SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN; + alrm_wake_val = SUN6I_ALARM_CONFIG_WAKEUP; + } else { + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, + chip->base + SUN6I_ALRM_IRQ_STA); + } + + writel(alrm_val, chip->base + SUN6I_ALRM_EN); + writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); + writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); +} + +static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + u32 date, time; + + /* + * read again in case it changes + */ + do { + date = readl(chip->base + SUN6I_RTC_YMD); + time = readl(chip->base + SUN6I_RTC_HMS); + } while ((date != readl(chip->base + SUN6I_RTC_YMD)) || + (time != readl(chip->base + SUN6I_RTC_HMS))); + + rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time); + rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); + rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); + + rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); + rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date); + rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); + + rtc_tm->tm_mon -= 1; + + /* + * switch from (data_year->min)-relative offset to + * a (1900)-relative one + */ + rtc_tm->tm_year += SUN6I_YEAR_OFF; + + return rtc_valid_tm(rtc_tm); +} + +static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + u32 alrm_st; + u32 alrm_en; + + alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); + alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); + wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); + wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); + rtc_time_to_tm(chip->alarm, &wkalrm->time); + + return 0; +} + +static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + struct rtc_time *alrm_tm = &wkalrm->time; + struct rtc_time tm_now; + unsigned long time_now = 0; + unsigned long time_set = 0; + unsigned long time_gap = 0; + int ret = 0; + + ret = sun6i_rtc_gettime(dev, &tm_now); + if (ret < 0) { + dev_err(dev, "Error in getting time\n"); + return -EINVAL; + } + + rtc_tm_to_time(alrm_tm, &time_set); + rtc_tm_to_time(&tm_now, &time_now); + if (time_set <= time_now) { + dev_err(dev, "Date to set in the past\n"); + return -EINVAL; + } + + time_gap = time_set - time_now; + + if (time_gap > U32_MAX) { + dev_err(dev, "Date too far in the future\n"); + return -EINVAL; + } + + sun6i_rtc_setaie(0, chip); + writel(0, chip->base + SUN6I_ALRM_COUNTER); + usleep_range(100, 300); + + writel(time_gap, chip->base + SUN6I_ALRM_COUNTER); + chip->alarm = time_set; + + sun6i_rtc_setaie(wkalrm->enabled, chip); + + return 0; +} + +static int sun6i_rtc_wait(struct sun6i_rtc_dev *chip, int offset, + unsigned int mask, unsigned int ms_timeout) +{ + const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout); + u32 reg; + + do { + reg = readl(chip->base + offset); + reg &= mask; + + if (!reg) + return 0; + + } while (time_before(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + u32 date = 0; + u32 time = 0; + int year; + + year = rtc_tm->tm_year + 1900; + if (year < SUN6I_YEAR_MIN || year > SUN6I_YEAR_MAX) { + dev_err(dev, "rtc only supports year in range %d - %d\n", + SUN6I_YEAR_MIN, SUN6I_YEAR_MAX); + return -EINVAL; + } + + rtc_tm->tm_year -= SUN6I_YEAR_OFF; + rtc_tm->tm_mon += 1; + + date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | + SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | + SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); + + if (is_leap_year(year)) + date |= SUN6I_LEAP_SET_VALUE(1); + + time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | + SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | + SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); + + /* Check whether registers are writable */ + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, + SUN6I_LOSC_CTRL_ACC_MASK, 50)) { + dev_err(dev, "rtc is still busy.\n"); + return -EBUSY; + } + + writel(time, chip->base + SUN6I_RTC_HMS); + + /* + * After writing the RTC HH-MM-SS register, the + * SUN6I_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not + * be cleared until the real writing operation is finished + */ + + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, + SUN6I_LOSC_CTRL_RTC_HMS_ACC, 50)) { + dev_err(dev, "Failed to set rtc time.\n"); + return -ETIMEDOUT; + } + + writel(date, chip->base + SUN6I_RTC_YMD); + + /* + * After writing the RTC YY-MM-DD register, the + * SUN6I_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not + * be cleared until the real writing operation is finished + */ + + if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, + SUN6I_LOSC_CTRL_RTC_YMD_ACC, 50)) { + dev_err(dev, "Failed to set rtc time.\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int sun6i_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + + if (!enabled) + sun6i_rtc_setaie(enabled, chip); + + return 0; +} + +static const struct rtc_class_ops sun6i_rtc_ops = { + .read_time = sun6i_rtc_gettime, + .set_time = sun6i_rtc_settime, + .read_alarm = sun6i_rtc_getalarm, + .set_alarm = sun6i_rtc_setalarm, + .alarm_irq_enable = sun6i_rtc_alarm_irq_enable +}; + +static int sun6i_rtc_probe(struct platform_device *pdev) +{ + struct sun6i_rtc_dev *chip; + struct resource *res; + int ret; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + platform_set_drvdata(pdev, chip); + chip->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + chip->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(chip->base)) + return PTR_ERR(chip->base); + + chip->irq = platform_get_irq(pdev, 0); + if (chip->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); + return chip->irq; + } + + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, + 0, dev_name(&pdev->dev), chip); + if (ret) { + dev_err(&pdev->dev, "Could not request IRQ\n"); + return ret; + } + + /* clear the alarm counter value */ + writel(0, chip->base + SUN6I_ALRM_COUNTER); + + /* disable counter alarm */ + writel(0, chip->base + SUN6I_ALRM_EN); + + /* disable counter alarm interrupt */ + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); + + /* disable week alarm */ + writel(0, chip->base + SUN6I_ALRM1_EN); + + /* disable week alarm interrupt */ + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); + + /* clear counter alarm pending interrupts */ + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + + SUN6I_ALRM_IRQ_STA); + + /* clear week alarm pending interrupts */ + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + + SUN6I_ALRM1_IRQ_STA); + + /* disable alarm wakeup */ + writel(0, chip->base + SUN6I_ALARM_CONFIG); + + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, + &sun6i_rtc_ops, THIS_MODULE); + if (IS_ERR(chip->rtc)) { + dev_err(&pdev->dev, "unable to register device\n"); + return PTR_ERR(chip->rtc); + } + + dev_info(&pdev->dev, "RTC enabled\n"); + + return 0; +} + +static int sun6i_rtc_remove(struct platform_device *pdev) +{ + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); + + rtc_device_unregister(chip->rtc); + + return 0; +} + +static const struct of_device_id sun6i_rtc_dt_ids[] = { + { .compatible = "allwinner,sun6i-a31-rtc" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); + +static struct platform_driver sun6i_rtc_driver = { + .probe = sun6i_rtc_probe, + .remove = sun6i_rtc_remove, + .driver = { + .name = "sun6i-rtc", + .owner = THIS_MODULE, + .of_match_table = sun6i_rtc_dt_ids, + }, +}; + +module_platform_driver(sun6i_rtc_driver); + +MODULE_DESCRIPTION("sun6i RTC driver"); +MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); +MODULE_LICENSE("GPL"); -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <1406126338-15062-2-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>]
* Re: [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver 2014-07-23 14:38 ` Chen-Yu Tsai @ 2014-07-23 16:02 ` Varka Bhadram -1 siblings, 0 replies; 20+ messages in thread From: Varka Bhadram @ 2014-07-23 16:02 UTC (permalink / raw) To: Chen-Yu Tsai, Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw On Wednesday 23 July 2014 08:08 PM, Chen-Yu Tsai wrote: > This patch introduces the driver for the RTC in the Allwinner A31 and > A23 SoCs. > > Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the > RTC in A31/A23 are a separate hardware block, which also contain a few > controls for the RTC block hardware (a regulator and RTC block GPIO pin > latches), while also having separate interrupts for the alarms. > > The hardware is different enough to make a different driver for it. > (...) > +Required properties: > +- compatible : Should be "allwinner,sun6i-a31-rtc" > +- reg: physical base address of the controller and length of memory mapped > + region. > +- interrupts: IRQ line for the RTC alarm 0. > + proper indentation.. - compatible : Should be "allwinner,sun6i-a31-rtc" - reg : physical base address of the controller and length of memory mapped region. - interrupts : IRQ line for the RTC alarm 0. .... > +Example: > + (...) > + > + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, > + 0, dev_name(&pdev->dev), chip); should match open parenthesis... devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, 0, dev_name(&pdev->dev), chip); > + if (ret) { > + dev_err(&pdev->dev, "Could not request IRQ\n"); > + return ret; > + } > + > + /* clear the alarm counter value */ > + writel(0, chip->base + SUN6I_ALRM_COUNTER); > + > + /* disable counter alarm */ > + writel(0, chip->base + SUN6I_ALRM_EN); > + > + /* disable counter alarm interrupt */ > + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); > + > + /* disable week alarm */ > + writel(0, chip->base + SUN6I_ALRM1_EN); > + > + /* disable week alarm interrupt */ > + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); > + > + /* clear counter alarm pending interrupts */ > + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + > + SUN6I_ALRM_IRQ_STA); > + > + /* clear week alarm pending interrupts */ > + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + > + SUN6I_ALRM1_IRQ_STA); > + > + /* disable alarm wakeup */ > + writel(0, chip->base + SUN6I_ALARM_CONFIG); > + > + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, > + &sun6i_rtc_ops, THIS_MODULE); dto.... > + if (IS_ERR(chip->rtc)) { > + dev_err(&pdev->dev, "unable to register device\n"); > + return PTR_ERR(chip->rtc); > + } > + > + dev_info(&pdev->dev, "RTC enabled\n"); > + > + return 0; > +} > + > +static int sun6i_rtc_remove(struct platform_device *pdev) > +{ > + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); > + > + rtc_device_unregister(chip->rtc); > + > + return 0; > +} > + > +static const struct of_device_id sun6i_rtc_dt_ids[] = { > + { .compatible = "allwinner,sun6i-a31-rtc" }, > + { /* sentinel */ }, > +}; > +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); > + > +static struct platform_driver sun6i_rtc_driver = { > + .probe = sun6i_rtc_probe, > + .remove = sun6i_rtc_remove, > + .driver = { > + .name = "sun6i-rtc", > + .owner = THIS_MODULE, we can drop owner field.... > + .of_match_table = sun6i_rtc_dt_ids, > + }, > +}; > + > +module_platform_driver(sun6i_rtc_driver); > + > +MODULE_DESCRIPTION("sun6i RTC driver"); > +MODULE_AUTHOR("Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>"); > +MODULE_LICENSE("GPL"); -- -Varka Bhadram -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver @ 2014-07-23 16:02 ` Varka Bhadram 0 siblings, 0 replies; 20+ messages in thread From: Varka Bhadram @ 2014-07-23 16:02 UTC (permalink / raw) To: linux-arm-kernel On Wednesday 23 July 2014 08:08 PM, Chen-Yu Tsai wrote: > This patch introduces the driver for the RTC in the Allwinner A31 and > A23 SoCs. > > Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the > RTC in A31/A23 are a separate hardware block, which also contain a few > controls for the RTC block hardware (a regulator and RTC block GPIO pin > latches), while also having separate interrupts for the alarms. > > The hardware is different enough to make a different driver for it. > (...) > +Required properties: > +- compatible : Should be "allwinner,sun6i-a31-rtc" > +- reg: physical base address of the controller and length of memory mapped > + region. > +- interrupts: IRQ line for the RTC alarm 0. > + proper indentation.. - compatible : Should be "allwinner,sun6i-a31-rtc" - reg : physical base address of the controller and length of memory mapped region. - interrupts : IRQ line for the RTC alarm 0. .... > +Example: > + (...) > + > + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, > + 0, dev_name(&pdev->dev), chip); should match open parenthesis... devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, 0, dev_name(&pdev->dev), chip); > + if (ret) { > + dev_err(&pdev->dev, "Could not request IRQ\n"); > + return ret; > + } > + > + /* clear the alarm counter value */ > + writel(0, chip->base + SUN6I_ALRM_COUNTER); > + > + /* disable counter alarm */ > + writel(0, chip->base + SUN6I_ALRM_EN); > + > + /* disable counter alarm interrupt */ > + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); > + > + /* disable week alarm */ > + writel(0, chip->base + SUN6I_ALRM1_EN); > + > + /* disable week alarm interrupt */ > + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); > + > + /* clear counter alarm pending interrupts */ > + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + > + SUN6I_ALRM_IRQ_STA); > + > + /* clear week alarm pending interrupts */ > + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + > + SUN6I_ALRM1_IRQ_STA); > + > + /* disable alarm wakeup */ > + writel(0, chip->base + SUN6I_ALARM_CONFIG); > + > + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, > + &sun6i_rtc_ops, THIS_MODULE); dto.... > + if (IS_ERR(chip->rtc)) { > + dev_err(&pdev->dev, "unable to register device\n"); > + return PTR_ERR(chip->rtc); > + } > + > + dev_info(&pdev->dev, "RTC enabled\n"); > + > + return 0; > +} > + > +static int sun6i_rtc_remove(struct platform_device *pdev) > +{ > + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); > + > + rtc_device_unregister(chip->rtc); > + > + return 0; > +} > + > +static const struct of_device_id sun6i_rtc_dt_ids[] = { > + { .compatible = "allwinner,sun6i-a31-rtc" }, > + { /* sentinel */ }, > +}; > +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); > + > +static struct platform_driver sun6i_rtc_driver = { > + .probe = sun6i_rtc_probe, > + .remove = sun6i_rtc_remove, > + .driver = { > + .name = "sun6i-rtc", > + .owner = THIS_MODULE, we can drop owner field.... > + .of_match_table = sun6i_rtc_dt_ids, > + }, > +}; > + > +module_platform_driver(sun6i_rtc_driver); > + > +MODULE_DESCRIPTION("sun6i RTC driver"); > +MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); > +MODULE_LICENSE("GPL"); -- -Varka Bhadram ^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <53CFDC9F.9060208-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>]
* Re: [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver 2014-07-23 16:02 ` Varka Bhadram @ 2014-07-25 7:57 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-25 7:57 UTC (permalink / raw) To: Varka Bhadram Cc: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring, linux-arm-kernel, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree, linux-sunxi On Thu, Jul 24, 2014 at 12:02 AM, Varka Bhadram <varkabhadram-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > On Wednesday 23 July 2014 08:08 PM, Chen-Yu Tsai wrote: >> >> This patch introduces the driver for the RTC in the Allwinner A31 and >> A23 SoCs. >> >> Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the >> RTC in A31/A23 are a separate hardware block, which also contain a few >> controls for the RTC block hardware (a regulator and RTC block GPIO pin >> latches), while also having separate interrupts for the alarms. >> >> The hardware is different enough to make a different driver for it. >> > (...) > > >> +Required properties: >> +- compatible : Should be "allwinner,sun6i-a31-rtc" >> +- reg: physical base address of the controller and length of memory >> mapped >> + region. >> +- interrupts: IRQ line for the RTC alarm 0. >> + > > > proper indentation.. > - compatible : Should be "allwinner,sun6i-a31-rtc" > > - reg : physical base address of the controller and length of > memory mapped > region. > > - interrupts : IRQ line for the RTC alarm 0. > .... > >> +Example: >> + > > > (...) > > >> + >> + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, >> + 0, dev_name(&pdev->dev), chip); > > > should match open parenthesis... > > > devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, > 0, dev_name(&pdev->dev), chip); ok. >> + if (ret) { >> + dev_err(&pdev->dev, "Could not request IRQ\n"); >> + return ret; >> + } >> + >> + /* clear the alarm counter value */ >> + writel(0, chip->base + SUN6I_ALRM_COUNTER); >> + >> + /* disable counter alarm */ >> + writel(0, chip->base + SUN6I_ALRM_EN); >> + >> + /* disable counter alarm interrupt */ >> + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); >> + >> + /* disable week alarm */ >> + writel(0, chip->base + SUN6I_ALRM1_EN); >> + >> + /* disable week alarm interrupt */ >> + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); >> + >> + /* clear counter alarm pending interrupts */ >> + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + >> + SUN6I_ALRM_IRQ_STA); >> + >> + /* clear week alarm pending interrupts */ >> + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + >> + SUN6I_ALRM1_IRQ_STA); >> + >> + /* disable alarm wakeup */ >> + writel(0, chip->base + SUN6I_ALARM_CONFIG); >> + >> + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, >> + &sun6i_rtc_ops, THIS_MODULE); > > > dto.... ok. >> + if (IS_ERR(chip->rtc)) { >> + dev_err(&pdev->dev, "unable to register device\n"); >> + return PTR_ERR(chip->rtc); >> + } >> + >> + dev_info(&pdev->dev, "RTC enabled\n"); >> + >> + return 0; >> +} >> + >> +static int sun6i_rtc_remove(struct platform_device *pdev) >> +{ >> + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); >> + >> + rtc_device_unregister(chip->rtc); >> + >> + return 0; >> +} >> + >> +static const struct of_device_id sun6i_rtc_dt_ids[] = { >> + { .compatible = "allwinner,sun6i-a31-rtc" }, >> + { /* sentinel */ }, >> +}; >> +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); >> + >> +static struct platform_driver sun6i_rtc_driver = { >> + .probe = sun6i_rtc_probe, >> + .remove = sun6i_rtc_remove, >> + .driver = { >> + .name = "sun6i-rtc", >> + .owner = THIS_MODULE, > > > we can drop owner field.... May I ask why this is not needed? Seems most if not all drivers set it. Thanks. >> + .of_match_table = sun6i_rtc_dt_ids, >> + }, >> +}; >> + >> +module_platform_driver(sun6i_rtc_driver); >> + >> +MODULE_DESCRIPTION("sun6i RTC driver"); >> +MODULE_AUTHOR("Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>"); >> +MODULE_LICENSE("GPL"); ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver @ 2014-07-25 7:57 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-25 7:57 UTC (permalink / raw) To: linux-arm-kernel On Thu, Jul 24, 2014 at 12:02 AM, Varka Bhadram <varkabhadram@gmail.com> wrote: > > On Wednesday 23 July 2014 08:08 PM, Chen-Yu Tsai wrote: >> >> This patch introduces the driver for the RTC in the Allwinner A31 and >> A23 SoCs. >> >> Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the >> RTC in A31/A23 are a separate hardware block, which also contain a few >> controls for the RTC block hardware (a regulator and RTC block GPIO pin >> latches), while also having separate interrupts for the alarms. >> >> The hardware is different enough to make a different driver for it. >> > (...) > > >> +Required properties: >> +- compatible : Should be "allwinner,sun6i-a31-rtc" >> +- reg: physical base address of the controller and length of memory >> mapped >> + region. >> +- interrupts: IRQ line for the RTC alarm 0. >> + > > > proper indentation.. > - compatible : Should be "allwinner,sun6i-a31-rtc" > > - reg : physical base address of the controller and length of > memory mapped > region. > > - interrupts : IRQ line for the RTC alarm 0. > .... > >> +Example: >> + > > > (...) > > >> + >> + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, >> + 0, dev_name(&pdev->dev), chip); > > > should match open parenthesis... > > > devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, > 0, dev_name(&pdev->dev), chip); ok. >> + if (ret) { >> + dev_err(&pdev->dev, "Could not request IRQ\n"); >> + return ret; >> + } >> + >> + /* clear the alarm counter value */ >> + writel(0, chip->base + SUN6I_ALRM_COUNTER); >> + >> + /* disable counter alarm */ >> + writel(0, chip->base + SUN6I_ALRM_EN); >> + >> + /* disable counter alarm interrupt */ >> + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); >> + >> + /* disable week alarm */ >> + writel(0, chip->base + SUN6I_ALRM1_EN); >> + >> + /* disable week alarm interrupt */ >> + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); >> + >> + /* clear counter alarm pending interrupts */ >> + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + >> + SUN6I_ALRM_IRQ_STA); >> + >> + /* clear week alarm pending interrupts */ >> + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + >> + SUN6I_ALRM1_IRQ_STA); >> + >> + /* disable alarm wakeup */ >> + writel(0, chip->base + SUN6I_ALARM_CONFIG); >> + >> + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, >> + &sun6i_rtc_ops, THIS_MODULE); > > > dto.... ok. >> + if (IS_ERR(chip->rtc)) { >> + dev_err(&pdev->dev, "unable to register device\n"); >> + return PTR_ERR(chip->rtc); >> + } >> + >> + dev_info(&pdev->dev, "RTC enabled\n"); >> + >> + return 0; >> +} >> + >> +static int sun6i_rtc_remove(struct platform_device *pdev) >> +{ >> + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); >> + >> + rtc_device_unregister(chip->rtc); >> + >> + return 0; >> +} >> + >> +static const struct of_device_id sun6i_rtc_dt_ids[] = { >> + { .compatible = "allwinner,sun6i-a31-rtc" }, >> + { /* sentinel */ }, >> +}; >> +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); >> + >> +static struct platform_driver sun6i_rtc_driver = { >> + .probe = sun6i_rtc_probe, >> + .remove = sun6i_rtc_remove, >> + .driver = { >> + .name = "sun6i-rtc", >> + .owner = THIS_MODULE, > > > we can drop owner field.... May I ask why this is not needed? Seems most if not all drivers set it. Thanks. >> + .of_match_table = sun6i_rtc_dt_ids, >> + }, >> +}; >> + >> +module_platform_driver(sun6i_rtc_driver); >> + >> +MODULE_DESCRIPTION("sun6i RTC driver"); >> +MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); >> +MODULE_LICENSE("GPL"); ^ permalink raw reply [flat|nested] 20+ messages in thread
[parent not found: <CAGb2v6746P-9rtW3gjUS3ttkZeqW6gNbunXHiSidNag1gCmk0A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver 2014-07-25 7:57 ` Chen-Yu Tsai @ 2014-07-25 8:13 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-25 8:13 UTC (permalink / raw) To: Varka Bhadram Cc: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring, linux-arm-kernel, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree, linux-sunxi On Fri, Jul 25, 2014 at 3:57 PM, Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> wrote: > On Thu, Jul 24, 2014 at 12:02 AM, Varka Bhadram <varkabhadram-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >> >> On Wednesday 23 July 2014 08:08 PM, Chen-Yu Tsai wrote: >>> >>> This patch introduces the driver for the RTC in the Allwinner A31 and >>> A23 SoCs. >>> >>> Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the >>> RTC in A31/A23 are a separate hardware block, which also contain a few >>> controls for the RTC block hardware (a regulator and RTC block GPIO pin >>> latches), while also having separate interrupts for the alarms. >>> >>> The hardware is different enough to make a different driver for it. >>> >> (...) >> >> >>> +Required properties: >>> +- compatible : Should be "allwinner,sun6i-a31-rtc" >>> +- reg: physical base address of the controller and length of memory >>> mapped >>> + region. >>> +- interrupts: IRQ line for the RTC alarm 0. >>> + >> >> >> proper indentation.. >> - compatible : Should be "allwinner,sun6i-a31-rtc" >> >> - reg : physical base address of the controller and length of >> memory mapped >> region. >> >> - interrupts : IRQ line for the RTC alarm 0. >> .... >> >>> +Example: >>> + >> >> >> (...) >> >> >>> + >>> + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, >>> + 0, dev_name(&pdev->dev), chip); >> >> >> should match open parenthesis... >> >> >> devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, >> 0, dev_name(&pdev->dev), chip); > > ok. > >>> + if (ret) { >>> + dev_err(&pdev->dev, "Could not request IRQ\n"); >>> + return ret; >>> + } >>> + >>> + /* clear the alarm counter value */ >>> + writel(0, chip->base + SUN6I_ALRM_COUNTER); >>> + >>> + /* disable counter alarm */ >>> + writel(0, chip->base + SUN6I_ALRM_EN); >>> + >>> + /* disable counter alarm interrupt */ >>> + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); >>> + >>> + /* disable week alarm */ >>> + writel(0, chip->base + SUN6I_ALRM1_EN); >>> + >>> + /* disable week alarm interrupt */ >>> + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); >>> + >>> + /* clear counter alarm pending interrupts */ >>> + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + >>> + SUN6I_ALRM_IRQ_STA); >>> + >>> + /* clear week alarm pending interrupts */ >>> + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + >>> + SUN6I_ALRM1_IRQ_STA); >>> + >>> + /* disable alarm wakeup */ >>> + writel(0, chip->base + SUN6I_ALARM_CONFIG); >>> + >>> + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, >>> + &sun6i_rtc_ops, THIS_MODULE); >> >> >> dto.... > > ok. > >>> + if (IS_ERR(chip->rtc)) { >>> + dev_err(&pdev->dev, "unable to register device\n"); >>> + return PTR_ERR(chip->rtc); >>> + } >>> + >>> + dev_info(&pdev->dev, "RTC enabled\n"); >>> + >>> + return 0; >>> +} >>> + >>> +static int sun6i_rtc_remove(struct platform_device *pdev) >>> +{ >>> + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); >>> + >>> + rtc_device_unregister(chip->rtc); >>> + >>> + return 0; >>> +} >>> + >>> +static const struct of_device_id sun6i_rtc_dt_ids[] = { >>> + { .compatible = "allwinner,sun6i-a31-rtc" }, >>> + { /* sentinel */ }, >>> +}; >>> +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); >>> + >>> +static struct platform_driver sun6i_rtc_driver = { >>> + .probe = sun6i_rtc_probe, >>> + .remove = sun6i_rtc_remove, >>> + .driver = { >>> + .name = "sun6i-rtc", >>> + .owner = THIS_MODULE, >> >> >> we can drop owner field.... > > May I ask why this is not needed? Seems most if not all drivers > set it. > > Thanks. Never mind. I figured it out. Sorry for the noise. >>> + .of_match_table = sun6i_rtc_dt_ids, >>> + }, >>> +}; >>> + >>> +module_platform_driver(sun6i_rtc_driver); >>> + >>> +MODULE_DESCRIPTION("sun6i RTC driver"); >>> +MODULE_AUTHOR("Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>"); >>> +MODULE_LICENSE("GPL"); ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver @ 2014-07-25 8:13 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-25 8:13 UTC (permalink / raw) To: linux-arm-kernel On Fri, Jul 25, 2014 at 3:57 PM, Chen-Yu Tsai <wens@csie.org> wrote: > On Thu, Jul 24, 2014 at 12:02 AM, Varka Bhadram <varkabhadram@gmail.com> wrote: >> >> On Wednesday 23 July 2014 08:08 PM, Chen-Yu Tsai wrote: >>> >>> This patch introduces the driver for the RTC in the Allwinner A31 and >>> A23 SoCs. >>> >>> Unlike the RTC found in A10/A20 SoCs, which was part of the timer, the >>> RTC in A31/A23 are a separate hardware block, which also contain a few >>> controls for the RTC block hardware (a regulator and RTC block GPIO pin >>> latches), while also having separate interrupts for the alarms. >>> >>> The hardware is different enough to make a different driver for it. >>> >> (...) >> >> >>> +Required properties: >>> +- compatible : Should be "allwinner,sun6i-a31-rtc" >>> +- reg: physical base address of the controller and length of memory >>> mapped >>> + region. >>> +- interrupts: IRQ line for the RTC alarm 0. >>> + >> >> >> proper indentation.. >> - compatible : Should be "allwinner,sun6i-a31-rtc" >> >> - reg : physical base address of the controller and length of >> memory mapped >> region. >> >> - interrupts : IRQ line for the RTC alarm 0. >> .... >> >>> +Example: >>> + >> >> >> (...) >> >> >>> + >>> + ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, >>> + 0, dev_name(&pdev->dev), chip); >> >> >> should match open parenthesis... >> >> >> devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, >> 0, dev_name(&pdev->dev), chip); > > ok. > >>> + if (ret) { >>> + dev_err(&pdev->dev, "Could not request IRQ\n"); >>> + return ret; >>> + } >>> + >>> + /* clear the alarm counter value */ >>> + writel(0, chip->base + SUN6I_ALRM_COUNTER); >>> + >>> + /* disable counter alarm */ >>> + writel(0, chip->base + SUN6I_ALRM_EN); >>> + >>> + /* disable counter alarm interrupt */ >>> + writel(0, chip->base + SUN6I_ALRM_IRQ_EN); >>> + >>> + /* disable week alarm */ >>> + writel(0, chip->base + SUN6I_ALRM1_EN); >>> + >>> + /* disable week alarm interrupt */ >>> + writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); >>> + >>> + /* clear counter alarm pending interrupts */ >>> + writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + >>> + SUN6I_ALRM_IRQ_STA); >>> + >>> + /* clear week alarm pending interrupts */ >>> + writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, chip->base + >>> + SUN6I_ALRM1_IRQ_STA); >>> + >>> + /* disable alarm wakeup */ >>> + writel(0, chip->base + SUN6I_ALARM_CONFIG); >>> + >>> + chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, >>> + &sun6i_rtc_ops, THIS_MODULE); >> >> >> dto.... > > ok. > >>> + if (IS_ERR(chip->rtc)) { >>> + dev_err(&pdev->dev, "unable to register device\n"); >>> + return PTR_ERR(chip->rtc); >>> + } >>> + >>> + dev_info(&pdev->dev, "RTC enabled\n"); >>> + >>> + return 0; >>> +} >>> + >>> +static int sun6i_rtc_remove(struct platform_device *pdev) >>> +{ >>> + struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); >>> + >>> + rtc_device_unregister(chip->rtc); >>> + >>> + return 0; >>> +} >>> + >>> +static const struct of_device_id sun6i_rtc_dt_ids[] = { >>> + { .compatible = "allwinner,sun6i-a31-rtc" }, >>> + { /* sentinel */ }, >>> +}; >>> +MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); >>> + >>> +static struct platform_driver sun6i_rtc_driver = { >>> + .probe = sun6i_rtc_probe, >>> + .remove = sun6i_rtc_remove, >>> + .driver = { >>> + .name = "sun6i-rtc", >>> + .owner = THIS_MODULE, >> >> >> we can drop owner field.... > > May I ask why this is not needed? Seems most if not all drivers > set it. > > Thanks. Never mind. I figured it out. Sorry for the noise. >>> + .of_match_table = sun6i_rtc_dt_ids, >>> + }, >>> +}; >>> + >>> +module_platform_driver(sun6i_rtc_driver); >>> + >>> +MODULE_DESCRIPTION("sun6i RTC driver"); >>> +MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); >>> +MODULE_LICENSE("GPL"); ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 2/6] rtc: sunxi: Depend on platforms sun4i/sun7i that actually have the rtc 2014-07-23 14:38 ` Chen-Yu Tsai @ 2014-07-23 14:38 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Now that we have Kconfig options for individual sunxi platforms, let the rtc-sunxi driver depend on the platforms that actually have this hardware, sun4i and sun7i. Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index dde2b57..f933b4b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1176,7 +1176,7 @@ config RTC_DRV_SUN6I config RTC_DRV_SUNXI tristate "Allwinner sun4i/sun7i RTC" - depends on ARCH_SUNXI + depends on MACH_SUN4I || MACH_SUN7I help If you say Y here you will get support for the RTC found on Allwinner A10/A20. -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 2/6] rtc: sunxi: Depend on platforms sun4i/sun7i that actually have the rtc @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: linux-arm-kernel Now that we have Kconfig options for individual sunxi platforms, let the rtc-sunxi driver depend on the platforms that actually have this hardware, sun4i and sun7i. Signed-off-by: Chen-Yu Tsai <wens@csie.org> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index dde2b57..f933b4b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1176,7 +1176,7 @@ config RTC_DRV_SUN6I config RTC_DRV_SUNXI tristate "Allwinner sun4i/sun7i RTC" - depends on ARCH_SUNXI + depends on MACH_SUN4I || MACH_SUN7I help If you say Y here you will get support for the RTC found on Allwinner A10/A20. -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 3/6] ARM: dts: sun6i: add rtc device node 2014-07-23 14:38 ` Chen-Yu Tsai @ 2014-07-23 14:38 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Now that we have a driver for sun6i's rtc hardware, add a device node for it so we can use it. Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> --- arch/arm/boot/dts/sun6i-a31.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 44b07e5..6a16019 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -779,6 +779,12 @@ interrupts = <1 9 0xf04>; }; + rtc: rtc@01f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = <0 40 4>; + }; + nmi_intc: interrupt-controller@01f00c0c { compatible = "allwinner,sun6i-a31-sc-nmi"; interrupt-controller; -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 3/6] ARM: dts: sun6i: add rtc device node @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: linux-arm-kernel Now that we have a driver for sun6i's rtc hardware, add a device node for it so we can use it. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- arch/arm/boot/dts/sun6i-a31.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 44b07e5..6a16019 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -779,6 +779,12 @@ interrupts = <1 9 0xf04>; }; + rtc: rtc at 01f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = <0 40 4>; + }; + nmi_intc: interrupt-controller at 01f00c0c { compatible = "allwinner,sun6i-a31-sc-nmi"; interrupt-controller; -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 4/6] ARM: dts: sun8i: add rtc device node 2014-07-23 14:38 ` Chen-Yu Tsai @ 2014-07-23 14:38 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw sun8i shares the same rtc hardware as sun6i. Now that we have a driver for it, add a device node to the DTSI for it so we can use it. Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> --- arch/arm/boot/dts/sun8i-a23.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 54ac0787..e0d1048 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -285,6 +285,12 @@ interrupts = <1 9 0xf04>; }; + rtc: rtc@01f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = <0 40 4>; + }; + prcm@01f01400 { compatible = "allwinner,sun8i-a23-prcm"; reg = <0x01f01400 0x200>; -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 4/6] ARM: dts: sun8i: add rtc device node @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: linux-arm-kernel sun8i shares the same rtc hardware as sun6i. Now that we have a driver for it, add a device node to the DTSI for it so we can use it. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- arch/arm/boot/dts/sun8i-a23.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 54ac0787..e0d1048 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -285,6 +285,12 @@ interrupts = <1 9 0xf04>; }; + rtc: rtc at 01f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = <0 40 4>; + }; + prcm at 01f01400 { compatible = "allwinner,sun8i-a23-prcm"; reg = <0x01f01400 0x200>; -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 5/6] ARM: sunxi: Add A31 RTC driver to sunxi_defconfig 2014-07-23 14:38 ` Chen-Yu Tsai @ 2014-07-23 14:38 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Now that we have a driver for A31's RTC, enable it in the default sunxi config. Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> --- arch/arm/configs/sunxi_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 7209bfd..0abc2ab 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -93,6 +93,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_RTC_CLASS=y # CONFIG_RTC_INTF_SYSFS is not set # CONFIG_RTC_INTF_PROC is not set +CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_SUNXI=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_PHY_SUN4I_USB=y -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 5/6] ARM: sunxi: Add A31 RTC driver to sunxi_defconfig @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: linux-arm-kernel Now that we have a driver for A31's RTC, enable it in the default sunxi config. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- arch/arm/configs/sunxi_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 7209bfd..0abc2ab 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -93,6 +93,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_RTC_CLASS=y # CONFIG_RTC_INTF_SYSFS is not set # CONFIG_RTC_INTF_PROC is not set +CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_SUNXI=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_PHY_SUN4I_USB=y -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 6/6] ARM: sunxi: Add A31 RTC driver to multi_v7_defconfig 2014-07-23 14:38 ` Chen-Yu Tsai @ 2014-07-23 14:38 ` Chen-Yu Tsai -1 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: Maxime Ripard, Russell King, Alessandro Zummo, Rob Herring Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Now that we have a driver for A31's RTC, enable it in multi_v7_defconfig. Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index a62ca27..130dd8d 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -346,6 +346,7 @@ CONFIG_RTC_DRV_TPS65910=y CONFIG_RTC_DRV_EM3027=y CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_VT8500=y +CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_SUNXI=y CONFIG_RTC_DRV_MV=y CONFIG_RTC_DRV_TEGRA=y -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 6/6] ARM: sunxi: Add A31 RTC driver to multi_v7_defconfig @ 2014-07-23 14:38 ` Chen-Yu Tsai 0 siblings, 0 replies; 20+ messages in thread From: Chen-Yu Tsai @ 2014-07-23 14:38 UTC (permalink / raw) To: linux-arm-kernel Now that we have a driver for A31's RTC, enable it in multi_v7_defconfig. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index a62ca27..130dd8d 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -346,6 +346,7 @@ CONFIG_RTC_DRV_TPS65910=y CONFIG_RTC_DRV_EM3027=y CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_VT8500=y +CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_SUNXI=y CONFIG_RTC_DRV_MV=y CONFIG_RTC_DRV_TEGRA=y -- 2.0.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-07-25 8:13 UTC | newest] Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-07-23 14:38 [PATCH v2 0/6] ARM: sunxi: RTC support for A31/A23 Chen-Yu Tsai 2014-07-23 14:38 ` Chen-Yu Tsai [not found] ` <1406126338-15062-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org> 2014-07-23 14:38 ` [PATCH v2 1/6] rtc: sun6i: Add sun6i RTC driver Chen-Yu Tsai 2014-07-23 14:38 ` Chen-Yu Tsai [not found] ` <1406126338-15062-2-git-send-email-wens-jdAy2FN1RRM@public.gmane.org> 2014-07-23 16:02 ` Varka Bhadram 2014-07-23 16:02 ` Varka Bhadram [not found] ` <53CFDC9F.9060208-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 2014-07-25 7:57 ` Chen-Yu Tsai 2014-07-25 7:57 ` Chen-Yu Tsai [not found] ` <CAGb2v6746P-9rtW3gjUS3ttkZeqW6gNbunXHiSidNag1gCmk0A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2014-07-25 8:13 ` Chen-Yu Tsai 2014-07-25 8:13 ` Chen-Yu Tsai 2014-07-23 14:38 ` [PATCH v2 2/6] rtc: sunxi: Depend on platforms sun4i/sun7i that actually have the rtc Chen-Yu Tsai 2014-07-23 14:38 ` Chen-Yu Tsai 2014-07-23 14:38 ` [PATCH v2 3/6] ARM: dts: sun6i: add rtc device node Chen-Yu Tsai 2014-07-23 14:38 ` Chen-Yu Tsai 2014-07-23 14:38 ` [PATCH v2 4/6] ARM: dts: sun8i: " Chen-Yu Tsai 2014-07-23 14:38 ` Chen-Yu Tsai 2014-07-23 14:38 ` [PATCH v2 5/6] ARM: sunxi: Add A31 RTC driver to sunxi_defconfig Chen-Yu Tsai 2014-07-23 14:38 ` Chen-Yu Tsai 2014-07-23 14:38 ` [PATCH v2 6/6] ARM: sunxi: Add A31 RTC driver to multi_v7_defconfig Chen-Yu Tsai 2014-07-23 14:38 ` Chen-Yu Tsai
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.