From patchwork Wed Mar 27 23:16:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067541 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="m+ry2Zzj"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3qV4sM1z9sR0 for ; Thu, 28 Mar 2019 10:19:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728859AbfC0XQy (ORCPT ); Wed, 27 Mar 2019 19:16:54 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58304 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728359AbfC0XQy (ORCPT ); Wed, 27 Mar 2019 19:16:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728610; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=xL2hJXyz4V+V30Vo8ubnzB12kI/VxzIQNxS6q084Dsk=; b=m+ry2ZzjYzdL9kQCTq2IR1UP5g65T8bjvWa5BxtvvngudcRYfz2GRbqnWG6WG0YxhR3JTM YZNcqMKSXff3bwUOL8LeyE6HQPrdY61qpQtr7C9HguEBkqdGIqpDgoahtU0b7QUjcN+pxT cAjzoNB2iaj9N5zfd9LuQbRcR7JXPKQ= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 01/27] dt-bindings: ingenic: Add DT bindings for TCU clocks Date: Thu, 28 Mar 2019 00:16:05 +0100 Message-Id: <20190327231631.15708-2-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org This header provides clock numbers for the ingenic,tcu DT binding. Signed-off-by: Paul Cercueil Reviewed-by: Rob Herring Acked-by: Stephen Boyd Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- include/dt-bindings/clock/ingenic,tcu.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 include/dt-bindings/clock/ingenic,tcu.h diff --git a/include/dt-bindings/clock/ingenic,tcu.h b/include/dt-bindings/clock/ingenic,tcu.h new file mode 100644 index 000000000000..d569650a7945 --- /dev/null +++ b/include/dt-bindings/clock/ingenic,tcu.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides clock numbers for the ingenic,tcu DT binding. + */ + +#ifndef __DT_BINDINGS_CLOCK_INGENIC_TCU_H__ +#define __DT_BINDINGS_CLOCK_INGENIC_TCU_H__ + +#define TCU_CLK_TIMER0 0 +#define TCU_CLK_TIMER1 1 +#define TCU_CLK_TIMER2 2 +#define TCU_CLK_TIMER3 3 +#define TCU_CLK_TIMER4 4 +#define TCU_CLK_TIMER5 5 +#define TCU_CLK_TIMER6 6 +#define TCU_CLK_TIMER7 7 +#define TCU_CLK_WDT 8 +#define TCU_CLK_OST 9 + +#endif /* __DT_BINDINGS_CLOCK_INGENIC_TCU_H__ */ From patchwork Wed Mar 27 23:16:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067513 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="nsn3hskc"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3mZ3Mp7z9sR3 for ; Thu, 28 Mar 2019 10:17:02 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730034AbfC0XQ5 (ORCPT ); Wed, 27 Mar 2019 19:16:57 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58334 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XQ4 (ORCPT ); Wed, 27 Mar 2019 19:16:56 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728613; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=CJm+6uSaS9KkHcCaxucqPKa1Tl1yOPtFMNkO2p4W1zI=; b=nsn3hskcwuTIc7Cyjk5XtjpYZ6Cu1VTo12n2r53fxDID+/XBq3qpPJCI+jvf78atSnNe5w GBJIGzlSjZXS4ArhvdBPqxa7DLCKyoi7eoux78oh95vKFYZmkDakoSTcwXMoUMawKukg+f s84voI2wTDlzedLjTjERwUnHGWUNcPA= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 02/27] doc: Add doc for the Ingenic TCU hardware Date: Thu, 28 Mar 2019 00:16:06 +0100 Message-Id: <20190327231631.15708-3-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add a documentation file about the Timer/Counter Unit (TCU) present in the Ingenic JZ47xx SoCs. The Timer/Counter Unit (TCU) in Ingenic JZ47xx SoCs is a multi-function hardware block. It features up to to eight channels, that can be used as counters, timers, or PWM. - JZ4725B, JZ4750, JZ4755 only have six TCU channels. The other SoCs all have eight channels. - JZ4725B introduced a separate channel, called Operating System Timer (OST). It is a 32-bit programmable timer. On JZ4770 and above, it is 64-bit. - Each one of the TCU channels has its own clock, which can be reparented to three different clocks (pclk, ext, rtc), gated, and reclocked, through their TCSR register. * The watchdog and OST hardware blocks also feature a TCSR register with the same format in their register space. * The TCU registers used to gate/ungate can also gate/ungate the watchdog and OST clocks. - Each TCU channel works in one of two modes: * mode TCU1: channels cannot work in sleep mode, but are easier to operate. * mode TCU2: channels can work in sleep mode, but the operation is a bit more complicated than with TCU1 channels. - The mode of each TCU channel depends on the SoC used: * On the oldest SoCs (up to JZ4740), all of the eight channels operate in TCU1 mode. * On JZ4725B, channel 5 operates as TCU2, the others operate as TCU1. * On newest SoCs (JZ4750 and above), channels 1-2 operate as TCU2, the others operate as TCU1. - Each channel can generate an interrupt. Some channels share an interrupt line, some don't, and this changes between SoC versions: * on older SoCs (JZ4740 and below), channel 0 and channel 1 have their own interrupt line; channels 2-7 share the last interrupt line. * On JZ4725B, channel 0 has its own interrupt; channels 1-5 share one interrupt line; the OST uses the last interrupt line. * on newer SoCs (JZ4750 and above), channel 5 has its own interrupt; channels 0-4 and (if eight channels) 6-7 all share one interrupt line; the OST uses the last interrupt line. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- Documentation/mips/ingenic-tcu.txt | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Documentation/mips/ingenic-tcu.txt diff --git a/Documentation/mips/ingenic-tcu.txt b/Documentation/mips/ingenic-tcu.txt new file mode 100644 index 000000000000..0ea35b2a46da --- /dev/null +++ b/Documentation/mips/ingenic-tcu.txt @@ -0,0 +1,60 @@ +Ingenic JZ47xx SoCs Timer/Counter Unit hardware +----------------------------------------------- + +The Timer/Counter Unit (TCU) in Ingenic JZ47xx SoCs is a multi-function +hardware block. It features up to to eight channels, that can be used as +counters, timers, or PWM. + +- JZ4725B, JZ4750, JZ4755 only have six TCU channels. The other SoCs all + have eight channels. + +- JZ4725B introduced a separate channel, called Operating System Timer + (OST). It is a 32-bit programmable timer. On JZ4770 and above, it is + 64-bit. + +- Each one of the TCU channels has its own clock, which can be reparented + to three different clocks (pclk, ext, rtc), gated, and reclocked, through + their TCSR register. + * The watchdog and OST hardware blocks also feature a TCSR register with + the same format in their register space. + * The TCU registers used to gate/ungate can also gate/ungate the watchdog + and OST clocks. + +- Each TCU channel works in one of two modes: + * mode TCU1: channels cannot work in sleep mode, but are easier to + operate. + * mode TCU2: channels can work in sleep mode, but the operation is a bit + more complicated than with TCU1 channels. + +- The mode of each TCU channel depends on the SoC used: + * On the oldest SoCs (up to JZ4740), all of the eight channels operate in + TCU1 mode. + * On JZ4725B, channel 5 operates as TCU2, the others operate as TCU1. + * On newest SoCs (JZ4750 and above), channels 1-2 operate as TCU2, the + others operate as TCU1. + +- Each channel can generate an interrupt. Some channels share an interrupt + line, some don't, and this changes between SoC versions: + * on older SoCs (JZ4740 and below), channel 0 and channel 1 have their + own interrupt line; channels 2-7 share the last interrupt line. + * On JZ4725B, channel 0 has its own interrupt; channels 1-5 share one + interrupt line; the OST uses the last interrupt line. + * on newer SoCs (JZ4750 and above), channel 5 has its own interrupt; + channels 0-4 and (if eight channels) 6-7 all share one interrupt line; + the OST uses the last interrupt line. + +Implementation +-------------- + +The functionalities of the TCU hardware are spread across multiple drivers: +- clocks/irq/timer: drivers/clocksource/ingenic-timer.c +- PWM: drivers/pwm/pwm-jz4740.c +- watchdog: drivers/watchdog/jz4740_wdt.c +- OST: drivers/clocksource/ingenic-ost.c + +Because various functionalities of the TCU that belong to different drivers +and frameworks can be controlled from the same registers, all of these +drivers access their registers through the same regmap. + +For more information regarding the devicetree bindings of the TCU drivers, +have a look at Documentation/devicetree/bindings/mfd/ingenic,tcu.txt. From patchwork Wed Mar 27 23:16:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067514 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="NHEKNCUv"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3mg34nTz9sBV for ; Thu, 28 Mar 2019 10:17:07 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730933AbfC0XRC (ORCPT ); Wed, 27 Mar 2019 19:17:02 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58430 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRC (ORCPT ); Wed, 27 Mar 2019 19:17:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728618; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=5Ll59DErd5wGJ3pnn+Wyg9b/lmHZ+0+DsY/1n4SmGV8=; b=NHEKNCUvkYUjmH7zrf136s4694WJWVTYrRJMAbVqa1IVlPGg3Q/rHdzjZ8IeQs5wZ17+j/ nIRVm1nlyegYGiODjgIPedmrp2pgbUxp8EBL1Hg0FucPdQC6alpXTJFPzBOpvFiVugT4PI zcP4t7jUkzeJKZL5XkyYh0rc/YMIr9U= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 03/27] dt-bindings: Add doc for the Ingenic TCU drivers Date: Thu, 28 Mar 2019 00:16:07 +0100 Message-Id: <20190327231631.15708-4-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add documentation about how to properly use the Ingenic TCU (Timer/Counter Unit) drivers from devicetree. Signed-off-by: Paul Cercueil Reviewed-by: Rob Herring Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- .../devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt | 25 ---- .../devicetree/bindings/timer/ingenic,tcu.txt | 139 +++++++++++++++++++++ .../bindings/watchdog/ingenic,jz4740-wdt.txt | 17 --- 3 files changed, 139 insertions(+), 42 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt create mode 100644 Documentation/devicetree/bindings/timer/ingenic,tcu.txt delete mode 100644 Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt diff --git a/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt b/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt deleted file mode 100644 index 7d9d3f90641b..000000000000 --- a/Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt +++ /dev/null @@ -1,25 +0,0 @@ -Ingenic JZ47xx PWM Controller -============================= - -Required properties: -- compatible: One of: - * "ingenic,jz4740-pwm" - * "ingenic,jz4770-pwm" - * "ingenic,jz4780-pwm" -- #pwm-cells: Should be 3. See pwm.txt in this directory for a description - of the cells format. -- clocks : phandle to the external clock. -- clock-names : Should be "ext". - - -Example: - - pwm: pwm@10002000 { - compatible = "ingenic,jz4740-pwm"; - reg = <0x10002000 0x1000>; - - #pwm-cells = <3>; - - clocks = <&ext>; - clock-names = "ext"; - }; diff --git a/Documentation/devicetree/bindings/timer/ingenic,tcu.txt b/Documentation/devicetree/bindings/timer/ingenic,tcu.txt new file mode 100644 index 000000000000..0a381cf9d286 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/ingenic,tcu.txt @@ -0,0 +1,139 @@ +Ingenic JZ47xx SoCs Timer/Counter Unit devicetree bindings +========================================================== + +For a description of the TCU hardware and drivers, have a look at +Documentation/mips/ingenic-tcu.txt. + +Required properties: + +- compatible: Must be one of: + * ingenic,jz4740-tcu + * ingenic,jz4725b-tcu + * ingenic,jz4770-tcu +- reg: Should be the offset/length value corresponding to the TCU registers +- clocks: List of phandle & clock specifiers for clocks external to the TCU. + The "pclk", "rtc", "ext" and "tcu" clocks should be provided. +- clock-names: List of name strings for the external clocks. +- #clock-cells: Should be <1>; + Clock consumers specify this argument to identify a clock. The valid values + may be found in . +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode an + interrupt source. The value should be 1. +- interrupt-parent : phandle of the interrupt controller. +- interrupts : Specifies the interrupt the controller is connected to. + +Optional properties: + +- ingenic,pwm-channels-mask: Bitmask of TCU channels reserved for PWM use. + Default value is 0xfc. + + +Children nodes +========================================================== + + +PWM node: +--------- + +Required properties: + +- compatible: Must be one of: + * ingenic,jz4740-pwm + * ingenic,jz4725b-pwm +- #pwm-cells: Should be 3. See ../pwm/pwm.txt for a description of the cell + format. +- clocks: List of phandle & clock specifiers for the TCU clocks. +- clock-names: List of name strings for the TCU clocks. + + +Watchdog node: +-------------- + +Required properties: + +- compatible: Must be one of: + * ingenic,jz4740-watchdog + * ingenic,jz4780-watchdog +- clocks: phandle to the WDT clock +- clock-names: should be "wdt" + + +OS Timer node: +--------- + +Required properties: + +- compatible: Must be one of: + * ingenic,jz4725b-ost + * ingenic,jz4770-ost +- clocks: phandle to the OST clock +- clock-names: should be "ost" +- interrupts : Specifies the interrupt the OST is connected to. + + +Example +========================================================== + +#include +#include + +/ { + tcu: timer@10002000 { + compatible = "ingenic,jz4770-tcu"; + reg = <0x10002000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x10002000 0x1000>; + + #clock-cells = <1>; + + clocks = <&cgu JZ4770_CLK_RTC + &cgu JZ4770_CLK_EXT + &cgu JZ4770_CLK_PCLK + &cgu JZ4770_CLK_EXT>; + clock-names = "rtc", "ext", "pclk", "tcu"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&intc>; + interrupts = <27 26 25>; + + watchdog: watchdog@0 { + compatible = "ingenic,jz4740-watchdog"; + reg = <0x0 0xc>; + + clocks = <&tcu TCU_CLK_WDT>; + clock-names = "wdt"; + }; + + pwm: pwm@40 { + compatible = "ingenic,jz4740-pwm"; + reg = <0x40 0x80>; + + #pwm-cells = <3>; + + clocks = <&tcu TCU_CLK_TIMER0 + &tcu TCU_CLK_TIMER1 + &tcu TCU_CLK_TIMER2 + &tcu TCU_CLK_TIMER3 + &tcu TCU_CLK_TIMER4 + &tcu TCU_CLK_TIMER5 + &tcu TCU_CLK_TIMER6 + &tcu TCU_CLK_TIMER7>; + clock-names = "timer0", "timer1", "timer2", "timer3", + "timer4", "timer5", "timer6", "timer7"; + }; + + ost: timer@e0 { + compatible = "ingenic,jz4770-ost"; + reg = <0xe0 0x20>; + + clocks = <&tcu TCU_CLK_OST>; + clock-names = "ost"; + + interrupts = <15>; + }; + }; +}; diff --git a/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt b/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt deleted file mode 100644 index ce1cb72d5345..000000000000 --- a/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt +++ /dev/null @@ -1,17 +0,0 @@ -Ingenic Watchdog Timer (WDT) Controller for JZ4740 & JZ4780 - -Required properties: -compatible: "ingenic,jz4740-watchdog" or "ingenic,jz4780-watchdog" -reg: Register address and length for watchdog registers -clocks: phandle to the RTC clock -clock-names: should be "rtc" - -Example: - -watchdog: jz4740-watchdog@10002000 { - compatible = "ingenic,jz4740-watchdog"; - reg = <0x10002000 0x10>; - - clocks = <&cgu JZ4740_CLK_RTC>; - clock-names = "rtc"; -}; From patchwork Wed Mar 27 23:16:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067539 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="xkfLfe2+"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3qR5kWSz9sBV for ; Thu, 28 Mar 2019 10:19:31 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731212AbfC0XRH (ORCPT ); Wed, 27 Mar 2019 19:17:07 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58490 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRG (ORCPT ); Wed, 27 Mar 2019 19:17:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728623; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=62MRtFz3VGnltzlL3cw4x9QcGk35sgJovfzSKaxeKBc=; b=xkfLfe2+4fSCE9ITBAjNqGc5xRbeMi0fpdBCTpzTyxtEwnE4S1n0JBnNsHvH0b/Olk3H1O 9BzrntnALOj040Oy1I+qm6zDiqMz8Uy5bISYJuTxF3kbb6MbFOrAuHJHyONmIGbCZYVVmd GPcw2Ycai6rHVS3Xg5X3GbIN0rtalm0= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 04/27] clocksource: Add a new timer-ingenic driver Date: Thu, 28 Mar 2019 00:16:08 +0100 Message-Id: <20190327231631.15708-5-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org This driver handles the TCU (Timer Counter Unit) present on the Ingenic JZ47xx SoCs, and provides the kernel with a system timer, and optionally with a clocksource and a sched_clock. It also provides clocks and interrupt handling to client drivers. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/clocksource/Kconfig | 10 + drivers/clocksource/Makefile | 1 + drivers/clocksource/ingenic-timer.c | 920 ++++++++++++++++++++++++++++++++++++ drivers/clocksource/ingenic-timer.h | 15 + include/linux/mfd/ingenic-tcu.h | 4 + 5 files changed, 950 insertions(+) create mode 100644 drivers/clocksource/ingenic-timer.c create mode 100644 drivers/clocksource/ingenic-timer.h diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 171502a356aa..c6fb17233ff2 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -645,6 +645,16 @@ config GX6605S_TIMER help This option enables support for gx6605s SOC's timer. +config INGENIC_TIMER + bool "Clocksource/timer using the TCU in Ingenic JZ SoCs" + depends on MIPS || COMPILE_TEST + depends on COMMON_CLK + select TIMER_OF + select IRQ_DOMAIN + select REGMAP + help + Support for the timer/counter unit of the Ingenic JZ SoCs. + config MILBEAUT_TIMER bool "Milbeaut timer driver" if COMPILE_TEST depends on OF diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index be6e0fbc7489..0e360da7b74d 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o +obj-$(CONFIG_INGENIC_TIMER) += ingenic-timer.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.o diff --git a/drivers/clocksource/ingenic-timer.c b/drivers/clocksource/ingenic-timer.c new file mode 100644 index 000000000000..dc446f280fd3 --- /dev/null +++ b/drivers/clocksource/ingenic-timer.c @@ -0,0 +1,920 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * JZ47xx SoCs TCU IRQ driver + * Copyright (C) 2019 Paul Cercueil + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ingenic-timer.h" + +/* 8 channels max + watchdog + OST */ +#define TCU_CLK_COUNT 10 + +enum tcu_clk_parent { + TCU_PARENT_PCLK, + TCU_PARENT_RTC, + TCU_PARENT_EXT, +}; + +struct ingenic_soc_info { + unsigned char num_channels; + bool has_ost; +}; + +struct ingenic_tcu_clk_info { + struct clk_init_data init_data; + u8 gate_bit; + u8 tcsr_reg; +}; + +struct ingenic_tcu_clk { + struct clk_hw hw; + + struct regmap *map; + const struct ingenic_tcu_clk_info *info; + + unsigned int idx; +}; + +struct ingenic_tcu { + const struct ingenic_soc_info *soc_info; + struct regmap *map; + struct clk *clk, *timer_clk, *cs_clk; + + struct irq_domain *domain; + unsigned int nb_parent_irqs; + u32 parent_irqs[3]; + + struct clk_hw_onecell_data *clocks; + + unsigned int timer_channel, cs_channel; + struct clock_event_device cevt; + struct clocksource cs; + char name[4]; + + unsigned long pwm_channels_mask; +}; + +static struct ingenic_tcu *ingenic_tcu; + +void __iomem *ingenic_tcu_base; +EXPORT_SYMBOL_GPL(ingenic_tcu_base); + +static inline struct ingenic_tcu_clk *to_tcu_clk(struct clk_hw *hw) +{ + return container_of(hw, struct ingenic_tcu_clk, hw); +} + +static int ingenic_tcu_enable(struct clk_hw *hw) +{ + struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); + const struct ingenic_tcu_clk_info *info = tcu_clk->info; + + regmap_write(tcu_clk->map, TCU_REG_TSCR, BIT(info->gate_bit)); + + return 0; +} + +static void ingenic_tcu_disable(struct clk_hw *hw) +{ + struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); + const struct ingenic_tcu_clk_info *info = tcu_clk->info; + + regmap_write(tcu_clk->map, TCU_REG_TSSR, BIT(info->gate_bit)); +} + +static int ingenic_tcu_is_enabled(struct clk_hw *hw) +{ + struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); + const struct ingenic_tcu_clk_info *info = tcu_clk->info; + unsigned int value; + + regmap_read(tcu_clk->map, TCU_REG_TSR, &value); + + return !(value & BIT(info->gate_bit)); +} + +static u8 ingenic_tcu_get_parent(struct clk_hw *hw) +{ + struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); + const struct ingenic_tcu_clk_info *info = tcu_clk->info; + unsigned int val = 0; + int ret; + + ret = regmap_read(tcu_clk->map, info->tcsr_reg, &val); + WARN_ONCE(ret < 0, "Unable to read TCSR %i", tcu_clk->idx); + + return ffs(val & TCU_TCSR_PARENT_CLOCK_MASK) - 1; +} + +static int ingenic_tcu_set_parent(struct clk_hw *hw, u8 idx) +{ + struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); + const struct ingenic_tcu_clk_info *info = tcu_clk->info; + int ret, enabled; + + /* + * To be able to access TCSR we must ungate the clock supply and we gate + * it again when done. + */ + enabled = ingenic_tcu_is_enabled(hw); + ingenic_tcu_enable(hw); + + ret = regmap_update_bits(tcu_clk->map, info->tcsr_reg, + TCU_TCSR_PARENT_CLOCK_MASK, BIT(idx)); + WARN_ONCE(ret < 0, "Unable to update TCSR %i", tcu_clk->idx); + + if (!enabled) + ingenic_tcu_disable(hw); + + return 0; +} + +static unsigned long ingenic_tcu_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); + const struct ingenic_tcu_clk_info *info = tcu_clk->info; + unsigned int prescale; + int ret; + + ret = regmap_read(tcu_clk->map, info->tcsr_reg, &prescale); + WARN_ONCE(ret < 0, "Unable to read TCSR %i", tcu_clk->idx); + + prescale = (prescale & TCU_TCSR_PRESCALE_MASK) >> TCU_TCSR_PRESCALE_LSB; + + return parent_rate >> (prescale * 2); +} + +static u8 ingenic_tcu_get_prescale(unsigned long rate, unsigned long req_rate) +{ + u8 prescale; + + for (prescale = 0; prescale < 5; prescale++) + if ((rate >> (prescale * 2)) <= req_rate) + return prescale; + + return 5; /* /1024 divider */ +} + +static long ingenic_tcu_round_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long *parent_rate) +{ + unsigned long rate = *parent_rate; + u8 prescale; + + if (req_rate > rate) + return -EINVAL; + + prescale = ingenic_tcu_get_prescale(rate, req_rate); + + return rate >> (prescale * 2); +} + +static int ingenic_tcu_set_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long parent_rate) +{ + struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw); + const struct ingenic_tcu_clk_info *info = tcu_clk->info; + struct regmap *map = tcu_clk->map; + u8 prescale = ingenic_tcu_get_prescale(parent_rate, req_rate); + int ret; + + ret = regmap_update_bits(map, info->tcsr_reg, + TCU_TCSR_PRESCALE_MASK, + prescale << TCU_TCSR_PRESCALE_LSB); + WARN_ONCE(ret < 0, "Unable to update TCSR %i", tcu_clk->idx); + + return 0; +} + +static const struct clk_ops ingenic_tcu_clk_ops = { + .get_parent = ingenic_tcu_get_parent, + .set_parent = ingenic_tcu_set_parent, + + .recalc_rate = ingenic_tcu_recalc_rate, + .round_rate = ingenic_tcu_round_rate, + .set_rate = ingenic_tcu_set_rate, + + .enable = ingenic_tcu_enable, + .disable = ingenic_tcu_disable, + .is_enabled = ingenic_tcu_is_enabled, +}; + +static const char * const ingenic_tcu_timer_parents[] = { + [TCU_PARENT_PCLK] = "pclk", + [TCU_PARENT_RTC] = "rtc", + [TCU_PARENT_EXT] = "ext", +}; + +#define DEF_TIMER(_name, _gate_bit, _tcsr) \ + { \ + .init_data = { \ + .name = _name, \ + .parent_names = ingenic_tcu_timer_parents, \ + .num_parents = ARRAY_SIZE(ingenic_tcu_timer_parents),\ + .ops = &ingenic_tcu_clk_ops, \ + .flags = CLK_SET_RATE_UNGATE, \ + }, \ + .gate_bit = _gate_bit, \ + .tcsr_reg = _tcsr, \ + } +static const struct ingenic_tcu_clk_info ingenic_tcu_clk_info[] = { + [TCU_CLK_TIMER0] = DEF_TIMER("timer0", 0, TCU_REG_TCSRc(0)), + [TCU_CLK_TIMER1] = DEF_TIMER("timer1", 1, TCU_REG_TCSRc(1)), + [TCU_CLK_TIMER2] = DEF_TIMER("timer2", 2, TCU_REG_TCSRc(2)), + [TCU_CLK_TIMER3] = DEF_TIMER("timer3", 3, TCU_REG_TCSRc(3)), + [TCU_CLK_TIMER4] = DEF_TIMER("timer4", 4, TCU_REG_TCSRc(4)), + [TCU_CLK_TIMER5] = DEF_TIMER("timer5", 5, TCU_REG_TCSRc(5)), + [TCU_CLK_TIMER6] = DEF_TIMER("timer6", 6, TCU_REG_TCSRc(6)), + [TCU_CLK_TIMER7] = DEF_TIMER("timer7", 7, TCU_REG_TCSRc(7)), +}; + +static const struct ingenic_tcu_clk_info ingenic_tcu_watchdog_clk_info = + DEF_TIMER("wdt", 16, TCU_REG_WDT_TCSR); +static const struct ingenic_tcu_clk_info ingenic_tcu_ost_clk_info = + DEF_TIMER("ost", 15, TCU_REG_OST_TCSR); +#undef DEF_TIMER + +static void ingenic_tcu_intc_cascade(struct irq_desc *desc) +{ + struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data); + struct irq_domain *domain = irq_desc_get_handler_data(desc); + struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0); + struct regmap *map = gc->private; + uint32_t irq_reg, irq_mask; + unsigned int i; + + regmap_read(map, TCU_REG_TFR, &irq_reg); + regmap_read(map, TCU_REG_TMR, &irq_mask); + + chained_irq_enter(irq_chip, desc); + + irq_reg &= ~irq_mask; + + for_each_set_bit(i, (unsigned long *)&irq_reg, 32) + generic_handle_irq(irq_linear_revmap(domain, i)); + + chained_irq_exit(irq_chip, desc); +} + +static void ingenic_tcu_gc_unmask_enable_reg(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct irq_chip_type *ct = irq_data_get_chip_type(d); + struct regmap *map = gc->private; + u32 mask = d->mask; + + irq_gc_lock(gc); + regmap_write(map, ct->regs.ack, mask); + regmap_write(map, ct->regs.enable, mask); + *ct->mask_cache |= mask; + irq_gc_unlock(gc); +} + +static void ingenic_tcu_gc_mask_disable_reg(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct irq_chip_type *ct = irq_data_get_chip_type(d); + struct regmap *map = gc->private; + u32 mask = d->mask; + + irq_gc_lock(gc); + regmap_write(map, ct->regs.disable, mask); + *ct->mask_cache &= ~mask; + irq_gc_unlock(gc); +} + +static void ingenic_tcu_gc_mask_disable_reg_and_ack(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct irq_chip_type *ct = irq_data_get_chip_type(d); + struct regmap *map = gc->private; + u32 mask = d->mask; + + irq_gc_lock(gc); + regmap_write(map, ct->regs.ack, mask); + regmap_write(map, ct->regs.disable, mask); + irq_gc_unlock(gc); +} + +static inline struct ingenic_tcu *cs_to_ingenic_tcu(struct clocksource *cs) +{ + return container_of(cs, struct ingenic_tcu, cs); +} + +static inline struct ingenic_tcu *to_ingenic_tcu(struct clock_event_device *evt) +{ + return container_of(evt, struct ingenic_tcu, cevt); +} + +static int ingenic_tcu_cevt_set_state_shutdown(struct clock_event_device *evt) +{ + struct ingenic_tcu *tcu = to_ingenic_tcu(evt); + + regmap_write(tcu->map, TCU_REG_TECR, BIT(tcu->timer_channel)); + + return 0; +} + +static u64 notrace ingenic_tcu_timer_read(void) +{ + unsigned int channel = ingenic_tcu->cs_channel; + u16 count; + + /* Bypass the regmap here as we must return as soon as possible */ + count = readw(ingenic_tcu_base + TCU_REG_TCNTc(channel)); + + return count; +} + +static u64 notrace ingenic_tcu_timer_cs_read(struct clocksource *cs) +{ + struct ingenic_tcu *tcu = cs_to_ingenic_tcu(cs); + unsigned int val; + + regmap_read(tcu->map, TCU_REG_TCNTc(tcu->cs_channel), &val); + + return val; +} + +static int ingenic_tcu_cevt_set_next(unsigned long next, + struct clock_event_device *evt) +{ + struct ingenic_tcu *tcu = to_ingenic_tcu(evt); + + if (next > 0xffff) + return -EINVAL; + + regmap_write(tcu->map, TCU_REG_TDFRc(tcu->timer_channel), next); + regmap_write(tcu->map, TCU_REG_TCNTc(tcu->timer_channel), 0); + regmap_write(tcu->map, TCU_REG_TESR, BIT(tcu->timer_channel)); + + return 0; +} + +static irqreturn_t ingenic_tcu_cevt_cb(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + struct ingenic_tcu *tcu = to_ingenic_tcu(evt); + + regmap_write(tcu->map, TCU_REG_TECR, BIT(tcu->timer_channel)); + + if (evt->event_handler) + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static int __init ingenic_tcu_register_clock(struct ingenic_tcu *tcu, + unsigned int idx, enum tcu_clk_parent parent, + const struct ingenic_tcu_clk_info *info, + struct clk_hw_onecell_data *clocks) +{ + struct ingenic_tcu_clk *tcu_clk; + int err; + + tcu_clk = kzalloc(sizeof(*tcu_clk), GFP_KERNEL); + if (!tcu_clk) + return -ENOMEM; + + tcu_clk->hw.init = &info->init_data; + tcu_clk->idx = idx; + tcu_clk->info = info; + tcu_clk->map = tcu->map; + + /* Reset channel and clock divider, set default parent */ + ingenic_tcu_enable(&tcu_clk->hw); + regmap_update_bits(tcu->map, info->tcsr_reg, 0xffff, BIT(parent)); + ingenic_tcu_disable(&tcu_clk->hw); + + err = clk_hw_register(NULL, &tcu_clk->hw); + if (err) + goto err_free_tcu_clk; + + err = clk_hw_register_clkdev(&tcu_clk->hw, info->init_data.name, NULL); + if (err) + goto err_clk_unregister; + + clocks->hws[idx] = &tcu_clk->hw; + + return 0; + +err_clk_unregister: + clk_hw_unregister(&tcu_clk->hw); +err_free_tcu_clk: + kfree(tcu_clk); + return err; +} + +static int __init ingenic_tcu_clk_init(struct ingenic_tcu *tcu, + struct device_node *np) +{ + size_t i; + int ret; + + tcu->clocks = kzalloc(sizeof(*tcu->clocks) + + sizeof(*tcu->clocks->hws) * TCU_CLK_COUNT, + GFP_KERNEL); + if (!tcu->clocks) + return -ENOMEM; + + tcu->clocks->num = TCU_CLK_COUNT; + + for (i = 0; i < tcu->soc_info->num_channels; i++) { + ret = ingenic_tcu_register_clock(tcu, i, TCU_PARENT_EXT, + &ingenic_tcu_clk_info[i], + tcu->clocks); + if (ret) { + pr_crit("ingenic-timer: cannot register clock timer%zu\n", i); + goto err_unregister_timer_clocks; + } + } + + /* + * We set EXT as the default parent clock for all the TCU clocks + * except for the watchdog one, where we set the RTC clock as the + * parent. Since the EXT and PCLK are much faster than the RTC clock, + * the watchdog would kick after a maximum time of 5s, and we might + * want a slower kicking time. + */ + ret = ingenic_tcu_register_clock(tcu, TCU_CLK_WDT, TCU_PARENT_RTC, + &ingenic_tcu_watchdog_clk_info, + tcu->clocks); + if (ret) { + pr_crit("ingenic-timer: cannot register watchdog clock\n"); + goto err_unregister_timer_clocks; + } + + if (tcu->soc_info->has_ost) { + ret = ingenic_tcu_register_clock(tcu, TCU_CLK_OST, + TCU_PARENT_EXT, + &ingenic_tcu_ost_clk_info, + tcu->clocks); + if (ret) { + pr_crit("ingenic-timer: cannot register ost clock\n"); + goto err_unregister_watchdog_clock; + } + } + + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, tcu->clocks); + if (ret) { + pr_crit("ingenic-timer: cannot add OF clock provider\n"); + goto err_unregister_ost_clock; + } + + return 0; + +err_unregister_ost_clock: + if (tcu->soc_info->has_ost) + clk_hw_unregister(tcu->clocks->hws[i + 1]); +err_unregister_watchdog_clock: + clk_hw_unregister(tcu->clocks->hws[i]); +err_unregister_timer_clocks: + for (i = 0; i < tcu->clocks->num; i++) + if (tcu->clocks->hws[i]) + clk_hw_unregister(tcu->clocks->hws[i]); + kfree(tcu->clocks); + return ret; +} + +static void __init ingenic_tcu_clk_cleanup(struct ingenic_tcu *tcu, + struct device_node *np) +{ + unsigned int i; + + of_clk_del_provider(np); + + for (i = 0; i < tcu->clocks->num; i++) + clk_hw_unregister(tcu->clocks->hws[i]); + kfree(tcu->clocks); +} + +static int __init ingenic_tcu_intc_init(struct ingenic_tcu *tcu, + struct device_node *np) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + int err, i, irqs; + + irqs = of_property_count_elems_of_size(np, "interrupts", sizeof(u32)); + if (irqs < 0 || irqs > ARRAY_SIZE(tcu->parent_irqs)) + return -EINVAL; + + tcu->nb_parent_irqs = irqs; + + tcu->domain = irq_domain_add_linear(np, 32, &irq_generic_chip_ops, + NULL); + if (!tcu->domain) + return -ENOMEM; + + err = irq_alloc_domain_generic_chips(tcu->domain, 32, 1, "TCU", + handle_level_irq, 0, + IRQ_NOPROBE | IRQ_LEVEL, 0); + if (err) + goto out_domain_remove; + + gc = irq_get_domain_generic_chip(tcu->domain, 0); + ct = gc->chip_types; + + gc->wake_enabled = IRQ_MSK(32); + gc->private = tcu->map; + + ct->regs.disable = TCU_REG_TMSR; + ct->regs.enable = TCU_REG_TMCR; + ct->regs.ack = TCU_REG_TFCR; + ct->chip.irq_unmask = ingenic_tcu_gc_unmask_enable_reg; + ct->chip.irq_mask = ingenic_tcu_gc_mask_disable_reg; + ct->chip.irq_mask_ack = ingenic_tcu_gc_mask_disable_reg_and_ack; + ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE; + + /* Mask all IRQs by default */ + regmap_write(tcu->map, TCU_REG_TMSR, IRQ_MSK(32)); + + /* + * On JZ4740, timer 0 and timer 1 have their own interrupt line; + * timers 2-7 share one interrupt. + * On SoCs >= JZ4770, timer 5 has its own interrupt line; + * timers 0-4 and 6-7 share one single interrupt. + * + * To keep things simple, we just register the same handler to + * all parent interrupts. The handler will properly detect which + * channel fired the interrupt. + */ + for (i = 0; i < irqs; i++) { + tcu->parent_irqs[i] = irq_of_parse_and_map(np, i); + if (!tcu->parent_irqs[i]) { + err = -EINVAL; + goto out_unmap_irqs; + } + + irq_set_chained_handler_and_data(tcu->parent_irqs[i], + ingenic_tcu_intc_cascade, + tcu->domain); + } + + return 0; + +out_unmap_irqs: + for (; i > 0; i--) + irq_dispose_mapping(tcu->parent_irqs[i - 1]); +out_domain_remove: + irq_domain_remove(tcu->domain); + return err; +} + +static void __init ingenic_tcu_intc_cleanup(struct ingenic_tcu *tcu) +{ + unsigned int i; + + for (i = 0; i < tcu->nb_parent_irqs; i++) + irq_dispose_mapping(tcu->parent_irqs[i]); + + irq_domain_remove(tcu->domain); +} + +static int __init ingenic_tcu_timer_init(struct ingenic_tcu *tcu) +{ + unsigned int timer_virq; + unsigned long rate; + int err; + + tcu->timer_clk = tcu->clocks->hws[tcu->timer_channel]->clk; + + err = clk_prepare_enable(tcu->timer_clk); + if (err) + return err; + + rate = clk_get_rate(tcu->timer_clk); + if (!rate) { + err = -EINVAL; + goto err_clk_disable; + } + + timer_virq = irq_create_mapping(tcu->domain, tcu->timer_channel); + if (!timer_virq) { + err = -EINVAL; + goto err_clk_disable; + } + + snprintf(tcu->name, sizeof(tcu->name), "TCU"); + + err = request_irq(timer_virq, ingenic_tcu_cevt_cb, IRQF_TIMER, + tcu->name, &tcu->cevt); + if (err) + goto err_irq_dispose_mapping; + + tcu->cevt.cpumask = cpumask_of(smp_processor_id()); + tcu->cevt.features = CLOCK_EVT_FEAT_ONESHOT; + tcu->cevt.name = tcu->name; + tcu->cevt.rating = 200; + tcu->cevt.set_state_shutdown = ingenic_tcu_cevt_set_state_shutdown; + tcu->cevt.set_next_event = ingenic_tcu_cevt_set_next; + + clockevents_config_and_register(&tcu->cevt, rate, 10, 0xffff); + + return 0; + +err_irq_dispose_mapping: + irq_dispose_mapping(timer_virq); +err_clk_disable: + clk_disable_unprepare(tcu->timer_clk); + return err; +} + +static int __init ingenic_tcu_clocksource_init(struct ingenic_tcu *tcu) +{ + unsigned int channel = tcu->cs_channel; + struct clocksource *cs = &tcu->cs; + unsigned long rate; + int err; + + tcu->cs_clk = tcu->clocks->hws[channel]->clk; + + err = clk_prepare_enable(tcu->cs_clk); + if (err) + return err; + + rate = clk_get_rate(tcu->cs_clk); + if (!rate) { + err = -EINVAL; + goto err_clk_disable; + } + + /* Reset channel */ + regmap_update_bits(tcu->map, TCU_REG_TCSRc(channel), + 0xffff & ~TCU_TCSR_RESERVED_BITS, 0); + + /* Reset counter */ + regmap_write(tcu->map, TCU_REG_TDFRc(channel), 0xffff); + regmap_write(tcu->map, TCU_REG_TCNTc(channel), 0); + + /* Enable channel */ + regmap_write(tcu->map, TCU_REG_TESR, BIT(channel)); + + cs->name = "ingenic-timer"; + cs->rating = 200; + cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; + cs->mask = CLOCKSOURCE_MASK(16); + cs->read = ingenic_tcu_timer_cs_read; + + err = clocksource_register_hz(cs, rate); + if (err) + goto err_clk_disable; + + return 0; + +err_clk_disable: + clk_disable_unprepare(tcu->cs_clk); + return err; +} + +static void __init ingenic_tcu_clocksource_cleanup(struct ingenic_tcu *tcu) +{ + clocksource_unregister(&tcu->cs); + clk_disable_unprepare(tcu->cs_clk); +} + +static const struct regmap_config ingenic_tcu_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static const struct ingenic_soc_info jz4740_soc_info = { + .num_channels = 8, + .has_ost = false, +}; + +static const struct ingenic_soc_info jz4725b_soc_info = { + .num_channels = 6, + .has_ost = true, +}; + +static const struct ingenic_soc_info jz4770_soc_info = { + .num_channels = 8, + .has_ost = true, +}; + +static const struct of_device_id ingenic_tcu_of_match[] = { + { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, }, + { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, }, + { .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, }, + { } +}; + +static int __init ingenic_tcu_init(struct device_node *np) +{ + const struct of_device_id *id = of_match_node(ingenic_tcu_of_match, np); + const struct ingenic_soc_info *soc_info = id->data; + struct ingenic_tcu *tcu; + struct resource res; + void __iomem *base; + long rate; + int ret; + + of_node_clear_flag(np, OF_POPULATED); + + tcu = kzalloc(sizeof(*tcu), GFP_KERNEL); + if (!tcu) + return -ENOMEM; + + /* + * Enable all TCU channels for PWM use by default except channel 0 + * and channel 1. + */ + tcu->pwm_channels_mask = GENMASK(soc_info->num_channels - 1, 2); + of_property_read_u32(np, "ingenic,pwm-channels-mask", + (u32 *)&tcu->pwm_channels_mask); + + /* Verify that we have at least two free channels */ + if (hweight8(tcu->pwm_channels_mask) > soc_info->num_channels - 2) { + pr_crit("ingenic-tcu: Invalid PWM channel mask: 0x%02lx\n", + tcu->pwm_channels_mask); + return -EINVAL; + } + + tcu->soc_info = soc_info; + ingenic_tcu = tcu; + + tcu->timer_channel = find_first_zero_bit(&tcu->pwm_channels_mask, + soc_info->num_channels); + tcu->cs_channel = find_next_zero_bit(&tcu->pwm_channels_mask, + soc_info->num_channels, + tcu->timer_channel + 1); + + base = of_io_request_and_map(np, 0, NULL); + if (IS_ERR(base)) { + ret = PTR_ERR(base); + goto err_free_ingenic_tcu; + } + + of_address_to_resource(np, 0, &res); + + ingenic_tcu_base = base; + + tcu->map = regmap_init_mmio(NULL, base, &ingenic_tcu_regmap_config); + if (IS_ERR(tcu->map)) { + ret = PTR_ERR(tcu->map); + goto err_iounmap; + } + + tcu->clk = of_clk_get_by_name(np, "tcu"); + if (IS_ERR(tcu->clk)) { + ret = PTR_ERR(tcu->clk); + pr_crit("ingenic-tcu: Unable to find TCU clock: %i\n", ret); + goto err_free_regmap; + } + + ret = clk_prepare_enable(tcu->clk); + if (ret) { + pr_crit("ingenic-tcu: Unable to enable TCU clock: %i\n", ret); + goto err_clk_put; + } + + ret = ingenic_tcu_intc_init(tcu, np); + if (ret) + goto err_clk_disable; + + ret = ingenic_tcu_clk_init(tcu, np); + if (ret) + goto err_tcu_intc_cleanup; + + ret = ingenic_tcu_clocksource_init(tcu); + if (ret) + goto err_tcu_clk_cleanup; + + ret = ingenic_tcu_timer_init(tcu); + if (ret) + goto err_tcu_clocksource_cleanup; + + /* Register the sched_clock at the end as there's no way to undo it */ + rate = clk_get_rate(tcu->cs_clk); + sched_clock_register(ingenic_tcu_timer_read, 16, rate); + + return 0; + +err_tcu_clocksource_cleanup: + ingenic_tcu_clocksource_cleanup(tcu); +err_tcu_clk_cleanup: + ingenic_tcu_clk_cleanup(tcu, np); +err_tcu_intc_cleanup: + ingenic_tcu_intc_cleanup(tcu); +err_clk_disable: + clk_disable_unprepare(tcu->clk); +err_clk_put: + clk_put(tcu->clk); +err_free_regmap: + regmap_exit(tcu->map); +err_iounmap: + iounmap(base); + release_mem_region(res.start, resource_size(&res)); +err_free_ingenic_tcu: + kfree(tcu); + return ret; +} + +TIMER_OF_DECLARE(jz4740_tcu_intc, "ingenic,jz4740-tcu", ingenic_tcu_init); +TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu", ingenic_tcu_init); +TIMER_OF_DECLARE(jz4770_tcu_intc, "ingenic,jz4770-tcu", ingenic_tcu_init); + + +static int __init ingenic_tcu_probe(struct platform_device *pdev) +{ + platform_set_drvdata(pdev, ingenic_tcu); + + regmap_attach_dev(&pdev->dev, ingenic_tcu->map, + &ingenic_tcu_regmap_config); + + return devm_of_platform_populate(&pdev->dev); +} + +#ifdef CONFIG_PM_SLEEP +static int ingenic_tcu_suspend(struct device *dev) +{ + struct ingenic_tcu *tcu = dev_get_drvdata(dev); + + clk_disable(tcu->cs_clk); + clk_disable(tcu->timer_clk); + clk_disable(tcu->clk); + return 0; +} + +static int ingenic_tcu_resume(struct device *dev) +{ + struct ingenic_tcu *tcu = dev_get_drvdata(dev); + int ret; + + ret = clk_enable(tcu->clk); + if (ret) + return ret; + + ret = clk_enable(tcu->timer_clk); + if (ret) + goto err_tcu_clk_disable; + + ret = clk_enable(tcu->cs_clk); + if (ret) + goto err_tcu_timer_clk_disable; + + return 0; + +err_tcu_timer_clk_disable: + clk_disable(tcu->timer_clk); +err_tcu_clk_disable: + clk_disable(tcu->clk); + return ret; +} + +static const struct dev_pm_ops ingenic_tcu_pm_ops = { + /* _noirq: We want the TCU clock to be gated last / ungated first */ + .suspend_noirq = ingenic_tcu_suspend, + .resume_noirq = ingenic_tcu_resume, +}; +#define INGENIC_TCU_PM_OPS (&ingenic_tcu_pm_ops) + +#else +#define INGENIC_TCU_PM_OPS NULL +#endif /* CONFIG_PM_SUSPEND */ + +static struct platform_driver ingenic_tcu_driver = { + .driver = { + .name = "ingenic-tcu", + .pm = INGENIC_TCU_PM_OPS, + .of_match_table = ingenic_tcu_of_match, + }, +}; + +static int __init ingenic_tcu_platform_init(void) +{ + return platform_driver_probe(&ingenic_tcu_driver, + ingenic_tcu_probe); +} +subsys_initcall(ingenic_tcu_platform_init); + +bool ingenic_tcu_pwm_can_use_chn(struct device *dev, unsigned int channel) +{ + struct ingenic_tcu *tcu = dev_get_drvdata(dev->parent); + + return !!(tcu->pwm_channels_mask & BIT(channel)); +} +EXPORT_SYMBOL_GPL(ingenic_tcu_pwm_can_use_chn); diff --git a/drivers/clocksource/ingenic-timer.h b/drivers/clocksource/ingenic-timer.h new file mode 100644 index 000000000000..fa43da836ab6 --- /dev/null +++ b/drivers/clocksource/ingenic-timer.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DRIVERS_CLOCKSOURCE_INGENIC_TIMER_H__ +#define __DRIVERS_CLOCKSOURCE_INGENIC_TIMER_H__ + +#include + +/* + * README: For use *ONLY* by the ingenic-ost driver. + * Regular drivers which want to access the TCU registers + * must have ingenic-timer as parent and retrieve the regmap + * doing dev_get_regmap(pdev->dev.parent); + */ +extern void __iomem *ingenic_tcu_base; + +#endif /* __DRIVERS_CLOCKSOURCE_INGENIC_TIMER_H__ */ diff --git a/include/linux/mfd/ingenic-tcu.h b/include/linux/mfd/ingenic-tcu.h index 2083fa20821d..7518a137ab40 100644 --- a/include/linux/mfd/ingenic-tcu.h +++ b/include/linux/mfd/ingenic-tcu.h @@ -7,6 +7,8 @@ #include +struct device; + #define TCU_REG_WDT_TDR 0x00 #define TCU_REG_WDT_TCER 0x04 #define TCU_REG_WDT_TCNT 0x08 @@ -53,4 +55,6 @@ #define TCU_REG_TCNTc(c) (TCU_REG_TCNT0 + ((c) * TCU_CHANNEL_STRIDE)) #define TCU_REG_TCSRc(c) (TCU_REG_TCSR0 + ((c) * TCU_CHANNEL_STRIDE)) +bool ingenic_tcu_pwm_can_use_chn(struct device *dev, unsigned int channel); + #endif /* __LINUX_MFD_INGENIC_TCU_H_ */ From patchwork Wed Mar 27 23:16:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067538 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="VwBeUAVd"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3qP5Swfz9sBV for ; Thu, 28 Mar 2019 10:19:29 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731356AbfC0XRJ (ORCPT ); Wed, 27 Mar 2019 19:17:09 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58540 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731122AbfC0XRI (ORCPT ); Wed, 27 Mar 2019 19:17:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728625; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=2HjsG60H2GgJjgPPTcQEt4g9NWXUCEtxTAIaggqC49E=; b=VwBeUAVd457o0BLGb5bjmGTz+yb/xWDGe4Obuw4txA06/dFH2xyINX5Uta2LtUlWwYcZcD nE2+zJuHXEPln9+mp18DS3tX6pv/wnMqJYWb2RrYn1oLwFNur8xRZWhV4HITKiAS8YeFcL 6axnn8cnfwRfi6IlP/cFzMnIRCxrzMk= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Maarten ter Huurne , Paul Cercueil Subject: [PATCH v11 05/27] clocksource: Add driver for the Ingenic JZ47xx OST Date: Thu, 28 Mar 2019 00:16:09 +0100 Message-Id: <20190327231631.15708-6-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org From: Maarten ter Huurne OST is the OS Timer, a 64-bit timer/counter with buffered reading. SoCs before the JZ4770 had (if any) a 32-bit OST; the JZ4770 and JZ4780 have a 64-bit OST. This driver will register both a clocksource and a sched_clock to the system. Signed-off-by: Maarten ter Huurne Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/clocksource/Kconfig | 8 ++ drivers/clocksource/Makefile | 1 + drivers/clocksource/ingenic-ost.c | 220 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 drivers/clocksource/ingenic-ost.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index c6fb17233ff2..d58ca614e852 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -655,6 +655,14 @@ config INGENIC_TIMER help Support for the timer/counter unit of the Ingenic JZ SoCs. +config INGENIC_OST + bool "Ingenic JZ47xx Operating System Timer" + depends on MIPS || COMPILE_TEST + depends on COMMON_CLK + select INGENIC_TIMER + help + Support for the OS Timer of the Ingenic JZ4770 or similar SoC. + config MILBEAUT_TIMER bool "Milbeaut timer driver" if COMPILE_TEST depends on OF diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 0e360da7b74d..b3d304ec7072 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o +obj-$(CONFIG_INGENIC_OST) += ingenic-ost.o obj-$(CONFIG_INGENIC_TIMER) += ingenic-timer.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o diff --git a/drivers/clocksource/ingenic-ost.c b/drivers/clocksource/ingenic-ost.c new file mode 100644 index 000000000000..66ad328c74cc --- /dev/null +++ b/drivers/clocksource/ingenic-ost.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * JZ47xx SoCs TCU Operating System Timer driver + * + * Copyright (C) 2016 Maarten ter Huurne + * Copyright (C) 2019 Paul Cercueil + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ingenic-timer.h" + +#define TCU_OST_TCSR_MASK 0xffc0 +#define TCU_OST_TCSR_CNT_MD BIT(15) + +#define TCU_OST_CHANNEL 15 + +struct ingenic_ost_soc_info { + bool is64bit; +}; + +struct ingenic_ost { + struct regmap *map; + struct clk *clk; + + struct clocksource cs; +}; + +static inline struct ingenic_ost *cs_to_ingenic_ost(struct clocksource *cs) +{ + return container_of(cs, struct ingenic_ost, cs); +} + +static u64 notrace ingenic_ost_read_cntl(void) +{ + /* Bypass the regmap here as we must return as soon as possible */ + return readl(ingenic_tcu_base + TCU_REG_OST_CNTL); +} + +static u64 notrace ingenic_ost_read_cnth(void) +{ + /* Bypass the regmap here as we must return as soon as possible */ + return readl(ingenic_tcu_base + TCU_REG_OST_CNTH); +} + +static u64 notrace ingenic_ost_clocksource_read64(struct clocksource *cs) +{ + struct ingenic_ost *ost = cs_to_ingenic_ost(cs); + unsigned int val1, val2; + u64 count, recount; + s64 diff; + + /* + * The buffering of the upper 32 bits of the timer prevents wrong + * results from the bottom 32 bits overflowing due to the timer ticking + * along. However, it does not prevent wrong results from simultaneous + * reads of the timer, which could reset the buffer mid-read. + * Since this kind of wrong read can happen only when the bottom bits + * overflow, there will be minutes between wrong reads, so if we read + * twice in succession, at least one of the reads will be correct. + */ + regmap_read(ost->map, TCU_REG_OST_CNTL, &val1); + regmap_read(ost->map, TCU_REG_OST_CNTHBUF, &val2); + count = (u64)val1 | (u64)val2 << 32; + + regmap_read(ost->map, TCU_REG_OST_CNTL, &val1); + regmap_read(ost->map, TCU_REG_OST_CNTHBUF, &val2); + recount = (u64)val1 | (u64)val2 << 32; + + /* + * A wrong read will produce a result that is 1<<32 too high: the bottom + * part from before overflow and the upper part from after overflow. + * Therefore, the lower value of the two reads is the correct value. + */ + diff = (s64)(recount - count); + if (unlikely(diff < 0)) + count = recount; + + return count; +} + +static u64 notrace ingenic_ost_clocksource_read32(struct clocksource *cs) +{ + struct ingenic_ost *ost = cs_to_ingenic_ost(cs); + unsigned int val; + + regmap_read(ost->map, TCU_REG_OST_CNTH, &val); + + return val; +} + +static int __init ingenic_ost_probe(struct platform_device *pdev) +{ + const struct ingenic_ost_soc_info *soc_info; + struct device *dev = &pdev->dev; + struct ingenic_ost *ost; + struct clocksource *cs; + unsigned long rate, flags; + int err; + + soc_info = device_get_match_data(dev); + if (!soc_info) + return -EINVAL; + + ost = devm_kzalloc(dev, sizeof(*ost), GFP_KERNEL); + if (!ost) + return -ENOMEM; + + ost->map = dev_get_regmap(dev->parent, NULL); + if (!ost->map) { + dev_err(dev, "regmap not found\n"); + return -EINVAL; + } + + ost->clk = devm_clk_get(dev, "ost"); + if (IS_ERR(ost->clk)) + return PTR_ERR(ost->clk); + + err = clk_prepare_enable(ost->clk); + if (err) + return err; + + /* Clear counter high/low registers */ + if (soc_info->is64bit) + regmap_write(ost->map, TCU_REG_OST_CNTL, 0); + regmap_write(ost->map, TCU_REG_OST_CNTH, 0); + + /* Don't reset counter at compare value. */ + regmap_update_bits(ost->map, TCU_REG_OST_TCSR, + TCU_OST_TCSR_MASK, TCU_OST_TCSR_CNT_MD); + + rate = clk_get_rate(ost->clk); + + /* Enable OST TCU channel */ + regmap_write(ost->map, TCU_REG_TESR, BIT(TCU_OST_CHANNEL)); + + cs = &ost->cs; + cs->name = "ingenic-ost"; + cs->rating = 320; + cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; + + if (soc_info->is64bit) { + cs->mask = CLOCKSOURCE_MASK(64); + cs->read = ingenic_ost_clocksource_read64; + } else { + cs->mask = CLOCKSOURCE_MASK(32); + cs->read = ingenic_ost_clocksource_read32; + } + + err = clocksource_register_hz(cs, rate); + if (err) { + dev_err(dev, "clocksource registration failed: %d\n", err); + clk_disable_unprepare(ost->clk); + return err; + } + + /* Cannot register a sched_clock with interrupts on */ + local_irq_save(flags); + if (soc_info->is64bit) + sched_clock_register(ingenic_ost_read_cntl, 32, rate); + else + sched_clock_register(ingenic_ost_read_cnth, 32, rate); + local_irq_restore(flags); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ingenic_ost_suspend(struct device *dev) +{ + struct ingenic_ost *ost = dev_get_drvdata(dev); + + clk_disable(ost->clk); + + return 0; +} + +static int ingenic_ost_resume(struct device *dev) +{ + struct ingenic_ost *ost = dev_get_drvdata(dev); + + return clk_enable(ost->clk); +} + +static SIMPLE_DEV_PM_OPS(ingenic_ost_pm_ops, ingenic_ost_suspend, + ingenic_ost_resume); +#define INGENIC_OST_PM_OPS (&ingenic_ost_pm_ops) +#else +#define INGENIC_OST_PM_OPS NULL +#endif /* CONFIG_PM_SUSPEND */ + +static const struct ingenic_ost_soc_info jz4725b_ost_soc_info = { + .is64bit = false, +}; + +static const struct ingenic_ost_soc_info jz4770_ost_soc_info = { + .is64bit = true, +}; + +static const struct of_device_id ingenic_ost_of_match[] = { + { .compatible = "ingenic,jz4725b-ost", .data = &jz4725b_ost_soc_info, }, + { .compatible = "ingenic,jz4770-ost", .data = &jz4770_ost_soc_info, }, + { } +}; + +static struct platform_driver ingenic_ost_driver = { + .driver = { + .name = "ingenic-ost", + .pm = INGENIC_OST_PM_OPS, + .of_match_table = ingenic_ost_of_match, + }, +}; +builtin_platform_driver_probe(ingenic_ost_driver, ingenic_ost_probe); From patchwork Wed Mar 27 23:16:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067537 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="UlWWWJtl"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3qK4k39z9sBV for ; Thu, 28 Mar 2019 10:19:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731515AbfC0XRN (ORCPT ); Wed, 27 Mar 2019 19:17:13 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58594 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRL (ORCPT ); Wed, 27 Mar 2019 19:17:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728628; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=82ez1uinMWY/ISDLZfsmAJcLgof/AbVr1evaas8n2mw=; b=UlWWWJtltSDN6HNQxDtoJWp1IfVHVcMM95uPi8vNZGlPEsp/43nn67nLdZucI7Om9JDPzM ewhQXaySI9AchPegYFWoIwkqAIiFcGB9NWa2zqxizUaZ8fG0KjAeUjQpiWFTkpszZfKDJ+ 5iYZ/Ubo9QsdC3fPHx5TV9/OrWbVf7U= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 06/27] MAINTAINERS: Add myself as maintainer for Ingenic TCU drivers Date: Thu, 28 Mar 2019 00:16:10 +0100 Message-Id: <20190327231631.15708-7-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add myself as maintainer for the ingenic-timer and ingenic-ost drivers. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3e5a5d263f29..da25d99d81aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7665,6 +7665,15 @@ L: linux-mtd@lists.infradead.org S: Maintained F: drivers/mtd/nand/raw/jz4780_* +INGENIC TCU driver +M: Paul Cercueil +S: Maintained +F: drivers/clocksource/ingenic-ost.c +F: drivers/clocksource/ingenic-timer.c +F: drivers/clocksource/ingenic-timer.h +F: include/linux/mfd/ingenic-tcu.h +F: include/dt-bindings/clock/ingenic,tcu.h + INOTIFY M: Jan Kara R: Amir Goldstein From patchwork Wed Mar 27 23:16:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067536 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="biyUtygW"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3qG5mRrz9sBV for ; Thu, 28 Mar 2019 10:19:22 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731634AbfC0XRO (ORCPT ); Wed, 27 Mar 2019 19:17:14 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58654 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731122AbfC0XRO (ORCPT ); Wed, 27 Mar 2019 19:17:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728631; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=1nobiONOw5T28uwag8BCDV7k1e7a1BrnY3DSy12emig=; b=biyUtygW9DPZLENN/uNYsybcF993JbxtutKYsa7oqPg3ReZmuIzXPwLGmou967rgA6/sTd kbpHmB29Vj8ARG8PLVWc9iLcGYkCORBxvt737AOQpZUFtf4VtpaG9jcZf6pRV2v9sJLVN6 6rOZREVqBFAosoMEqSJG1EegcNLdY8o= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 07/27] watchdog: jz4740: Use WDT clock provided by TCU driver Date: Thu, 28 Mar 2019 00:16:11 +0100 Message-Id: <20190327231631.15708-8-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Instead of requesting the "ext" clock and handling the watchdog clock divider and gating in the watchdog driver, we now request and use the "wdt" clock that is supplied by the ingenic-timer "TCU" driver. The major benefit is that the watchdog's clock rate and parent can now be specified from within devicetree, instead of hardcoded in the driver. Also, this driver won't poke anymore into the TCU registers to enable/disable the clock, as this is now handled by the TCU driver. On the bad side, we break the ABI with devicetree - as we now request a different clock. In this very specific case it is still okay, as every Ingenic JZ47xx-based board out there compile the devicetree within the kernel; so it's still time to push breaking changes, in order to get a clean devicetree that won't break once it musn't. Signed-off-by: Paul Cercueil Reviewed-by: Guenter Roeck Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/watchdog/Kconfig | 2 + drivers/watchdog/jz4740_wdt.c | 86 +++++++++++++++++-------------------------- 2 files changed, 36 insertions(+), 52 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 242eea859637..69b3b023c863 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1546,7 +1546,9 @@ config INDYDOG config JZ4740_WDT tristate "Ingenic jz4740 SoC hardware watchdog" depends on MACH_JZ4740 || MACH_JZ4780 + depends on COMMON_CLK select WATCHDOG_CORE + select INGENIC_TIMER help Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs. diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index ec4d99a830ba..1d504ecf45e1 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -26,25 +26,9 @@ #include #include -#include - #define JZ_REG_WDT_TIMER_DATA 0x0 #define JZ_REG_WDT_COUNTER_ENABLE 0x4 #define JZ_REG_WDT_TIMER_COUNTER 0x8 -#define JZ_REG_WDT_TIMER_CONTROL 0xC - -#define JZ_WDT_CLOCK_PCLK 0x1 -#define JZ_WDT_CLOCK_RTC 0x2 -#define JZ_WDT_CLOCK_EXT 0x4 - -#define JZ_WDT_CLOCK_DIV_SHIFT 3 - -#define JZ_WDT_CLOCK_DIV_1 (0 << JZ_WDT_CLOCK_DIV_SHIFT) -#define JZ_WDT_CLOCK_DIV_4 (1 << JZ_WDT_CLOCK_DIV_SHIFT) -#define JZ_WDT_CLOCK_DIV_16 (2 << JZ_WDT_CLOCK_DIV_SHIFT) -#define JZ_WDT_CLOCK_DIV_64 (3 << JZ_WDT_CLOCK_DIV_SHIFT) -#define JZ_WDT_CLOCK_DIV_256 (4 << JZ_WDT_CLOCK_DIV_SHIFT) -#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT) #define DEFAULT_HEARTBEAT 5 #define MAX_HEARTBEAT 2048 @@ -65,7 +49,8 @@ MODULE_PARM_DESC(heartbeat, struct jz4740_wdt_drvdata { struct watchdog_device wdt; void __iomem *base; - struct clk *rtc_clk; + struct clk *clk; + unsigned long clk_rate; }; static int jz4740_wdt_ping(struct watchdog_device *wdt_dev) @@ -80,31 +65,12 @@ static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev, unsigned int new_timeout) { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); - unsigned int rtc_clk_rate; - unsigned int timeout_value; - unsigned short clock_div = JZ_WDT_CLOCK_DIV_1; - - rtc_clk_rate = clk_get_rate(drvdata->rtc_clk); - - timeout_value = rtc_clk_rate * new_timeout; - while (timeout_value > 0xffff) { - if (clock_div == JZ_WDT_CLOCK_DIV_1024) { - /* Requested timeout too high; - * use highest possible value. */ - timeout_value = 0xffff; - break; - } - timeout_value >>= 2; - clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT); - } + u16 timeout_value = (u16)(drvdata->clk_rate * new_timeout); writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE); - writew(clock_div, drvdata->base + JZ_REG_WDT_TIMER_CONTROL); writew((u16)timeout_value, drvdata->base + JZ_REG_WDT_TIMER_DATA); writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER); - writew(clock_div | JZ_WDT_CLOCK_RTC, - drvdata->base + JZ_REG_WDT_TIMER_CONTROL); writeb(0x1, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE); @@ -114,7 +80,13 @@ static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev, static int jz4740_wdt_start(struct watchdog_device *wdt_dev) { - jz4740_timer_enable_watchdog(); + struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + int ret; + + ret = clk_prepare_enable(drvdata->clk); + if (ret) + return ret; + jz4740_wdt_set_timeout(wdt_dev, wdt_dev->timeout); return 0; @@ -125,7 +97,7 @@ static int jz4740_wdt_stop(struct watchdog_device *wdt_dev) struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE); - jz4740_timer_disable_watchdog(); + clk_disable_unprepare(drvdata->clk); return 0; } @@ -163,26 +135,42 @@ MODULE_DEVICE_TABLE(of, jz4740_wdt_of_matches); static int jz4740_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct jz4740_wdt_drvdata *drvdata; struct watchdog_device *jz4740_wdt; struct resource *res; + long rate; int ret; - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct jz4740_wdt_drvdata), - GFP_KERNEL); + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) - heartbeat = DEFAULT_HEARTBEAT; + drvdata->clk = devm_clk_get(&pdev->dev, "wdt"); + if (IS_ERR(drvdata->clk)) { + dev_err(&pdev->dev, "cannot find WDT clock\n"); + return PTR_ERR(drvdata->clk); + } + + /* Set smallest clock possible */ + rate = clk_round_rate(drvdata->clk, 1); + if (rate < 0) + return rate; + ret = clk_set_rate(drvdata->clk, rate); + if (ret) + return ret; + + drvdata->clk_rate = rate; jz4740_wdt = &drvdata->wdt; jz4740_wdt->info = &jz4740_wdt_info; jz4740_wdt->ops = &jz4740_wdt_ops; - jz4740_wdt->timeout = heartbeat; jz4740_wdt->min_timeout = 1; - jz4740_wdt->max_timeout = MAX_HEARTBEAT; - jz4740_wdt->parent = &pdev->dev; + jz4740_wdt->max_timeout = 0xffff / rate; + jz4740_wdt->timeout = clamp(heartbeat, + jz4740_wdt->min_timeout, + jz4740_wdt->max_timeout); + jz4740_wdt->parent = dev; watchdog_set_nowayout(jz4740_wdt, nowayout); watchdog_set_drvdata(jz4740_wdt, drvdata); @@ -191,12 +179,6 @@ static int jz4740_wdt_probe(struct platform_device *pdev) if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); - drvdata->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); - if (IS_ERR(drvdata->rtc_clk)) { - dev_err(&pdev->dev, "cannot find RTC clock\n"); - return PTR_ERR(drvdata->rtc_clk); - } - ret = devm_watchdog_register_device(&pdev->dev, &drvdata->wdt); if (ret < 0) return ret; From patchwork Wed Mar 27 23:16:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067535 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="eyB1tjix"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3qD0mvYz9sR0 for ; Thu, 28 Mar 2019 10:19:20 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731773AbfC0XRR (ORCPT ); Wed, 27 Mar 2019 19:17:17 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58708 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRQ (ORCPT ); Wed, 27 Mar 2019 19:17:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728633; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=OwUsbI8IxO1V1yE1w8GK6J9zL51AaRpn3nDzojyNNEo=; b=eyB1tjixTkrvz1EOlNWuXL16/CZWzLcoSraTjC+p7C41udlb/wDT5hv+fS7xWqDHgefoSK 7hVMiGXNDE+U9w9EA6DXsY2BEkZaU9oZb/Nuwkjuv1xYplwc528I1LW+NUKVCktRFjONeI u8pQUhj1EasxhRKU5j6u5DHl7bl1EuY= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 08/27] watchdog: jz4740: Use regmap provided by TCU driver Date: Thu, 28 Mar 2019 00:16:12 +0100 Message-Id: <20190327231631.15708-9-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Since we broke the ABI by changing the clock, the driver was also updated to use the regmap provided by the TCU driver. Signed-off-by: Paul Cercueil Reviewed-by: Guenter Roeck Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/watchdog/jz4740_wdt.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index 1d504ecf45e1..0f54306aee25 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -13,6 +13,7 @@ * */ +#include #include #include #include @@ -25,10 +26,7 @@ #include #include #include - -#define JZ_REG_WDT_TIMER_DATA 0x0 -#define JZ_REG_WDT_COUNTER_ENABLE 0x4 -#define JZ_REG_WDT_TIMER_COUNTER 0x8 +#include #define DEFAULT_HEARTBEAT 5 #define MAX_HEARTBEAT 2048 @@ -48,7 +46,7 @@ MODULE_PARM_DESC(heartbeat, struct jz4740_wdt_drvdata { struct watchdog_device wdt; - void __iomem *base; + struct regmap *map; struct clk *clk; unsigned long clk_rate; }; @@ -57,7 +55,7 @@ static int jz4740_wdt_ping(struct watchdog_device *wdt_dev) { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); - writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER); + regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0); return 0; } @@ -67,12 +65,12 @@ static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev, struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); u16 timeout_value = (u16)(drvdata->clk_rate * new_timeout); - writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0); - writew((u16)timeout_value, drvdata->base + JZ_REG_WDT_TIMER_DATA); - writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER); + regmap_write(drvdata->map, TCU_REG_WDT_TDR, timeout_value); + regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0); - writeb(0x1, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN); wdt_dev->timeout = new_timeout; return 0; @@ -96,7 +94,7 @@ static int jz4740_wdt_stop(struct watchdog_device *wdt_dev) { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); - writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0); clk_disable_unprepare(drvdata->clk); return 0; @@ -138,7 +136,6 @@ static int jz4740_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct jz4740_wdt_drvdata *drvdata; struct watchdog_device *jz4740_wdt; - struct resource *res; long rate; int ret; @@ -174,10 +171,11 @@ static int jz4740_wdt_probe(struct platform_device *pdev) watchdog_set_nowayout(jz4740_wdt, nowayout); watchdog_set_drvdata(jz4740_wdt, drvdata); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(drvdata->base)) - return PTR_ERR(drvdata->base); + drvdata->map = dev_get_regmap(dev->parent, NULL); + if (!drvdata->map) { + dev_err(dev, "regmap not found\n"); + return -EINVAL; + } ret = devm_watchdog_register_device(&pdev->dev, &drvdata->wdt); if (ret < 0) From patchwork Wed Mar 27 23:16:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067515 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="vicXpbPf"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3n367Bdz9sR5 for ; Thu, 28 Mar 2019 10:17:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731895AbfC0XRW (ORCPT ); Wed, 27 Mar 2019 19:17:22 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58748 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRV (ORCPT ); Wed, 27 Mar 2019 19:17:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728639; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=XhLng3suBiZ2PLO2z7A3l2ORblQjHoPUvLQwQ2gl/jQ=; b=vicXpbPf/s28/UN+Zcm+YTOCCW8+Kax7WXUIp/ZsUbld8yqYyYc00xpoQOObDbiFrd9pn9 DCCUki9JQ+AYZA9kGpPutAn6+T1wvO1pDAmcVDWEWXwHfEyLH+1KV0JXqxTqKWeuxfDS0+ P69m77bVF5nlLdS0jrJe4WMeSmtrcBI= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 09/27] watchdog: jz4740: Avoid starting watchdog in set_timeout Date: Thu, 28 Mar 2019 00:16:13 +0100 Message-Id: <20190327231631.15708-10-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Previously the jz4740_wdt_set_timeout() function was starting the timer unconditionally, even if it was stopped when that function was entered. Now, the timer will be restarted only if it was already running before this function is called. Signed-off-by: Paul Cercueil Reviewed-by: Guenter Roeck Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/watchdog/jz4740_wdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index 0f54306aee25..45d9495170e5 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -64,13 +64,15 @@ static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev, { struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); u16 timeout_value = (u16)(drvdata->clk_rate * new_timeout); + u32 tcer; + regmap_read(drvdata->map, TCU_REG_WDT_TCER, &tcer); regmap_write(drvdata->map, TCU_REG_WDT_TCER, 0); regmap_write(drvdata->map, TCU_REG_WDT_TDR, timeout_value); regmap_write(drvdata->map, TCU_REG_WDT_TCNT, 0); - regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, tcer & TCU_WDT_TCER_TCEN); wdt_dev->timeout = new_timeout; return 0; @@ -86,6 +88,7 @@ static int jz4740_wdt_start(struct watchdog_device *wdt_dev) return ret; jz4740_wdt_set_timeout(wdt_dev, wdt_dev->timeout); + regmap_write(drvdata->map, TCU_REG_WDT_TCER, TCU_WDT_TCER_TCEN); return 0; } From patchwork Wed Mar 27 23:16:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067534 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="oH/A85oM"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3qB3fCjz9sBV for ; Thu, 28 Mar 2019 10:19:18 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732029AbfC0XR1 (ORCPT ); Wed, 27 Mar 2019 19:17:27 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58808 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRZ (ORCPT ); Wed, 27 Mar 2019 19:17:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728642; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=Tdp1HR7Wya6O2Qut1e0WFaLfWwxMFTgq95PeML6V/kc=; b=oH/A85oMFJmY3J6UjX2oZfyL5W6+8Eda9plCmr9rLKgYMqFVd8CHVeODmu8ix4cka3kpme JYOlXQc8JaHcaCkXL5RMFWp+vYFyfRvYmonWvgJPQDOAR6t6ckgLSWZhfhlikOVGadFWFC HToXaJzUDN6S+xyhAOTP2Fi87YcmWps= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 10/27] watchdog: jz4740: Drop dependency on MACH_JZ47xx, use COMPILE_TEST Date: Thu, 28 Mar 2019 00:16:14 +0100 Message-Id: <20190327231631.15708-11-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Depending on MACH_JZ47xx prevent us from creating a generic kernel that works on more than one MIPS board. Instead, we just depend on MIPS being set. On other architectures, this driver can still be built, thanks to COMPILE_TEST. This is used by automated tools to find bugs, for instance. Signed-off-by: Paul Cercueil Reviewed-by: Guenter Roeck Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 69b3b023c863..f7df17df2f30 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1545,7 +1545,7 @@ config INDYDOG config JZ4740_WDT tristate "Ingenic jz4740 SoC hardware watchdog" - depends on MACH_JZ4740 || MACH_JZ4780 + depends on MIPS || COMPILE_TEST depends on COMMON_CLK select WATCHDOG_CORE select INGENIC_TIMER From patchwork Wed Mar 27 23:16:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067533 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="a3t0Cuqr"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3q93622z9sBV for ; Thu, 28 Mar 2019 10:19:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732159AbfC0XRa (ORCPT ); Wed, 27 Mar 2019 19:17:30 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58870 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728062AbfC0XR3 (ORCPT ); Wed, 27 Mar 2019 19:17:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728645; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=Ni8LFzXj/UyOabVnj06Nu3HY1xjYOi1WduyzJX/jpgw=; b=a3t0Cuqrl3PJZbIf9NcS1U6Hrb11SmhI6CBvs8Wg8+01HWh+01svlhhuxY5ZNYqB+TcsGq phOYlRNAbQ6fSAzjZMZx+bZBY4jz21761ZdPPOH6Tw6AFRKgNBVX3hCANOUPPB/Z4LlVd8 GjGyxg9tj7Jqd4sOL9nhD2ZoYyjVLtY= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 11/27] pwm: jz4740: Apply configuration atomically Date: Thu, 28 Mar 2019 00:16:15 +0100 Message-Id: <20190327231631.15708-12-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org This is cleaner, more future-proof, and incidentally it also fixes the PWM resetting its config when stopped/started several times. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek Acked-by: Thierry Reding --- drivers/pwm/pwm-jz4740.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index a7b134af5e04..b2f910413f81 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -83,17 +83,16 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) jz4740_timer_disable(pwm->hwpwm); } -static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) +static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) { struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip); unsigned long long tmp; unsigned long period, duty; unsigned int prescaler = 0; uint16_t ctrl; - bool is_enabled; - tmp = (unsigned long long)clk_get_rate(jz4740->clk) * period_ns; + tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period; do_div(tmp, 1000000000); period = tmp; @@ -105,16 +104,14 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (prescaler == 6) return -EINVAL; - tmp = (unsigned long long)period * duty_ns; - do_div(tmp, period_ns); + tmp = (unsigned long long)period * state->duty_cycle; + do_div(tmp, state->period); duty = period - tmp; if (duty >= period) duty = period - 1; - is_enabled = jz4740_timer_is_enabled(pwm->hwpwm); - if (is_enabled) - jz4740_pwm_disable(chip, pwm); + jz4740_pwm_disable(chip, pwm); jz4740_timer_set_count(pwm->hwpwm, 0); jz4740_timer_set_duty(pwm->hwpwm, duty); @@ -125,18 +122,7 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); - if (is_enabled) - jz4740_pwm_enable(chip, pwm); - - return 0; -} - -static int jz4740_pwm_set_polarity(struct pwm_chip *chip, - struct pwm_device *pwm, enum pwm_polarity polarity) -{ - uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm); - - switch (polarity) { + switch (state->polarity) { case PWM_POLARITY_NORMAL: ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW; break; @@ -146,16 +132,17 @@ static int jz4740_pwm_set_polarity(struct pwm_chip *chip, } jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); + + if (state->enabled) + jz4740_pwm_enable(chip, pwm); + return 0; } static const struct pwm_ops jz4740_pwm_ops = { .request = jz4740_pwm_request, .free = jz4740_pwm_free, - .config = jz4740_pwm_config, - .set_polarity = jz4740_pwm_set_polarity, - .enable = jz4740_pwm_enable, - .disable = jz4740_pwm_disable, + .apply = jz4740_pwm_apply, .owner = THIS_MODULE, }; From patchwork Wed Mar 27 23:16:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067516 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="TiV1J3Tg"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3nC3sGNz9sR3 for ; Thu, 28 Mar 2019 10:17:35 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732248AbfC0XRe (ORCPT ); Wed, 27 Mar 2019 19:17:34 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58926 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRc (ORCPT ); Wed, 27 Mar 2019 19:17:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728649; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=el5zc9kKHl8yaJaBUzXwPG3gnMwu3m5CekGe8tBw7AQ=; b=TiV1J3TgUfNZV0Yb8/EMrLwshPAnn8QfkbtZDlR4rKOFvBdAVeQd8NbvMTGTurv3BHCtL2 cqNIUY2hM1LmVn6Pgjb1ZOwo7kpGVx+jD9TaKNEO0IzVdT1iKjblMsak17ruEnA2nJ5OtB aRg6fPkICxE8DrBNQgNOs6Ghxh4ZlkQ= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 12/27] pwm: jz4740: Use regmap from TCU driver Date: Thu, 28 Mar 2019 00:16:16 +0100 Message-Id: <20190327231631.15708-13-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The ingenic-timer "TCU" driver provides us with a regmap, that we can use to safely access the TCU registers. While this driver is devicetree-compatible, it is never (as of now) probed from devicetree, so this change does not introduce a ABI problem with current devicetree files. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/pwm/Kconfig | 1 + drivers/pwm/pwm-jz4740.c | 79 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 54f8238aac0d..a4abb7417d63 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -213,6 +213,7 @@ config PWM_IMX27 config PWM_JZ4740 tristate "Ingenic JZ47xx PWM support" depends on MACH_INGENIC + select REGMAP help Generic PWM framework driver for Ingenic JZ47xx based machines. diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index b2f910413f81..144e2a54aa59 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -17,18 +17,19 @@ #include #include #include +#include #include #include #include #include - -#include +#include #define NUM_PWM 8 struct jz4740_pwm_chip { struct pwm_chip chip; struct clk *clk; + struct regmap *map; }; static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip) @@ -38,6 +39,8 @@ static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip) static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { + struct jz4740_pwm_chip *jz = to_jz4740(chip); + /* * Timers 0 and 1 are used for system tasks, so they are unavailable * for use as PWMs. @@ -45,42 +48,44 @@ static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) if (pwm->hwpwm < 2) return -EBUSY; - jz4740_timer_start(pwm->hwpwm); + regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm)); return 0; } static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - jz4740_timer_set_ctrl(pwm->hwpwm, 0); + struct jz4740_pwm_chip *jz = to_jz4740(chip); - jz4740_timer_stop(pwm->hwpwm); + regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm)); } static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { - uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm); + struct jz4740_pwm_chip *jz = to_jz4740(chip); - ctrl |= JZ_TIMER_CTRL_PWM_ENABLE; - jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); - jz4740_timer_enable(pwm->hwpwm); + /* Enable PWM output */ + regmap_update_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm), + TCU_TCSR_PWM_EN, TCU_TCSR_PWM_EN); + /* Start counter */ + regmap_write(jz->map, TCU_REG_TESR, BIT(pwm->hwpwm)); return 0; } static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { - uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm); + struct jz4740_pwm_chip *jz = to_jz4740(chip); /* Disable PWM output. * In TCU2 mode (channel 1/2 on JZ4750+), this must be done before the * counter is stopped, while in TCU1 mode the order does not matter. */ - ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE; - jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); + regmap_update_bits(jz->map, TCU_REG_TCSRc(pwm->hwpwm), + TCU_TCSR_PWM_EN, 0); /* Stop counter */ - jz4740_timer_disable(pwm->hwpwm); + regmap_write(jz->map, TCU_REG_TECR, BIT(pwm->hwpwm)); } static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, @@ -90,7 +95,6 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long long tmp; unsigned long period, duty; unsigned int prescaler = 0; - uint16_t ctrl; tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period; do_div(tmp, 1000000000); @@ -113,26 +117,42 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, jz4740_pwm_disable(chip, pwm); - jz4740_timer_set_count(pwm->hwpwm, 0); - jz4740_timer_set_duty(pwm->hwpwm, duty); - jz4740_timer_set_period(pwm->hwpwm, period); + /* + * Set abrupt shutdown. + * + * TODO: test the hardware with this bit disabled, as shutting down + * abruptly is not desired. + */ + regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), + TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD); + + /* Set clock prescale */ + regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), + TCU_TCSR_PRESCALE_MASK, + prescaler << TCU_TCSR_PRESCALE_LSB); - ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT | - JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN; + /* Reset counter to 0 */ + regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0); - jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); + /* Set duty */ + regmap_write(jz4740->map, TCU_REG_TDHRc(pwm->hwpwm), duty); + /* Set period */ + regmap_write(jz4740->map, TCU_REG_TDFRc(pwm->hwpwm), period); + + /* Set polarity */ switch (state->polarity) { case PWM_POLARITY_NORMAL: - ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW; + regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), + TCU_TCSR_PWM_INITL_HIGH, 0); break; case PWM_POLARITY_INVERSED: - ctrl |= JZ_TIMER_CTRL_PWM_ACTIVE_LOW; + regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), + TCU_TCSR_PWM_INITL_HIGH, + TCU_TCSR_PWM_INITL_HIGH); break; } - jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); - if (state->enabled) jz4740_pwm_enable(chip, pwm); @@ -149,8 +169,9 @@ static const struct pwm_ops jz4740_pwm_ops = { static int jz4740_pwm_probe(struct platform_device *pdev) { struct jz4740_pwm_chip *jz4740; + struct device *dev = &pdev->dev; - jz4740 = devm_kzalloc(&pdev->dev, sizeof(*jz4740), GFP_KERNEL); + jz4740 = devm_kzalloc(dev, sizeof(*jz4740), GFP_KERNEL); if (!jz4740) return -ENOMEM; @@ -158,7 +179,13 @@ static int jz4740_pwm_probe(struct platform_device *pdev) if (IS_ERR(jz4740->clk)) return PTR_ERR(jz4740->clk); - jz4740->chip.dev = &pdev->dev; + jz4740->map = dev_get_regmap(dev->parent, NULL); + if (!jz4740->map) { + dev_err(dev, "regmap not found\n"); + return -EINVAL; + } + + jz4740->chip.dev = dev; jz4740->chip.ops = &jz4740_pwm_ops; jz4740->chip.npwm = NUM_PWM; jz4740->chip.base = -1; From patchwork Wed Mar 27 23:16:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067517 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="OQemeoP+"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3nG4Q62z9sBV for ; Thu, 28 Mar 2019 10:17:38 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732351AbfC0XRh (ORCPT ); Wed, 27 Mar 2019 19:17:37 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:58960 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728062AbfC0XRf (ORCPT ); Wed, 27 Mar 2019 19:17:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728652; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=84XFp/3OTyDVdnxK+E/XC2OidipIlzVjFnqGlQ1f+1s=; b=OQemeoP+zarqba0kFt9NXGYJdmPAisixK2noP1tWFoxtcEAdcGLw37IAAvxq2PeHsus8kg Hg2LcvyS8C9MWnCBVVwvrhidarGsDxc3/Vwz+QbwoUnGK/IXWQpzfES6I7SSFnLP1wpLPo 2wnESFCKlY5wWg9fFqzGVC1HIpZgbSg= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 13/27] pwm: jz4740: Use clocks from TCU driver Date: Thu, 28 Mar 2019 00:16:17 +0100 Message-Id: <20190327231631.15708-14-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The ingenic-timer "TCU" driver provides us with clocks, that can be (un)gated, reparented or reclocked from devicetree, instead of having these settings hardcoded in this driver. While this driver is devicetree-compatible, it is never (as of now) probed from devicetree, so this change does not introduce a ABI problem with current devicetree files. Note that the "select REGMAP" has been dropped because it's already enabled by the "select INGENIC_TIMER". Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/pwm/Kconfig | 3 ++- drivers/pwm/pwm-jz4740.c | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index a4abb7417d63..a1aba52793ee 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -213,7 +213,8 @@ config PWM_IMX27 config PWM_JZ4740 tristate "Ingenic JZ47xx PWM support" depends on MACH_INGENIC - select REGMAP + depends on COMMON_CLK + select INGENIC_TIMER help Generic PWM framework driver for Ingenic JZ47xx based machines. diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 144e2a54aa59..1a0eab0abafe 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -28,7 +28,6 @@ struct jz4740_pwm_chip { struct pwm_chip chip; - struct clk *clk; struct regmap *map; }; @@ -39,7 +38,9 @@ static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip) static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { - struct jz4740_pwm_chip *jz = to_jz4740(chip); + struct clk *clk; + char clk_name[16]; + int ret; /* * Timers 0 and 1 are used for system tasks, so they are unavailable @@ -48,16 +49,29 @@ static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) if (pwm->hwpwm < 2) return -EBUSY; - regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm)); + snprintf(clk_name, sizeof(clk_name), "timer%u", pwm->hwpwm); + + clk = clk_get(chip->dev, clk_name); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + ret = clk_prepare_enable(clk); + if (ret) { + clk_put(clk); + return ret; + } + + pwm_set_chip_data(pwm, clk); return 0; } static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct jz4740_pwm_chip *jz = to_jz4740(chip); + struct clk *clk = pwm_get_chip_data(pwm); - regmap_write(jz->map, TCU_REG_TSCR, BIT(pwm->hwpwm)); + clk_disable_unprepare(clk); + clk_put(clk); } static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) @@ -92,16 +106,20 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip); + struct clk *clk = pwm_get_chip_data(pwm), + *parent_clk = clk_get_parent(clk); + unsigned long rate, period, duty; unsigned long long tmp; - unsigned long period, duty; unsigned int prescaler = 0; - tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period; + rate = clk_get_rate(parent_clk); + tmp = (unsigned long long)rate * state->period; do_div(tmp, 1000000000); period = tmp; while (period > 0xffff && prescaler < 6) { period >>= 2; + rate >>= 2; ++prescaler; } @@ -126,10 +144,7 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD); - /* Set clock prescale */ - regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), - TCU_TCSR_PRESCALE_MASK, - prescaler << TCU_TCSR_PRESCALE_LSB); + clk_set_rate(clk, rate); /* Reset counter to 0 */ regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0); @@ -175,10 +190,6 @@ static int jz4740_pwm_probe(struct platform_device *pdev) if (!jz4740) return -ENOMEM; - jz4740->clk = devm_clk_get(&pdev->dev, "ext"); - if (IS_ERR(jz4740->clk)) - return PTR_ERR(jz4740->clk); - jz4740->map = dev_get_regmap(dev->parent, NULL); if (!jz4740->map) { dev_err(dev, "regmap not found\n"); From patchwork Wed Mar 27 23:16:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067532 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="fBCn0n2k"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3py68Bdz9sR4 for ; Thu, 28 Mar 2019 10:19:06 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732518AbfC0XRl (ORCPT ); Wed, 27 Mar 2019 19:17:41 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59018 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726102AbfC0XRi (ORCPT ); Wed, 27 Mar 2019 19:17:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728654; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=GkICgK8vBLcuX0i49vbljswblHjkddWYl4PLQNv7YN4=; b=fBCn0n2kr2zKU+fYHSy5pOAEVW5H1+Z8POU4Iedav/d33XjWF7EkWJ0I6Ww3f04a/Lt15L 5l/GlIMhZkk9Dlez0weEgBb1s8dqcuMFZNUYT5WfMovwHML1KFwBy9L0zRqab9x0t3tAIj XNVfmx1UlnLdJtqmsmuryOdvkKUn9BA= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 14/27] pwm: jz4740: Improve algorithm of clock calculation Date: Thu, 28 Mar 2019 00:16:18 +0100 Message-Id: <20190327231631.15708-15-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The previous algorithm hardcoded details about how the TCU clocks work. The new algorithm will compute the maximum frequency at which the clock can run for the given period/duty parameters, and use clk_set_max_rate() to ensure that we will always compute period/duty values that fit in our 16-bit register fields. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/pwm/pwm-jz4740.c | 51 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 1a0eab0abafe..b55ee879e23d 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -108,24 +108,47 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip); struct clk *clk = pwm_get_chip_data(pwm), *parent_clk = clk_get_parent(clk); - unsigned long rate, period, duty; + unsigned long rate, parent_rate, period, duty; unsigned long long tmp; - unsigned int prescaler = 0; + int ret; - rate = clk_get_rate(parent_clk); - tmp = (unsigned long long)rate * state->period; - do_div(tmp, 1000000000); - period = tmp; + parent_rate = clk_get_rate(parent_clk); + + jz4740_pwm_disable(chip, pwm); + + /* Reset the clock to the maximum rate, and we'll reduce it if needed */ + ret = clk_set_rate(clk, parent_rate); + if (ret) + return ret; - while (period > 0xffff && prescaler < 6) { - period >>= 2; - rate >>= 2; - ++prescaler; + /* + * Limit the clock to a maximum rate that still gives us a period value + * which fits in 16 bits. + */ + tmp = 0xffffull * NSEC_PER_SEC; + do_div(tmp, state->period); + + ret = clk_set_max_rate(clk, tmp); + if (ret) { + dev_err(chip->dev, "Unable to set max rate: %i\n", ret); + return ret; } - if (prescaler == 6) - return -EINVAL; + /* + * Read back the clock rate, as it may have been modified by + * clk_set_max_rate() + */ + rate = clk_get_rate(clk); + + if (rate != parent_rate) + dev_dbg(chip->dev, "PWM clock updated to %lu Hz\n", rate); + /* Calculate period value */ + tmp = (unsigned long long)rate * state->period; + do_div(tmp, NSEC_PER_SEC); + period = (unsigned long)tmp; + + /* Calculate duty value */ tmp = (unsigned long long)period * state->duty_cycle; do_div(tmp, state->period); duty = period - tmp; @@ -133,8 +156,6 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (duty >= period) duty = period - 1; - jz4740_pwm_disable(chip, pwm); - /* * Set abrupt shutdown. * @@ -144,8 +165,6 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD); - clk_set_rate(clk, rate); - /* Reset counter to 0 */ regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0); From patchwork Wed Mar 27 23:16:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067518 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="Gqoh3Ei7"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3nL2yQqz9sR0 for ; Thu, 28 Mar 2019 10:17:42 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732534AbfC0XRl (ORCPT ); Wed, 27 Mar 2019 19:17:41 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59062 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732379AbfC0XRj (ORCPT ); Wed, 27 Mar 2019 19:17:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728657; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=Vfr89DEuixHt/Ld1cIBzy7ff8DhBwMoI2s6wXld3jbA=; b=Gqoh3Ei750tF1iMZ/7XovFZZ27Dfq2vbkPgmTacQO5D95aB6Fu8XcQqn4o1vqVko84Sokq FHhvNT60SUjNALPzjL+9qBjoWWn7Xj+ow5uxcis9Gb/h8B/cnUtz8qwl3gaiAh0QJRx1yy NzGC/KErRdA3GrSAYSO56YoI23qXDU0= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 15/27] pwm: jz4740: Allow selection of PWM channels 0 and 1 Date: Thu, 28 Mar 2019 00:16:19 +0100 Message-Id: <20190327231631.15708-16-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The TCU channels 0 and 1 were previously reserved for system tasks, and thus unavailable for PWM. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/pwm/pwm-jz4740.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index b55ee879e23d..c874a387c1d9 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -42,11 +42,7 @@ static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) char clk_name[16]; int ret; - /* - * Timers 0 and 1 are used for system tasks, so they are unavailable - * for use as PWMs. - */ - if (pwm->hwpwm < 2) + if (!ingenic_tcu_pwm_can_use_chn(chip->dev, pwm->hwpwm)) return -EBUSY; snprintf(clk_name, sizeof(clk_name), "timer%u", pwm->hwpwm); From patchwork Wed Mar 27 23:16:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067531 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="Rc+YFeB5"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pq0MKbz9sBV for ; Thu, 28 Mar 2019 10:18:59 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729235AbfC0XS6 (ORCPT ); Wed, 27 Mar 2019 19:18:58 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59118 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728062AbfC0XRm (ORCPT ); Wed, 27 Mar 2019 19:17:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728659; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=i7nXZc2dagRgFRfMyZHWXJxqtg8BMbqF+6N1Dzaibgs=; b=Rc+YFeB50ozbmFA6ZyQpQTqO63FcyjAH/wYcdEnZ1VYSTUtvwspSSDJSKlgt6iUPwQHHyP 0iH7rKy6haua6j+8GVXHnYbvnh5glYLZb30tQLSTM4AtYC7NU8l/fhDrrKzzWC/xFp3yob +nWXHHrj7yg5z7V9ENQdEaGPT0SaVFk= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 16/27] pwm: jz4740: Drop dependency on MACH_INGENIC, use COMPILE_TEST Date: Thu, 28 Mar 2019 00:16:20 +0100 Message-Id: <20190327231631.15708-17-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Depending on MACH_INGENIC prevent us from creating a generic kernel that works on more than one MIPS board. Instead, we just depend on MIPS being set. On other architectures, this driver can still be built, thanks to COMPILE_TEST. This is used by automated tools to find bugs, for instance. Signed-off-by: Paul Cercueil Acked-by: Thierry Reding Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/pwm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index a1aba52793ee..e73e744a7a71 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -212,7 +212,7 @@ config PWM_IMX27 config PWM_JZ4740 tristate "Ingenic JZ47xx PWM support" - depends on MACH_INGENIC + depends on MIPS || COMPILE_TEST depends on COMMON_CLK select INGENIC_TIMER help From patchwork Wed Mar 27 23:16:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067519 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="jgoZsvoc"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3nX0bcsz9sR0 for ; Thu, 28 Mar 2019 10:17:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732663AbfC0XRq (ORCPT ); Wed, 27 Mar 2019 19:17:46 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59176 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732572AbfC0XRo (ORCPT ); Wed, 27 Mar 2019 19:17:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728661; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=LaBZgQfRycafkqZkxA0KQOxGTobHePRrAgEM3XkEjFQ=; b=jgoZsvocN306f74/spp3hXET5Vp2umbTJKJaHkj2+YNuDEsJrLS5dXWKdGi/eT7ciF8ip3 wQQ/JhAzpQ98zPdv6tXwqu7TaheVyvUJz1KGDUYeziiW/MbZiFUrtRbr3v2rNhallNg2vT AmRgxCzdj9uOUQYEP+diU6AhTRB95io= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 17/27] pwm: jz4740: Remove unused devicetree compatible strings Date: Thu, 28 Mar 2019 00:16:21 +0100 Message-Id: <20190327231631.15708-18-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Right now none of the Ingenic-based boards probe this driver from devicetree. This driver defined three compatible strings for the exact same behaviour. Before these strings are used, we can remove two of them. Signed-off-by: Paul Cercueil Acked-by: Thierry Reding Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/pwm/pwm-jz4740.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index c874a387c1d9..47d891bd22c7 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -233,8 +233,6 @@ static int jz4740_pwm_remove(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id jz4740_pwm_dt_ids[] = { { .compatible = "ingenic,jz4740-pwm", }, - { .compatible = "ingenic,jz4770-pwm", }, - { .compatible = "ingenic,jz4780-pwm", }, {}, }; MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids); From patchwork Wed Mar 27 23:16:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067530 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="lPDcbnnW"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pl6zyjz9sR3 for ; Thu, 28 Mar 2019 10:18:55 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732819AbfC0XRw (ORCPT ); Wed, 27 Mar 2019 19:17:52 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59222 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732628AbfC0XRq (ORCPT ); Wed, 27 Mar 2019 19:17:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728664; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=Xjf4DrrtmSZT3xvRmQjVzrD+mdW5u5tnY/n+24Z5NZk=; b=lPDcbnnW5sOTHZbgIiELh/TmzQdiOUgyihxHOkJn1WVGaZDCUii4U2ufFGob/POt4k2Qu1 IYBm4Yo/MoonSw6/DIRbGdub1fngJpiMdJt13QbUeM5l6S33/vOJAEEqMsm5inmu+KTlKa SDEgJb78dIg7c2TtveFWCLG3elzeDUU= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 18/27] clk: jz4740: Add TCU clock Date: Thu, 28 Mar 2019 00:16:22 +0100 Message-Id: <20190327231631.15708-19-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add the missing TCU clock to the list of clocks supplied by the CGU for the JZ4740 SoC. Signed-off-by: Paul Cercueil Acked-by: Stephen Boyd Acked-by: Rob Herring Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- drivers/clk/ingenic/jz4740-cgu.c | 6 ++++++ include/dt-bindings/clock/jz4740-cgu.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c index b86edd328249..5d0d5be1e6a7 100644 --- a/drivers/clk/ingenic/jz4740-cgu.c +++ b/drivers/clk/ingenic/jz4740-cgu.c @@ -211,6 +211,12 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, .gate = { CGU_REG_CLKGR, 5 }, }, + + [JZ4740_CLK_TCU] = { + "tcu", CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 1 }, + }, }; static void __init jz4740_cgu_init(struct device_node *np) diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h index 6ed83f926ae7..e82d77028581 100644 --- a/include/dt-bindings/clock/jz4740-cgu.h +++ b/include/dt-bindings/clock/jz4740-cgu.h @@ -34,5 +34,6 @@ #define JZ4740_CLK_ADC 19 #define JZ4740_CLK_I2C 20 #define JZ4740_CLK_AIC 21 +#define JZ4740_CLK_TCU 22 #endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */ From patchwork Wed Mar 27 23:16:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067528 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="YXcP/R4G"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pk1h22z9sR0 for ; Thu, 28 Mar 2019 10:18:54 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732833AbfC0XRw (ORCPT ); Wed, 27 Mar 2019 19:17:52 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59276 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732572AbfC0XRv (ORCPT ); Wed, 27 Mar 2019 19:17:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728668; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=NjQ2F08kMImKzahKxPvopZlS77+2wWI9m9V/KZlaiA0=; b=YXcP/R4GPbq8hsKtPtul+l1iPGHFyzdOQgOZzDZThZtuIlXjq0H0XkkA5Tnhn6mhSgNbDf MwJo/8BtxoL4BJN2N0kvWAQZOy+SCVhf8ZNcLuCBQ2Szet5JB0yj0QypSRRwV65vhq2sqe DJWgRXs5erMmL/tpBjZs1NB9CzRKr4Q= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 19/27] MIPS: Kconfig: Select TCU timer driver when MACH_INGENIC is set Date: Thu, 28 Mar 2019 00:16:23 +0100 Message-Id: <20190327231631.15708-20-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org We cannot boot to userspace (not even initramfs) if the timer driver is not present; so it makes sense to enable it unconditionally when MACH_INGENIC is set. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4a5f5b0ee9a9..eca480d43d93 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -393,6 +393,7 @@ config MACH_INGENIC select BUILTIN_DTB if MIPS_NO_APPENDED_DTB select USE_OF select LIBFDT + select INGENIC_TIMER config LANTIQ bool "Lantiq based platforms" From patchwork Wed Mar 27 23:16:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067527 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="J5d6HYmQ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pc08LZz9sBV for ; Thu, 28 Mar 2019 10:18:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732969AbfC0XRz (ORCPT ); Wed, 27 Mar 2019 19:17:55 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59332 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732789AbfC0XRy (ORCPT ); Wed, 27 Mar 2019 19:17:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728671; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=KFKwUEoDAk7gdYsZVkBRSVJxZAHwqP1sIhxgE7LIeak=; b=J5d6HYmQVuee6h579KsQj5Jk95nQBIt5Cszu0xSxiFwwptPLtBADU+oqn5PO9lweDIOMcA VuOfr3lZEeUSmcrLfNWXm5tsNOdE8yPGAEI3GNHGSb5jzd0aWpuPup2XKuhjAJWV756TL1 h4vRioRkNq53AvHlKlpvJkBuiEuvIJQ= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 20/27] MIPS: jz4740: Add DTS nodes for the TCU drivers Date: Thu, 28 Mar 2019 00:16:24 +0100 Message-Id: <20190327231631.15708-21-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Add DTS nodes for the JZ4780, JZ4770 and JZ4740 devicetree files. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/boot/dts/ingenic/jz4740.dtsi | 51 +++++++++++++++++++++++--- arch/mips/boot/dts/ingenic/jz4770.dtsi | 59 ++++++++++++++++++++++++++++++ arch/mips/boot/dts/ingenic/jz4780.dtsi | 67 ++++++++++++++++++++++++++++++---- 3 files changed, 164 insertions(+), 13 deletions(-) diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 2beb78a62b7d..bfa97e29f348 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include / { #address-cells = <1>; @@ -45,12 +46,52 @@ #clock-cells = <1>; }; - watchdog: watchdog@10002000 { - compatible = "ingenic,jz4740-watchdog"; - reg = <0x10002000 0x10>; + tcu: timer@10002000 { + compatible = "ingenic,jz4740-tcu"; + reg = <0x10002000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x10002000 0x1000>; - clocks = <&cgu JZ4740_CLK_RTC>; - clock-names = "rtc"; + #clock-cells = <1>; + + clocks = <&cgu JZ4740_CLK_RTC + &cgu JZ4740_CLK_EXT + &cgu JZ4740_CLK_PCLK + &cgu JZ4740_CLK_TCU>; + clock-names = "rtc", "ext", "pclk", "tcu"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&intc>; + interrupts = <23 22 21>; + + watchdog: watchdog@0 { + compatible = "ingenic,jz4740-watchdog"; + reg = <0x0 0xc>; + + clocks = <&tcu TCU_CLK_WDT>; + clock-names = "wdt"; + }; + + pwm: pwm@40 { + compatible = "ingenic,jz4740-pwm"; + reg = <0x40 0x80>; + + #pwm-cells = <3>; + + clocks = <&tcu TCU_CLK_TIMER0 + &tcu TCU_CLK_TIMER1 + &tcu TCU_CLK_TIMER2 + &tcu TCU_CLK_TIMER3 + &tcu TCU_CLK_TIMER4 + &tcu TCU_CLK_TIMER5 + &tcu TCU_CLK_TIMER6 + &tcu TCU_CLK_TIMER7>; + clock-names = "timer0", "timer1", "timer2", "timer3", + "timer4", "timer5", "timer6", "timer7"; + }; }; rtc_dev: rtc@10003000 { diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi index 49ede6c14ff3..89c7a4b9773c 100644 --- a/arch/mips/boot/dts/ingenic/jz4770.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include / { #address-cells = <1>; @@ -46,6 +47,64 @@ #clock-cells = <1>; }; + tcu: timer@10002000 { + compatible = "ingenic,jz4770-tcu"; + reg = <0x10002000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x10002000 0x1000>; + + #clock-cells = <1>; + + clocks = <&cgu JZ4770_CLK_RTC + &cgu JZ4770_CLK_EXT + &cgu JZ4770_CLK_PCLK + &cgu JZ4770_CLK_EXT>; + clock-names = "rtc", "ext", "pclk", "tcu"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&intc>; + interrupts = <27 26 25>; + + watchdog: watchdog@0 { + compatible = "ingenic,jz4740-watchdog"; + reg = <0x0 0xc>; + + clocks = <&tcu TCU_CLK_WDT>; + clock-names = "wdt"; + }; + + pwm: pwm@40 { + compatible = "ingenic,jz4740-pwm"; + reg = <0x40 0x80>; + + #pwm-cells = <3>; + + clocks = <&tcu TCU_CLK_TIMER0 + &tcu TCU_CLK_TIMER1 + &tcu TCU_CLK_TIMER2 + &tcu TCU_CLK_TIMER3 + &tcu TCU_CLK_TIMER4 + &tcu TCU_CLK_TIMER5 + &tcu TCU_CLK_TIMER6 + &tcu TCU_CLK_TIMER7>; + clock-names = "timer0", "timer1", "timer2", "timer3", + "timer4", "timer5", "timer6", "timer7"; + }; + + ost: timer@e0 { + compatible = "ingenic,jz4770-ost"; + reg = <0xe0 0x20>; + + clocks = <&tcu TCU_CLK_OST>; + clock-names = "ost"; + + interrupts = <15>; + }; + }; + pinctrl: pin-controller@10010000 { compatible = "ingenic,jz4770-pinctrl"; reg = <0x10010000 0x600>; diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi index b03cdec56de9..9f45c075b4f8 100644 --- a/arch/mips/boot/dts/ingenic/jz4780.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include / { @@ -46,6 +47,64 @@ #clock-cells = <1>; }; + tcu: timer@10002000 { + compatible = "ingenic,jz4770-tcu"; + reg = <0x10002000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x10002000 0x1000>; + + #clock-cells = <1>; + + clocks = <&cgu JZ4780_CLK_RTCLK + &cgu JZ4780_CLK_EXCLK + &cgu JZ4780_CLK_PCLK + &cgu JZ4780_CLK_EXCLK>; + clock-names = "rtc", "ext", "pclk", "tcu"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&intc>; + interrupts = <27 26 25>; + + watchdog: watchdog@0 { + compatible = "ingenic,jz4780-watchdog"; + reg = <0x0 0xc>; + + clocks = <&tcu TCU_CLK_WDT>; + clock-names = "wdt"; + }; + + pwm: pwm@40 { + compatible = "ingenic,jz4740-pwm"; + reg = <0x40 0x80>; + + #pwm-cells = <3>; + + clocks = <&tcu TCU_CLK_TIMER0 + &tcu TCU_CLK_TIMER1 + &tcu TCU_CLK_TIMER2 + &tcu TCU_CLK_TIMER3 + &tcu TCU_CLK_TIMER4 + &tcu TCU_CLK_TIMER5 + &tcu TCU_CLK_TIMER6 + &tcu TCU_CLK_TIMER7>; + clock-names = "timer0", "timer1", "timer2", "timer3", + "timer4", "timer5", "timer6", "timer7"; + }; + + ost: timer@e0 { + compatible = "ingenic,jz4770-ost"; + reg = <0xe0 0x20>; + + clocks = <&tcu TCU_CLK_OST>; + clock-names = "ost"; + + interrupts = <15>; + }; + }; + rtc_dev: rtc@10003000 { compatible = "ingenic,jz4780-rtc"; reg = <0x10003000 0x4c>; @@ -239,14 +298,6 @@ status = "disabled"; }; - watchdog: watchdog@10002000 { - compatible = "ingenic,jz4780-watchdog"; - reg = <0x10002000 0x10>; - - clocks = <&cgu JZ4780_CLK_RTCLK>; - clock-names = "rtc"; - }; - nemc: nemc@13410000 { compatible = "ingenic,jz4780-nemc"; reg = <0x13410000 0x10000>; From patchwork Wed Mar 27 23:16:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067526 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="wxLli0Jw"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pZ0hMkz9sBV for ; Thu, 28 Mar 2019 10:18:46 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733045AbfC0XR7 (ORCPT ); Wed, 27 Mar 2019 19:17:59 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59396 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732979AbfC0XR6 (ORCPT ); Wed, 27 Mar 2019 19:17:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728675; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=JbtPoYzT85iVihfhiK6KVCiEkJhZBN9XvYChQW69SQ4=; b=wxLli0JwheSJZ4gtfzkawG+F3FX7DzYOCEY1n5RP+/Q/WcIUe4qvNnK3zPdGEzUaymVdtX 9C1PPG8gsRznrTqU2pwKX6HGJbiGPN0GA9FxALeZzu+HoY/tX3kb3zR7hildd4P7fGH3S8 /s9Our9dohtdhQXkclOoSLyCH/t2gB4= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 21/27] MIPS: qi_lb60: Move PWM devices to devicetree Date: Thu, 28 Mar 2019 00:16:25 +0100 Message-Id: <20190327231631.15708-22-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Probe the few drivers using PWMs from devicetree, now that we have a devicetree node for the PWM driver. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/boot/dts/ingenic/qi_lb60.dts | 14 ++++++++++++++ arch/mips/jz4740/board-qi_lb60.c | 19 ------------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts index 76aaf8982554..85529a142409 100644 --- a/arch/mips/boot/dts/ingenic/qi_lb60.dts +++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts @@ -9,6 +9,14 @@ chosen { stdout-path = &uart0; }; + + beeper { + compatible = "pwm-beeper"; + pwms = <&pwm 4 0 0>; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_pwm4>; + }; }; &ext { @@ -30,4 +38,10 @@ groups = "uart0-data"; bias-disable; }; + + pins_pwm4: pwm4 { + function = "pwm4"; + groups = "pwm4"; + bias-disable; + }; }; diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 6718efb400f4..02b9c131a051 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -27,7 +27,6 @@ #include #include #include -#include #include @@ -395,17 +394,6 @@ static struct gpiod_lookup_table qi_lb60_mmc_gpio_table = { }, }; -/* beeper */ -static struct pwm_lookup qi_lb60_pwm_lookup[] = { - PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0, - PWM_POLARITY_NORMAL), -}; - -static struct platform_device qi_lb60_pwm_beeper = { - .name = "pwm-beeper", - .id = -1, -}; - /* charger */ static char *qi_lb60_batteries[] = { "battery", @@ -454,10 +442,8 @@ static struct platform_device *jz_platform_devices[] __initdata = { &jz4740_i2s_device, &jz4740_codec_device, &jz4740_adc_device, - &jz4740_pwm_device, &jz4740_dma_device, &qi_lb60_gpio_keys, - &qi_lb60_pwm_beeper, &qi_lb60_charger_device, &qi_lb60_audio_device, }; @@ -486,10 +472,6 @@ static struct pinctrl_map pin_map[] __initdata = { "10010000.jz4740-pinctrl", "PD0", pin_cfg_bias_disable), PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0", "10010000.jz4740-pinctrl", "PD2", pin_cfg_bias_disable), - - /* PWM pin configuration */ - PIN_MAP_MUX_GROUP_DEFAULT("jz4740-pwm", - "10010000.jz4740-pinctrl", "pwm4", "pwm4"), }; @@ -508,7 +490,6 @@ static int __init qi_lb60_init_platform_devices(void) spi_register_board_info(qi_lb60_spi_board_info, ARRAY_SIZE(qi_lb60_spi_board_info)); - pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup)); pinctrl_register_mappings(pin_map, ARRAY_SIZE(pin_map)); return platform_add_devices(jz_platform_devices, From patchwork Wed Mar 27 23:16:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067525 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="Dv8XV9bl"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pX53Kcz9sBV for ; Thu, 28 Mar 2019 10:18:44 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733108AbfC0XSC (ORCPT ); Wed, 27 Mar 2019 19:18:02 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59468 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732789AbfC0XSB (ORCPT ); Wed, 27 Mar 2019 19:18:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728678; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=G+EzRBQpk9DxezKApxB3XMfQ8fsiA9FA550z/ZOndCI=; b=Dv8XV9blNBqxzTPsKTtPbQZHNwaE9PrZmuCO4LjUkXrBuGBIl/dhazBMbPnHDQfBSzFiHg a+JCqzCdBUNdnwgDr3jR4vhpGE5lgBgvxUugC4aclXjanYl4N1pFdTVuwQPPDvQKlZ3zfX jkkL4l4G3SV1YYkMhwfx3WbB6M82k6E= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 22/27] MIPS: qi_lb60: Reduce system timer and clocksource to 750 kHz Date: Thu, 28 Mar 2019 00:16:26 +0100 Message-Id: <20190327231631.15708-23-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The default clock (12 MHz) is too fast for the system timer, which fails to report time accurately. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/boot/dts/ingenic/qi_lb60.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts index 85529a142409..de9d45e2c24a 100644 --- a/arch/mips/boot/dts/ingenic/qi_lb60.dts +++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts @@ -45,3 +45,9 @@ bias-disable; }; }; + +&tcu { + /* 750 kHz for the system timer and clocksource */ + assigned-clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER1>; + assigned-clock-rates = <750000>, <750000>; +}; From patchwork Wed Mar 27 23:16:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067524 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="hk8sxpii"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pS6vd2z9sR3 for ; Thu, 28 Mar 2019 10:18:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733160AbfC0XSE (ORCPT ); Wed, 27 Mar 2019 19:18:04 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59528 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732979AbfC0XSD (ORCPT ); Wed, 27 Mar 2019 19:18:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728680; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=atf0ej3oIfTr6kclnjZ7r8yX+La9UJl2lE532ffBQWw=; b=hk8sxpiiamN/S/TaYEbNWfBg7PLpnWU4XIvDmSn8IThUVJbYPA1f7QIvl5UQnReRJ1HC5E MQod2XYwsMjplrXbpDfSsgdLjcrR81MzIdTfH/na8wnAIEjd+WI3uljGAIHxCtNeanfIp0 Ai02Xh5T7/inKjDzV7lV+KXUV1sFoZw= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 23/27] MIPS: CI20: Reduce system timer and clocksource to 3 MHz Date: Thu, 28 Mar 2019 00:16:27 +0100 Message-Id: <20190327231631.15708-24-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The default clock (48 MHz) is too fast for the system timer. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/boot/dts/ingenic/ci20.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts index 4f7b1fa31cf5..30b01cfaaf5a 100644 --- a/arch/mips/boot/dts/ingenic/ci20.dts +++ b/arch/mips/boot/dts/ingenic/ci20.dts @@ -238,3 +238,9 @@ bias-disable; }; }; + +&tcu { + /* 3 MHz for the system timer and clocksource */ + assigned-clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER1>; + assigned-clock-rates = <3000000>, <3000000>; +}; From patchwork Wed Mar 27 23:16:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067520 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="OtVcgFSh"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3ny1rJbz9sR0 for ; Thu, 28 Mar 2019 10:18:14 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733206AbfC0XSI (ORCPT ); Wed, 27 Mar 2019 19:18:08 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59590 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733164AbfC0XSH (ORCPT ); Wed, 27 Mar 2019 19:18:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728684; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=ka4onLI32P6QSiyTqTOYiXU4C2Q8s1zZFk8NMlE3pt4=; b=OtVcgFShqVChYyu8E9BLzG5mDVbgSnJDYx/rEVlhIEBXAbJYsNUyUvUudSb5E6nzzbfuLQ WTJjdQPZqy+B0c87BxHn9mGIKJAW2j1F2aePZjT59R7oIVgwR0PjFoRnGCz0k9HYeFW5/H b3NYk5xnjqNfGICBr5uIXX54gIo18rI= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 24/27] MIPS: CI20: defconfig: enable OST driver Date: Thu, 28 Mar 2019 00:16:28 +0100 Message-Id: <20190327231631.15708-25-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The OST driver provides a clocksource and sched_clock that are much more accurate than the default ones. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/configs/ci20_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig index 412800d5d7e0..2f101c7c1749 100644 --- a/arch/mips/configs/ci20_defconfig +++ b/arch/mips/configs/ci20_defconfig @@ -105,6 +105,7 @@ CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_JZ4740=y CONFIG_DMADEVICES=y CONFIG_DMA_JZ4780=y +CONFIG_INGENIC_OST=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_MEMORY=y CONFIG_EXT4_FS=y From patchwork Wed Mar 27 23:16:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067523 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="WWVo51jN"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pP6nj3z9sBV for ; Thu, 28 Mar 2019 10:18:37 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733236AbfC0XSN (ORCPT ); Wed, 27 Mar 2019 19:18:13 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59652 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733225AbfC0XSM (ORCPT ); Wed, 27 Mar 2019 19:18:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728689; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=BhaqD9cfvvcuJii1b2J+pKSfpooSP6Z22B7yIRH/Y4U=; b=WWVo51jNNHZanVTmVzPzQIFT+GrRakQOvU6KUJOzRLOlzIc3VDTyS62wipw2A/62Mk/U6W bEjxVO7+NfMhFcOre+ysO1aImAQ1wz/kolCrmrIIycIB1+RNjE8Eh7uXWTZGctIClqfiMf 6UU6RYaS/7pfnWYKEuUZgTtNNAZmFcQ= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 25/27] MIPS: GCW0: Reduce system timer and clocksource to 750 kHz Date: Thu, 28 Mar 2019 00:16:29 +0100 Message-Id: <20190327231631.15708-26-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The default clock (12 MHz) is too fast for the system timer. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/boot/dts/ingenic/gcw0.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/boot/dts/ingenic/gcw0.dts b/arch/mips/boot/dts/ingenic/gcw0.dts index 35f0291e8d38..2f26b8a498e9 100644 --- a/arch/mips/boot/dts/ingenic/gcw0.dts +++ b/arch/mips/boot/dts/ingenic/gcw0.dts @@ -60,3 +60,9 @@ /* The WiFi module is connected to the UHC. */ status = "okay"; }; + +&tcu { + /* 750 kHz for the system timer and clocksource */ + assigned-clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER1>; + assigned-clock-rates = <750000>, <750000>; +}; From patchwork Wed Mar 27 23:16:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067522 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="hhg8u4LG"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3pF5jkjz9sBV for ; Thu, 28 Mar 2019 10:18:29 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733270AbfC0XSP (ORCPT ); Wed, 27 Mar 2019 19:18:15 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59726 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729245AbfC0XSO (ORCPT ); Wed, 27 Mar 2019 19:18:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728692; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=DH0RBuCyaUcwEdmMa6NQzCrm92kH4f4vPKoN8rRVzzE=; b=hhg8u4LGxyQth35qkAHoslLPJRmUYSdyXgMupktjBfXSAewZZQjF+qlbEXLzejkq0LCaQV bXLpsxrPDGBZKp8Q3E8dIoBcSQAkPqUHRQB/InHBsCLsUFnyx/CYxReJNG9c00dOhDLrDR rATIw/XOKXTEw3Jn+TWUnRtXuXCA2uY= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 26/27] MIPS: GCW0: defconfig: Enable OST, watchdog, PWM drivers Date: Thu, 28 Mar 2019 00:16:30 +0100 Message-Id: <20190327231631.15708-27-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The OST driver provides a clocksource and sched_clock that are much more accurate than the default ones. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/configs/gcw0_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/mips/configs/gcw0_defconfig b/arch/mips/configs/gcw0_defconfig index a3e3eb3c5a8b..7116400e8cbf 100644 --- a/arch/mips/configs/gcw0_defconfig +++ b/arch/mips/configs/gcw0_defconfig @@ -20,8 +20,13 @@ CONFIG_SERIAL_8250=y # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_INGENIC=y +CONFIG_WATCHDOG=y +CONFIG_JZ4740_WDT=y CONFIG_USB=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_NOP_USB_XCEIV=y +CONFIG_INGENIC_OST=y +CONFIG_PWM=y +CONFIG_PWM_JZ4740=y CONFIG_TMPFS=y From patchwork Wed Mar 27 23:16:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Cercueil X-Patchwork-Id: 1067521 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=crapouillou.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=crapouillou.net header.i=@crapouillou.net header.b="h3SUQIhs"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44V3p430z7z9sR4 for ; Thu, 28 Mar 2019 10:18:20 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733302AbfC0XST (ORCPT ); Wed, 27 Mar 2019 19:18:19 -0400 Received: from outils.crapouillou.net ([89.234.176.41]:59770 "EHLO crapouillou.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729235AbfC0XSR (ORCPT ); Wed, 27 Mar 2019 19:18:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=crapouillou.net; s=mail; t=1553728694; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:in-reply-to: references:references; bh=kFiu4oCKNBmynf8g6iCJQc/PgL5heWklR+ACmJIz+jA=; b=h3SUQIhsfUNKeXzXNEeu0TXqAWMUnzWFoz2yz7/SjkRzoeWreLidYkLuIcFNxrrkmebNuP C1czWP4cFlSFTnTg4pCUFaYjQ4TjyTeatX78OezL4rCt95PYRI/wgrZdNT7dNuJDbuUPKQ nxdb28lKyp22DM5zasrggFKn5Tqpjsg= From: Paul Cercueil To: Rob Herring , Mark Rutland , Thierry Reding , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Ralf Baechle , Paul Burton , James Hogan , Jonathan Corbet , Michael Turquette , Stephen Boyd Cc: Mathieu Malaterre , od@zcrc.me, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org, linux-doc@vger.kernel.org, linux-clk@vger.kernel.org, Paul Cercueil Subject: [PATCH v11 27/27] MIPS: jz4740: Drop obsolete code Date: Thu, 28 Mar 2019 00:16:31 +0100 Message-Id: <20190327231631.15708-28-paul@crapouillou.net> In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net> References: <20190327231631.15708-1-paul@crapouillou.net> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The old clocksource/timer platform code is now obsoleted by the newly introduced ingenic-timer and ingenic-ost drivers. Signed-off-by: Paul Cercueil Tested-by: Mathieu Malaterre Tested-by: Artur Rojek --- arch/mips/include/asm/mach-jz4740/platform.h | 1 - arch/mips/include/asm/mach-jz4740/timer.h | 135 -------------------- arch/mips/jz4740/Makefile | 3 +- arch/mips/jz4740/platform.c | 6 - arch/mips/jz4740/setup.c | 8 ++ arch/mips/jz4740/time.c | 176 --------------------------- arch/mips/jz4740/timer.c | 51 -------- 7 files changed, 9 insertions(+), 371 deletions(-) delete mode 100644 arch/mips/include/asm/mach-jz4740/timer.h delete mode 100644 arch/mips/jz4740/time.c delete mode 100644 arch/mips/jz4740/timer.c diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h index c0c932ac72a7..cd464d956882 100644 --- a/arch/mips/include/asm/mach-jz4740/platform.h +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -29,7 +29,6 @@ extern struct platform_device jz4740_i2s_device; extern struct platform_device jz4740_pcm_device; extern struct platform_device jz4740_codec_device; extern struct platform_device jz4740_adc_device; -extern struct platform_device jz4740_pwm_device; extern struct platform_device jz4740_dma_device; #endif diff --git a/arch/mips/include/asm/mach-jz4740/timer.h b/arch/mips/include/asm/mach-jz4740/timer.h deleted file mode 100644 index 8750a1d04e22..000000000000 --- a/arch/mips/include/asm/mach-jz4740/timer.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen - * JZ4740 platform timer support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __ASM_MACH_JZ4740_TIMER -#define __ASM_MACH_JZ4740_TIMER - -#define JZ_REG_TIMER_STOP 0x0C -#define JZ_REG_TIMER_STOP_SET 0x1C -#define JZ_REG_TIMER_STOP_CLEAR 0x2C -#define JZ_REG_TIMER_ENABLE 0x00 -#define JZ_REG_TIMER_ENABLE_SET 0x04 -#define JZ_REG_TIMER_ENABLE_CLEAR 0x08 -#define JZ_REG_TIMER_FLAG 0x10 -#define JZ_REG_TIMER_FLAG_SET 0x14 -#define JZ_REG_TIMER_FLAG_CLEAR 0x18 -#define JZ_REG_TIMER_MASK 0x20 -#define JZ_REG_TIMER_MASK_SET 0x24 -#define JZ_REG_TIMER_MASK_CLEAR 0x28 - -#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30) -#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34) -#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38) -#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C) - -#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10) -#define JZ_TIMER_IRQ_FULL(x) BIT(x) - -#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN BIT(9) -#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW BIT(8) -#define JZ_TIMER_CTRL_PWM_ENABLE BIT(7) -#define JZ_TIMER_CTRL_PRESCALE_MASK 0x1c -#define JZ_TIMER_CTRL_PRESCALE_OFFSET 0x3 -#define JZ_TIMER_CTRL_PRESCALE_1 (0 << 3) -#define JZ_TIMER_CTRL_PRESCALE_4 (1 << 3) -#define JZ_TIMER_CTRL_PRESCALE_16 (2 << 3) -#define JZ_TIMER_CTRL_PRESCALE_64 (3 << 3) -#define JZ_TIMER_CTRL_PRESCALE_256 (4 << 3) -#define JZ_TIMER_CTRL_PRESCALE_1024 (5 << 3) - -#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET) - -#define JZ_TIMER_CTRL_SRC_EXT BIT(2) -#define JZ_TIMER_CTRL_SRC_RTC BIT(1) -#define JZ_TIMER_CTRL_SRC_PCLK BIT(0) - -extern void __iomem *jz4740_timer_base; -void __init jz4740_timer_init(void); - -void jz4740_timer_enable_watchdog(void); -void jz4740_timer_disable_watchdog(void); - -static inline void jz4740_timer_stop(unsigned int timer) -{ - writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET); -} - -static inline void jz4740_timer_start(unsigned int timer) -{ - writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR); -} - -static inline bool jz4740_timer_is_enabled(unsigned int timer) -{ - return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer); -} - -static inline void jz4740_timer_enable(unsigned int timer) -{ - writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET); -} - -static inline void jz4740_timer_disable(unsigned int timer) -{ - writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR); -} - -static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period) -{ - writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer)); -} - -static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty) -{ - writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer)); -} - -static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count) -{ - writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer)); -} - -static inline uint16_t jz4740_timer_get_count(unsigned int timer) -{ - return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer)); -} - -static inline void jz4740_timer_ack_full(unsigned int timer) -{ - writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR); -} - -static inline void jz4740_timer_irq_full_enable(unsigned int timer) -{ - writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR); - writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR); -} - -static inline void jz4740_timer_irq_full_disable(unsigned int timer) -{ - writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET); -} - -static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl) -{ - writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer)); -} - -static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer) -{ - return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer)); -} - -#endif diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile index 88d6aa7d000b..72eb805028a4 100644 --- a/arch/mips/jz4740/Makefile +++ b/arch/mips/jz4740/Makefile @@ -5,8 +5,7 @@ # Object file lists. -obj-y += prom.o time.o reset.o setup.o \ - platform.o timer.o +obj-y += prom.o reset.o setup.o platform.o CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index cbc5f8e87230..af0ecaeb4931 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -233,12 +233,6 @@ struct platform_device jz4740_adc_device = { .resource = jz4740_adc_resources, }; -/* PWM */ -struct platform_device jz4740_pwm_device = { - .name = "jz4740-pwm", - .id = -1, -}; - /* DMA */ static struct resource jz4740_dma_resources[] = { { diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c index 7e63c54eb8d2..0bebd6172073 100644 --- a/arch/mips/jz4740/setup.c +++ b/arch/mips/jz4740/setup.c @@ -14,6 +14,8 @@ * */ +#include +#include #include #include #include @@ -107,3 +109,9 @@ void __init arch_init_irq(void) { irqchip_init(); } + +void __init plat_time_init(void) +{ + of_clk_init(NULL); + timer_probe(); +} diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c deleted file mode 100644 index 2ca9160f642a..000000000000 --- a/arch/mips/jz4740/time.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen - * JZ4740 platform time support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "clock.h" - -#define TIMER_CLOCKEVENT 0 -#define TIMER_CLOCKSOURCE 1 - -static uint16_t jz4740_jiffies_per_tick; - -static u64 jz4740_clocksource_read(struct clocksource *cs) -{ - return jz4740_timer_get_count(TIMER_CLOCKSOURCE); -} - -static struct clocksource jz4740_clocksource = { - .name = "jz4740-timer", - .rating = 200, - .read = jz4740_clocksource_read, - .mask = CLOCKSOURCE_MASK(16), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static u64 notrace jz4740_read_sched_clock(void) -{ - return jz4740_timer_get_count(TIMER_CLOCKSOURCE); -} - -static irqreturn_t jz4740_clockevent_irq(int irq, void *devid) -{ - struct clock_event_device *cd = devid; - - jz4740_timer_ack_full(TIMER_CLOCKEVENT); - - if (!clockevent_state_periodic(cd)) - jz4740_timer_disable(TIMER_CLOCKEVENT); - - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static int jz4740_clockevent_set_periodic(struct clock_event_device *evt) -{ - jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); - jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); - jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); - jz4740_timer_enable(TIMER_CLOCKEVENT); - - return 0; -} - -static int jz4740_clockevent_resume(struct clock_event_device *evt) -{ - jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); - jz4740_timer_enable(TIMER_CLOCKEVENT); - - return 0; -} - -static int jz4740_clockevent_shutdown(struct clock_event_device *evt) -{ - jz4740_timer_disable(TIMER_CLOCKEVENT); - - return 0; -} - -static int jz4740_clockevent_set_next(unsigned long evt, - struct clock_event_device *cd) -{ - jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); - jz4740_timer_set_period(TIMER_CLOCKEVENT, evt); - jz4740_timer_enable(TIMER_CLOCKEVENT); - - return 0; -} - -static struct clock_event_device jz4740_clockevent = { - .name = "jz4740-timer", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = jz4740_clockevent_set_next, - .set_state_shutdown = jz4740_clockevent_shutdown, - .set_state_periodic = jz4740_clockevent_set_periodic, - .set_state_oneshot = jz4740_clockevent_shutdown, - .tick_resume = jz4740_clockevent_resume, - .rating = 200, -#ifdef CONFIG_MACH_JZ4740 - .irq = JZ4740_IRQ_TCU0, -#endif -#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780) - .irq = JZ4780_IRQ_TCU2, -#endif -}; - -static struct irqaction timer_irqaction = { - .handler = jz4740_clockevent_irq, - .flags = IRQF_PERCPU | IRQF_TIMER, - .name = "jz4740-timerirq", - .dev_id = &jz4740_clockevent, -}; - -void __init plat_time_init(void) -{ - int ret; - uint32_t clk_rate; - uint16_t ctrl; - struct clk *ext_clk; - - of_clk_init(NULL); - jz4740_timer_init(); - - ext_clk = clk_get(NULL, "ext"); - if (IS_ERR(ext_clk)) - panic("unable to get ext clock"); - clk_rate = clk_get_rate(ext_clk) >> 4; - clk_put(ext_clk); - - jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ); - - clockevent_set_clock(&jz4740_clockevent, clk_rate); - jz4740_clockevent.min_delta_ns = clockevent_delta2ns(100, &jz4740_clockevent); - jz4740_clockevent.min_delta_ticks = 100; - jz4740_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &jz4740_clockevent); - jz4740_clockevent.max_delta_ticks = 0xffff; - jz4740_clockevent.cpumask = cpumask_of(0); - - clockevents_register_device(&jz4740_clockevent); - - ret = clocksource_register_hz(&jz4740_clocksource, clk_rate); - - if (ret) - printk(KERN_ERR "Failed to register clocksource: %d\n", ret); - - sched_clock_register(jz4740_read_sched_clock, 16, clk_rate); - - setup_irq(jz4740_clockevent.irq, &timer_irqaction); - - ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT; - - jz4740_timer_set_ctrl(TIMER_CLOCKEVENT, ctrl); - jz4740_timer_set_ctrl(TIMER_CLOCKSOURCE, ctrl); - - jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); - jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); - - jz4740_timer_set_period(TIMER_CLOCKSOURCE, 0xffff); - - jz4740_timer_enable(TIMER_CLOCKEVENT); - jz4740_timer_enable(TIMER_CLOCKSOURCE); -} diff --git a/arch/mips/jz4740/timer.c b/arch/mips/jz4740/timer.c deleted file mode 100644 index 777877feef71..000000000000 --- a/arch/mips/jz4740/timer.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen - * JZ4740 platform timer support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include - -#include -#include - -void __iomem *jz4740_timer_base; -EXPORT_SYMBOL_GPL(jz4740_timer_base); - -void jz4740_timer_enable_watchdog(void) -{ - writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR); -} -EXPORT_SYMBOL_GPL(jz4740_timer_enable_watchdog); - -void jz4740_timer_disable_watchdog(void) -{ - writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_SET); -} -EXPORT_SYMBOL_GPL(jz4740_timer_disable_watchdog); - -void __init jz4740_timer_init(void) -{ - jz4740_timer_base = ioremap(JZ4740_TCU_BASE_ADDR, 0x100); - - if (!jz4740_timer_base) - panic("Failed to ioremap timer registers"); - - /* Disable all timer clocks except for those used as system timers */ - writel(0x000100fc, jz4740_timer_base + JZ_REG_TIMER_STOP_SET); - - /* Timer irqs are unmasked by default, mask them */ - writel(0x00ff00ff, jz4740_timer_base + JZ_REG_TIMER_MASK_SET); -}