Re: Enabling DBGEN signal in GP OMAP3
At least on the am335x, the trick actually works! I have a working demo which configures ICEPick registers and even performs transactions on the debug interconnect. I've been lazy and imported a bunch of files from my baremetal projects so I could easily mess with the hardware, rudely bypassing the kernel. The whole implementation is hideous in all sorts of ways, but it gets the job done: https://github.com/dutchanddutch/jbang The key part, how to bitbang JTAG, is reasonably isolated from all this in src/jbang.cc and glues onto the device-specific part via hw-subarctic.h. You could probably also turn jbang.cc into plain C without too much effort and discard the rest... I accept that my code style is probably a bit of an acquired taste ;-) For the omap3, apart from the differences in padconf details, you'll want to change icepick_init_regs[] to just { 0x23002100 } I think and hopefully you can then write the DAPCTL regs using ap_write(). I hope this example is of any help. Matthijs -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] ARM: omap2plus_defconfig: Fix SATA and NAND for v4.0-rc
Hi, These changes fix SATA boot and NAND for OMAP based boards. I must also point out that basic SATA operation is also broken when TI_PIPE3 driver is built as a module. I will be investigating that on lower priority. -- cheers, -roger Roger Quadros (2): ARM: omap2plus_defconfig: Enable OMAP NAND BCH driver ARM: omap2plus_defconfig: Fix SATA boot arch/arm/configs/omap2plus_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] ARM: omap2plus_defconfig: Enable OMAP NAND BCH driver
Without this NAND doesn't work on most EVMs. Signed-off-by: Roger Quadros rog...@ti.com --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index b738652..b674245 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -114,6 +114,7 @@ CONFIG_MTD_PHYSMAP_OF=y CONFIG_MTD_NAND=y CONFIG_MTD_NAND_ECC_BCH=y CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_BCH=y CONFIG_MTD_ONENAND=y CONFIG_MTD_ONENAND_VERIFY_WRITE=y CONFIG_MTD_ONENAND_OMAP2=y -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] ARM: omap2plus_defconfig: Fix SATA boot
SATA operation depends on PIPE3 PHY and if we want to boot from SATA drives, we have to have the PIPE3 PHY driver built-in. Signed-off-by: Roger Quadros rog...@ti.com --- arch/arm/configs/omap2plus_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index b674245..088096f 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -375,7 +375,7 @@ CONFIG_PWM_TIEHRPWM=m CONFIG_PWM_TWL=m CONFIG_PWM_TWL_LED=m CONFIG_OMAP_USB2=m -CONFIG_TI_PIPE3=m +CONFIG_TI_PIPE3=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 6/7] DT: omap4/5: add binding for the wake-up generator
Signed-off-by: Marc Zyngier marc.zyng...@arm.com --- .../interrupt-controller/ti,omap4-wugen-mpu| 33 ++ 1 file changed, 33 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu new file mode 100644 index 000..43effa0 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu @@ -0,0 +1,33 @@ +TI OMAP4 Wake-up Generator + +All TI OMAP4/5 (and their derivatives) an interrupt controller that +routes interrupts to the GIC, and also serves as a wakeup source. It +is also referred to as WUGEN-MPU, hence the name of the binding. + +Reguired properties: + +- compatible : should contain at least ti,omap4-wugen-mpu or + ti,omap5-wugen-mpu +- reg : Specifies base physical address and size of the registers. +- interrupt-controller : Identifies the node as an interrupt controller. +- #interrupt-cells : Specifies the number of cells needed to encode an + interrupt source. The value must be 3. +- interrupt-parent : a phandle to the GIC these interrupts are routed + to. + +Notes: + +- Because this HW ultimately routes interrupts to the GIC, the + interrupt specifier must be that of the GIC. +- Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs + are explicitly forbiden. + +Example: + + wakeupgen: interrupt-controller@48281000 { + compatible = ti,omap5-wugen-mpu, ti,omap4-wugen-mpu; + interrupt-controller; + #interrupt-cells = 3; + reg = 0x48281000 0x1000; + interrupt-parent = gic; + }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 3/7] DT: update ti,irq-crossbar binding
Make it look like a real interrupt controller. Signed-off-by: Marc Zyngier marc.zyng...@arm.com --- .../devicetree/bindings/arm/omap/crossbar.txt | 18 +- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt index 4139db3..a9b28d7 100644 --- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt +++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt @@ -9,7 +9,9 @@ inputs. Required properties: - compatible : Should be ti,irq-crossbar - reg: Base address and the size of the crossbar registers. -- ti,max-irqs: Total number of irqs available at the interrupt controller. +- interrupt-controller: indicates that this block is an interrupt controller. +- interrupt-parent: the interrupt controller this block is connected to. +- ti,max-irqs: Total number of irqs available at the parent interrupt controller. - ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed. - ti,reg-size: Size of a individual register in bytes. Every individual register is assumed to be of same size. Valid sizes are 1, 2, 4. @@ -27,13 +29,13 @@ Optional properties: when the interrupt controller irq is unused (when not provided, default is 0) Examples: - crossbar_mpu: @4a02 { + crossbar_mpu: crossbar@4a002a48 { compatible = ti,irq-crossbar; reg = 0x4a002a48 0x130; ti,max-irqs = 160; ti,max-crossbar-sources = 400; ti,reg-size = 2; - ti,irqs-reserved = 0 1 2 3 5 6 131 132 139 140; + ti,irqs-reserved = 0 1 2 3 5 6 131 132; ti,irqs-skip = 10 133 139 140; }; @@ -44,10 +46,6 @@ Documentation/devicetree/bindings/arm/gic.txt for further details. An interrupt consumer on an SoC using crossbar will use: interrupts = GIC_SPI request_number interrupt_level -When the request number is between 0 to that described by -ti,max-crossbar-sources, it is assumed to be a crossbar mapping. If the -request_number is greater than ti,max-crossbar-sources, then it is mapped as a -quirky hardware mapping direct to GIC. Example: device_x@0x4a023000 { @@ -55,9 +53,3 @@ Example: interrupts = GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH; ... }; - - device_y@0x4a033000 { - /* Direct mapped GIC SPI 1 used */ - interrupts = GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH; - ... - }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 7/7] ARM: omap: convert wakeupgen to stacked domains
OMAP4/5 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead. This patch does just this, updating the DT files to actually reflect what the HW provides. BIG FAT WARNING: because the DTs were so far lying by not exposing the WUGEN HW block, kernels with this patch applied won't have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot. On a platform with this patch applied, the system looks like this: root@bacon-fat:~# cat /proc/interrupts CPU0 CPU1 16: 0 0 WUGEN 37 gp_timer 19: 233799 155916 GIC 27 arch_timer 23: 0 0 WUGEN 9 l3-dbg-irq 24: 1 0 WUGEN 10 l3-app-irq 27:282 0 WUGEN 13 omap-dma-engine 44: 0 0 4ae1.gpio 13 DMA 294: 0 0 WUGEN 20 gpmc 297:506 0 WUGEN 56 4807.i2c 298: 0 0 WUGEN 57 48072000.i2c 299: 0 0 WUGEN 61 4806.i2c 300: 0 0 WUGEN 62 4807a000.i2c 301: 8 0 WUGEN 60 4807c000.i2c 308: 2439 0 WUGEN 74 OMAP UART2 312:362 0 WUGEN 83 mmc2 313:502 0 WUGEN 86 mmc0 314: 13 0 WUGEN 94 mmc1 350: 0 0 PRCM pinctrl, pinctrl 406: 35155709 0 GIC 109 ehci_hcd:usb1 407: 0 0 WUGEN 7 palmas 409: 0 0 WUGEN 119 twl6040 410: 0 0 twl6040 5 twl6040_irq_ready 411: 0 0 twl6040 0 twl6040_irq_th IPI0: 0 1 CPU wakeup interrupts IPI1: 0 0 Timer broadcast interrupts IPI2: 95334 902334 Rescheduling interrupts IPI3: 0 0 Function call interrupts IPI4:479648 Single function call interrupts IPI5: 0 0 CPU stop interrupts IPI6: 0 0 IRQ work interrupts IPI7: 0 0 completion interrupts Err: 0 Signed-off-by: Marc Zyngier marc.zyng...@arm.com --- arch/arm/boot/dts/am4372.dtsi | 11 ++- arch/arm/boot/dts/am437x-gp-evm.dts | 1 - arch/arm/boot/dts/am437x-sk-evm.dts | 1 - arch/arm/boot/dts/am43x-epos-evm.dts | 1 - arch/arm/boot/dts/dra7.dtsi | 12 ++- arch/arm/boot/dts/dra72x.dtsi | 2 +- arch/arm/boot/dts/dra74x.dtsi | 2 +- arch/arm/boot/dts/omap4-duovero.dtsi | 2 - arch/arm/boot/dts/omap4-panda-common.dtsi | 8 +- arch/arm/boot/dts/omap4-sdp.dts | 8 +- arch/arm/boot/dts/omap4-var-som-om44.dtsi | 2 - arch/arm/boot/dts/omap4.dtsi | 18 - arch/arm/boot/dts/omap5-cm-t54.dts| 1 - arch/arm/boot/dts/omap5-uevm.dts | 2 - arch/arm/boot/dts/omap5.dtsi | 26 --- arch/arm/mach-omap2/omap-wakeupgen.c | 125 +++--- arch/arm/mach-omap2/omap-wakeupgen.h | 1 - arch/arm/mach-omap2/omap4-common.c| 17 ++-- 18 files changed, 162 insertions(+), 78 deletions(-) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index 1943fc3..8a099bc 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -15,7 +15,7 @@ / { compatible = ti,am4372, ti,am43; - interrupt-parent = gic; + interrupt-parent = wakeupgen; aliases { @@ -48,6 +48,15 @@ #interrupt-cells = 3; reg = 0x48241000 0x1000, 0x48240100 0x0100; + interrupt-parent = gic; + }; + + wakeupgen: interrupt-controller@48281000 { + compatible = ti,omap4-wugen-mpu; + interrupt-controller; + #interrupt-cells = 3; + reg = 0x48281000 0x1000; + interrupt-parent = gic; }; l2-cache-controller@48242000 { diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index f84d971..26956cb 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -352,7 +352,6 @@ reg = 0x24; compatible = ti,tps65218; interrupts = GIC_SPI 7 IRQ_TYPE_NONE; /* NMIn */ - interrupt-parent = gic; interrupt-controller; #interrupt-cells = 2; diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 832d243..8ae29c9 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -392,7 +392,6 @@ tps@24 { compatible = ti,tps65218; reg = 0x24; - interrupt-parent = gic; interrupts = GIC_SPI 7
[PATCH v5 0/7] irqchip: Move OMAP{4,5}/DRA7 to use stacked domains
This series is extracted from [4], which is trying to remove all traces of gic_arch_extn from the tree. As some maintainers are more responsive than others (understatement of the year...), I've decided to split it per sub-arch, and get it moving, at least partially. This series addresses OMAP{4,5} by converting the WUGEN to stacked domains. The DRA7 crossbar gets the same treatment. It is worth realizing that: - I haven't been able to test this as much as I would have wanted to (it's only been tested on omap4 and omap5). - This actively *breaks* existing setups. Once you boot a new kernel with an old DT, suspend/resume *will* be broken. Old kernels on a new DT won't even boot! You've been warned. This really outline the necessity of actually describing the HW in device trees... Based on 4.0-rc1. * From v4: [4] - Extracted from the full series - Rebased on 4.0-rc1 * From v3 [3]: - Rebased on top of the patch working around hardcoded IRQ on OMAP4/5 [4] - Fixed more iMX6 DTs (Stephan) - Fixed Exynos4/5 DTs * From v2 [2]: - Addressed numerous comments from Thierry - Merged bug fixes from Nishanth - Merged bug fix from Stefan * From v1 [1]: - Rebased on 3.19-rc3 - Fixed a number of additional platforms - Added crossbar conversion to stacked domains - Merged bug fixes from Nishanth [4]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/317531.html [3]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/315385.html [2]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314041.html [1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/307338.html Marc Zyngier (7): genirq: Add irqchip_set_wake_parent irqchip: crossbar: convert dra7 crossbar to stacked domains DT: update ti,irq-crossbar binding irqchip: GIC: get rid of routable domain DT: arm,gic: kill arm,routable-irqs DT: omap4/5: add binding for the wake-up generator ARM: omap: convert wakeupgen to stacked domains Documentation/devicetree/bindings/arm/gic.txt | 6 - .../devicetree/bindings/arm/omap/crossbar.txt | 18 +- .../interrupt-controller/ti,omap4-wugen-mpu| 33 arch/arm/boot/dts/am4372.dtsi | 11 +- arch/arm/boot/dts/am437x-gp-evm.dts| 1 - arch/arm/boot/dts/am437x-sk-evm.dts| 1 - arch/arm/boot/dts/am43x-epos-evm.dts | 1 - arch/arm/boot/dts/am57xx-beagle-x15.dts| 3 +- arch/arm/boot/dts/dra7-evm.dts | 2 +- arch/arm/boot/dts/dra7.dtsi| 43 +++-- arch/arm/boot/dts/dra72-evm.dts| 1 - arch/arm/boot/dts/dra72x.dtsi | 3 +- arch/arm/boot/dts/dra74x.dtsi | 5 +- arch/arm/boot/dts/omap4-duovero.dtsi | 2 - arch/arm/boot/dts/omap4-panda-common.dtsi | 8 +- arch/arm/boot/dts/omap4-sdp.dts| 8 +- arch/arm/boot/dts/omap4-var-som-om44.dtsi | 2 - arch/arm/boot/dts/omap4.dtsi | 18 +- arch/arm/boot/dts/omap5-cm-t54.dts | 1 - arch/arm/boot/dts/omap5-uevm.dts | 2 - arch/arm/boot/dts/omap5.dtsi | 26 ++- arch/arm/mach-omap2/omap-wakeupgen.c | 125 ++--- arch/arm/mach-omap2/omap-wakeupgen.h | 1 - arch/arm/mach-omap2/omap4-common.c | 21 +-- drivers/irqchip/irq-crossbar.c | 207 - drivers/irqchip/irq-gic.c | 59 +- include/linux/irq.h| 1 + include/linux/irqchip/arm-gic.h| 6 - include/linux/irqchip/irq-crossbar.h | 11 -- kernel/irq/chip.c | 16 ++ 30 files changed, 364 insertions(+), 278 deletions(-) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu delete mode 100644 include/linux/irqchip/irq-crossbar.h -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 2/7] irqchip: crossbar: convert dra7 crossbar to stacked domains
Support for the TI crossbar used on the DRA7 family of chips is implemented as an ugly hack on the side of the GIC. Converting it to stacked domains makes it slightly more palatable, as it results in a cleanup. Unfortunately, as the DT bindings failed to acknowledge the fact that this is actually yet another interrupt controller (the third, actually), we have yet another breakage. Oh well. Signed-off-by: Marc Zyngier marc.zyng...@arm.com --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 3 +- arch/arm/boot/dts/dra7-evm.dts | 2 +- arch/arm/boot/dts/dra7.dtsi | 35 +++--- arch/arm/boot/dts/dra72-evm.dts | 1 - arch/arm/boot/dts/dra72x.dtsi | 3 +- arch/arm/boot/dts/dra74x.dtsi | 5 +- arch/arm/mach-omap2/omap4-common.c | 4 - drivers/irqchip/irq-crossbar.c | 207 ++-- include/linux/irqchip/irq-crossbar.h| 11 -- 9 files changed, 146 insertions(+), 125 deletions(-) delete mode 100644 include/linux/irqchip/irq-crossbar.h diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 03750af..170fbf9 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -454,7 +454,6 @@ mcp_rtc: rtc@6f { compatible = microchip,mcp7941x; reg = 0x6f; - interrupt-parent = gic; interrupts = GIC_SPI 2 IRQ_TYPE_LEVEL_LOW; /* IRQ_SYS_1N */ pinctrl-names = default; @@ -477,7 +476,7 @@ uart3 { status = okay; - interrupts-extended = gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH, + interrupts-extended = crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH, dra7_pmx_core 0x248; pinctrl-names = default; diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 746cddb..789ee58 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -446,7 +446,7 @@ status = okay; pinctrl-names = default; pinctrl-0 = uart1_pins; - interrupts-extended = gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH, + interrupts-extended = crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH, dra7_pmx_core 0x3e0; }; diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 5827fed..850f949 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -13,14 +13,13 @@ #include skeleton.dtsi #define MAX_SOURCES 400 -#define DIRECT_IRQ(irq) (MAX_SOURCES + irq) / { #address-cells = 1; #size-cells = 1; compatible = ti,dra7xx; - interrupt-parent = gic; + interrupt-parent = crossbar_mpu; aliases { i2c0 = i2c1; @@ -50,18 +49,19 @@ GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW), GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW), GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW); + interrupt-parent = gic; }; gic: interrupt-controller@48211000 { compatible = arm,cortex-a15-gic; interrupt-controller; #interrupt-cells = 3; - arm,routable-irqs = 192; reg = 0x48211000 0x1000, 0x48212000 0x1000, 0x48214000 0x2000, 0x48216000 0x2000; interrupts = GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH); + interrupt-parent = gic; }; /* @@ -91,8 +91,8 @@ ti,hwmods = l3_main_1, l3_main_2; reg = 0x4400 0x100, 0x4500 0x1000; - interrupts = GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH, -GIC_SPI DIRECT_IRQ(10) IRQ_TYPE_LEVEL_HIGH; + interrupts-extended = crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH, + gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH; prm: prm@4ae06000 { compatible = ti,dra7-prm; @@ -344,7 +344,7 @@ uart1: serial@4806a000 { compatible = ti,omap4-uart; reg = 0x4806a000 0x100; - interrupts-extended = gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH; + interrupts-extended = crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH; ti,hwmods = uart1; clock-frequency = 4800; status = disabled; @@ -355,7 +355,7 @@ uart2: serial@4806c000 { compatible = ti,omap4-uart; reg = 0x4806c000 0x100; - interrupts-extended = gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH; + interrupts = GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH;
[PATCH v5 5/7] DT: arm,gic: kill arm,routable-irqs
Nobody will regret it. Signed-off-by: Marc Zyngier marc.zyng...@arm.com --- Documentation/devicetree/bindings/arm/gic.txt | 6 -- 1 file changed, 6 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt index c97484b..1e0d212 100644 --- a/Documentation/devicetree/bindings/arm/gic.txt +++ b/Documentation/devicetree/bindings/arm/gic.txt @@ -56,11 +56,6 @@ Optional regions, used when the GIC doesn't have banked registers. The offset is cpu-offset * cpu-nr. -- arm,routable-irqs : Total number of gic irq inputs which are not directly - connected from the peripherals, but are routed dynamically - by a crossbar/multiplexer preceding the GIC. The GIC irq - input line is assigned dynamically when the corresponding - peripheral's crossbar line is mapped. Example: intc: interrupt-controller@fff11000 { @@ -68,7 +63,6 @@ Example: #interrupt-cells = 3; #address-cells = 1; interrupt-controller; - arm,routable-irqs = 160; reg = 0xfff11000 0x1000, 0xfff10100 0x100; }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 4/7] irqchip: GIC: get rid of routable domain
The only user of the so called routable domain functionality now being fixed, let's clean up the GIC. Signed-off-by: Marc Zyngier marc.zyng...@arm.com --- drivers/irqchip/irq-gic.c | 59 - include/linux/irqchip/arm-gic.h | 6 - 2 files changed, 5 insertions(+), 60 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 4634cf7..e3ca6da 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -798,15 +798,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_domain_set_info(d, irq, hw, gic_chip, d-host_data, handle_fasteoi_irq, NULL, NULL); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - - gic_routable_irq_domain_ops-map(d, irq, hw); } return 0; } static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq) { - gic_routable_irq_domain_ops-unmap(d, irq); } static int gic_irq_domain_xlate(struct irq_domain *d, @@ -825,16 +822,8 @@ static int gic_irq_domain_xlate(struct irq_domain *d, *out_hwirq = intspec[1] + 16; /* For SPIs, we need to add 16 more to get the GIC irq ID number */ - if (!intspec[0]) { - ret = gic_routable_irq_domain_ops-xlate(d, controller, -intspec, -intsize, -out_hwirq, -out_type); - - if (IS_ERR_VALUE(ret)) - return ret; - } + if (!intspec[0]) + *out_hwirq += 16; *out_type = intspec[2] IRQ_TYPE_SENSE_MASK; @@ -891,37 +880,6 @@ static const struct irq_domain_ops gic_irq_domain_ops = { .xlate = gic_irq_domain_xlate, }; -/* Default functions for routable irq domain */ -static int gic_routable_irq_domain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - return 0; -} - -static void gic_routable_irq_domain_unmap(struct irq_domain *d, - unsigned int irq) -{ -} - -static int gic_routable_irq_domain_xlate(struct irq_domain *d, - struct device_node *controller, - const u32 *intspec, unsigned int intsize, - unsigned long *out_hwirq, - unsigned int *out_type) -{ - *out_hwirq += 16; - return 0; -} - -static const struct irq_domain_ops gic_default_routable_irq_domain_ops = { - .map = gic_routable_irq_domain_map, - .unmap = gic_routable_irq_domain_unmap, - .xlate = gic_routable_irq_domain_xlate, -}; - -const struct irq_domain_ops *gic_routable_irq_domain_ops = - gic_default_routable_irq_domain_ops; - void __init gic_init_bases(unsigned int gic_nr, int irq_start, void __iomem *dist_base, void __iomem *cpu_base, u32 percpu_offset, struct device_node *node) @@ -929,7 +887,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, irq_hw_number_t hwirq_base; struct gic_chip_data *gic; int gic_irqs, irq_base, i; - int nr_routable_irqs; BUG_ON(gic_nr = MAX_GIC_NR); @@ -985,15 +942,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic-gic_irqs = gic_irqs; if (node) { /* DT case */ - const struct irq_domain_ops *ops = gic_irq_domain_hierarchy_ops; - - if (!of_property_read_u32(node, arm,routable-irqs, - nr_routable_irqs)) { - ops = gic_irq_domain_ops; - gic_irqs = nr_routable_irqs; - } - - gic-domain = irq_domain_add_linear(node, gic_irqs, ops, gic); + gic-domain = irq_domain_add_linear(node, gic_irqs, + gic_irq_domain_hierarchy_ops, + gic); } else {/* Non-DT case */ /* * For primary GICs, skip over SGIs. diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 71d706d..3978c5b 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -115,11 +115,5 @@ int gic_get_cpu_id(unsigned int cpu); void gic_migrate_target(unsigned int new_cpu_id); unsigned long gic_get_sgir_physaddr(void); -extern const struct irq_domain_ops *gic_routable_irq_domain_ops; -static inline void __init register_routable_domain_ops - (const struct irq_domain_ops *ops) -{ - gic_routable_irq_domain_ops = ops; -}
[PATCH v5 1/7] genirq: Add irqchip_set_wake_parent
This proves to be useful with stacked domains, when the current domain doesn't implement wake-up, but expect the parent to do so. Signed-off-by: Marc Zyngier marc.zyng...@arm.com --- include/linux/irq.h | 1 + kernel/irq/chip.c | 16 2 files changed, 17 insertions(+) diff --git a/include/linux/irq.h b/include/linux/irq.h index d09ec7a..3057c48 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -460,6 +460,7 @@ extern void irq_chip_eoi_parent(struct irq_data *data); extern int irq_chip_set_affinity_parent(struct irq_data *data, const struct cpumask *dest, bool force); +extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on); #endif /* Handling of unhandled and spurious interrupts: */ diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 6f1c7a5..eb9a4ea 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -948,6 +948,22 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data) return -ENOSYS; } + +/** + * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt + * @data: Pointer to interrupt specific data + * @on:Whether to set or reset the wake-up capability of this irq + * + * Conditional, as the underlying parent chip might not implement it. + */ +int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on) +{ + data = data-parent_data; + if (data-chip-irq_set_wake) + return data-chip-irq_set_wake(data, on); + + return -ENOSYS; +} #endif /** -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] ARM OMAP2+ GPMC: always program GPMCFCLKDIVIDER
On Tue, Feb 17, 2015 at 3:25 PM, Roger Quadros rog...@ti.com wrote: one more thing to note is that just specifying sync-clk-ps in DT is not enough for asynchronous devices. The driver doesn't set gpmc_t-sync_clk if gpmc,sync-read or gpmc,sync-write was not set in the DT, which would be the case for asynchronous devices. You're mistaken. It's always parsed, no matter what. See [1]. But I did implement your suggestion of computing the divider in the mean time. I'm going to send the patches rebased to 3.19 tomorrow, after I tested them. What is your proposal to make things better? And what is your use case that doesn't work with existing setup? Well, the current setup was obviously inspired by an asynchronous-only use-case, where all the timings are in seconds and get converted on-the-fly. Of course, currently, there is no support to re-compute them once the gpmc_fclk changes frequency, but I guess that's what the TODO about the clock framework is about? Anyway, my synchronous use-case is inherently... synchronous. Synchronous protocols shouldn't be specified in ns at all. They should directly be specified in clock ticks. This is also advantageous, as changes in gpmc_fclk don't need to propagate to the registers. My main grief with the current setup is its dependency on the *unknown* gpmc_fclk period at startup when the DT is processed and GPMC code is called. For instance, my private DT currently operates on the assumption of 166 Mhz L3 clk (and therefore gpmc_fclk), so all my timings are in multiples of 6 ns. Should now a colleague of mine think it would be a splendid idea to change this frequency by means of bootloader options [to save power, to process data even faster, etc], everything would break, because the L3 might have to be clocked at 100 MHz (due to divider limits along the clock tree for example) thus making my gpmc_fclk period 10ns. Now all my synchronous timings are wrong, because all DT values round to different clock ticks. One solution would obviously be very verbose: Split synchronous and asynchronous timings completely. Have a time-ns and a time-tck (where time is waitmonitoring, or readaccess etc) setting for different use cases. This would work for truly asynchronous (read _and_ write asynchronous) as well as truly synchronous (read _and_ write synchronous) setups. This 'simple' model breaks for parts where one form of access is synchronous while the other is asynchronous, e.g. Spansion WS/NS/VS parts, see [2] pg. 10. There's no easy solution for mixed timings, because some timing parameters are shared between synchronous and asynchronous accesses (WAITMONITORINGTIME, CSONTIME, ADVONTIME, WRDATAONADMUXBUS etc.). One obvious solution is to try to slow the synchronous side down until asynchronous timings can be met, but that would make for very slow accesses in most cases. For instance, I originally started out thinking the GPMC would run at 100 MHz externally -- because it's the max frequency rating -- only to be surprised when the clock looked weird on the GPMC_CLK pin, because it was at 166 MHz. I'm not sure how to completely remedy this, but specifying timings in ns in DT and then depending on the correct board frequency is kind of shady... :( Regards, Robert [1]: http://lxr.free-electrons.com/source/drivers/memory/omap-gpmc.c#L1509 [2]: http://processors.wiki.ti.com/images/5/56/SpansionNOR-AM35x.pdf ; (WS/NS/VS can be used for synchronous burst read / asynchronous single write) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 0/7] irqchip: Move OMAP{4,5}/DRA7 to use stacked domains
On 02/23/2015 02:32 PM, Nishanth Menon wrote: On 17:44-20150223, Marc Zyngier wrote: This series is extracted from [4], which is trying to remove all traces of gic_arch_extn from the tree. As some maintainers are more responsive than others (understatement of the year...), I've decided to split it per sub-arch, and get it moving, at least partially. This series addresses OMAP{4,5} by converting the WUGEN to stacked domains. The DRA7 crossbar gets the same treatment. It is worth realizing that: - I haven't been able to test this as much as I would have wanted to (it's only been tested on omap4 and omap5). - This actively *breaks* existing setups. Once you boot a new kernel with an old DT, suspend/resume *will* be broken. Old kernels on a new DT won't even boot! You've been warned. This really outline the necessity of actually describing the HW in device trees... Based on 4.0-rc1. * From v4: [4] - Extracted from the full series - Rebased on 4.0-rc1 * From v3 [3]: - Rebased on top of the patch working around hardcoded IRQ on OMAP4/5 [4] - Fixed more iMX6 DTs (Stephan) - Fixed Exynos4/5 DTs * From v2 [2]: - Addressed numerous comments from Thierry - Merged bug fixes from Nishanth - Merged bug fix from Stefan * From v1 [1]: - Rebased on 3.19-rc3 - Fixed a number of additional platforms - Added crossbar conversion to stacked domains - Merged bug fixes from Nishanth [4]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/317531.html [3]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/315385.html [2]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314041.html [1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/307338.html Marc Zyngier (7): genirq: Add irqchip_set_wake_parent irqchip: crossbar: convert dra7 crossbar to stacked domains DT: update ti,irq-crossbar binding irqchip: GIC: get rid of routable domain DT: arm,gic: kill arm,routable-irqs DT: omap4/5: add binding for the wake-up generator ARM: omap: convert wakeupgen to stacked domains Documentation/devicetree/bindings/arm/gic.txt | 6 - .../devicetree/bindings/arm/omap/crossbar.txt | 18 +- .../interrupt-controller/ti,omap4-wugen-mpu| 33 arch/arm/boot/dts/am4372.dtsi | 11 +- arch/arm/boot/dts/am437x-gp-evm.dts| 1 - arch/arm/boot/dts/am437x-sk-evm.dts| 1 - arch/arm/boot/dts/am43x-epos-evm.dts | 1 - arch/arm/boot/dts/am57xx-beagle-x15.dts| 3 +- arch/arm/boot/dts/dra7-evm.dts | 2 +- arch/arm/boot/dts/dra7.dtsi| 43 +++-- arch/arm/boot/dts/dra72-evm.dts| 1 - arch/arm/boot/dts/dra72x.dtsi | 3 +- arch/arm/boot/dts/dra74x.dtsi | 5 +- arch/arm/boot/dts/omap4-duovero.dtsi | 2 - arch/arm/boot/dts/omap4-panda-common.dtsi | 8 +- arch/arm/boot/dts/omap4-sdp.dts| 8 +- arch/arm/boot/dts/omap4-var-som-om44.dtsi | 2 - arch/arm/boot/dts/omap4.dtsi | 18 +- arch/arm/boot/dts/omap5-cm-t54.dts | 1 - arch/arm/boot/dts/omap5-uevm.dts | 2 - arch/arm/boot/dts/omap5.dtsi | 26 ++- arch/arm/mach-omap2/omap-wakeupgen.c | 125 ++--- arch/arm/mach-omap2/omap-wakeupgen.h | 1 - arch/arm/mach-omap2/omap4-common.c | 21 +-- drivers/irqchip/irq-crossbar.c | 207 - drivers/irqchip/irq-gic.c | 59 +- include/linux/irq.h| 1 + include/linux/irqchip/arm-gic.h| 6 - include/linux/irqchip/irq-crossbar.h | 11 -- kernel/irq/chip.c | 16 ++ 30 files changed, 364 insertions(+), 278 deletions(-) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu delete mode 100644 include/linux/irqchip/irq-crossbar.h marc-test-irq (Applied the series to v4.0-rc1) - boot logs: 1: am335x-evm: BOOT: PASS: http://paste.ubuntu.org.cn/2469913 2: am335x-sk: BOOT: PASS: http://paste.ubuntu.org.cn/2469914 3: am3517-evm: BOOT: PASS: http://paste.ubuntu.org.cn/2469915 4: am37x-evm: BOOT: PASS: http://paste.ubuntu.org.cn/2469916 5: am437x-sk: BOOT: PASS: http://paste.ubuntu.org.cn/2469917 6:am43xx-epos: BOOT: PASS: http://paste.ubuntu.org.cn/2469918 7: am43xx-gpevm: BOOT: PASS: http://paste.ubuntu.org.cn/2469919 8: BeagleBoard-XM: BOOT: PASS: http://paste.ubuntu.org.cn/2469920 9
Re: [PATCH v5 0/7] irqchip: Move OMAP{4,5}/DRA7 to use stacked domains
On 17:44-20150223, Marc Zyngier wrote: This series is extracted from [4], which is trying to remove all traces of gic_arch_extn from the tree. As some maintainers are more responsive than others (understatement of the year...), I've decided to split it per sub-arch, and get it moving, at least partially. This series addresses OMAP{4,5} by converting the WUGEN to stacked domains. The DRA7 crossbar gets the same treatment. It is worth realizing that: - I haven't been able to test this as much as I would have wanted to (it's only been tested on omap4 and omap5). - This actively *breaks* existing setups. Once you boot a new kernel with an old DT, suspend/resume *will* be broken. Old kernels on a new DT won't even boot! You've been warned. This really outline the necessity of actually describing the HW in device trees... Based on 4.0-rc1. * From v4: [4] - Extracted from the full series - Rebased on 4.0-rc1 * From v3 [3]: - Rebased on top of the patch working around hardcoded IRQ on OMAP4/5 [4] - Fixed more iMX6 DTs (Stephan) - Fixed Exynos4/5 DTs * From v2 [2]: - Addressed numerous comments from Thierry - Merged bug fixes from Nishanth - Merged bug fix from Stefan * From v1 [1]: - Rebased on 3.19-rc3 - Fixed a number of additional platforms - Added crossbar conversion to stacked domains - Merged bug fixes from Nishanth [4]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/317531.html [3]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/315385.html [2]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314041.html [1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/307338.html Marc Zyngier (7): genirq: Add irqchip_set_wake_parent irqchip: crossbar: convert dra7 crossbar to stacked domains DT: update ti,irq-crossbar binding irqchip: GIC: get rid of routable domain DT: arm,gic: kill arm,routable-irqs DT: omap4/5: add binding for the wake-up generator ARM: omap: convert wakeupgen to stacked domains Documentation/devicetree/bindings/arm/gic.txt | 6 - .../devicetree/bindings/arm/omap/crossbar.txt | 18 +- .../interrupt-controller/ti,omap4-wugen-mpu| 33 arch/arm/boot/dts/am4372.dtsi | 11 +- arch/arm/boot/dts/am437x-gp-evm.dts| 1 - arch/arm/boot/dts/am437x-sk-evm.dts| 1 - arch/arm/boot/dts/am43x-epos-evm.dts | 1 - arch/arm/boot/dts/am57xx-beagle-x15.dts| 3 +- arch/arm/boot/dts/dra7-evm.dts | 2 +- arch/arm/boot/dts/dra7.dtsi| 43 +++-- arch/arm/boot/dts/dra72-evm.dts| 1 - arch/arm/boot/dts/dra72x.dtsi | 3 +- arch/arm/boot/dts/dra74x.dtsi | 5 +- arch/arm/boot/dts/omap4-duovero.dtsi | 2 - arch/arm/boot/dts/omap4-panda-common.dtsi | 8 +- arch/arm/boot/dts/omap4-sdp.dts| 8 +- arch/arm/boot/dts/omap4-var-som-om44.dtsi | 2 - arch/arm/boot/dts/omap4.dtsi | 18 +- arch/arm/boot/dts/omap5-cm-t54.dts | 1 - arch/arm/boot/dts/omap5-uevm.dts | 2 - arch/arm/boot/dts/omap5.dtsi | 26 ++- arch/arm/mach-omap2/omap-wakeupgen.c | 125 ++--- arch/arm/mach-omap2/omap-wakeupgen.h | 1 - arch/arm/mach-omap2/omap4-common.c | 21 +-- drivers/irqchip/irq-crossbar.c | 207 - drivers/irqchip/irq-gic.c | 59 +- include/linux/irq.h| 1 + include/linux/irqchip/arm-gic.h| 6 - include/linux/irqchip/irq-crossbar.h | 11 -- kernel/irq/chip.c | 16 ++ 30 files changed, 364 insertions(+), 278 deletions(-) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu delete mode 100644 include/linux/irqchip/irq-crossbar.h marc-test-irq (Applied the series to v4.0-rc1) - boot logs: 1: am335x-evm: BOOT: PASS: http://paste.ubuntu.org.cn/2469913 2: am335x-sk: BOOT: PASS: http://paste.ubuntu.org.cn/2469914 3: am3517-evm: BOOT: PASS: http://paste.ubuntu.org.cn/2469915 4: am37x-evm: BOOT: PASS: http://paste.ubuntu.org.cn/2469916 5: am437x-sk: BOOT: PASS: http://paste.ubuntu.org.cn/2469917 6:am43xx-epos: BOOT: PASS: http://paste.ubuntu.org.cn/2469918 7: am43xx-gpevm: BOOT: PASS: http://paste.ubuntu.org.cn/2469919 8: BeagleBoard-XM: BOOT: PASS: http://paste.ubuntu.org.cn/2469920 9:beagleboard-vanilla: BOOT: PASS: http
Re: [PATCH 2/4] ARM OMAP2+ GPMC: always program GPMCFCLKDIVIDER
* Robert Abel ra...@cit-ec.uni-bielefeld.de [150223 13:42]: On Tue, Feb 17, 2015 at 3:25 PM, Roger Quadros rog...@ti.com wrote: one more thing to note is that just specifying sync-clk-ps in DT is not enough for asynchronous devices. The driver doesn't set gpmc_t-sync_clk if gpmc,sync-read or gpmc,sync-write was not set in the DT, which would be the case for asynchronous devices. You're mistaken. It's always parsed, no matter what. See [1]. But I did implement your suggestion of computing the divider in the mean time. I'm going to send the patches rebased to 3.19 tomorrow, after I tested them. What is your proposal to make things better? And what is your use case that doesn't work with existing setup? Well, the current setup was obviously inspired by an asynchronous-only use-case, where all the timings are in seconds and get converted on-the-fly. Of course, currently, there is no support to re-compute them once the gpmc_fclk changes frequency, but I guess that's what the TODO about the clock framework is about? Anyway, my synchronous use-case is inherently... synchronous. Synchronous protocols shouldn't be specified in ns at all. They should directly be specified in clock ticks. This is also advantageous, as changes in gpmc_fclk don't need to propagate to the registers. My main grief with the current setup is its dependency on the *unknown* gpmc_fclk period at startup when the DT is processed and GPMC code is called. For instance, my private DT currently operates on the assumption of 166 Mhz L3 clk (and therefore gpmc_fclk), so all my timings are in multiples of 6 ns. Should now a colleague of mine think it would be a splendid idea to change this frequency by means of bootloader options [to save power, to process data even faster, etc], everything would break, because the L3 might have to be clocked at 100 MHz (due to divider limits along the clock tree for example) thus making my gpmc_fclk period 10ns. Now all my synchronous timings are wrong, because all DT values round to different clock ticks. One solution would obviously be very verbose: Split synchronous and asynchronous timings completely. Have a time-ns and a time-tck (where time is waitmonitoring, or readaccess etc) setting for different use cases. This would work for truly asynchronous (read _and_ write asynchronous) as well as truly synchronous (read _and_ write synchronous) setups. This 'simple' model breaks for parts where one form of access is synchronous while the other is asynchronous, e.g. Spansion WS/NS/VS parts, see [2] pg. 10. There's no easy solution for mixed timings, because some timing parameters are shared between synchronous and asynchronous accesses (WAITMONITORINGTIME, CSONTIME, ADVONTIME, WRDATAONADMUXBUS etc.). One obvious solution is to try to slow the synchronous side down until asynchronous timings can be met, but that would make for very slow accesses in most cases. For instance, I originally started out thinking the GPMC would run at 100 MHz externally -- because it's the max frequency rating -- only to be surprised when the clock looked weird on the GPMC_CLK pin, because it was at 166 MHz. I'm not sure how to completely remedy this, but specifying timings in ns in DT and then depending on the correct board frequency is kind of shady... :( There have been few gpmc devices that were configured to work with changing L3 frequencies. For the related retime function, maybe take a look at the code removed for tusb_set_sync_mode() in commit 47acde167260. Just specifying the ticks is not enough there either.. Sorry I don't have a solution to how the timings should be specified, but both timings and ticks are needed it seems. Regards, Tony [1]: http://lxr.free-electrons.com/source/drivers/memory/omap-gpmc.c#L1509 [2]: http://processors.wiki.ti.com/images/5/56/SpansionNOR-AM35x.pdf ; (WS/NS/VS can be used for synchronous burst read / asynchronous single write) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 0/7] irqchip: Move OMAP{4,5}/DRA7 to use stacked domains
* Marc Zyngier marc.zyng...@arm.com [150223 09:48]: This series is extracted from [4], which is trying to remove all traces of gic_arch_extn from the tree. As some maintainers are more responsive than others (understatement of the year...), I've decided to split it per sub-arch, and get it moving, at least partially. This series addresses OMAP{4,5} by converting the WUGEN to stacked domains. The DRA7 crossbar gets the same treatment. It is worth realizing that: - I haven't been able to test this as much as I would have wanted to (it's only been tested on omap4 and omap5). - This actively *breaks* existing setups. Once you boot a new kernel with an old DT, suspend/resume *will* be broken. Old kernels on a new DT won't even boot! You've been warned. This really outline the necessity of actually describing the HW in device trees... Could we parse still the old binding and produce warning for the case when a new kernel is booted with the old DT? That would make it easier for people to debug what's going on. Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: advanced LED controllers
On Mon, Feb 23, 2015 at 11:34:57PM +0100, Pavel Machek wrote: On Thu 2015-02-19 15:14:24, Felipe Balbi wrote: Hi, Do we have support for LED controllers which can handle patterns of different kinds ? I mean, currently, if we have an LED controller such as TPIC2810 [1] which can control 8 different leds and each LED corresponds to one bit on register 0x44, we could control leds by just playing a wave file on the controller and create easy patterns with that. AFAICT, in linux today we would have to register each of the 8 LEDs as a different LED and have driver magic to write the proper bits on register 0x44, that seems a bit overkill, specially when we want to make patterns: instead of writing 0xff we would have to write 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 separately and have the driver cache the previous results so we don't end up switching off other LEDs. IOW, what could be handled with a single write, currently needs 8. I wonder if there's any work happening to support these slightly more inteligent LED engines. regards [1] http://www.ti.com/product/tpic2810 ps: tpic2810 is probably the simplest example, lp551, lp5523 and others have even more advanced pattern engines which can even handle RGB leds. Well... some more advanced pattern engines can actually run code, up to and including prime number computation. So yes, this is complex, and how to handle it nicely is a question... I have notcc to compile for that. right, the point is that this is a solution which only works with lp5523 and IMO linux led subsystem should do a little more for such devices. -- balbi signature.asc Description: Digital signature
Re: advanced LED controllers
On Thu 2015-02-19 15:14:24, Felipe Balbi wrote: Hi, Do we have support for LED controllers which can handle patterns of different kinds ? I mean, currently, if we have an LED controller such as TPIC2810 [1] which can control 8 different leds and each LED corresponds to one bit on register 0x44, we could control leds by just playing a wave file on the controller and create easy patterns with that. AFAICT, in linux today we would have to register each of the 8 LEDs as a different LED and have driver magic to write the proper bits on register 0x44, that seems a bit overkill, specially when we want to make patterns: instead of writing 0xff we would have to write 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 separately and have the driver cache the previous results so we don't end up switching off other LEDs. IOW, what could be handled with a single write, currently needs 8. I wonder if there's any work happening to support these slightly more inteligent LED engines. regards [1] http://www.ti.com/product/tpic2810 ps: tpic2810 is probably the simplest example, lp551, lp5523 and others have even more advanced pattern engines which can even handle RGB leds. Well... some more advanced pattern engines can actually run code, up to and including prime number computation. So yes, this is complex, and how to handle it nicely is a question... I have notcc to compile for that. #!/usr/bin/python3 # # NOTification Compiler # # for LP5523 chip. # # Copyright 2014 Pavel Machek pa...@ucw.cz, GPLv3 # # http://wiki.maemo.org/LED_patterns#Lysti_Format_Engine_Patterns_and_Commands # http://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=lp5523fileType=pdf # # Seems to have A,B local variables, C global variable, # # 2.6.28-omap1 seems to cut execution after 16 steps. import sys Pavel -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
* Felipe Balbi ba...@ti.com [150223 18:28]: Hi, On Mon, Feb 23, 2015 at 05:59:04PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 16:09]: Hi Nishanth, Olof told me about a new L3 error happening on omap5-uevm with v4.0-rc1: WARNING: CPU: 0 PID: 0 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x214/0x340() 400.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access ... I tried bisecting this with no luck, but narrowed it down to having CONFIG_CPUFREQ_DT=y causing it, while =m wont' trigger it. This got changed by commit 40d1746d2eee (ARM: omap2plus_defconfig: use CONFIG_CPUFREQ_DT). Any ideas? Hmm so setting CONFIG_CPUFREQ_DT=m in arch/arm/configs/omap2plus_defconfig produces the same output with make omap2plus_defconfig as with =y.. So CPUFREQ_DT can't be the real cause of the problem. It's now looking like the l3-noc warning does not get triggered on every boot. It also seems the zImage triggering the error does not trigger the error on every boot. To trigger the error, it seems the device needs to be powered down for at least 10 or so seconds between the boots. So far no luck reproducing the error on v3.19. The easy way to reproduce is to power down omap5 for at least 10 seconds, make omap2lus_defconfig on v4.0-rc1 and boot it. And so far it looks like next-20150204 works and next-20150209 failed at once so far. But of course I would not trust anything at this point :) got a log of the failure ? Is it pointing to a device or one of the L4s? Well mostly the MASTER MPU TARGET L4PER2, the following stack dump is really the stack dump of the l3_interrupt_handler. Might be worth to boot with just the bare minimum (UART timers) and disable everything else. You might need to build busybox and append that to the kernel so you don't need to rely on MMC/USB/etc for rootfs. After that, you could start enabling modules one by one (as modules, not built-in) and loading them one by one to see which one causes the failure. Big PITA, I know, but I can't think of any other way to go about this. It seems the best way to deal with this is to make the l3_handle_target actually show the address where the error happened to limit it down to a single device.. Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
* Tony Lindgren t...@atomide.com [150223 18:43]: * Felipe Balbi ba...@ti.com [150223 18:28]: Hi, On Mon, Feb 23, 2015 at 05:59:04PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 16:09]: Hi Nishanth, Olof told me about a new L3 error happening on omap5-uevm with v4.0-rc1: WARNING: CPU: 0 PID: 0 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x214/0x340() 400.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access ... I tried bisecting this with no luck, but narrowed it down to having CONFIG_CPUFREQ_DT=y causing it, while =m wont' trigger it. This got changed by commit 40d1746d2eee (ARM: omap2plus_defconfig: use CONFIG_CPUFREQ_DT). Any ideas? Hmm so setting CONFIG_CPUFREQ_DT=m in arch/arm/configs/omap2plus_defconfig produces the same output with make omap2plus_defconfig as with =y.. So CPUFREQ_DT can't be the real cause of the problem. It's now looking like the l3-noc warning does not get triggered on every boot. It also seems the zImage triggering the error does not trigger the error on every boot. To trigger the error, it seems the device needs to be powered down for at least 10 or so seconds between the boots. So far no luck reproducing the error on v3.19. The easy way to reproduce is to power down omap5 for at least 10 seconds, make omap2lus_defconfig on v4.0-rc1 and boot it. And so far it looks like next-20150204 works and next-20150209 failed at once so far. But of course I would not trust anything at this point :) got a log of the failure ? Is it pointing to a device or one of the L4s? Well mostly the MASTER MPU TARGET L4PER2, the following stack dump is really the stack dump of the l3_interrupt_handler. Might be worth to boot with just the bare minimum (UART timers) and disable everything else. You might need to build busybox and append that to the kernel so you don't need to rely on MMC/USB/etc for rootfs. After that, you could start enabling modules one by one (as modules, not built-in) and loading them one by one to see which one causes the failure. Big PITA, I know, but I can't think of any other way to go about this. It seems the best way to deal with this is to make the l3_handle_target actually show the address where the error happened to limit it down to a single device.. Looks like the address is 0 for Custom Error. Anyways, reverting a fix for similar issue found on omap3 so far seems to help, that's 3d009c8c61f9 (gpio: omap: Fix bad device access with setup_irq()). That got merged very late for v3.19, so it certainly explains why it was not noticed until now. Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
* Felipe Balbi ba...@ti.com [150223 19:19]: On Mon, Feb 23, 2015 at 07:01:42PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 18:43]: Looks like the address is 0 for Custom Error. Anyways, reverting yeah, that's because the error comes from l4per2, not l3 :-) Right so it seems :) a fix for similar issue found on omap3 so far seems to help, that's 3d009c8c61f9 (gpio: omap: Fix bad device access with setup_irq()). if we revert that, we regress omap3, right ? Yes we saw that getting triggered on omap3/4 before 3d009c8c61f9. Now looking at the stack trace again, it actually has something: ... [c05999a4] (__irq_svc) from [c0599164] (_raw_spin_unlock_irqrestore+0x34/0x44) [c0599164] (_raw_spin_unlock_irqrestore) from [c0027120] (omap_hwmod_idle+0x34/0x44) [c0027120] (omap_hwmod_idle) from [c00283f8] (omap_device_idle+0x38/0x78) [c00283f8] (omap_device_idle) from [c0028454] (_od_runtime_suspend+0x1c/0x24) [c0028454] (_od_runtime_suspend) from [c03b5214] (__rpm_callback+0x2c/0x60) [c03b5214] (__rpm_callback) from [c03b5268] (rpm_callback+0x20/0x80) [c03b5268] (rpm_callback) from [c03b56b8] (rpm_suspend+0xe8/0x55c) [c03b56b8] (rpm_suspend) from [c03b6bdc] (pm_runtime_work+0x74/0xa8) [c03b6bdc] (pm_runtime_work) from [c0054608] (process_one_work+0x1b0/0x4a0) ... If it's the gpio-omap, there's probably some confusion still in the driver regarding the GPIO bank idle status. Anyways, will look more into it tomorrow. Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 0/7] irqchip: Move OMAP{4,5}/DRA7 to use stacked domains
* Tony Lindgren t...@atomide.com [150223 15:10]: * Marc Zyngier marc.zyng...@arm.com [150223 09:48]: This series is extracted from [4], which is trying to remove all traces of gic_arch_extn from the tree. As some maintainers are more responsive than others (understatement of the year...), I've decided to split it per sub-arch, and get it moving, at least partially. This series addresses OMAP{4,5} by converting the WUGEN to stacked domains. The DRA7 crossbar gets the same treatment. It is worth realizing that: - I haven't been able to test this as much as I would have wanted to (it's only been tested on omap4 and omap5). - This actively *breaks* existing setups. Once you boot a new kernel with an old DT, suspend/resume *will* be broken. Old kernels on a new DT won't even boot! You've been warned. This really outline the necessity of actually describing the HW in device trees... Could we parse still the old binding and produce warning for the case when a new kernel is booted with the old DT? That would make it easier for people to debug what's going on. Other than that, this series seems to behave for me. Please feel free to add Acked-by: Tony Lindgren t...@atomide.com. It Looks like this series should be applied into an immutable branch against v4.0-rc1 that I can pull in as needed to avoid merge conflicts with the dts files. Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/4] mmc: core: fold mmc_set_bus_width calls into sdio_enable_4bit_bus.
Every call to sdio_enable_4bit_bus is followed (on success) but a call to mmc_set_bus_width(). To simplify the code, include those calls directly in sdio_enable_4bit_bus(). Signed-off-by: NeilBrown n...@brown.name --- drivers/mmc/core/sdio.c | 32 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index ce6cc47206b0..5bc6c7dbbd60 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -293,19 +293,22 @@ static int sdio_enable_4bit_bus(struct mmc_card *card) int err; if (card-type == MMC_TYPE_SDIO) - return sdio_enable_wide(card); - - if ((card-host-caps MMC_CAP_4_BIT_DATA) - (card-scr.bus_widths SD_SCR_BUS_WIDTH_4)) { + err = sdio_enable_wide(card); + else if ((card-host-caps MMC_CAP_4_BIT_DATA) +(card-scr.bus_widths SD_SCR_BUS_WIDTH_4)) { err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); if (err) return err; + err = sdio_enable_wide(card); + if (err = 0) + mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); } else return 0; - err = sdio_enable_wide(card); - if (err = 0) - mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); + if (err 0) { + mmc_set_bus_width(card-host, MMC_BUS_WIDTH_4); + err = 0; + } return err; } @@ -547,13 +550,8 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) /* * Switch to wider bus (if supported). */ - if (card-host-caps MMC_CAP_4_BIT_DATA) { + if (card-host-caps MMC_CAP_4_BIT_DATA) err = sdio_enable_4bit_bus(card); - if (err 0) { - mmc_set_bus_width(card-host, MMC_BUS_WIDTH_4); - err = 0; - } - } /* Set the driver strength for the card */ sdio_select_driver_type(card); @@ -803,9 +801,7 @@ try_again: * Switch to wider bus (if supported). */ err = sdio_enable_4bit_bus(card); - if (err 0) - mmc_set_bus_width(card-host, MMC_BUS_WIDTH_4); - else if (err) + if (err) goto remove; } finish: @@ -983,10 +979,6 @@ static int mmc_sdio_resume(struct mmc_host *host) } else if (mmc_card_keep_power(host) mmc_card_wake_sdio_irq(host)) { /* We may have switched to 1-bit mode during suspend */ err = sdio_enable_4bit_bus(host-card); - if (err 0) { - mmc_set_bus_width(host, MMC_BUS_WIDTH_4); - err = 0; - } } if (!err host-sdio_irqs) { -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/4] mmc: omap_hsmmc: switch to 1-bit before stopping clocks.
Make use of the new mmc_sdio_want_no_clocks() call to avoid stopping clocks while SD Card interrupts are enabled and we aren't in 1-bit mode. Also stop clocks immediately in omap_hsmmc_disable_fclk() if 1-bit mode has been entered for this purpose. With this, I can use my libertas wifi with a 4-bit bus, with interrupts and runtime power-management enabled, and get around 14Mb/sec throughput (which is the best I've seen). Signed-off-by: NeilBrown n...@brown.name --- drivers/mmc/host/omap_hsmmc.c | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f84cfb01716d..14fce3b92633 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1791,9 +1791,12 @@ static int omap_hsmmc_disable_fclk(struct mmc_host *mmc) { struct omap_hsmmc_host *host = mmc_priv(mmc); - pm_runtime_mark_last_busy(host-dev); - pm_runtime_put_autosuspend(host-dev); - + if (atomic_read(mmc-sdio_narrowed) == 2) + pm_runtime_put_sync(host-dev); + else { + pm_runtime_mark_last_busy(host-dev); + pm_runtime_put_autosuspend(host-dev); + } return 0; } @@ -2311,6 +2314,10 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) spin_lock_irqsave(host-irq_lock, flags); if ((host-mmc-caps MMC_CAP_SDIO_IRQ) (host-flags HSMMC_SDIO_IRQ_ENABLED)) { + if (mmc_sdio_want_no_clocks(host-mmc) == 0) { + ret = -EBUSY; + goto abort; + } /* disable sdio irq handling to prevent race */ OMAP_HSMMC_WRITE(host-base, ISE, 0); OMAP_HSMMC_WRITE(host-base, IE, 0); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] mmc: core: allow non-blocking form of mmc_claim_host
Change the handling for the 'abort' flag so that if it is set, but we can claim the host, then do the claim, rather than aborting. When the abort is async this just means that a race between aborting an allowing a claim is resolved slightly differently. Any code must already be able to handle 'abort' being set just as the host is claimed. This allows extra functionality. If __mmc_claim_host() is called with an 'abort' pointer which is initialized to '1', it will effect a non-blocking 'claim'. Signed-off-by: NeilBrown n...@brown.name --- drivers/mmc/core/core.c |3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 23f10f72e5f3..541c8903dc6b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -912,10 +912,11 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) spin_lock_irqsave(host-lock, flags); } set_current_state(TASK_RUNNING); - if (!stop) { + if (!host-claimed || host-claimer == current) { host-claimed = 1; host-claimer = current; host-claim_cnt += 1; + stop = 0; } else wake_up(host-wq); spin_unlock_irqrestore(host-lock, flags); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] Switch to 1-bit mode SDIO before disabling clocks.
This is a reworking of this code that I promised at the end of January. SDIO interrupt in 4-bit mode require the clock to be running. So we need to switch to 1-bit mode before turning off the clock. This series provides infrastructure in mmc-core, and adds the functionality to omap_hsmmc. Thanks, NeilBrown --- NeilBrown (4): mmc: core: fold mmc_set_bus_width calls into sdio_enable_4bit_bus. mmc: core: allow non-blocking form of mmc_claim_host mmc: sdio: support switching to 1-bit before turning off clocks mmc: omap_hsmmc: switch to 1-bit before stopping clocks. drivers/mmc/core/core.c | 21 +--- drivers/mmc/core/sdio.c | 74 + drivers/mmc/host/omap_hsmmc.c | 13 ++- include/linux/mmc/core.h |2 + include/linux/mmc/host.h |2 + 5 files changed, 83 insertions(+), 29 deletions(-) -- Signature -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] mmc: sdio: support switching to 1-bit before turning off clocks
According to section 7.1.2 of http://www.sandisk.com/media/File/OEM/Manuals/SD_SDIO_specsv1.pdf In the case where the interrupt mechanism is used to wake the host while the card is in a low power state (i.e. no clocks), Both the card and the host shall be placed into the 1-bit SD mode prior to stopping the clock. This is particularly important for the Marvell libertas wifi chip in the GTA04. While in 4-bit mode it will only signal an interrupt when the clock is running (which is why setting CLKEXTFREE is important). In 1-bit mode, the interrupt is asynchronous (explained in OMAP3 TRM description of the CIRQ flag to MMCHS_STAT: In 1-bit mode, interrupt source is asynchronous (can be a source of asynchronous wakeup). In 4-bit mode, interrupt source is sampled during the interrupt cycle. ) It is awkward to simply set 1-bit mode in -runtime_suspend as that will call mmc_set_ios which calls ops-set_ios(), which will likely call pm_runtime_get_sync(), on the device that is currently suspending. This deadlocks. So: - create a work_struct to schedule setting of 1-bit mode - introduce an 'sdio_narrowed' state flag which transitions: 0 (normal) - 1 (convert to 1-bit pending) - 2 (have switch to 1-bit mode) - 0 (normal) - create a function mmc_sdio_want_no_clocks() which can be called when the driver wants to turn off clocks (presumably after an idle timeout). This either succeeds (in 1-bit mode) or fails and schedules the work to switch to 1-bit mode. - when the host is claimed, if sdio_narrowed is 2, restore the 4-bit bus - When the host is released, if sdio_narrowed is 1, then some caller other than our worker claimed the host first, so clear sdio_narrowed. This all allows a graceful and race-free switch to 1-bit mode before switching off the clocks, if SDIO interrupts are enabled. A host should call mmc_sdio_want_no_clocks() when about to turn off clocks if sdio interrupts are enabled, and the -disable() function should not use a timeout (pm_runtime_put_autosuspend) if -sdio_narrowed is 2. Signed-off-by: NeilBrown n...@brown.name --- drivers/mmc/core/core.c | 18 ++ drivers/mmc/core/sdio.c | 42 +- include/linux/mmc/core.h |2 ++ include/linux/mmc/host.h |2 ++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 541c8903dc6b..0258fdf1a03d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -921,8 +921,14 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) wake_up(host-wq); spin_unlock_irqrestore(host-lock, flags); remove_wait_queue(host-wq, wait); - if (host-ops-enable !stop host-claim_cnt == 1) - host-ops-enable(host); + if (!stop host-claim_cnt == 1) { + if (host-ops-enable) + host-ops-enable(host); + if (atomic_read(host-sdio_narrowed) == 2) { + sdio_enable_4bit_bus(host-card); + atomic_set(host-sdio_narrowed, 0); + } + } return stop; } @@ -941,8 +947,12 @@ void mmc_release_host(struct mmc_host *host) WARN_ON(!host-claimed); - if (host-ops-disable host-claim_cnt == 1) - host-ops-disable(host); + if (host-claim_cnt == 1) { + if (atomic_read(host-sdio_narrowed) == 1) + atomic_set(host-sdio_narrowed, 0); + if (host-ops-disable) + host-ops-disable(host); + } spin_lock_irqsave(host-lock, flags); if (--host-claim_cnt) { diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 5bc6c7dbbd60..9761e4d5f49b 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -288,7 +288,7 @@ static int sdio_disable_wide(struct mmc_card *card) } -static int sdio_enable_4bit_bus(struct mmc_card *card) +int sdio_enable_4bit_bus(struct mmc_card *card) { int err; @@ -313,6 +313,45 @@ static int sdio_enable_4bit_bus(struct mmc_card *card) return err; } +static void mmc_sdio_width_work(struct work_struct *work) +{ + struct mmc_host *host = container_of(work, struct mmc_host, +sdio_width_work); + atomic_t noblock; + + atomic_set(noblock, 1); + if (__mmc_claim_host(host, noblock)) + return; + if (atomic_read(host-sdio_narrowed) != 1) { + /* Nothing to do */ + mmc_release_host(host); + return; + } + if (sdio_disable_wide(host-card) == 0) + atomic_set(host-sdio_narrowed, 2); + else + atomic_set(host-sdio_narrowed, 0); + mmc_release_host(host); +} + +int mmc_sdio_want_no_clocks(struct mmc_host *host) +{ + if (!(host-caps MMC_CAP_SDIO_IRQ) || +
New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
Hi Nishanth, Olof told me about a new L3 error happening on omap5-uevm with v4.0-rc1: WARNING: CPU: 0 PID: 0 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x214/0x340() 400.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access ... I tried bisecting this with no luck, but narrowed it down to having CONFIG_CPUFREQ_DT=y causing it, while =m wont' trigger it. This got changed by commit 40d1746d2eee (ARM: omap2plus_defconfig: use CONFIG_CPUFREQ_DT). Any ideas? Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
* Tony Lindgren t...@atomide.com [150223 16:09]: Hi Nishanth, Olof told me about a new L3 error happening on omap5-uevm with v4.0-rc1: WARNING: CPU: 0 PID: 0 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x214/0x340() 400.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access ... I tried bisecting this with no luck, but narrowed it down to having CONFIG_CPUFREQ_DT=y causing it, while =m wont' trigger it. This got changed by commit 40d1746d2eee (ARM: omap2plus_defconfig: use CONFIG_CPUFREQ_DT). Any ideas? Hmm so setting CONFIG_CPUFREQ_DT=m in arch/arm/configs/omap2plus_defconfig produces the same output with make omap2plus_defconfig as with =y.. So CPUFREQ_DT can't be the real cause of the problem. It's now looking like the l3-noc warning does not get triggered on every boot. It also seems the zImage triggering the error does not trigger the error on every boot. To trigger the error, it seems the device needs to be powered down for at least 10 or so seconds between the boots. So far no luck reproducing the error on v3.19. The easy way to reproduce is to power down omap5 for at least 10 seconds, make omap2lus_defconfig on v4.0-rc1 and boot it. And so far it looks like next-20150204 works and next-20150209 failed at once so far. But of course I would not trust anything at this point :) Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
Hi, On Mon, Feb 23, 2015 at 07:01:42PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 18:43]: * Felipe Balbi ba...@ti.com [150223 18:28]: Hi, On Mon, Feb 23, 2015 at 05:59:04PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 16:09]: Hi Nishanth, Olof told me about a new L3 error happening on omap5-uevm with v4.0-rc1: WARNING: CPU: 0 PID: 0 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x214/0x340() 400.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access ... I tried bisecting this with no luck, but narrowed it down to having CONFIG_CPUFREQ_DT=y causing it, while =m wont' trigger it. This got changed by commit 40d1746d2eee (ARM: omap2plus_defconfig: use CONFIG_CPUFREQ_DT). Any ideas? Hmm so setting CONFIG_CPUFREQ_DT=m in arch/arm/configs/omap2plus_defconfig produces the same output with make omap2plus_defconfig as with =y.. So CPUFREQ_DT can't be the real cause of the problem. It's now looking like the l3-noc warning does not get triggered on every boot. It also seems the zImage triggering the error does not trigger the error on every boot. To trigger the error, it seems the device needs to be powered down for at least 10 or so seconds between the boots. So far no luck reproducing the error on v3.19. The easy way to reproduce is to power down omap5 for at least 10 seconds, make omap2lus_defconfig on v4.0-rc1 and boot it. And so far it looks like next-20150204 works and next-20150209 failed at once so far. But of course I would not trust anything at this point :) got a log of the failure ? Is it pointing to a device or one of the L4s? Well mostly the MASTER MPU TARGET L4PER2, the following stack dump is really the stack dump of the l3_interrupt_handler. Might be worth to boot with just the bare minimum (UART timers) and disable everything else. You might need to build busybox and append that to the kernel so you don't need to rely on MMC/USB/etc for rootfs. After that, you could start enabling modules one by one (as modules, not built-in) and loading them one by one to see which one causes the failure. Big PITA, I know, but I can't think of any other way to go about this. It seems the best way to deal with this is to make the l3_handle_target actually show the address where the error happened to limit it down to a single device.. Looks like the address is 0 for Custom Error. Anyways, reverting yeah, that's because the error comes from l4per2, not l3 :-) a fix for similar issue found on omap3 so far seems to help, that's 3d009c8c61f9 (gpio: omap: Fix bad device access with setup_irq()). if we revert that, we regress omap3, right ? -- balbi signature.asc Description: Digital signature
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
On Mon, Feb 23, 2015 at 06:35:06PM -0800, Tony Lindgren wrote: * Felipe Balbi ba...@ti.com [150223 18:28]: Hi, On Mon, Feb 23, 2015 at 05:59:04PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 16:09]: Hi Nishanth, Olof told me about a new L3 error happening on omap5-uevm with v4.0-rc1: WARNING: CPU: 0 PID: 0 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x214/0x340() 400.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access ... I tried bisecting this with no luck, but narrowed it down to having CONFIG_CPUFREQ_DT=y causing it, while =m wont' trigger it. This got changed by commit 40d1746d2eee (ARM: omap2plus_defconfig: use CONFIG_CPUFREQ_DT). Any ideas? Hmm so setting CONFIG_CPUFREQ_DT=m in arch/arm/configs/omap2plus_defconfig produces the same output with make omap2plus_defconfig as with =y.. So CPUFREQ_DT can't be the real cause of the problem. It's now looking like the l3-noc warning does not get triggered on every boot. It also seems the zImage triggering the error does not trigger the error on every boot. To trigger the error, it seems the device needs to be powered down for at least 10 or so seconds between the boots. So far no luck reproducing the error on v3.19. The easy way to reproduce is to power down omap5 for at least 10 seconds, make omap2lus_defconfig on v4.0-rc1 and boot it. And so far it looks like next-20150204 works and next-20150209 failed at once so far. But of course I would not trust anything at this point :) got a log of the failure ? Is it pointing to a device or one of the L4s? Well mostly the MASTER MPU TARGET L4PER2, the following stack dump is really the stack dump of the l3_interrupt_handler. Might be worth to boot with just the bare minimum (UART timers) and disable everything else. You might need to build busybox and append that to the kernel so you don't need to rely on MMC/USB/etc for rootfs. After that, you could start enabling modules one by one (as modules, not built-in) and loading them one by one to see which one causes the failure. Big PITA, I know, but I can't think of any other way to go about this. It seems the best way to deal with this is to make the l3_handle_target actually show the address where the error happened to limit it down to a single device.. you can't really do that from within l3. It doesn't have enough information to figure that out. Since it pointed you to l4per2, then you need to decode l4per2's debug registers. That has never been implemented, though. What happened here is that l4per2 detected the bogus access from one of the devices attached to it and passed the error up to l3. Since we only have l3 decoding, that's what you see and it ends up being really cryptic. If you decode l4per2's registers, I'm sure it'll point you to a real device. I guess just to prove the concept, you just hack it inside l3 irq handler, though ideally we would have a real drivers/bus/omap-l4.c, or something like that. -- balbi signature.asc Description: Digital signature
[PATCH 2/4] usb: phy: twl4030: allow charger to see usb current draw limits.
The charger needs to know when a USB gadget has been enumerated and what the agreed maximum current was so that it can adjust charging accordingly. So define a set_power() function to record the permitted draw, and pass a pointer to that when sending USB_EVENT_ENUMERATED notification. Signed-off-by: NeilBrown ne...@suse.de --- drivers/phy/phy-twl4030-usb.c | 27 +-- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 97c59074233f..023fe150c7a1 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -163,6 +163,11 @@ struct twl4030_usb { enum omap_musb_vbus_id_status linkstat; boolvbus_supplied; + /* Permitted vbus draw - only meaningful after +* USB_EVENT_ENUMERATED +*/ + unsignedvbus_draw; + struct delayed_work id_workaround_work; }; @@ -547,12 +552,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) mutex_unlock(twl-lock); if (status_changed) { - /* FIXME add a set_power() method so that B-devices can -* configure the charger appropriately. It's not always -* correct to consume VBUS power, and how much current to -* consume is a function of the USB configuration chosen -* by the host. -* + /* * REVISIT usb_gadget_vbus_connect(...) as needed, ditto * its disconnect() sibling, when changing to/from the * USB_LINK_VBUS state. musb_hdrc won't care until it @@ -625,6 +625,20 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host) return 0; } +static int twl4030_set_power(struct usb_phy *phy, unsigned mA) +{ + struct twl4030_usb *twl = phy_to_twl(phy); + + if (twl-vbus_draw != mA) { + phy-last_event = USB_EVENT_ENUMERATED; + twl-vbus_draw = mA; + atomic_notifier_call_chain(phy-notifier, + USB_EVENT_ENUMERATED, + twl-vbus_draw); + } + return 0; +} + static const struct phy_ops ops = { .init = twl4030_phy_init, .power_on = twl4030_phy_power_on, @@ -675,6 +689,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) twl-phy.label = twl4030; twl-phy.otg= otg; twl-phy.type = USB_PHY_TYPE_USB2; + twl-phy.set_power = twl4030_set_power; otg-usb_phy= twl-phy; otg-set_host = twl4030_set_host; -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/4] usb: phy: twl4030: make runtime pm more reliable.
A construct like: if (pm_runtime_suspended(twl-dev)) pm_runtime_get_sync(twl-dev); is against the spirit of the runtime_pm interface as it makes the internal refcounting useless. In this case it is also racy, particularly as 'put_autosuspend' is use to drop a reference. When that happens a timer is started and the device is runtime-suspended after the timeout. If the above code runs in this window, the device will not be found to be suspended so no pm_runtime reference is taken. When the timer expires the device will be suspended, which is against the intention of the code. So be more direct is taking and dropping references. If twl-linkstat is VBUS_VALID or ID_GROUND, then hold a pm_runtime reference, otherwise don't. Signed-off-by: NeilBrown ne...@suse.de --- drivers/phy/phy-twl4030-usb.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 8e87f54671f3..97c59074233f 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -536,8 +536,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) mutex_lock(twl-lock); if (status = 0 status != twl-linkstat) { + status_changed = + (twl-linkstat == OMAP_MUSB_VBUS_VALID || +twl-linkstat == OMAP_MUSB_ID_GROUND) + != + (status == OMAP_MUSB_VBUS_VALID || +status == OMAP_MUSB_ID_GROUND); twl-linkstat = status; - status_changed = true; } mutex_unlock(twl-lock); @@ -555,13 +560,10 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) */ if ((status == OMAP_MUSB_VBUS_VALID) || (status == OMAP_MUSB_ID_GROUND)) { - if (pm_runtime_suspended(twl-dev)) - pm_runtime_get_sync(twl-dev); + pm_runtime_get_sync(twl-dev); } else { - if (pm_runtime_active(twl-dev)) { - pm_runtime_mark_last_busy(twl-dev); - pm_runtime_put_autosuspend(twl-dev); - } + pm_runtime_mark_last_busy(twl-dev); + pm_runtime_put_autosuspend(twl-dev); } omap_musb_mailbox(status); } @@ -768,6 +770,10 @@ static int twl4030_usb_remove(struct platform_device *pdev) /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); + + if (twl-linkstat == OMAP_MUSB_VBUS_VALID || + twl-linkstat == OMAP_MUSB_ID_GROUND) + pm_runtime_put_noidle(twl-dev); pm_runtime_mark_last_busy(twl-dev); pm_runtime_put(twl-dev); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] usb: phy: twl4030: add support for reading restore on ID pin.
The twl4030 phy can measure, with low precision, the resistance-to-ground of the ID pin. Add a function to read the value, and export the result via sysfs. If the read fails, which it does sometimes, try again in 50msec. Signed-off-by: NeilBrown ne...@suse.de --- drivers/phy/phy-twl4030-usb.c | 63 + 1 file changed, 63 insertions(+) diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 023fe150c7a1..759950898df9 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -374,6 +374,56 @@ static void twl4030_i2c_access(struct twl4030_usb *twl, int on) } } +enum twl4030_id_status { + TWL4030_GROUND, + TWL4030_102K, + TWL4030_200K, + TWL4030_440K, + TWL4030_FLOATING, + TWL4030_ID_UNKNOWN, +}; +static char *twl4030_id_names[] = { + ground, + 102k, + 200k, + 440k, + floating, + unknown +}; + +enum twl4030_id_status twl4030_get_id(struct twl4030_usb *twl) +{ + int ret; + + pm_runtime_get_sync(twl-dev); + if (twl-usb_mode == T2_USB_MODE_ULPI) + twl4030_i2c_access(twl, 1); + ret = twl4030_usb_read(twl, ULPI_OTG_CTRL); + if (ret 0 || !(ret ULPI_OTG_ID_PULLUP)) { + /* Need pull-up to read ID */ + twl4030_usb_set_bits(twl, ULPI_OTG_CTRL, +ULPI_OTG_ID_PULLUP); + mdelay(50); + } + ret = twl4030_usb_read(twl, ID_STATUS); + if (ret 0 || (ret 0x1f) == 0) { + mdelay(50); + ret = twl4030_usb_read(twl, ID_STATUS); + } + + if (twl-usb_mode == T2_USB_MODE_ULPI) + twl4030_i2c_access(twl, 0); + pm_runtime_put_autosuspend(twl-dev); + + if (ret 0) + return TWL4030_ID_UNKNOWN; + ret = ffs(ret) - 1; + if (ret TWL4030_GROUND || ret TWL4030_FLOATING) + return TWL4030_ID_UNKNOWN; + + return ret; +} + static void __twl4030_phy_power(struct twl4030_usb *twl, int on) { u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); @@ -531,6 +581,16 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev, } static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); +static ssize_t twl4030_usb_id_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct twl4030_usb *twl = dev_get_drvdata(dev); + return scnprintf(buf, PAGE_SIZE, %s\n, +twl4030_id_names[twl4030_get_id(twl)]); +} +static DEVICE_ATTR(id, 0444, twl4030_usb_id_show, NULL); + static irqreturn_t twl4030_usb_irq(int irq, void *_twl) { struct twl4030_usb *twl = _twl; @@ -723,6 +783,8 @@ static int twl4030_usb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, twl); if (device_create_file(pdev-dev, dev_attr_vbus)) dev_warn(pdev-dev, could not create sysfs file\n); + if (device_create_file(pdev-dev, dev_attr_id)) + dev_warn(pdev-dev, could not create sysfs file\n); ATOMIC_INIT_NOTIFIER_HEAD(twl-phy.notifier); @@ -768,6 +830,7 @@ static int twl4030_usb_remove(struct platform_device *pdev) pm_runtime_get_sync(twl-dev); cancel_delayed_work(twl-id_workaround_work); device_remove_file(twl-dev, dev_attr_vbus); + device_remove_file(twl-dev, dev_attr_id); /* set transceiver mode to power on defaults */ twl4030_usb_set_mode(twl, -1); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/4] usb: phy: twl4030: test ID resistance to see if charger is present.
If an 'A' plug is inserted, ID should be pulled to ground. If a 'B' plug, then ID should be floating. If an Accessory Charger Adapter is inserted, then ID will be neither grounded nor floating. In this case tell the USB subsystem that it is an A plug, and the battery charging subsystem that it is a charger. Fortunately, this will treat the Openmoko charger (and other similar chargers) as a charger. Signed-off-by: NeilBrown ne...@suse.de --- drivers/phy/phy-twl4030-usb.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 759950898df9..8a43080cdbd7 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -596,9 +596,31 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) struct twl4030_usb *twl = _twl; enum omap_musb_vbus_id_status status; bool status_changed = false; + bool found_charger = false; status = twl4030_usb_linkstat(twl); + if (status == OMAP_MUSB_ID_GROUND || + status == OMAP_MUSB_VBUS_VALID) { + /* We should check the resistance on the ID pin. +* If not a Ground or Floating, then this is +* likely a charger +*/ + enum twl4030_id_status sts = twl4030_get_id(twl); + if (sts TWL4030_GROUND + sts TWL4030_FLOATING) { + /* +* This might be a charger, or an +* Accessory Charger Adapter. +* In either case we can charge, and it +* makes sense to tell the USB system +* that we might be acting as a HOST. +*/ + status = OMAP_MUSB_ID_GROUND; + found_charger = true; + } + } + mutex_lock(twl-lock); if (status = 0 status != twl-linkstat) { status_changed = @@ -627,6 +649,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) } omap_musb_mailbox(status); } + if (found_charger twl-phy.last_event != USB_EVENT_CHARGER) { + twl-phy.last_event = USB_EVENT_CHARGER; + atomic_notifier_call_chain(twl-phy.notifier, + USB_EVENT_CHARGER, + NULL); + } /* don't schedule during sleep - irq works right then */ if (status == OMAP_MUSB_ID_GROUND pm_runtime_active(twl-dev)) { -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] Enhancements to twl4030 phy to support better charging.
Hi, the following 4 patches make some improvements to the twl4030 phy. Together with some other patches I have for twl4030_charger, they allow for better automatic control of charging. In particular, the status of the ID pin is assessed and the result in communicated to the charger drivers. There is also support for conveying the max current negotiated by a host to the charger. Comments most welcome. thanks, NeilBrown --- NeilBrown (4): usb: phy: twl4030: make runtime pm more reliable. usb: phy: twl4030: allow charger to see usb current draw limits. usb: phy: twl4030: add support for reading restore on ID pin. usb: phy: twl4030: test ID resistance to see if charger is present. drivers/phy/phy-twl4030-usb.c | 138 + 1 file changed, 125 insertions(+), 13 deletions(-) -- Signature -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/15] twl4030_charger: distinguish between USB current and 'AC' current
The twl4030 charger has two current sources, 'USB' and 'AC' (which is really DC of course...). If 'AC' is providing current, we should set the current limit differently to when it isn't (and so USB is used). So split 'cur' into 'usb_cur' and 'ac_cur' and use accordingly. Now we must review the current setting on any interrupt or USB event which might indicate that the charger-source has changed. Signed-off-by: NeilBrown ne...@suse.de --- drivers/power/twl4030_charger.c | 30 +- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 7c35cd9ba171..bfc9b808301e 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -22,6 +22,7 @@ #include linux/power_supply.h #include linux/notifier.h #include linux/usb/otg.h +#include linux/i2c/twl4030-madc.h #define TWL4030_BCIMSTATEC 0x02 #define TWL4030_BCIICHG0x08 @@ -103,7 +104,9 @@ struct twl4030_bci { /* ichg values in uA. If any are 'large', we set CGAIN to * '1' which doubles the range for half the precision. */ - int ichg_eoc, ichg_lo, ichg_hi, cur; + int ichg_eoc, ichg_lo, ichg_hi; + int usb_cur, ac_cur; + boolac_is_active; unsigned long event; }; @@ -224,11 +227,23 @@ static int ua2regval(int ua, bool cgain) static int twl4030_charger_update_current(struct twl4030_bci *bci) { int status; + int cur; unsigned reg, cur_reg; u8 bcictl1, oldreg, fullreg; int cgain = 0; u8 boot_bci; + /* If VAC exceeds 4.5V (MADC 11) and ac is enabled, set current +* for 'ac' +*/ + if (twl4030_get_madc_conversion(11) 4500) { + cur = bci-ac_cur; + bci-ac_is_active = 1; + } else { + cur = bci-usb_cur; + bci-ac_is_active = 0; + } + /* First, check thresholds and see if cgain is needed */ if (bci-ichg_eoc = 20) cgain = 1; @@ -236,7 +251,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci) cgain = 1; if (bci-ichg_hi = 82) cgain = 1; - if (bci-cur 852000) + if (cur 852000) cgain = 1; status = twl4030_bci_read(TWL4030_BCICTL1, bcictl1); @@ -311,7 +326,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci) /* And finally, set the current. This is stored in * two registers. */ - reg = ua2regval(bci-cur, cgain); + reg = ua2regval(cur, cgain); /* we have only 10 bit */ if (reg 0x3ff) reg = 0x3ff; @@ -364,6 +379,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) if (enable !IS_ERR_OR_NULL(bci-transceiver)) { + twl4030_charger_update_current(bci); + /* Need to keep phy powered */ if (!bci-usb_enabled) { pm_runtime_get_sync(bci-transceiver-dev); @@ -456,6 +473,7 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void *arg) struct twl4030_bci *bci = arg; dev_dbg(bci-dev, CHG_PRES irq\n); + twl4030_charger_update_current(bci); power_supply_changed(bci-ac); power_supply_changed(bci-usb); @@ -488,6 +506,7 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg) power_supply_changed(bci-ac); power_supply_changed(bci-usb); } + twl4030_charger_update_current(bci); /* various monitoring events, for now we just log them here */ if (irqs1 (TWL4030_TBATOR2 | TWL4030_TBATOR1)) @@ -701,10 +720,11 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) bci-ichg_eoc = 80100; /* Stop charging when current drops to here */ bci-ichg_lo = 241000; /* low threshold */ bci-ichg_hi = 50; /* High threshold */ + bci-ac_cur = 50; /* 500mA */ if (allow_usb) - bci-cur = 50; /* 500mA */ + bci-usb_cur = 50; /* 500mA */ else - bci-cur = 10; /* 100mA */ + bci-usb_cur = 10; /* 100mA */ bci-dev = pdev-dev; bci-irq_chg = platform_get_irq(pdev, 0); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/15] twl4030_charger: allow fine control of charger current.
The twl4030 allows control of the incoming current. Part of this control is a 'CGAIN' setting which doubles the range for half the precision. This control affects several different current setting, so all need to be updated at once when CGAIN is changed. With this patch, all of these current setting are managed by the driver, but most are left at their default settings. The current drawn is set to 500mA if the allow_usb module parameter is set, and to 100mA otherwise. More fine control will appear in later patches. Signed-off-by: NeilBrown ne...@suse.de --- drivers/power/twl4030_charger.c | 161 +-- 1 file changed, 153 insertions(+), 8 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 0b6fb06a0c01..7c35cd9ba171 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -31,6 +31,11 @@ #define TWL4030_BCIMFSTS4 0x10 #define TWL4030_BCICTL10x23 #define TWL4030_BB_CFG 0x12 +#define TWL4030_BCIIREF1 0x27 +#define TWL4030_BCIIREF2 0x28 +#define TWL4030_BCIMFKEY 0x11 +#define TWL4030_BCIMFTH8 0x1d +#define TWL4030_BCIMFTH9 0x1e #define TWL4030_BCIMFSTS1 0x01 @@ -95,6 +100,11 @@ struct twl4030_bci { int irq_bci; int usb_enabled; + /* ichg values in uA. If any are 'large', we set CGAIN to +* '1' which doubles the range for half the precision. +*/ + int ichg_eoc, ichg_lo, ichg_hi, cur; + unsigned long event; }; @@ -211,6 +221,140 @@ static int ua2regval(int ua, bool cgain) return ret; } +static int twl4030_charger_update_current(struct twl4030_bci *bci) +{ + int status; + unsigned reg, cur_reg; + u8 bcictl1, oldreg, fullreg; + int cgain = 0; + u8 boot_bci; + + /* First, check thresholds and see if cgain is needed */ + if (bci-ichg_eoc = 20) + cgain = 1; + if (bci-ichg_lo = 40) + cgain = 1; + if (bci-ichg_hi = 82) + cgain = 1; + if (bci-cur 852000) + cgain = 1; + + status = twl4030_bci_read(TWL4030_BCICTL1, bcictl1); + if (status 0) + return status; + if (twl_i2c_read_u8(TWL_MODULE_PM_MASTER, boot_bci, + TWL4030_PM_MASTER_BOOT_BCI) 0) + boot_bci = 0; + boot_bci = 7; + + if ((!!cgain) != !!(bcictl1 TWL4030_CGAIN)) + /* Need to turn for charging while we change the +* CGAIN bit. Leave it off while everything is +* updated. +*/ + twl4030_clear_set_boot_bci(boot_bci, 0); + + /* For ichg_eoc, reg value must be 100000, we only +* set the in high nibble. +*/ + reg = ua2regval(bci-ichg_eoc, cgain); + if (reg 0x278) + reg = 0x278; + if (reg 0x200) + reg = 0x200; + reg = (reg 3) 0xf; + fullreg = reg 4; + + /* For ichg_lo, reg value must be 10. +* is stored in low nibble */ + reg = ua2regval(bci-ichg_lo, cgain); + if (reg 0x2F0) + reg = 0x2F0; + if (reg 0x200) + reg = 0x200; + reg = (reg 4) 0xf; + fullreg |= reg; + + /* ichg_eoc and ichg_lo live in same register */ + status = twl4030_bci_read(TWL4030_BCIMFTH8, oldreg); + if (status 0) + return status; + if (oldreg != fullreg) { + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xF4, + TWL4030_BCIMFKEY); + if (status 0) + return status; + twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, +fullreg, TWL4030_BCIMFTH8); + } + + /* ichg_hi threshold must be 101100 (I think) */ + reg = ua2regval(bci-ichg_hi, cgain); + if (reg 0x3E0) + reg = 0x3E0; + if (reg 0x200) + reg = 0x200; + fullreg = (reg 5) 0xF; + fullreg = 4; + status = twl4030_bci_read(TWL4030_BCIMFTH9, oldreg); + if (status 0) + return status; + if ((oldreg 0xF0) != fullreg) { + fullreg |= (oldreg 0x0F); + status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7, + TWL4030_BCIMFKEY); + if (status 0) + return status; + twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, +fullreg, TWL4030_BCIMFTH9); + } + + /* And finally, set the current. This is stored in +* two registers. */ + reg = ua2regval(bci-cur, cgain); + /* we have only 10 bit */ + if (reg 0x3ff) + reg = 0x3ff;
[PATCH 04/15] twl4030_charger: use runtime_pm to keep usb phy active while charging.
The twl4030 usb phy needs to be active while we are using the USB VBUS as a current source for charging. In particular, the usb3v1 regulator must be enabled and the PHY_PWR_PHYPWD bit must be set to keep the phy powered. commit ab37813f4093a5f59cb8e083cde277289dc72ed3 twl4030_charger: Allow charger to control the regulator that feeds it Gave the charger control over the regulator, but didn't resolve the PHY_PWR_PHYPWD issue. Now that both of these are controlled by runtime_pm in phy-twl4030-usb, we can simply take a runtime_pm reference to the USB phy whenever the charger wants to use it as a current source. So this patch reverts the above commit, and adds the necessary runtime_pm calls. Signed-off-by: NeilBrown ne...@suse.de --- drivers/mfd/twl-core.c |9 - drivers/power/twl4030_charger.c | 18 +- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 489674a2497e..831696ee2472 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -788,9 +788,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, static struct regulator_consumer_supply usb1v8 = { .supply = usb1v8, }; - static struct regulator_consumer_supply usb3v1[] = { - { .supply = usb3v1 }, - { .supply = bci3v1 }, + static struct regulator_consumer_supply usb3v1 = { + .supply = usb3v1, }; /* First add the regulators so that they can be used by transceiver */ @@ -818,7 +817,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, return PTR_ERR(child); child = add_regulator_linked(TWL4030_REG_VUSB3V1, - usb_fixed, usb3v1, 2, + usb_fixed, usb3v1, 1, features); if (IS_ERR(child)) return PTR_ERR(child); @@ -838,7 +837,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) child) { usb1v5.dev_name = dev_name(child); usb1v8.dev_name = dev_name(child); - usb3v1[0].dev_name = dev_name(child); + usb3v1.dev_name = dev_name(child); } } diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 51321f0c5548..11f352a5ef55 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -22,7 +22,6 @@ #include linux/power_supply.h #include linux/notifier.h #include linux/usb/otg.h -#include linux/regulator/machine.h #define TWL4030_BCIMSTATEC 0x02 #define TWL4030_BCIICHG0x08 @@ -94,7 +93,6 @@ struct twl4030_bci { struct work_struct work; int irq_chg; int irq_bci; - struct regulator*usb_reg; int usb_enabled; unsigned long event; @@ -208,7 +206,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) { int ret; - if (enable) { + if (enable !IS_ERR_OR_NULL(bci-transceiver)) { /* Check for USB charger connected */ if (!twl4030_bci_have_vbus(bci)) return -ENODEV; @@ -222,14 +220,9 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) return -EACCES; } - /* Need to keep regulator on */ + /* Need to keep phy powered */ if (!bci-usb_enabled) { - ret = regulator_enable(bci-usb_reg); - if (ret) { - dev_err(bci-dev, - Failed to enable regulator\n); - return ret; - } + pm_runtime_get_sync(bci-transceiver-dev); bci-usb_enabled = 1; } @@ -244,7 +237,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) } else { ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); if (bci-usb_enabled) { - regulator_disable(bci-usb_reg); + pm_runtime_mark_last_busy(bci-transceiver-dev); + pm_runtime_put_autosuspend(bci-transceiver-dev); bci-usb_enabled = 0; } } @@ -602,8 +596,6 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
[PATCH 06/15] twl4030_charger: split uA calculation into a function.
We will need this calculation in other places, so create functions to map between register value and uA value. Signed-off-by: NeilBrown ne...@suse.de --- drivers/power/twl4030_charger.c | 48 --- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index db8931a17541..0b6fb06a0c01 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -178,6 +178,40 @@ static int twl4030_is_battery_present(struct twl4030_bci *bci) } /* + * TI provided formulas: + * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85 + * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7 + * Here we use integer approximation of: + * CGAIN == 0: val * 1.6618 - 0.85 * 1000 + * CGAIN == 1: (val * 1.6618 - 0.85 * 1000) * 2 + */ +/* + * convert twl register value for currents into uA + */ +static int regval2ua(int regval, bool cgain) +{ + if (cgain) + return (regval * 16618 - 8500 * 1000) / 5; + else + return (regval * 16618 - 8500 * 1000) / 10; +} + +/* + * convert uA currents into twl register value + */ +static int ua2regval(int ua, bool cgain) +{ + int ret; + if (cgain) + ua /= 2; + ret = (ua * 10 + 8500 * 1000) / 16618; + /* rounding problems */ + if (ret 512) + ret = 512; + return ret; +} + +/* * Enable/Disable USB Charge functionality. */ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) @@ -366,14 +400,6 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, return NOTIFY_OK; } -/* - * TI provided formulas: - * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85 - * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7 - * Here we use integer approximation of: - * CGAIN == 0: val * 1.6618 - 0.85 - * CGAIN == 1: (val * 1.6618 - 0.85) * 2 - */ static int twl4030_charger_get_current(void) { int curr; @@ -388,11 +414,7 @@ static int twl4030_charger_get_current(void) if (ret) return ret; - ret = (curr * 16618 - 850 * 1) / 10; - if (bcictl1 TWL4030_CGAIN) - ret *= 2; - - return ret; + return regval2ua(curr, bcictl1 TWL4030_CGAIN); } /* -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 05/15] twl4030_charger: trust phy to determine when USB power is available.
The usb phy driver already determines when VBUS is available, so repeating the test in the charger driver is pointless duplication. On probe, process the last event from the phy, and from then on, do whatever the phy tells us without double-checking. Signed-off-by: NeilBrown ne...@suse.de --- drivers/power/twl4030_charger.c | 33 ++--- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 11f352a5ef55..db8931a17541 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -178,28 +178,6 @@ static int twl4030_is_battery_present(struct twl4030_bci *bci) } /* - * Check if VBUS power is present - */ -static int twl4030_bci_have_vbus(struct twl4030_bci *bci) -{ - int ret; - u8 hwsts; - - ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, hwsts, - TWL4030_PM_MASTER_STS_HW_CONDITIONS); - if (ret 0) - return 0; - - dev_dbg(bci-dev, check_vbus: HW_CONDITIONS %02x\n, hwsts); - - /* in case we also have STS_USB_ID, VBUS is driven by TWL itself */ - if ((hwsts TWL4030_STS_VBUS) !(hwsts TWL4030_STS_USB_ID)) - return 1; - - return 0; -} - -/* * Enable/Disable USB Charge functionality. */ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) @@ -207,10 +185,6 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) int ret; if (enable !IS_ERR_OR_NULL(bci-transceiver)) { - /* Check for USB charger connected */ - if (!twl4030_bci_have_vbus(bci)) - return -ENODEV; - /* * Until we can find out what current the device can provide, * require a module param to enable USB charging. @@ -649,7 +623,12 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) dev_warn(pdev-dev, failed to unmask interrupts: %d\n, ret); twl4030_charger_enable_ac(true); - twl4030_charger_enable_usb(bci, true); + if (!IS_ERR_OR_NULL(bci-transceiver)) + twl4030_bci_usb_ncb(bci-usb_nb, + bci-transceiver-last_event, + NULL); + else + twl4030_charger_enable_usb(bci, false); if (pdata) twl4030_charger_enable_backup(pdata-bb_uvolt, pdata-bb_uamp); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/15] Enhance twl4030_charger functionality.
These patches make a number of improvements to twl4030_charger. So are just internal cleanups (e.g. use of devres). Others allow better control of charging through both manual and automatic means. - the maximum current can be configured via sysfs. - the charger will only draw that current if it can do so without the voltage dropping too much - a 'continuous' mode is available which ignores voltage and just takes what it can (to be used with caution, but very useful in some circumstances). - 'ac' and 'usb' power sources can be configured separately. Some of this functionality requires patch to phy-twl4030-usb.c which have been sent separately. Thanks, NeilBrown --- NeilBrown (15): power_supply core: support use of devres to register/unregister a power supply. twl4030_charger: use devm_request_threaded_irq twl4030_charger: use devres for power_supply_register and kzalloc. twl4030_charger: use runtime_pm to keep usb phy active while charging. twl4030_charger: trust phy to determine when USB power is available. twl4030_charger: split uA calculation into a function. twl4030_charger: allow fine control of charger current. twl4030_charger: distinguish between USB current and 'AC' current twl4030_charger: allow max_current to be managed via sysfs. twl4030_charger: only draw USB current as negotiated with host. twl4030_charger: enable manual enable/disable of usb charging. twl4030_charger: add software controlled linear charging mode. twl4030_charger: add ac/mode to match usb/mode twl4030_charger: Increase current carefully while watching voltage. twl4030_charger: assume a 'charger' can supply maximum current. drivers/mfd/twl-core.c|9 - drivers/power/power_supply_core.c | 45 +++ drivers/power/twl4030_charger.c | 572 +++-- include/linux/power_supply.h |4 4 files changed, 539 insertions(+), 91 deletions(-) -- Signature -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
* Tony Lindgren t...@atomide.com [150223 19:29]: * Felipe Balbi ba...@ti.com [150223 19:19]: On Mon, Feb 23, 2015 at 07:01:42PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 18:43]: Looks like the address is 0 for Custom Error. Anyways, reverting yeah, that's because the error comes from l4per2, not l3 :-) Right so it seems :) a fix for similar issue found on omap3 so far seems to help, that's 3d009c8c61f9 (gpio: omap: Fix bad device access with setup_irq()). if we revert that, we regress omap3, right ? Yes we saw that getting triggered on omap3/4 before 3d009c8c61f9. Now looking at the stack trace again, it actually has something: ... [c05999a4] (__irq_svc) from [c0599164] (_raw_spin_unlock_irqrestore+0x34/0x44) [c0599164] (_raw_spin_unlock_irqrestore) from [c0027120] (omap_hwmod_idle+0x34/0x44) [c0027120] (omap_hwmod_idle) from [c00283f8] (omap_device_idle+0x38/0x78) [c00283f8] (omap_device_idle) from [c0028454] (_od_runtime_suspend+0x1c/0x24) [c0028454] (_od_runtime_suspend) from [c03b5214] (__rpm_callback+0x2c/0x60) [c03b5214] (__rpm_callback) from [c03b5268] (rpm_callback+0x20/0x80) [c03b5268] (rpm_callback) from [c03b56b8] (rpm_suspend+0xe8/0x55c) [c03b56b8] (rpm_suspend) from [c03b6bdc] (pm_runtime_work+0x74/0xa8) [c03b6bdc] (pm_runtime_work) from [c0054608] (process_one_work+0x1b0/0x4a0) ... If it's the gpio-omap, there's probably some confusion still in the driver regarding the GPIO bank idle status. Anyways, will look more into it tomorrow. And now I'm seeing the error with 3d009c8c61f9 reverted, so it does not seem to be that either.. Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: New l3-noc error with CPUFREQ_DT built-in with v4.0-rc1
Hi, On Mon, Feb 23, 2015 at 05:59:04PM -0800, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150223 16:09]: Hi Nishanth, Olof told me about a new L3 error happening on omap5-uevm with v4.0-rc1: WARNING: CPU: 0 PID: 0 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x214/0x340() 400.ocp:L3 Custom Error: MASTER MPU TARGET L4PER2 (Idle): Data Access in Supervisor mode during Functional access ... I tried bisecting this with no luck, but narrowed it down to having CONFIG_CPUFREQ_DT=y causing it, while =m wont' trigger it. This got changed by commit 40d1746d2eee (ARM: omap2plus_defconfig: use CONFIG_CPUFREQ_DT). Any ideas? Hmm so setting CONFIG_CPUFREQ_DT=m in arch/arm/configs/omap2plus_defconfig produces the same output with make omap2plus_defconfig as with =y.. So CPUFREQ_DT can't be the real cause of the problem. It's now looking like the l3-noc warning does not get triggered on every boot. It also seems the zImage triggering the error does not trigger the error on every boot. To trigger the error, it seems the device needs to be powered down for at least 10 or so seconds between the boots. So far no luck reproducing the error on v3.19. The easy way to reproduce is to power down omap5 for at least 10 seconds, make omap2lus_defconfig on v4.0-rc1 and boot it. And so far it looks like next-20150204 works and next-20150209 failed at once so far. But of course I would not trust anything at this point :) got a log of the failure ? Is it pointing to a device or one of the L4s? Might be worth to boot with just the bare minimum (UART timers) and disable everything else. You might need to build busybox and append that to the kernel so you don't need to rely on MMC/USB/etc for rootfs. After that, you could start enabling modules one by one (as modules, not built-in) and loading them one by one to see which one causes the failure. Big PITA, I know, but I can't think of any other way to go about this. -- balbi signature.asc Description: Digital signature
[PATCH 03/15] twl4030_charger: use devres for power_supply_register and kzalloc.
Final allocations/registrations are now managed by devres. Signed-off-by: NeilBrown ne...@suse.de --- drivers/power/twl4030_charger.c | 23 ++- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 300dd7a34e80..51321f0c5548 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -565,7 +565,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) int ret; u32 reg; - bci = kzalloc(sizeof(*bci), GFP_KERNEL); + bci = devm_kzalloc(pdev-dev, sizeof(*bci), GFP_KERNEL); if (bci == NULL) return -ENOMEM; @@ -580,7 +580,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) ret = twl4030_is_battery_present(bci); if (ret) { dev_crit(pdev-dev, Battery was not detected:%d\n, ret); - goto fail_no_battery; + goto fail; } platform_set_drvdata(pdev, bci); @@ -590,10 +590,10 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) bci-ac.num_properties = ARRAY_SIZE(twl4030_charger_props); bci-ac.get_property = twl4030_bci_get_property; - ret = power_supply_register(pdev-dev, bci-ac); + ret = devm_power_supply_register(pdev-dev, bci-ac); if (ret) { dev_err(pdev-dev, failed to register ac: %d\n, ret); - goto fail_register_ac; + goto fail; } bci-usb.name = twl4030_usb; @@ -604,10 +604,10 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) bci-usb_reg = regulator_get(bci-dev, bci3v1); - ret = power_supply_register(pdev-dev, bci-usb); + ret = devm_power_supply_register(pdev-dev, bci-usb); if (ret) { dev_err(pdev-dev, failed to register usb: %d\n, ret); - goto fail_register_usb; + goto fail; } ret = devm_request_threaded_irq(pdev-dev, bci-irq_chg, NULL, @@ -667,13 +667,6 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) return 0; fail: - power_supply_unregister(bci-usb); -fail_register_usb: - power_supply_unregister(bci-ac); -fail_register_ac: -fail_no_battery: - kfree(bci); - return ret; } @@ -691,10 +684,6 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, TWL4030_INTERRUPTS_BCIIMR2A); - power_supply_unregister(bci-usb); - power_supply_unregister(bci-ac); - kfree(bci); - return 0; } -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/15] twl4030_charger: use devm_request_threaded_irq
This simplifies the error paths. Signed-off-by: NeilBrown ne...@suse.de --- drivers/power/twl4030_charger.c | 18 ++ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 4cf5ffbc904a..300dd7a34e80 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -610,21 +610,21 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) goto fail_register_usb; } - ret = request_threaded_irq(bci-irq_chg, NULL, + ret = devm_request_threaded_irq(pdev-dev, bci-irq_chg, NULL, twl4030_charger_interrupt, IRQF_ONESHOT, pdev-name, bci); if (ret 0) { dev_err(pdev-dev, could not request irq %d, status %d\n, bci-irq_chg, ret); - goto fail_chg_irq; + goto fail; } - ret = request_threaded_irq(bci-irq_bci, NULL, + ret = devm_request_threaded_irq(pdev-dev, bci-irq_bci, NULL, twl4030_bci_interrupt, IRQF_ONESHOT, pdev-name, bci); if (ret 0) { dev_err(pdev-dev, could not request irq %d, status %d\n, bci-irq_bci, ret); - goto fail_bci_irq; + goto fail; } INIT_WORK(bci-work, twl4030_bci_usb_work); @@ -647,7 +647,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) TWL4030_INTERRUPTS_BCIIMR1A); if (ret 0) { dev_err(pdev-dev, failed to unmask interrupts: %d\n, ret); - goto fail_unmask_interrupts; + goto fail; } reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV); @@ -666,11 +666,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) return 0; -fail_unmask_interrupts: - free_irq(bci-irq_bci, bci); -fail_bci_irq: - free_irq(bci-irq_chg, bci); -fail_chg_irq: +fail: power_supply_unregister(bci-usb); fail_register_usb: power_supply_unregister(bci-ac); @@ -695,8 +691,6 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, TWL4030_INTERRUPTS_BCIIMR2A); - free_irq(bci-irq_bci, bci); - free_irq(bci-irq_chg, bci); power_supply_unregister(bci-usb); power_supply_unregister(bci-ac); kfree(bci); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/15] power_supply core: support use of devres to register/unregister a power supply.
Using devm_power_supply_register allows the unregister to happen automatically on error or final put. Signed-off-by: NeilBrown ne...@suse.de --- drivers/power/power_supply_core.c | 45 + include/linux/power_supply.h |4 +++ 2 files changed, 49 insertions(+) diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 694e8cddd5c1..44c810456212 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -617,6 +617,51 @@ int power_supply_register_no_ws(struct device *parent, struct power_supply *psy) } EXPORT_SYMBOL_GPL(power_supply_register_no_ws); +static void devm_power_supply_release(struct device *dev, void *res) +{ + struct power_supply **psy = res; + + power_supply_unregister(*psy); +} + +int devm_power_supply_register(struct device *parent, struct power_supply *psy) +{ + struct power_supply **ptr = devres_alloc(devm_power_supply_release, +sizeof(*ptr), GFP_KERNEL); + int ret; + + if (!ptr) + return -ENOMEM; + ret = __power_supply_register(parent, psy, true); + if (ret 0) + devres_free(ptr); + else { + *ptr = psy; + devres_add(parent, ptr); + } + return ret; +} +EXPORT_SYMBOL_GPL(devm_power_supply_register); + +int devm_power_supply_register_no_ws(struct device *parent, struct power_supply *psy) +{ + struct power_supply **ptr = devres_alloc(devm_power_supply_release, +sizeof(*ptr), GFP_KERNEL); + int ret; + + if (!ptr) + return -ENOMEM; + ret = __power_supply_register(parent, psy, false); + if (ret 0) + devres_free(ptr); + else { + *ptr = psy; + devres_add(parent, ptr); + } + return ret; +} +EXPORT_SYMBOL_GPL(devm_power_supply_register_no_ws); + void power_supply_unregister(struct power_supply *psy) { cancel_work_sync(psy-changed_work); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 096dbced02ac..f606d6b4bd56 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -278,6 +278,10 @@ extern int power_supply_register(struct device *parent, struct power_supply *psy); extern int power_supply_register_no_ws(struct device *parent, struct power_supply *psy); +extern int devm_power_supply_register(struct device *parent, +struct power_supply *psy); +extern int devm_power_supply_register_no_ws(struct device *parent, +struct power_supply *psy); extern void power_supply_unregister(struct power_supply *psy); extern int power_supply_powers(struct power_supply *psy, struct device *dev); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html