* [PATCH 2/3] Phytec phyFLEX-i.MX6 : Added GPMI-NAND Support
From: Ashutosh singh @ 2014-02-04 4:35 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support for GPMI-NAND on Phytec phyFLEX-i.MX6 Quad module.
Signed-off-by: Ashutosh singh <ashutosh.s@phytec.in>
---
arch/arm/boot/dts/imx6q-phytec-pbab01.dts | 4 ++++
arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi | 7 +++++++
2 files changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
index 91aecba..21c8b37 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
+++ b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
@@ -21,6 +21,10 @@
status = "okay";
};
+&gpmi {
+ status = "okay";
+};
+
&uart4 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
index fb39dae..8787101 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
@@ -176,6 +176,13 @@
status = "disabled";
};
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+ nand-on-flash-bbt;
+ status = "disabled";
+};
+
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart4_1>;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/3] Phytec phyFLEX-i.MX6 : Added USB_HOST Support
From: Ashutosh singh @ 2014-02-04 4:34 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support for USB_HOST on Phytec phyFLEX-i.MX6 Quad module.
Signed-off-by: Ashutosh singh <ashutosh.s@phytec.in>
---
arch/arm/boot/dts/imx6q-phytec-pbab01.dts | 4 ++++
arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi | 15 +++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
index 87c3702..91aecba 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
+++ b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
@@ -25,6 +25,10 @@
status = "okay";
};
+&usbh1 {
+ status = "okay";
+};
+
&usbotg {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
index e682bf8..fb39dae 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
@@ -27,6 +27,15 @@
gpio = <&gpio4 15 0>;
enable-active-low;
};
+
+ reg_usb_h1_vbus: regulator at 1 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_h1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 0 0>;
+ enable-active-low;
+ };
};
&ecspi3 {
@@ -144,6 +153,7 @@
MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */
MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* USB_OTG_PWR_EN */
+ MX6QDL_PAD_GPIO_0__USB_H1_PWR 0x80000000 /* USB_H1_PWR_EN */
>;
};
};
@@ -172,6 +182,11 @@
status = "disabled";
};
+&usbh1 {
+ vbus-supply = <®_usb_h1_vbus>;
+ status = "disabled";
+};
+
&usbotg {
vbus-supply = <®_usb_otg_vbus>;
pinctrl-names = "default";
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2] Phytec phyFLEX-i.MX6 : Added USB_OTG Support
From: Ashutosh singh @ 2014-02-04 3:39 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support for USB_OTG on Phytec phyFLEX-i.MX6 Quad module.
Signed-off-by: Ashutosh singh <ashutosh.s@phytec.in>
---
arch/arm/boot/dts/imx6q-phytec-pbab01.dts | 4 ++++
arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
index 7d37ec6..87c3702 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
+++ b/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
@@ -25,6 +25,10 @@
status = "okay";
};
+&usbotg {
+ status = "okay";
+};
+
&usdhc2 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
index 1a3b50d..e682bf8 100644
--- a/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
@@ -18,6 +18,15 @@
memory {
reg = <0x10000000 0x80000000>;
};
+
+ reg_usb_otg_vbus: regulator at 0 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 15 0>;
+ enable-active-low;
+ };
};
&ecspi3 {
@@ -134,6 +143,7 @@
MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* USB_OTG_PWR_EN */
>;
};
};
@@ -162,6 +172,14 @@
status = "disabled";
};
+&usbotg {
+ vbus-supply = <®_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg_1>;
+ disable-over-current;
+ status = "disabled";
+};
+
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2_2>;
--
1.7.9.5
^ permalink raw reply related
* a LLC sched domain bug for panda board?
From: Preeti U Murthy @ 2014-02-04 3:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKfTPtBV0cSALdVcMsnGHwQPoNCEp5CXQGg36ZAgK7kWJ6gaMQ@mail.gmail.com>
Hi Alex, Vincent,
On 02/04/2014 02:10 AM, Vincent Guittot wrote:
> Yes, it's probably worth enabling by default for all ARM arch.
>
> Vincent
>
> On 02/04/2014 12:28 AM, Vincent Guittot wrote:
>> On 3 February 2014 17:27, Vincent Guittot <vincent.guittot@linaro.org>
> wrote:
>>> Have you checked that CONFIG_SCHED_LC is set ?
>>
>> sorry it's CONFIG_SCHED_MC
>
> Thanks for reminder! no it wasn't set. Does it means
> arch/arm/configs/omap2plus_defconfig need add this config?
Hmm..ok let me think this aloud. So looks like the SMT,MC and the NUMA
sched domains are optional depending on the architecture. They are
config dependent. These domains could potentially exist on the processor
layout, but if the respective CONFIG options are not set, the scheduler
could very well ignore these levels.
What this means is that although the architecture could populate the
cpu_sibling_mask and cpu_coregroup_mask, the scheduler is not mandated
to schedule across the SMT and MC levels of the topology.
Its just the CPU sched domain which is guaranteed to be present no
matter what.
This is indeed interesting to note :) Thanks Alex for bringing up this
point :)
On PowerPC, the SCHED_MC option can never be set. Its not even optional.
On x86, it is on by default and on arm looks like its off by default.
Thanks,
Regards
Preeti U Murthy
>
>>
>>>
>>>
>>> On 3 February 2014 17:17, Alex Shi <alex.shi@linaro.org> wrote:
>>>> I just run the 3.14-rc1 kernel on panda board. The only domain for it is
>>>> 'CPU' domain, but this domain has no SD_SHARE_PKG_RESOURCES setting, it
>>>> has no sd_llc.
>>>>
>>>> Guess the right domain for this board should be MC. So is it a bug?
>>>>
>>>> ..
>>>> /proc/sys/kernel/sched_domain/cpu0/domain0/name:CPU
>>>> ..
>>>> /proc/sys/kernel/sched_domain/cpu1/domain0/name:CPU
>>>>
>>>> --
>>>> Thanks
>>>> Alex
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-kernel"
> in
>>>> the body of a message to majordomo at vger.kernel.org
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>> Please read the FAQ at http://www.tux.org/lkml/
>
> --
> Thanks
> Alex
>
^ permalink raw reply
* [PATCH v3 2/8] ARM: dts: sun7i: Add GMAC clock node to sun7i DTSI
From: Chen-Yu Tsai @ 2014-02-04 3:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140203193431.GD25625@lukather>
On Tue, Feb 4, 2014 at 3:34 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Mon, Feb 03, 2014 at 11:32:20AM +0800, Chen-Yu Tsai wrote:
>> The GMAC uses 1 of 2 sources for its transmit clock, depending on the
>> PHY interface mode. Add both sources as dummy clocks, and as parents
>> to the GMAC clock node.
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++++++++++++++
>> 1 file changed, 28 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
>> index 1595e9a..fc7f470 100644
>> --- a/arch/arm/boot/dts/sun7i-a20.dtsi
>> +++ b/arch/arm/boot/dts/sun7i-a20.dtsi
>> @@ -314,6 +314,34 @@
>> };
>>
>> /*
>> + * The following two are dummy clocks, placeholders used
>> + * on gmac_tx clock. The actual frequency and availability
>> + * depends on the external PHY, operation mode and link
>> + * speed.
>> + */
>
> If it depends on the external PHY, I guess that means it also depends
> on the board, right? Or is the GMAC supposed to always have that clock
> running at 25MHz, no matter what PHY is connected to it?
What I meant in the comment is that we cannot control the actual clock
rate of the TX clock. We can only select the source, and this is what
gmac_tx clock does. It is just a clock mux. The 125MHz and 25MHz clock
rates are used by the clk_set_rate in the stmmac glue layer to do
auto-reparenting.
The board dependent factor is what _type_ of PHY it is using, i.e.
MII, GMII, or RGMII. If it's MII, the PHY should provide the clock.
If it's RGMII, the internal clock would be used. GMII is a mix of
both. The actual clock rate depends on the link speed.
I should rephrase the comment along the lines of:
The following two are dummy clocks, placeholders used in the gmac_tx
clock. The gmac driver will choose one parent depending on the PHY
interface mode, using clk_set_rate auto-reparenting.
The actual TX clock rate is not controlled by the gmac_tx clock.
Cheers
ChenYu
^ permalink raw reply
* [PATCH v3 1/8] clk: sunxi: Add Allwinner A20/A31 GMAC clock unit
From: Chen-Yu Tsai @ 2014-02-04 2:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140203193108.GC25625@lukather>
Hi,
On Tue, Feb 4, 2014 at 3:31 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Mon, Feb 03, 2014 at 11:32:19AM +0800, Chen-Yu Tsai wrote:
>> The Allwinner A20/A31 clock module controls the transmit clock source
>> and interface type of the GMAC ethernet controller. Model this as
>> a single clock for GMAC drivers to use.
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> Documentation/devicetree/bindings/clock/sunxi.txt | 26 +++++++
>> drivers/clk/sunxi/clk-sunxi.c | 83 +++++++++++++++++++++++
>> 2 files changed, 109 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
>> index 0cf679b..f43b4c0 100644
>> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
>> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
>> @@ -37,6 +37,7 @@ Required properties:
>> "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
>> "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
>> "allwinner,sun7i-a20-out-clk" - for the external output clocks
>> + "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
>>
>> Required properties for all clocks:
>> - reg : shall be the control register address for the clock.
>> @@ -50,6 +51,9 @@ Required properties for all clocks:
>> If the clock module only has one output, the name shall be the
>> module name.
>>
>> +For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
>> +dummy clocks at 25 MHz and 125 MHz, respectively. See example.
>> +
>> Clock consumers should specify the desired clocks they use with a
>> "clocks" phandle cell. Consumers that are using a gated clock should
>> provide an additional ID in their clock property. This ID is the
>> @@ -96,3 +100,25 @@ mmc0_clk: clk at 01c20088 {
>> clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>> clock-output-names = "mmc0";
>> };
>> +
>> +mii_phy_tx_clk: clk at 2 {
>> + #clock-cells = <0>;
>> + compatible = "fixed-clock";
>> + clock-frequency = <25000000>;
>> + clock-output-names = "mii_phy_tx";
>> +};
>> +
>> +gmac_int_tx_clk: clk at 3 {
>> + #clock-cells = <0>;
>> + compatible = "fixed-clock";
>> + clock-frequency = <125000000>;
>> + clock-output-names = "gmac_int_tx";
>> +};
>> +
>> +gmac_clk: clk at 01c20164 {
>> + #clock-cells = <0>;
>> + compatible = "allwinner,sun7i-a20-gmac-clk";
>> + reg = <0x01c20164 0x4>;
>> + clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
>
> You should also document in which order you expect the parents to
> be. Or it will probably be easier to just use clock-names here.
Is it not clear from the "Required properties" section above?
>
>> + clock-output-names = "gmac";
>> +};
>> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
>> index 736fb60..0b361d2 100644
>> --- a/drivers/clk/sunxi/clk-sunxi.c
>> +++ b/drivers/clk/sunxi/clk-sunxi.c
>> @@ -379,6 +379,89 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
>>
>>
>> /**
>> + * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
>> + *
>> + * This clock looks something like this
>> + * ________________________
>> + * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
>> + * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
>> + * Ext. 125MHz RGMII TX clk >--|__divider__/ |
>> + * |________________________|
>> + *
>> + * The external 125 MHz reference is optional, i.e. GMAC can use its
>> + * internal TX clock just fine. The A31 GMAC clock module does not have
>> + * the divider controls for the external reference.
>> + *
>> + * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
>> + * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
>> + * select the appropriate source and gate/ungate the output to the PHY.
>> + *
>> + * Only the GMAC should use this clock. Altering the clock so that it doesn't
>> + * match the GMAC's operation parameters will result in the GMAC not being
>> + * able to send traffic out. The GMAC driver should set the clock rate and
>> + * enable/disable this clock to configure the required state. The clock
>> + * driver then responds by auto-reparenting the clock.
>> + */
>> +
>> +#define SUN7I_A20_GMAC_GPIT 2
>> +#define SUN7I_A20_GMAC_MASK 0x3
>> +#define SUN7I_A20_GMAC_MAX_PARENTS 2
>> +
>> +static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
>> +{
>> + struct clk *clk;
>> + struct clk_mux *mux;
>> + struct clk_gate *gate;
>> + const char *clk_name = node->name;
>> + const char *parents[SUN7I_A20_GMAC_MAX_PARENTS];
>> + void *reg;
>> + int i = 0;
>> +
>> + /* allocate mux and gate clock structs */
>> + mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
>> + if (!mux)
>> + return;
>
> Newline.
>
>> + gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
>> + if (!gate) {
>> + kfree(mux);
>> + return;
>> + }
>> +
>> + reg = of_iomap(node, 0);
>
> You should check for the return code here.
>
>> + of_property_read_string(node, "clock-output-names", &clk_name);
>
> And here too, since you made the clock-output-names property mandatory
>
>> + while (i < SUN7I_A20_GMAC_MAX_PARENTS &&
>> + (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
>
> You should check for an error here too, but if you switch to using
> clock-names, that will probably be refactored anyway.
>
>> + i++;
>> +
>> + /* set up gate and fixed rate properties */
>> + gate->reg = reg;
>> + gate->bit_idx = SUN7I_A20_GMAC_GPIT;
>> + gate->lock = &clk_lock;
>> + mux->reg = reg;
>> + mux->mask = SUN7I_A20_GMAC_MASK;
>> + mux->flags = CLK_MUX_INDEX_BIT;
>> + mux->lock = &clk_lock;
>> +
>> + clk = clk_register_composite(NULL, clk_name,
>> + parents, i,
>> + &mux->hw, &clk_mux_ops,
>> + NULL, NULL,
>> + &gate->hw, &clk_gate_ops,
>> + 0);
>> +
>> + if (!IS_ERR(clk)) {
>> + of_clk_add_provider(node, of_clk_src_simple_get, clk);
>> + clk_register_clkdev(clk, clk_name, NULL);
>> + }
>> +}
>> +CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
>> + sun7i_a20_gmac_clk_setup);
>> +
>> +
>> +
>> +/**
>> * sunxi_factors_clk_setup() - Setup function for factor clocks
>> */
>>
>> --
>> 1.9.rc1
>>
>
> It looks fine otherwise.
I'll fix the rest.
Cheers
ChenYu
^ permalink raw reply
* [RFC/RFT 1/2] ARM: mm: introduce arch hooks for dma address translation routines
From: Olof Johansson @ 2014-02-04 2:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391470107-15927-2-git-send-email-santosh.shilimkar@ti.com>
Hi,
On Mon, Feb 3, 2014 at 3:28 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> Currently arch specific DMA address translation routines can be enabled
> using only defines which makes impossible to use them in with
> multi-platform builds.
>
> Hence, introduce arch specific hooks for DMA address translations
> routines to be compatible with multi-platform builds:
> dma_addr_t (*arch_pfn_to_dma)(struct device *dev, unsigned long pfn);
> unsigned long (*arch_dma_to_pfn)(struct device *dev, dma_addr_t addr);
> void* (*arch_dma_to_virt)(struct device *dev, dma_addr_t addr);
> dma_addr_t (*arch_virt_to_dma)(struct device *dev, void *addr);
>
> In case if architecture won't use it - DMA address translation routines
> will fall-back to existing implementation.
>
> Also, modify machines omap1, ks8695, iop13xx to use new DMA hooks.
[...]
> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
> index e701a4d..84acc46 100644
> --- a/arch/arm/include/asm/dma-mapping.h
> +++ b/arch/arm/include/asm/dma-mapping.h
> @@ -55,28 +55,16 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
> * functions used internally by the DMA-mapping API to provide DMA
> * addresses. They must not be used by drivers.
> */
> -#ifndef __arch_pfn_to_dma
> -static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
> -{
> - return (dma_addr_t)__pfn_to_bus(pfn);
> -}
>
> -static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
> -{
> - return __bus_to_pfn(addr);
> -}
> +extern dma_addr_t (*__arch_pfn_to_dma)(struct device *dev, unsigned long pfn);
> +extern unsigned long (*__arch_dma_to_pfn)(struct device *dev, dma_addr_t addr);
> +extern void* (*__arch_dma_to_virt)(struct device *dev, dma_addr_t addr);
> +extern dma_addr_t (*__arch_virt_to_dma)(struct device *dev, void *addr);
I tend to prefer having these kind of function pointers grouped in a
struct instead of in the toplevel namespace like this. It allows you
to use a set_<foo>_ops() interface too instead and reduces
exposed/exported internals since only the global struct pointer has to
be exported.
>
> -static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
> -{
> - return (void *)__bus_to_virt((unsigned long)addr);
> -}
I don't actually see any in-tree users of dma_to_virt(). It can
probably be removed.
> -static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
> -{
> - return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> -}
> +/* Keep __arch_pfn_to_dma defined as it's used by some drivers (V4L2)*/
> +#define __arch_pfn_to_dma __arch_pfn_to_dma
Ick. The v4l driver should be fixed. Marek?
[...]
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index 5c43ca5..74111bf 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -39,6 +39,35 @@
>
> #include "mm.h"
>
> +static inline dma_addr_t __pfn_to_dma(struct device *dev, unsigned long pfn)
> +{
> + return (dma_addr_t)__pfn_to_bus(pfn);
> +}
> +
> +static inline unsigned long __dma_to_pfn(struct device *dev, dma_addr_t addr)
> +{
> + return __bus_to_pfn(addr);
> +}
> +
> +static inline void *__dma_to_virt(struct device *dev, dma_addr_t addr)
> +{
> + return (void *)__bus_to_virt((unsigned long)addr);
> +}
> +
> +static inline dma_addr_t __virt_to_dma(struct device *dev, void *addr)
> +{
> + return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
> +}
> +
> +dma_addr_t (*__arch_pfn_to_dma)(struct device *dev, unsigned long pfn) = __pfn_to_dma;
> +EXPORT_SYMBOL(__arch_pfn_to_dma);
> +unsigned long (*__arch_dma_to_pfn)(struct device *dev, dma_addr_t addr) = __dma_to_pfn;
> +EXPORT_SYMBOL(__arch_dma_to_pfn);
> +void* (*__arch_dma_to_virt)(struct device *dev, dma_addr_t addr) = __dma_to_virt;
> +EXPORT_SYMBOL(__arch_dma_to_virt);
> +dma_addr_t (*__arch_virt_to_dma)(struct device *dev, void *addr) = __virt_to_dma;
> +EXPORT_SYMBOL(__arch_virt_to_dma);
Independent on whether someone objects to my preference of exporting a
struct, these (or that struct pointer) should probably be
EXPORT_SYMBOL_GPL().
-Olof
^ permalink raw reply
* [PATCH] security: select correct default LSM_MMAP_MIN_ADDR on arm on arm64
From: Colin Cross @ 2014-02-04 2:15 UTC (permalink / raw)
To: linux-arm-kernel
Binaries compiled for arm may run on arm64 if CONFIG_COMPAT is
selected. Set LSM_MMAP_MIN_ADDR to 32768 if ARM64 && COMPAT to
prevent selinux failures launching 32-bit static executables that
are mapped at 0x8000.
Signed-off-by: Colin Cross <ccross@android.com>
---
security/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/Kconfig b/security/Kconfig
index e9c6ac724fef..beb86b500adf 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -103,7 +103,7 @@ config INTEL_TXT
config LSM_MMAP_MIN_ADDR
int "Low address space for LSM to protect from user allocation"
depends on SECURITY && SECURITY_SELINUX
- default 32768 if ARM
+ default 32768 if ARM || (ARM64 && COMPAT)
default 65536
help
This is the portion of low virtual memory which should be protected
--
1.9.0.rc1.175.g0b1dcb5
^ permalink raw reply related
* [PATCH v5 16/16] ARM: Remove uprobes dependency on kprobes
From: David Long @ 2014-02-04 2:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391442358.3509.19.camel@linaro1.home>
On 02/03/14 10:45, Jon Medhurst (Tixy) wrote:
> On Thu, 2014-01-23 at 15:05 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Now that arm uprobes support has been made separate from the arm kprobes code
>> the Kconfig can be changed to reflect that.
>>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>> arch/arm/Kconfig | 1 -
>> 1 file changed, 1 deletion(-)
>>
>> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
>> index fec5a6b..9ddc4ae 100644
>> --- a/arch/arm/Kconfig
>> +++ b/arch/arm/Kconfig
>> @@ -204,7 +204,6 @@ config NEED_DMA_MAP_STATE
>> def_bool y
>>
>> config ARCH_SUPPORTS_UPROBES
>> - depends on KPROBES
>> def_bool y
>>
>> config ARCH_HAS_DMA_SET_COHERENT_MASK
>
>
> Was this patch meant to have other contents? If not, it seems a bit
> pointless as all it does is remove a line added in the previous patch,
> so should just be folded into that one.
>
That patch was added late to a much earlier rev. It should have been
merged with the previous patch before now. I have just done so.
-dl
^ permalink raw reply
* [PATCH v5 07/16] ARM: Remove use of struct kprobe from generic probes code
From: David Long @ 2014-02-04 2:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391439425.3509.16.camel@linaro1.home>
On 02/03/14 09:57, Jon Medhurst (Tixy) wrote:
> On Thu, 2014-01-23 at 15:05 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Change the generic ARM probes code to pass in the opcode and architecture-specific
>> structure separately instead of using struct kprobe, so we do not pollute
>> code being used only for uprobes or other non-kprobes instruction
>> interpretation.
>>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>
> One minor nit-pick...
>
> [...]
>> diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
>> index c7ee290..cea707a 100644
>> --- a/arch/arm/kernel/kprobes-thumb.c
>> +++ b/arch/arm/kernel/kprobes-thumb.c
> [...]
>> @@ -593,7 +590,7 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
>> bx_write_pc(pc, regs);
>> }
>>
>> -static enum kprobe_insn __kprobes
>> +enum kprobe_insn __kprobes
>> t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi,
>> struct decode_header *d)
>> {
>
> The above removal of 'static' appears to be an unneeded accidental
> change?
>
Yes, that got lost during editing. The change has been made.
-dl
^ permalink raw reply
* [PATCH v5 05/16] ARM: use a function table for determining instruction interpreter action
From: David Long @ 2014-02-04 2:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391437498.3509.11.camel@linaro1.home>
On 02/03/14 09:24, Jon Medhurst (Tixy) wrote:
> On Thu, 2014-01-23 at 15:05 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Make the instruction interpreter call back to semantic action functions
>> through a function pointer array provided by the invoker. The interpreter
>> decodes the instructions into groups and uses the group number to index
>> into the supplied array. kprobes and uprobes code will each supply their
>> own array of functions.
>>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>
> [...]
>
>> --- a/arch/arm/kernel/probes.c
>> +++ b/arch/arm/kernel/probes.c
>> @@ -378,10 +378,11 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
>> */
>> int __kprobes
>> kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
>> - const union decode_item *table, bool thumb)
>> + const union decode_item *table, bool thumb,
>> + const union decode_action *actions)
>> {
>> - const struct decode_header *h = (struct decode_header *)table;
>> - const struct decode_header *next;
>> + struct decode_header *h = (struct decode_header *)table;
>> + struct decode_header *next;
>
> The decode tables are fixed structures which nothing should want to
> modify, so I think the const's above should be kept. I believe that
> you've had to resort to changing them because the following typedef
> lacks a 'const' on the final argument....
>
I've made the change.
> [...]
>> diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
>> index c610fa9..81b6e61 100644
> [...]
>>
>> +typedef enum kprobe_insn (probes_custom_decode_t)(kprobe_opcode_t,
>> + struct arch_specific_insn *,
>> + struct decode_header *);
>> +
>
> Adding 'const' above will also have the knock on effect of requiring
> const on all the 'custom decode' functions as well.
>
I've made those numerous changes as well.
-dl
^ permalink raw reply
* [RFC/RFT 2/2] ARM: keystone: Install hooks for dma address translation routines
From: Olof Johansson @ 2014-02-04 2:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391470107-15927-3-git-send-email-santosh.shilimkar@ti.com>
Hi,
On Mon, Feb 3, 2014 at 3:28 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> Keystone platforms have their physical memory mapped at an address
> outside the 32-bit physical range. A Keystone machine with 16G of RAM
> would find its memory at 0x0800000000 - 0x0bffffffff.
> The system interconnect allows to perform DMA transfers from first 2G of
> physical memory (0x08 0000 0000 to 08 7FFF FFFF) which aliased in
> hardware to the 32-bit addressable space (0x80000000 - 0xffffffff),
> because DMA HW supports only 32-bits addressing.
>
> Hence, add arch hooks for dma address translation routines.
>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Olof Johansson <olof@lixom.net>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
> arch/arm/mach-keystone/keystone.c | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
> diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
> index 1b43a27..54dae03 100644
> --- a/arch/arm/mach-keystone/keystone.c
> +++ b/arch/arm/mach-keystone/keystone.c
> @@ -14,6 +14,7 @@
> #include <linux/init.h>
> #include <linux/of_platform.h>
> #include <linux/of_address.h>
> +#include <linux/dma-mapping.h>
>
> #include <asm/setup.h>
> #include <asm/mach/map.h>
> @@ -53,6 +54,28 @@ static phys_addr_t keystone_virt_to_idmap(unsigned long x)
> return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET + KEYSTONE_LOW_PHYS_START;
> }
>
> +static unsigned long keystone_dma_pfn_offset __read_mostly;
> +
> +static dma_addr_t keystone_pfn_to_dma(struct device *dev, unsigned long pfn)
> +{
> + return PFN_PHYS(pfn - keystone_dma_pfn_offset);
> +}
> +
> +static unsigned long keystone_dma_to_pfn(struct device *dev, dma_addr_t addr)
> +{
> + return PFN_DOWN(addr) + keystone_dma_pfn_offset;
> +}
> +
> +static void *keystone_dma_to_virt(struct device *dev, dma_addr_t addr)
> +{
> + return phys_to_virt(addr + PFN_PHYS(keystone_dma_pfn_offset));
> +}
> +
> +static dma_addr_t keystone_virt_to_dma(struct device *dev, void *addr)
> +{
> + return virt_to_phys(addr) - PFN_PHYS(keystone_dma_pfn_offset);
> +}
> +
> static void __init keystone_init_meminfo(void)
> {
> bool lpae = IS_ENABLED(CONFIG_ARM_LPAE);
> @@ -89,6 +112,14 @@ static void __init keystone_init_meminfo(void)
> /* Populate the arch idmap hook */
> arch_virt_to_idmap = keystone_virt_to_idmap;
>
> + /* Populate the arch DMA hooks */
> + keystone_dma_pfn_offset = PFN_DOWN(KEYSTONE_HIGH_PHYS_START -
> + KEYSTONE_LOW_PHYS_START);
> + __arch_pfn_to_dma = keystone_pfn_to_dma;
> + __arch_dma_to_pfn = keystone_dma_to_pfn;
> + __arch_dma_to_virt = keystone_dma_to_virt;
> + __arch_virt_to_dma = keystone_virt_to_dma;
Is this truly a static window, or is it going through an IOMMU that
just happens to have an identity mapping setup per default?
PPC servers use "ibm,dma-window" to describe the assigned dma address
space for busses/devices, but the window itself doesn't contain any
information about the physical address mapping (since it goes through
an iommu after that). It likely doesn't fit this particular use case,
but it's something we should look at as a base in case we need to
start looking at bindings for this instead of coding it per SoC. We'll
know more once we've seen what a few of the implementations out there
are.
-Olof
^ permalink raw reply
* [GIT PULL] ARM: mvebu: stable fix for v3.13
From: Greg KH @ 2014-02-04 1:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140114154141.GO19878@titan.lakedaemon.net>
On Tue, Jan 14, 2014 at 10:41:41AM -0500, Jason Cooper wrote:
> arm-soc folks,
>
> Sorry for the lateness in the window on this one. I'd like to see it
> get into v3.13 if possible, but if it doesn't get there till v3.13.1, I
> understand.
>
> This fixes a boot hang experienced on some Openblocks AX3-4 boards.
> Once i2c transaction support was added, it was discovered that the A0
> revision of the Armada XP had broken offload support which causes the
> kernel to hang at boot. The only way to detect this situation is to
> read the PCI config register to get the SoC revision, then disable
> offload if we are on an A0 SoC.
>
> Unfortunately, this makes for a rather large patch series against
> stable. Doing the fix in a smaller patch would create a runtime
> dependency between i2c and PCI which we prefer to avoid.
>
> I'm Cc'ing Greg and linux-stable as a heads-up, and so they can comment
> or ask questions.
It's a big change for stable, but as it's self-contained, and only
touches one platform/driver, I'll take it...
greg k-h
^ permalink raw reply
* [PATCH] dma: mv_xor: Silence a bunch of LPAE-related warnings
From: Olof Johansson @ 2014-02-04 1:13 UTC (permalink / raw)
To: linux-arm-kernel
Enabling some of the mvebu platforms in the multiplatform config for ARM
enabled these drivers, which also triggered a bunch of warnings when LPAE
is enabled (thus making phys_addr_t 64-bit).
Most changes are switching printk formats, but also a bit of changes to what
used to be array-based pointer arithmetic that could just be done with the
address types instead.
The warnings were:
drivers/dma/mv_xor.c: In function 'mv_xor_tx_submit':
drivers/dma/mv_xor.c:500:3: warning: format '%x' expects argument of type
'unsigned int', but argument 4 has type 'dma_addr_t' [-Wformat]
drivers/dma/mv_xor.c: In function 'mv_xor_alloc_chan_resources':
drivers/dma/mv_xor.c:553:13: warning: cast to pointer from integer of
different size [-Wint-to-pointer-cast]
drivers/dma/mv_xor.c:555:4: warning: cast from pointer to integer of
different size [-Wpointer-to-int-cast]
drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_memcpy':
drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type
'unsigned int', but argument 5 has type 'dma_addr_t' [-Wformat]
drivers/dma/mv_xor.c:584:2: warning: format '%x' expects argument of type
'unsigned int', but argument 6 has type 'dma_addr_t' [-Wformat]
drivers/dma/mv_xor.c: In function 'mv_xor_prep_dma_xor':
drivers/dma/mv_xor.c:628:2: warning: format '%u' expects argument of type
'unsigned int', but argument 7 has type 'dma_addr_t' [-Wformat]
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/dma/mv_xor.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 53fb0c8365b0..766b68ed505c 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -497,8 +497,8 @@ mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
if (!mv_can_chain(grp_start))
goto submit_done;
- dev_dbg(mv_chan_to_devp(mv_chan), "Append to last desc %x\n",
- old_chain_tail->async_tx.phys);
+ dev_dbg(mv_chan_to_devp(mv_chan), "Append to last desc %pa\n",
+ &old_chain_tail->async_tx.phys);
/* fix up the hardware chain */
mv_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
@@ -527,7 +527,8 @@ submit_done:
/* returns the number of allocated descriptors */
static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
{
- char *hw_desc;
+ void *virt_desc;
+ dma_addr_t dma_desc;
int idx;
struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
struct mv_xor_desc_slot *slot = NULL;
@@ -542,17 +543,16 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
" %d descriptor slots", idx);
break;
}
- hw_desc = (char *) mv_chan->dma_desc_pool_virt;
- slot->hw_desc = (void *) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+ virt_desc = mv_chan->dma_desc_pool_virt;
+ slot->hw_desc = virt_desc + idx * MV_XOR_SLOT_SIZE;
dma_async_tx_descriptor_init(&slot->async_tx, chan);
slot->async_tx.tx_submit = mv_xor_tx_submit;
INIT_LIST_HEAD(&slot->chain_node);
INIT_LIST_HEAD(&slot->slot_node);
INIT_LIST_HEAD(&slot->tx_list);
- hw_desc = (char *) mv_chan->dma_desc_pool;
- slot->async_tx.phys =
- (dma_addr_t) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+ dma_desc = mv_chan->dma_desc_pool;
+ slot->async_tx.phys = dma_desc + idx * MV_XOR_SLOT_SIZE;
slot->idx = idx++;
spin_lock_bh(&mv_chan->lock);
@@ -582,8 +582,8 @@ mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
int slot_cnt;
dev_dbg(mv_chan_to_devp(mv_chan),
- "%s dest: %x src %x len: %u flags: %ld\n",
- __func__, dest, src, len, flags);
+ "%s dest: %pad src %pad len: %u flags: %ld\n",
+ __func__, &dest, &src, len, flags);
if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
return NULL;
@@ -626,8 +626,8 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
BUG_ON(len > MV_XOR_MAX_BYTE_COUNT);
dev_dbg(mv_chan_to_devp(mv_chan),
- "%s src_cnt: %d len: dest %x %u flags: %ld\n",
- __func__, src_cnt, len, dest, flags);
+ "%s src_cnt: %d len: %u dest %pad flags: %ld\n",
+ __func__, src_cnt, len, &dest, flags);
spin_lock_bh(&mv_chan->lock);
slot_cnt = mv_chan_xor_slot_count(len, src_cnt);
--
1.8.4.1.601.g02b3b1d
^ permalink raw reply related
* [PATCH 2/3] mmc: sh-mmcif: add DMA SG synchronisation
From: Simon Horman @ 2014-02-04 0:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <Pine.LNX.4.64.1401311249070.3234@axis700.grange>
On Fri, Jan 31, 2014 at 12:54:29PM +0100, Guennadi Liakhovetski wrote:
> According to the DMA API data has to be synchronised before starting
> a DMA transfer to device and after completing a DMA transfer from device.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
> ---
> drivers/mmc/host/sh_mmcif.c | 18 ++++++++++--------
> 1 files changed, 10 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
> index d032b08..902780c 100644
> --- a/drivers/mmc/host/sh_mmcif.c
> +++ b/drivers/mmc/host/sh_mmcif.c
> @@ -345,6 +345,8 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
> DMA_TO_DEVICE);
> if (ret > 0) {
> host->dma_active = true;
> + dma_sync_sg_for_device(chan->device->dev, sg, data->sg_len,
> + DMA_TO_DEVICE);
> desc = dmaengine_prep_slave_sg(chan, sg, ret,
> DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> }
> @@ -1118,14 +1120,14 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
> time = wait_for_completion_interruptible_timeout(&host->dma_complete,
> host->timeout);
>
> - if (data->flags & MMC_DATA_READ)
> - dma_unmap_sg(host->chan_rx->device->dev,
> - data->sg, data->sg_len,
> - DMA_FROM_DEVICE);
> - else
> - dma_unmap_sg(host->chan_tx->device->dev,
> - data->sg, data->sg_len,
> - DMA_TO_DEVICE);
> + if (data->flags & MMC_DATA_READ) {
> + struct device *dev = host->chan_rx->device->dev;
> + dma_unmap_sg(dev, data->sg, data->sg_len, DMA_FROM_DEVICE);
> + dma_sync_sg_for_cpu(dev, data->sg, data->sg_len, DMA_FROM_DEVICE);
> + } else {
> + struct device *dev = host->chan_tx->device->dev;
> + dma_unmap_sg(dev, data->sg, data->sg_len, DMA_TO_DEVICE);
> + }
>
> if (host->sd_error) {
> dev_err(host->mmc->parent,
> --
> 1.7.2.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH 1/3] mmc: tmio-mmc: add DMA SG synchronisation
From: Simon Horman @ 2014-02-04 0:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <Pine.LNX.4.64.1401311248320.3234@axis700.grange>
On Fri, Jan 31, 2014 at 12:54:19PM +0100, Guennadi Liakhovetski wrote:
> According to the DMA API data has to be synchronised before starting
> a DMA transfer to device and after completing a DMA transfer from device.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
> ---
> drivers/mmc/host/tmio_mmc_dma.c | 21 ++++++++++++---------
> 1 files changed, 12 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
> index 65edb4a..a997b94 100644
> --- a/drivers/mmc/host/tmio_mmc_dma.c
> +++ b/drivers/mmc/host/tmio_mmc_dma.c
> @@ -168,9 +168,12 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
> }
>
> ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
> - if (ret > 0)
> + if (ret > 0) {
> + dma_sync_sg_for_device(chan->device->dev, sg, host->sg_len,
> + DMA_TO_DEVICE);
> desc = dmaengine_prep_slave_sg(chan, sg, ret,
> DMA_MEM_TO_DEV, DMA_CTRL_ACK);
> + }
>
> if (desc) {
> cookie = dmaengine_submit(desc);
> @@ -247,14 +250,14 @@ static void tmio_mmc_tasklet_fn(unsigned long arg)
> if (!host->data)
> goto out;
>
> - if (host->data->flags & MMC_DATA_READ)
> - dma_unmap_sg(host->chan_rx->device->dev,
> - host->sg_ptr, host->sg_len,
> - DMA_FROM_DEVICE);
> - else
> - dma_unmap_sg(host->chan_tx->device->dev,
> - host->sg_ptr, host->sg_len,
> - DMA_TO_DEVICE);
> + if (host->data->flags & MMC_DATA_READ) {
> + struct device *dev = host->chan_rx->device->dev;
> + dma_unmap_sg(dev, host->sg_ptr, host->sg_len, DMA_FROM_DEVICE);
> + dma_sync_sg_for_cpu(dev, host->sg_ptr, host->sg_len, DMA_FROM_DEVICE);
> + } else {
> + struct device *dev = host->chan_tx->device->dev;
> + dma_unmap_sg(dev, host->sg_ptr, host->sg_len, DMA_TO_DEVICE);
> + }
>
> tmio_mmc_do_data_irq(host);
> out:
> --
> 1.7.2.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH v3 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Mark Brown @ 2014-02-04 0:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140131224704.GI2950@lukather>
On Fri, Jan 31, 2014 at 11:47:04PM +0100, Maxime Ripard wrote:
> On Fri, Jan 31, 2014 at 12:48:09PM +0000, Mark Brown wrote:
> > On Fri, Jan 31, 2014 at 11:55:50AM +0100, Maxime Ripard wrote:
> > > + pm_runtime_enable(&pdev->dev);
> > > + if (!pm_runtime_enabled(&pdev->dev)) {
> > > + ret = sun6i_spi_runtime_resume(&pdev->dev);
> > > + if (ret) {
> > > + dev_err(&pdev->dev, "Couldn't resume the device\n");
> > > + return ret;
> > > + }
> > > + }
> > No, as discussed don't do this - notice how other drivers aren't written
> > this way either. Like I said leave the device powered on startup and
> > then let it be idled by runtime PM.
> Well, some SPI drivers are actually written like that (all the tegra
It's not been done consistently, no - that should be fixed.
> SPI drivers for example). It's not an excuse, but waking up the device
> only to put it back in suspend right away seems kind of
It isn't awesome, no. Ideally the runtime PM code would do this but
then you couldn't ifdef the operations which as far as I can tell is the
main thing people want from disabling it and it gets complicated for
devices that genuinely do power up on startup so here we are.
> inefficient. Plus, the pm_runtime_idle callback you suggested are
> actually calling runtime_idle, while we want to call runtime_suspend.
Yeah, I didn't actually check if I was looking at the right call there.
-------------- 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/20140204/f016f8c3/attachment.sig>
^ permalink raw reply
* [PATCH 0/4] clk: mvebu: fix clk init order
From: Sebastian Hesselbarth @ 2014-02-03 23:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140203231603.GA11613@1wt.eu>
On 02/04/2014 12:16 AM, Willy Tarreau wrote:
> On Thu, Jan 30, 2014 at 11:31:32AM +0100, Sebastian Hesselbarth wrote:
>> On 01/30/14 11:24, Gregory CLEMENT wrote:
>>> On 25/01/2014 19:19, Sebastian Hesselbarth wrote:
>>>> This patch set fixes clk init order that went upside-down with
>>>> v3.14. I haven't really investigated what caused this, but I assume
>>>> it is related with DT node reordering by addresses.
>>>
>>> Can you explain what kind of issue do you observe?
>>
>> Sure. When probing CLK_OF_DECLAREed clock drivers, clock-gating driver
>> gets registered before core-clocks. It therefore cannot resolve it's
>> parent clock name for tclk and all clock gates will have no parent
>> clock.
>>
>> Usually, you'll see in some drivers (e.g. v643xx_eth) div_by_zero errors
>> poping up, when they calculate a frequency division factors based on
>> clock gate frequency, which should have been tclk but is 0 now.
>
> Well, to be honnest, I have no idea whether your patch is the right way
> to fix the problem or not, but what I can say is that it fixes such oopses
> that appear in 3.14-rc1 when booting on mirabox :
>
> Division by zero in kernel.
Willy,
you have hit exactly the reason for this patch.
[...]
> By the way, seeing how often a trick related to the DT is nedeed to solve an
> oops or a panic, I'm really scared that this whole DT mess is just becoming
> the exact copy of the ACPI mess (but 15 years later) and we'll experience the
> same horrible things :-( Sometimes I'm wondering whether there are not too
> many structural things put in there...
To be precise, it is not a DT-related trick at all. You would have the
same issues, if you'd register those "low-level" (i.e. early) drivers
without DT. It is more about missing init ordering, here.
There could be different ways to work this out, even elevating clock
devices to "normal" probed devices could be possible. I am sure, in the
long run, it will work out, but now this is a fix for v3.14-rc1.
@Jason, Andrew, Gregory, Thomas:
Now that v3.14 is out, anything against taking this in as fixes for rc1?
Sebastian
^ permalink raw reply
* [PATCH] arm64: Add architecture support for PCI
From: Jason Gunthorpe @ 2014-02-03 23:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqL+3S8w=_Fb-t0rVcq0sDiPSDM6nqn3mR2DHKw=VTffsg@mail.gmail.com>
On Mon, Feb 03, 2014 at 05:07:48PM -0600, Rob Herring wrote:
> > An interesting question however is what the transition plan is to
> > have the code shared between arm32 and arm64: We will certainly need
> > to share at least the dw-pcie and the generic SBSA compliant pci
> > implementation.
>
> You might want to re-read the SBSA. Unless ARM provides an IP block or
> there is some other standard such as EHCI or AHCI, there is no generic
> implementation. You only have to go look at the Linux EHCI or AHCI
> drivers and see how meaningless and inadequate "use EHCI" is. For PCI,
> the text is so brief in the SBSA there will be no way PCI is going to
> just work given all the variations of root complexes, bridges, address
> windows, etc. we typically see on ARM platforms. I could be wrong and
> some AML magic will solve all the problems. :)
The biggest hinderance I've seen while looking at ARM PCI drivers is
quite simply - they don't follow the PCI-E spec. There is a spec, and
it is not followed.
This fixup in the X-Gene is a solid example, the purpose of the BAR in
a PCI-PCI bridge is very clear: using it to specify the system
DRAM aperature is completely wrong.
Not having working aperture windows in the root complex's bridges is
completely wrong.
Lacking any ability to generate 8 and 16 bit config write TLP's is
wrong.
Starting with an end-port PCI-E core and re-tasking it to be a root
port bridge and ignoring all the requirements with the bridge's config
space is utterly and completely WRONG.
Specifying 'use EHCI, AHCI, etc' - which are all PCI based standards
without clearly specifying exactly how PCI is suppose to work is
completely bonkers.
What is needed is a spec that says:
1) Here is how you generate config TLPs. A MMIO region that
conforms to the already specified x86 ECAM would
be perfect
2) Here is a dword by dword break down of the entire config space in
a SOC. Here is where a on-board AHCI controller must show up in
config space. Here is how an external PCI-E port must show
up. Etc. Most of this is already specified, but it clearly needs
to be layed out explicitly for ARM SOCs to actually follow it.
3) Here is how you specify the aperture(s) associated with PCI BAR's
and bridge windows in config space. And yes: The CONFIG SPACE
BARS MUST WORK.
4) Here is how MSI works, these are the values you put in the
address/data and here is how you collect the interrupt.
5) Here is how Legacy INTx must be mapped into the GIC.
This is what x86 does, and they have been doing it well for 10
years. If you want to play in the server game you have to properly
implement PCI.
Jason
^ permalink raw reply
* [RFC/RFT 0/2] ARM: mm: Introduce arch hooks for dma address translation
From: Santosh Shilimkar @ 2014-02-03 23:28 UTC (permalink / raw)
To: linux-arm-kernel
Currently arch specific DMA address translation routines can be enabled
using only defines wtth "mach/memory.h" which makes impossible to use them
in with multi-platform, single zImage builds.
Hence, introduce arch specific hooks for DMA address translations
routines to be compatible with multi-platform builds. In case if
an architecture won't use it - DMA address translation routines
will fall-back to existing implementation.
Series updates existing machines like omap1, ks8695, iop13xx to
use new DMA hooks.
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Greg Ungerer <gerg@uclinux.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Olof Johansson <olof@lixom.net>
CC: Grygorii Strashko <grygorii.strashko@ti.com>
Santosh Shilimkar (2):
ARM: mm: introduce arch hooks for dma address translation routines
ARM: keystone: Install hooks for dma address translation routines
arch/arm/include/asm/dma-mapping.h | 25 +++--------
arch/arm/mach-iop13xx/include/mach/memory.h | 61 ---------------------------
arch/arm/mach-iop13xx/setup.c | 58 +++++++++++++++++++++++++
arch/arm/mach-keystone/keystone.c | 31 ++++++++++++++
arch/arm/mach-ks8695/cpu.c | 50 ++++++++++++++++++++++
arch/arm/mach-ks8695/include/mach/memory.h | 33 ---------------
arch/arm/mach-omap1/include/mach/memory.h | 39 -----------------
arch/arm/mach-omap1/io.c | 52 +++++++++++++++++++++++
arch/arm/mm/dma-mapping.c | 29 +++++++++++++
9 files changed, 226 insertions(+), 152 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH 0/4] clk: mvebu: fix clk init order
From: Willy Tarreau @ 2014-02-03 23:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52EA2A04.2070109@gmail.com>
Hi Sebastian,
On Thu, Jan 30, 2014 at 11:31:32AM +0100, Sebastian Hesselbarth wrote:
> On 01/30/14 11:24, Gregory CLEMENT wrote:
> >On 25/01/2014 19:19, Sebastian Hesselbarth wrote:
> >>This patch set fixes clk init order that went upside-down with
> >>v3.14. I haven't really investigated what caused this, but I assume
> >>it is related with DT node reordering by addresses.
> >
> >Can you explain what kind of issue do you observe?
>
> Sure. When probing CLK_OF_DECLAREed clock drivers, clock-gating driver
> gets registered before core-clocks. It therefore cannot resolve it's
> parent clock name for tclk and all clock gates will have no parent
> clock.
>
> Usually, you'll see in some drivers (e.g. v643xx_eth) div_by_zero errors
> poping up, when they calculate a frequency division factors based on
> clock gate frequency, which should have been tclk but is 0 now.
Well, to be honnest, I have no idea whether your patch is the right way
to fix the problem or not, but what I can say is that it fixes such oopses
that appear in 3.14-rc1 when booting on mirabox :
Division by zero in kernel.
CPU: 0 PID: 6 Comm: kworker/u2:0 Not tainted 3.13.0-bck-mbx #6
Workqueue: kmmcd mmc_rescan
[<c0010865>] (unwind_backtrace+0x1/0x98) from [<c000e947>] (show_stack+0xb/0xc)
[<c000e947>] (show_stack+0xb/0xc) from [<c0135913>] (Ldiv0+0x9/0x12)
[<c0135913>] (Ldiv0+0x9/0x12) from [<c01f708b>] (mvsd_set_ios+0xcb/0x160)
[<c01f708b>] (mvsd_set_ios+0xcb/0x160) from [<c01ec1fd>] (__mmc_set_clock+0x2d/0
x40)
[<c01ec1fd>] (__mmc_set_clock+0x2d/0x40) from [<c01f1a59>] (mmc_sdio_init_card+0
x391/0x808)
[<c01f1a59>] (mmc_sdio_init_card+0x391/0x808) from [<c01f2163>] (mmc_attach_sdio
+0x5b/0x218)
[<c01f2163>] (mmc_attach_sdio+0x5b/0x218) from [<c01ed0d9>] (mmc_rescan+0x159/0x
1b4)
[<c01ed0d9>] (mmc_rescan+0x159/0x1b4) from [<c0024579>] (process_one_work+0xa9/0
x21c)
[<c0024579>] (process_one_work+0xa9/0x21c) from [<c002494d>] (worker_thread+0xb5
/0x248)
[<c002494d>] (worker_thread+0xb5/0x248) from [<c0027f1b>] (kthread+0x7b/0x94)
+0xa7/0x138)
[<c04228b3>] (kernel_init_freeable+0xa7/0x138) from [<c027e6cf>] (kernel_init+0x
7/0xb8)
[<c027e6cf>] (kernel_init+0x7/0xb8) from [<c000cb9d>] (ret_from_fork+0x11/0x34)
mvsdio d00d4000.mvsdio: lacking card detect (fall back to polling)
By the way, seeing how often a trick related to the DT is nedeed to solve an
oops or a panic, I'm really scared that this whole DT mess is just becoming
the exact copy of the ACPI mess (but 15 years later) and we'll experience the
same horrible things :-( Sometimes I'm wondering whether there are not too
many structural things put in there...
Regards,
Willy
^ permalink raw reply
* [PATCH] arm64: Add architecture support for PCI
From: Rob Herring @ 2014-02-03 23:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3808209.DeG1VobanZ@wuerfel>
On Mon, Feb 3, 2014 at 2:05 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 03 February 2014 19:18:38 Liviu Dudau wrote:
>> On Mon, Feb 03, 2014 at 06:58:56PM +0000, Arnd Bergmann wrote:
>> > On Monday 03 February 2014 18:43:48 Liviu Dudau wrote:
[snip]
>> Agree. This is the RFC version. I didn't dare to post a patch with fixes
>> for all architectures. :)
>
> No need to change the other architectures. You can make it opt-in for
> now and just put the code into a common location.
>
> An interesting question however is what the transition plan is to
> have the code shared between arm32 and arm64: We will certainly need
> to share at least the dw-pcie and the generic SBSA compliant pci
> implementation.
You might want to re-read the SBSA. Unless ARM provides an IP block or
there is some other standard such as EHCI or AHCI, there is no generic
implementation. You only have to go look at the Linux EHCI or AHCI
drivers and see how meaningless and inadequate "use EHCI" is. For PCI,
the text is so brief in the SBSA there will be no way PCI is going to
just work given all the variations of root complexes, bridges, address
windows, etc. we typically see on ARM platforms. I could be wrong and
some AML magic will solve all the problems. :)
Rob
^ permalink raw reply
* [PATCH v5 6/6] regmap: spmi: support base and extended register spaces
From: Josh Cartwright @ 2014-02-03 23:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391468739-20987-1-git-send-email-joshc@codeaurora.org>
SPMI states that a slave may contain two register spaces, the Base
register space is a 5-bit byte-addressable space accessed via the
Register Read/Write and Register Zero Write command sequences, and the
Extended register space: a 16-bit byte-addressable space accessed via
the Extended Read/Write and Extended Read/Write Long command sequences.
Provide support for accessing both of these spaces, taking advantage of
the more bandwidth-efficient commands ('Register 0 Write' vs 'Register
Write', and 'Extended Register Read/Write' vs 'Extended Register
Read/Write Long') when possible.
Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
Acked-by: Mark Brown <broonie@linaro.org>
---
drivers/base/regmap/regmap-spmi.c | 228 ++++++++++++++++++++++++++++++++------
include/linux/regmap.h | 12 +-
2 files changed, 205 insertions(+), 35 deletions(-)
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c
index ac23910..d7026dc 100644
--- a/drivers/base/regmap/regmap-spmi.c
+++ b/drivers/base/regmap/regmap-spmi.c
@@ -22,69 +22,235 @@
#include <linux/module.h>
#include <linux/init.h>
-static int regmap_spmi_read(void *context,
- const void *reg, size_t reg_size,
- void *val, size_t val_size)
+static int regmap_spmi_base_read(void *context,
+ const void *reg, size_t reg_size,
+ void *val, size_t val_size)
{
+ u8 addr = *(u8 *)reg;
+ int err = 0;
+
+ BUG_ON(reg_size != 1);
+
+ while (val_size-- && !err)
+ err = spmi_register_read(context, addr++, val++);
+
+ return err;
+}
+
+static int regmap_spmi_base_gather_write(void *context,
+ const void *reg, size_t reg_size,
+ const void *val, size_t val_size)
+{
+ const u8 *data = val;
+ u8 addr = *(u8 *)reg;
+ int err = 0;
+
+ BUG_ON(reg_size != 1);
+
+ /*
+ * SPMI defines a more bandwidth-efficient 'Register 0 Write' sequence,
+ * use it when possible.
+ */
+ if (addr == 0 && val_size) {
+ err = spmi_register_zero_write(context, *data);
+ if (err)
+ goto err_out;
+
+ data++;
+ addr++;
+ val_size--;
+ }
+
+ while (val_size) {
+ err = spmi_register_write(context, addr, *data);
+ if (err)
+ goto err_out;
+
+ data++;
+ addr++;
+ val_size--;
+ }
+
+err_out:
+ return err;
+}
+
+static int regmap_spmi_base_write(void *context, const void *data,
+ size_t count)
+{
+ BUG_ON(count < 1);
+ return regmap_spmi_base_gather_write(context, data, 1, data + 1,
+ count - 1);
+}
+
+static struct regmap_bus regmap_spmi_base = {
+ .read = regmap_spmi_base_read,
+ .write = regmap_spmi_base_write,
+ .gather_write = regmap_spmi_base_gather_write,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+/**
+ * regmap_init_spmi_base(): Create regmap for the Base register space
+ * @sdev: SPMI device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_spmi_base(struct spmi_device *sdev,
+ const struct regmap_config *config)
+{
+ return regmap_init(&sdev->dev, ®map_spmi_base, sdev, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_spmi_base);
+
+/**
+ * devm_regmap_init_spmi_base(): Create managed regmap for Base register space
+ * @sdev: SPMI device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap. The regmap will be automatically freed by the
+ * device management code.
+ */
+struct regmap *devm_regmap_init_spmi_base(struct spmi_device *sdev,
+ const struct regmap_config *config)
+{
+ return devm_regmap_init(&sdev->dev, ®map_spmi_base, sdev, config);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_base);
+
+static int regmap_spmi_ext_read(void *context,
+ const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ int err = 0;
+ size_t len;
+ u16 addr;
+
BUG_ON(reg_size != 2);
- return spmi_ext_register_readl(context, *(u16 *)reg,
- val, val_size);
+
+ addr = *(u16 *)reg;
+
+ /*
+ * Split accesses into two to take advantage of the more
+ * bandwidth-efficient 'Extended Register Read' command when possible
+ */
+ while (addr <= 0xFF && val_size) {
+ len = min_t(size_t, val_size, 16);
+
+ err = spmi_ext_register_read(context, addr, val, len);
+ if (err)
+ goto err_out;
+
+ addr += len;
+ val += len;
+ val_size -= len;
+ }
+
+ while (val_size) {
+ len = min_t(size_t, val_size, 8);
+
+ err = spmi_ext_register_readl(context, addr, val, val_size);
+ if (err)
+ goto err_out;
+
+ addr += len;
+ val += len;
+ val_size -= len;
+ }
+
+err_out:
+ return err;
}
-static int regmap_spmi_gather_write(void *context,
- const void *reg, size_t reg_size,
- const void *val, size_t val_size)
+static int regmap_spmi_ext_gather_write(void *context,
+ const void *reg, size_t reg_size,
+ const void *val, size_t val_size)
{
+ int err = 0;
+ size_t len;
+ u16 addr;
+
BUG_ON(reg_size != 2);
- return spmi_ext_register_writel(context, *(u16 *)reg, val, val_size);
+
+ addr = *(u16 *)reg;
+
+ while (addr <= 0xFF && val_size) {
+ len = min_t(size_t, val_size, 16);
+
+ err = spmi_ext_register_write(context, addr, val, len);
+ if (err)
+ goto err_out;
+
+ addr += len;
+ val += len;
+ val_size -= len;
+ }
+
+ while (val_size) {
+ len = min_t(size_t, val_size, 8);
+
+ err = spmi_ext_register_writel(context, addr, val, len);
+ if (err)
+ goto err_out;
+
+ addr += len;
+ val += len;
+ val_size -= len;
+ }
+
+err_out:
+ return err;
}
-static int regmap_spmi_write(void *context, const void *data,
- size_t count)
+static int regmap_spmi_ext_write(void *context, const void *data,
+ size_t count)
{
BUG_ON(count < 2);
- return regmap_spmi_gather_write(context, data, 2, data + 2, count - 2);
+ return regmap_spmi_ext_gather_write(context, data, 2, data + 2,
+ count - 2);
}
-static struct regmap_bus regmap_spmi = {
- .read = regmap_spmi_read,
- .write = regmap_spmi_write,
- .gather_write = regmap_spmi_gather_write,
+static struct regmap_bus regmap_spmi_ext = {
+ .read = regmap_spmi_ext_read,
+ .write = regmap_spmi_ext_write,
+ .gather_write = regmap_spmi_ext_gather_write,
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
};
/**
- * regmap_init_spmi(): Initialize register map
- *
- * @sdev: Device that will be interacted with
- * @config: Configuration for register map
+ * regmap_init_spmi_ext(): Create regmap for Ext register space
+ * @sdev: Device that will be interacted with
+ * @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer to
* a struct regmap.
*/
-struct regmap *regmap_init_spmi(struct spmi_device *sdev,
- const struct regmap_config *config)
+struct regmap *regmap_init_spmi_ext(struct spmi_device *sdev,
+ const struct regmap_config *config)
{
- return regmap_init(&sdev->dev, ®map_spmi, sdev, config);
+ return regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config);
}
-EXPORT_SYMBOL_GPL(regmap_init_spmi);
+EXPORT_SYMBOL_GPL(regmap_init_spmi_ext);
/**
- * devm_regmap_init_spmi(): Initialise managed register map
- *
- * @sdev: Device that will be interacted with
- * @config: Configuration for register map
+ * devm_regmap_init_spmi_ext(): Create managed regmap for Ext register space
+ * @sdev: SPMI device that will be interacted with
+ * @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer
* to a struct regmap. The regmap will be automatically freed by the
* device management code.
*/
-struct regmap *devm_regmap_init_spmi(struct spmi_device *sdev,
+struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *sdev,
const struct regmap_config *config)
{
- return devm_regmap_init(&sdev->dev, ®map_spmi, sdev, config);
+ return devm_regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config);
}
-EXPORT_SYMBOL_GPL(devm_regmap_init_spmi);
+EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_ext);
MODULE_LICENSE("GPL");
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 4149f1a..8cc73ac 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -321,8 +321,10 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config);
struct regmap *regmap_init_spi(struct spi_device *dev,
const struct regmap_config *config);
-struct regmap *regmap_init_spmi(struct spmi_device *dev,
- const struct regmap_config *config);
+struct regmap *regmap_init_spmi_base(struct spmi_device *dev,
+ const struct regmap_config *config);
+struct regmap *regmap_init_spmi_ext(struct spmi_device *dev,
+ const struct regmap_config *config);
struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
void __iomem *regs,
const struct regmap_config *config);
@@ -335,8 +337,10 @@ struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config);
struct regmap *devm_regmap_init_spi(struct spi_device *dev,
const struct regmap_config *config);
-struct regmap *devm_regmap_init_spmi(struct spmi_device *dev,
- const struct regmap_config *config);
+struct regmap *devm_regmap_init_spmi_base(struct spmi_device *dev,
+ const struct regmap_config *config);
+struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *dev,
+ const struct regmap_config *config);
struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id,
void __iomem *regs,
const struct regmap_config *config);
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [PATCH v5 5/6] spmi: document the PMIC arbiter SPMI bindings
From: Josh Cartwright @ 2014-02-03 23:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391468739-20987-1-git-send-email-joshc@codeaurora.org>
Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
---
.../bindings/spmi/qcom,spmi-pmic-arb.txt | 60 ++++++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
diff --git a/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
new file mode 100644
index 0000000..a0a5759
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
@@ -0,0 +1,60 @@
+Qualcomm SPMI Controller (PMIC Arbiter)
+
+The SPMI PMIC Arbiter is found on the Snapdragon 800 Series. It is an SPMI
+controller with wrapping arbitration logic to allow for multiple on-chip
+devices to control a single SPMI master.
+
+The PMIC Arbiter can also act as an interrupt controller, providing interrupts
+to slave devices.
+
+See spmi.txt for the generic SPMI controller binding requirements for child
+nodes.
+
+See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
+generic interrupt controller binding documentation.
+
+Required properties:
+- compatible : should be "qcom,spmi-pmic-arb".
+- reg-names : should be "core", "intr", "cnfg"
+- reg : register specifiers, must contain:
+ "core" - core registers
+ "intr" - interrupt controller registers
+ "cnfg" - configuration registers
+- #address-cells : must be set to 2
+- #size-cells : must be set to 0
+- qcom,ee : indicates the active Execution Environment identifier (0-5)
+- qcom,channel : which of the PMIC Arb provided channels to use for accesses (0-5)
+- interrupts : interrupt list for the PMIC Arb controller, must contain a
+ single interrupt entry for the peripheral interrupt
+- interrupt-names : corresponding interrupt names for the interrupts
+ listed in the 'interrupts' property, must contain:
+ "periph_irq" - summary interrupt for PMIC peripherals
+- interrupt-controller : boolean indicator that the PMIC arbiter is an interrupt controller
+- #interrupt-cells : must be set to 4. Interrupts are specified as a 4-tuple:
+ cell 1: slave ID for the requested interrupt (0-15)
+ cell 2: peripheral ID for requested interrupt (0-255)
+ cell 3: the requested peripheral interrupt (0-7)
+ cell 4: interrupt flags indicating level-sense information, as defined in
+ dt-bindings/interrupt-controller/irq.h
+
+Example:
+
+ spmi {
+ compatible = "qcom,spmi-pmic-arb";
+ reg-names = "core", "intr", "cnfg";
+ reg = <0xfc4cf000 0x1000>,
+ <0xfc4cb000 0x1000>,
+ <0xfc4ca000 0x1000>;
+
+ interrupt-names = "periph_irq";
+ interrupts = <0 190 0>;
+
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ };
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [PATCH v5 4/6] spmi: pmic_arb: add support for interrupt handling
From: Josh Cartwright @ 2014-02-03 23:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391468739-20987-1-git-send-email-joshc@codeaurora.org>
The Qualcomm PMIC Arbiter, in addition to being a basic SPMI controller,
also implements interrupt handling for slave devices. Note, this is
outside the scope of SPMI, as SPMI leaves interrupt handling completely
unspecified.
Extend the driver to provide a irq_chip implementation and chained irq
handling which allows for these interrupts to be used.
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
---
drivers/spmi/Kconfig | 1 +
drivers/spmi/spmi-pmic-arb.c | 377 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 376 insertions(+), 2 deletions(-)
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 80b7901..075bd79 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -13,6 +13,7 @@ if SPMI
config SPMI_MSM_PMIC_ARB
tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
depends on ARM
+ depends on IRQ_DOMAIN
depends on ARCH_MSM || COMPILE_TEST
default ARCH_MSM
help
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index b7f753f..e4b6854 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -13,6 +13,9 @@
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -103,6 +106,14 @@ enum pmic_arb_cmd_op_code {
* @cnfg: address of the PMIC Arbiter configuration registers.
* @lock: lock to synchronize accesses.
* @channel: which channel to use for accesses.
+ * @irq: PMIC ARB interrupt.
+ * @ee: the current Execution Environment
+ * @min_apid: minimum APID (used for bounding IRQ search)
+ * @max_apid: maximum APID
+ * @mapping_table: in-memory copy of PPID -> APID mapping table.
+ * @domain: irq domain object for PMIC IRQ domain
+ * @spmic: SPMI controller object
+ * @apid_to_ppid: cached mapping from APID to PPID
*/
struct spmi_pmic_arb_dev {
void __iomem *base;
@@ -110,6 +121,14 @@ struct spmi_pmic_arb_dev {
void __iomem *cnfg;
spinlock_t lock;
u8 channel;
+ int irq;
+ u8 ee;
+ u8 min_apid;
+ u8 max_apid;
+ u32 mapping_table[SPMI_MAPPING_TABLE_LEN];
+ struct irq_domain *domain;
+ struct spmi_controller *spmic;
+ u16 apid_to_ppid[256];
};
static inline u32 pmic_arb_base_read(struct spmi_pmic_arb_dev *dev, u32 offset)
@@ -306,12 +325,316 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
return rc;
}
+enum qpnpint_regs {
+ QPNPINT_REG_RT_STS = 0x10,
+ QPNPINT_REG_SET_TYPE = 0x11,
+ QPNPINT_REG_POLARITY_HIGH = 0x12,
+ QPNPINT_REG_POLARITY_LOW = 0x13,
+ QPNPINT_REG_LATCHED_CLR = 0x14,
+ QPNPINT_REG_EN_SET = 0x15,
+ QPNPINT_REG_EN_CLR = 0x16,
+ QPNPINT_REG_LATCHED_STS = 0x18,
+};
+
+struct spmi_pmic_arb_qpnpint_type {
+ u8 type; /* 1 -> edge */
+ u8 polarity_high;
+ u8 polarity_low;
+} __packed;
+
+/* Simplified accessor functions for irqchip callbacks */
+static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf,
+ size_t len)
+{
+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+ u8 sid = d->hwirq >> 24;
+ u8 per = d->hwirq >> 16;
+
+ if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid,
+ (per << 8) + reg, buf, len))
+ dev_err_ratelimited(&pa->spmic->dev,
+ "failed irqchip transaction on %x\n",
+ d->irq);
+}
+
+static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len)
+{
+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+ u8 sid = d->hwirq >> 24;
+ u8 per = d->hwirq >> 16;
+
+ if (pmic_arb_read_cmd(pa->spmic, SPMI_CMD_EXT_READL, sid,
+ (per << 8) + reg, buf, len))
+ dev_err_ratelimited(&pa->spmic->dev,
+ "failed irqchip transaction on %x\n",
+ d->irq);
+}
+
+static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
+{
+ unsigned int irq;
+ u32 status;
+ int id;
+
+ status = readl_relaxed(pa->intr + SPMI_PIC_IRQ_STATUS(apid));
+ while (status) {
+ id = ffs(status) - 1;
+ status &= ~(1 << id);
+ irq = irq_find_mapping(pa->domain,
+ pa->apid_to_ppid[apid] << 16
+ | id << 8
+ | apid);
+ generic_handle_irq(irq);
+ }
+}
+
+static void pmic_arb_chained_irq(unsigned int irq, struct irq_desc *desc)
+{
+ struct spmi_pmic_arb_dev *pa = irq_get_handler_data(irq);
+ struct irq_chip *chip = irq_get_chip(irq);
+ void __iomem *intr = pa->intr;
+ int first = pa->min_apid >> 5;
+ int last = pa->max_apid >> 5;
+ u32 status;
+ int i, id;
+
+ chained_irq_enter(chip, desc);
+
+ for (i = first; i <= last; ++i) {
+ status = readl_relaxed(intr +
+ SPMI_PIC_OWNER_ACC_STATUS(pa->ee, i));
+ while (status) {
+ id = ffs(status) - 1;
+ status &= ~(1 << id);
+ periph_interrupt(pa, id + i * 32);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void qpnpint_irq_ack(struct irq_data *d)
+{
+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+ u8 irq = d->hwirq >> 8;
+ u8 apid = d->hwirq;
+ unsigned long flags;
+ u8 data;
+
+ spin_lock_irqsave(&pa->lock, flags);
+ writel_relaxed(1 << irq, pa->intr + SPMI_PIC_IRQ_CLEAR(apid));
+ spin_unlock_irqrestore(&pa->lock, flags);
+
+ data = 1 << irq;
+ qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
+}
+
+static void qpnpint_irq_mask(struct irq_data *d)
+{
+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+ u8 irq = d->hwirq >> 8;
+ u8 apid = d->hwirq;
+ unsigned long flags;
+ u32 status;
+ u8 data;
+
+ spin_lock_irqsave(&pa->lock, flags);
+ status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+ if (status & SPMI_PIC_ACC_ENABLE_BIT) {
+ status = status & ~SPMI_PIC_ACC_ENABLE_BIT;
+ writel_relaxed(status, pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+ }
+ spin_unlock_irqrestore(&pa->lock, flags);
+
+ data = 1 << irq;
+ qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1);
+}
+
+static void qpnpint_irq_unmask(struct irq_data *d)
+{
+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d);
+ u8 irq = d->hwirq >> 8;
+ u8 apid = d->hwirq;
+ unsigned long flags;
+ u32 status;
+ u8 data;
+
+ spin_lock_irqsave(&pa->lock, flags);
+ status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+ if (!(status & SPMI_PIC_ACC_ENABLE_BIT)) {
+ writel_relaxed(status | SPMI_PIC_ACC_ENABLE_BIT,
+ pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+ }
+ spin_unlock_irqrestore(&pa->lock, flags);
+
+ data = 1 << irq;
+ qpnpint_spmi_write(d, QPNPINT_REG_EN_SET, &data, 1);
+}
+
+static void qpnpint_irq_enable(struct irq_data *d)
+{
+ u8 irq = d->hwirq >> 8;
+ u8 data;
+
+ qpnpint_irq_unmask(d);
+
+ data = 1 << irq;
+ qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1);
+}
+
+static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+ struct spmi_pmic_arb_qpnpint_type type;
+ u8 irq = d->hwirq >> 8;
+
+ qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
+
+ if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+ type.type |= 1 << irq;
+ if (flow_type & IRQF_TRIGGER_RISING)
+ type.polarity_high |= 1 << irq;
+ if (flow_type & IRQF_TRIGGER_FALLING)
+ type.polarity_low |= 1 << irq;
+ } else {
+ if ((flow_type & (IRQF_TRIGGER_HIGH)) &&
+ (flow_type & (IRQF_TRIGGER_LOW)))
+ return -EINVAL;
+
+ type.type &= ~(1 << irq); /* level trig */
+ if (flow_type & IRQF_TRIGGER_HIGH)
+ type.polarity_high |= 1 << irq;
+ else
+ type.polarity_low |= 1 << irq;
+ }
+
+ qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type));
+ return 0;
+}
+
+static struct irq_chip pmic_arb_irqchip = {
+ .name = "pmic_arb",
+ .irq_enable = qpnpint_irq_enable,
+ .irq_ack = qpnpint_irq_ack,
+ .irq_mask = qpnpint_irq_mask,
+ .irq_unmask = qpnpint_irq_unmask,
+ .irq_set_type = qpnpint_irq_set_type,
+ .flags = IRQCHIP_MASK_ON_SUSPEND
+ | IRQCHIP_SKIP_SET_WAKE,
+};
+
+struct spmi_pmic_arb_irq_spec {
+ unsigned slave:4;
+ unsigned per:8;
+ unsigned irq:3;
+};
+
+static int search_mapping_table(struct spmi_pmic_arb_dev *pa,
+ struct spmi_pmic_arb_irq_spec *spec,
+ u8 *apid)
+{
+ u16 ppid = spec->slave << 8 | spec->per;
+ u32 *mapping_table = pa->mapping_table;
+ int index = 0, i;
+ u32 data;
+
+ for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) {
+ data = mapping_table[index];
+
+ if (ppid & (1 << SPMI_MAPPING_BIT_INDEX(data))) {
+ if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) {
+ index = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+ } else {
+ *apid = SPMI_MAPPING_BIT_IS_1_RESULT(data);
+ return 0;
+ }
+ } else {
+ if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) {
+ index = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+ } else {
+ *apid = SPMI_MAPPING_BIT_IS_0_RESULT(data);
+ return 0;
+ }
+ }
+ }
+
+ return -ENODEV;
+}
+
+static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
+ struct device_node *controller,
+ const u32 *intspec,
+ unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ struct spmi_pmic_arb_dev *pa = d->host_data;
+ struct spmi_pmic_arb_irq_spec spec;
+ int err;
+ u8 apid;
+
+ dev_dbg(&pa->spmic->dev,
+ "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n",
+ intspec[0], intspec[1], intspec[2]);
+
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize != 4)
+ return -EINVAL;
+ if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7)
+ return -EINVAL;
+
+ spec.slave = intspec[0];
+ spec.per = intspec[1];
+ spec.irq = intspec[2];
+
+ err = search_mapping_table(pa, &spec, &apid);
+ if (err)
+ return err;
+
+ pa->apid_to_ppid[apid] = spec.slave << 8 | spec.per;
+
+ /* Keep track of {max,min}_apid for bounding search during interrupt */
+ if (apid > pa->max_apid)
+ pa->max_apid = apid;
+ if (apid < pa->min_apid)
+ pa->min_apid = apid;
+
+ *out_hwirq = spec.slave << 24
+ | spec.per << 16
+ | spec.irq << 8
+ | apid;
+ *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
+
+ dev_dbg(&pa->spmic->dev, "out_hwirq = %lu\n", *out_hwirq);
+
+ return 0;
+}
+
+static int qpnpint_irq_domain_map(struct irq_domain *d,
+ unsigned int virq,
+ irq_hw_number_t hwirq)
+{
+ struct spmi_pmic_arb_dev *pa = d->host_data;
+
+ dev_dbg(&pa->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq);
+
+ irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_level_irq);
+ irq_set_chip_data(virq, d->host_data);
+ irq_set_noprobe(virq);
+ return 0;
+}
+
+static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
+ .map = qpnpint_irq_domain_map,
+ .xlate = qpnpint_irq_domain_dt_translate,
+};
+
static int spmi_pmic_arb_probe(struct platform_device *pdev)
{
struct spmi_pmic_arb_dev *pa;
struct spmi_controller *ctrl;
struct resource *res;
- u32 channel;
+ u32 channel, ee;
int err, i;
ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pa));
@@ -319,6 +642,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
return -ENOMEM;
pa = spmi_controller_get_drvdata(ctrl);
+ pa->spmic = ctrl;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
pa->base = devm_ioremap_resource(&ctrl->dev, res);
@@ -341,6 +665,12 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
goto err_put_ctrl;
}
+ pa->irq = platform_get_irq_byname(pdev, "periph_irq");
+ if (pa->irq < 0) {
+ err = pa->irq;
+ goto err_put_ctrl;
+ }
+
err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel);
if (err) {
dev_err(&pdev->dev, "channel unspecified.\n");
@@ -355,6 +685,29 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
pa->channel = channel;
+ err = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &ee);
+ if (err) {
+ dev_err(&pdev->dev, "EE unspecified.\n");
+ goto err_put_ctrl;
+ }
+
+ if (ee > 5) {
+ dev_err(&pdev->dev, "invalid EE (%u) specified\n", ee);
+ err = -EINVAL;
+ goto err_put_ctrl;
+ }
+
+ pa->ee = ee;
+
+ for (i = 0; i < ARRAY_SIZE(pa->mapping_table); ++i)
+ pa->mapping_table[i] = readl_relaxed(
+ pa->cnfg + SPMI_MAPPING_TABLE_REG(i));
+
+ /* Initialize max_apid/min_apid to the opposite bounds, during
+ * the irq domain translation, we are sure to update these */
+ pa->max_apid = 0;
+ pa->min_apid = PMIC_ARB_MAX_PERIPHS - 1;
+
platform_set_drvdata(pdev, ctrl);
spin_lock_init(&pa->lock);
@@ -362,15 +715,31 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
ctrl->read_cmd = pmic_arb_read_cmd;
ctrl->write_cmd = pmic_arb_write_cmd;
+ dev_dbg(&pdev->dev, "adding irq domain\n");
+ pa->domain = irq_domain_add_tree(pdev->dev.of_node,
+ &pmic_arb_irq_domain_ops, pa);
+ if (!pa->domain) {
+ dev_err(&pdev->dev, "unable to create irq_domain\n");
+ err = -ENOMEM;
+ goto err_put_ctrl;
+ }
+
+ irq_set_handler_data(pa->irq, pa);
+ irq_set_chained_handler(pa->irq, pmic_arb_chained_irq);
+
err = spmi_controller_add(ctrl);
if (err)
- goto err_put_ctrl;
+ goto err_domain_remove;
dev_dbg(&ctrl->dev, "PMIC Arb Version 0x%x\n",
pmic_arb_base_read(pa, PMIC_ARB_VERSION));
return 0;
+err_domain_remove:
+ irq_set_chained_handler(pa->irq, NULL);
+ irq_set_handler_data(pa->irq, NULL);
+ irq_domain_remove(pa->domain);
err_put_ctrl:
spmi_controller_put(ctrl);
return err;
@@ -379,7 +748,11 @@ err_put_ctrl:
static int spmi_pmic_arb_remove(struct platform_device *pdev)
{
struct spmi_controller *ctrl = platform_get_drvdata(pdev);
+ struct spmi_pmic_arb_dev *pa = spmi_controller_get_drvdata(ctrl);
spmi_controller_remove(ctrl);
+ irq_set_chained_handler(pa->irq, NULL);
+ irq_set_handler_data(pa->irq, NULL);
+ irq_domain_remove(pa->domain);
spmi_controller_put(ctrl);
return 0;
}
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox