* Build breakage with omap2plus_defconfig
From: Felipe Balbi @ 2011-01-07 12:38 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
Today's Linus' tree (01539ba2a706ab7d35fc0667dff919ade7f87d63) fails to
build with omap2plus_defconfig:
$ crossmake
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
CALL scripts/checksyscalls.sh
CHK include/generated/compile.h
CC arch/arm/kernel/swp_emulate.o
/tmp/cc2V7p5j.s: Assembler messages:
/tmp/cc2V7p5j.s:161: Error: selected processor does not support ARM mode `ldrexb r3,[r4]'
/tmp/cc2V7p5j.s:162: Error: selected processor does not support ARM mode `strexb r0,r2,[r4]'
make[1]: *** [arch/arm/kernel/swp_emulate.o] Error 1
make: *** [arch/arm/kernel] Error 2
Compiler is:
$ arm-linux-gcc --version
arm-linux-gcc (Sourcery G++ Lite 2010q1-202) 4.4.1
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
I'm downloading Sourcery G++ Lite 2010.09-50 for ARM GNU/Linux to check
if it's not a bug on the compiler.
--
balbi
^ permalink raw reply
* [PATCH] i2c-pxa2xx: Add PCI support for PXA I2C controller
From: Sebastian Andrzej Siewior @ 2011-01-07 12:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110106215726.GB30799@suse.de>
The Sodaville I2C controller is almost the same as found on PXA2xx. The
difference:
- the register are at a different offset
- no slave support
The PCI probe code adds three platform devices which are probed then by
the platform code.
The X86 part also adds dummy clock defines because we don't have HW
clock support.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
---
I switched to platform_device_alloc() now so the rece should be gone.
I also pushed out the whole series.
drivers/i2c/busses/Kconfig | 7 +-
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-pxa-pci.c | 176 ++++++++++++++++++++++++++++++++++++++
drivers/i2c/busses/i2c-pxa.c | 27 +++++-
4 files changed, 206 insertions(+), 5 deletions(-)
create mode 100644 drivers/i2c/busses/i2c-pxa-pci.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 3a6321c..9ee3e60 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -525,15 +525,18 @@ config I2C_PNX
config I2C_PXA
tristate "Intel PXA2XX I2C adapter"
- depends on ARCH_PXA || ARCH_MMP
+ depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
help
If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module
will be called i2c-pxa.
+config I2C_PXA_PCI
+ def_bool I2C_PXA && X86_32 && PCI && OF
+
config I2C_PXA_SLAVE
bool "Intel PXA2XX I2C Slave comms support"
- depends on I2C_PXA
+ depends on I2C_PXA && !X86_32
help
Support I2C slave mode communications on the PXA I2C bus. This
is necessary for systems where the PXA may be a target on the
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 84cb16a..78db2e3 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
+obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c
new file mode 100644
index 0000000..6659d26
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pxa-pci.c
@@ -0,0 +1,176 @@
+/*
+ * The CE4100's I2C device is more or less the same one as found on PXA.
+ * It does not support slave mode, the register slightly moved. This PCI
+ * device provides three bars, every contains a single I2C controller.
+ */
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+#define CE4100_PCI_I2C_DEVS 3
+
+struct ce4100_devices {
+ struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
+};
+
+static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
+{
+ struct platform_device *pdev;
+ struct i2c_pxa_platform_data pdata;
+ struct resource res[2];
+ struct device_node *child;
+ static int devnum;
+ int ret;
+
+ memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
+ memset(&res, 0, sizeof(res));
+
+ res[0].flags = IORESOURCE_MEM;
+ res[0].start = pci_resource_start(dev, bar);
+ res[0].end = pci_resource_end(dev, bar);
+
+ res[1].flags = IORESOURCE_IRQ;
+ res[1].start = dev->irq;
+ res[1].end = dev->irq;
+
+ for_each_child_of_node(dev->dev.of_node, child) {
+ const void *prop;
+ struct resource r;
+ int ret;
+
+ ret = of_address_to_resource(child, 0, &r);
+ if (ret < 0)
+ continue;
+ if (r.start != res[0].start)
+ continue;
+ if (r.end != res[0].end)
+ continue;
+ if (r.flags != res[0].flags)
+ continue;
+
+ prop = of_get_property(child, "fast-mode", NULL);
+ if (prop)
+ pdata.fast_mode = 1;
+
+ break;
+ }
+
+ if (!child) {
+ dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
+ bar);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pdev = platform_device_alloc("ce4100-i2c", devnum);
+ if (!pdev) {
+ of_node_put(child);
+ ret = -ENOMEM;
+ goto out;
+ }
+ pdev->dev.parent = &dev->dev;
+ pdev->dev.of_node = child;
+
+ ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+ if (ret)
+ goto err;
+
+ ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (ret)
+ goto err;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto err;
+ devnum++;
+ return pdev;
+err:
+ platform_device_put(pdev);
+out:
+ return ERR_PTR(ret);
+}
+
+static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ int ret;
+ int i;
+ struct ce4100_devices *sds;
+
+ ret = pci_enable_device_mem(dev);
+ if (ret)
+ return ret;
+
+ if (!dev->dev.of_node) {
+ dev_err(&dev->dev, "Missing device tree node.\n");
+ return -EINVAL;
+ }
+ sds = kzalloc(sizeof(*sds), GFP_KERNEL);
+ if (!sds)
+ goto err_mem;
+
+ for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
+ sds->pdev[i] = add_i2c_device(dev, i);
+ if (IS_ERR(sds->pdev[i])) {
+ while (--i >= 0)
+ platform_device_unregister(sds->pdev[i]);
+ goto err_dev_add;
+ }
+ }
+ pci_set_drvdata(dev, sds);
+ return 0;
+
+err_dev_add:
+ pci_set_drvdata(dev, NULL);
+ kfree(sds);
+err_mem:
+ pci_disable_device(dev);
+ return ret;
+}
+
+static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
+{
+ struct ce4100_devices *sds;
+ unsigned int i;
+
+ sds = pci_get_drvdata(dev);
+ pci_set_drvdata(dev, NULL);
+
+ for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
+ platform_device_unregister(sds->pdev[i]);
+
+ pci_disable_device(dev);
+ kfree(sds);
+}
+
+static struct pci_device_id ce4100_i2c_devices[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
+ { },
+};
+MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
+
+static struct pci_driver ce4100_i2c_driver = {
+ .name = "ce4100_i2c",
+ .id_table = ce4100_i2c_devices,
+ .probe = ce4100_i2c_probe,
+ .remove = __devexit_p(ce4100_i2c_remove),
+};
+
+static int __init ce4100_i2c_init(void)
+{
+ return pci_register_driver(&ce4100_i2c_driver);
+}
+module_init(ce4100_i2c_init);
+
+static void __exit ce4100_i2c_exit(void)
+{
+ pci_unregister_driver(&ce4100_i2c_driver);
+}
+module_exit(ce4100_i2c_exit);
+
+MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index fc2a90e..225e9a5 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -38,6 +38,13 @@
#include <asm/irq.h>
+#ifdef CONFIG_X86
+#define clk_get(dev, id) NULL
+#define clk_put(clk) do { } while (0)
+#define clk_disable(clk) do { } while (0)
+#define clk_enable(clk) do { } while (0)
+#endif
+
struct pxa_reg_layout {
u32 ibmr;
u32 idbr;
@@ -49,6 +56,7 @@ struct pxa_reg_layout {
enum pxa_i2c_types {
REGS_PXA2XX,
REGS_PXA3XX,
+ REGS_CE4100,
};
/*
@@ -69,11 +77,19 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
.isr = 0x18,
.isar = 0x20,
},
+ [REGS_CE4100] = {
+ .ibmr = 0x14,
+ .idbr = 0x0c,
+ .icr = 0x00,
+ .isr = 0x04,
+ /* no isar register */
+ },
};
static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa2xx-i2c", REGS_PXA2XX },
{ "pxa3xx-pwri2c", REGS_PXA3XX },
+ { "ce4100-i2c", REGS_CE4100 },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -442,7 +458,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
writel(I2C_ISR_INIT, _ISR(i2c));
writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
- writel(i2c->slave_addr, _ISAR(i2c));
+ if (i2c->reg_isar)
+ writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */
writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
@@ -1074,7 +1091,8 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
- i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
+ if (i2c_type != REGS_CE4100)
+ i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
i2c->iobase = res->start;
i2c->iosize = resource_size(res);
@@ -1113,7 +1131,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &dev->dev;
- ret = i2c_add_numbered_adapter(&i2c->adap);
+ if (i2c_type == REGS_CE4100)
+ ret = i2c_add_adapter(&i2c->adap);
+ else
+ ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
printk(KERN_INFO "I2C: Failed to add bus\n");
goto eadapt;
--
1.7.3.2
^ permalink raw reply related
* [PATCH V2] ARM: S5PV310: Implement kernel timers using MCT
From: Russell King - ARM Linux @ 2011-01-07 12:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <019e01cbae63$2511a5e0$6f34f1a0$%kim@samsung.com>
On Fri, Jan 07, 2011 at 09:05:11PM +0900, Kukjin Kim wrote:
> Russell King - ARM Linux wrote:
> >
> > On Tue, Jan 04, 2011 at 11:18:47AM +0900, Kukjin Kim wrote:
> > > From: Changhwan Youn <chaos.youn@samsung.com>
> > >
> > > The Multi-Core Timer(MCT) of S5PV310 is designed for implementing
> > > clock source timer and clock event timers. This patch implements
> > > 1 clock source timer with 64 bit free running counter of MCT and
> > > 2 clock event timers with two of 31-bit tick counters.
> >
> > I want to wait until after this merge window before commenting too much
> > on this; some of this patch will be impacted by changes in this merge
> > window.
> >
> Hmmm...Ok, I understood.
That stuff is now in mainline - not only the new sched_clock() support
but also the SMP changes (which impact on your MCT code.) Please rebase
on latest mainline and re-send.
> > > +static void s5pv310_frc_suspend(struct clocksource *cs)
> > > +{
> > > + time_suspended = s5pv310_frc_read(cs);
> > > +};
> > > +
> > > +static void s5pv310_frc_resume(struct clocksource *cs)
> > > +{
> > > + s5pv310_mct_frc_start((u32)(time_suspended >> 32),
> > (u32)time_suspended);
> > > +};
> >
> > Is this something which other clocksource drivers need to do, or does the
> > core automatically deal with the clocksource being irregular across a
> > suspend/resume event?
> >
> Normally this is not necessary because core deals with the irregularity of
> clocksource, but for sched_clock() implementation, clocksource had better be
> regular across a suspend/resume event. One example is "Show timing
> information on printks" kernel configuration. Without this code, timing
> information resets after suspend/resume event.
>
> Following is not submitted but will be submitted :-)
>
> unsigned long long sched_clock(void)
> {
> struct clocksource *cs = &mct_frc;
>
> return clocksource_cyc2ns(cs->read(NULL), sched_mult, sched_shift);
> }
Please use the new sched_clock stuff which guarantees to return a 64-bit
cycle count (which is what sched_clock() is required to do.)
^ permalink raw reply
* [PATCH 3/9] Add a mfd IPUv3 driver
From: Samuel Ortiz @ 2011-01-07 12:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110103154214.GB11033@pengutronix.de>
Hi Sascha,
On Mon, Jan 03, 2011 at 04:42:14PM +0100, Sascha Hauer wrote:
> On Mon, Dec 20, 2010 at 11:48:41AM +0100, Sascha Hauer wrote:
> > The IPU is the Image Processing Unit found on i.MX50/51/53 SoCs. It
> > features several units for image processing, this patch adds support
> > for the units needed for Framebuffer support, namely:
> >
> > - Display Controller (dc)
> > - Display Interface (di)
> > - Display Multi Fifo Controller (dmfc)
> > - Display Processor (dp)
> > - Image DMA Controller (idmac)
> >
> > This patch is based on the Freescale driver, but follows a different
> > approach. The Freescale code implements logical idmac channels and
> > the handling of the subunits is hidden in common idmac code pathes
> > in big switch/case statements. This patch instead just provides code
> > and resource management for the different subunits. The user, in this
> > case the framebuffer driver, decides how the different units play
> > together.
> >
> > The IPU has other units missing in this patch:
> >
> > - CMOS Sensor Interface (csi)
> > - Video Deinterlacer (vdi)
> > - Sensor Multi FIFO Controler (smfc)
> > - Image Converter (ic)
> > - Image Rotator (irt)
> >
> > So expect more files to come in this directory.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>
> Hello Samuel,
>
> I see no further comments on this series. Does this mean you are ok with
> the patch or didn't you find the time looking at it?
I'm coming back from my xmas holidays today, and haven't had time to look at
it yet. Hopefully next week.
> This patch can go via the mfd tree or I can push this via my i.MX tree.
> Going via the i.MX tree makes life a bit easier for me because we do not
> run into merge order dependencies. Please let me know what you prefer.
I'm usually fine either way. If taking it through your tree makes your life
easier, then we should go for it.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH V2] ARM: S5PV310: Implement kernel timers using MCT
From: Kukjin Kim @ 2011-01-07 12:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110106155358.GH31708@n2100.arm.linux.org.uk>
Russell King - ARM Linux wrote:
>
> On Tue, Jan 04, 2011 at 11:18:47AM +0900, Kukjin Kim wrote:
> > From: Changhwan Youn <chaos.youn@samsung.com>
> >
> > The Multi-Core Timer(MCT) of S5PV310 is designed for implementing
> > clock source timer and clock event timers. This patch implements
> > 1 clock source timer with 64 bit free running counter of MCT and
> > 2 clock event timers with two of 31-bit tick counters.
>
> I want to wait until after this merge window before commenting too much
> on this; some of this patch will be impacted by changes in this merge
> window.
>
Hmmm...Ok, I understood.
> > +static void s5pv310_frc_suspend(struct clocksource *cs)
> > +{
> > + time_suspended = s5pv310_frc_read(cs);
> > +};
> > +
> > +static void s5pv310_frc_resume(struct clocksource *cs)
> > +{
> > + s5pv310_mct_frc_start((u32)(time_suspended >> 32),
> (u32)time_suspended);
> > +};
>
> Is this something which other clocksource drivers need to do, or does the
> core automatically deal with the clocksource being irregular across a
> suspend/resume event?
>
Normally this is not necessary because core deals with the irregularity of
clocksource, but for sched_clock() implementation, clocksource had better be
regular across a suspend/resume event. One example is "Show timing
information on printks" kernel configuration. Without this code, timing
information resets after suspend/resume event.
Following is not submitted but will be submitted :-)
unsigned long long sched_clock(void)
{
struct clocksource *cs = &mct_frc;
return clocksource_cyc2ns(cs->read(NULL), sched_mult, sched_shift);
}
> > +irqreturn_t s5pv310_mct_tick0_isr(int irq, void *dev_id)
> > +{
> > + struct clock_event_device *evt = dev_id;
> > +
> > + /*
> > + * This is for supporting oneshot mode.
> > + * Mct would generate interrupt periodically
> > + * without explicit stopping.
> > + */
> > + if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
> > + s5pv310_mct_tick_stop(MCT_TICK0);
> > +
> > + /* Clear the MCT tick0 interrupt */
> > + s5pv310_mct_write(0x1, S5PV310_MCT_L0_INT_CSTAT);
> > +
> > + evt->event_handler(evt);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +irqreturn_t s5pv310_mct_tick1_isr(int irq, void *dev_id)
> > +{
> > + struct clock_event_device *evt = dev_id;
> > +
> > + /*
> > + * This is for supporting oneshot mode.
> > + * Mct would generate interrupt periodically
> > + * without explicit stopping.
> > + */
> > + if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
> > + s5pv310_mct_tick_stop(MCT_TICK1);
> > +
> > + /* Clear the MCT tick1 interrupt */
> > + s5pv310_mct_write(0x1, S5PV310_MCT_L1_INT_CSTAT);
> > +
> > + evt->event_handler(evt);
> > +
> > + return IRQ_HANDLED;
> > +}
>
> Umm, why not wrap up the clock_event_device into your own structure,
> which then carries the base address of the MCT to be used - rather than
> duplicating the code just because the base address is different. Eg,
>
> struct mct_clock_event_device {
> struct clock_event_device evt;
> void __iomem *base;
> };
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCHv3] watchdog: add support for the Synopsys DesignWare WDT
From: Jamie Iles @ 2011-01-07 12:03 UTC (permalink / raw)
To: linux-arm-kernel
The Synopsys DesignWare watchdog is found in several ARM based systems
and provides a choice of 16 timeout periods depending on the clock
input. The watchdog cannot be disabled once started.
v3:
- convert pm to dev_pm_ops
- use devres for resource allocation
v2:
- constify fops
- request_mem_region() before ioremap()
- disable clk if misc_register() fails
Cc: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
drivers/watchdog/Kconfig | 9 ++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/dw_wdt.c | 300 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 310 insertions(+), 0 deletions(-)
create mode 100644 drivers/watchdog/dw_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 8a3aa2f..0981aae 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -331,6 +331,15 @@ config IMX2_WDT
To compile this driver as a module, choose M here: the
module will be called imx2_wdt.
+config DW_WATCHDOG
+ tristate "Synopsys DesignWare watchdog"
+ select WATCHDOG_NOWAYOUT
+ help
+ Say Y here if to include support for the Synopsys DesignWare
+ watchdog timer found in many ARM chips.
+ To compile this driver as a module, choose M here: the
+ module will be called dw_wdt.
+
# AVR32 Architecture
config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 4b0ef38..3b3da4a 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
+obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
new file mode 100644
index 0000000..e0d0e377
--- /dev/null
+++ b/drivers/watchdog/dw_wdt.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2010 Picochip Ltd., Jamie Iles
+ * http://www.picochip.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This file implements a driver for the Synopsys DesignWare watchdog device
+ * in the many ARM subsystems. The watchdog has 16 different timeout periods
+ * and these are a function of the input clock frequency.
+ */
+#define pr_fmt(fmt) "dw_wdt: " fmt
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+
+#define WDOG_CONTROL_REG_OFFSET 0x00
+#define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04
+#define WDOG_CURRENT_COUNT_REG_OFFSET 0x08
+#define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c
+
+/* The maximum TOP (timeout period) value that can be set in the watchdog. */
+#define DW_WDT_MAX_TOP 15
+
+static struct {
+ spinlock_t lock;
+ void __iomem *regs;
+ struct clk *clk;
+} dw_wdt;
+
+static inline int dw_wdt_is_enabled(void)
+{
+#define WDOG_CONTROL_REG_WDT_EN_MASK 0x01
+ return readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET) &
+ WDOG_CONTROL_REG_WDT_EN_MASK;
+}
+
+static inline int dw_wdt_top_in_seconds(unsigned top)
+{
+ /*
+ * There are 16 possible timeout values in 0..15 where the number of
+ * cycles is 2 ^ (16 + i) and the watchdog counts down.
+ */
+ return (1 << (16 + top)) / clk_get_rate(dw_wdt.clk);
+}
+
+static int dw_wdt_set_top(unsigned top_s)
+{
+ int i, top_val = -1;
+
+ /*
+ * Iterate over the timeout values until we find the closest match. We
+ * always look for >=.
+ */
+ for (i = 0; i <= DW_WDT_MAX_TOP; ++i)
+ if (dw_wdt_top_in_seconds(i) >= top_s) {
+ top_val = i;
+ break;
+ }
+
+ /*
+ * If we didn't find a suitable value, it must have been too large. Go
+ * with the biggest that we can.
+ */
+ if (top_val < 0)
+ top_val = DW_WDT_MAX_TOP;
+
+ /* Set the new value in the watchdog. */
+ writel(top_val, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+
+ return dw_wdt_top_in_seconds(top_val);
+}
+
+static int dw_wdt_get_top(void)
+{
+ int top = readl(dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET) & 0xF;
+
+ return dw_wdt_top_in_seconds(top);
+}
+
+static void dw_wdt_keepalive(void)
+{
+#define WDOG_COUNTER_RESTART_KICK_VALUE 0x76
+ writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
+ WDOG_COUNTER_RESTART_REG_OFFSET);
+}
+
+static int dw_wdt_open(struct inode *inode, struct file *filp)
+{
+ /* Make sure we don't get unloaded. */
+ __module_get(THIS_MODULE);
+
+ spin_lock(&dw_wdt.lock);
+ if (!dw_wdt_is_enabled()) {
+ /*
+ * The watchdog is not currently enabled. Set the timeout to
+ * the maximum and then start it.
+ */
+ dw_wdt_set_top(DW_WDT_MAX_TOP);
+ writel(WDOG_CONTROL_REG_WDT_EN_MASK,
+ dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
+ }
+ spin_unlock(&dw_wdt.lock);
+
+ return nonseekable_open(inode, filp);
+}
+
+ssize_t dw_wdt_write(struct file *filp, const char __user *buf, size_t len,
+ loff_t *offset)
+{
+ dw_wdt_keepalive();
+
+ return len;
+}
+
+static u32 dw_wdt_time_left(void)
+{
+ return readl(dw_wdt.regs + WDOG_CURRENT_COUNT_REG_OFFSET) /
+ clk_get_rate(dw_wdt.clk);
+}
+
+static const struct watchdog_info dw_wdt_ident = {
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+ .identity = "Synopsys DesignWare Watchdog",
+};
+
+static long dw_wdt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ unsigned long val;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user((struct watchdog_info *)arg, &dw_wdt_ident,
+ sizeof(dw_wdt_ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int *)arg);
+
+ case WDIOC_KEEPALIVE:
+ dw_wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+ return put_user(dw_wdt_set_top(val), (int __user *)arg);
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(dw_wdt_get_top(), (int __user *)arg);
+
+ case WDIOC_GETTIMELEFT:
+ /* Get the time left until expiry. */
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+ return put_user(dw_wdt_time_left(), (int __user *)arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static int dw_wdt_release(struct inode *inode, struct file *filp)
+{
+ pr_crit("WATCHDOG: device closed - timer will not stop\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int dw_wdt_suspend(struct device *dev)
+{
+ clk_disable(dw_wdt.clk);
+
+ return 0;
+}
+
+static int dw_wdt_resume(struct device *dev)
+{
+ int err = clk_enable(dw_wdt.clk);
+
+ if (err)
+ return err;
+
+ dw_wdt_keepalive();
+
+ return 0;
+}
+
+static const struct dev_pm_ops dw_wdt_pm_ops = {
+ .suspend = dw_wdt_suspend,
+ .resume = dw_wdt_resume,
+};
+
+#define DW_WDT_PM_OPS (&dw_wdt_pm_ops)
+#else /* CONFIG_PM */
+#define DW_WDT_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = dw_wdt_open,
+ .write = dw_wdt_write,
+ .unlocked_ioctl = dw_wdt_ioctl,
+ .release = dw_wdt_release
+};
+
+static struct miscdevice dw_wdt_miscdev = {
+ .fops = &wdt_fops,
+ .name = "watchdog",
+ .minor = WATCHDOG_MINOR,
+};
+
+static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!mem)
+ return -EINVAL;
+
+ if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+ "iomem"))
+ return -ENOMEM;
+
+ dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start,
+ resource_size(mem));
+ if (!dw_wdt.regs)
+ return -ENOMEM;
+
+ dw_wdt.clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR_OR_NULL(dw_wdt.clk))
+ return -ENODEV;
+ clk_enable(dw_wdt.clk);
+
+ ret = misc_register(&dw_wdt_miscdev);
+ if (ret)
+ goto register_failed;
+
+ return 0;
+
+register_failed:
+ clk_disable(dw_wdt.clk);
+ clk_put(dw_wdt.clk);
+
+ return ret;
+}
+
+static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
+{
+ clk_disable(dw_wdt.clk);
+ clk_put(dw_wdt.clk);
+
+ misc_deregister(&dw_wdt_miscdev);
+
+ return 0;
+}
+
+static struct platform_driver dw_wdt_driver = {
+ .probe = dw_wdt_drv_probe,
+ .remove = __devexit_p(dw_wdt_drv_remove),
+ .driver = {
+ .name = "dw_wdt",
+ .owner = THIS_MODULE,
+ .pm = DW_WDT_PM_OPS,
+ },
+};
+
+static int __init dw_wdt_watchdog_init(void)
+{
+ spin_lock_init(&dw_wdt.lock);
+
+ return platform_driver_register(&dw_wdt_driver);
+}
+
+static void __exit dw_wdt_watchdog_exit(void)
+{
+ platform_driver_unregister(&dw_wdt_driver);
+}
+
+module_init(dw_wdt_watchdog_init);
+module_exit(dw_wdt_watchdog_exit);
+
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver");
+MODULE_LICENSE("GPL");
--
1.7.3.4
^ permalink raw reply related
* [PATCH] watchdog: add support for the Synopsys DesignWare WDT
From: Jamie Iles @ 2011-01-07 11:41 UTC (permalink / raw)
To: linux-arm-kernel
The Synopsys DesignWare watchdog is found in several ARM based systems
and provides a choice of 16 timeout periods depending on the clock
input. The watchdog cannot be disabled once started.
If the platform does not provide a clk for the watchdog then the user
can specify the input frequency with the struct dw_wdt_platform_data in
<linux/platform_data/dw_wdt.h>
v4:
- cleanups as suggested by Viresh Kumar and Wim
- provide a mechanism to handle NULL clks and allow
platform_data to specify the clk_rate
- provide open-once protection
v3:
- convert pm to dev_pm_ops
- use devres for resource allocation
v2:
- constify fops
- request_mem_region() before ioremap()
- disable clk if misc_register() fails
Cc: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
drivers/watchdog/Kconfig | 10 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/dw_wdt.c | 329 ++++++++++++++++++++++++++++++++++
include/linux/platform_data/dw_wdt.h | 27 +++
4 files changed, 367 insertions(+), 0 deletions(-)
create mode 100644 drivers/watchdog/dw_wdt.c
create mode 100644 include/linux/platform_data/dw_wdt.h
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 8a3aa2f..057bce0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -331,6 +331,16 @@ config IMX2_WDT
To compile this driver as a module, choose M here: the
module will be called imx2_wdt.
+config DW_WATCHDOG
+ tristate "Synopsys DesignWare watchdog"
+ depends on ARM
+ select WATCHDOG_NOWAYOUT
+ help
+ Say Y here if to include support for the Synopsys DesignWare
+ watchdog timer found in many ARM chips.
+ To compile this driver as a module, choose M here: the
+ module will be called dw_wdt.
+
# AVR32 Architecture
config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 4b0ef38..3b3da4a 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
+obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
new file mode 100644
index 0000000..b6d9b6e
--- /dev/null
+++ b/drivers/watchdog/dw_wdt.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2010-2011 Picochip Ltd., Jamie Iles
+ * http://www.picochip.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This file implements a driver for the Synopsys DesignWare watchdog device
+ * in the many ARM subsystems. The watchdog has 16 different timeout periods
+ * and these are a function of the input clock frequency.
+ */
+#define pr_fmt(fmt) "dw_wdt: " fmt
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+
+#include <linux/platform_data/dw_wdt.h>
+
+#define WDOG_CONTROL_REG_OFFSET 0x00
+#define WDOG_CONTROL_REG_WDT_EN_MASK 0x01
+#define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04
+#define WDOG_CURRENT_COUNT_REG_OFFSET 0x08
+#define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c
+#define WDOG_COUNTER_RESTART_KICK_VALUE 0x76
+
+/* The maximum TOP (timeout period) value that can be set in the watchdog. */
+#define DW_WDT_MAX_TOP 15
+
+static struct {
+ spinlock_t lock;
+ void __iomem *regs;
+ struct clk *clk;
+ unsigned long clk_rate;
+ unsigned long in_use;
+} dw_wdt;
+
+static inline int dw_wdt_is_enabled(void)
+{
+ return readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET) &
+ WDOG_CONTROL_REG_WDT_EN_MASK;
+}
+
+static inline int dw_wdt_top_in_seconds(unsigned top)
+{
+ /*
+ * There are 16 possible timeout values in 0..15 where the number of
+ * cycles is 2 ^ (16 + i) and the watchdog counts down.
+ */
+ return (1 << (16 + top)) / dw_wdt.clk_rate;
+}
+
+static int dw_wdt_set_top(unsigned top_s)
+{
+ int i, top_val = -1;
+
+ /*
+ * Iterate over the timeout values until we find the closest match. We
+ * always look for >=.
+ */
+ for (i = 0; i <= DW_WDT_MAX_TOP; ++i)
+ if (dw_wdt_top_in_seconds(i) >= top_s) {
+ top_val = i;
+ break;
+ }
+
+ /*
+ * If we didn't find a suitable value, it must have been too large. Go
+ * with the biggest that we can.
+ */
+ if (top_val < 0)
+ top_val = DW_WDT_MAX_TOP;
+
+ /* Set the new value in the watchdog. */
+ writel(top_val, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+
+ return dw_wdt_top_in_seconds(top_val);
+}
+
+static int dw_wdt_get_top(void)
+{
+ int top = readl(dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET) & 0xF;
+
+ return dw_wdt_top_in_seconds(top);
+}
+
+static void dw_wdt_keepalive(void)
+{
+ writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
+ WDOG_COUNTER_RESTART_REG_OFFSET);
+}
+
+static int dw_wdt_open(struct inode *inode, struct file *filp)
+{
+ if (test_and_set_bit(0, &dw_wdt.in_use))
+ return -EBUSY;
+
+ /* Make sure we don't get unloaded. */
+ __module_get(THIS_MODULE);
+
+ spin_lock(&dw_wdt.lock);
+ if (!dw_wdt_is_enabled()) {
+ /*
+ * The watchdog is not currently enabled. Set the timeout to
+ * the maximum and then start it.
+ */
+ dw_wdt_set_top(DW_WDT_MAX_TOP);
+ writel(WDOG_CONTROL_REG_WDT_EN_MASK,
+ dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
+ }
+ spin_unlock(&dw_wdt.lock);
+
+ return nonseekable_open(inode, filp);
+}
+
+ssize_t dw_wdt_write(struct file *filp, const char __user *buf, size_t len,
+ loff_t *offset)
+{
+ dw_wdt_keepalive();
+
+ return len;
+}
+
+static u32 dw_wdt_time_left(void)
+{
+ return readl(dw_wdt.regs + WDOG_CURRENT_COUNT_REG_OFFSET) /
+ dw_wdt.clk_rate;
+}
+
+static const struct watchdog_info dw_wdt_ident = {
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+ .identity = "Synopsys DesignWare Watchdog",
+};
+
+static long dw_wdt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ unsigned long val;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user((struct watchdog_info *)arg, &dw_wdt_ident,
+ sizeof(dw_wdt_ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int *)arg);
+
+ case WDIOC_KEEPALIVE:
+ dw_wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+ return put_user(dw_wdt_set_top(val), (int __user *)arg);
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(dw_wdt_get_top(), (int __user *)arg);
+
+ case WDIOC_GETTIMELEFT:
+ /* Get the time left until expiry. */
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+ return put_user(dw_wdt_time_left(), (int __user *)arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static int dw_wdt_release(struct inode *inode, struct file *filp)
+{
+ pr_crit("WATCHDOG: device closed - timer will not stop\n");
+
+ clear_bit(0, &dw_wdt.in_use);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int dw_wdt_suspend(struct device *dev)
+{
+ clk_disable(dw_wdt.clk);
+
+ return 0;
+}
+
+static int dw_wdt_resume(struct device *dev)
+{
+ int err = clk_enable(dw_wdt.clk);
+
+ if (err)
+ return err;
+
+ dw_wdt_keepalive();
+
+ return 0;
+}
+
+static const struct dev_pm_ops dw_wdt_pm_ops = {
+ .suspend = dw_wdt_suspend,
+ .resume = dw_wdt_resume,
+};
+#endif /* CONFIG_PM */
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = dw_wdt_open,
+ .write = dw_wdt_write,
+ .unlocked_ioctl = dw_wdt_ioctl,
+ .release = dw_wdt_release
+};
+
+static struct miscdevice dw_wdt_miscdev = {
+ .fops = &wdt_fops,
+ .name = "watchdog",
+ .minor = WATCHDOG_MINOR,
+};
+
+static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct dw_wdt_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!mem)
+ return -EINVAL;
+
+ if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+ "dw_wdt"))
+ return -ENOMEM;
+
+ dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start,
+ resource_size(mem));
+ if (!dw_wdt.regs)
+ return -ENOMEM;
+
+ dw_wdt.clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(dw_wdt.clk))
+ return -ENODEV;
+
+ ret = clk_enable(dw_wdt.clk);
+ if (ret)
+ goto out_put_clk;
+
+ /*
+ * The timeout period of the watchdog is derived from the input clock
+ * frequency. For platforms that don't have a clk for the watchdog,
+ * they can specify the WDT clock rate through the clk_rate field of
+ * the struct dw_wdt_platform_data platform data.
+ */
+ if (pdata && pdata->clk_rate > 0)
+ dw_wdt.clk_rate = pdata->clk_rate;
+ else
+ dw_wdt.clk_rate = clk_get_rate(dw_wdt.clk);
+
+ if (!dw_wdt.clk_rate) {
+ dev_err(&pdev->dev, "no clk rate defined for watchdog, cannot enable\n");
+ ret = -EINVAL;
+ goto out_disable_clk;
+ }
+
+ spin_lock_init(&dw_wdt.lock);
+
+ ret = misc_register(&dw_wdt_miscdev);
+ if (ret)
+ goto out_put_clk;
+
+ return 0;
+
+out_disable_clk:
+ clk_disable(dw_wdt.clk);
+out_put_clk:
+ clk_put(dw_wdt.clk);
+
+ return ret;
+}
+
+static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
+{
+ misc_deregister(&dw_wdt_miscdev);
+
+ clk_disable(dw_wdt.clk);
+ clk_put(dw_wdt.clk);
+
+ return 0;
+}
+
+static struct platform_driver dw_wdt_driver = {
+ .probe = dw_wdt_drv_probe,
+ .remove = __devexit_p(dw_wdt_drv_remove),
+ .driver = {
+ .name = "dw_wdt",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &dw_wdt_pm_ops,
+#endif /* CONFIG_PM */
+ },
+};
+
+static int __init dw_wdt_watchdog_init(void)
+{
+ return platform_driver_register(&dw_wdt_driver);
+}
+module_init(dw_wdt_watchdog_init);
+
+static void __exit dw_wdt_watchdog_exit(void)
+{
+ platform_driver_unregister(&dw_wdt_driver);
+}
+module_exit(dw_wdt_watchdog_exit);
+
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/dw_wdt.h b/include/linux/platform_data/dw_wdt.h
new file mode 100644
index 0000000..0af10ef
--- /dev/null
+++ b/include/linux/platform_data/dw_wdt.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Picochip Ltd., Jamie Iles
+ * http://www.picochip.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This file implements a driver for the Synopsys DesignWare watchdog device
+ * in the many ARM subsystems. The watchdog has 16 different timeout periods
+ * and these are a function of the input clock frequency.
+ */
+#ifndef __DW_WDT_H__
+#define __DW_WDT_H__
+
+/**
+ * struct dw_wdt_platform_data - DesignWare WDT platform data
+ *
+ * @clk_rate: The frequency (HZ) at which the watchdog is driven. The timeout
+ * periods are derived from this frequency.
+ */
+struct dw_wdt_platform_data {
+ unsigned long clk_rate;
+};
+
+#endif /* __DW_WDT_H__ */
--
1.7.3.4
^ permalink raw reply related
* I2C support for CE4100, v3
From: Sebastian Andrzej Siewior @ 2011-01-07 11:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110105215159.GU817@trinity.fluff.org>
* Ben Dooks | 2011-01-05 21:51:59 [+0000]:
>> Sebastian Andrzej Siewior (6):
>> i2c/pxa: use dynamic register layout
>> arm/pxa2xx: reorganize I2C files
>> i2c/pxa2xx: Add PCI support for PXA I2C controller
>> i2c/pxa2xx: add support for shared IRQ handler
>> i2c/pxa2xx: check timeout correctly
>> i2c/pxa2xx: pass of_node from platform driver to adapter and publish
>
>please rename these i2c-pxa2xx
>and for the ARM, use ARM: pxa2xx as the prefix
>
Done
Sebastian
^ permalink raw reply
* [PATCH v2 2/5] omap2plus: prm: Trvial build break fix for undefined reference to 'omap2_prm_read_mod_reg'
From: Santosh Shilimkar @ 2011-01-07 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1101061056340.22048@utopia.booyaka.com>
> -----Original Message-----
> From: Paul Walmsley [mailto:paul at pwsan.com]
> Sent: Thursday, January 06, 2011 11:28 PM
Kevin,
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; khilman at ti.com; tony at atomide.com;
> linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH v2 2/5] omap2plus: prm: Trvial build break fix
> for undefined reference to 'omap2_prm_read_mod_reg'
>
> Hi Santosh
>
[.....]
>
> I think it would be best to use WARN() on these, rather than
> WARN_ONCE().
> That's because these could be called from different parts of the
> code
> base, and the stack backtrace will help someone figure out all the
> code
> that needs to be fixed.
>
> Once you do that, this patch is
>
> Acked-by: Paul Walmsley <paul@pwsan.com>
>
>
With WARN() instead of WARN_ONCE() and Paul's ack, here
is an updated patch.
^ permalink raw reply
* [PATCH 1/1] arm: omap: gpio: define .disable callback for gpio irq chip
From: Russell King - ARM Linux @ 2011-01-07 10:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110107095609.GC6137@besouro.research.nokia.com>
On Fri, Jan 07, 2011 at 11:56:09AM +0200, Eduardo Valentin wrote:
> It is in wakeup-enable gpio. But the driver removes the wakeup
> flag from the gpio on its suspend function right after disabling the irq.
> disable_irq(gpio_irq);
> disable_irq_wake(gpio_irq);
>
> In this case, the device uses gpio 61 as its irq line.
I think the solution to this is to have genirq synchronize the hardware
state with the lazy state on suspend transitions rather than trying to
fix this on a case-by-case basis.
^ permalink raw reply
* Memory sharing issue by application on V4L2 based device driver with system mmu.
From: daeinki @ 2011-01-07 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294390465.6019.212.camel@thor.local>
Michel D?nzer ? ?:
> On Fre, 2011-01-07 at 11:17 +0900, InKi Dae wrote:
>> thank you for your comments.
>>
>> your second comment has no any problem as I said before, user virtual
>> addess could be translated in page unit. but the problem, as you said,
>> is that when cpu access to the memory in user mode, the memory
>> allocated by malloc, page fault occurs so we can't find pfn to user
>> virtual address. I missed that. but I think we could resolve this one.
>>
>> as before, user application allocates memory through malloc function
>> and then send it to device driver(using userptr feature). if the pfn
>> is null when device driver translated user virtual address in page
>> unit then it allocates phsical memory in page unit using some
>> interface such as alloc_page() and then mapping them. when pfn is
>> null, to check it and allocate physical memory in page unit could be
>> processed by videobuf2.
>>
>> of course, videobuf2 has no any duty considered for system mmu. so
>> videobuf2 just provides callback for 3rd party and any platform with
>> system mmu such as Samsung SoC C210 implements the function(allocating
>> physical memory and mapping it) and registers it to callback of
>> videobuf2. by doing so, I think your first comment could be cleared.
>
> FWIW, TTM (drivers/gpu/drm/ttm, include/drm/ttm) is designed and used
> for managing memory between CPU/GPU and kernel/userspace access. I
> haven't looked at your requirements in detail, but if you haven't looked
> at TTM yet, it sounds like it might be worth a look.
>
>
Thank you for your advice. I would look at TTM driver.
^ permalink raw reply
* [patch 1/1] mx51: add support for pwm
From: Uwe Kleine-König @ 2011-01-07 9:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTin7U0+sJ+Xz7BiJ2NbtiGXsyQbdVKejU9M5qrUp@mail.gmail.com>
Hello Jason,
On Fri, Jan 07, 2011 at 05:30:28PM +0800, Jason Liu wrote:
> 2011/1/7 Arnaud Patard <arnaud.patard@rtp-net.org>:
> > This patch is adding support for pwm1 and pwm2 devices found
> > on mx51.
> > [ this patch has been tested with pwm-backlight driver ]
> >
> > Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
> > Index: linux-2.6-submit/arch/arm/mach-mx5/clock-mx51-mx53.c
> > ===================================================================
> > --- linux-2.6-submit.orig/arch/arm/mach-mx5/clock-mx51-mx53.c ? 2011-01-04 11:36:15.000000000 +0100
> > +++ linux-2.6-submit/arch/arm/mach-mx5/clock-mx51-mx53.c ? ? ? ?2011-01-04 11:39:55.000000000 +0100
> > @@ -1206,6 +1206,11 @@
> > ?DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
> > ? ? ? ?NULL, ?NULL, &ipg_clk, &gpt_ipg_clk);
> >
> > +DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
> > + ? ? ? NULL, NULL, &ipg_clk, NULL);
> > +DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
> > + ? ? ? NULL, NULL, &ipg_clk, NULL);
> > +
> > ?/* I2C */
> > ?DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
> > ? ? ? ?NULL, NULL, &ipg_clk, NULL);
> > @@ -1298,6 +1303,8 @@
> > ? ? ? ?_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
> > ? ? ? ?_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
> > ? ? ? ?_REGISTER_CLOCK("fec.0", NULL, fec_clk)
> > + ? ? ? _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
> > + ? ? ? _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
> > ? ? ? ?_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
> > ? ? ? ?_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
> > ? ? ? ?_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
> > Index: linux-2.6-submit/arch/arm/mach-mx5/devices.c
> > ===================================================================
> > --- linux-2.6-submit.orig/arch/arm/mach-mx5/devices.c ? 2011-01-04 11:11:43.000000000 +0100
> > +++ linux-2.6-submit/arch/arm/mach-mx5/devices.c ? ? ? ?2011-01-04 11:39:55.000000000 +0100
> > @@ -120,6 +120,44 @@
> > ? ? ? ?},
> > ?};
> [...]
> > +struct platform_device mxc_pwm2_device = {
> > + ? ? ? .name = "mxc_pwm",
> > + ? ? ? .id = 1,
> > + ? ? ? .num_resources = ARRAY_SIZE(pwm2_resources),
> > + ? ? ? .resource = pwm2_resources,
> > +};
> > +
>
> Why not follow the arch/arm/plat-mxc/devices/platform-imx-xxx to add
> devices support?
good question. Note that arch/arm/plat-mxc/devices/platform-mxc_pwm.c
already exists in Sascha's tree. (Maybe now even Linus'.)
> I saw that some devices was added in arch/arm/mach-mx5/devices.c, but
> most are in
> arch/arm/plat-mxc/devices/xx, what's the rule for it when we add
> device support?
devices.c was used traditionally and isn't yet completely converted.
Mostly due to lack of time for such things.
So I'd say: for new things use the dynamic stuff in
arch/arm/plat-mxc/devices and if you're motivated help converting the
existing devices to it, too.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH 1/1] arm: omap: gpio: define .disable callback for gpio irq chip
From: Eduardo Valentin @ 2011-01-07 9:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <878vyxx697.fsf@ti.com>
Hello Kevin,
On Thu, Jan 06, 2011 at 09:59:48AM -0800, ext Kevin Hilman wrote:
> Eduardo Valentin <eduardo.valentin@nokia.com> writes:
>
> > On Wed, Jan 05, 2011 at 03:22:51PM -0800, ext Kevin Hilman wrote:
> >> Eduardo Valentin <eduardo.valentin@nokia.com> writes:
> >>
> >> > Hello Russell,
> >> >
> >> > On Wed, Jan 05, 2011 at 06:19:18PM +0000, Russell King wrote:
> >> >> On Wed, Jan 05, 2011 at 07:58:03PM +0200, Eduardo Valentin wrote:
> >> >> > Currently, if one calls disable_irq(gpio_irq), the irq
> >> >> > won't get disabled.
> >> >> >
> >> >> > This is happening because the omap gpio code defines only
> >> >> > a .mask callback. And the default_disable function is just
> >> >> > a stub. The result is that, when someone calls disable_irq
> >> >> > for an irq in a gpio line, it will be kept enabled.
> >> >> >
> >> >> > This patch solves this issue by setting the .disable
> >> >> > callback to point to the same .mask callback.
> >> >>
> >> >> Amd this is a problem because?
> >> >
> >> > errr.. because the interrupt is enabled when it was supposed to be disabled?
> >> >
> >>
> >> As Russell pointed out, it's not actually "supposed" to be.
> >>
> >> With lazy disable, what disable_irq() does is prevent the *handler* from
> >> ever being called. If another interrupt arrives, it will be caught by
> >> the genirq core, marked as IRQ_PENDING and then masked. This "don't
> >> disable unless we really have to" is the desired behavior of the lazy
> >> disable feature.
> >
> > Right. I'm convinced that the handler won't be called because of the lazy
> > disable mechanism.
> >
> >>
> >> >>
> >> >> The way this works is that although it isn't disabled at that point,
> >> >> if it never triggers, then everything remains happy. However, if it
> >> >> does trigger, the genirq code will then mask the interrupt and won't
> >> >> call the handler.
> >> >
> >> > Right.. I didn't see from this point. I will check how that gets unmasked.
> >> > But even so, if I understood correctly what you described, it would still
> >> > open a time window which the system would see at least 1 interrupt during
> >> > the time it was not suppose to. And that can wakeup a system which is in
> >> > deep sleep mode, either via dynamic idle or static suspend.
> >> >
> >> > It is unlikely, I know. But it can still happen. And can be avoided.
> >>
> >> If the GPIO is configured as a wakeup source, then wouldn't you want
> >> activity on that GPIO to wake up the system?
> >
> > Yes I would want it.. of course, if the interrupt is enabled though..
> >
> > I'm still trying to find a valid situation where someone disables an irq
> > but still wants its activity to be a wakeup source. I couldn't find so far..
> >
> >
> >>
> >> If you don't want wakeups on that GPIO, then the driver should probably
> >> be using disable_irq_wake().
> >
> > Yes. Let's take this situation. Let's assume a driver, at its suspend callback,
> > explicitly reports to the system that its irq can be disabled and also should
> > not be seen as a wakeup source, by calling disable_irq(gpio_irq) and
> > disable_irq_wake(gpio_irq).
> >
> > What should be the expected system behavior when the user says echo mem > /sys/power/state?
> >
> > From the point we are done with devices suspend, that gpio will still
> > be marked as an irq, at the bank level. But its corresponding pad will
> > have its wakeup bit disabled. Would that work? I think yes, in most cases.
> >
> > Now let's take the WFI instruction as a divisor for 2 situations:
> >
> > A - common / working case: an interrupt on that gpio still happens after the WFI instruction.
> > Since the system is in sleep mode and the pad for that gpio is not wakeup
> > capable, then nothing would happen and the system won't wakeup. Then, I think
> > everyone is happy here.
> >
> > B - corner case: an interrupt on that gpio happens before the WFI instruction.
> > Since the system is active, the gpio bank can still report this interrupt
> > and will do it. The suspend won't happen due to a irq which has been
> > explicitly marked as disabled and wakeup incapable.
> > Then, would that be the expected behavior? Assuming that the driver
> > has explicitly said to the system, you should not bother about this at all.
>
> Well, expected behaviour would be that GPIO bank should not be reporting
> the this interrupt at all since it has been disabled.
>
> However, since you're asking, I assume that you're not seeing this
> expected behavior.
Yeah that's right. But it is rather difficult to reproduce.
>
> Ignoring wakeups for a second, if this corner case happens on a
> non-wakeup capable GPIO using lazy disable, I would not expect suspend
> to be prevented. The genirq core would see the IRQ, mark it as
> IRQ_PENDING, mask it and return. and suspend should continue.
True.
>
> hmm... however, if the IRQ happens after interrupts are disabled, the
> genirq core won't handle it, and our PM core will see a pending
> interrupt and abort idle/suspend.
True again. And that's what think it is happening.
>
> Are you seeing this corner case for a wakeup-enable GPIO or a non
> wakeup-enabled GPIO?
It is in wakeup-enable gpio. But the driver removes the wakeup
flag from the gpio on its suspend function right after disabling the irq.
disable_irq(gpio_irq);
disable_irq_wake(gpio_irq);
In this case, the device uses gpio 61 as its irq line.
>
> /me looks at code
>
> I'm assuming now it's for a wakeup-enabled GPIO.
Right..
>
> Another more likely possibility is that the IRQ arrives between the time
> the driver does its disable_irq_wake() and when the GPIO driver actually
> suspends. We currently defer disalbing the bank-level IRQ wakeup
> capabilities until the suspend method of the GPIO driver is run (which
> is very late in the suspend cycle, since it is a sysdev.) Thinking
> about this some more, I'm not sure exactly why we do this. The current
> code seems to only manage GPIO wakeups for suspend/resume but not for
> idle, so it defers the actual register writes until the suspend hook.
> Since we presumably also want wakeup-enabled GPIOs to wake up from idle,
> we probably shouldn't be deferring the wakeup enable/disable.
I'm not sure if this is related to wakeup at all. Problem that I see
is that the suspend is aborted due to an interrupt. And that interrupt
has been disabled and marked as non-wakeup in the previous device suspend step.
I've checked that by verifying the gpio bank irqenable1 register and the
pad conf for the gpio in use, right before entering omap_sram_idle in the suspend path.
[ 10.360321] GPIO BANK2 - 0x0 0x60200800
[ 10.360321] GPIO61 PAD conf 0x11C
The line starting with GPIO BANK2 tells me that GPIO_IRQSTATUS1 is 0x0 at
that point. And GPIO_IRQENABLE1 is 0x60200800. Meaning, channel of GPIO 61
is still enabled at that point. The second line tells me that wakeup bit
for GPIO61 is off. And of course, the suspend fails when we have a match
of IRQSTATUS1 with IRQENABLE1, in this case for GPIO 61, which is my trigger here.
But on this specific printing I didn't see the issue. However, just the
fact that we reach this point with GPIO bank still seeing the IRQ for GPIO 61
enabled is already an indication that something is asking for failure.
So, that's the problematic situation. The gpio is still seen as an interrupt,
although it has been set to be disabled.
The wakeup is not an issue here I'd say. Mainly because the system is still
active, in the process to enter sleep, so no need to wakeup in order to see
that interrupt coming from bank2.
After applying the patch I sent here, I see then the interrupts getting disabled
by the time we are entering the omap_sram_idle.
[ 13.671142] GPIO BANK2 - 0x0 0x0
[ 13.671142] GPIO61 PAD conf 0x11C
The fact that no interrupts are enabled after this patch points that
not only gpio 61 could be triggering the suspend failure. I still
couldn't reproduce it on dynamic idle, but I can imagine that it
is actually possible to reach this issue also in dyn. idle.
>
> Here's an expirement. If you have a use case that is
> preventing a suspend in this corner case, let's try to immediately
> enable/disable wakeups instead of waiting for the suspend/resume hooks.
>
> Below is a test patch only briefly tested on Zoom3 which has it's
> network interface on a GPIO IRQ. It does not have wakeups enabled, and
> under ping flood from a host (ping -f), it suspended just fine. I added
> an enable_irq_wake() the driver and it was still able to suspend during
> ping flood.
>
> If you suspect the above might be happening in your corner case, can you
> give this a try to see if it changes?
Yes sure. I will try to test that, even though I still think the wakeups are
not the problem. And another issue is that, as you probably have noticed,
it is a very rare situation. Since it's rather difficult to reproduce I might
take some time to give you some feedback here.
>
> It's also worth noting that we are currently not managing IO pad wakeups
> in the GPIO core. We are only mananging GPIO module level wakeups,
> which only are in effect if CORE is active. Now that we have a mux
> framework that can probably handle this, we need a mapping of GPIO lines
> to pads so we can also manage IO pad level wakeups from the GPIO core
> code. However, if your corner case is arriving before WFI, than I
> suspect CORE is active, and module level wakeups is what you're running into.
>
> Kevin
>
> commit 3af8a1051a44462c62c5a5d47a8256626e32fbba
> Author: Kevin Hilman <khilman@ti.com>
> Date: Thu Jan 6 09:45:24 2011 -0800
>
> GPIO: enable/disable wakeups immediately
>
> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
> index ccf2660..1418423 100644
> --- a/arch/arm/plat-omap/gpio.c
> +++ b/arch/arm/plat-omap/gpio.c
> @@ -977,34 +977,39 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
> static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
> {
> unsigned long uninitialized_var(flags);
> + void __iomem *wake_status;
> + void __iomem *wake_clear;
> + void __iomem *wake_set;
> +
> + printk("KJH: %s: bank IRQ %d, GPIO %d enable=%d\n", __func__,
> + bank->irq, gpio, enable);
>
> switch (bank->method) {
> #ifdef CONFIG_ARCH_OMAP16XX
> case METHOD_MPUIO:
> case METHOD_GPIO_1610:
> - spin_lock_irqsave(&bank->lock, flags);
> - if (enable)
> - bank->suspend_wakeup |= (1 << gpio);
> - else
> - bank->suspend_wakeup &= ~(1 << gpio);
> - spin_unlock_irqrestore(&bank->lock, flags);
> + wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
> + wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
> + wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
> return 0;
> #endif
> #ifdef CONFIG_ARCH_OMAP2PLUS
> case METHOD_GPIO_24XX:
> - case METHOD_GPIO_44XX:
> + wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
> + wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
> + wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
> +
> if (bank->non_wakeup_gpios & (1 << gpio)) {
> printk(KERN_ERR "Unable to modify wakeup on "
> "non-wakeup GPIO%d\n",
> (bank - gpio_bank) * 32 + gpio);
> return -EINVAL;
> }
> - spin_lock_irqsave(&bank->lock, flags);
> - if (enable)
> - bank->suspend_wakeup |= (1 << gpio);
> - else
> - bank->suspend_wakeup &= ~(1 << gpio);
> - spin_unlock_irqrestore(&bank->lock, flags);
> + break;
> + case METHOD_GPIO_44XX:
> + wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
> + wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
> + wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
> return 0;
> #endif
> default:
> @@ -1012,6 +1017,16 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
> bank->method);
> return -EINVAL;
> }
> +
> + spin_lock_irqsave(&bank->lock, flags);
> + if (enable)
> + __raw_writel((1 << gpio), wake_set);
> + else
> + __raw_writel((1 << gpio), wake_clear);
> +
> + spin_unlock_irqrestore(&bank->lock, flags);
> +
> + return 0;
> }
>
> static void _reset_gpio(struct gpio_bank *bank, int gpio)
> @@ -1755,105 +1770,9 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
> }
>
> #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
> -static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
> -{
> - int i;
> -
> - if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
> - return 0;
> -
> - for (i = 0; i < gpio_bank_count; i++) {
> - struct gpio_bank *bank = &gpio_bank[i];
> - void __iomem *wake_status;
> - void __iomem *wake_clear;
> - void __iomem *wake_set;
> - unsigned long flags;
> -
> - switch (bank->method) {
> -#ifdef CONFIG_ARCH_OMAP16XX
> - case METHOD_GPIO_1610:
> - wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
> - wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
> - wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
> - break;
> -#endif
> -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
> - case METHOD_GPIO_24XX:
> - wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
> - wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
> - wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
> - break;
> -#endif
> -#ifdef CONFIG_ARCH_OMAP4
> - case METHOD_GPIO_44XX:
> - wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
> - wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
> - wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
> - break;
> -#endif
> - default:
> - continue;
> - }
> -
> - spin_lock_irqsave(&bank->lock, flags);
> - bank->saved_wakeup = __raw_readl(wake_status);
> - __raw_writel(0xffffffff, wake_clear);
> - __raw_writel(bank->suspend_wakeup, wake_set);
> - spin_unlock_irqrestore(&bank->lock, flags);
> - }
> -
> - return 0;
> -}
> -
> -static int omap_gpio_resume(struct sys_device *dev)
> -{
> - int i;
> -
> - if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
> - return 0;
> -
> - for (i = 0; i < gpio_bank_count; i++) {
> - struct gpio_bank *bank = &gpio_bank[i];
> - void __iomem *wake_clear;
> - void __iomem *wake_set;
> - unsigned long flags;
> -
> - switch (bank->method) {
> -#ifdef CONFIG_ARCH_OMAP16XX
> - case METHOD_GPIO_1610:
> - wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
> - wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
> - break;
> -#endif
> -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
> - case METHOD_GPIO_24XX:
> - wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
> - wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
> - break;
> -#endif
> -#ifdef CONFIG_ARCH_OMAP4
> - case METHOD_GPIO_44XX:
> - wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
> - wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
> - break;
> -#endif
> - default:
> - continue;
> - }
> -
> - spin_lock_irqsave(&bank->lock, flags);
> - __raw_writel(0xffffffff, wake_clear);
> - __raw_writel(bank->saved_wakeup, wake_set);
> - spin_unlock_irqrestore(&bank->lock, flags);
> - }
> -
> - return 0;
> -}
>
> static struct sysdev_class omap_gpio_sysclass = {
> .name = "gpio",
> - .suspend = omap_gpio_suspend,
> - .resume = omap_gpio_resume,
> };
>
> static struct sys_device omap_gpio_device = {
--
Eduardo Valentin
^ permalink raw reply
* [PATCH 0/2] Common struct clk implementation, v10
From: Uwe Kleine-König @ 2011-01-07 9:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D266D6C.7050005@fluff.org>
Hi Ben,
On Fri, Jan 07, 2011 at 01:33:32AM +0000, Ben Dooks wrote:
> On 05/01/11 03:51, Jeremy Kerr wrote:
> > Hi all,
> >
> > These patches are an attempt to allow platforms to share clock code. At
> > present, the definitions of 'struct clk' are local to platform code,
> > which makes allocating and initialising cross-platform clock sources
> > difficult, and makes it impossible to compile a single image containing
> > support for two ARM platforms with different struct clks.
>
> no, it doesn't actually. you could do run-time link and select
> the right arch support.
does that mean you're against the patch set?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v3 05/10] net/fec: add dual fec support for mx28
From: Uwe Kleine-König @ 2011-01-07 9:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110107070056.GA28358@freescale.com>
Hello,
On Fri, Jan 07, 2011 at 03:00:57PM +0800, Shawn Guo wrote:
> On Thu, Jan 06, 2011 at 08:10:47AM +0100, Uwe Kleine-K?nig wrote:
> > Hello Shawn,
> >
> [...]
> > > > > + /*
> > > > > + * enet-mac reset will reset mac address registers too,
> > > > > + * so need to reconfigure it.
> > > > > + */
> > > > > + if (fec_is_enetmac) {
> > > > > + memcpy(&temp_mac, dev->dev_addr, ETH_ALEN);
> > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > > > + writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
> > > > > + writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
> > > > where is the value saved to temp_mac[]? For me it looks you write
> > > > uninitialized data into the mac registers.
> > >
> > > memcpy above.
> > oops. right. I looked for something like
> >
> > temp_mac[0] = dev->dev_addr[0] << $shiftfor0 | ...
> >
> > which AFAIK is what you want here. memcpy is sensible to (at least)
> > endian issues. If you ask me factor out the setting of the mac address
> > in probe to a function and use that here, too.
> >
> The memcpy of mac address is being widely used in fec and other
> network drivers, and I do not prefer to change something so common
> in this patch set.
Hmm, fec_get_mac uses memcpy as does fec_set_mac_address.
fec_enet_init uses mask and shift. When writing my comment I only saw
the latter. Having that uniform and only in two places (one for setting
and for reading) would be great.
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH 1/2] Add a common struct clk
From: Uwe Kleine-König @ 2011-01-07 9:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110107003205.GL31708@n2100.arm.linux.org.uk>
Hello Russell,
On Fri, Jan 07, 2011 at 12:32:05AM +0000, Russell King - ARM Linux wrote:
> On Fri, Jan 07, 2011 at 08:10:20AM +0800, Jeremy Kerr wrote:
> > Hi Richard,
> >
> > > > > +struct clk {
> > > > > + const struct clk_ops *ops;
> > > > > + unsigned int enable_count;
> > > > > + int flags;
> > > > > + union {
> > > > > + struct mutex mutex;
> > > > > + spinlock_t spinlock;
> > > > > + } lock;
> > > > > +};
> > > >
> > > > Here you have a "polymorphic" lock, where the clock instance knows
> > > > which type it is supposed to be. I got flak from David Miller and
> > > >
> > > > others trying to do the same thing with the mdio_bus:
> > > > http://kerneltrap.org/mailarchive/linux-netdev/2010/7/6/6280618
> > > >
> > > > The criticism, applied to your case, is that the clk_enable() caller
> > > > cannot know whether it is safe to make the call or not. I was told,
> > > > "there has got to be a better way."
> > >
> > > Note that this is not "new". Currently there is no convention available
> > > if clk_enable sleeps or not. See e.g.
> > > http://thread.gmane.org/gmane.linux.ports.arm.kernel/100744
> >
> > As Uwe says, the common clock does not change these semantics; I would prefer
> > to keep the driver API changes at a minimum with these patches.
> >
> > But yes, it would be a good idea to:
> >
> > * introduce clk_enable_atomic, which requires clk->flags & CLK_ATOMIC
> >
> > * add might_sleep to clk_enable(), encouraging clk uses in atomic contexts
> > to switch to clk_enable_atomic.
> >
> > We'd still be able to handle CLK_ATOMIC clocks in clk_enable(), so the
> > enforcement only needs to be one-way.
>
> I think the atomic stuff should be the norm through and through - otherwise
> we're going to end up with problems in drivers where they use the _atomic()
> stuff, but the clocks behind are coded to sleep.
>
> I hate the GPIO APIs for doing this _cansleep crap as the decision of
> whether to use the _cansleep or normal APIs normally can't be made at
> the time when the API is used, but sometime later. Many people just use
> the non-_cansleep versions irrespective of the context they're in -
> which is unnecessarily restrictive - consider what happens if you then
> have that driver use a GPIO on an I2C peripheral...
I'd prefer it the other way around, too. (That is an atomic
gpio_set_value_atomic and a sleeping gpio_set_value.) So if someone
uses the wrong one it's more likely that (s)he notices it. Other than
that I agree that not having to do this would be preferable.
When applying the clk_enable_atomic stuff to the amba-pl011 driver (see
link above), I would just get a different error (clk_enable_atomic would
return -ESOMETHING instead of a backtrace about sleeping in atomic
context). Hmm, not very useful.
On the other hand fixing the clk API to the sleeping or non-sleeping
approach has disadvantages, too:
- sleeping
doesn't allow enabling a clk in atomic context which (e.g. in the
case of amba-pl011) provides maximal power saving.
- atomic
some clocks need long to become enabled, so long critical sections
are introduced
Having a maxtracer for the clk_enable/disable functions would be great
to get some numbers. I volunteer to try to add something like that to
the common clk thing when it is merged. (Yes, I still think that
merging Jeremy's patches for .38 is good.)
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH V3 42/63] ST SPEAr: replace readl, writel with __raw_readl, __raw_writel in uncompress.h
From: stanley.miao @ 2011-01-07 9:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110107091720.GM31708@n2100.arm.linux.org.uk>
Russell King - ARM Linux wrote:
> On Fri, Jan 07, 2011 at 10:26:25AM +0800, stanley.miao wrote:
>
>> Viresh Kumar wrote:
>>
>>> readl also calls outer cache maintainance operations
>>>
>> I use readl here on spear13xx. It works fine.
>> This is the definition of readl, could you tell me which code calls
>> outer cache maintainance ?
>>
>> #define readl(c) ({ __u32 __v = le32_to_cpu((__force __le32) \
>> __raw_readl(__mem_pci(c))); __v; })
>>
>
> #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
>
> is how it's now defined, and __iormb() is defined to be rmb() on ARMv7+,
> which translates to a dmb.
>
> writel() on the other hand is less straight forward. It uses __iowmb()
> which translates to a wmb() on ARMv7+, which is a dsb and an outer cache
> sync operation. This will fail in the decompressor code as there's no
> outer cache support there.
>
>
Hi, Russell, Thanks for your patient explanation.
With this in mind, I think readl_relaxed() should be better here.
Stanley.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110107/26ec7e42/attachment-0001.html>
^ permalink raw reply
* Last nights ARM pull
From: Russell King - ARM Linux @ 2011-01-07 9:32 UTC (permalink / raw)
To: linux-arm-kernel
Feedback from Linus on last nights pull of ARM bits:
| So I pulled and just looked them up, but in general things like the
| drivers/usb/host/ehci-hcd.c changes that aren't obviously to some
| ARM-only file is something I end up just wanting to know more about,
| so if you can note those parts that would help.
As most of these were stuff in devel-stable which came from other git
trees, can other git tree people please ensure that as much driver stuff
as possible goes through the relevant subsystem tree.
Thanks.
^ permalink raw reply
* [PATCH 0/2] ARM: Gemini: add RTC support for Gemini SoC
From: Russell King - ARM Linux @ 2011-01-07 9:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1292339307-14336-1-git-send-email-ulli.kroll@googlemail.com>
On Tue, Dec 14, 2010 at 04:08:25PM +0100, Hans Ulli Kroll wrote:
> This patch adds the driver for the rtc chip on the Gemini SoC
I'll take patch 2, but not patch 1. There is no requirement for patch 1
to come via my tree - it can be handled by the RTC people.
My tree is not for random driver code being merged into mainline just
because it's used on some ARM platform somewhere.
(I'm making this request as a result of feedback from Linus on last nights
merge of the ARM tree.)
Thanks.
^ permalink raw reply
* [patch 1/1] mx51: add support for pwm
From: Jason Liu @ 2011-01-07 9:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110107090656.517403682@rtp-net.org>
Hi, Arnaud,
2011/1/7 Arnaud Patard <arnaud.patard@rtp-net.org>:
> This patch is adding support for pwm1 and pwm2 devices found
> on mx51.
> [ this patch has been tested with pwm-backlight driver ]
>
> Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
> Index: linux-2.6-submit/arch/arm/mach-mx5/clock-mx51-mx53.c
> ===================================================================
> --- linux-2.6-submit.orig/arch/arm/mach-mx5/clock-mx51-mx53.c ? 2011-01-04 11:36:15.000000000 +0100
> +++ linux-2.6-submit/arch/arm/mach-mx5/clock-mx51-mx53.c ? ? ? ?2011-01-04 11:39:55.000000000 +0100
> @@ -1206,6 +1206,11 @@
> ?DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
> ? ? ? ?NULL, ?NULL, &ipg_clk, &gpt_ipg_clk);
>
> +DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
> + ? ? ? NULL, NULL, &ipg_clk, NULL);
> +DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
> + ? ? ? NULL, NULL, &ipg_clk, NULL);
> +
> ?/* I2C */
> ?DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
> ? ? ? ?NULL, NULL, &ipg_clk, NULL);
> @@ -1298,6 +1303,8 @@
> ? ? ? ?_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
> ? ? ? ?_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
> ? ? ? ?_REGISTER_CLOCK("fec.0", NULL, fec_clk)
> + ? ? ? _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
> + ? ? ? _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
> ? ? ? ?_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
> ? ? ? ?_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
> ? ? ? ?_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
> Index: linux-2.6-submit/arch/arm/mach-mx5/devices.c
> ===================================================================
> --- linux-2.6-submit.orig/arch/arm/mach-mx5/devices.c ? 2011-01-04 11:11:43.000000000 +0100
> +++ linux-2.6-submit/arch/arm/mach-mx5/devices.c ? ? ? ?2011-01-04 11:39:55.000000000 +0100
> @@ -120,6 +120,44 @@
> ? ? ? ?},
> ?};
[...]
> +struct platform_device mxc_pwm2_device = {
> + ? ? ? .name = "mxc_pwm",
> + ? ? ? .id = 1,
> + ? ? ? .num_resources = ARRAY_SIZE(pwm2_resources),
> + ? ? ? .resource = pwm2_resources,
> +};
> +
Why not follow the arch/arm/plat-mxc/devices/platform-imx-xxx to add
devices support?
I saw that some devices was added in arch/arm/mach-mx5/devices.c, but
most are in
arch/arm/plat-mxc/devices/xx, what's the rule for it when we add
device support?
[...]
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
* [PATCH 1/1] arm: mxc: move IOMUX_CONFIG_SION definition to iomux-v3.h
From: Richard Zhao @ 2011-01-07 9:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294311939-15503-1-git-send-email-richard.zhao@freescale.com>
Hi Sascha,
On Thu, Jan 6, 2011 at 7:05 PM, Richard Zhao <richard.zhao@freescale.com> wrote:
> Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
Will you accept this patch?
Thanks
Richard
> ---
> ?arch/arm/plat-mxc/include/mach/iomux-mx53.h | ? ?1 -
> ?arch/arm/plat-mxc/include/mach/iomux-v3.h ? | ? ?1 +
> ?2 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
> index 5deee01..2673007 100644
> --- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
> +++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
> @@ -34,7 +34,6 @@ typedef enum iomux_config {
> ? ? ? ?IOMUX_CONFIG_ALT6,
> ? ? ? ?IOMUX_CONFIG_ALT7,
> ? ? ? ?IOMUX_CONFIG_GPIO, /* added to help user use GPIO mode */
> - ? ? ? IOMUX_CONFIG_SION = 0x1 << 4, /* LOOPBACK:MUX SION bit */
> ?} iomux_pin_cfg_t;
>
> ?/* These 2 defines are for pins that may not have a mux register, but could
> diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
> index 2277b01..82620af 100644
> --- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
> +++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
> @@ -105,6 +105,7 @@ typedef u64 iomux_v3_cfg_t;
> ?#define PAD_CTL_SRE_FAST ? ? ? ? ? ? ? (1 << 0)
> ?#define PAD_CTL_SRE_SLOW ? ? ? ? ? ? ? (0 << 0)
>
> +#define IOMUX_CONFIG_SION ? ? ? ? ? ? ?(0x1 << 4)
>
> ?#define MX51_NUM_GPIO_PORT ? ? 4
>
> --
> 1.6.3.3
>
>
>
^ permalink raw reply
* [PATCH V3 42/63] ST SPEAr: replace readl, writel with __raw_readl, __raw_writel in uncompress.h
From: Russell King - ARM Linux @ 2011-01-07 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D2679D1.3080005@windriver.com>
On Fri, Jan 07, 2011 at 10:26:25AM +0800, stanley.miao wrote:
> Viresh Kumar wrote:
>> readl also calls outer cache maintainance operations
>
> I use readl here on spear13xx. It works fine.
> This is the definition of readl, could you tell me which code calls
> outer cache maintainance ?
>
> #define readl(c) ({ __u32 __v = le32_to_cpu((__force __le32) \
> __raw_readl(__mem_pci(c))); __v; })
#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
is how it's now defined, and __iormb() is defined to be rmb() on ARMv7+,
which translates to a dmb.
writel() on the other hand is less straight forward. It uses __iowmb()
which translates to a wmb() on ARMv7+, which is a dsb and an outer cache
sync operation. This will fail in the decompressor code as there's no
outer cache support there.
^ permalink raw reply
* [patch 1/1] mx51: add support for pwm
From: Arnaud Patard (Rtp) @ 2011-01-07 9:06 UTC (permalink / raw)
To: linux-arm-kernel
An embedded and charset-unspecified text was scrubbed...
Name: mx51_pwm.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110107/2599c43b/attachment.ksh>
^ permalink raw reply
* [patch 2/5] ulpi: handle ULPI_OTG_CTRL_CHRGVBUS
From: Arnaud Patard (Rtp) @ 2011-01-07 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D257553.30101@compulab.co.il>
Hi
Igor Grinberg <grinberg@compulab.co.il> writes:
[...]
> Thanks for the information. Now I am finally getting the picture of what's is
> going on there...
>
>> On the Smartbook at least both USB host ports (H1 and H2) on the board
>> (one port each) are connected directly to 4-port USB hubs (SMSC2514).
>> We don't have anything on there except that connection: the hub should
>> handle VBUS properly. Both ports use an SMSC3317 (just a 3311 with a
>> built in 3.3V supply so the id and behavior should be identical).
>
> OK, so the SMSC331x ulpi transceiver is connected to the SMSC2514 usb hub,
> so all the peripheral devices (ethernet/wifi/bt/hid) are connected to the
> downstream ports of that hub and thus get their Vbus as expected. This is fine.
>
>> On the Smarttop H1 is connected to a 4-port USB hub (Terminus FE1.1)
>> with the same configuration. Same PHY. The DR port is connected
>> directly to an ASIX ethernet controller. VBUS seems routed to a test
>> point.
>>
>> I'm curious exactly what the real problem here is: that VBUS is
>> basically not being handled correctly? It should be driven or not? I'm
>> not entirely familiar with the specification.
>
> SMSC2514 usb hub will not provide power to its D+ and D- pull-up resistors
> until it detects a Vbus enabled on the upstream port. This is totally fine.
>
> SMSC331x ulpi transceiver does not have either an integrated Vbus switch or
> an integrated charge pump - this means that it cannot provide a Vbus to the hub.
>
> The hub in its turn does not power the pull-up resistors and peripheral devices
> are not being connected to the usb subsystem.
>
> With this patch applied, SMSC331x ulpi transceiver issues an SRP pulses on the Vbus
> and hub senses that there is something that looks like Vbus and then enables the
> pull-up resistors -> peripheral devices are being connected to the usb subsystem.
> This behavior violates the ULPI (and mostly certain OTG and may be also USB 2.0)
> specification and SMSC2514 usb hub datasheet.
>
> According to the SMSC2514 usb hub datasheet, VBUS_DET pin has to be connected
> to a valid Vbus from the upstream port, but SMSC331x does not provide this Vbus.
> This means that you should have add a Vbus switch or a charge pump to the
> VBUS_DET pin of the usb hub and provide means (like GPIO) to enable/disable that
> switch or charge pump.
> This is h/w design bug we are dealing with.
>
> The best solution to this would be to add a missing h/w component.
> Now, I understand that it can be kind a problematic ;)
> But, we cannot violate the ULPI spec and the generic driver to workaround
> some h/w problem that is existing in some specific configuration and hopefully will
> be fixed in the next h/w revisions. Therefore, as I said before, this patch is NAK.
>
> What we can do is:
> 1) implement the int (*start_srp)(struct otg_transceiver *otg);
> method as defined by the ULPI spec.
>
> 2) and then add a call (along with huge comment explaining this workaround)
> to otg_start_srp(). I'd recommend to restrict this call to that specific board somehow,
> but it is up to Sascha to decide where to put it.
What about the following patch ?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ulpi_chrgvbus2.patch
Type: text/x-diff
Size: 1867 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110107/dad4f389/attachment-0001.bin>
^ permalink raw reply
* [PATCH 1/1] arm: omap: gpio: define .disable callback for gpio irq chip
From: David Brownell @ 2011-01-07 9:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110105202939.GC8717@n2100.arm.linux.org.uk>
> o lazy-disable state
This is an odd state, and confusion regularly
comes up ... I've never been a fan of having the
imperatively named disable_irq() act like a
disable_irq_at a_random_later_time_ _but_nyet(). If
one must have the latter function, clearer IMO
to name it better and have disable_irq()
do exactly that by the time it returns ... that
is after all what folk expect given its name and conventional interpretation of "disable".
(ergo confusion when that's not what happens)
lazy_disable_irq() would be accurate, butI'm not
sure many folk would choose to use it.
- Dave
^ permalink raw reply
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