* [PATCHv3 3/8] rtc: add STM32 RTC driver
From: Amelie Delaunay @ 2017-01-05 13:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483623809-29937-1-git-send-email-amelie.delaunay@st.com>
This patch adds support for the STM32 RTC.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
drivers/rtc/Kconfig | 11 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-stm32.c | 776 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 788 insertions(+)
create mode 100644 drivers/rtc/rtc-stm32.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e859d14..11eb28a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1706,6 +1706,17 @@ config RTC_DRV_PIC32
This driver can also be built as a module. If so, the module
will be called rtc-pic32
+config RTC_DRV_STM32
+ tristate "STM32 RTC"
+ select REGMAP_MMIO
+ depends on ARCH_STM32 || COMPILE_TEST
+ help
+ If you say yes here you get support for the STM32 On-Chip
+ Real Time Clock.
+
+ This driver can also be built as a module, if so, the module
+ will be called "rtc-stm32".
+
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 1ac694a..87bd9cc 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -144,6 +144,7 @@ obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
+obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o
obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o
obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
new file mode 100644
index 0000000..fdd3a31
--- /dev/null
+++ b/drivers/rtc/rtc-stm32.c
@@ -0,0 +1,776 @@
+/*
+ * Copyright (C) Amelie Delaunay 2016
+ * Author: Amelie Delaunay <amelie.delaunay@st.com>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/bcd.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+
+#define DRIVER_NAME "stm32_rtc"
+
+/* STM32 RTC registers */
+#define STM32_RTC_TR 0x00
+#define STM32_RTC_DR 0x04
+#define STM32_RTC_CR 0x08
+#define STM32_RTC_ISR 0x0C
+#define STM32_RTC_PRER 0x10
+#define STM32_RTC_ALRMAR 0x1C
+#define STM32_RTC_WPR 0x24
+
+/* STM32_RTC_TR bit fields */
+#define STM32_RTC_TR_SEC_SHIFT 0
+#define STM32_RTC_TR_SEC GENMASK(6, 0)
+#define STM32_RTC_TR_MIN_SHIFT 8
+#define STM32_RTC_TR_MIN GENMASK(14, 8)
+#define STM32_RTC_TR_HOUR_SHIFT 16
+#define STM32_RTC_TR_HOUR GENMASK(21, 16)
+
+/* STM32_RTC_DR bit fields */
+#define STM32_RTC_DR_DATE_SHIFT 0
+#define STM32_RTC_DR_DATE GENMASK(5, 0)
+#define STM32_RTC_DR_MONTH_SHIFT 8
+#define STM32_RTC_DR_MONTH GENMASK(12, 8)
+#define STM32_RTC_DR_WDAY_SHIFT 13
+#define STM32_RTC_DR_WDAY GENMASK(15, 13)
+#define STM32_RTC_DR_YEAR_SHIFT 16
+#define STM32_RTC_DR_YEAR GENMASK(23, 16)
+
+/* STM32_RTC_CR bit fields */
+#define STM32_RTC_CR_FMT BIT(6)
+#define STM32_RTC_CR_ALRAE BIT(8)
+#define STM32_RTC_CR_ALRAIE BIT(12)
+
+/* STM32_RTC_ISR bit fields */
+#define STM32_RTC_ISR_ALRAWF BIT(0)
+#define STM32_RTC_ISR_INITS BIT(4)
+#define STM32_RTC_ISR_RSF BIT(5)
+#define STM32_RTC_ISR_INITF BIT(6)
+#define STM32_RTC_ISR_INIT BIT(7)
+#define STM32_RTC_ISR_ALRAF BIT(8)
+
+/* STM32_RTC_PRER bit fields */
+#define STM32_RTC_PRER_PRED_S_SHIFT 0
+#define STM32_RTC_PRER_PRED_S GENMASK(14, 0)
+#define STM32_RTC_PRER_PRED_A_SHIFT 16
+#define STM32_RTC_PRER_PRED_A GENMASK(22, 16)
+
+/* STM32_RTC_ALRMAR and STM32_RTC_ALRMBR bit fields */
+#define STM32_RTC_ALRMXR_SEC_SHIFT 0
+#define STM32_RTC_ALRMXR_SEC GENMASK(6, 0)
+#define STM32_RTC_ALRMXR_SEC_MASK BIT(7)
+#define STM32_RTC_ALRMXR_MIN_SHIFT 8
+#define STM32_RTC_ALRMXR_MIN GENMASK(14, 8)
+#define STM32_RTC_ALRMXR_MIN_MASK BIT(15)
+#define STM32_RTC_ALRMXR_HOUR_SHIFT 16
+#define STM32_RTC_ALRMXR_HOUR GENMASK(21, 16)
+#define STM32_RTC_ALRMXR_PM BIT(22)
+#define STM32_RTC_ALRMXR_HOUR_MASK BIT(23)
+#define STM32_RTC_ALRMXR_DATE_SHIFT 24
+#define STM32_RTC_ALRMXR_DATE GENMASK(29, 24)
+#define STM32_RTC_ALRMXR_WDSEL BIT(30)
+#define STM32_RTC_ALRMXR_WDAY_SHIFT 24
+#define STM32_RTC_ALRMXR_WDAY GENMASK(27, 24)
+#define STM32_RTC_ALRMXR_DATE_MASK BIT(31)
+
+/* STM32_RTC_WPR key constants */
+#define RTC_WPR_1ST_KEY 0xCA
+#define RTC_WPR_2ND_KEY 0x53
+#define RTC_WPR_WRONG_KEY 0xFF
+
+/*
+ * RTC registers are protected agains parasitic write access.
+ * PWR_CR_DBP bit must be set to enable write access to RTC registers.
+ */
+/* STM32_PWR_CR */
+#define PWR_CR 0x00
+/* STM32_PWR_CR bit field */
+#define PWR_CR_DBP BIT(8)
+
+static struct regmap *dbp;
+
+struct stm32_rtc {
+ struct rtc_device *rtc_dev;
+ void __iomem *base;
+ struct clk *ck_rtc;
+ spinlock_t lock; /* Protects registers accesses */
+ int irq_alarm;
+};
+
+static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
+{
+ writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + STM32_RTC_WPR);
+ writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + STM32_RTC_WPR);
+}
+
+static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
+{
+ writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + STM32_RTC_WPR);
+}
+
+static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
+{
+ unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+ if (!(isr & STM32_RTC_ISR_INITF)) {
+ isr |= STM32_RTC_ISR_INIT;
+ writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+
+ /*
+ * It takes around 2 ck_rtc clock cycles to enter in
+ * initialization phase mode (and have INITF flag set). As
+ * slowest ck_rtc frequency may be 32kHz and highest should be
+ * 1MHz, we poll every 10 us with a timeout of 100ms.
+ */
+ return readl_relaxed_poll_timeout_atomic(
+ rtc->base + STM32_RTC_ISR,
+ isr, (isr & STM32_RTC_ISR_INITF),
+ 10, 100000);
+ }
+
+ return 0;
+}
+
+static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc)
+{
+ unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+ isr &= ~STM32_RTC_ISR_INIT;
+ writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+}
+
+static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
+{
+ unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+ isr &= ~STM32_RTC_ISR_RSF;
+ writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+
+ /*
+ * Wait for RSF to be set to ensure the calendar registers are
+ * synchronised, it takes around 2 ck_rtc clock cycles
+ */
+ return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+ isr,
+ (isr & STM32_RTC_ISR_RSF),
+ 10, 100000);
+}
+
+static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
+{
+ struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id;
+ unsigned int isr, cr;
+
+ mutex_lock(&rtc->rtc_dev->ops_lock);
+
+ isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+ cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+
+ if ((isr & STM32_RTC_ISR_ALRAF) &&
+ (cr & STM32_RTC_CR_ALRAIE)) {
+ /* Alarm A flag - Alarm interrupt */
+ dev_dbg(&rtc->rtc_dev->dev, "Alarm occurred\n");
+
+ /* Pass event to the kernel */
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+ /* Clear event flag, otherwise new events won't be received */
+ writel_relaxed(isr & ~STM32_RTC_ISR_ALRAF,
+ rtc->base + STM32_RTC_ISR);
+ }
+
+ mutex_unlock(&rtc->rtc_dev->ops_lock);
+
+ return IRQ_HANDLED;
+}
+
+/* Convert rtc_time structure from bin to bcd format */
+static void tm2bcd(struct rtc_time *tm)
+{
+ tm->tm_sec = bin2bcd(tm->tm_sec);
+ tm->tm_min = bin2bcd(tm->tm_min);
+ tm->tm_hour = bin2bcd(tm->tm_hour);
+
+ tm->tm_mday = bin2bcd(tm->tm_mday);
+ tm->tm_mon = bin2bcd(tm->tm_mon + 1);
+ tm->tm_year = bin2bcd(tm->tm_year - 100);
+ /*
+ * Number of days since Sunday
+ * - on kernel side, 0=Sunday...6=Saturday
+ * - on rtc side, 0=invalid,1=Monday...7=Sunday
+ */
+ tm->tm_wday = (!tm->tm_wday) ? 7 : tm->tm_wday;
+}
+
+/* Convert rtc_time structure from bcd to bin format */
+static void bcd2tm(struct rtc_time *tm)
+{
+ tm->tm_sec = bcd2bin(tm->tm_sec);
+ tm->tm_min = bcd2bin(tm->tm_min);
+ tm->tm_hour = bcd2bin(tm->tm_hour);
+
+ tm->tm_mday = bcd2bin(tm->tm_mday);
+ tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
+ tm->tm_year = bcd2bin(tm->tm_year) + 100;
+ /*
+ * Number of days since Sunday
+ * - on kernel side, 0=Sunday...6=Saturday
+ * - on rtc side, 0=invalid,1=Monday...7=Sunday
+ */
+ tm->tm_wday %= 7;
+}
+
+static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int tr, dr;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&rtc->lock, irqflags);
+
+ /* Time and Date in BCD format */
+ tr = readl_relaxed(rtc->base + STM32_RTC_TR);
+ dr = readl_relaxed(rtc->base + STM32_RTC_DR);
+
+ spin_unlock_irqrestore(&rtc->lock, irqflags);
+
+ tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
+ tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
+ tm->tm_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
+
+ tm->tm_mday = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
+ tm->tm_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
+ tm->tm_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
+ tm->tm_wday = (dr & STM32_RTC_DR_WDAY) >> STM32_RTC_DR_WDAY_SHIFT;
+
+ /* We don't report tm_yday and tm_isdst */
+
+ bcd2tm(tm);
+
+ if (rtc_valid_tm(tm) < 0) {
+ dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int tr, dr;
+ unsigned long irqflags;
+ int ret = 0;
+
+ if (rtc_valid_tm(tm) < 0) {
+ dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
+ return -EINVAL;
+ }
+
+ tm2bcd(tm);
+
+ /* Time in BCD format */
+ tr = ((tm->tm_sec << STM32_RTC_TR_SEC_SHIFT) & STM32_RTC_TR_SEC) |
+ ((tm->tm_min << STM32_RTC_TR_MIN_SHIFT) & STM32_RTC_TR_MIN) |
+ ((tm->tm_hour << STM32_RTC_TR_HOUR_SHIFT) & STM32_RTC_TR_HOUR);
+
+ /* Date in BCD format */
+ dr = ((tm->tm_mday << STM32_RTC_DR_DATE_SHIFT) & STM32_RTC_DR_DATE) |
+ ((tm->tm_mon << STM32_RTC_DR_MONTH_SHIFT) & STM32_RTC_DR_MONTH) |
+ ((tm->tm_year << STM32_RTC_DR_YEAR_SHIFT) & STM32_RTC_DR_YEAR) |
+ ((tm->tm_wday << STM32_RTC_DR_WDAY_SHIFT) & STM32_RTC_DR_WDAY);
+
+ spin_lock_irqsave(&rtc->lock, irqflags);
+
+ stm32_rtc_wpr_unlock(rtc);
+
+ ret = stm32_rtc_enter_init_mode(rtc);
+ if (ret) {
+ dev_err(dev, "Can't enter in init mode. Set time aborted.\n");
+ goto end;
+ }
+
+ writel_relaxed(tr, rtc->base + STM32_RTC_TR);
+ writel_relaxed(dr, rtc->base + STM32_RTC_DR);
+
+ stm32_rtc_exit_init_mode(rtc);
+
+ ret = stm32_rtc_wait_sync(rtc);
+end:
+ stm32_rtc_wpr_lock(rtc);
+
+ spin_unlock_irqrestore(&rtc->lock, irqflags);
+
+ return ret;
+}
+
+static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ struct rtc_time *tm = &alrm->time;
+ unsigned int alrmar, cr, isr;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&rtc->lock, irqflags);
+
+ alrmar = readl_relaxed(rtc->base + STM32_RTC_ALRMAR);
+ cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+ spin_unlock_irqrestore(&rtc->lock, irqflags);
+
+ if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
+ /*
+ * Date/day doesn't matter in Alarm comparison so alarm
+ * triggers every day
+ */
+ tm->tm_mday = -1;
+ tm->tm_wday = -1;
+ } else {
+ if (alrmar & STM32_RTC_ALRMXR_WDSEL) {
+ /* Alarm is set to a day of week */
+ tm->tm_mday = -1;
+ tm->tm_wday = (alrmar & STM32_RTC_ALRMXR_WDAY) >>
+ STM32_RTC_ALRMXR_WDAY_SHIFT;
+ tm->tm_wday %= 7;
+ } else {
+ /* Alarm is set to a day of month */
+ tm->tm_wday = -1;
+ tm->tm_mday = (alrmar & STM32_RTC_ALRMXR_DATE) >>
+ STM32_RTC_ALRMXR_DATE_SHIFT;
+ }
+ }
+
+ if (alrmar & STM32_RTC_ALRMXR_HOUR_MASK) {
+ /* Hours don't matter in Alarm comparison */
+ tm->tm_hour = -1;
+ } else {
+ tm->tm_hour = (alrmar & STM32_RTC_ALRMXR_HOUR) >>
+ STM32_RTC_ALRMXR_HOUR_SHIFT;
+ if (alrmar & STM32_RTC_ALRMXR_PM)
+ tm->tm_hour += 12;
+ }
+
+ if (alrmar & STM32_RTC_ALRMXR_MIN_MASK) {
+ /* Minutes don't matter in Alarm comparison */
+ tm->tm_min = -1;
+ } else {
+ tm->tm_min = (alrmar & STM32_RTC_ALRMXR_MIN) >>
+ STM32_RTC_ALRMXR_MIN_SHIFT;
+ }
+
+ if (alrmar & STM32_RTC_ALRMXR_SEC_MASK) {
+ /* Seconds don't matter in Alarm comparison */
+ tm->tm_sec = -1;
+ } else {
+ tm->tm_sec = (alrmar & STM32_RTC_ALRMXR_SEC) >>
+ STM32_RTC_ALRMXR_SEC_SHIFT;
+ }
+
+ bcd2tm(tm);
+
+ alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0;
+ alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0;
+
+ return 0;
+}
+
+static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ unsigned long irqflags;
+ unsigned int isr, cr;
+
+ spin_lock_irqsave(&rtc->lock, irqflags);
+
+ cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+
+ stm32_rtc_wpr_unlock(rtc);
+
+ /* We expose Alarm A to the kernel */
+ if (enabled)
+ cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
+ else
+ cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
+ writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+
+ /* Clear event irqflags, otherwise new events won't be received */
+ isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+ isr &= ~STM32_RTC_ISR_ALRAF;
+ writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+
+ stm32_rtc_wpr_lock(rtc);
+
+ spin_unlock_irqrestore(&rtc->lock, irqflags);
+
+ return 0;
+}
+
+static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
+{
+ unsigned int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec;
+ unsigned int dr = readl_relaxed(rtc->base + STM32_RTC_DR);
+ unsigned int tr = readl_relaxed(rtc->base + STM32_RTC_TR);
+
+ cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
+ cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
+ cur_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
+ cur_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
+ cur_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
+ cur_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
+
+ /*
+ * Assuming current date is M-D-Y H:M:S.
+ * RTC alarm can't be set on a specific month and year.
+ * So the valid alarm range is:
+ * M-D-Y H:M:S < alarm <= (M+1)-D-Y H:M:S
+ * with a specific case for December...
+ */
+ if ((((tm->tm_year > cur_year) &&
+ (tm->tm_mon == 0x1) && (cur_mon == 0x12)) ||
+ ((tm->tm_year == cur_year) &&
+ (tm->tm_mon <= cur_mon + 1))) &&
+ ((tm->tm_mday < cur_day) ||
+ ((tm->tm_mday == cur_day) &&
+ ((tm->tm_hour < cur_hour) ||
+ ((tm->tm_hour == cur_hour) && (tm->tm_min < cur_min)) ||
+ ((tm->tm_hour == cur_hour) && (tm->tm_min == cur_min) &&
+ (tm->tm_sec <= cur_sec))))))
+ return 0;
+
+ return -EINVAL;
+}
+
+static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ struct rtc_time *tm = &alrm->time;
+ unsigned long irqflags;
+ unsigned int cr, isr, alrmar;
+ int ret = 0;
+
+ if (rtc_valid_tm(tm)) {
+ dev_err(dev, "Alarm time not valid.\n");
+ return -EINVAL;
+ }
+
+ tm2bcd(tm);
+
+ /*
+ * RTC alarm can't be set on a specific date, unless this date is
+ * up to the same day of month next month.
+ */
+ if (stm32_rtc_valid_alrm(rtc, tm) < 0) {
+ dev_err(dev, "Alarm can be set only on upcoming month.\n");
+ return -EINVAL;
+ }
+
+ alrmar = 0;
+ /* tm_year and tm_mon are not used because not supported by RTC */
+ alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) &
+ STM32_RTC_ALRMXR_DATE;
+ /* 24-hour format */
+ alrmar &= ~STM32_RTC_ALRMXR_PM;
+ alrmar |= (tm->tm_hour << STM32_RTC_ALRMXR_HOUR_SHIFT) &
+ STM32_RTC_ALRMXR_HOUR;
+ alrmar |= (tm->tm_min << STM32_RTC_ALRMXR_MIN_SHIFT) &
+ STM32_RTC_ALRMXR_MIN;
+ alrmar |= (tm->tm_sec << STM32_RTC_ALRMXR_SEC_SHIFT) &
+ STM32_RTC_ALRMXR_SEC;
+
+ spin_lock_irqsave(&rtc->lock, irqflags);
+
+ stm32_rtc_wpr_unlock(rtc);
+
+ /* Disable Alarm */
+ cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ cr &= ~STM32_RTC_CR_ALRAE;
+ writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+
+ /*
+ * Poll Alarm write flag to be sure that Alarm update is allowed: it
+ * takes around 2 ck_rtc clock cycles
+ */
+ ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+ isr,
+ (isr & STM32_RTC_ISR_ALRAWF),
+ 10, 100000);
+
+ if (ret) {
+ dev_err(dev, "Alarm update not allowed\n");
+ goto end;
+ }
+
+ /* Write to Alarm register */
+ writel_relaxed(alrmar, rtc->base + STM32_RTC_ALRMAR);
+
+ if (alrm->enabled)
+ stm32_rtc_alarm_irq_enable(dev, 1);
+ else
+ stm32_rtc_alarm_irq_enable(dev, 0);
+
+end:
+ stm32_rtc_wpr_lock(rtc);
+
+ spin_unlock_irqrestore(&rtc->lock, irqflags);
+
+ return ret;
+}
+
+static const struct rtc_class_ops stm32_rtc_ops = {
+ .read_time = stm32_rtc_read_time,
+ .set_time = stm32_rtc_set_time,
+ .read_alarm = stm32_rtc_read_alarm,
+ .set_alarm = stm32_rtc_set_alarm,
+ .alarm_irq_enable = stm32_rtc_alarm_irq_enable,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id stm32_rtc_of_match[] = {
+ { .compatible = "st,stm32-rtc" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
+#endif
+
+static int stm32_rtc_init(struct platform_device *pdev,
+ struct stm32_rtc *rtc)
+{
+ unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
+ unsigned int rate;
+ unsigned long irqflags;
+ int ret = 0;
+
+ rate = clk_get_rate(rtc->ck_rtc);
+
+ /* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
+ pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
+ pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
+
+ for (pred_a = pred_a_max; pred_a >= 0; pred_a--) {
+ pred_s = (rate / (pred_a + 1)) - 1;
+
+ if (((pred_s + 1) * (pred_a + 1)) == rate)
+ break;
+ }
+
+ /*
+ * Can't find a 1Hz, so give priority to RTC power consumption
+ * by choosing the higher possible value for prediv_a
+ */
+ if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) {
+ pred_a = pred_a_max;
+ pred_s = (rate / (pred_a + 1)) - 1;
+
+ dev_warn(&pdev->dev, "ck_rtc is %s\n",
+ (rate - ((pred_a + 1) * (pred_s + 1)) < 0) ?
+ "fast" : "slow");
+ }
+
+ spin_lock_irqsave(&rtc->lock, irqflags);
+
+ stm32_rtc_wpr_unlock(rtc);
+
+ ret = stm32_rtc_enter_init_mode(rtc);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Can't enter in init mode. Prescaler config failed.\n");
+ goto end;
+ }
+
+ prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
+ writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+ prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
+ writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+
+ /* Force 24h time format */
+ cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ cr &= ~STM32_RTC_CR_FMT;
+ writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+
+ stm32_rtc_exit_init_mode(rtc);
+
+ ret = stm32_rtc_wait_sync(rtc);
+end:
+ stm32_rtc_wpr_lock(rtc);
+
+ spin_unlock_irqrestore(&rtc->lock, irqflags);
+
+ return ret;
+}
+
+static int stm32_rtc_probe(struct platform_device *pdev)
+{
+ struct stm32_rtc *rtc;
+ struct resource *res;
+ int ret;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rtc->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rtc->base))
+ return PTR_ERR(rtc->base);
+
+ dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "st,syscfg");
+ if (IS_ERR(dbp)) {
+ dev_err(&pdev->dev, "no st,syscfg\n");
+ return PTR_ERR(dbp);
+ }
+
+ spin_lock_init(&rtc->lock);
+
+ rtc->ck_rtc = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(rtc->ck_rtc)) {
+ dev_err(&pdev->dev, "no ck_rtc clock");
+ return PTR_ERR(rtc->ck_rtc);
+ }
+
+ ret = clk_prepare_enable(rtc->ck_rtc);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
+
+ /*
+ * After a system reset, RTC_ISR.INITS flag can be read to check if
+ * the calendar has been initalized or not. INITS flag is reset by a
+ * power-on reset (no vbat, no power-supply). It is not reset if
+ * ck_rtc parent clock has changed (so RTC prescalers need to be
+ * changed). That's why we cannot rely on this flag to know if RTC
+ * init has to be done.
+ */
+ ret = stm32_rtc_init(pdev, rtc);
+ if (ret)
+ goto err;
+
+ rtc->irq_alarm = platform_get_irq(pdev, 0);
+ if (rtc->irq_alarm <= 0) {
+ dev_err(&pdev->dev, "no alarm irq\n");
+ ret = rtc->irq_alarm;
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, rtc);
+
+ ret = device_init_wakeup(&pdev->dev, true);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "alarm won't be able to wake up the system");
+
+ rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
+ &stm32_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc->rtc_dev)) {
+ ret = PTR_ERR(rtc->rtc_dev);
+ dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
+ ret);
+ goto err;
+ }
+
+ /* Handle RTC alarm interrupts */
+ ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL,
+ stm32_rtc_alarm_irq,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ pdev->name, rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n",
+ rtc->irq_alarm);
+ goto err;
+ }
+
+ /*
+ * If INITS flag is reset (calendar year field set to 0x00), calendar
+ * must be initialized
+ */
+ if (!(readl_relaxed(rtc->base + STM32_RTC_ISR) & STM32_RTC_ISR_INITS))
+ dev_warn(&pdev->dev, "Date/Time must be initialized\n");
+
+ return 0;
+err:
+ clk_disable_unprepare(rtc->ck_rtc);
+
+ regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
+
+ device_init_wakeup(&pdev->dev, false);
+
+ return ret;
+}
+
+static int __exit stm32_rtc_remove(struct platform_device *pdev)
+{
+ struct stm32_rtc *rtc = platform_get_drvdata(pdev);
+ unsigned int cr;
+
+ /* Disable interrupts */
+ stm32_rtc_wpr_unlock(rtc);
+ cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ cr &= ~STM32_RTC_CR_ALRAIE;
+ writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+ stm32_rtc_wpr_lock(rtc);
+
+ clk_disable_unprepare(rtc->ck_rtc);
+
+ /* Enable backup domain write protection */
+ regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
+
+ device_init_wakeup(&pdev->dev, false);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int stm32_rtc_suspend(struct device *dev)
+{
+ struct stm32_rtc *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ return enable_irq_wake(rtc->irq_alarm);
+
+ return 0;
+}
+
+static int stm32_rtc_resume(struct device *dev)
+{
+ struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = stm32_rtc_wait_sync(rtc);
+ if (ret < 0)
+ return ret;
+
+ if (device_may_wakeup(dev))
+ return disable_irq_wake(rtc->irq_alarm);
+
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
+ stm32_rtc_suspend, stm32_rtc_resume);
+
+static struct platform_driver stm32_rtc_driver = {
+ .probe = stm32_rtc_probe,
+ .remove = stm32_rtc_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .pm = &stm32_rtc_pm_ops,
+ .of_match_table = stm32_rtc_of_match,
+ },
+};
+
+module_platform_driver(stm32_rtc_driver);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 Real Time Clock driver");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCHv3 4/8] ARM: dts: stm32: Add RTC support for STM32F429 MCU
From: Amelie Delaunay @ 2017-01-05 13:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483623809-29937-1-git-send-email-amelie.delaunay@st.com>
This patch adds STM32 RTC bindings for STM32F429.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index d195ccf..d181025 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -125,6 +125,20 @@
status = "disabled";
};
+ rtc: rtc at 40002800 {
+ compatible = "st,stm32-rtc";
+ reg = <0x40002800 0x400>;
+ clocks = <&rcc 1 CLK_RTC>;
+ clock-names = "ck_rtc";
+ assigned-clocks = <&rcc 1 CLK_RTC>;
+ assigned-clock-parents = <&rcc 1 CLK_LSE>;
+ interrupt-parent = <&exti>;
+ interrupts = <17 1>;
+ interrupt-names = "alarm";
+ st,syscfg = <&pwrcfg>;
+ status = "disabled";
+ };
+
usart2: serial at 40004400 {
compatible = "st,stm32-usart", "st,stm32-uart";
reg = <0x40004400 0x400>;
--
1.9.1
^ permalink raw reply related
* [PATCHv3 5/8] ARM: dts: stm32: enable RTC on stm32f429-disco
From: Amelie Delaunay @ 2017-01-05 13:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483623809-29937-1-git-send-email-amelie.delaunay@st.com>
This patch enables RTC on stm32f429-disco with LSI as clock source because
X2 crystal for LSE is not fitted by default.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/boot/dts/stm32f429-disco.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429-disco.dts b/arch/arm/boot/dts/stm32f429-disco.dts
index b6e63d8..49eddf6 100644
--- a/arch/arm/boot/dts/stm32f429-disco.dts
+++ b/arch/arm/boot/dts/stm32f429-disco.dts
@@ -94,6 +94,12 @@
clock-frequency = <8000000>;
};
+&rtc {
+ assigned-clocks = <&rcc 1 CLK_RTC>;
+ assigned-clock-parents = <&rcc 1 CLK_LSI>;
+ status = "okay";
+};
+
&usart1 {
pinctrl-0 = <&usart1_pins_a>;
pinctrl-names = "default";
--
1.9.1
^ permalink raw reply related
* [PATCHv3 6/8] ARM: dts: stm32: enable RTC on stm32f469-disco
From: Amelie Delaunay @ 2017-01-05 13:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483623809-29937-1-git-send-email-amelie.delaunay@st.com>
This patch enables RTC on stm32f469-disco with default LSE clock source.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/boot/dts/stm32f469-disco.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
index 8a163d7..af57dd5 100644
--- a/arch/arm/boot/dts/stm32f469-disco.dts
+++ b/arch/arm/boot/dts/stm32f469-disco.dts
@@ -78,6 +78,10 @@
clock-frequency = <8000000>;
};
+&rtc {
+ status = "okay";
+};
+
&usart3 {
status = "okay";
};
--
1.9.1
^ permalink raw reply related
* [PATCHv3 7/8] ARM: dts: stm32: enable RTC on stm32429i-eval
From: Amelie Delaunay @ 2017-01-05 13:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483623809-29937-1-git-send-email-amelie.delaunay@st.com>
This patch enables RTC on stm32429i-eval with default LSE clock source.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/boot/dts/stm32429i-eval.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index 8b158f9..5007da9 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -134,6 +134,10 @@
};
};
+&rtc {
+ status = "okay";
+};
+
&usart1 {
pinctrl-0 = <&usart1_pins_a>;
pinctrl-names = "default";
--
1.9.1
^ permalink raw reply related
* [PATCHv3 8/8] ARM: configs: stm32: Add RTC support in STM32 defconfig
From: Amelie Delaunay @ 2017-01-05 13:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483623809-29937-1-git-send-email-amelie.delaunay@st.com>
This patch adds STM32 RTC support in stm32_defconfig file.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
arch/arm/configs/stm32_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
index be19e09..0acff9e 100644
--- a/arch/arm/configs/stm32_defconfig
+++ b/arch/arm/configs/stm32_defconfig
@@ -57,6 +57,8 @@ CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_STM32=y
CONFIG_DMADEVICES=y
CONFIG_STM32_DMA=y
# CONFIG_FILE_LOCKING is not set
--
1.9.1
^ permalink raw reply related
* [GIT PULL] arm-soc fixes for 4.10-rc
From: Arnd Bergmann @ 2017-01-05 13:45 UTC (permalink / raw)
To: linux-arm-kernel
The following changes since commit 0c744ea4f77d72b3dcebb7a8f2684633ec79be88:
Linux 4.10-rc2 (2017-01-01 14:31:53 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-fixes
for you to fetch changes up to 1b9ec81258827001c869f003e0b8dd2ddc104717:
Merge tag 'davinci-fixes-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into fixes (2017-01-04 16:43:00 +0100)
----------------------------------------------------------------
This is a rather large set of bugfixes, as we just returned from the
Christmas break. Most of these are relatively unimportant fixes for
regressions introduced during the merge window, and about half of
the changes are for mach-omap2.
A couple of patches are just cleanups and dead code removal that I would
not normally have considered for merging after -rc2, but I decided to
take them along with the fixes this time.
Notable fixes include:
- removing the skeleton.dtsi include broke a number of machines, and we
have to put empty /chosen nodes back to be able to pass kernel command
lines as before
- enabling Samsung platforms no longer hardwires CONFIG_HZ to 200,
as it had been for no good reason for a long time.
----------------------------------------------------------------
Adam Ford (1):
ARM: dts: omap3: Add DTS for Logic PD SOM-LV 37xx Dev Kit
Alexandre Bailon (2):
ARM: davinci: Make __clk_{enable,disable} functions public
ARM: davinci: da8xx: Fix sleeping function called from invalid context
Andreas F?rber (1):
ARM: dts: vf610-zii-dev-rev-b: Add missing newline
Arnd Bergmann (12):
Merge tag 'renesas-fixes-for-v4.10' of https://git.kernel.org/.../horms/renesas into fixes
Merge tag 'qcom-fixes-for-4.10-rc1' of git://git.kernel.org/.../agross/linux into fixes
Merge tag 'samsung-soc-4.10-2' of git://git.kernel.org/.../krzk/linux into fixes
Merge tag 'omap-for-v4.10/fixes-rc1' of git://git.kernel.org/.../tmlind/linux-omap into fixes
Merge tag 'qcom-arm-fixes-for-4.10-rc2' of git://git.kernel.org/.../agross/linux into fixes
Merge tag 'imx-fixes-4.10' of git://git.kernel.org/.../shawnguo/linux into fixes
Merge tag 'scpi-fixes-4.10' of git://git.kernel.org/.../sudeep.holla/linux into fixes
Merge tag 'vexpress-fixes-4.10' of git://git.kernel.org/.../sudeep.holla/linux into fixes
Merge tag 'juno-fixes-4.10' of git://git.kernel.org/.../sudeep.holla/linux into fixes
Merge tag 'psci-fixes-4.10' of git://git.kernel.org/.../lpieralisi/linux into fixes
Merge tag 'amlogic-fixes' of git://git.kernel.org/.../khilman/linux-amlogic into fixes
Merge tag 'davinci-fixes-for-v4.10' of git://git.kernel.org/.../nsekhar/linux-davinci into fixes
Bartosz Golaszewski (2):
ARM: davinci: da850: fix infinite loop in clk_set_rate()
ARM: davinci: da850: don't add emac clock to lookup table twice
Bjorn Andersson (1):
ARM: dts: qcom: apq8064: Add missing scm clock
Christoffer Dall (1):
ARM: dts: vexpress: Support GICC_DIR operations
Fabio Estevam (1):
ARM: dts: imx6: Disable "weim" node in the dtsi files
Gary Bisson (1):
ARM: dts: imx6qdl-nitrogen6x: remove duplicate iomux entry
Grygorii Strashko (2):
ARM: OMAP2+: Remove legacy gpio code
ARM: omap2+: am437x: rollback to use omap3_gptimer_timer_init()
Javier Martinez Canillas (9):
ARM: dts: omap2: Add an empty chosen node to top level DTSI
ARM: dts: omap3: Add an empty chosen node to top level DTSI
ARM: dts: omap4: Add an empty chosen node to top level DTSI
ARM: dts: omap5: Add an empty chosen node to top level DTSI
ARM: dts: am33xx: Add an empty chosen node to top level DTSI
ARM: dts: am4372: Add an empty chosen node to top level DTSI
ARM: dts: dm814x: Add an empty chosen node to top level DTSI
ARM: dts: dm816x: Add an empty chosen node to top level DTSI
ARM: dts: dra7: Add an empty chosen node to top level DTSI
Kevin Hilman (2):
ARM64: dts: meson-gxl: fix GPIO include
ARM64: defconfig: enable DRM_MESON as module
Kishon Vijay Abraham I (1):
ARM: dts: am572x-idk: Add gpios property to control PCIE_RESETn
Krzysztof Kozlowski (1):
ARM: Drop fixed 200 Hz timer requirement from Samsung platforms
Lokesh Vutla (1):
ARM: dts: dra72-evm-tps65917: Add voltage supplies to usb_phy, mmc, dss
Maninder Singh (1):
ARM: omap2+: fixing wrong strcat for Non-NULL terminated string
Markus Elfring (1):
ARM: OMAP2+: PRM: Delete an error message for a failed memory allocation
Martin Blumenstingl (1):
firmware: arm_scpi: fix reading sensor values on pre-1.0 SCPI firmwares
Milo Kim (4):
ARM: dts: am335x: Fix the interrupt name of TPS65217
dt-bindings: mfd: Remove TPS65217 interrupts
dt-bindings: power/supply: Update TPS65217 properties
dt-bindings: input: Specify the interrupt number of TPS65217 power button
Neil Armstrong (1):
ARM64: dts: meson-gx: Add Graphic Controller nodes
Pali Roh?r (1):
ARM: dts: n900: Mark eMMC slot with no-sdio and no-sd flags
Pankaj Dubey (1):
ARM: EXYNOS: Remove smp_init_cpus hook from platsmp.c
Roger Quadros (2):
ARM: dts: am57xx-idk: Support VBUS detection on USB2 port
ARM: dts: am57xx-idk: Put USB2 port in peripheral mode
Simon Horman (1):
arm64: dts: h3ulcb: Provide sd0_uhs node
Stephen Boyd (1):
arm64: dts: msm8996: Add required memory carveouts
Sudeep Holla (3):
arm64: dts: vexpress: Support GICC_DIR operations
drivers: psci: annotate timer on stack to silence odebug messages
MAINTAINERS: extend PSCI entry to cover the newly add PSCI checker code
Sylwester Nawrocki (1):
ARM: S3C24XX: Add DMA slave maps for remaining s3c24xx SoCs
Tony Lindgren (1):
Merge branch 'omap-for-v4.10/legacy' into omap-for-v4.10/fixes
Vladimir Murzin (1):
ARM: i.MX: remove map_io callback
Vladimir Zapolskiy (1):
ARM: dts: imx31: fix AVIC base address
.../bindings/input/tps65218-pwrbutton.txt | 4 +-
.../bindings/power/supply/tps65217_charger.txt | 7 +-
MAINTAINERS | 2 +-
arch/arm/Kconfig | 3 +-
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/am335x-bone-common.dtsi | 8 +-
arch/arm/boot/dts/am33xx.dtsi | 1 +
arch/arm/boot/dts/am4372.dtsi | 1 +
arch/arm/boot/dts/am571x-idk.dts | 10 +-
arch/arm/boot/dts/am572x-idk.dts | 14 +-
arch/arm/boot/dts/am57xx-idk-common.dtsi | 9 +-
arch/arm/boot/dts/dm814x.dtsi | 1 +
arch/arm/boot/dts/dm816x.dtsi | 1 +
arch/arm/boot/dts/dra7.dtsi | 1 +
arch/arm/boot/dts/dra72-evm-tps65917.dtsi | 16 +++
arch/arm/boot/dts/imx31.dtsi | 4 +-
arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 1 -
arch/arm/boot/dts/imx6qdl.dtsi | 1 +
arch/arm/boot/dts/imx6sl.dtsi | 1 +
arch/arm/boot/dts/imx6sx.dtsi | 1 +
arch/arm/boot/dts/omap2.dtsi | 1 +
arch/arm/boot/dts/omap3-n900.dts | 2 +
arch/arm/boot/dts/omap3.dtsi | 1 +
arch/arm/boot/dts/omap4.dtsi | 1 +
arch/arm/boot/dts/omap5.dtsi | 1 +
arch/arm/boot/dts/qcom-apq8064.dtsi | 4 +
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 2 +-
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 2 +-
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts | 3 +-
arch/arm/mach-davinci/clock.c | 12 +-
arch/arm/mach-davinci/clock.h | 2 +
arch/arm/mach-davinci/da850.c | 32 ++++-
arch/arm/mach-davinci/usb-da8xx.c | 34 ++---
arch/arm/mach-exynos/platsmp.c | 31 ----
arch/arm/mach-imx/mach-imx1.c | 1 -
arch/arm/mach-omap2/Makefile | 2 +-
arch/arm/mach-omap2/board-generic.c | 2 +-
arch/arm/mach-omap2/gpio.c | 160 ---------------------
arch/arm/mach-omap2/omap_hwmod.c | 8 +-
arch/arm/mach-omap2/omap_hwmod_common_data.h | 4 -
arch/arm/mach-omap2/prm_common.c | 4 +-
arch/arm/mach-omap2/timer.c | 9 +-
arch/arm/mach-s3c24xx/common.c | 76 ++++++++++
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 16 +++
.../boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts | 16 +++
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 16 +++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 4 +
.../boot/dts/amlogic/meson-gxl-nexbox-a95x.dts | 16 +++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 6 +-
.../arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 16 +++
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi | 4 +
arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8996.dtsi | 10 ++
arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts | 2 +-
arch/arm64/configs/defconfig | 1 +
drivers/firmware/arm_scpi.c | 10 +-
drivers/firmware/psci_checker.c | 4 +-
include/dt-bindings/mfd/tps65217.h | 26 ----
58 files changed, 334 insertions(+), 296 deletions(-)
delete mode 100644 arch/arm/mach-omap2/gpio.c
delete mode 100644 include/dt-bindings/mfd/tps65217.h
^ permalink raw reply
* [PATCH 02/10] iommu/of: Prepare for deferred IOMMU configuration
From: Robin Murphy @ 2017-01-05 13:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170105122714.GA30449@red-moon>
On 05/01/17 12:27, Lorenzo Pieralisi wrote:
> On Thu, Jan 05, 2017 at 02:04:37PM +0530, Sricharan wrote:
>> Hi Robin/Lorenzo,
>>
>>> Hi Robin,Lorenzo,
>>>
>>>> On Wed, Nov 30, 2016 at 04:42:27PM +0000, Robin Murphy wrote:
>>>>> On 30/11/16 16:17, Lorenzo Pieralisi wrote:
>>>>>> Sricharan, Robin,
>>>>>>
>>>>>> I gave this series a go on ACPI and apart from an SMMU v3 fix-up
>>>>>> it seems to work, more thorough testing required though.
>>>>>>
>>>>>> A key question below.
>>>>>>
>>>>>> On Wed, Nov 30, 2016 at 05:52:16AM +0530, Sricharan R wrote:
>>>>>>> From: Robin Murphy <robin.murphy@arm.com>
>>>>>>>
>>>>>>> IOMMU configuration represents unchanging properties of the hardware,
>>>>>>> and as such should only need happen once in a device's lifetime, but
>>>>>>> the necessary interaction with the IOMMU device and driver complicates
>>>>>>> exactly when that point should be.
>>>>>>>
>>>>>>> Since the only reasonable tool available for handling the inter-device
>>>>>>> dependency is probe deferral, we need to prepare of_iommu_configure()
>>>>>>> to run later than it is currently called (i.e. at driver probe rather
>>>>>>> than device creation), to handle being retried, and to tell whether a
>>>>>>> not-yet present IOMMU should be waited for or skipped (by virtue of
>>>>>>> having declared a built-in driver or not).
>>>>>>>
>>>>>>> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
>>>>>>> ---
>>>>>>> drivers/iommu/of_iommu.c | 30 +++++++++++++++++++++++++++++-
>>>>>>> 1 file changed, 29 insertions(+), 1 deletion(-)
>>>>>>>
>>>>>>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
>>>>>>> index ee49081..349bd1d 100644
>>>>>>> --- a/drivers/iommu/of_iommu.c
>>>>>>> +++ b/drivers/iommu/of_iommu.c
>>>>>>> @@ -104,12 +104,20 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
>>>>>>> int err;
>>>>>>>
>>>>>>> ops = iommu_get_instance(fwnode);
>>>>>>> - if (!ops || !ops->of_xlate)
>>>>>>> + if ((ops && !ops->of_xlate) ||
>>>>>>> + (!ops && !of_match_node(&__iommu_of_table, iommu_spec->np)))
>>>>>>
>>>>>> IIUC of_match_node() here is there to check there is a driver compiled
>>>>>> in for this device_node (aka compatible string in OF world), correct ?
>>>>>
>>>>> Yes - specifically, it's checking the magic table for a matching
>>>>> IOMMU_OF_DECLARE entry.
>>>>>
>>>>>> If that's the case (and I think that's what Sricharan was referring to
>>>>>> in his ACPI query) I need to cook-up something on the ACPI side to
>>>>>> emulate the OF linker table behaviour (or anyway to detect a driver is
>>>>>> actually in the kernel), it is not that difficult but it is key to know,
>>>>>> I will give it some thought to make it as clean as possible.
>>>>>
>>>>> I didn't think this would be a concern for ACPI, since IORT works much
>>>>> the same way the current of_iommu_init_fn/of_platform_device_create()
>>>>> bodges in drivers so for DT. If you can only discover SMMUs from IORT,
>>>>> then iort_init_platform_devices() will have already created every SMMU
>>>>> that's going to exist before discovering other devices from wherever
>>>>> they come from, thus you could never get into the situation of probing a
>>>>> device without its SMMU being ready (if it's ever going to be). Is that
>>>>> not right?
>>>>
>>>> It is right, my point and question is: we are probing a device and we
>>>> have to know whether it is worth deferring its IOMMU DMA setup. On DT,
>>>> through of_match_node(&__iommu_of_table, iommu_device_node) we check at
>>>> once that:
>>>>
>>>> 1 - A device for the IOMMU exists
>>>>
>>>> AND
>>>>
>>>> 2 - A driver for the IOMMU is compiled in the kernel
>>>>
>>>> Is this correct ? As you said (1) is not a concern on ACPI IORT (because
>>>> we create the IOMMU device before _any_ other device so either the IOMMU
>>>> device is there or it will never be by the time master devices are
>>>> probed), but for (2) I need to slightly change how the IORT linker entry
>>>> work to make sure we can detect a driver is actually compiled in the
>>>> kernel, it is easy, I was just asking if my understanding was correct
>>>> and I think that was what Sricharan was referring to in his query.
>>>>
>>>
>>> Yes right, this was what i was looking for in the ACPI case and putting this
>>> in the iort_iommu_xlate was needed to return EPROBE_DEFER when the
>>> driver is not yet been probed.
>>
>> With the thinking of taking this series through, would it be fine if i
>> cleanup the pci configure hanging outside and push it in to
>> of/acpi_iommu configure respectively ? This time with all neeeded for
>> ACPI added as well. Also on the last post of V4, Lorenzo commented
>> that it worked for him, although still the of_match_node equivalent in
>> ACPI has to be added. If i can get that, then i will add that as well
>> to make this complete.
>
> Question: I had a look into this and instead of fiddling about with the
> linker script entries in ACPI (ie IORT_ACPI_DECLARE - which I hope this
> patchset would help remove entirely), I think that the only check we
> need in IORT is, depending on what type of SMMU a given device is
> connected to, to check if the respective SMMU driver is compiled in the
> kernel and it will be probed, _eventually_.
>
> As Robin said, by the time a device is probed the respective SMMU
> devices are already created and registered with IORT kernel code or
> they will never be, so to understand if we should defer probing
> SMMU device creation is _not_ really a problem in ACPI.
>
> To check if a SMMU driver is enabled, do we really need a linker
> table ?
>
> Would not a check based on eg:
>
> /**
> * @type: IOMMU IORT node type of the IOMMU a device is connected to
> */
> static bool iort_iommu_driver_enabled(u8 type)
> {
> switch (type) {
> case ACPI_IORT_SMMU_V3:
> return IS_ENABLED(CONFIG_ARM_SMMU_V3);
IS_BUILTIN(...)
> case ACPI_IORT_SMMU:
> return IS_ENABLED(CONFIG_ARM_SMMU);
> default:
> pr_warn("Unknown IORT SMMU type\n");
Might displaying the actual value be helfpul for debugging a broken IORT
table?
> return false;
> }
> }
>
> be sufficient (it is a bit gross, agreed, but it is to understand if
> that's all we need) ? Is there anything I am missing ?
>
> Let me know, I will put together a patch for you I really do not
> want to block your series for this trivial niggle.
Other than that, though, I like it :) IORT has a small, strictly
bounded, set of supported devices, so I really don't see the need to go
overboard putting it on parity with DT when something this neat and
simple will suffice.
Robin.
>
> Thanks,
> Lorenzo
>
^ permalink raw reply
* [PATCHv2 1/5] clk: mvebu: support for 98DX3236 SoC
From: Mark Rutland @ 2017-01-05 13:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170105033641.6212-2-chris.packham@alliedtelesis.co.nz>
On Thu, Jan 05, 2017 at 04:36:37PM +1300, Chris Packham wrote:
> The 98DX3236, 98DX3336, 98DX4521 and variants have a different TCLK from
> the Armada XP (200MHz vs 250MHz). The CPU core clock is fixed at 800MHz.
>
> The clock gating options are a subset of those on the Armada XP.
>
> The core clock divider is different to the Armada XP also.
>
> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
> ---
> Changes in v2:
> - Update devicetree binding documentation for new compatible string
>
> .../devicetree/bindings/clock/mvebu-cpu-clock.txt | 1 +
> drivers/clk/mvebu/Makefile | 2 +-
> drivers/clk/mvebu/armada-xp.c | 42 +++++
> drivers/clk/mvebu/clk-cpu.c | 33 +++-
> drivers/clk/mvebu/mv98dx3236-corediv.c | 207 +++++++++++++++++++++
> 5 files changed, 281 insertions(+), 4 deletions(-)
> create mode 100644 drivers/clk/mvebu/mv98dx3236-corediv.c
It looks like you also need to update
Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt for the
addition of "marvell,mv98dx3236-corediv-clock".
>
> diff --git a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
> index 99c214660bdc..7f28506eaee7 100644
> --- a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
> @@ -3,6 +3,7 @@ Device Tree Clock bindings for cpu clock of Marvell EBU platforms
> Required properties:
> - compatible : shall be one of the following:
> "marvell,armada-xp-cpu-clock" - cpu clocks for Armada XP
> + "marvell,mv98dx3236-cpu-clock" - cpu clocks for 98DX3236 SoC
> - reg : Address and length of the clock complex register set, followed
> by address and length of the PMU DFS registers
> - #clock-cells : should be set to 1.
[...]
> +static void __init mv98dx3236_corediv_clk_init(struct device_node *node)
> +{
> + struct clk_init_data init;
> + struct clk_corediv *corediv;
> + struct clk **clks;
> + void __iomem *base;
> + const __be32 *off;
> + const char *parent_name;
> + const char *clk_name;
> + int len;
> + struct device_node *dfx_node;
> +
> + dfx_node = of_parse_phandle(node, "base", 0);
> + if (WARN_ON(!dfx_node))
What's going on here? The existing bingings don't mention a "base"
phandle, and nothing was added to describe it.
> + return;
> +
> + off = of_get_property(node, "reg", &len);
> + if (WARN_ON(!off))
> + return;
Please don't use of_get_property directly; generally you should use the
existing higher-level helpers like of_proeprty_read_u32().
> +
> + base = of_iomap(dfx_node, 0);
> + if (WARN_ON(!base))
> + return;
> +
> + of_node_put(dfx_node);
> +
> + parent_name = of_clk_get_parent_name(node, 0);
> +
> + clk_data.clk_num = 1;
> +
> + /* clks holds the clock array */
> + clks = kcalloc(clk_data.clk_num, sizeof(struct clk *),
> + GFP_KERNEL);
> + if (WARN_ON(!clks))
> + goto err_unmap;
> + /* corediv holds the clock specific array */
> + corediv = kcalloc(clk_data.clk_num, sizeof(struct clk_corediv),
> + GFP_KERNEL);
> + if (WARN_ON(!corediv))
> + goto err_free_clks;
> +
> + spin_lock_init(&corediv->lock);
> +
> + of_property_read_string_index(node, "clock-output-names",
> + 0, &clk_name);
> +
> + init.num_parents = 1;
> + init.parent_names = &parent_name;
> + init.name = clk_name;
> + init.ops = &ops;
> + init.flags = 0;
> +
> + corediv[0].reg = (void *)((int)base + be32_to_cpu(*off));
I don't understand this, but I guess this has something to do with that
base phandle. Is the corediv clock a sub-component of some "base" clock?
I don't think this binding is the best way of describing that.
Thanks,
Mark.
^ permalink raw reply
* [PATCHv2 4/5] arm: mvebu: Add device tree for 98DX3236 SoCs
From: Mark Rutland @ 2017-01-05 13:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170105033641.6212-5-chris.packham@alliedtelesis.co.nz>
On Thu, Jan 05, 2017 at 04:36:40PM +1300, Chris Packham wrote:
> + internal-regs {
> + coreclk: mvebu-sar at 18230 {
> + compatible = "marvell,mv98dx3236-core-clock";
> + };
> +
> + cpuclk: clock-complex at 18700 {
> + compatible = "marvell,mv98dx3236-cpu-clock";
> + };
> +
> + corediv-clock at 18740 {
> + compatible = "marvell,mv98dx3236-corediv-clock";
> + reg = <0xf8268 0xc>;
> + base = <&dfx>;
> + #clock-cells = <1>;
> + clocks = <&mainpll>;
> + clock-output-names = "nand";
> + };
[...]
> + };
> +
> + dfx-registers {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>;
> +
> + dfx: dfx at 0 {
> + compatible = "simple-bus";
> + reg = <0 0x100000>;
> + };
> + };
What is this dfx-registers, exactly? It has no children, so why is it a
simple-bus?
>From the above, and the patch adding the corediv driver, it looks like
the corediv-clock actually lives in this block, so I don't understand
why the corediv-clock is sitting in internal-regs with a sideband
reference to dfx.
Thanks,
Mark.
^ permalink raw reply
* [PATCHv2 0/5] Support for Marvell switches with integrated CPUs
From: Marcin Wojtas @ 2017-01-05 14:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170105130945.GA18033@lunn.ch>
Hi Andrew,
2017-01-05 14:09 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
>> I'd love to see a switchdev driver but it's a huge task (and no I'm not
>> committing to writing it). As it stands Marvell ship a switch SDK
>> largely executes in userspace with a small kernel module providing some
>> linkage to the underlying hardware.
>
> Is there any similarity to the mv88e6xxx family?
Prestera switches (they are sold as standalone devices and with
integrated CPU's, like ones submitted) are as far from mv88e6xxx as
possible. There are various mix of 1/2.5/10/40G ports, depending on
model.
>
> If it was similar registers, just a different access mechanising, we
> could probably extend the mv88e6xxx to support MMIO as well as MDIO.
>
The difference is huge, nothing existing in the mainline can fit. The
driver, that exposes resources to the userspace SDK (called CPSS, it's
huge and complex piece of code) is existing in Marvell internal
branches (kernel v4.4 is the latest one), but I doubt such solution
(despite it's really small) is upstreamable. I believe it can be
shipped to the customers along with the SDK as a kernel module. Having
the CPU's support in the mainline is IMO sufficient.
Best regards,
Marcin
^ permalink raw reply
* [PATCH v1 0/3] soc: rockchip: power-domain: support RK3328 SoC
From: Heiko Stuebner @ 2017-01-05 14:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482464872-12954-1-git-send-email-zhangqing@rock-chips.com>
Am Freitag, 23. Dezember 2016, 11:47:49 CET schrieb Elaine Zhang:
> Elaine Zhang (3):
> dt/bindings: power: add RK3328 SoCs header for idle-request
> dt-bindings: add binding for rk3328 power domains
> soc: rockchip: power-domain: Modify power domain driver for rk3328
>
> .../bindings/soc/rockchip/power_domain.txt | 3 ++
> drivers/soc/rockchip/pm_domains.c | 63
> +++++++++++++++++++--- include/dt-bindings/power/rk3328-power.h |
> 18 +++++++
> 3 files changed, 78 insertions(+), 6 deletions(-)
> create mode 100644 include/dt-bindings/power/rk3328-power.h
I've split patch 3 into two parts (hiword support and rk3328 addition) and
applied all for 4.11
Thanks
Heiko
^ permalink raw reply
* [PATCHv2 0/5] Support for Marvell switches with integrated CPUs
From: Marcin Wojtas @ 2017-01-05 14:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170105033641.6212-1-chris.packham@alliedtelesis.co.nz>
Hi Chris,
Thanks a lot for your work and v2. Can you please add changelog
between patchset versions in your cover letter?
Best regards,
Marcin
2017-01-05 4:36 GMT+01:00 Chris Packham <chris.packham@alliedtelesis.co.nz>:
> The 98DX3236, 98DX3336 and 98DX4251 are a set of switch ASICs with
> integrated CPUs. They CPU block is common within these product lines and
> (as far as I can tell/have been told) is based on the Armada XP. There
> are a few differences due to the fact they have to squeeze the CPU into
> the same package as the switch.
>
> Chris Packham (4):
> clk: mvebu: support for 98DX3236 SoC
> arm: mvebu: support for SMP on 98DX3336 SoC
> arm: mvebu: Add device tree for 98DX3236 SoCs
> arm: mvebu: Add device tree for db-dxbc2 and db-xc3-24g4xg boards
>
> Kalyan Kinthada (1):
> pinctrl: mvebu: pinctrl driver for 98DX3236 SoC
>
> Documentation/devicetree/bindings/arm/cpus.txt | 1 +
> .../bindings/arm/marvell/98dx3236-resume-ctrl.txt | 18 ++
> .../devicetree/bindings/arm/marvell/98dx3236.txt | 23 ++
> .../devicetree/bindings/clock/mvebu-cpu-clock.txt | 1 +
> .../pinctrl/marvell,armada-98dx3236-pinctrl.txt | 46 ++++
> arch/arm/boot/dts/armada-xp-98dx3236.dtsi | 247 +++++++++++++++++++++
> arch/arm/boot/dts/armada-xp-98dx3336.dtsi | 78 +++++++
> arch/arm/boot/dts/armada-xp-98dx4251.dtsi | 92 ++++++++
> arch/arm/boot/dts/db-dxbc2.dts | 159 +++++++++++++
> arch/arm/boot/dts/db-xc3-24g4xg.dts | 155 +++++++++++++
> arch/arm/mach-mvebu/Makefile | 1 +
> arch/arm/mach-mvebu/common.h | 1 +
> arch/arm/mach-mvebu/platsmp.c | 43 ++++
> arch/arm/mach-mvebu/pmsu-98dx3236.c | 69 ++++++
> drivers/clk/mvebu/Makefile | 2 +-
> drivers/clk/mvebu/armada-xp.c | 42 ++++
> drivers/clk/mvebu/clk-cpu.c | 33 ++-
> drivers/clk/mvebu/mv98dx3236-corediv.c | 207 +++++++++++++++++
> drivers/pinctrl/mvebu/pinctrl-armada-xp.c | 155 +++++++++++++
> 19 files changed, 1369 insertions(+), 4 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/marvell/98dx3236-resume-ctrl.txt
> create mode 100644 Documentation/devicetree/bindings/arm/marvell/98dx3236.txt
> create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-98dx3236-pinctrl.txt
> create mode 100644 arch/arm/boot/dts/armada-xp-98dx3236.dtsi
> create mode 100644 arch/arm/boot/dts/armada-xp-98dx3336.dtsi
> create mode 100644 arch/arm/boot/dts/armada-xp-98dx4251.dtsi
> create mode 100644 arch/arm/boot/dts/db-dxbc2.dts
> create mode 100644 arch/arm/boot/dts/db-xc3-24g4xg.dts
> create mode 100644 arch/arm/mach-mvebu/pmsu-98dx3236.c
> create mode 100644 drivers/clk/mvebu/mv98dx3236-corediv.c
>
> --
> 2.11.0.24.ge6920cf
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RESEND 2/2] arm64: dts: Add dts files for Hisilicon Hi3660 SoC
From: Andy Gross @ 2017-01-05 14:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482744972-56622-2-git-send-email-puck.chen@hisilicon.com>
On Mon, Dec 26, 2016 at 05:36:12PM +0800, Chen Feng wrote:
> Add initial dtsi file to support Hisilicon Hi3660 SoC with
> support of Octal core CPUs in two clusters(4 * A53 & 4 * A73).
>
> Also add dts file to support HiKey960 development board which
> based on Hi3660 SoC.
> The output console is earlycon "earlycon=pl011,0xfdf05000".
> And the con_init uart5 with a fixed clock, which already
> configured at bootloader.
>
> When clock is available, the uart5 will be modified.
>
> Tested on HiKey960 Board.
>
> Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
> ---
> arch/arm64/boot/dts/hisilicon/Makefile | 1 +
> arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 34 +++++
> arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 156 ++++++++++++++++++++++
> 3 files changed, 191 insertions(+)
> create mode 100644 arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
> create mode 100644 arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>
> diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
> index d5f43a0..b633b5d 100644
> --- a/arch/arm64/boot/dts/hisilicon/Makefile
> +++ b/arch/arm64/boot/dts/hisilicon/Makefile
> @@ -1,4 +1,5 @@
> dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
> +dtb-$(CONFIG_ARCH_HISI) += hi3660-hikey960.dtb
> dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb
> dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb
>
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
> new file mode 100644
> index 0000000..3d7aead
> --- /dev/null
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
> @@ -0,0 +1,34 @@
> +/*
> + * dts file for Hisilicon HiKey960 Development Board
> + *
> + * Copyright (C) 2016, Hisilicon Ltd.
> + *
> + */
> +
> +/dts-v1/;
> +
> +#include "hi3660.dtsi"
> +
> +/ {
> + model = "HiKey960";
> + compatible = "hisilicon,hi3660";
> +
> + aliases {
> + serial5 = &uart5; /* console UART */
> + };
> +
> + chosen {
> + stdout-path = "serial5:115200n8";
> + };
> +
> + memory at 0 {
> + device_type = "memory";
> + reg = <0x0 0x00400000 0x0 0xBFE00000>;
Use lower case letters for hex numbers. 0xbfe00000.
> + };
> +
> + soc {
> + uart5: uart at fdf05000 {
> + status = "ok";
> + };
> + };
> +};
<snip>
Regards,
Andy
^ permalink raw reply
* [PATCH 4/4] watchdog: tangox: Use watchdog core to install restart handler
From: Guenter Roeck @ 2017-01-05 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <df7b5570-a44d-0c25-fedd-03a0891fdff3@sigmadesigns.com>
On 01/05/2017 01:42 AM, Marc Gonzalez wrote:
> [ Adding Mans ]
>
> Guenter, patch c7ef68c32265 states "Fixes: a3e376d26ace".
> Is that true? I mean, they seem quite orthogonal; then again I know
> nothing of this framework.
>
max_hw_heartbeat_ms must be set for WDOG_HW_RUNNING to work.
Guenter
> Regards.
>
> On 04/01/2017 22:28, Guenter Roeck wrote:
>> Use the infrastructure provided by the watchdog core to install
>> the restart handler.
>>
>> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
>> ---
>> drivers/watchdog/tangox_wdt.c | 32 +++++++++++---------------------
>> 1 file changed, 11 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/watchdog/tangox_wdt.c b/drivers/watchdog/tangox_wdt.c
>> index 202c4b9cc921..49e6e805db7c 100644
>> --- a/drivers/watchdog/tangox_wdt.c
>> +++ b/drivers/watchdog/tangox_wdt.c
>> @@ -15,9 +15,7 @@
>> #include <linux/kernel.h>
>> #include <linux/module.h>
>> #include <linux/moduleparam.h>
>> -#include <linux/notifier.h>
>> #include <linux/platform_device.h>
>> -#include <linux/reboot.h>
>> #include <linux/watchdog.h>
>>
>> #define DEFAULT_TIMEOUT 30
>> @@ -47,7 +45,6 @@ struct tangox_wdt_device {
>> void __iomem *base;
>> unsigned long clk_rate;
>> struct clk *clk;
>> - struct notifier_block restart;
>> };
>>
>> static int tangox_wdt_set_timeout(struct watchdog_device *wdt,
>> @@ -96,24 +93,24 @@ static const struct watchdog_info tangox_wdt_info = {
>> .identity = "tangox watchdog",
>> };
>>
>> +static int tangox_wdt_restart(struct watchdog_device *wdt,
>> + unsigned long action, void *data)
>> +{
>> + struct tangox_wdt_device *dev = watchdog_get_drvdata(wdt);
>> +
>> + writel(1, dev->base + WD_COUNTER);
>> +
>> + return 0;
>> +}
>> +
>> static const struct watchdog_ops tangox_wdt_ops = {
>> .start = tangox_wdt_start,
>> .stop = tangox_wdt_stop,
>> .set_timeout = tangox_wdt_set_timeout,
>> .get_timeleft = tangox_wdt_get_timeleft,
>> + .restart = tangox_wdt_restart,
>> };
>>
>> -static int tangox_wdt_restart(struct notifier_block *nb, unsigned long action,
>> - void *data)
>> -{
>> - struct tangox_wdt_device *dev =
>> - container_of(nb, struct tangox_wdt_device, restart);
>> -
>> - writel(1, dev->base + WD_COUNTER);
>> -
>> - return NOTIFY_DONE;
>> -}
>> -
>> static int tangox_wdt_probe(struct platform_device *pdev)
>> {
>> struct tangox_wdt_device *dev;
>> @@ -180,12 +177,6 @@ static int tangox_wdt_probe(struct platform_device *pdev)
>>
>> platform_set_drvdata(pdev, dev);
>>
>> - dev->restart.notifier_call = tangox_wdt_restart;
>> - dev->restart.priority = 128;
>> - err = register_restart_handler(&dev->restart);
>> - if (err)
>> - dev_warn(&pdev->dev, "failed to register restart handler\n");
>> -
>> dev_info(&pdev->dev, "SMP86xx/SMP87xx watchdog registered\n");
>>
>> return 0;
>> @@ -202,7 +193,6 @@ static int tangox_wdt_remove(struct platform_device *pdev)
>> tangox_wdt_stop(&dev->wdt);
>> clk_disable_unprepare(dev->clk);
>>
>> - unregister_restart_handler(&dev->restart);
>> watchdog_unregister_device(&dev->wdt);
>>
>> return 0;
>>
>
^ permalink raw reply
* [PATCH net-next v4 0/2] Add support for the ethernet switch on the ESPRESSObin
From: Gregory CLEMENT @ 2017-01-05 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161221125734.1034-1-romain.perier@free-electrons.com>
Hi David,
On mer., d?c. 21 2016, Romain Perier <romain.perier@free-electrons.com> wrote:
> This set of patches adds support for the Marvell ethernet switch 88E6341.
> It also add the devicetree definition of this switch to the DT board.
The forth version of this series had been sent while the net-next merge
window was closed so I think it was missed.
Do you want that we send it again on the netdev mainling list?
Thanks,
Gregory
>
> Romain Perier (2):
> net: dsa: mv88e6xxx: Don't forbid MDIO I/Os for PHY addr >=
> num_of_ports
> net: dsa: mv88e6xxx: Add support for ethernet switch 88E6341/88E6141
>
> drivers/net/dsa/mv88e6xxx/chip.c | 48 ++++++++++++++++++++++++++++++-----
> drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 4 ++-
> 2 files changed, 45 insertions(+), 7 deletions(-)
>
> --
>
> Note: As requested by Gregory, I have removed the patch for the DT (already merged).
>
> 2.9.3
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [GIT PULL] efi: Pass secure boot mode to kernel
From: David Howells @ 2017-01-05 14:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161208115652.GE5462@codeblueprint.co.uk>
Matt Fleming <matt@codeblueprint.co.uk> wrote:
> > Is it too late to request this for the upcoming merge window?
>
> For something as non-trivial as this, yes, it's too late. We generally
> close the EFI tree window for new features around -rc5 time.
Can I request that it be pulled now? Are you going to update efi/core?
Thanks,
David
^ permalink raw reply
* [PATCH v7 0/8] Add PWM and IIO timer drivers for STM32
From: Lee Jones @ 2017-01-05 14:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483608344-9012-1-git-send-email-benjamin.gaignard@st.com>
On Thu, 05 Jan 2017, Benjamin Gaignard wrote:
> version 7:
> - rebase on v4.10-rc2
> - remove iio_device code from driver and keep only the trigger part
>
> version 6:
> - rename stm32-gptimer in stm32-timers.
> - change "st,stm32-gptimer" compatible to "st,stm32-timers".
> - modify "st,breakinput" parameter in pwm part.
> - split DT patch in 2
>
> version 5:
> - fix comments done on version 4
> - rebased on kernel 4.9-rc8
> - change nodes names and re-order then by addresses
>
> version 4:
> - fix comments done on version 3
> - don't use interrupts anymore in IIO timer
> - detect hardware capabilities at probe time to simplify binding
>
> version 3:
> - no change on mfd and pwm divers patches
> - add cross reference between bindings
> - change compatible to "st,stm32-timer-trigger"
> - fix attributes access rights
> - use string instead of int for master_mode and slave_mode
> - document device attributes in sysfs-bus-iio-timer-stm32
> - update DT with the new compatible
>
> version 2:
> - keep only one compatible per driver
> - use DT parameters to describe hardware block configuration:
> - pwm channels, complementary output, counter size, break input
> - triggers accepted and create by IIO timers
> - change DT to limite use of reference to the node
> - interrupt is now in IIO timer driver
> - rename stm32-mfd-timer to stm32-timers (for general purpose timer)
>
> The following patches enable PWM and IIO Timer features for STM32 platforms.
>
> Those two features are mixed into the registers of the same hardware block
> (named general purpose timer) which lead to introduce a multifunctions driver
> on the top of them to be able to share the registers.
>
> In STM32f4 14 instances of timer hardware block exist, even if they all have
> the same register mapping they could have a different number of pwm channels
> and/or different triggers capabilities. We use various parameters in DT to
> describe the differences between hardware blocks
>
> The MFD (stm32-timers.c) takes care of clock and register mapping
> by using regmap. stm32_timers structure is provided to its sub-node to
> share those information.
>
> PWM driver is implemented into pwm-stm32.c. Depending of the instance we may
> have up to 4 channels, sometime with complementary outputs or 32 bits counter
> instead of 16 bits. Some hardware blocks may also have a break input function
> which allows to stop pwm depending of a level, defined in devicetree, on an
> external pin.
>
> IIO timer driver (stm32-timer-trigger.c and stm32-timer-trigger.h) define a list
> of hardware triggers usable by hardware blocks like ADC, DAC or other timers.
>
> The matrix of possible connections between blocks is quite complex so we use
> trigger names and is_stm32_iio_timer_trigger() function to be sure that
> triggers are valid and configure the IPs.
>
> At run time IIO timer hardware blocks can configure (through "master_mode"
> IIO device attribute) which internal signal (counter enable, reset,
> comparison block, etc...) is used to generate the trigger.
>
> Benjamin Gaignard (8):
> MFD: add bindings for STM32 Timers driver
> MFD: add STM32 Timers driver
> PWM: add pwm-stm32 DT bindings
> PWM: add PWM driver for STM32 plaftorm
> IIO: add bindings for STM32 timer trigger driver
> IIO: add STM32 timer trigger driver
> ARM: dts: stm32: add Timers driver for stm32f429 MCU
> ARM: dts: stm32: Enable pwm1 and pwm3 for stm32f469-disco
Any reason why you've dropped all your Acks?
I don't really want to review it again if little is different.
How much MFD related code has changed since the last review?
> .../ABI/testing/sysfs-bus-iio-timer-stm32 | 29 ++
> .../bindings/iio/timer/stm32-timer-trigger.txt | 23 ++
> .../devicetree/bindings/mfd/stm32-timers.txt | 46 +++
> .../devicetree/bindings/pwm/pwm-stm32.txt | 33 ++
> arch/arm/boot/dts/stm32f429.dtsi | 275 +++++++++++++
> arch/arm/boot/dts/stm32f469-disco.dts | 28 ++
> drivers/iio/Kconfig | 1 -
> drivers/iio/trigger/Kconfig | 10 +
> drivers/iio/trigger/Makefile | 1 +
> drivers/iio/trigger/stm32-timer-trigger.c | 340 ++++++++++++++++
> drivers/mfd/Kconfig | 11 +
> drivers/mfd/Makefile | 2 +
> drivers/mfd/stm32-timers.c | 80 ++++
> drivers/pwm/Kconfig | 9 +
> drivers/pwm/Makefile | 1 +
> drivers/pwm/pwm-stm32.c | 434 +++++++++++++++++++++
> include/linux/iio/timer/stm32-timer-trigger.h | 62 +++
> include/linux/mfd/stm32-timers.h | 71 ++++
> 18 files changed, 1455 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
> create mode 100644 Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt
> create mode 100644 Documentation/devicetree/bindings/mfd/stm32-timers.txt
> create mode 100644 Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> create mode 100644 drivers/iio/trigger/stm32-timer-trigger.c
> create mode 100644 drivers/mfd/stm32-timers.c
> create mode 100644 drivers/pwm/pwm-stm32.c
> create mode 100644 include/linux/iio/timer/stm32-timer-trigger.h
> create mode 100644 include/linux/mfd/stm32-timers.h
>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH 0/6] ARM: dts: phyBOARD-WEGA-AM335x updates
From: Teresa Remmet @ 2017-01-05 14:50 UTC (permalink / raw)
To: linux-arm-kernel
Set of small patches to update the device tree of the
phyCORE-AM335x SOM and phyBOARD-WEGA-AM335x.
Teresa Remmet (6):
ARM: dts: am335x-phycore-som: Update NAND partition table
ARM: dts: am335x-phycore-som: Update compatible string for spi nor
ARM: dts: am335x-phycore-som: Add i2c temp sensor
ARM: dts: am335x-wega: Set USB0 mode to otg
ARM: dts: am335x-phycore-som: Update ethernet phy node
ARM: dts: am335x-wega: Update ethernet phy node
arch/arm/boot/dts/am335x-phycore-som.dtsi | 30 +++++++++++++++++++-----------
arch/arm/boot/dts/am335x-wega.dtsi | 9 +++++++--
2 files changed, 26 insertions(+), 13 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 1/6] ARM: dts: am335x-phycore-som: Update NAND partition table
From: Teresa Remmet @ 2017-01-05 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483627851-17996-1-git-send-email-t.remmet@phytec.de>
To improve NAND safety we updated the partition layout.
Added barebox backup partition and removed kernel and oftree
partition. They are kept in ubi now.
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
arch/arm/boot/dts/am335x-phycore-som.dtsi | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/arch/arm/boot/dts/am335x-phycore-som.dtsi b/arch/arm/boot/dts/am335x-phycore-som.dtsi
index 75e24ad..ef3fe5a 100644
--- a/arch/arm/boot/dts/am335x-phycore-som.dtsi
+++ b/arch/arm/boot/dts/am335x-phycore-som.dtsi
@@ -222,21 +222,19 @@
label = "barebox";
reg = <0x80000 0x80000>;
};
+
partition at 5 {
- label = "bareboxenv";
- reg = <0x100000 0x40000>;
+ label = "barebox_backup";
+ reg = <0x100000 0x80000>;
};
+
partition at 6 {
- label = "oftree";
- reg = <0x140000 0x40000>;
+ label = "bareboxenv";
+ reg = <0x180000 0x40000>;
};
partition at 7 {
- label = "kernel";
- reg = <0x180000 0x800000>;
- };
- partition at 8 {
label = "root";
- reg = <0x980000 0x0>;
+ reg = <0x1C0000 0x0>;
};
};
};
--
1.9.1
^ permalink raw reply related
* [PATCH 2/6] ARM: dts: am335x-phycore-som: Update compatible string for spi nor
From: Teresa Remmet @ 2017-01-05 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483627851-17996-1-git-send-email-t.remmet@phytec.de>
As we may have different SPI NOR flashes with 8MB populated on
phyCORE-AM335x SOM, set the "jedec,spi-nor" SPI Flash compatible string.
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
arch/arm/boot/dts/am335x-phycore-som.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/am335x-phycore-som.dtsi b/arch/arm/boot/dts/am335x-phycore-som.dtsi
index ef3fe5a..8060ce5 100644
--- a/arch/arm/boot/dts/am335x-phycore-som.dtsi
+++ b/arch/arm/boot/dts/am335x-phycore-som.dtsi
@@ -339,7 +339,7 @@
status = "okay";
serial_flash: m25p80 at 0 {
- compatible = "m25p80";
+ compatible = "jedec,spi-nor";
spi-max-frequency = <48000000>;
reg = <0x0>;
m25p,fast-read;
--
1.9.1
^ permalink raw reply related
* [PATCH 3/6] ARM: dts: am335x-phycore-som: Add i2c temp sensor
From: Teresa Remmet @ 2017-01-05 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483627851-17996-1-git-send-email-t.remmet@phytec.de>
Include the i2c temperature sensor which is optionaly mounted
on the phyCORE-AM335x-R2 module.
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
arch/arm/boot/dts/am335x-phycore-som.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/am335x-phycore-som.dtsi b/arch/arm/boot/dts/am335x-phycore-som.dtsi
index 8060ce5..08d1134 100644
--- a/arch/arm/boot/dts/am335x-phycore-som.dtsi
+++ b/arch/arm/boot/dts/am335x-phycore-som.dtsi
@@ -120,6 +120,12 @@
reg = <0x2d>;
};
+ i2c_tmp102: temp at 4b {
+ compatible = "ti,tmp102";
+ reg = <0x4b>;
+ status = "disabled";
+ };
+
i2c_eeprom: eeprom at 52 {
compatible = "atmel,24c32";
pagesize = <32>;
--
1.9.1
^ permalink raw reply related
* [PATCH 4/6] ARM: dts: am335x-wega: Set USB0 mode to otg
From: Teresa Remmet @ 2017-01-05 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483627851-17996-1-git-send-email-t.remmet@phytec.de>
Set USB0 to otg mode (default) and not fix to peripheral.
As it can be used in host mode also.
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
arch/arm/boot/dts/am335x-wega.dtsi | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm/boot/dts/am335x-wega.dtsi b/arch/arm/boot/dts/am335x-wega.dtsi
index 02c6736..e97fd6d 100644
--- a/arch/arm/boot/dts/am335x-wega.dtsi
+++ b/arch/arm/boot/dts/am335x-wega.dtsi
@@ -206,7 +206,6 @@
};
&usb0 {
- dr_mode = "peripheral";
status = "okay";
};
--
1.9.1
^ permalink raw reply related
* [PATCH 5/6] ARM: dts: am335x-phycore-som: Update ethernet phy node
From: Teresa Remmet @ 2017-01-05 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483627851-17996-1-git-send-email-t.remmet@phytec.de>
Update ethernet phy0 node to use phy-handle now.
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
arch/arm/boot/dts/am335x-phycore-som.dtsi | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/am335x-phycore-som.dtsi b/arch/arm/boot/dts/am335x-phycore-som.dtsi
index 08d1134..de91275 100644
--- a/arch/arm/boot/dts/am335x-phycore-som.dtsi
+++ b/arch/arm/boot/dts/am335x-phycore-som.dtsi
@@ -78,7 +78,7 @@
};
&cpsw_emac0 {
- phy_id = <&davinci_mdio>, <0>;
+ phy-handle = <&phy0>;
phy-mode = "rmii";
dual_emac_res_vlan = <1>;
};
@@ -87,6 +87,10 @@
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
status = "okay";
+
+ phy0: ethernet-phy at 0 {
+ reg = <0>;
+ };
};
&mac {
--
1.9.1
^ permalink raw reply related
* [PATCH 6/6] ARM: dts: am335x-wega: Update ethernet phy node
From: Teresa Remmet @ 2017-01-05 14:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483627851-17996-1-git-send-email-t.remmet@phytec.de>
Update ethernet phy1 node to use phy-handle now.
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
arch/arm/boot/dts/am335x-wega.dtsi | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/am335x-wega.dtsi b/arch/arm/boot/dts/am335x-wega.dtsi
index e97fd6d..8ce5417 100644
--- a/arch/arm/boot/dts/am335x-wega.dtsi
+++ b/arch/arm/boot/dts/am335x-wega.dtsi
@@ -119,11 +119,17 @@
};
&cpsw_emac1 {
- phy_id = <&davinci_mdio>, <1>;
+ phy-handle = <&phy1>;
phy-mode = "mii";
dual_emac_res_vlan = <2>;
};
+&davinci_mdio {
+ phy1: ethernet-phy at 1 {
+ reg = <1>;
+ };
+};
+
&mac {
slaves = <2>;
pinctrl-names = "default";
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox