* [PATCH V2 2/2] ARM: dts: omap3-ldp: fix mmc configuration
From: Nishanth Menon @ 2014-02-14 5:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392356749-32091-1-git-send-email-nm@ti.com>
MMC1 is the only MMC interface available on the platform. Further,
since the platform is based on older revision of SoC which is not
capable of doing multi-block reads, mark it with compatibility for the
same and add pinmux to ensure that all relevant pins are configured
for non-MMC boot mode.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
Changes since V1:
- fixed commit message as suggested by Balaji.
- update to use new compatible match for the erratum.
V1: https://patchwork.kernel.org/patch/3514881/
arch/arm/boot/dts/omap3-ldp.dts | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm/boot/dts/omap3-ldp.dts b/arch/arm/boot/dts/omap3-ldp.dts
index ddce0d8..0abe986 100644
--- a/arch/arm/boot/dts/omap3-ldp.dts
+++ b/arch/arm/boot/dts/omap3-ldp.dts
@@ -174,8 +174,20 @@
};
&mmc1 {
+ /* See 35xx errata 2.1.1.128 in SPRZ278F */
+ compatible = "ti,omap3-pre-es3-hsmmc";
vmmc-supply = <&vmmc1>;
bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+};
+
+&mmc2 {
+ status="disabled";
+};
+
+&mmc3 {
+ status="disabled";
};
&omap3_pmx_core {
@@ -209,6 +221,17 @@
0x174 (PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */
>;
};
+
+ mmc1_pins: pinmux_mmc1_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.mmc1_clk */
+ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.mmc1_cmd */
+ OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.mmc1_dat0 */
+ OMAP3_CORE1_IOPAD(0x214A, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.mmc1_dat1 */
+ OMAP3_CORE1_IOPAD(0x214C, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.mmc1_dat2 */
+ OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.mmc1_dat3 */
+ >;
+ };
};
&usb_otg_hs {
--
1.7.9.5
^ permalink raw reply related
* [PATCH] mmc: omap_hsmmc: Add support for Erratum 2.1.1.128 in device tree boot
From: Nishanth Menon @ 2014-02-14 5:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140213230554.GI28216@atomide.com>
On 02/13/2014 05:05 PM, Tony Lindgren wrote:
> * Nishanth Menon <nm@ti.com> [140205 06:15]:
>> On Wed 05 Feb 2014 08:10:34 AM CST, Balaji T K wrote:
>>>>>
>>>>> Rather than ti,errata.. specific property, something like
>>>>> caps no/disable multiblock read is more readable in my opinion, Otherwise
>>>>
>>>> Is'nt the better definition to state i have quirk X and allow the
>>>> driver to do the necessary thing/things needed to handle quirk X? in
>>>> this case, there is just one thing to do: broken multi_block_read, in
>>>> the case of other quirks, there might be more than 1 thing to do.. let
>>>> driver figure that out, dts just states the h/w capabilty or in this
>>>> case, the quirk capability.
>>>>
>>>
>>> But in this case there is only one. disable multi block read is more readable
>>> than the errata reference, No strong feelings though.
>>
>> Considering this might set an precedence for other quirk description,
>> I'd like to leave it as it stands.
>
> Hmm if this really depends on the hardware version, how about
> just add new compatible flag ti,omap3430-rev-xyz-hsmmc that
> allows the driver to deal with the errata?
>
yep - that is a very good idea. updated v2 series tested and posted:
http://marc.info/?l=linux-omap&m=139235682727541&w=2
https://patchwork.kernel.org/patch/3650061/
https://patchwork.kernel.org/patch/3650031/
--
Regards,
Nishanth Menon
^ permalink raw reply
* [PATCH 2/2] ARM: bcm2835: add unit address to all nodes w/ reg prop
From: Stephen Warren @ 2014-02-14 5:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392181392-29694-2-git-send-email-swarren@wwwdotorg.org>
On 02/11/2014 10:03 PM, Stephen Warren wrote:
> DT nodes that contain a reg property should include a unit address in
> their name. Add the missing unit addresses.
I've dropped this one patch; I noticed it causes some issues with
clocks, and some of the already-existing node name unit addresses need
cleaning up too.
^ permalink raw reply
* [PATCH V2] ARM: bcm2835: node name unit address cleanup
From: Stephen Warren @ 2014-02-14 6:04 UTC (permalink / raw)
To: linux-arm-kernel
DT nodes that contain a reg property should include a unit address in
their name. Add the missing unit addresses.
The unit address in a node name must match the value in the reg property.
Fix the cases where they don't match.
Don't fix the /clocks/* node names yet; that causes problems the clock
driver to attempt to register multiple clocks with the same name, which
fails.
Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
---
v2:
* Fix existing mismatching unit addresses.
* Don't touch the /clocks/* nodes.
---
arch/arm/boot/dts/bcm2835.dtsi | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 5ceba45..a2d4889 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -15,7 +15,7 @@
#size-cells = <1>;
ranges = <0x7e000000 0x20000000 0x02000000>;
- timer {
+ timer at 7e003000 {
compatible = "brcm,bcm2835-system-timer";
reg = <0x7e003000 0x1000>;
interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
@@ -43,24 +43,24 @@
brcm,dma-channel-mask = <0x7f35>;
};
- intc: interrupt-controller {
+ intc: interrupt-controller at 7e00b200 {
compatible = "brcm,bcm2835-armctrl-ic";
reg = <0x7e00b200 0x200>;
interrupt-controller;
#interrupt-cells = <2>;
};
- watchdog {
+ watchdog at 7e100000 {
compatible = "brcm,bcm2835-pm-wdt";
reg = <0x7e100000 0x28>;
};
- rng {
+ rng at 7e104000 {
compatible = "brcm,bcm2835-rng";
reg = <0x7e104000 0x10>;
};
- gpio: gpio {
+ gpio: gpio at 7e200000 {
compatible = "brcm,bcm2835-gpio";
reg = <0x7e200000 0xb4>;
/*
@@ -83,7 +83,7 @@
#interrupt-cells = <2>;
};
- uart at 20201000 {
+ uart at 7e201000 {
compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
reg = <0x7e201000 0x1000>;
interrupts = <2 25>;
@@ -101,7 +101,7 @@
dma-names = "tx", "rx";
};
- spi: spi at 20204000 {
+ spi: spi at 7e204000 {
compatible = "brcm,bcm2835-spi";
reg = <0x7e204000 0x1000>;
interrupts = <2 22>;
@@ -121,7 +121,7 @@
status = "disabled";
};
- sdhci: sdhci {
+ sdhci: sdhci at 7e300000 {
compatible = "brcm,bcm2835-sdhci";
reg = <0x7e300000 0x100>;
interrupts = <2 30>;
@@ -129,7 +129,7 @@
status = "disabled";
};
- i2c1: i2c at 20804000 {
+ i2c1: i2c at 7e804000 {
compatible = "brcm,bcm2835-i2c";
reg = <0x7e804000 0x1000>;
interrupts = <2 21>;
@@ -139,7 +139,7 @@
status = "disabled";
};
- usb {
+ usb at 7e980000 {
compatible = "brcm,bcm2835-usb";
reg = <0x7e980000 0x10000>;
interrupts = <1 9>;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/2] clk: fixed-rate: use full DT node name
From: Stephen Warren @ 2014-02-14 6:16 UTC (permalink / raw)
To: linux-arm-kernel
clk-fixed-rate currently names clocks according to a node's name without
the unit address. When faced with the legal and technically correct DT
structure below, this causes rgistration attempts for 3 clocks with the
same name, 2 of which fail.
clocks {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
clk_mmc: clock at 0 {
compatible = "fixed-clock";
reg = <0>;
...
clk_i2c: clock at 1 {
compatible = "fixed-clock";
reg = <1>;
...
clk_spi: clock at 2 {
compatible = "fixed-clock";
reg = <2>;
...
Solve this by naming the clocks after the full node name rather than the
short version (e.g. /clocks/clock at 0).
Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
---
Note that if this is accepted, I intend to submit a patch for the RPi DTS
which uses the naming structure above, so it might be useful to place this
patch in its own branch. Or, I could submit the cleanup after 3.15-rc1.
---
drivers/clk/clk-fixed-rate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index 0fc56ab..3335b3c 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -115,7 +115,7 @@ EXPORT_SYMBOL_GPL(clk_register_fixed_rate);
void of_fixed_clk_setup(struct device_node *node)
{
struct clk *clk;
- const char *clk_name = node->name;
+ const char *clk_name = node->full_name;
u32 rate;
u32 accuracy = 0;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/2] ARM: bcm2835: fix clock DT node names
From: Stephen Warren @ 2014-02-14 6:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392358613-19962-1-git-send-email-swarren@wwwdotorg.org>
DT nodes should be named according to the type of object that they
represent rather than the identity. DT nodes that contain a reg
property should include a unit address in their name. Fix these issues.
Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
---
This is the bcm2835 patch which depends on patch 1. I guess this could
also go through the clk tree if that makes it easier, although there's
always the small risk of conflicts if you do that.
arch/arm/boot/dts/bcm2835.dtsi | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index a2d4889..1cf1ae7 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -155,21 +155,21 @@
#address-cells = <1>;
#size-cells = <0>;
- clk_mmc: mmc {
+ clk_mmc: clock at 0 {
compatible = "fixed-clock";
reg = <0>;
#clock-cells = <0>;
clock-frequency = <100000000>;
};
- clk_i2c: i2c {
+ clk_i2c: clock at 1 {
compatible = "fixed-clock";
reg = <1>;
#clock-cells = <0>;
clock-frequency = <250000000>;
};
- clk_spi: spi {
+ clk_spi: clock at 2 {
compatible = "fixed-clock";
reg = <2>;
#clock-cells = <0>;
--
1.8.3.2
^ permalink raw reply related
* [PATCH] PCI: imx6: Fix link_up detection
From: Sascha Hauer @ 2014-02-14 6:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52FD0F1A.4000208@boundarydevices.com>
On Thu, Feb 13, 2014 at 11:29:46AM -0700, Troy Kisky wrote:
> On 2/12/2014 12:36 AM, Marek Vasut wrote:
> >On Wednesday, February 12, 2014 at 08:27:55 AM, Sascha Hauer wrote:
> >
> >+CC Troy Kisky, since I think he submitted something similar some time ago
> >already.
> >
> >Otherwise I agree this happens.
> >
> Sorry, I haven't submitted this yet, but was planning to today. Here's
> what would have been sent.
>
> From 32c560d33fe2c3945d69f3396689f0abb76f7e1f Mon Sep 17 00:00:00 2001
> From: Marek Vasut <marex@denx.de>
> Date: Sat, 25 Jan 2014 14:22:48 -0700
> Subject: [PATCH 1/1] pci-imx6.c: wait for retraining
>
> This patch handles the case where the PCIe link is up and running, yet drops
> into the LTSSM training mode. The link spends short time in the LTSSM training
> mode, but the current code can misinterpret it as the link being stalled.
> Waiting for the LTSSM training to complete fixes the issue.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Tested-by: Troy Kisky <troy.kisky@boundarydevices.com>
Thanks, that works.
Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
Sascha
> ---
> drivers/pci/host/pci-imx6.c | 47 ++++++++++++++++++++++++++++++++-------------
> 1 file changed, 34 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index e8663a8..ee08250 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -424,20 +424,40 @@ static void imx6_pcie_reset_phy(struct pcie_port *pp)
> static int imx6_pcie_link_up(struct pcie_port *pp)
> {
> - u32 rc, ltssm, rx_valid;
> + u32 rc, debug_r0, rx_valid;
> + int count = 5;
> /*
> - * Test if the PHY reports that the link is up and also that
> - * the link training finished. It might happen that the PHY
> - * reports the link is already up, but the link training bit
> - * is still set, so make sure to check the training is done
> - * as well here.
> + * Test if the PHY reports that the link is up and also that the LTSSM
> + * training finished. There are three possible states of the link when
> + * this code is called:
> + * 1) The link is DOWN (unlikely)
> + * The link didn't come up yet for some reason. This usually means
> + * we have a real problem somewhere. Reset the PHY and exit. This
> + * state calls for inspection of the DEBUG registers.
> + * 2) The link is UP, but still in LTSSM training
> + * Wait for the training to finish, which should take a very short
> + * time. If the training does not finish, we have a problem and we
> + * need to inspect the DEBUG registers. If the training does finish,
> + * the link is up and operating correctly.
> + * 3) The link is UP and no longer in LTSSM training
> + * The link is up and operating correctly.
> */
> - rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
> - if ((rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) &&
> - !(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
> - return 1;
> -
> + while (1) {
> + rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
> + if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
> + break;
> + if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
> + return 1;
> + if (!count--)
> + break;
> + dev_dbg(pp->dev, "Link is up, but still in training\n");
> + /*
> + * Wait a little bit, then re-check if the link finished
> + * the training.
> + */
> + usleep_range(1000, 2000);
> + }
> /*
> * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
> * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
> @@ -446,15 +466,16 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
> * to gen2 is stuck
> */
> pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
> - ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F;
> + debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
> if (rx_valid & 0x01)
> return 0;
> - if (ltssm != 0x0d)
> + if ((debug_r0 & 0x3f) != 0x0d)
> return 0;
> dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
> + dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
> imx6_pcie_reset_phy(pp);
> --
> 1.8.1.2
>
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH v5 0/3] serial: fsl_lpuart: add DMA support
From: Yuan Yao @ 2014-02-14 7:27 UTC (permalink / raw)
To: linux-arm-kernel
Changed in v5:
- Revoke move dma properties from dtsi to dts.
- Change the explanations for dmas, dma-names in document.
- Change the description for [PATCH 3] serial: fsl_lpuart: documented the clock requirement.
Changed in v4:
- Move dma properties from dtsi to dts.
- Cancle the macro(SERIAL_FSL_LPUART_DMA) .
- Separate the document for clocks which undocumented before into a single patch.
- Change some explanations in document(clocks, clock-names, dmas, dma-names).
- Change "lpuart-tx" and "lpuart-rx" to "tx" and "rx".
Changed in v3:
- Use the streaming DMA API for receive.
- Add the macro(SERIAL_FSL_LPUART_DMA) and dts node propertie for whether using the dma.
- Adjust some coding style.
Changed in v2:
- Add eDMA support for lpuart receive.
- Use dma_mapping_error test dma_map_single.
- Change some names of variable.
- Fix some bugs.
Added in v1:
- Add device tree bindings for lupart eDMA support.
- Add eDMA support for lpuart send.
^ permalink raw reply
* [PATCH v5 1/3] ARM: dts: vf610: lpuart: Add eDMA support
From: Yuan Yao @ 2014-02-14 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392362839-8004-1-git-send-email-yao.yuan@freescale.com>
Add lpuart dts node properties for eDMA support, them depend on the eDMA driver.
Signed-off-by: Yuan Yao <yao.yuan@freescale.com>
---
arch/arm/boot/dts/vf610.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 365e0fa..8f523b0 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -94,6 +94,9 @@
interrupts = <0 61 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART0>;
clock-names = "ipg";
+ dmas = <&edma0 0 2>,
+ <&edma0 0 3>;
+ dma-names = "rx","tx";
status = "disabled";
};
@@ -103,6 +106,9 @@
interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART1>;
clock-names = "ipg";
+ dmas = <&edma0 0 4>,
+ <&edma0 0 5>;
+ dma-names = "rx","tx";
status = "disabled";
};
@@ -112,6 +118,9 @@
interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART2>;
clock-names = "ipg";
+ dmas = <&edma0 0 6>,
+ <&edma0 0 7>;
+ dma-names = "rx","tx";
status = "disabled";
};
@@ -121,6 +130,9 @@
interrupts = <0 64 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks VF610_CLK_UART3>;
clock-names = "ipg";
+ dmas = <&edma0 0 8>,
+ <&edma0 0 9>;
+ dma-names = "rx","tx";
status = "disabled";
};
--
1.8.4
^ permalink raw reply related
* [PATCH v5 2/3] serial: fsl_lpuart: add DMA support
From: Yuan Yao @ 2014-02-14 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392362839-8004-1-git-send-email-yao.yuan@freescale.com>
Add dma support for lpuart. This function depend on DMA driver.
You can turn on it by write both the dmas and dma-name properties in dts node.
Signed-off-by: Yuan Yao <yao.yuan@freescale.com>
---
.../devicetree/bindings/serial/fsl-lpuart.txt | 19 +-
drivers/tty/serial/fsl_lpuart.c | 430 ++++++++++++++++++++-
2 files changed, 433 insertions(+), 16 deletions(-)
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
index 6fd1dd1..6e1cbbf 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
@@ -5,10 +5,24 @@ Required properties:
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
+Optional properties:
+- dmas: List of two DMA specifiers, using a three-cell specifier for each channel.
+ a phandle plus two integer cells. The three cells in order are:
+ 1.A phandle pointing to the DMA controller.
+ 2.specifies the channel group(DMAMUX) in which this request can be multiplexed,
+ 3.specifies the request source.
+- dma-names: Contains one identifier string for each DMA specifier in the dmas property.
+ "tx" for the transmit channel, "rx" for the receive channel.
+
+Note: Optional properties for DMA support. Write them both or both not.
+
Example:
uart0: serial at 40027000 {
- compatible = "fsl,vf610-lpuart";
- reg = <0x40027000 0x1000>;
- interrupts = <0 61 0x00>;
- };
+ compatible = "fsl,vf610-lpuart";
+ reg = <0x40027000 0x1000>;
+ interrupts = <0 61 0x00>;
+ dmas = <&edma0 0 2>,
+ <&edma0 0 3>;
+ dma-names = "rx","tx";
+ };
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 8978dc9..c5eb897 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -13,14 +13,19 @@
#define SUPPORT_SYSRQ
#endif
-#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
#include <linux/io.h>
#include <linux/irq.h>
-#include <linux/clk.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/console.h>
+#include <linux/of_dma.h>
#include <linux/serial_core.h>
+#include <linux/slab.h>
#include <linux/tty_flip.h>
/* All registers are 8-bit width */
@@ -112,6 +117,10 @@
#define UARTSFIFO_TXOF 0x02
#define UARTSFIFO_RXUF 0x01
+#define DMA_MAXBURST 16
+#define DMA_MAXBURST_MASK (DMA_MAXBURST - 1)
+#define FSL_UART_RX_DMA_BUFFER_SIZE 64
+
#define DRIVER_NAME "fsl-lpuart"
#define DEV_NAME "ttyLP"
#define UART_NR 6
@@ -121,6 +130,24 @@ struct lpuart_port {
struct clk *clk;
unsigned int txfifo_size;
unsigned int rxfifo_size;
+
+ bool lpuart_dma_use;
+ struct dma_chan *dma_tx_chan;
+ struct dma_chan *dma_rx_chan;
+ struct dma_async_tx_descriptor *dma_tx_desc;
+ struct dma_async_tx_descriptor *dma_rx_desc;
+ dma_addr_t dma_tx_buf_bus;
+ dma_addr_t dma_rx_buf_bus;
+ dma_cookie_t dma_tx_cookie;
+ dma_cookie_t dma_rx_cookie;
+ unsigned char *dma_tx_buf_virt;
+ unsigned char *dma_rx_buf_virt;
+ unsigned int dma_tx_bytes;
+ unsigned int dma_rx_bytes;
+ int dma_tx_in_progress;
+ int dma_rx_in_progress;
+ unsigned int dma_rx_timeout;
+ struct timer_list lpuart_timer;
};
static struct of_device_id lpuart_dt_ids[] = {
@@ -131,6 +158,10 @@ static struct of_device_id lpuart_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
+/* Forward declare this for the dma callbacks*/
+static void lpuart_dma_tx_complete(void *arg);
+static void lpuart_dma_rx_complete(void *arg);
+
static void lpuart_stop_tx(struct uart_port *port)
{
unsigned char temp;
@@ -152,6 +183,210 @@ static void lpuart_enable_ms(struct uart_port *port)
{
}
+static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
+ struct tty_port *tty, int count)
+{
+ int copied;
+
+ sport->port.icount.rx += count;
+
+ if (!tty) {
+ dev_err(sport->port.dev, "No tty port\n");
+ return;
+ }
+
+ dma_sync_single_for_cpu(sport->port.dev, sport->dma_rx_buf_bus,
+ FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
+ copied = tty_insert_flip_string(tty,
+ ((unsigned char *)(sport->dma_rx_buf_virt)), count);
+
+ if (copied != count) {
+ WARN_ON(1);
+ dev_err(sport->port.dev, "RxData copy to tty layer failed\n");
+ }
+
+ dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
+ FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
+}
+
+static void lpuart_pio_tx(struct lpuart_port *sport)
+{
+ struct circ_buf *xmit = &sport->port.state->xmit;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
+ while (!uart_circ_empty(xmit) &&
+ readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size) {
+ writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ sport->port.icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&sport->port);
+
+ if (uart_circ_empty(xmit))
+ writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
+ sport->port.membase + UARTCR5);
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static int lpuart_dma_tx(struct lpuart_port *sport, unsigned long count)
+{
+ struct circ_buf *xmit = &sport->port.state->xmit;
+ dma_addr_t tx_bus_addr;
+
+ dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
+ sport->dma_tx_bytes = count & ~(DMA_MAXBURST_MASK);
+ tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
+ sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
+ tx_bus_addr, sport->dma_tx_bytes,
+ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
+
+ if (!sport->dma_tx_desc) {
+ dev_err(sport->port.dev, "Not able to get desc for tx\n");
+ return -EIO;
+ }
+
+ sport->dma_tx_desc->callback = lpuart_dma_tx_complete;
+ sport->dma_tx_desc->callback_param = sport;
+ sport->dma_tx_in_progress = 1;
+ sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
+ dma_async_issue_pending(sport->dma_tx_chan);
+
+ return 0;
+}
+
+static void lpuart_prepare_tx(struct lpuart_port *sport)
+{
+ struct circ_buf *xmit = &sport->port.state->xmit;
+ unsigned long count = CIRC_CNT_TO_END(xmit->head,
+ xmit->tail, UART_XMIT_SIZE);
+
+ if (!count)
+ return;
+
+ if (count < DMA_MAXBURST)
+ writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
+ sport->port.membase + UARTCR5);
+ else {
+ writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
+ sport->port.membase + UARTCR5);
+ lpuart_dma_tx(sport, count);
+ }
+}
+
+static void lpuart_dma_tx_complete(void *arg)
+{
+ struct lpuart_port *sport = arg;
+ struct circ_buf *xmit = &sport->port.state->xmit;
+ unsigned long flags;
+
+ async_tx_ack(sport->dma_tx_desc);
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
+ xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1);
+ sport->dma_tx_in_progress = 0;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&sport->port);
+
+ lpuart_prepare_tx(sport);
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static int lpuart_dma_rx(struct lpuart_port *sport)
+{
+ dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
+ FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
+ sport->dma_rx_desc = dmaengine_prep_slave_single(sport->dma_rx_chan,
+ sport->dma_rx_buf_bus, FSL_UART_RX_DMA_BUFFER_SIZE,
+ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+
+ if (!sport->dma_rx_desc) {
+ dev_err(sport->port.dev, "Not able to get desc for rx\n");
+ return -EIO;
+ }
+
+ sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
+ sport->dma_rx_desc->callback_param = sport;
+ sport->dma_rx_in_progress = 1;
+ sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
+ dma_async_issue_pending(sport->dma_rx_chan);
+
+ return 0;
+}
+
+static void lpuart_dma_rx_complete(void *arg)
+{
+ struct lpuart_port *sport = arg;
+ struct tty_port *port = &sport->port.state->port;
+ unsigned long flags;
+
+ async_tx_ack(sport->dma_rx_desc);
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
+ sport->dma_rx_in_progress = 0;
+ lpuart_copy_rx_to_tty(sport, port, FSL_UART_RX_DMA_BUFFER_SIZE);
+ tty_flip_buffer_push(port);
+ lpuart_dma_rx(sport);
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static void lpuart_timer_func(unsigned long data)
+{
+ struct lpuart_port *sport = (struct lpuart_port *)data;
+ struct tty_port *port = &sport->port.state->port;
+ struct dma_tx_state state;
+ unsigned long flags;
+ unsigned char temp;
+ int count;
+
+ del_timer(&sport->lpuart_timer);
+ dmaengine_pause(sport->dma_rx_chan);
+ dmaengine_tx_status(sport->dma_rx_chan, sport->dma_rx_cookie, &state);
+ dmaengine_terminate_all(sport->dma_rx_chan);
+ count = FSL_UART_RX_DMA_BUFFER_SIZE - state.residue;
+ async_tx_ack(sport->dma_rx_desc);
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
+ sport->dma_rx_in_progress = 0;
+ lpuart_copy_rx_to_tty(sport, port, count);
+ tty_flip_buffer_push(port);
+ temp = readb(sport->port.membase + UARTCR5);
+ writeb(temp & ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static inline void lpuart_prepare_rx(struct lpuart_port *sport)
+{
+ unsigned long flags;
+ unsigned char temp;
+
+ spin_lock_irqsave(&sport->port.lock, flags);
+
+ init_timer(&sport->lpuart_timer);
+ sport->lpuart_timer.function = lpuart_timer_func;
+ sport->lpuart_timer.data = (unsigned long)sport;
+ sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
+ add_timer(&sport->lpuart_timer);
+
+ lpuart_dma_rx(sport);
+ temp = readb(sport->port.membase + UARTCR5);
+ writeb(temp | UARTCR5_RDMAS, sport->port.membase + UARTCR5);
+
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
{
struct circ_buf *xmit = &sport->port.state->xmit;
@@ -172,14 +407,21 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
static void lpuart_start_tx(struct uart_port *port)
{
- struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ struct circ_buf *xmit = &sport->port.state->xmit;
unsigned char temp;
temp = readb(port->membase + UARTCR2);
writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
- if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
- lpuart_transmit_buffer(sport);
+ if (sport->lpuart_dma_use) {
+ if (!uart_circ_empty(xmit) && !sport->dma_tx_in_progress)
+ lpuart_prepare_tx(sport);
+ } else {
+ if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
+ lpuart_transmit_buffer(sport);
+ }
}
static irqreturn_t lpuart_txint(int irq, void *dev_id)
@@ -279,12 +521,19 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
sts = readb(sport->port.membase + UARTSR1);
- if (sts & UARTSR1_RDRF)
- lpuart_rxint(irq, dev_id);
-
+ if (sts & UARTSR1_RDRF) {
+ if (sport->lpuart_dma_use)
+ lpuart_prepare_rx(sport);
+ else
+ lpuart_rxint(irq, dev_id);
+ }
if (sts & UARTSR1_TDRE &&
- !(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS))
- lpuart_txint(irq, dev_id);
+ !(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS)) {
+ if (sport->lpuart_dma_use)
+ lpuart_pio_tx(sport);
+ else
+ lpuart_txint(irq, dev_id);
+ }
return IRQ_HANDLED;
}
@@ -366,13 +615,156 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
sport->port.membase + UARTCFIFO);
- writeb(2, sport->port.membase + UARTTWFIFO);
+ writeb(0, sport->port.membase + UARTTWFIFO);
writeb(1, sport->port.membase + UARTRWFIFO);
/* Restore cr2 */
writeb(cr2_saved, sport->port.membase + UARTCR2);
}
+static int lpuart_dma_tx_request(struct uart_port *port)
+{
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ struct dma_chan *tx_chan;
+ struct dma_slave_config dma_tx_sconfig;
+ dma_addr_t dma_bus;
+ unsigned char *dma_buf;
+ int ret;
+
+ tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
+
+ if (!tx_chan) {
+ dev_err(sport->port.dev, "Dma tx channel request failed!\n");
+ return -ENODEV;
+ }
+
+ dma_bus = dma_map_single(tx_chan->device->dev,
+ sport->port.state->xmit.buf,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+ if (dma_mapping_error(tx_chan->device->dev, dma_bus)) {
+ dev_err(sport->port.dev, "dma_map_single tx failed\n");
+ dma_release_channel(tx_chan);
+ return -ENOMEM;
+ }
+
+ dma_buf = sport->port.state->xmit.buf;
+ dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
+ dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ dma_tx_sconfig.dst_maxburst = DMA_MAXBURST;
+ dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
+ ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
+
+ if (ret < 0) {
+ dev_err(sport->port.dev,
+ "Dma slave config failed, err = %d\n", ret);
+ dma_release_channel(tx_chan);
+ return ret;
+ }
+
+ sport->dma_tx_chan = tx_chan;
+ sport->dma_tx_buf_virt = dma_buf;
+ sport->dma_tx_buf_bus = dma_bus;
+ sport->dma_tx_in_progress = 0;
+
+ return 0;
+}
+
+static int lpuart_dma_rx_request(struct uart_port *port)
+{
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ struct dma_chan *rx_chan;
+ struct dma_slave_config dma_rx_sconfig;
+ dma_addr_t dma_bus;
+ unsigned char *dma_buf;
+ int ret;
+
+ rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
+
+ if (!rx_chan) {
+ dev_err(sport->port.dev, "Dma rx channel request failed!\n");
+ return -ENODEV;
+ }
+
+ dma_buf = devm_kzalloc(sport->port.dev,
+ FSL_UART_RX_DMA_BUFFER_SIZE, GFP_KERNEL);
+
+ if (!dma_buf) {
+ dev_err(sport->port.dev, "Dma rx alloc failed\n");
+ dma_release_channel(rx_chan);
+ return -ENOMEM;
+ }
+
+ dma_bus = dma_map_single(rx_chan->device->dev, dma_buf,
+ FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(rx_chan->device->dev, dma_bus)) {
+ dev_err(sport->port.dev, "dma_map_single rx failed\n");
+ dma_release_channel(rx_chan);
+ return -ENOMEM;
+ }
+
+ dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDR;
+ dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ dma_rx_sconfig.src_maxburst = 1;
+ dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
+ ret = dmaengine_slave_config(rx_chan, &dma_rx_sconfig);
+
+ if (ret < 0) {
+ dev_err(sport->port.dev,
+ "Dma slave config failed, err = %d\n", ret);
+ dma_release_channel(rx_chan);
+ return ret;
+ }
+
+ sport->dma_rx_chan = rx_chan;
+ sport->dma_rx_buf_virt = dma_buf;
+ sport->dma_rx_buf_bus = dma_bus;
+ sport->dma_rx_in_progress = 0;
+
+ sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
+ FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
+ sport->rxfifo_size / 2;
+
+ if (sport->dma_rx_timeout < msecs_to_jiffies(20))
+ sport->dma_rx_timeout = msecs_to_jiffies(20);
+
+ return 0;
+}
+
+static void lpuart_dma_tx_free(struct uart_port *port)
+{
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ struct dma_chan *dma_chan;
+
+ dma_unmap_single(sport->port.dev, sport->dma_tx_buf_bus,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
+ dma_chan = sport->dma_tx_chan;
+ sport->dma_tx_chan = NULL;
+ sport->dma_tx_buf_bus = 0;
+ sport->dma_tx_buf_virt = NULL;
+ dma_release_channel(dma_chan);
+}
+
+static void lpuart_dma_rx_free(struct uart_port *port)
+{
+ struct lpuart_port *sport = container_of(port,
+ struct lpuart_port, port);
+ struct dma_chan *dma_chan;
+
+ dma_unmap_single(sport->port.dev, sport->dma_rx_buf_bus,
+ FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
+
+ dma_chan = sport->dma_rx_chan;
+ sport->dma_rx_chan = NULL;
+ sport->dma_rx_buf_bus = 0;
+ sport->dma_rx_buf_virt = NULL;
+ dma_release_channel(dma_chan);
+}
+
static int lpuart_startup(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@@ -380,6 +772,15 @@ static int lpuart_startup(struct uart_port *port)
unsigned long flags;
unsigned char temp;
+ /*whether use dma support by dma request results*/
+ if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
+ sport->lpuart_dma_use = false;
+ } else {
+ sport->lpuart_dma_use = true;
+ temp = readb(port->membase + UARTCR5);
+ writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
+ }
+
ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
DRIVER_NAME, sport);
if (ret)
@@ -414,6 +815,11 @@ static void lpuart_shutdown(struct uart_port *port)
spin_unlock_irqrestore(&port->lock, flags);
devm_free_irq(port->dev, port->irq, sport);
+
+ if (sport->lpuart_dma_use) {
+ lpuart_dma_tx_free(port);
+ lpuart_dma_rx_free(port);
+ }
}
static void
--
1.8.4
^ permalink raw reply related
* [PATCH v5 3/3] serial: fsl_lpuart: documented the clock requirement.
From: Yuan Yao @ 2014-02-14 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392362839-8004-1-git-send-email-yao.yuan@freescale.com>
This is a correction to the documentation. It was previously required but not documented.
Signed-off-by: Yuan Yao <yao.yuan@freescale.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
---
Documentation/devicetree/bindings/serial/fsl-lpuart.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
index 6e1cbbf..9666f97 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
@@ -4,6 +4,8 @@ Required properties:
- compatible : Should be "fsl,<soc>-lpuart"
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
+- clocks : phandle + clock specifier pairs, one for each entry in clock-names
+- clock-names : should contain: "ipg" - the uart clock
Optional properties:
- dmas: List of two DMA specifiers, using a three-cell specifier for each channel.
@@ -22,6 +24,8 @@ uart0: serial at 40027000 {
compatible = "fsl,vf610-lpuart";
reg = <0x40027000 0x1000>;
interrupts = <0 61 0x00>;
+ clocks = <&clks VF610_CLK_UART0>;
+ clock-names = "ipg";
dmas = <&edma0 0 2>,
<&edma0 0 3>;
dma-names = "rx","tx";
--
1.8.4
^ permalink raw reply related
* [PATCH v4 1/2] spi:fsl-dspi:convert to use regmap and big-endian supports
From: Li.Xiubo at freescale.com @ 2014-02-14 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392190146-18852-1-git-send-email-b44548@freescale.com>
> @@ -435,12 +441,20 @@ static const struct dev_pm_ops dspi_pm = {
> SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume)
> };
>
> +static struct regmap_config dspi_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x88,
> +};
> +
If needed, you should add the callbacks like:
.readable_reg,
.writeable_reg,
.volatile_reg,
Otherwise, it looks fine to me, for both patches:
Reviewed-by: Xiubo Li <Li.Xiubo@freescale.com>
^ permalink raw reply
* [PATCH v2 2/2] ARM: sunxi: dt: Convert to the new i2c compatibles
From: Wolfram Sang @ 2014-02-14 7:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140213225248.GB15350@lukather>
> > For non-a10, That should be at least
> >
> > compatible = "allwinner,sun4i-a13-i2c", "allwinner,sun4i-a10-i2c";
> >
> > or
> >
> > compatible = "allwinner,sun4i-a13-i2c", "allwinner,sun4i-i2c";
> >
> > depending on the outcome above.
> >
> > Or is my knowledge outdated already?
> >
>
> Since they are strictly compatible, we don't need to introduce any
> different compatible string here.
You never know all errata in advance. From what I know, one should
always use the specfic naming first, and then the generic fallback. So,
in case a distinction is needed later (think errata), then one doesn't
need to change the devicetrees.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140214/23f31104/attachment.sig>
^ permalink raw reply
* [PATCH v2 09/52] arm, hw-breakpoint: Fix CPU hotplug callback registration
From: Srivatsa S. Bhat @ 2014-02-14 7:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140214074750.22701.47330.stgit@srivatsabhat.in.ibm.com>
Subsystems that want to register CPU hotplug callbacks, as well as perform
initialization for the CPUs that are already online, often do it as shown
below:
get_online_cpus();
for_each_online_cpu(cpu)
init_cpu(cpu);
register_cpu_notifier(&foobar_cpu_notifier);
put_online_cpus();
This is wrong, since it is prone to ABBA deadlocks involving the
cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
with CPU hotplug operations).
Instead, the correct and race-free way of performing the callback
registration is:
cpu_notifier_register_begin();
for_each_online_cpu(cpu)
init_cpu(cpu);
/* Note the use of the double underscored version of the API */
__register_cpu_notifier(&foobar_cpu_notifier);
cpu_notifier_register_done();
Fix the hw-breakpoint code in arm by using this latter form of callback
registration.
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
arch/arm/kernel/hw_breakpoint.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 3d44660..3702de8 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -1072,6 +1072,8 @@ static int __init arch_hw_breakpoint_init(void)
core_num_brps = get_num_brps();
core_num_wrps = get_num_wrps();
+ cpu_notifier_register_begin();
+
/*
* We need to tread carefully here because DBGSWENABLE may be
* driven low on this core and there isn't an architected way to
@@ -1088,6 +1090,7 @@ static int __init arch_hw_breakpoint_init(void)
if (!cpumask_empty(&debug_err_mask)) {
core_num_brps = 0;
core_num_wrps = 0;
+ cpu_notifier_register_done();
return 0;
}
@@ -1107,7 +1110,10 @@ static int __init arch_hw_breakpoint_init(void)
TRAP_HWBKPT, "breakpoint debug exception");
/* Register hotplug and PM notifiers. */
- register_cpu_notifier(&dbg_reset_nb);
+ __register_cpu_notifier(&dbg_reset_nb);
+
+ cpu_notifier_register_done();
+
pm_init();
return 0;
}
^ permalink raw reply related
* [PATCH v2 10/52] arm, kvm: Fix CPU hotplug callback registration
From: Srivatsa S. Bhat @ 2014-02-14 7:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140214074750.22701.47330.stgit@srivatsabhat.in.ibm.com>
Subsystems that want to register CPU hotplug callbacks, as well as perform
initialization for the CPUs that are already online, often do it as shown
below:
get_online_cpus();
for_each_online_cpu(cpu)
init_cpu(cpu);
register_cpu_notifier(&foobar_cpu_notifier);
put_online_cpus();
This is wrong, since it is prone to ABBA deadlocks involving the
cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
with CPU hotplug operations).
Instead, the correct and race-free way of performing the callback
registration is:
cpu_notifier_register_begin();
for_each_online_cpu(cpu)
init_cpu(cpu);
/* Note the use of the double underscored version of the API */
__register_cpu_notifier(&foobar_cpu_notifier);
cpu_notifier_register_done();
Fix the kvm code in arm by using this latter form of callback registration.
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Gleb Natapov <gleb@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: kvmarm at lists.cs.columbia.edu
Cc: kvm at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
arch/arm/kvm/arm.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 1d8248e..147b917 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1050,21 +1050,26 @@ int kvm_arch_init(void *opaque)
}
}
+ cpu_notifier_register_begin();
+
err = init_hyp_mode();
if (err)
goto out_err;
- err = register_cpu_notifier(&hyp_init_cpu_nb);
+ err = __register_cpu_notifier(&hyp_init_cpu_nb);
if (err) {
kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
goto out_err;
}
+ cpu_notifier_register_done();
+
hyp_cpu_pm_init();
kvm_coproc_table_init();
return 0;
out_err:
+ cpu_notifier_register_done();
return err;
}
^ permalink raw reply related
* use {readl|writel}_relaxed instead of readl/writel in i2c-designware-core ?
From: Jisheng Zhang @ 2014-02-14 7:54 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
The writel/readl is too expensive especially on Cortex A9 w/ outer L2 cache. This
introduce i2c read/write error on Marvell Berlin SoCs when there are L2 cache
maintenance operations at the same time.
In our internal berlin bsp, we just replaced readl/writel with the relaxed
version. But AFAIK, the "relaxed" version doesn't exist on all architectures. How
to handle this issue?
Any suggestions are appreciated.
Thanks in advance,
Jisheng
^ permalink raw reply
* [PATCH v2 30/52] arm64, hw_breakpoint.c: Fix CPU hotplug callback registration
From: Srivatsa S. Bhat @ 2014-02-14 7:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140214074750.22701.47330.stgit@srivatsabhat.in.ibm.com>
Subsystems that want to register CPU hotplug callbacks, as well as perform
initialization for the CPUs that are already online, often do it as shown
below:
get_online_cpus();
for_each_online_cpu(cpu)
init_cpu(cpu);
register_cpu_notifier(&foobar_cpu_notifier);
put_online_cpus();
This is wrong, since it is prone to ABBA deadlocks involving the
cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
with CPU hotplug operations).
Instead, the correct and race-free way of performing the callback
registration is:
cpu_notifier_register_begin();
for_each_online_cpu(cpu)
init_cpu(cpu);
/* Note the use of the double underscored version of the API */
__register_cpu_notifier(&foobar_cpu_notifier);
cpu_notifier_register_done();
Fix the hw-breakpoint code in arm64 by using this latter form of callback
registration.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
arch/arm64/kernel/hw_breakpoint.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index f17f581..bee7897 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -913,6 +913,8 @@ static int __init arch_hw_breakpoint_init(void)
pr_info("found %d breakpoint and %d watchpoint registers.\n",
core_num_brps, core_num_wrps);
+ cpu_notifier_register_begin();
+
/*
* Reset the breakpoint resources. We assume that a halting
* debugger will leave the world in a nice state for us.
@@ -927,7 +929,10 @@ static int __init arch_hw_breakpoint_init(void)
TRAP_HWBKPT, "hw-watchpoint handler");
/* Register hotplug notifier. */
- register_cpu_notifier(&hw_breakpoint_reset_nb);
+ __register_cpu_notifier(&hw_breakpoint_reset_nb);
+
+ cpu_notifier_register_done();
+
/* Register cpu_suspend hw breakpoint restore hook */
cpu_suspend_set_dbg_restorer(hw_breakpoint_reset);
^ permalink raw reply related
* [PATCH v2 31/52] arm64, debug-monitors: Fix CPU hotplug callback registration
From: Srivatsa S. Bhat @ 2014-02-14 7:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140214074750.22701.47330.stgit@srivatsabhat.in.ibm.com>
Subsystems that want to register CPU hotplug callbacks, as well as perform
initialization for the CPUs that are already online, often do it as shown
below:
get_online_cpus();
for_each_online_cpu(cpu)
init_cpu(cpu);
register_cpu_notifier(&foobar_cpu_notifier);
put_online_cpus();
This is wrong, since it is prone to ABBA deadlocks involving the
cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
with CPU hotplug operations).
Instead, the correct and race-free way of performing the callback
registration is:
cpu_notifier_register_begin();
for_each_online_cpu(cpu)
init_cpu(cpu);
/* Note the use of the double underscored version of the API */
__register_cpu_notifier(&foobar_cpu_notifier);
cpu_notifier_register_done();
Fix the debug-monitors code in arm64 by using this latter form of callback
registration.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
arch/arm64/kernel/debug-monitors.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 636ba8b..c985531 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -155,12 +155,16 @@ static struct notifier_block os_lock_nb = {
static int debug_monitors_init(void)
{
+ cpu_notifier_register_begin();
+
/* Clear the OS lock. */
smp_call_function(clear_os_lock, NULL, 1);
clear_os_lock(NULL);
/* Register hotplug handler. */
- register_cpu_notifier(&os_lock_nb);
+ __register_cpu_notifier(&os_lock_nb);
+
+ cpu_notifier_register_done();
return 0;
}
postcore_initcall(debug_monitors_init);
^ permalink raw reply related
* [PATCH v3] input: sirfsoc-onkey - report onkey untouch event by detecting pin status
From: Dmitry Torokhov @ 2014-02-14 7:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392348001-4950-1-git-send-email-21cnbao@gmail.com>
Hi Barry,
On Fri, Feb 14, 2014 at 11:20:01AM +0800, Barry Song wrote:
> From: Xianglong Du <Xianglong.Du@csr.com>
>
> this patch adds a delayed_work to detect the untouch of onkey since HW will
> not generate interrupt for it.
>
> at the same time, we move the KEY event to POWER instead of SUSPEND, which
> will be suitable for both Android and Linux. Userspace PowerManager Daemon
> will decide to suspend or shutdown based on how long we have touched onkey
>
> Signed-off-by: Xianglong Du <Xianglong.Du@csr.com>
> Signed-off-by: Rongjun Ying <Rongjun.Ying@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
> ---
> -v3: move to use custom devres action
Thank you for making the changes, however it seems that we can control
whether the device generates interrupts or not and so we can implement
open and close methods. If patch below works then your
cancel_delayed_work() call should go into sirfosc_pwrc_close() and we do
not need to use devm_free_irq() not custom action.
Thanks.
--
Dmitry
Input: sirfsoc-onkey - implement open and close methods
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
We can control whetehr device generates interrupts or not so let's
implement open and close methods of input device so that we do not do any
processing until there are users.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/misc/sirfsoc-onkey.c | 50 +++++++++++++++++++++++++++++-------
1 file changed, 40 insertions(+), 10 deletions(-)
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index e8897c3..dc7db65 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -49,6 +49,35 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv,
+ bool enable)
+{
+ u32 int_mask;
+
+ int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK);
+ if (enable)
+ int_mask |= PWRC_ON_KEY_BIT;
+ else
+ int_mask &= ~PWRC_ON_KEY_BIT;
+ sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK);
+}
+
+static int sirfsoc_pwrc_open(struct input_dev *input)
+{
+ struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
+
+ sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
+
+ return 0;
+}
+
+static void sirfsoc_pwrc_close(struct input_dev *input)
+{
+ struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
+
+ sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
+}
+
static const struct of_device_id sirfsoc_pwrc_of_match[] = {
{ .compatible = "sirf,prima2-pwrc" },
{},
@@ -70,7 +99,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
}
/*
- * we can't use of_iomap because pwrc is not mapped in memory,
+ * We can't use of_iomap because pwrc is not mapped in memory,
* the so-called base address is only offset in rtciobrg
*/
error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base);
@@ -88,6 +117,11 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
pwrcdrv->input->phys = "pwrc/input0";
pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR);
+ pwrcdrv->input->open = sirfsoc_pwrc_open;
+ pwrcdrv->input->close = sirfsoc_pwrc_close;
+
+ input_set_drvdata(pwrcdrv->input, pwrcdrv);
+
irq = platform_get_irq(pdev, 0);
error = devm_request_irq(&pdev->dev, irq,
sirfsoc_pwrc_isr, IRQF_SHARED,
@@ -98,11 +132,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
return error;
}
- sirfsoc_rtc_iobrg_writel(
- sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) |
- PWRC_ON_KEY_BIT,
- pwrcdrv->pwrc_base + PWRC_INT_MASK);
-
error = input_register_device(pwrcdrv->input);
if (error) {
dev_err(&pdev->dev,
@@ -129,15 +158,16 @@ static int pwrc_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev);
+ struct input_dev *input = pwrcdrv->input;
/*
* Do not mask pwrc interrupt as we want pwrc work as a wakeup source
* if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
*/
- sirfsoc_rtc_iobrg_writel(
- sirfsoc_rtc_iobrg_readl(
- pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT,
- pwrcdrv->pwrc_base + PWRC_INT_MASK);
+ mutex_lock(&input->mutex);
+ if (input->users)
+ sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
+ mutex_unlock(&input->mutex);
return 0;
}
^ permalink raw reply related
* [PATCH v2 4/4] Documentation: dt: OMAP: Update Overo/Tobi
From: Florian Vaussard @ 2014-02-14 7:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52FCDA29.90605@ti.com>
Hi,
On 02/13/2014 03:43 PM, Nishanth Menon wrote:
> On 02/13/2014 04:25 AM, Florian Vaussard wrote:
>> Update the compatible string for Overo/Tobi to reflect the latest
>> changes.
>>
>> Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
>> ---
>> Documentation/devicetree/bindings/arm/omap/omap.txt | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
>> index 34dc40c..af9b4a0 100644
>> --- a/Documentation/devicetree/bindings/arm/omap/omap.txt
>> +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
>> @@ -91,7 +91,7 @@ Boards:
>> compatible = "ti,omap3-beagle", "ti,omap3"
>>
>> - OMAP3 Tobi with Overo : Commercial expansion board with daughter board
>> - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"
>> + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3"
> omap3-overo-storm-tobi.dts is not covered here, so, I wonder as the
> number of boards supported keep increasing, is'nt it better we drop
> the board information from omap.txt?
>
I am not opposed to this. We will just have checkpatch warnings due to
undocumented compatible strings.
Regards,
Florian
^ permalink raw reply
* [PATCH v2 4/4] Documentation: dt: OMAP: Update Overo/Tobi
From: Nishanth Menon @ 2014-02-14 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52FDCC9B.2050608@epfl.ch>
On 02/14/2014 01:58 AM, Florian Vaussard wrote:
> Hi,
>
> On 02/13/2014 03:43 PM, Nishanth Menon wrote:
>> On 02/13/2014 04:25 AM, Florian Vaussard wrote:
>>> Update the compatible string for Overo/Tobi to reflect the latest
>>> changes.
>>>
>>> Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
>>> ---
>>> Documentation/devicetree/bindings/arm/omap/omap.txt | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
>>> index 34dc40c..af9b4a0 100644
>>> --- a/Documentation/devicetree/bindings/arm/omap/omap.txt
>>> +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
>>> @@ -91,7 +91,7 @@ Boards:
>>> compatible = "ti,omap3-beagle", "ti,omap3"
>>>
>>> - OMAP3 Tobi with Overo : Commercial expansion board with daughter board
>>> - compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"
>>> + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3"
>> omap3-overo-storm-tobi.dts is not covered here, so, I wonder as the
>> number of boards supported keep increasing, is'nt it better we drop
>> the board information from omap.txt?
>>
>
> I am not opposed to this. We will just have checkpatch warnings due to
> undocumented compatible strings.
Aaah, I seemed to have missed bff5da43 commit, thanks for pointing me
at it - unrelated to this patch, I think the board cleanups is a
little overdue :(
Acked-by: Nishanth Menon <nm@ti.com>
--
Regards,
Nishanth Menon
^ permalink raw reply
* [BUG] FL1009: xHCI host not responding to stop endpoint command.
From: Thomas Petazzoni @ 2014-02-14 8:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140214000910.GB16889@xanatos>
Sarah, Arnaud,
On Thu, 13 Feb 2014 16:09:10 -0800, Sarah Sharp wrote:
> > Unless you have some objections or some positive feedback from Fresco
> > Logic people, can you queue your quirks for FL1009 for 3.14-rc* and
> > -stable? Note that I am just asking, i.e. if you want to wait a bit
> > more, I am not that in a hurry.
>
> Sorry for not getting back to you sooner. The Fresco Logic folks said
> that the FL1000 and FL1400 hosts are actually the same chipset, and it
> doesn't support MSI. However, they say the FL1009 *should* support MSI.
>
> So that doesn't rule out issues with the Marvell PCI MSI code. I
> suspect that's actually the root cause, since I haven't gotten any bug
> reports that the FL1009 doesn't work with MSI enabled on other systems.
Ok, I'll try to have a look into this, by re-reading the entire
thread, and trying to propose some patches that add debugging details
in the Marvell PCI MSI code to try to understand what's going on.
Thanks!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply
* [PATCHv14][ 3/4] video: Kconfig: Allow more broad selection of the imxfb framebuffer driver.
From: Tomi Valkeinen @ 2014-02-14 8:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390410577-22073-3-git-send-email-denis@eukrea.com>
Hi,
On 22/01/14 19:09, Denis Carikli wrote:
> Without that patch, a user can't select the imxfb driver when the i.MX25 and/or
> the i.MX27 device tree board are selected and that no boards that selects
> IMX_HAVE_PLATFORM_IMX_FB are compiled in.
>
> Cc: Eric B?nard <eric@eukrea.com>
> Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-fbdev at vger.kernel.org
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> Acked-by: Shawn Guo <shawn.guo@linaro.org>
> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Applied for 3.14 fbdev fixes.
As a generic comment, I'd appreciate if you'd use normal formatting in
the patch descriptions (no double spaces in the beginning of the lines).
Tomi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140214/b4a85b49/attachment.sig>
^ permalink raw reply
* [PATCH V2 4/4] ARM: OMAP2+: AM43x: Use gptimer as clocksource
From: Rajendra Nayak @ 2014-02-14 8:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140213231919.GO28216@atomide.com>
On Friday 14 February 2014 04:49 AM, Tony Lindgren wrote:
> * Lokesh Vutla <lokeshvutla@ti.com> [140207 02:24]:
>> From: Rajendra Nayak <rnayak@ti.com>
>>
>> The SyncTimer in AM43x is clocked using the following two sources:
>> 1) An inaccuarte 32k clock (CLK_32KHZ) derived from PER DPLL, causing system
>> time to go slowly (~10% deviation).
>> 2) external 32KHz RTC clock, which may not always be available on board like
>> in the case of ePOS EVM
>>
>> Use gptimer as clocksource instead, as is done in the case of AM335x
>> (which does not have a SyncTimer). With this, system time keeping works
>> accurately.
>
> Hmm doesn't this also mean that PM for any deeper idle states won't
> work properly?
Thats true. This would mean we cannot put the peripheral/core domain down
in idle. Suspend however can still work if suspend/resume callbacks are added
to the clockevent and clocksource code to shut the non-wakeup domain timer.
regards,
Rajendra
>
> Regards,
>
> Tony
>
>> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
>> ---
>> arch/arm/mach-omap2/board-generic.c | 2 +-
>> arch/arm/mach-omap2/timer.c | 3 ++-
>> 2 files changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
>> index 8e3daa1..5679464a 100644
>> --- a/arch/arm/mach-omap2/board-generic.c
>> +++ b/arch/arm/mach-omap2/board-generic.c
>> @@ -229,7 +229,7 @@ DT_MACHINE_START(AM43_DT, "Generic AM43 (Flattened Device Tree)")
>> .init_late = am43xx_init_late,
>> .init_irq = omap_gic_of_init,
>> .init_machine = omap_generic_init,
>> - .init_time = omap3_sync32k_timer_init,
>> + .init_time = omap3_gptimer_timer_init,
>> .dt_compat = am43_boards_compat,
>> MACHINE_END
>> #endif
>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>> index 74044aa..b62de9f 100644
>> --- a/arch/arm/mach-omap2/timer.c
>> +++ b/arch/arm/mach-omap2/timer.c
>> @@ -604,7 +604,8 @@ OMAP_SYS_32K_TIMER_INIT(3_secure, 12, "secure_32k_fck", "ti,timer-secure",
>> 2, "timer_sys_ck", NULL);
>> #endif /* CONFIG_ARCH_OMAP3 */
>>
>> -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
>> +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
>> + defined(CONFIG_SOC_AM43XX)
>> OMAP_SYS_GP_TIMER_INIT(3, 2, "timer_sys_ck", NULL,
>> 1, "timer_sys_ck", "ti,timer-alwon");
>> #endif
>> --
>> 1.7.9.5
>>
^ permalink raw reply
* [PATCH v3] input: sirfsoc-onkey - report onkey untouch event by detecting pin status
From: Barry Song @ 2014-02-14 8:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140214075717.GA14682@core.coreip.homeip.net>
2014-02-14 15:57 GMT+08:00 Dmitry Torokhov <dmitry.torokhov@gmail.com>:
> Hi Barry,
>
> On Fri, Feb 14, 2014 at 11:20:01AM +0800, Barry Song wrote:
>> From: Xianglong Du <Xianglong.Du@csr.com>
>>
>> this patch adds a delayed_work to detect the untouch of onkey since HW will
>> not generate interrupt for it.
>>
>> at the same time, we move the KEY event to POWER instead of SUSPEND, which
>> will be suitable for both Android and Linux. Userspace PowerManager Daemon
>> will decide to suspend or shutdown based on how long we have touched onkey
>>
>> Signed-off-by: Xianglong Du <Xianglong.Du@csr.com>
>> Signed-off-by: Rongjun Ying <Rongjun.Ying@csr.com>
>> Signed-off-by: Barry Song <Baohua.Song@csr.com>
>> ---
>> -v3: move to use custom devres action
>
> Thank you for making the changes, however it seems that we can control
> whether the device generates interrupts or not and so we can implement
> open and close methods. If patch below works then your
> cancel_delayed_work() call should go into sirfosc_pwrc_close() and we do
> not need to use devm_free_irq() not custom action.
this one looks making lots of senses. it makes sure HW will not
trigger any SW behaviour before probe() finishes, and also makes sure
HW will not trigger any SW behaviour in remove(). i'd like xianglong
to give a quick test on it.
>
> Thanks.
>
> --
> Dmitry
>
>
> Input: sirfsoc-onkey - implement open and close methods
>
> From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>
> We can control whetehr device generates interrupts or not so let's
> implement open and close methods of input device so that we do not do any
> processing until there are users.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/misc/sirfsoc-onkey.c | 50 +++++++++++++++++++++++++++++-------
> 1 file changed, 40 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
> index e8897c3..dc7db65 100644
> --- a/drivers/input/misc/sirfsoc-onkey.c
> +++ b/drivers/input/misc/sirfsoc-onkey.c
> @@ -49,6 +49,35 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv,
> + bool enable)
> +{
> + u32 int_mask;
> +
> + int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK);
> + if (enable)
> + int_mask |= PWRC_ON_KEY_BIT;
> + else
> + int_mask &= ~PWRC_ON_KEY_BIT;
> + sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK);
> +}
> +
> +static int sirfsoc_pwrc_open(struct input_dev *input)
> +{
> + struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
> +
> + sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
> +
> + return 0;
> +}
> +
> +static void sirfsoc_pwrc_close(struct input_dev *input)
> +{
> + struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
> +
> + sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
> +}
> +
> static const struct of_device_id sirfsoc_pwrc_of_match[] = {
> { .compatible = "sirf,prima2-pwrc" },
> {},
> @@ -70,7 +99,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
> }
>
> /*
> - * we can't use of_iomap because pwrc is not mapped in memory,
> + * We can't use of_iomap because pwrc is not mapped in memory,
> * the so-called base address is only offset in rtciobrg
> */
> error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base);
> @@ -88,6 +117,11 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
> pwrcdrv->input->phys = "pwrc/input0";
> pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR);
>
> + pwrcdrv->input->open = sirfsoc_pwrc_open;
> + pwrcdrv->input->close = sirfsoc_pwrc_close;
> +
> + input_set_drvdata(pwrcdrv->input, pwrcdrv);
> +
> irq = platform_get_irq(pdev, 0);
> error = devm_request_irq(&pdev->dev, irq,
> sirfsoc_pwrc_isr, IRQF_SHARED,
> @@ -98,11 +132,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
> return error;
> }
>
> - sirfsoc_rtc_iobrg_writel(
> - sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) |
> - PWRC_ON_KEY_BIT,
> - pwrcdrv->pwrc_base + PWRC_INT_MASK);
> -
> error = input_register_device(pwrcdrv->input);
> if (error) {
> dev_err(&pdev->dev,
> @@ -129,15 +158,16 @@ static int pwrc_resume(struct device *dev)
> {
> struct platform_device *pdev = to_platform_device(dev);
> struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev);
> + struct input_dev *input = pwrcdrv->input;
>
> /*
> * Do not mask pwrc interrupt as we want pwrc work as a wakeup source
> * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
> */
> - sirfsoc_rtc_iobrg_writel(
> - sirfsoc_rtc_iobrg_readl(
> - pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT,
> - pwrcdrv->pwrc_base + PWRC_INT_MASK);
> + mutex_lock(&input->mutex);
> + if (input->users)
> + sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
> + mutex_unlock(&input->mutex);
>
> return 0;
> }
-barry
^ 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