* S805 RTC driver @ 2016-06-23 20:21 Ben Dooks 2016-06-23 20:21 ` [RFC 1/4] rtc: support for amlogic meson rtc Ben Dooks ` (5 more replies) 0 siblings, 6 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-23 20:21 UTC (permalink / raw) To: linus-amlogic This has been sitting in my tree for a while, so I thought it would be a good idea to try and get it moving along and possibly submittied soon. I've not been able to fully test this as I don't have an S805 MMC driver to allow me to boot to a userland on my ODroid-C1 board. ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC 1/4] rtc: support for amlogic meson rtc 2016-06-23 20:21 S805 RTC driver Ben Dooks @ 2016-06-23 20:21 ` Ben Dooks 2016-06-24 14:25 ` Neil Armstrong 2016-06-24 14:26 ` Neil Armstrong 2016-06-23 20:21 ` [RFC 2/4] odroidc1: enable rtc Ben Dooks ` (4 subsequent siblings) 5 siblings, 2 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-23 20:21 UTC (permalink / raw) To: linus-amlogic Add support for the AMLogic meson8b/meson6 RTC block. Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> --- drivers/rtc/Kconfig | 10 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-meson.c | 339 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+) create mode 100644 drivers/rtc/rtc-meson.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9f8b59d..a90634f5 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1222,6 +1222,16 @@ config RTC_DRV_IMXDI This driver can also be built as a module, if so, the module will be called "rtc-imxdi". +config RTC_DRV_MESON + tristate "AMLogic Meson Real Time Clock" + depends on ARCH_MESON + help + Support for AMLogic Meson RTC block + + This driver can also be built as a module, if so, the module + will be called "rtc-meson". + + config RTC_DRV_OMAP tristate "TI OMAP Real Time Clock" depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 024da27..1d1426e 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o +obj-$(CONFIG_RTC_DRV_MESON) += rtc-meson.o obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c new file mode 100644 index 0000000..2480551 --- /dev/null +++ b/drivers/rtc/rtc-meson.c @@ -0,0 +1,339 @@ + +/* drivers/rtc/rtc-meson.c + * + * Copyright (c) 2015 Codethink Ltd + * Ben Dooks <ben.dooks@codethink.co.uk> + * Based on origin by Carlo Caione <carlo@endlessm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/reset.h> +#include <linux/rtc.h> +#include <linux/io.h> +#include <linux/of.h> + +/* registers accessed from cpu bus */ +#define RTC_REG(x) ((x) * 4) /* rtc registers 0-4 */ + +#define LINE_SDI (1 << 2) +#define LINE_SEN (1 << 1) +#define LINE_SCLK (1 << 0) + +#define RTCREG0_START_SER BIT(17) +#define RTCREG0_WAIT_SER BIT(22) + +#define RTCREG1_READY BIT(1) + +/* rtc registers accessed via rtc-serial inteface */ +#define RTC_COUNTER (0) +#define RTC_SEC_ADJ (2) + +#define RTC_ADDR_BITS (3) /* number of address bits to send */ +#define RTC_DATA_BITS (32) /* number of data bits to tx/rx */ + +#define MESON_STATIC_BIAS_CUR (0x5 << 1) +#define MESON_STATIC_VOLTAGE (0x3 << 11) + +struct meson_rtc { + struct rtc_device *rtc; /* rtc device we created */ + struct device *dev; /* device we bound from */ + struct reset_control *reset; /* reset source */ + struct mutex lock; /* rtc lock */ + void __iomem *regs; /* rtc register access */ +}; + +static void meson_rtc_setline(struct meson_rtc *rtc, unsigned bit, unsigned to) +{ + u32 reg0; + + reg0 = readl(rtc->regs + RTC_REG(0)); + if (to) + reg0 |= bit; + else + reg0 &= ~bit; + writel(reg0, rtc->regs + RTC_REG(0)); + +} + +static void meson_rtc_sclk_pulse(struct meson_rtc *rtc) +{ + udelay(5); + meson_rtc_setline(rtc, LINE_SCLK, 0); + udelay(5); + meson_rtc_setline(rtc, LINE_SCLK, 1); +} + +static void meson_rtc_send_bit(struct meson_rtc *rtc, unsigned bit) +{ + meson_rtc_setline(rtc, LINE_SDI, bit ? 1 : 0); + meson_rtc_sclk_pulse(rtc); +} + +static void meson_rtc_send_bits(struct meson_rtc *rtc, u32 data, unsigned nr) +{ + u32 bit = 1 << (nr - 1); + + while (bit) { + meson_rtc_send_bit(rtc, data & bit); + bit >>= 1; + } +} + +static void meson_rtc_set_dir(struct meson_rtc *rtc, u32 mode) +{ + meson_rtc_setline(rtc, LINE_SDI, 0); + meson_rtc_send_bit(rtc, mode); + meson_rtc_setline(rtc, LINE_SDI, 0); +} + +static u32 meson_rtc_read_sdo(struct meson_rtc *rtc) +{ + return readl(rtc->regs + RTC_REG(1)) & (1 << 0); +} + +static u32 meson_rtc_get_data(struct meson_rtc *rtc) +{ + u32 val = 0; + int bit; + + for (bit = 0; bit < RTC_DATA_BITS; bit++) { + meson_rtc_sclk_pulse(rtc); + val <<= 1; + val |= meson_rtc_read_sdo(rtc); + } + + return val; +} + +static int meson_rtc_wait_bus(struct meson_rtc *rtc, unsigned timeout_ms) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + u32 val; + + val = readl(rtc->regs + RTC_REG(0)); + val &= ~(LINE_SDI | LINE_SEN | LINE_SCLK); + writel(val, rtc->regs + RTC_REG(0)); + + while (time_before(jiffies, timeout)) { + val = readl(rtc->regs + RTC_REG(1)); + if (val & RTCREG1_READY) + return 1; + + dev_info(rtc->dev, "%s: reg1=%08x\n", __func__, val); + msleep(10); + } + + return 0; +} + +static int meson_rtc_get_bus(struct meson_rtc *rtc) +{ + int ret, retries = 3; + + while (retries) { + if (meson_rtc_wait_bus(rtc, 300)) + return 0; + + dev_warn(rtc->dev, "failed to get bus, re-setting\n"); + + retries--; + ret = reset_control_reset(rtc->reset); + if (ret) + return ret; + } + + dev_err(rtc->dev, "%s: bus is not ready\n", __func__); + return -ETIMEDOUT; +} + +static int meson_rtc_read(struct meson_rtc *rtc, unsigned int reg, u32 *data) +{ + int ret; + + ret = meson_rtc_get_bus(rtc); + if (ret) + return ret; + + meson_rtc_setline(rtc, LINE_SEN, 1); + meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS); + meson_rtc_setline(rtc, LINE_SEN, 0); + meson_rtc_set_dir(rtc, 0); + *data = meson_rtc_get_data(rtc); + + return 0; +} + +static int meson_rtc_write(struct meson_rtc *rtc, unsigned int reg, u32 data) +{ + int ret; + + ret = meson_rtc_get_bus(rtc); + if (ret) + return ret; + + meson_rtc_setline(rtc, LINE_SEN, 1); + meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS); + meson_rtc_setline(rtc, LINE_SEN, 0); + meson_rtc_set_dir(rtc, 1); + meson_rtc_send_bits(rtc, data, RTC_DATA_BITS); + + return 0; +} + +static int meson_rtc_gettime(struct device *dev, struct rtc_time *tm) +{ + struct meson_rtc *rtc = dev_get_drvdata(dev); + int ret; + u32 time; + + mutex_lock(&rtc->lock); + + ret = meson_rtc_read(rtc, RTC_COUNTER, &time); + if (ret) + return ret; + + rtc_time_to_tm(time, tm); + dev_info(dev, "read time %lu\n", (unsigned long)time); + + mutex_unlock(&rtc->lock); + return 0; +} + +static int meson_rtc_settime(struct device *dev, struct rtc_time *tm) +{ + struct meson_rtc *rtc = dev_get_drvdata(dev); + unsigned long time; + int ret; + + mutex_lock(&rtc->lock); + + rtc_tm_to_time(tm, &time); + ret = meson_rtc_write(rtc, RTC_COUNTER, time); + + mutex_unlock(&rtc->lock); + return ret; +} + +static const struct rtc_class_ops meson_rtc_ops = { + .read_time = meson_rtc_gettime, + .set_time = meson_rtc_settime, +}; + +static int meson_rtc_wait_serialiser(struct meson_rtc *rtc) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(100); + + while (time_before(jiffies, timeout)) { + if (!(readl(rtc->regs + RTC_REG(0)) & RTCREG0_WAIT_SER)) + return 0; + msleep(10); + } + + return -ETIMEDOUT; +} + +static int meson_rtc_write_static(struct meson_rtc *rtc, u32 data) +{ + u32 tmp; + + mutex_lock(&rtc->lock); + + writel(data >> 8, rtc->regs + RTC_REG(4)); + + tmp = readl(rtc->regs + RTC_REG(0)); + tmp &= ~(0xff << 24); + tmp |= (data << 24); + tmp |= RTCREG0_START_SER; + + writel(tmp, rtc->regs + RTC_REG(0)); + + if (meson_rtc_wait_serialiser(rtc)) + return -ETIMEDOUT; + + dev_info(rtc->dev, "rtc_reg0 = %08x\n", readl(rtc->regs + RTC_REG(0))); + mutex_unlock(&rtc->lock); + + return 0; +} + +static int meson_rtc_probe(struct platform_device *pdev) +{ + struct meson_rtc *rtc; + struct device *dev = &pdev->dev; + struct resource *res; + u32 tm; + int ret; + + rtc = devm_kzalloc(dev, sizeof(struct meson_rtc), GFP_KERNEL); + if (!rtc) { + dev_err(dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rtc->regs = devm_ioremap_resource(dev, res); + rtc->dev = dev; + + if (IS_ERR(rtc->regs)) + return PTR_ERR(rtc->regs); + + mutex_init(&rtc->lock); + platform_set_drvdata(pdev, rtc); + + ret = meson_rtc_write_static(rtc, + MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE); + if (ret) { + dev_err(dev, "failed to set static values\n"); + return ret; + } + + rtc->reset = devm_reset_control_get(dev, NULL); + if (IS_ERR(rtc->reset)) + dev_warn(dev, "no reset available, rtc may not work\n"); + + /* check if we can read RTC counter, if not then the RTC is probably + * not functional. If it isn't probably best to not bind */ + ret = meson_rtc_read(rtc, RTC_COUNTER, &tm); + if (ret) { + dev_err(dev, "cannot read RTC counter, RTC not functional\n"); + return ret; + } + + rtc->rtc = devm_rtc_device_register(dev, "meson", + &meson_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc->rtc)) { + dev_err(dev, "cannot attach rtc\n"); + return PTR_ERR(rtc->rtc); + } + + dev_info(dev, "device registered\n"); + return 0; +} + +static const struct of_device_id meson_rtc_dt_match[] = { + { .compatible = "amlogic,meson6-rtc", }, + { .compatible = "amlogic,meson8-rtc", }, + { .compatible = "amlogic,meson8b-rtc", }, + { }, +}; +MODULE_DEVICE_TABLE(of, meson_rtc_dt_match); + +static struct platform_driver meson_rtc_driver = { + .probe = meson_rtc_probe, + .driver = { + .name = "meson-rtc", + .of_match_table = of_match_ptr(meson_rtc_dt_match), + }, +}; +module_platform_driver(meson_rtc_driver); + +MODULE_DESCRIPTION("AMLogic MESON RTC Driver"); +MODULE_AUTHOR("Ben Dooks <ben.doosk@codethink.co.uk>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:meson-rtc"); -- 2.8.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC 1/4] rtc: support for amlogic meson rtc 2016-06-23 20:21 ` [RFC 1/4] rtc: support for amlogic meson rtc Ben Dooks @ 2016-06-24 14:25 ` Neil Armstrong 2016-06-24 14:54 ` Ben Dooks 2016-06-24 14:26 ` Neil Armstrong 1 sibling, 1 reply; 12+ messages in thread From: Neil Armstrong @ 2016-06-24 14:25 UTC (permalink / raw) To: linus-amlogic Hi Ben, On 06/23/2016 10:21 PM, Ben Dooks wrote: > Add support for the AMLogic meson8b/meson6 RTC block. > > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> > --- [...] > + > +/* registers accessed from cpu bus */ > +#define RTC_REG(x) ((x) * 4) /* rtc registers 0-4 */ > + > +#define LINE_SDI (1 << 2) > +#define LINE_SEN (1 << 1) > +#define LINE_SCLK (1 << 0) > + > +#define RTCREG0_START_SER BIT(17) > +#define RTCREG0_WAIT_SER BIT(22) > + > +#define RTCREG1_READY BIT(1) > + > +/* rtc registers accessed via rtc-serial inteface */ > +#define RTC_COUNTER (0) > +#define RTC_SEC_ADJ (2) > + > +#define RTC_ADDR_BITS (3) /* number of address bits to send */ > +#define RTC_DATA_BITS (32) /* number of data bits to tx/rx */ > + > +#define MESON_STATIC_BIAS_CUR (0x5 << 1) > +#define MESON_STATIC_VOLTAGE (0x3 << 11) Cleanup indentation here. > + > +struct meson_rtc { > + struct rtc_device *rtc; /* rtc device we created */ > + struct device *dev; /* device we bound from */ > + struct reset_control *reset; /* reset source */ > + struct mutex lock; /* rtc lock */ > + void __iomem *regs; /* rtc register access */ > +}; > + > +static void meson_rtc_setline(struct meson_rtc *rtc, unsigned bit, unsigned to) > +{ > + u32 reg0; > + > + reg0 = readl(rtc->regs + RTC_REG(0)); > + if (to) > + reg0 |= bit; > + else > + reg0 &= ~bit; > + writel(reg0, rtc->regs + RTC_REG(0)); > + > +} > + > +static void meson_rtc_sclk_pulse(struct meson_rtc *rtc) > +{ > + udelay(5); > + meson_rtc_setline(rtc, LINE_SCLK, 0); > + udelay(5); > + meson_rtc_setline(rtc, LINE_SCLK, 1); > +} > + > +static void meson_rtc_send_bit(struct meson_rtc *rtc, unsigned bit) > +{ > + meson_rtc_setline(rtc, LINE_SDI, bit ? 1 : 0); You can use !!bit here also > + meson_rtc_sclk_pulse(rtc); > +} > + > +static void meson_rtc_send_bits(struct meson_rtc *rtc, u32 data, unsigned nr) > +{ > + u32 bit = 1 << (nr - 1); > + > + while (bit) { > + meson_rtc_send_bit(rtc, data & bit); > + bit >>= 1; > + } > +} > + > +static void meson_rtc_set_dir(struct meson_rtc *rtc, u32 mode) > +{ > + meson_rtc_setline(rtc, LINE_SDI, 0); > + meson_rtc_send_bit(rtc, mode); > + meson_rtc_setline(rtc, LINE_SDI, 0); > +} > + > +static u32 meson_rtc_read_sdo(struct meson_rtc *rtc) > +{ > + return readl(rtc->regs + RTC_REG(1)) & (1 << 0); Drop the << 0 here, or replace by BIT(0) > +} > + > +static u32 meson_rtc_get_data(struct meson_rtc *rtc) > +{ > + u32 val = 0; > + int bit; > + > + for (bit = 0; bit < RTC_DATA_BITS; bit++) { > + meson_rtc_sclk_pulse(rtc); > + val <<= 1; > + val |= meson_rtc_read_sdo(rtc); > + } > + > + return val; > +} > + > +static int meson_rtc_wait_bus(struct meson_rtc *rtc, unsigned timeout_ms) > +{ > + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); > + u32 val; > + > + val = readl(rtc->regs + RTC_REG(0)); > + val &= ~(LINE_SDI | LINE_SEN | LINE_SCLK); > + writel(val, rtc->regs + RTC_REG(0)); > + > + while (time_before(jiffies, timeout)) { > + val = readl(rtc->regs + RTC_REG(1)); > + if (val & RTCREG1_READY) > + return 1; > + > + dev_info(rtc->dev, "%s: reg1=%08x\n", __func__, val); > + msleep(10); > + } > + > + return 0; > +} > + > +static int meson_rtc_get_bus(struct meson_rtc *rtc) > +{ > + int ret, retries = 3; > + > + while (retries) { > + if (meson_rtc_wait_bus(rtc, 300)) > + return 0; Put the timeout time in a define 300 to be easily changed. > + > + dev_warn(rtc->dev, "failed to get bus, re-setting\n"); > + > + retries--; > + ret = reset_control_reset(rtc->reset); > + if (ret) > + return ret; > + } > + > + dev_err(rtc->dev, "%s: bus is not ready\n", __func__); > + return -ETIMEDOUT; > +} > + > +static int meson_rtc_read(struct meson_rtc *rtc, unsigned int reg, u32 *data) > +{ > + int ret; > + > + ret = meson_rtc_get_bus(rtc); > + if (ret) > + return ret; > + > + meson_rtc_setline(rtc, LINE_SEN, 1); > + meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS); > + meson_rtc_setline(rtc, LINE_SEN, 0); > + meson_rtc_set_dir(rtc, 0); > + *data = meson_rtc_get_data(rtc); > + > + return 0; > +} > + > +static int meson_rtc_write(struct meson_rtc *rtc, unsigned int reg, u32 data) > +{ > + int ret; > + > + ret = meson_rtc_get_bus(rtc); > + if (ret) > + return ret; > + > + meson_rtc_setline(rtc, LINE_SEN, 1); > + meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS); > + meson_rtc_setline(rtc, LINE_SEN, 0); > + meson_rtc_set_dir(rtc, 1); > + meson_rtc_send_bits(rtc, data, RTC_DATA_BITS); > + > + return 0; > +} > + > +static int meson_rtc_gettime(struct device *dev, struct rtc_time *tm) > +{ > + struct meson_rtc *rtc = dev_get_drvdata(dev); > + int ret; > + u32 time; > + > + mutex_lock(&rtc->lock); > + > + ret = meson_rtc_read(rtc, RTC_COUNTER, &time); > + if (ret) > + return ret; > + > + rtc_time_to_tm(time, tm); > + dev_info(dev, "read time %lu\n", (unsigned long)time); Replace by a dev_dbg here. > + > + mutex_unlock(&rtc->lock); > + return 0; > +} > + > +static int meson_rtc_settime(struct device *dev, struct rtc_time *tm) > +{ > + struct meson_rtc *rtc = dev_get_drvdata(dev); > + unsigned long time; > + int ret; > + > + mutex_lock(&rtc->lock); > + > + rtc_tm_to_time(tm, &time); > + ret = meson_rtc_write(rtc, RTC_COUNTER, time); > + > + mutex_unlock(&rtc->lock); > + return ret; > +} > + > +static const struct rtc_class_ops meson_rtc_ops = { > + .read_time = meson_rtc_gettime, > + .set_time = meson_rtc_settime, > +}; > + > +static int meson_rtc_wait_serialiser(struct meson_rtc *rtc) > +{ > + unsigned long timeout = jiffies + msecs_to_jiffies(100); > + > + while (time_before(jiffies, timeout)) { > + if (!(readl(rtc->regs + RTC_REG(0)) & RTCREG0_WAIT_SER)) > + return 0; > + msleep(10); > + } > + > + return -ETIMEDOUT; > +} > + > +static int meson_rtc_write_static(struct meson_rtc *rtc, u32 data) > +{ > + u32 tmp; > + > + mutex_lock(&rtc->lock); > + > + writel(data >> 8, rtc->regs + RTC_REG(4)); > + > + tmp = readl(rtc->regs + RTC_REG(0)); > + tmp &= ~(0xff << 24); > + tmp |= (data << 24); > + tmp |= RTCREG0_START_SER; Add a define for the shifts here. > + > + writel(tmp, rtc->regs + RTC_REG(0)); > + > + if (meson_rtc_wait_serialiser(rtc)) > + return -ETIMEDOUT; > + > + dev_info(rtc->dev, "rtc_reg0 = %08x\n", readl(rtc->regs + RTC_REG(0))); > + mutex_unlock(&rtc->lock); > + dev_dbg instead here. > + return 0; > +} > + > +static int meson_rtc_probe(struct platform_device *pdev) > +{ > + struct meson_rtc *rtc; > + struct device *dev = &pdev->dev; > + struct resource *res; > + u32 tm; > + int ret; > + > + rtc = devm_kzalloc(dev, sizeof(struct meson_rtc), GFP_KERNEL); > + if (!rtc) { > + dev_err(dev, "failed to allocate memory\n"); > + return -ENOMEM; > + } > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + rtc->regs = devm_ioremap_resource(dev, res); > + rtc->dev = dev; > + > + if (IS_ERR(rtc->regs)) > + return PTR_ERR(rtc->regs); > + > + mutex_init(&rtc->lock); > + platform_set_drvdata(pdev, rtc); > + > + ret = meson_rtc_write_static(rtc, > + MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE); > + if (ret) { > + dev_err(dev, "failed to set static values\n"); > + return ret; > + } > + > + rtc->reset = devm_reset_control_get(dev, NULL); > + if (IS_ERR(rtc->reset)) > + dev_warn(dev, "no reset available, rtc may not work\n"); > + > + /* check if we can read RTC counter, if not then the RTC is probably > + * not functional. If it isn't probably best to not bind */ > + ret = meson_rtc_read(rtc, RTC_COUNTER, &tm); > + if (ret) { > + dev_err(dev, "cannot read RTC counter, RTC not functional\n"); > + return ret; > + } > + > + rtc->rtc = devm_rtc_device_register(dev, "meson", > + &meson_rtc_ops, THIS_MODULE); > + if (IS_ERR(rtc->rtc)) { > + dev_err(dev, "cannot attach rtc\n"); > + return PTR_ERR(rtc->rtc); > + } > + > + dev_info(dev, "device registered\n"); > + return 0; > +} > + > +static const struct of_device_id meson_rtc_dt_match[] = { > + { .compatible = "amlogic,meson6-rtc", }, > + { .compatible = "amlogic,meson8-rtc", }, > + { .compatible = "amlogic,meson8b-rtc", }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, meson_rtc_dt_match); > + > +static struct platform_driver meson_rtc_driver = { > + .probe = meson_rtc_probe, > + .driver = { > + .name = "meson-rtc", > + .of_match_table = of_match_ptr(meson_rtc_dt_match), > + }, > +}; > +module_platform_driver(meson_rtc_driver); > + > +MODULE_DESCRIPTION("AMLogic MESON RTC Driver"); > +MODULE_AUTHOR("Ben Dooks <ben.doosk@codethink.co.uk>"); > +MODULE_LICENSE("GPL"); > +MODULE_ALIAS("platform:meson-rtc"); > Neil ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC 1/4] rtc: support for amlogic meson rtc 2016-06-24 14:25 ` Neil Armstrong @ 2016-06-24 14:54 ` Ben Dooks 0 siblings, 0 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-24 14:54 UTC (permalink / raw) To: linus-amlogic On 24/06/16 15:25, Neil Armstrong wrote: > Hi Ben, > > On 06/23/2016 10:21 PM, Ben Dooks wrote: >> Add support for the AMLogic meson8b/meson6 RTC block. >> >> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> >> --- > > [...] > >> + >> +/* registers accessed from cpu bus */ >> +#define RTC_REG(x) ((x) * 4) /* rtc registers 0-4 */ >> + >> +#define LINE_SDI (1 << 2) >> +#define LINE_SEN (1 << 1) >> +#define LINE_SCLK (1 << 0) >> + >> +#define RTCREG0_START_SER BIT(17) >> +#define RTCREG0_WAIT_SER BIT(22) >> + >> +#define RTCREG1_READY BIT(1) >> + >> +/* rtc registers accessed via rtc-serial inteface */ >> +#define RTC_COUNTER (0) >> +#define RTC_SEC_ADJ (2) >> + >> +#define RTC_ADDR_BITS (3) /* number of address bits to send */ >> +#define RTC_DATA_BITS (32) /* number of data bits to tx/rx */ >> + >> +#define MESON_STATIC_BIAS_CUR (0x5 << 1) >> +#define MESON_STATIC_VOLTAGE (0x3 << 11) > > Cleanup indentation here. ok, will do. >> + >> +struct meson_rtc { >> + struct rtc_device *rtc; /* rtc device we created */ >> + struct device *dev; /* device we bound from */ >> + struct reset_control *reset; /* reset source */ >> + struct mutex lock; /* rtc lock */ >> + void __iomem *regs; /* rtc register access */ >> +}; >> + >> +static void meson_rtc_setline(struct meson_rtc *rtc, unsigned bit, unsigned to) >> +{ >> + u32 reg0; >> + >> + reg0 = readl(rtc->regs + RTC_REG(0)); >> + if (to) >> + reg0 |= bit; >> + else >> + reg0 &= ~bit; >> + writel(reg0, rtc->regs + RTC_REG(0)); >> + >> +} >> + >> +static void meson_rtc_sclk_pulse(struct meson_rtc *rtc) >> +{ >> + udelay(5); >> + meson_rtc_setline(rtc, LINE_SCLK, 0); >> + udelay(5); >> + meson_rtc_setline(rtc, LINE_SCLK, 1); >> +} >> + >> +static void meson_rtc_send_bit(struct meson_rtc *rtc, unsigned bit) >> +{ >> + meson_rtc_setline(rtc, LINE_SDI, bit ? 1 : 0); > > You can use !!bit here also I /could/ but I don't like it, and it's not going to improve the code. >> + meson_rtc_sclk_pulse(rtc); >> +} >> + >> +static void meson_rtc_send_bits(struct meson_rtc *rtc, u32 data, unsigned nr) >> +{ >> + u32 bit = 1 << (nr - 1); >> + >> + while (bit) { >> + meson_rtc_send_bit(rtc, data & bit); >> + bit >>= 1; >> + } >> +} >> + >> +static void meson_rtc_set_dir(struct meson_rtc *rtc, u32 mode) >> +{ >> + meson_rtc_setline(rtc, LINE_SDI, 0); >> + meson_rtc_send_bit(rtc, mode); >> + meson_rtc_setline(rtc, LINE_SDI, 0); >> +} >> + >> +static u32 meson_rtc_read_sdo(struct meson_rtc *rtc) >> +{ >> + return readl(rtc->regs + RTC_REG(1)) & (1 << 0); > > Drop the << 0 here, or replace by BIT(0) ok, will do. >> +} >> + >> +static u32 meson_rtc_get_data(struct meson_rtc *rtc) >> +{ >> + u32 val = 0; >> + int bit; >> + >> + for (bit = 0; bit < RTC_DATA_BITS; bit++) { >> + meson_rtc_sclk_pulse(rtc); >> + val <<= 1; >> + val |= meson_rtc_read_sdo(rtc); >> + } >> + >> + return val; >> +} >> + >> +static int meson_rtc_wait_bus(struct meson_rtc *rtc, unsigned timeout_ms) >> +{ >> + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); >> + u32 val; >> + >> + val = readl(rtc->regs + RTC_REG(0)); >> + val &= ~(LINE_SDI | LINE_SEN | LINE_SCLK); >> + writel(val, rtc->regs + RTC_REG(0)); >> + >> + while (time_before(jiffies, timeout)) { >> + val = readl(rtc->regs + RTC_REG(1)); >> + if (val & RTCREG1_READY) >> + return 1; >> + >> + dev_info(rtc->dev, "%s: reg1=%08x\n", __func__, val); >> + msleep(10); >> + } >> + >> + return 0; >> +} >> + >> +static int meson_rtc_get_bus(struct meson_rtc *rtc) >> +{ >> + int ret, retries = 3; >> + >> + while (retries) { >> + if (meson_rtc_wait_bus(rtc, 300)) >> + return 0; > > Put the timeout time in a define 300 to be easily changed. not sure that's necessary, it's just in one place. >> + >> + dev_warn(rtc->dev, "failed to get bus, re-setting\n"); >> + >> + retries--; >> + ret = reset_control_reset(rtc->reset); >> + if (ret) >> + return ret; >> + } >> + >> + dev_err(rtc->dev, "%s: bus is not ready\n", __func__); >> + return -ETIMEDOUT; >> +} >> + >> +static int meson_rtc_read(struct meson_rtc *rtc, unsigned int reg, u32 *data) >> +{ >> + int ret; >> + >> + ret = meson_rtc_get_bus(rtc); >> + if (ret) >> + return ret; >> + >> + meson_rtc_setline(rtc, LINE_SEN, 1); >> + meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS); >> + meson_rtc_setline(rtc, LINE_SEN, 0); >> + meson_rtc_set_dir(rtc, 0); >> + *data = meson_rtc_get_data(rtc); >> + >> + return 0; >> +} >> + >> +static int meson_rtc_write(struct meson_rtc *rtc, unsigned int reg, u32 data) >> +{ >> + int ret; >> + >> + ret = meson_rtc_get_bus(rtc); >> + if (ret) >> + return ret; >> + >> + meson_rtc_setline(rtc, LINE_SEN, 1); >> + meson_rtc_send_bits(rtc, reg, RTC_ADDR_BITS); >> + meson_rtc_setline(rtc, LINE_SEN, 0); >> + meson_rtc_set_dir(rtc, 1); >> + meson_rtc_send_bits(rtc, data, RTC_DATA_BITS); >> + >> + return 0; >> +} >> + >> +static int meson_rtc_gettime(struct device *dev, struct rtc_time *tm) >> +{ >> + struct meson_rtc *rtc = dev_get_drvdata(dev); >> + int ret; >> + u32 time; >> + >> + mutex_lock(&rtc->lock); >> + >> + ret = meson_rtc_read(rtc, RTC_COUNTER, &time); >> + if (ret) >> + return ret; >> + >> + rtc_time_to_tm(time, tm); >> + dev_info(dev, "read time %lu\n", (unsigned long)time); > > Replace by a dev_dbg here. Already done for v2. >> + >> + mutex_unlock(&rtc->lock); >> + return 0; >> +} >> + >> +static int meson_rtc_settime(struct device *dev, struct rtc_time *tm) >> +{ >> + struct meson_rtc *rtc = dev_get_drvdata(dev); >> + unsigned long time; >> + int ret; >> + >> + mutex_lock(&rtc->lock); >> + >> + rtc_tm_to_time(tm, &time); >> + ret = meson_rtc_write(rtc, RTC_COUNTER, time); >> + >> + mutex_unlock(&rtc->lock); >> + return ret; >> +} >> + >> +static const struct rtc_class_ops meson_rtc_ops = { >> + .read_time = meson_rtc_gettime, >> + .set_time = meson_rtc_settime, >> +}; >> + >> +static int meson_rtc_wait_serialiser(struct meson_rtc *rtc) >> +{ >> + unsigned long timeout = jiffies + msecs_to_jiffies(100); >> + >> + while (time_before(jiffies, timeout)) { >> + if (!(readl(rtc->regs + RTC_REG(0)) & RTCREG0_WAIT_SER)) >> + return 0; >> + msleep(10); >> + } >> + >> + return -ETIMEDOUT; >> +} >> + >> +static int meson_rtc_write_static(struct meson_rtc *rtc, u32 data) >> +{ >> + u32 tmp; >> + >> + mutex_lock(&rtc->lock); >> + >> + writel(data >> 8, rtc->regs + RTC_REG(4)); >> + >> + tmp = readl(rtc->regs + RTC_REG(0)); >> + tmp &= ~(0xff << 24); >> + tmp |= (data << 24); >> + tmp |= RTCREG0_START_SER; > > Add a define for the shifts here. > >> + >> + writel(tmp, rtc->regs + RTC_REG(0)); >> + >> + if (meson_rtc_wait_serialiser(rtc)) >> + return -ETIMEDOUT; >> + >> + dev_info(rtc->dev, "rtc_reg0 = %08x\n", readl(rtc->regs + RTC_REG(0))); >> + mutex_unlock(&rtc->lock); >> + > > dev_dbg instead here. Yep, caught already for v2. >> + return 0; >> +} >> + >> +static int meson_rtc_probe(struct platform_device *pdev) >> +{ >> + struct meson_rtc *rtc; >> + struct device *dev = &pdev->dev; >> + struct resource *res; >> + u32 tm; >> + int ret; >> + >> + rtc = devm_kzalloc(dev, sizeof(struct meson_rtc), GFP_KERNEL); >> + if (!rtc) { >> + dev_err(dev, "failed to allocate memory\n"); >> + return -ENOMEM; >> + } >> + >> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >> + rtc->regs = devm_ioremap_resource(dev, res); >> + rtc->dev = dev; >> + >> + if (IS_ERR(rtc->regs)) >> + return PTR_ERR(rtc->regs); >> + >> + mutex_init(&rtc->lock); >> + platform_set_drvdata(pdev, rtc); >> + >> + ret = meson_rtc_write_static(rtc, >> + MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE); >> + if (ret) { >> + dev_err(dev, "failed to set static values\n"); >> + return ret; >> + } >> + >> + rtc->reset = devm_reset_control_get(dev, NULL); >> + if (IS_ERR(rtc->reset)) >> + dev_warn(dev, "no reset available, rtc may not work\n"); >> + >> + /* check if we can read RTC counter, if not then the RTC is probably >> + * not functional. If it isn't probably best to not bind */ >> + ret = meson_rtc_read(rtc, RTC_COUNTER, &tm); >> + if (ret) { >> + dev_err(dev, "cannot read RTC counter, RTC not functional\n"); >> + return ret; >> + } >> + >> + rtc->rtc = devm_rtc_device_register(dev, "meson", >> + &meson_rtc_ops, THIS_MODULE); >> + if (IS_ERR(rtc->rtc)) { >> + dev_err(dev, "cannot attach rtc\n"); >> + return PTR_ERR(rtc->rtc); >> + } >> + >> + dev_info(dev, "device registered\n"); >> + return 0; >> +} >> + >> +static const struct of_device_id meson_rtc_dt_match[] = { >> + { .compatible = "amlogic,meson6-rtc", }, >> + { .compatible = "amlogic,meson8-rtc", }, >> + { .compatible = "amlogic,meson8b-rtc", }, >> + { }, >> +}; >> +MODULE_DEVICE_TABLE(of, meson_rtc_dt_match); >> + >> +static struct platform_driver meson_rtc_driver = { >> + .probe = meson_rtc_probe, >> + .driver = { >> + .name = "meson-rtc", >> + .of_match_table = of_match_ptr(meson_rtc_dt_match), >> + }, >> +}; >> +module_platform_driver(meson_rtc_driver); >> + >> +MODULE_DESCRIPTION("AMLogic MESON RTC Driver"); >> +MODULE_AUTHOR("Ben Dooks <ben.doosk@codethink.co.uk>"); >> +MODULE_LICENSE("GPL"); >> +MODULE_ALIAS("platform:meson-rtc"); >> > > > Neil Ta. -- Ben Dooks http://www.codethink.co.uk/ Senior Engineer Codethink - Providing Genius ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC 1/4] rtc: support for amlogic meson rtc 2016-06-23 20:21 ` [RFC 1/4] rtc: support for amlogic meson rtc Ben Dooks 2016-06-24 14:25 ` Neil Armstrong @ 2016-06-24 14:26 ` Neil Armstrong 1 sibling, 0 replies; 12+ messages in thread From: Neil Armstrong @ 2016-06-24 14:26 UTC (permalink / raw) To: linus-amlogic On 06/23/2016 10:21 PM, Ben Dooks wrote: > Add support for the AMLogic meson8b/meson6 RTC block. > > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> > --- > drivers/rtc/Kconfig | 10 ++ > drivers/rtc/Makefile | 1 + > drivers/rtc/rtc-meson.c | 339 ++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 350 insertions(+) > create mode 100644 drivers/rtc/rtc-meson.c > > diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig > index 9f8b59d..a90634f5 100644 > --- a/drivers/rtc/Kconfig > +++ b/drivers/rtc/Kconfig > @@ -1222,6 +1222,16 @@ config RTC_DRV_IMXDI > This driver can also be built as a module, if so, the module > will be called "rtc-imxdi". > > +config RTC_DRV_MESON > + tristate "AMLogic Meson Real Time Clock" > + depends on ARCH_MESON You can also || COMPILE_TEST here > + help > + Support for AMLogic Meson RTC block > + > + This driver can also be built as a module, if so, the module > + will be called "rtc-meson". > + > + > config RTC_DRV_OMAP > tristate "TI OMAP Real Time Clock" > depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST Neil ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC 2/4] odroidc1: enable rtc 2016-06-23 20:21 S805 RTC driver Ben Dooks 2016-06-23 20:21 ` [RFC 1/4] rtc: support for amlogic meson rtc Ben Dooks @ 2016-06-23 20:21 ` Ben Dooks 2016-06-23 20:21 ` [RFC 3/4] meson-rtc: add device-tree binding Ben Dooks ` (3 subsequent siblings) 5 siblings, 0 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-23 20:21 UTC (permalink / raw) To: linus-amlogic --- arch/arm/boot/dts/meson8b-odroidc1.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts index e50f1a1..5c7826f 100644 --- a/arch/arm/boot/dts/meson8b-odroidc1.dts +++ b/arch/arm/boot/dts/meson8b-odroidc1.dts @@ -76,3 +76,8 @@ pinctrl-0 = <&uart_ao_a_pins>; pinctrl-names = "default"; }; + +&rtc { + status = "okay"; +}; + -- 2.8.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC 3/4] meson-rtc: add device-tree binding 2016-06-23 20:21 S805 RTC driver Ben Dooks 2016-06-23 20:21 ` [RFC 1/4] rtc: support for amlogic meson rtc Ben Dooks 2016-06-23 20:21 ` [RFC 2/4] odroidc1: enable rtc Ben Dooks @ 2016-06-23 20:21 ` Ben Dooks 2016-06-23 20:21 ` [RFC 4/4] meson8b: add rtc node Ben Dooks ` (2 subsequent siblings) 5 siblings, 0 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-23 20:21 UTC (permalink / raw) To: linus-amlogic --- .../devicetree/bindings/rtc/rtc-amlogic.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/rtc-amlogic.txt diff --git a/Documentation/devicetree/bindings/rtc/rtc-amlogic.txt b/Documentation/devicetree/bindings/rtc/rtc-amlogic.txt new file mode 100644 index 0000000..efc7672 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-amlogic.txt @@ -0,0 +1,21 @@ +* AMlogic Meson RTC + +Required properties: +- compatible: should be one of the following describing the hardware: + * "amlogic,meson6-rtc" + * "amlogic,meson8-rtc" + * "amlogic,meson8b-rtc" + +- reg: physical register space for the controller's memory mapped registers. + +Optional properties: +- resets: reset controller reference to allow reset of the controller +- interrupts: single interrupt reference if interrupt support needed + +Example: + + rtc: rtc at c8100740 { + compatible = "amlogic,meson6-rtc"; + reg = <0xc8100740 0x14>; + status = "disabled"; + }; -- 2.8.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC 4/4] meson8b: add rtc node 2016-06-23 20:21 S805 RTC driver Ben Dooks ` (2 preceding siblings ...) 2016-06-23 20:21 ` [RFC 3/4] meson-rtc: add device-tree binding Ben Dooks @ 2016-06-23 20:21 ` Ben Dooks 2016-06-24 12:42 ` [Linux-kernel] S805 RTC driver Ben Dooks 2016-06-24 14:29 ` Neil Armstrong 5 siblings, 0 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-23 20:21 UTC (permalink / raw) To: linus-amlogic --- arch/arm/boot/dts/meson8b.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi index fc4080d..15a9d8d 100644 --- a/arch/arm/boot/dts/meson8b.dtsi +++ b/arch/arm/boot/dts/meson8b.dtsi @@ -156,6 +156,13 @@ status = "disabled"; }; + rtc: rtc at c8100740 { + compatible = "amlogic,meson8b-rtc"; + reg = <0xc8100740 0x14>; + resets = <&reset RESET_RTC>; + status = "disabled"; + }; + clkc: clock-controller at c1104000 { #clock-cells = <1>; compatible = "amlogic,meson8b-clkc"; -- 2.8.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Linux-kernel] S805 RTC driver 2016-06-23 20:21 S805 RTC driver Ben Dooks ` (3 preceding siblings ...) 2016-06-23 20:21 ` [RFC 4/4] meson8b: add rtc node Ben Dooks @ 2016-06-24 12:42 ` Ben Dooks 2016-06-24 14:29 ` Neil Armstrong 5 siblings, 0 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-24 12:42 UTC (permalink / raw) To: linus-amlogic On 23/06/16 21:21, Ben Dooks wrote: > This has been sitting in my tree for a while, so I thought > it would be a good idea to try and get it moving along and > possibly submittied soon. > > I've not been able to fully test this as I don't have an > S805 MMC driver to allow me to boot to a userland on my > ODroid-C1 board. If no-one is going to comment, I will submit this on Monday. -- Ben Dooks http://www.codethink.co.uk/ Senior Engineer Codethink - Providing Genius ^ permalink raw reply [flat|nested] 12+ messages in thread
* S805 RTC driver 2016-06-23 20:21 S805 RTC driver Ben Dooks ` (4 preceding siblings ...) 2016-06-24 12:42 ` [Linux-kernel] S805 RTC driver Ben Dooks @ 2016-06-24 14:29 ` Neil Armstrong 2016-06-24 14:36 ` Ben Dooks 2016-06-24 15:47 ` Ben Dooks 5 siblings, 2 replies; 12+ messages in thread From: Neil Armstrong @ 2016-06-24 14:29 UTC (permalink / raw) To: linus-amlogic On 06/23/2016 10:21 PM, Ben Dooks wrote: > This has been sitting in my tree for a while, so I thought > it would be a good idea to try and get it moving along and > possibly submittied soon. > > I've not been able to fully test this as I don't have an > S805 MMC driver to allow me to boot to a userland on my > ODroid-C1 board. You could generate a dummy buildroot initramfs loaded in the Image with the RTC tools. Neil > > _______________________________________________ > linux-amlogic mailing list > linux-amlogic at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-amlogic > ^ permalink raw reply [flat|nested] 12+ messages in thread
* S805 RTC driver 2016-06-24 14:29 ` Neil Armstrong @ 2016-06-24 14:36 ` Ben Dooks 2016-06-24 15:47 ` Ben Dooks 1 sibling, 0 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-24 14:36 UTC (permalink / raw) To: linus-amlogic On 24/06/16 15:29, Neil Armstrong wrote: > On 06/23/2016 10:21 PM, Ben Dooks wrote: >> This has been sitting in my tree for a while, so I thought >> it would be a good idea to try and get it moving along and >> possibly submittied soon. >> >> I've not been able to fully test this as I don't have an >> S805 MMC driver to allow me to boot to a userland on my >> ODroid-C1 board. > > You could generate a dummy buildroot initramfs loaded in the Image with the RTC tools. I managed to get the older 4.x mmc driver from Carlo working so have a debian image to build. -- Ben Dooks http://www.codethink.co.uk/ Senior Engineer Codethink - Providing Genius ^ permalink raw reply [flat|nested] 12+ messages in thread
* S805 RTC driver 2016-06-24 14:29 ` Neil Armstrong 2016-06-24 14:36 ` Ben Dooks @ 2016-06-24 15:47 ` Ben Dooks 1 sibling, 0 replies; 12+ messages in thread From: Ben Dooks @ 2016-06-24 15:47 UTC (permalink / raw) To: linus-amlogic On 24/06/16 15:29, Neil Armstrong wrote: > On 06/23/2016 10:21 PM, Ben Dooks wrote: >> This has been sitting in my tree for a while, so I thought >> it would be a good idea to try and get it moving along and >> possibly submittied soon. >> >> I've not been able to fully test this as I don't have an >> S805 MMC driver to allow me to boot to a userland on my >> ODroid-C1 board. > > You could generate a dummy buildroot initramfs loaded in the Image with the RTC tools. Thanks for the review, will try and send a RFCv2 today. -- Ben Dooks http://www.codethink.co.uk/ Senior Engineer Codethink - Providing Genius ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2016-06-24 15:47 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-06-23 20:21 S805 RTC driver Ben Dooks 2016-06-23 20:21 ` [RFC 1/4] rtc: support for amlogic meson rtc Ben Dooks 2016-06-24 14:25 ` Neil Armstrong 2016-06-24 14:54 ` Ben Dooks 2016-06-24 14:26 ` Neil Armstrong 2016-06-23 20:21 ` [RFC 2/4] odroidc1: enable rtc Ben Dooks 2016-06-23 20:21 ` [RFC 3/4] meson-rtc: add device-tree binding Ben Dooks 2016-06-23 20:21 ` [RFC 4/4] meson8b: add rtc node Ben Dooks 2016-06-24 12:42 ` [Linux-kernel] S805 RTC driver Ben Dooks 2016-06-24 14:29 ` Neil Armstrong 2016-06-24 14:36 ` Ben Dooks 2016-06-24 15:47 ` Ben Dooks
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.