From patchwork Sun Oct 29 21:26:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 739165 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DAFA3C4167D for ; Sun, 29 Oct 2023 21:27:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230381AbjJ2V1v (ORCPT ); Sun, 29 Oct 2023 17:27:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230145AbjJ2V1u (ORCPT ); Sun, 29 Oct 2023 17:27:50 -0400 Received: from out5-smtp.messagingengine.com (out5-smtp.messagingengine.com [66.111.4.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19FAFBC; Sun, 29 Oct 2023 14:27:45 -0700 (PDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 79A015C0131; Sun, 29 Oct 2023 17:27:44 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sun, 29 Oct 2023 17:27:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm1; t=1698614864; x= 1698701264; bh=A2jXfVOkfopr59synhPTE2K5qelNk+BTDcO0NBezLEc=; b=n mjYzBDOSdbYxM2dg1RIjohpz+AATAlO2OhI1iKnT4UC+pmImKoY3C7QLRlF7a/Ac w9Tiq4Wru2TWUrVfNpydhdLyiTKVZcmOHA6zA/UCcdodTDGrimwQog3xPFLdo+bv cjUhbalXMAYuY4Vah2HAnsRVuKlUKRWAYiQw0Otm/x5Ev9CP+nOMUN0lPmYkfHGC 4Ws7WcN8SzZd7s1wz7xMmvZMLOFUgLIhCIT+FL9NOGSlMUM+KeNGT91yQiLV9U1O YKKmyOm1rVY1cYam69b5/nOu5cGy2N3wrnmJeCYy+BDqIRneTu576PvEwLTmptpk +zWLUpXqE3EbLqpWBUtVA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1698614864; x= 1698701264; bh=A2jXfVOkfopr59synhPTE2K5qelNk+BTDcO0NBezLEc=; b=k bQXc6GN/XXLAqBz+O2oD3QrgAKXmQF6uykd4CePuJ8ZSiI8AxRbHMDy1BYf1TDM6 Ctjk4ASQyOpR2C2dHvBA8sVuAi7MUQrstiO4nMUkk5mur33TsAx+g0BvnqEaVfHc VfxAGbzLjPP1eL8Jy2VWRwNDA8F7O7t52dVKXXveLePSdKUfOhe8u9ODFUTBpxwi ZXYKUMtDzLJtBA1SRaPce3LfghtBJ5gpHovuCc20DPOqDUAFx+e9d3j/q5UHPxZ9 0c5nxwUl2JZUTsIJCSPJcljf460KQTpA0w1SC4WOVYaaoIoYzWsq7opFhZ/tIF8V bbj6EyFxXIS0dCzjhQ8Jg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrleekgddugeekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomhepufgrmhhu vghlucfjohhllhgrnhguuceoshgrmhhuvghlsehshhholhhlrghnugdrohhrgheqnecugg ftrfgrthhtvghrnhepgffhvefhgfehjeehgfekheeuffegheffjeegheeuudeufeffhffh ueeihfeufffhnecuffhomhgrihhnpeguvghvihgtvghtrhgvvgdrohhrghenucevlhhush htvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehsrghmuhgvlhesshhh ohhllhgrnhgurdhorhhg X-ME-Proxy: Feedback-ID: i0ad843c9:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 29 Oct 2023 17:27:42 -0400 (EDT) From: Samuel Holland To: Lee Jones , Pavel Machek , linux-leds@vger.kernel.org, Chen-Yu Tsai , Jernej Skrabec Cc: Samuel Holland , Andre Przywara , Conor Dooley , Cristian Ciocaltea , Guo Ren , Jisheng Zhang , John Watts , Krzysztof Kozlowski , Maksim Kiselev , Marc Kleine-Budde , Palmer Dabbelt , Philipp Zabel , Rob Herring , Trevor Woerner , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, linux-sunxi@lists.linux.dev, Maxime Ripard , Palmer Dabbelt , Rob Herring Subject: [PATCH v8 1/5] dt-bindings: leds: Add Allwinner A100 LED controller Date: Sun, 29 Oct 2023 16:26:55 -0500 Message-ID: <20231029212738.7871-2-samuel@sholland.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231029212738.7871-1-samuel@sholland.org> References: <20231029212738.7871-1-samuel@sholland.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org The Allwinner A100, R329, and D1 SoCs contain an LED controller designed to drive a series of RGB LED pixels. It supports PIO and DMA transfers, and has configurable timing and pixel format. All three implementations appear to be identical, so use the oldest as the fallback compatible. Acked-by: Guo Ren Acked-by: Maxime Ripard Acked-by: Palmer Dabbelt Reviewed-by: Rob Herring Tested-by: Trevor Woerner Signed-off-by: Samuel Holland --- Changes in v8: - Remove redundant "Bindings" from the binding document title - Make the DMA channel optional; the driver now works without DMA Changes in v5: - A100 contains the original implementation, so use that as the base compatible string, and rename the binding to match - Add "unevaluatedProperties: false" to the child multi-led binding Changes in v4: - Use "default" instead of "maxItems" for timing properties Changes in v3: - Removed quotes from enumeration values - Added vendor prefix to timing/format properties - Renamed "format" property to "pixel-format" for clarity - Dropped "vled-supply" as it is unrelated to the controller hardware Changes in v2: - Fixed typo leading to duplicate t1h-ns property - Removed "items" layer in definition of dmas/dma-names - Replaced uint32 type reference with maxItems in timing properties .../leds/allwinner,sun50i-a100-ledc.yaml | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/allwinner,sun50i-a100-ledc.yaml diff --git a/Documentation/devicetree/bindings/leds/allwinner,sun50i-a100-ledc.yaml b/Documentation/devicetree/bindings/leds/allwinner,sun50i-a100-ledc.yaml new file mode 100644 index 000000000000..760cb336dccb --- /dev/null +++ b/Documentation/devicetree/bindings/leds/allwinner,sun50i-a100-ledc.yaml @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/allwinner,sun50i-a100-ledc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A100 LED Controller + +maintainers: + - Samuel Holland + +description: + The LED controller found in Allwinner sunxi SoCs uses a one-wire serial + interface to drive up to 1024 RGB LEDs. + +properties: + compatible: + oneOf: + - const: allwinner,sun50i-a100-ledc + - items: + - enum: + - allwinner,sun20i-d1-ledc + - allwinner,sun50i-r329-ledc + - const: allwinner,sun50i-a100-ledc + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus clock + - description: Module clock + + clock-names: + items: + - const: bus + - const: mod + + resets: + maxItems: 1 + + dmas: + maxItems: 1 + description: TX DMA channel + + dma-names: + const: tx + + allwinner,pixel-format: + description: Pixel format (subpixel transmission order), default is "grb" + enum: + - bgr + - brg + - gbr + - grb + - rbg + - rgb + + allwinner,t0h-ns: + default: 336 + description: Length of high pulse when transmitting a "0" bit + + allwinner,t0l-ns: + default: 840 + description: Length of low pulse when transmitting a "0" bit + + allwinner,t1h-ns: + default: 882 + description: Length of high pulse when transmitting a "1" bit + + allwinner,t1l-ns: + default: 294 + description: Length of low pulse when transmitting a "1" bit + + allwinner,treset-ns: + default: 300000 + description: Minimum delay between transmission frames + +patternProperties: + "^multi-led@[0-9a-f]+$": + type: object + $ref: leds-class-multicolor.yaml# + unevaluatedProperties: false + properties: + reg: + minimum: 0 + maximum: 1023 + description: Index of the LED in the series (must be contiguous) + + required: + - reg + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + + ledc: led-controller@2008000 { + compatible = "allwinner,sun20i-d1-ledc", + "allwinner,sun50i-a100-ledc"; + reg = <0x2008000 0x400>; + interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu 12>, <&ccu 34>; + clock-names = "bus", "mod"; + resets = <&ccu 12>; + dmas = <&dma 42>; + dma-names = "tx"; + #address-cells = <1>; + #size-cells = <0>; + + multi-led@0 { + reg = <0x0>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; + }; + +... From patchwork Sun Oct 29 21:26:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 739164 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70855C4332F for ; Sun, 29 Oct 2023 21:27:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230402AbjJ2V1x (ORCPT ); Sun, 29 Oct 2023 17:27:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230382AbjJ2V1v (ORCPT ); Sun, 29 Oct 2023 17:27:51 -0400 Received: from out5-smtp.messagingengine.com (out5-smtp.messagingengine.com [66.111.4.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CA9AAC0; Sun, 29 Oct 2023 14:27:46 -0700 (PDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 3CCE45C0165; Sun, 29 Oct 2023 17:27:46 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sun, 29 Oct 2023 17:27:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to; s=fm1; t= 1698614866; x=1698701266; bh=sPSgcwKkfnrqnXpSyrNRl5PfjZhAo3I6N64 oZP29y7A=; b=h2vohgyZZXX+Yjue3st/rNZRIQvNRnn0/TtFRbqufHxcl6kIuj3 zH+0Sa7x++cguO47kxSjCfpMpAcWg4HQQAL2o9PmF4GYKwLCTMWbT2MjYDYvmZGz xk/kkFzzUACfoZdhw7qE9/E6tpMRM9ikNlKY4/eQdB/VDcxiafISNryNXyHeJhDk vkWNHExMFl+uKsyt//MRfzAKCDSTZ53Fh2zXyIFE12YR3SU/QRaZjeHKKnlOvJJx lpv4Dmu4VXMEWshcf/zat8zM/6x78FaCsPLvzJqZg6FhBlohhkD7GQ4MiXsJuDVr sm9QCLql8FQVH0s78rtM2IUrCEdeEeqJaLg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1698614866; x=1698701266; bh=sPSgcwKkfnrqnXpSyrNRl5PfjZhAo3I6N64 oZP29y7A=; b=I/iLbdObcYo+Vn2VR47kn9Uh+DuGcm5p0nEvM0ja98+SIb+2c/b 0qEfGB75pM914DRQp5vRqO3ctg6KUg/FRji9f0ym0HMdur9W/qUQtt0yiFSLONX3 oFGDVGRAGD2/ggBm1Fkbw9VwEWNCoanVM95ouc2s9PlRRV92nF2mqwcgSjlliJDu Jq5KjOVnXLMwdPimcWfU4eNMNkuH5ocxVBjXPyZHP1EN7V5Gexh19QZLpdC7Mchl lCY1Ha/QaVSbWSpRiQpKqe/6yKpfDBEGjj8hVn5GDkg0RXUKy+Ej762fxiqSsG/+ 6dZ3VZZ6Kqd6pIp64tcxyz84Sb6xCcGZBVA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrleekgddugeekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpefurghm uhgvlhcujfholhhlrghnugcuoehsrghmuhgvlhesshhhohhllhgrnhgurdhorhhgqeenuc ggtffrrghtthgvrhhnpeefueevueeffeelheelhfelgeelgffgieekffevteefveejueei teeugfefieehleenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfh hrohhmpehsrghmuhgvlhesshhhohhllhgrnhgurdhorhhg X-ME-Proxy: Feedback-ID: i0ad843c9:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 29 Oct 2023 17:27:44 -0400 (EDT) From: Samuel Holland To: Lee Jones , Pavel Machek , linux-leds@vger.kernel.org, Chen-Yu Tsai , Jernej Skrabec Cc: Samuel Holland , Andre Przywara , Conor Dooley , Cristian Ciocaltea , Guo Ren , Jisheng Zhang , John Watts , Krzysztof Kozlowski , Maksim Kiselev , Marc Kleine-Budde , Palmer Dabbelt , Philipp Zabel , Rob Herring , Trevor Woerner , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, linux-sunxi@lists.linux.dev, Palmer Dabbelt Subject: [PATCH v8 2/5] leds: sun50i-a100: New driver for the A100 LED controller Date: Sun, 29 Oct 2023 16:26:56 -0500 Message-ID: <20231029212738.7871-3-samuel@sholland.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231029212738.7871-1-samuel@sholland.org> References: <20231029212738.7871-1-samuel@sholland.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Some Allwinner sunxi SoCs, starting with the A100, contain an LED controller designed to drive RGB LED pixels. Add a driver for it using the multicolor LED framework, and with LEDs defined in the device tree. Acked-by: Guo Ren Acked-by: Jernej Skrabec Acked-by: Palmer Dabbelt Signed-off-by: Samuel Holland --- Changes in v8: - Fix spelling in the Kconfig description - Fix the file header comment style - Wrap to 100 columns instead of 80 - Use GENMASK for register bit fields - Use FIELD_PREP for setting all multiple-bit register fields - Add and use the LEDC_CHANNELS_PER_LED macro - Make length and offset variables unsigned to avoid mixed signedness - Add __counted_by for sun50i_a100_ledc::leds - Move the new/existing xfer logic out of sun50i_a100_ledc_pio_xfer() - Get the FIFO usage from INT_STS instead of assuming it is half full - Make the DMA channel optional; always use PIO if it is unavailable - Set up DMA before triggering the LEDC transfer to avoid underrun - Correctly enable/disable the DRQ for each transfer - Use more descriptive names for variables containing register values - Add blank lines and comments to improve readability - Add a comment explaining the write to the status register - Remove unnecessary debugging prints - Use the more-idiomatic post-increment operator in for loops - Allow gaps in child node 'reg' values (separate max_addr/num_leds) - Use device-managed allocation for the DMA buffer - Unregister LEDs before shutting down the controller to correctly respect LED_RETAIN_AT_SHUTDOWN (or lack thereof) - Use the .remove_new platform driver hook Changes in v7: - Use DEFINE_SIMPLE_DEV_PM_OPS Changes in v5: - Rename the driver R329 -> A100, since that is the actual original implementation Changes in v4: - Depend on LEDS_CLASS_MULTICOLOR Changes in v3: - Added vendor prefix to timing/format properties - Renamed "format" property to "pixel-format" for clarity - Dropped "vled-supply" as it is unrelated to the controller hardware - Changed "writesl" to "iowrite32_rep" so the driver builds on hppa Changes in v2: - Renamed from sunxi-ledc to sun50i-r329-ledc - Added missing "static" to functions/globals as reported by 0day bot drivers/leds/Kconfig | 9 + drivers/leds/Makefile | 1 + drivers/leds/leds-sun50i-a100.c | 580 ++++++++++++++++++++++++++++++++ 3 files changed, 590 insertions(+) create mode 100644 drivers/leds/leds-sun50i-a100.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index b92208eccdea..bfc5af75761e 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -297,6 +297,15 @@ config LEDS_COBALT_RAQ help This option enables support for the Cobalt Raq series LEDs. +config LEDS_SUN50I_A100 + tristate "LED support for Allwinner A100 RGB LED controller" + depends on LEDS_CLASS_MULTICOLOR && OF + depends on ARCH_SUNXI || COMPILE_TEST + help + This option enables support for the RGB LED controller found + in some Allwinner sunxi SoCs, including A100, R329, and D1. + It uses a one-wire interface to control up to 1024 LEDs. + config LEDS_SUNFIRE tristate "LED support for SunFire servers." depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index d7348e8bc019..b82a538e3f8c 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o obj-$(CONFIG_LEDS_PWM) += leds-pwm.o obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o +obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o diff --git a/drivers/leds/leds-sun50i-a100.c b/drivers/leds/leds-sun50i-a100.c new file mode 100644 index 000000000000..e4a7e692a908 --- /dev/null +++ b/drivers/leds/leds-sun50i-a100.c @@ -0,0 +1,580 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021-2023 Samuel Holland + * + * Partly based on drivers/leds/leds-turris-omnia.c, which is: + * Copyright (c) 2020 by Marek BehĂșn + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LEDC_CTRL_REG 0x0000 +#define LEDC_CTRL_REG_DATA_LENGTH GENMASK(28, 16) +#define LEDC_CTRL_REG_RGB_MODE GENMASK(8, 6) +#define LEDC_CTRL_REG_LEDC_EN BIT(0) +#define LEDC_T01_TIMING_CTRL_REG 0x0004 +#define LEDC_T01_TIMING_CTRL_REG_T1H GENMASK(26, 21) +#define LEDC_T01_TIMING_CTRL_REG_T1L GENMASK(20, 16) +#define LEDC_T01_TIMING_CTRL_REG_T0H GENMASK(10, 6) +#define LEDC_T01_TIMING_CTRL_REG_T0L GENMASK(5, 0) +#define LEDC_RESET_TIMING_CTRL_REG 0x000c +#define LEDC_RESET_TIMING_CTRL_REG_TR GENMASK(28, 16) +#define LEDC_RESET_TIMING_CTRL_REG_LED_NUM GENMASK(9, 0) +#define LEDC_DATA_REG 0x0014 +#define LEDC_DMA_CTRL_REG 0x0018 +#define LEDC_DMA_CTRL_REG_DMA_EN BIT(5) +#define LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL GENMASK(4, 0) +#define LEDC_INT_CTRL_REG 0x001c +#define LEDC_INT_CTRL_REG_GLOBAL_INT_EN BIT(5) +#define LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN BIT(1) +#define LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN BIT(0) +#define LEDC_INT_STS_REG 0x0020 +#define LEDC_INT_STS_REG_FIFO_WLW GENMASK(15, 10) +#define LEDC_INT_STS_REG_FIFO_CPUREQ_INT BIT(1) +#define LEDC_INT_STS_REG_TRANS_FINISH_INT BIT(0) + +#define LEDC_FIFO_DEPTH 32U +#define LEDC_MAX_LEDS 1024 +#define LEDC_CHANNELS_PER_LED 3 /* RGB */ + +#define LEDS_TO_BYTES(n) ((n) * sizeof(u32)) + +struct sun50i_a100_ledc_led { + struct led_classdev_mc mc_cdev; + struct mc_subled subled_info[LEDC_CHANNELS_PER_LED]; + u32 addr; +}; + +#define to_ledc_led(mc) container_of(mc, struct sun50i_a100_ledc_led, mc_cdev) + +struct sun50i_a100_ledc_timing { + u32 t0h_ns; + u32 t0l_ns; + u32 t1h_ns; + u32 t1l_ns; + u32 treset_ns; +}; + +struct sun50i_a100_ledc { + struct device *dev; + void __iomem *base; + struct clk *bus_clk; + struct clk *mod_clk; + struct reset_control *reset; + + u32 *buffer; + struct dma_chan *dma_chan; + dma_addr_t dma_handle; + unsigned int pio_length; + unsigned int pio_offset; + + spinlock_t lock; + unsigned int next_length; + bool xfer_active; + + u32 format; + struct sun50i_a100_ledc_timing timing; + + u32 max_addr; + u32 num_leds; + struct sun50i_a100_ledc_led leds[] __counted_by(num_leds); +}; + +static int sun50i_a100_ledc_dma_xfer(struct sun50i_a100_ledc *priv, unsigned int length) +{ + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + + desc = dmaengine_prep_slave_single(priv->dma_chan, priv->dma_handle, + LEDS_TO_BYTES(length), DMA_MEM_TO_DEV, 0); + if (!desc) + return -ENOMEM; + + cookie = dmaengine_submit(desc); + if (dma_submit_error(cookie)) + return -EIO; + + dma_async_issue_pending(priv->dma_chan); + + return 0; +} + +static void sun50i_a100_ledc_pio_xfer(struct sun50i_a100_ledc *priv, unsigned int fifo_used) +{ + unsigned int burst, length, offset; + u32 control; + + length = priv->pio_length; + offset = priv->pio_offset; + burst = min(length, LEDC_FIFO_DEPTH - fifo_used); + + iowrite32_rep(priv->base + LEDC_DATA_REG, priv->buffer + offset, burst); + + if (burst < length) { + priv->pio_length = length - burst; + priv->pio_offset = offset + burst; + + if (!offset) { + control = readl(priv->base + LEDC_INT_CTRL_REG); + control |= LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN; + writel(control, priv->base + LEDC_INT_CTRL_REG); + } + } else { + /* Disable the request IRQ once all data is written. */ + control = readl(priv->base + LEDC_INT_CTRL_REG); + control &= ~LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN; + writel(control, priv->base + LEDC_INT_CTRL_REG); + } +} + +static void sun50i_a100_ledc_start_xfer(struct sun50i_a100_ledc *priv, unsigned int length) +{ + bool use_dma = false; + u32 control; + + if (priv->dma_chan && length > LEDC_FIFO_DEPTH) { + int ret; + + ret = sun50i_a100_ledc_dma_xfer(priv, length); + if (ret) + dev_warn(priv->dev, "Failed to set up DMA (%d), using PIO\n", ret); + else + use_dma = true; + } + + /* The DMA trigger level must be at least the burst length. */ + control = FIELD_PREP(LEDC_DMA_CTRL_REG_DMA_EN, use_dma) | + FIELD_PREP_CONST(LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL, LEDC_FIFO_DEPTH / 2); + writel(control, priv->base + LEDC_DMA_CTRL_REG); + + control = readl(priv->base + LEDC_CTRL_REG); + control &= ~LEDC_CTRL_REG_DATA_LENGTH; + control |= FIELD_PREP(LEDC_CTRL_REG_DATA_LENGTH, length) | LEDC_CTRL_REG_LEDC_EN; + writel(control, priv->base + LEDC_CTRL_REG); + + if (!use_dma) { + /* The FIFO is empty when starting a new transfer. */ + unsigned int fifo_used = 0; + + priv->pio_length = length; + priv->pio_offset = 0; + + sun50i_a100_ledc_pio_xfer(priv, fifo_used); + } +} + +static irqreturn_t sun50i_a100_ledc_irq(int irq, void *data) +{ + struct sun50i_a100_ledc *priv = data; + u32 status; + + status = readl(priv->base + LEDC_INT_STS_REG); + + if (status & LEDC_INT_STS_REG_TRANS_FINISH_INT) { + unsigned int next_length; + + spin_lock(&priv->lock); + + /* If another transfer is queued, dequeue and start it. */ + next_length = priv->next_length; + if (next_length) + priv->next_length = 0; + else + priv->xfer_active = false; + + spin_unlock(&priv->lock); + + if (next_length) + sun50i_a100_ledc_start_xfer(priv, next_length); + } else if (status & LEDC_INT_STS_REG_FIFO_CPUREQ_INT) { + /* Continue the current transfer. */ + sun50i_a100_ledc_pio_xfer(priv, FIELD_GET(LEDC_INT_STS_REG_FIFO_WLW, status)); + } + + /* Clear the W1C status bits. */ + writel(status, priv->base + LEDC_INT_STS_REG); + + return IRQ_HANDLED; +} + +static void sun50i_a100_ledc_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct sun50i_a100_ledc *priv = dev_get_drvdata(cdev->dev->parent); + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct sun50i_a100_ledc_led *led = to_ledc_led(mc_cdev); + unsigned int next_length; + unsigned long flags; + bool xfer_active; + + led_mc_calc_color_components(mc_cdev, brightness); + + priv->buffer[led->addr] = led->subled_info[0].brightness << 16 | + led->subled_info[1].brightness << 8 | + led->subled_info[2].brightness; + + spin_lock_irqsave(&priv->lock, flags); + + /* Start, enqueue, or extend an enqueued transfer, as appropriate. */ + next_length = max(priv->next_length, led->addr + 1); + xfer_active = priv->xfer_active; + if (xfer_active) + priv->next_length = next_length; + else + priv->xfer_active = true; + + spin_unlock_irqrestore(&priv->lock, flags); + + if (!xfer_active) + sun50i_a100_ledc_start_xfer(priv, next_length); +} + +static const char *const sun50i_a100_ledc_formats[] = { + "rgb", "rbg", "grb", "gbr", "brg", "bgr", +}; + +static int sun50i_a100_ledc_parse_format(const struct device_node *np, + struct sun50i_a100_ledc *priv) +{ + const char *format = "grb"; + u32 i; + + of_property_read_string(np, "allwinner,pixel-format", &format); + + for (i = 0; i < ARRAY_SIZE(sun50i_a100_ledc_formats); i++) { + if (!strcmp(format, sun50i_a100_ledc_formats[i])) { + priv->format = i; + return 0; + } + } + + return dev_err_probe(priv->dev, -EINVAL, "Bad pixel format '%s'\n", format); +} + +static void sun50i_a100_ledc_set_format(struct sun50i_a100_ledc *priv) +{ + u32 control; + + control = readl(priv->base + LEDC_CTRL_REG); + control &= ~LEDC_CTRL_REG_RGB_MODE; + control |= FIELD_PREP(LEDC_CTRL_REG_RGB_MODE, priv->format); + writel(control, priv->base + LEDC_CTRL_REG); +} + +static const struct sun50i_a100_ledc_timing sun50i_a100_ledc_default_timing = { + .t0h_ns = 336, + .t0l_ns = 840, + .t1h_ns = 882, + .t1l_ns = 294, + .treset_ns = 300000, +}; + +static int sun50i_a100_ledc_parse_timing(const struct device_node *np, + struct sun50i_a100_ledc *priv) +{ + struct sun50i_a100_ledc_timing *timing = &priv->timing; + + *timing = sun50i_a100_ledc_default_timing; + + of_property_read_u32(np, "allwinner,t0h-ns", &timing->t0h_ns); + of_property_read_u32(np, "allwinner,t0l-ns", &timing->t0l_ns); + of_property_read_u32(np, "allwinner,t1h-ns", &timing->t1h_ns); + of_property_read_u32(np, "allwinner,t1l-ns", &timing->t1l_ns); + of_property_read_u32(np, "allwinner,treset-ns", &timing->treset_ns); + + return 0; +} + +static void sun50i_a100_ledc_set_timing(struct sun50i_a100_ledc *priv) +{ + const struct sun50i_a100_ledc_timing *timing = &priv->timing; + unsigned long mod_freq = clk_get_rate(priv->mod_clk); + u32 cycle_ns = NSEC_PER_SEC / mod_freq; + u32 control; + + control = FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T1H, timing->t1h_ns / cycle_ns) | + FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T1L, timing->t1l_ns / cycle_ns) | + FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T0H, timing->t0h_ns / cycle_ns) | + FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T0L, timing->t0l_ns / cycle_ns); + writel(control, priv->base + LEDC_T01_TIMING_CTRL_REG); + + control = FIELD_PREP(LEDC_RESET_TIMING_CTRL_REG_TR, timing->treset_ns / cycle_ns) | + FIELD_PREP(LEDC_RESET_TIMING_CTRL_REG_LED_NUM, priv->max_addr); + writel(control, priv->base + LEDC_RESET_TIMING_CTRL_REG); +} + +static int sun50i_a100_ledc_resume(struct device *dev) +{ + struct sun50i_a100_ledc *priv = dev_get_drvdata(dev); + int ret; + + ret = reset_control_deassert(priv->reset); + if (ret) + return ret; + + ret = clk_prepare_enable(priv->bus_clk); + if (ret) + goto err_assert_reset; + + ret = clk_prepare_enable(priv->mod_clk); + if (ret) + goto err_disable_bus_clk; + + sun50i_a100_ledc_set_format(priv); + sun50i_a100_ledc_set_timing(priv); + + writel(LEDC_INT_CTRL_REG_GLOBAL_INT_EN | LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN, + priv->base + LEDC_INT_CTRL_REG); + + return 0; + +err_disable_bus_clk: + clk_disable_unprepare(priv->bus_clk); +err_assert_reset: + reset_control_assert(priv->reset); + + return ret; +} + +static int sun50i_a100_ledc_suspend(struct device *dev) +{ + struct sun50i_a100_ledc *priv = dev_get_drvdata(dev); + + /* Wait for all transfers to complete. */ + for (;;) { + unsigned long flags; + bool xfer_active; + + spin_lock_irqsave(&priv->lock, flags); + xfer_active = priv->xfer_active; + spin_unlock_irqrestore(&priv->lock, flags); + if (!xfer_active) + break; + + msleep(1); + } + + clk_disable_unprepare(priv->mod_clk); + clk_disable_unprepare(priv->bus_clk); + reset_control_assert(priv->reset); + + return 0; +} + +static void sun50i_a100_ledc_dma_cleanup(void *data) +{ + struct sun50i_a100_ledc *priv = data; + + dma_release_channel(priv->dma_chan); +} + +static int sun50i_a100_ledc_probe(struct platform_device *pdev) +{ + const struct device_node *np = pdev->dev.of_node; + struct dma_slave_config dma_cfg = {}; + struct led_init_data init_data = {}; + struct sun50i_a100_ledc_led *led; + struct device *dev = &pdev->dev; + struct sun50i_a100_ledc *priv; + struct device_node *child; + struct resource *mem; + u32 max_addr = 0; + u32 num_leds = 0; + int irq, ret; + + /* + * The maximum LED address must be known in sun50i_a100_ledc_resume() before + * class device registration, so parse and validate the subnodes up front. + */ + for_each_available_child_of_node(np, child) { + u32 addr, color; + + ret = of_property_read_u32(child, "reg", &addr); + if (ret || addr >= LEDC_MAX_LEDS) { + of_node_put(child); + return dev_err_probe(dev, -EINVAL, "'reg' must be between 0 and %d\n", + LEDC_MAX_LEDS - 1); + } + + ret = of_property_read_u32(child, "color", &color); + if (ret || color != LED_COLOR_ID_RGB) { + of_node_put(child); + return dev_err_probe(dev, -EINVAL, "'color' must be LED_COLOR_ID_RGB\n"); + } + + max_addr = max(max_addr, addr); + num_leds++; + } + + if (!num_leds) + return -ENODEV; + + priv = devm_kzalloc(dev, struct_size(priv, leds, num_leds), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->max_addr = max_addr; + priv->num_leds = num_leds; + spin_lock_init(&priv->lock); + dev_set_drvdata(dev, priv); + + ret = sun50i_a100_ledc_parse_format(np, priv); + if (ret) + return ret; + + ret = sun50i_a100_ledc_parse_timing(np, priv); + if (ret) + return ret; + + priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->bus_clk = devm_clk_get(dev, "bus"); + if (IS_ERR(priv->bus_clk)) + return PTR_ERR(priv->bus_clk); + + priv->mod_clk = devm_clk_get(dev, "mod"); + if (IS_ERR(priv->mod_clk)) + return PTR_ERR(priv->mod_clk); + + priv->reset = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->dma_chan = dma_request_chan(dev, "tx"); + if (IS_ERR(priv->dma_chan)) { + if (PTR_ERR(priv->dma_chan) != -ENODEV) + return PTR_ERR(priv->dma_chan); + + priv->dma_chan = NULL; + + priv->buffer = devm_kzalloc(dev, LEDS_TO_BYTES(LEDC_MAX_LEDS), GFP_KERNEL); + if (!priv->buffer) + return -ENOMEM; + } else { + ret = devm_add_action_or_reset(dev, sun50i_a100_ledc_dma_cleanup, priv); + if (ret) + return ret; + + dma_cfg.dst_addr = mem->start + LEDC_DATA_REG; + dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_cfg.dst_maxburst = LEDC_FIFO_DEPTH / 2; + + ret = dmaengine_slave_config(priv->dma_chan, &dma_cfg); + if (ret) + return ret; + + priv->buffer = dmam_alloc_attrs(dmaengine_get_dma_device(priv->dma_chan), + LEDS_TO_BYTES(LEDC_MAX_LEDS), &priv->dma_handle, + GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); + if (!priv->buffer) + return -ENOMEM; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(dev, irq, sun50i_a100_ledc_irq, 0, dev_name(dev), priv); + if (ret) + return ret; + + ret = sun50i_a100_ledc_resume(dev); + if (ret) + return ret; + + led = priv->leds; + for_each_available_child_of_node(np, child) { + struct led_classdev *cdev; + + /* The node was already validated above. */ + of_property_read_u32(child, "reg", &led->addr); + + led->subled_info[0].color_index = LED_COLOR_ID_RED; + led->subled_info[0].channel = 0; + led->subled_info[1].color_index = LED_COLOR_ID_GREEN; + led->subled_info[1].channel = 1; + led->subled_info[2].color_index = LED_COLOR_ID_BLUE; + led->subled_info[2].channel = 2; + + led->mc_cdev.num_colors = ARRAY_SIZE(led->subled_info); + led->mc_cdev.subled_info = led->subled_info; + + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness = U8_MAX; + cdev->brightness_set = sun50i_a100_ledc_brightness_set; + + init_data.fwnode = of_fwnode_handle(child); + + ret = led_classdev_multicolor_register_ext(dev, &led->mc_cdev, &init_data); + if (ret) { + dev_err_probe(dev, ret, "Failed to register multicolor LED %u", led->addr); + goto err_put_child; + } + + led++; + } + + dev_info(dev, "Registered %u LEDs\n", num_leds); + + return 0; + +err_put_child: + of_node_put(child); + while (led-- > priv->leds) + led_classdev_multicolor_unregister(&led->mc_cdev); + sun50i_a100_ledc_suspend(&pdev->dev); + + return ret; +} + +static void sun50i_a100_ledc_remove(struct platform_device *pdev) +{ + struct sun50i_a100_ledc *priv = platform_get_drvdata(pdev); + + for (u32 i = 0; i < priv->num_leds; i++) + led_classdev_multicolor_unregister(&priv->leds[i].mc_cdev); + sun50i_a100_ledc_suspend(&pdev->dev); +} + +static const struct of_device_id sun50i_a100_ledc_of_match[] = { + { .compatible = "allwinner,sun50i-a100-ledc" }, + {} +}; +MODULE_DEVICE_TABLE(of, sun50i_a100_ledc_of_match); + +static DEFINE_SIMPLE_DEV_PM_OPS(sun50i_a100_ledc_pm, + sun50i_a100_ledc_suspend, + sun50i_a100_ledc_resume); + +static struct platform_driver sun50i_a100_ledc_driver = { + .probe = sun50i_a100_ledc_probe, + .remove_new = sun50i_a100_ledc_remove, + .shutdown = sun50i_a100_ledc_remove, + .driver = { + .name = "sun50i-a100-ledc", + .of_match_table = sun50i_a100_ledc_of_match, + .pm = pm_ptr(&sun50i_a100_ledc_pm), + }, +}; +module_platform_driver(sun50i_a100_ledc_driver); + +MODULE_AUTHOR("Samuel Holland "); +MODULE_DESCRIPTION("Allwinner A100 LED controller driver"); +MODULE_LICENSE("GPL"); From patchwork Sun Oct 29 21:26:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 739473 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 946FDC4167B for ; Sun, 29 Oct 2023 21:27:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230388AbjJ2V1w (ORCPT ); Sun, 29 Oct 2023 17:27:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230325AbjJ2V1u (ORCPT ); Sun, 29 Oct 2023 17:27:50 -0400 Received: from out5-smtp.messagingengine.com (out5-smtp.messagingengine.com [66.111.4.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75109C1; Sun, 29 Oct 2023 14:27:48 -0700 (PDT) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id E055F5C0132; Sun, 29 Oct 2023 17:27:47 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Sun, 29 Oct 2023 17:27:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm1; t=1698614867; x= 1698701267; bh=iEJQRW8XFToPuwgph8rKTRMVOhjzZOWs5XTsNlQdUKI=; b=y ZwG9v2PoNbsKRh7ZW+9x4bEOOutmyNp4MzYot7123IKjKsPWq+yyB+NIIQA3E4mT 8tb+G+KrTzwEnmzi375qqbwfKQ2HbFkZL4fg6DNu0Sw0fx6oV+O91LO07QED1U94 8qHKBJE4ujEIytwIG/vpU7Oeqz2jtwqfSNh0bcf+TLYhvRwLOIbaqlsTZaaDEVHN eik/+xpPSNmj2/ZvKUjX4eBBzA0zwo/YA1gDF0iQpwPfcXdDNFt3KeFJsBK731BD umaohYZrPo+/INYurd0RbYn+hjWNpNGYS549pl6aObUT27FspDTv3L8R13Kd/M0P bCr2E5ght93/LdLHs3bHw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1698614867; x= 1698701267; bh=iEJQRW8XFToPuwgph8rKTRMVOhjzZOWs5XTsNlQdUKI=; b=L dTfUGdQhJDft9NEWrDELH1Vu9ex0KCsF9nYXX9EdjiO1BcPTcRDaMwMfv78cFwGX ZRAKUkf71ZM2B8uZT7rmq+8Q0qXkzzORP7MMhkli5fBf8D/BBc++TIn9ivZO2qt2 +bDX3e8dGV3OmnB2FIG5Vu0T4yF9XGDOLKqLRxaDIzBfHqXcl0AjPCnPv0eEMPXK nCkOiA4c/vH+l+a1SPa96XBPTbWkLlf62aTHXsV6z/qx6Ifh5Nxu3+cMNtfCb90E ge42fruG/LA1NBiLdXz+S2WpVLc70Mdum825/MGxB4m8t3jPFraN2tM3dSXt/kP6 0mE5aV+NckYOO2UzSS9kg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrleekgddugeekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomhepufgrmhhu vghlucfjohhllhgrnhguuceoshgrmhhuvghlsehshhholhhlrghnugdrohhrgheqnecugg ftrfgrthhtvghrnhepudekteeuudehtdelteevgfduvddvjefhfedulefgudevgeeghefg udefiedtveetnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrh homhepshgrmhhuvghlsehshhholhhlrghnugdrohhrgh X-ME-Proxy: Feedback-ID: i0ad843c9:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 29 Oct 2023 17:27:46 -0400 (EDT) From: Samuel Holland To: Lee Jones , Pavel Machek , linux-leds@vger.kernel.org, Chen-Yu Tsai , Jernej Skrabec Cc: Samuel Holland , Andre Przywara , Conor Dooley , Cristian Ciocaltea , Guo Ren , Jisheng Zhang , John Watts , Krzysztof Kozlowski , Maksim Kiselev , Marc Kleine-Budde , Palmer Dabbelt , Philipp Zabel , Rob Herring , Trevor Woerner , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v8 3/5] arm64: dts: allwinner: a100: Add LED controller node Date: Sun, 29 Oct 2023 16:26:57 -0500 Message-ID: <20231029212738.7871-4-samuel@sholland.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231029212738.7871-1-samuel@sholland.org> References: <20231029212738.7871-1-samuel@sholland.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Allwinner A100 contains an LED controller. Add it to the devicetree. Acked-by: Guo Ren Reviewed-by: Jernej Skrabec Signed-off-by: Samuel Holland --- (no changes since v5) Changes in v5: - New patch for v5 arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi index a3dccf193765..037750d383f8 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi @@ -273,6 +273,20 @@ i2c3: i2c@5002c00 { #size-cells = <0>; }; + ledc: led-controller@5018000 { + compatible = "allwinner,sun50i-a100-ledc"; + reg = <0x5018000 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_LEDC>, <&ccu CLK_LEDC>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_LEDC>; + dmas = <&dma 42>; + dma-names = "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + ths: thermal-sensor@5070400 { compatible = "allwinner,sun50i-a100-ths"; reg = <0x05070400 0x100>; From patchwork Sun Oct 29 21:26:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 739472 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 87FB1C001B0 for ; Sun, 29 Oct 2023 21:27:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230426AbjJ2V1y (ORCPT ); Sun, 29 Oct 2023 17:27:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52216 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229533AbjJ2V1w (ORCPT ); Sun, 29 Oct 2023 17:27:52 -0400 Received: from out5-smtp.messagingengine.com (out5-smtp.messagingengine.com [66.111.4.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1FB97C2; Sun, 29 Oct 2023 14:27:50 -0700 (PDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 8AF385C0195; Sun, 29 Oct 2023 17:27:49 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sun, 29 Oct 2023 17:27:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm1; t=1698614869; x= 1698701269; bh=Uya9a1BC8Na+HTXRovX+d1wlxedeh/xYXLNyXbjnaHM=; b=y dWKhjeQxRnwmMJYv55er3v5Qoa0/lM+Co29bHkbHbOo2eqX17zLXz0c6s8ACNPOt 0qCBF0sacmwhDJLgTOQlQyAk4wrtbv3gmKrTru6PTBS4mSxIEMijMu3XzW9/YF+p 6SDXSHoliYPKpVn+XMCC3Nqlx8VhzfLLNiQVpO94Uv3x0Okvlyho8JCXvOUqsqKX SA0Myc/m2N3rF8FNr4W+LCQs6Hbc/CGHPM+McEdGujp+D6DSJQHIUqiVmUlZDSiM LiW5DxwrsERChLz9y0VW41F4J18hCep5XIPoMa5cpHWfYK2JRx3LZIq4ajef5lXm jPi/bCTKTgysCXR8KQxSw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1698614869; x= 1698701269; bh=Uya9a1BC8Na+HTXRovX+d1wlxedeh/xYXLNyXbjnaHM=; b=J Nui7if+5+cA+svFA2HPLjpncsOngAA5fXHBU+hpTjvL1gooPSRfTuV+r0nWWvS+M qKpLy1EbVD6cXqJEEw6c6ZC1sA7VaAxlDD1oSqlXF+ghpa+BUiQmprcFrlxqXyAC btit2xqCA1tf0cYJYM/Xx6Dw/U7nstM6paoMw5TAB5Ii1w84ksxfFyVGawZN24w7 Gn7G/aVi7Z07XrXA1OZvARC7xujhwuqqa/NQO5rP76s6xy/yNzUplN0un9rYP5Qm epUZShs5zeq1n2o5pWvWvvij5HYlAJ1bkCYtZqyWY2caSGiQ6qM4TYQCxYYnknWZ 3i4EdgF39xfwsgVLLIWig== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrleekgddugeekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomhepufgrmhhu vghlucfjohhllhgrnhguuceoshgrmhhuvghlsehshhholhhlrghnugdrohhrgheqnecugg ftrfgrthhtvghrnhepudekteeuudehtdelteevgfduvddvjefhfedulefgudevgeeghefg udefiedtveetnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrh homhepshgrmhhuvghlsehshhholhhlrghnugdrohhrgh X-ME-Proxy: Feedback-ID: i0ad843c9:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 29 Oct 2023 17:27:48 -0400 (EDT) From: Samuel Holland To: Lee Jones , Pavel Machek , linux-leds@vger.kernel.org, Chen-Yu Tsai , Jernej Skrabec Cc: Samuel Holland , Andre Przywara , Conor Dooley , Cristian Ciocaltea , Guo Ren , Jisheng Zhang , John Watts , Krzysztof Kozlowski , Maksim Kiselev , Marc Kleine-Budde , Palmer Dabbelt , Philipp Zabel , Rob Herring , Trevor Woerner , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v8 4/5] riscv: dts: allwinner: d1: Add LED controller node Date: Sun, 29 Oct 2023 16:26:58 -0500 Message-ID: <20231029212738.7871-5-samuel@sholland.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231029212738.7871-1-samuel@sholland.org> References: <20231029212738.7871-1-samuel@sholland.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Allwinner D1 contains an LED controller. Add its devicetree node, as well as the pinmux used by the reference board design. Acked-by: Guo Ren Reviewed-by: Jernej Skrabec Tested-by: Trevor Woerner Signed-off-by: Samuel Holland --- (no changes since v5) Changes in v5: - New patch for v5 arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 6 ++++++ arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi index b18f368e06e0..b0fb0ea377bc 100644 --- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi +++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi @@ -58,6 +58,12 @@ i2c2_pb0_pins: i2c2-pb0-pins { function = "i2c2"; }; + /omit-if-no-ref/ + ledc_pc0_pin: ledc-pc0-pin { + pins = "PC0"; + function = "ledc"; + }; + /omit-if-no-ref/ uart0_pb8_pins: uart0-pb8-pins { pins = "PB8", "PB9"; diff --git a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi index 5a9d7f5a75b4..a476b59ba306 100644 --- a/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi +++ b/arch/riscv/boot/dts/allwinner/sunxi-d1s-t113.dtsi @@ -156,6 +156,21 @@ ccu: clock-controller@2001000 { #reset-cells = <1>; }; + ledc: led-controller@2008000 { + compatible = "allwinner,sun20i-d1-ledc", + "allwinner,sun50i-a100-ledc"; + reg = <0x2008000 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_LEDC>, <&ccu CLK_LEDC>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_LEDC>; + dmas = <&dma 42>; + dma-names = "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + gpadc: adc@2009000 { compatible = "allwinner,sun20i-d1-gpadc"; reg = <0x2009000 0x400>; From patchwork Sun Oct 29 21:26:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 739163 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17BABC00142 for ; Sun, 29 Oct 2023 21:27:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230325AbjJ2V17 (ORCPT ); Sun, 29 Oct 2023 17:27:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230422AbjJ2V1x (ORCPT ); Sun, 29 Oct 2023 17:27:53 -0400 Received: from out5-smtp.messagingengine.com (out5-smtp.messagingengine.com [66.111.4.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A992E97; Sun, 29 Oct 2023 14:27:51 -0700 (PDT) Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailout.nyi.internal (Postfix) with ESMTP id 221405C00F5; Sun, 29 Oct 2023 17:27:51 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Sun, 29 Oct 2023 17:27:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm1; t=1698614871; x= 1698701271; bh=pqggGLCwnACae2UnEHHjv/s1fXcJLCQyy4ZCbqoi31o=; b=Z gqMwS2D+kJ4kswoDW9i2nb/5RDjHHQQg/nlgEd+ZmGnvnSfPEq3ES4y4nD1TbFC2 fk/CoxFMftMxtamvIarT2HF1MXgW2vRqFrkprnSsXkfpUB5hm2VBwEhY5oMts6fk 4zLhwSAIAsZCLlJNMVHuBmSc1hle3Oon+3m2xjMeSYL3v3kj56ANZ2ZbGuv1w5oA Ma0vPwUHAfPAiTtRqH0NqrkdtWmA47gFZwirZpl4MZPV7ROWZyno/PLVAfnD4Lsm wxROGu+uMI873u4cbReIwIa5PKA2DCXYZ0krA8IsdoIZ8JetvnOv89oHeX/UcLJ0 WIofRgq9xo3JZFoy9NnFg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1698614871; x= 1698701271; bh=pqggGLCwnACae2UnEHHjv/s1fXcJLCQyy4ZCbqoi31o=; b=t JmCwC8aYLZGOFM9dYO+XRT+YMxeyVgPh1nmN2/K5bCGlXN/NFlsIJcq9Hyf3S8x5 1oHvNdoRcU8JL4W5BtlCKNwtwWW//yz53YCczG2LR7re3TtlT3rSRjb21wC91AF0 +j30s5Czv8ylIRQJ3SXlB8PKxO8iOKjvHppIztWa/GNKq/aWK/mtKlhRyKJpjnJW RYsjlzwef55QiKeto2DCKbLGh9U3/OHFG8s4c7m2LdFUy5PLt3IOXqAvrPOZMmLr NM420mpp94tD41XaMfJdVy7sgqoHpP3fNHf7OaGM38lpBv1n7lNtvb/DY1Bo+yPY hAgDv+JuMEage2Jujp/GA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrleekgddugeekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomhepufgrmhhu vghlucfjohhllhgrnhguuceoshgrmhhuvghlsehshhholhhlrghnugdrohhrgheqnecugg ftrfgrthhtvghrnhepudekteeuudehtdelteevgfduvddvjefhfedulefgudevgeeghefg udefiedtveetnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrh homhepshgrmhhuvghlsehshhholhhlrghnugdrohhrgh X-ME-Proxy: Feedback-ID: i0ad843c9:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 29 Oct 2023 17:27:50 -0400 (EDT) From: Samuel Holland To: Lee Jones , Pavel Machek , linux-leds@vger.kernel.org, Chen-Yu Tsai , Jernej Skrabec Cc: Samuel Holland , Andre Przywara , Conor Dooley , Cristian Ciocaltea , Guo Ren , Jisheng Zhang , John Watts , Krzysztof Kozlowski , Maksim Kiselev , Marc Kleine-Budde , Palmer Dabbelt , Philipp Zabel , Rob Herring , Trevor Woerner , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, linux-sunxi@lists.linux.dev Subject: [PATCH v8 5/5] riscv: dts: allwinner: d1: Add RGB LEDs to boards Date: Sun, 29 Oct 2023 16:26:59 -0500 Message-ID: <20231029212738.7871-6-samuel@sholland.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231029212738.7871-1-samuel@sholland.org> References: <20231029212738.7871-1-samuel@sholland.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Some D1-based boards feature an onboard RGB LED. Enable them. Acked-by: Guo Ren Acked-by: Jernej Skrabec Tested-by: Trevor Woerner Signed-off-by: Samuel Holland --- (no changes since v5) Changes in v5: - New patch for v5 .../boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts | 12 ++++++++++++ arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts index 08cf716328a0..feaa75d5aead 100644 --- a/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts +++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-lichee-rv-dock.dts @@ -59,6 +59,18 @@ &ehci1 { status = "okay"; }; +&ledc { + pinctrl-0 = <&ledc_pc0_pin>; + pinctrl-names = "default"; + status = "okay"; + + multi-led@0 { + reg = <0x0>; + color = ; + function = LED_FUNCTION_STATUS; + }; +}; + &mmc1 { bus-width = <4>; mmc-pwrseq = <&wifi_pwrseq>; diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts index 8dbe717c79ce..73840ea300f0 100644 --- a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts +++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts @@ -22,6 +22,7 @@ #include #include +#include /dts-v1/; @@ -121,6 +122,18 @@ pcf8574a: gpio@38 { }; }; +&ledc { + pinctrl-0 = <&ledc_pc0_pin>; + pinctrl-names = "default"; + status = "okay"; + + multi-led@0 { + reg = <0x0>; + color = ; + function = LED_FUNCTION_STATUS; + }; +}; + &mdio { ext_rgmii_phy: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c22";