Received: by 2002:a5d:925a:0:0:0:0:0 with SMTP id e26csp706998iol; Thu, 9 Jun 2022 12:10:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx0ybYqjkyjh9wj5gzzr4RkUncljlfaNN0UH/0L9kr3MxS+bmDeYPkPDwy9ay0oOnydvxHB X-Received: by 2002:a17:90a:de15:b0:1df:63dd:9cfc with SMTP id m21-20020a17090ade1500b001df63dd9cfcmr4852511pjv.200.1654801819746; Thu, 09 Jun 2022 12:10:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654801819; cv=none; d=google.com; s=arc-20160816; b=NE1ggqKDsgr2Vueztu3VOW7hCGK2yF+J81eh/ofZDoKPIzoEYb3fmctz+Ia9chUSPL LYfFqFw1XLP8b/XHY+PxAvaQe2oJHtOqviPLBNskXGB+XlxmyCCGdvGUJfmp4cUShGUI W5V/hF5R0uxNPF5Jh62S1qfey1LpX79209Q1Q5AIAqmQWPIG/EJyQH94PVNtnMn2GdHL dzpD9c+C3LzsbOs7GHABjKFN+2EvMNIOhUz5Tktf6NuNTK2870sHpPHynMpXCZeldP3w wm9kb819j//2gdhR6FpcUc7KBO6oKFWPDSQoSkx1xcP2GqURFlWzYLutTz8TjBSG9K0S DTQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=VeJH2GjgTNv55jeCpCfZ1ujKSjcX5p8lHDW19F4+qv0=; b=mCjOL6oYmgMTrMs2/rJygZaMkPXff7Pog+0t0fDkHwptTZw+pvedl1t6OAFqQmpLH5 o2O5p3vtN7ccy6pQAOwIV2ZM9qWDu6ae69lBN5VGYy06e2Oa/10Ez2hZhuSpqrsPwjuh bNCQ/mKLlNiCjQNQEGYXQekNU/BiK5e25GFsAaXKW33e2oo4AaIVg/YwuUPKNkBuIF/X QHHLBP5bweP6Yp5BQ/v/e7u+LVQ+3TNDMbQ8qADprR9NykrFi0g7tOhdLhK9BPlWWGU7 VarNyuEfOP+bvd3ZudtGlPU0bqWveerudx4swsZdUXzTYZcUkFVruwT1lU7Q3B9QnEcy DJBg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=eU51bgef; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 14-20020a63000e000000b003f979ee8706si34990732pga.765.2022.06.09.12.10.06; Thu, 09 Jun 2022 12:10:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=eU51bgef; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344868AbiFIQ6I (ORCPT + 99 others); Thu, 9 Jun 2022 12:58:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53232 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238833AbiFIQ6D (ORCPT ); Thu, 9 Jun 2022 12:58:03 -0400 Received: from mail-ej1-x629.google.com (mail-ej1-x629.google.com [IPv6:2a00:1450:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A65E9BE176; Thu, 9 Jun 2022 09:58:01 -0700 (PDT) Received: by mail-ej1-x629.google.com with SMTP id s12so41485578ejx.3; Thu, 09 Jun 2022 09:58:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=VeJH2GjgTNv55jeCpCfZ1ujKSjcX5p8lHDW19F4+qv0=; b=eU51bgefzD4BjSWwpiGbcxgEQEXO5kaPih1MD0/kJ8dKtUTbxN1L+VPH8x71j31XaQ 215GBGMNb8eotwEdhZpA0DuYQud1RfSg2bN1RSAONgW4D/x21ylx2sAoouEVuqH5kBG5 uCfISMSgZMxlya10bCwA1qOrBD5OxxBHgVqocUc/pQLAeo4as0p9eq6JKTl7y0GnBmyq NCDQl7i7pNzhR7yIIh8sddZilQChCu4q568RtEoo46P+w+xhJTHTcBSN9mSP89ZP7X8W EkbW9sMwsxhAQW6q8zgEqLtlqlZ+9hEBsjW7l4pBijYq8hnVZqhpBfsCJN3buf3UsTpt Pq8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=VeJH2GjgTNv55jeCpCfZ1ujKSjcX5p8lHDW19F4+qv0=; b=rd4rPCQot3aAtdTQhIp2vhlxOz/8nFeRgPgtmvf++rSNTFN1txdh+OA95kdJffN3eP bIACF6kd+ulEB0svU3nXT91T1WrQJVaj7QMpwGrLThz33KFEYCA4pn141+f+W5IcyXB+ xQCmejK8Mvwt46n+4P8xyEXTMqJUYnpJZsmvwc8PBTTVyZwMEeKTVpKRAU+eakINt2pl 65SlrHSDQQUJ5n0QLym3YjcSq80hwvRFf/EyeKPnuIIletRDLLWO2on933ZX/Xm5kLpm zsOKJ2jgg6e37Sowqr7C07wOUTGGu6OdWTytr8H9msUAB5SQx+vXvXElvN9DRlipMyMu nnBg== X-Gm-Message-State: AOAM532HLOV2gI3hqt4pyShwtoqt/8JmYp8os2T+lyu7X1EaoFMDhReZ c0snWnMu47+6fsWOIQVMqS0gZmDTPzFojCEcisw= X-Received: by 2002:a17:906:1193:b0:70d:cf39:a4db with SMTP id n19-20020a170906119300b0070dcf39a4dbmr31577671eja.44.1654793880193; Thu, 09 Jun 2022 09:58:00 -0700 (PDT) MIME-Version: 1.0 References: <20220609162734.1462625-1-jjhiblot@traphandler.com> <20220609162734.1462625-3-jjhiblot@traphandler.com> In-Reply-To: <20220609162734.1462625-3-jjhiblot@traphandler.com> From: Andy Shevchenko Date: Thu, 9 Jun 2022 18:57:24 +0200 Message-ID: Subject: Re: [PATCH v3 2/3] leds: Add driver for the TLC5925 LED controller To: Jean-Jacques Hiblot Cc: Pavel Machek , krzk+dt@kernel.org, Rob Herring , Linux LED Subsystem , devicetree , Linux Kernel Mailing List Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Jun 9, 2022 at 6:30 PM Jean-Jacques Hiblot wrote: > > The TLC5925 is a 16-channels constant-current LED sink driver. > It is controlled via SPI but doesn't offer a register-based interface. > Instead it contains a shift register and latches that convert the > serial input into a parallel output. Can you add Datasheet: tag here with the corresponding URL? Rationale is to get a link to the datasheet by just browsing Git log without browsing the source code, which will benefit via Web UIs. > Signed-off-by: Jean-Jacques Hiblot ... > +#include > +#include > +#include > +#include > +#include > +#include > +#include Keep it sorted? ... > +struct single_led_priv { > + int idx; > + struct led_classdev cdev; For pointer arithmetics it's better to swap these two members. > +}; > + > +struct tlc5925_leds_priv { > + int max_num_leds; > + u8 *state; unsigned long? DECLARE_BITMAP() ? > + spinlock_t lock; > + struct single_led_priv leds[]; > +}; ... > + if (brightness) > + priv->state[index / 8] |= (1 << (index % 8)); > + else > + priv->state[index / 8] &= ~(1 << (index % 8)); assign_bit() ... > + return spi_write(spi, priv->state, priv->max_num_leds / 8); BITS_TO_BYTES() ? ... > + count = device_get_child_node_count(dev); > + if (!count) { > + dev_err(dev, "no led defined.\n"); > + return -ENODEV; return dev_err_probe(...); here and everywhere in ->probe() and Co. > + } ... > + ret = device_property_read_u32_array(dev, "ti,shift-register-length", > + &max_num_leds, 1); Always an array of 1 element? call device_property_read_u32(). ... > + if (max_num_leds % 8) { > + dev_err(dev, "'ti,shift-register-length' must be a multiple of 8\n"); > + return -EINVAL; > + } Is this really fatal? I would rather issue a warning and go on if it has at least 8 there. So the idea is to use a minimum that holds multiple of 8. ... > + /* Assert all the OE/ lines */ > + gpios = devm_gpiod_get_array(dev, "output-enable-b", GPIOD_OUT_LOW); > + if (IS_ERR(gpios)) { > + dev_err(dev, "Unable to get the 'output-enable-b' gpios\n"); > + return PTR_ERR(gpios); > + } You have to use dev_err_probe() here, otherwise it will spam logs a lot in case of deferred probe. ... > + priv->state = devm_kzalloc(dev, DIV_ROUND_UP(max_num_leds, 8), GFP_KERNEL); devm_bitmap_zalloc() ... > + device_for_each_child_node(dev, child) { > + struct led_init_data init_data = {.fwnode = child}; Missed spaces. > + struct led_classdev *cdev; > + u32 idx; > + > + ret = fwnode_property_read_u32_array(child, "reg", &idx, 1); fwnode_property_read_u32() > + if (ret || idx >= max_num_leds) { > + dev_err(dev, "%s: invalid reg value. Ignoring.\n", > + fwnode_get_name(child)); > + fwnode_handle_put(child); > + continue; Either dev_warn + continue, or dev_err + return dev_err_probe(). > + } > + > + count--; > + priv->leds[count].idx = idx; > + cdev = &(priv->leds[count].cdev); > + cdev->brightness = LED_OFF; > + cdev->max_brightness = 1; > + cdev->brightness_set_blocking = tlc5925_brightness_set_blocking; > + > + ret = devm_led_classdev_register_ext(dev, cdev, &init_data); > + if (ret) { Ditto. > + dev_err(dev, "%s: cannot create LED device.\n", > + fwnode_get_name(child)); > + fwnode_handle_put(child); > + continue; > + } > + } ... > +static const struct of_device_id tlc5925_dt_ids[] = { > + { .compatible = "ti,tlc5925", }, > + {}, No comma for terminator entry. > +}; Where is the MODULE_DEVICE_TABLE() for this one? ... > + No need for this blank line. > +module_spi_driver(tlc5925_driver); -- With Best Regards, Andy Shevchenko