Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp4828116imm; Wed, 30 May 2018 12:51:09 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLOWbNFLgoCYpSGH/FhEW9fmkPQ5yDM6Mhp2PX+8kvTrGu1Bsf1OZ2jY4FnkXV55DnF9U+1 X-Received: by 2002:a17:902:3381:: with SMTP id b1-v6mr4108701plc.248.1527709869086; Wed, 30 May 2018 12:51:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527709869; cv=none; d=google.com; s=arc-20160816; b=nWC/Sy7lP5roikfOIRlYnTg+G7VhGX3yP262rOQ2/uOJcZX47H9N3YyJkm48jhzKif mDuN2QMxvCZxOU5PLsChW7tKh4tNVw6qWtoyx+zcDMJVZqm4eraodhC39Z9xLqFV0wl/ MBftPJ2ozHb/KssGFLvgu3rvAchkXmI980z2TdPLvNsMgvxWWZE0Pb8oJMiP/9Cnlp6A IU3OLc7uyQyH82qW0HvgSok+LMU5eS365n0+CX8tH8WRB7xdFj3q/J7ThQV+KI0hirBK gVDGe7OXNle9R44WtVNIYgjbQ0XRlq5gPXkCnzgSKo4fHH0hv9U334yIrygze3Fxarbh Nh3g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=G1b+RrAv2o2Dl1S8tx5Wu8I18YY7UbOQzMedrufaWyM=; b=hfZ5kJb2MtY+PdmBEAZFE9JDAHl0Z0nbFaLOPnx2sURptFgmYNMHK+mZtUu08gH9JQ jyuVArxQYxvoTkmvONQAmb5pS+D/Ro1x8hgSGaBJS75ZpgeeOPo173yKZDbg5VNh77cf akR9KR1ukhDCFhZ6tr7DYbXA/r8gefCtzwiv6r1hv3j/OEaUH/q0eMPL66drYFOeUSwk XV70lqAo2YET4vu0a7EU+qCwP+7GYH7J/LP9IXluuxKYa0MDoSunZzgNzZfoHqSGjcT1 ViMO8EgOVRCy49uGEE48Sm3GrkEMZA8PIl4vKcRb+jTKFgmToZcaqQIFBjP9ZiUApXTb Xuow== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=DOzcHqDt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v16-v6si34115557pfm.151.2018.05.30.12.50.55; Wed, 30 May 2018 12:51:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=DOzcHqDt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932173AbeE3Tta (ORCPT + 99 others); Wed, 30 May 2018 15:49:30 -0400 Received: from mail-vk0-f65.google.com ([209.85.213.65]:42900 "EHLO mail-vk0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753556AbeE3Tt1 (ORCPT ); Wed, 30 May 2018 15:49:27 -0400 Received: by mail-vk0-f65.google.com with SMTP id s187-v6so61782vke.9; Wed, 30 May 2018 12:49:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc; bh=G1b+RrAv2o2Dl1S8tx5Wu8I18YY7UbOQzMedrufaWyM=; b=DOzcHqDtgLj3Mbp/C+dBVhiFil+moc+uYT3noEXKIwAeZxuVEMF2z7mtZxL0Mp5XeC 09wWYXoQBI864aNrKUrSBxbzvOsPAUfW+QNEmmKC0vbE+nx2H2wFk6btr31CC9F9VEcT Ibk/RoGm2jnuujjb7KYKZjQYg2BYhTsglCOazK2ZPosgf0EMl4p63IrB5OgLjd1SL3o3 Lrmp0u7S37ZgUJg93bmTamXsuqzy9IFEWnth3Benul5J2vWf9SB5Tn7rF/SwBwQQKTSQ 6qF1DMdExuxMNZQO9IQp9VcVxRVnfJ4tLyoC9RyNOHjU3QrtVLcLkKbOi+V5dtWOelLr 3R7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:sender:in-reply-to:references:from :date:message-id:subject:to:cc; bh=G1b+RrAv2o2Dl1S8tx5Wu8I18YY7UbOQzMedrufaWyM=; b=i+iERuOMGxefjS3ZMXFQIUSa/olsFYaa/wEkYYRvloPu79MbryfA8juUQyrAtF1uoq UzM1lKOs2p4YMrKHaqaBjPzTHBiyswmlOAvJNVFmC7trG6ywazs9FoPFlE38LYMz0pUd HBndOGQDlsg/uls+ccrgxBks+DOwWcZHpe8dIDwZLWGTDMwCWczbqXgh/3BnKJXOWBpQ L+z1VwUSI+xe1l/ntM3jw3wapXn3RlX7HoPrUT1+GqjzETX1NE3buDQ8QPxLkiD1G1Gw gcJ9eZstjyHvSrDrb9xCVeENyi42mTTXRAhUaCRrEg2f+OfhehL+p11xM80M5bcdSSR/ acUw== X-Gm-Message-State: ALKqPwf1edZByxX+jBZTqBF6B+Gm7793Qgxr4lwOTaiHWl4MRYjhqWV7 UwLSiohzXCdsSkE/hXpV6/K3v0UunsEGZY+Zc5o= X-Received: by 2002:a1f:e686:: with SMTP id d128-v6mr2438635vkh.176.1527709766601; Wed, 30 May 2018 12:49:26 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a67:7a0a:0:0:0:0:0 with HTTP; Wed, 30 May 2018 12:49:25 -0700 (PDT) In-Reply-To: <1527154169-32380-6-git-send-email-michel.pollet@bp.renesas.com> References: <1527154169-32380-1-git-send-email-michel.pollet@bp.renesas.com> <1527154169-32380-6-git-send-email-michel.pollet@bp.renesas.com> From: Geert Uytterhoeven Date: Wed, 30 May 2018 21:49:25 +0200 X-Google-Sender-Auth: buKUUg6mU14XJGSumNKiRWKdtD8 Message-ID: Subject: Re: [PATCH v7 5/5] clk: renesas: Renesas R9A06G032 clock driver To: Michel Pollet Cc: Linux-Renesas , Simon Horman , Phil Edworthy , Michel Pollet , Michael Turquette , Stephen Boyd , Rob Herring , Mark Rutland , Geert Uytterhoeven , linux-clk , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , Linux Kernel Mailing List Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Michel, On Thu, May 24, 2018 at 11:28 AM, Michel Pollet wrote: > This provides a clock driver for the Renesas R09A06G032. > This uses a structure derived from both the RCAR gen2 driver as well as > the renesas-cpg-mssr driver. > > Signed-off-by: Michel Pollet Thanks for your patch! > --- /dev/null > +++ b/drivers/clk/renesas/r9a06g032-clocks.c > +/* register/bit pairs are encoded as an uint16_t */ > +static void clk_rdesc_set( > + struct r9a06g032_priv *clocks, > + uint16_t one, unsigned int on) > +{ > + u32 __iomem *reg = ((u32 __iomem *)clocks->reg) + (one >> 5); Do you need the cast? Gcc does support void pointer arithmetic, and treats that like byte pointers. > + u32 val = clk_readl(reg); > + > + val = (val & ~(1U << (one & 0x1f))) | ((!!on) << (one & 0x1f)); > + clk_writel(val, reg); Hence clk_writel(val, clocks->reg + 4 * (one >> 5)); Actually clk_{read,write}l() are deprecated, please use {read,write}l() instead. > +static void r9a06g032_clk_gate_disable(struct clk_hw *hw) > +{ > + struct r9a06g032_clk_gate *g = to_r9a06g032_gate(hw); > + > + if (!g->read_only) > + r9a06g032_clk_gate_set(g->clocks, &g->gate, 0); > + else > + pr_debug("%s %s: disallowed\n", __func__, > + __clk_get_name(hw->clk)); You can print the name of a clock using %pC: pr_debug("%s %pC: disallowed\n", __func__, hw->clk); But I don't think you need the check, cfr. below. > +static struct clk *r9a06g032_register_gate( > + struct r9a06g032_priv *clocks, > + const char *parent_name, > + const struct r9a06g032_clkdesc *desc) > +{ > + struct clk *clk; > + struct r9a06g032_clk_gate *g; > + struct clk_init_data init; > + > + g = kzalloc(sizeof(struct r9a06g032_clk_gate), GFP_KERNEL); > + if (!g) > + return NULL; > + > + init.name = desc->name; > + init.ops = &r9a06g032_clk_gate_ops; > + init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; > + init.parent_names = parent_name ? &parent_name : NULL; > + init.num_parents = parent_name ? 1 : 0; > + > + g->clocks = clocks; > + g->index = desc->index; > + g->gate = desc->gate; > + g->hw.init = &init; > + g->read_only = 0; > + > + clk = clk_register(NULL, &g->hw); > + if (IS_ERR(clk)) { > + kfree(g); > + return NULL; > + } > + /* > + * important here, some clocks are already in use by the CM3, we > + * have to assume they are not Linux's to play with and try to disable > + * at the end of the boot! > + * Therefore we increase the clock usage count by arbitrarily enabling > + * the clock, allowing it to stay untouched at the end of the boot. > + */ > + g->read_only = r9a06g032_clk_gate_is_enabled(&g->hw); Is checking if the clock is enabled the recommended way to find out if a clock is used by the Cortex M3? No need for a table? > + if (g->read_only) > + pr_debug("%s was enabled, making read-only\n", desc->name); You can set init.flags |= CLK_IS_CRITICAL instead of using your own flag. > +static unsigned long r9a06g032_divider_recalc_rate( > + struct clk_hw *hw, > + unsigned long parent_rate) > +{ > + struct r9a06g032_clk_div *clk = to_r9a06g032_divider(hw); > + u32 *reg = ((u32 *)clk->clocks->reg) + clk->reg; Fishy operations on __iomem pointers > + long div = clk_readl(reg); u32 div? > + > + if (div < clk->min) > + div = clk->min; > + else if (div > clk->max) > + div = clk->max; > + return DIV_ROUND_UP(parent_rate, div); > +} > + > +/* > + * Attempts to find a value that is in range of min,max, > + * and if a table of set dividers was specified for this > + * register, try to find the fixed divider that is the closest > + * to the target frequency > + */ > +static long r9a06g032_divider_clamp_div( > + struct r9a06g032_clk_div *clk, > + unsigned long rate, unsigned long prate) > +{ > + /* + 1 to cope with rates that have the remainder dropped */ > + long div = DIV_ROUND_UP(prate, rate + 1); > + int i; unsigned int i > + > + if (div <= clk->min) > + return clk->min; > + if (div >= clk->max) > + return clk->max; > + > + for (i = 0; clk->table_size && i < clk->table_size - 1; i++) { > +static long r9a06g032_divider_round_rate( > + struct clk_hw *hw, unsigned long rate, > + unsigned long *prate) > +{ > + struct r9a06g032_clk_div *clk = to_r9a06g032_divider(hw); > + long div = DIV_ROUND_UP(*prate, rate); > + > + pr_devel("%s %pC %ld (prate %ld) (wanted div %ld)\n", __func__, Ah, you do know about %pC ;-) > + hw->clk, rate, *prate, div); > + pr_devel(" min %d (%ld) max %d (%ld)\n", > + clk->min, DIV_ROUND_UP(*prate, clk->min), > + clk->max, DIV_ROUND_UP(*prate, clk->max)); > + > + div = r9a06g032_divider_clamp_div(clk, rate, *prate); > + /* > + * this is a hack. Currently the serial driver asks for a clock rate > + * that is 16 times the baud rate -- and that is wildly outside the > + * range of the UART divider, somehow there is no provision for that > + * case of 'let the divider as is if outside range'. > + * The serial driver *shouldn't* play with these clocks anyway, there's > + * several uarts attached to this divider, and changing this impacts > + * everyone. Huh? > + */ > + if (clk->index == R9A06G032_DIV_UART) { > + pr_devel("%s div uart hack!\n", __func__); > + return clk_get_rate(hw->clk); > + } > + pr_devel("%s %pC %ld / %ld = %ld\n", __func__, hw->clk, > + *prate, div, DIV_ROUND_UP(*prate, div)); > + return DIV_ROUND_UP(*prate, div); > +} > + > +static int r9a06g032_divider_set_rate( > + struct clk_hw *hw, unsigned long rate, > + unsigned long parent_rate) > +{ > + struct r9a06g032_clk_div *clk = to_r9a06g032_divider(hw); > + /* + 1 to cope with rates that have the remainder dropped */ > + u32 div = DIV_ROUND_UP(parent_rate, rate + 1); > + u32 *reg = ((u32 *)clk->clocks->reg) + clk->reg; > + > + pr_devel("%s %pC rate %ld parent %ld div %d\n", __func__, hw->clk, > + rate, parent_rate, div); > + > + /* > + * Need to write the bit 31 with the divider value to > + * latch it. Technically we should wait until it has been > + * cleared too. > + * TODO: Find whether this callback is sleepable, in case > + * the hardware /does/ require some sort of spinloop here. > + */ > + clk_writel(div | (1U << 31), reg); BIT(31)? > + > + return 0; > +} > +static struct clk *r9a06g032_register_divider( > + struct r9a06g032_priv *clocks, > + const char *parent_name, > + const struct r9a06g032_clkdesc *desc) > +{ > + struct r9a06g032_clk_div *div; > + struct clk *clk; > + struct clk_init_data init; > + int i; unsigned int i; > +static void __init r9a06g032_clocks_init(struct device_node *np) > +{ > + struct r9a06g032_priv *clocks; > + struct clk **clks; > + unsigned int i; > + uint16_t uart_group_sel[2]; > + > + clocks = kzalloc(sizeof(*clocks), GFP_KERNEL); > + clks = kzalloc(R9A06G032_CLOCK_COUNT * sizeof(struct clk *), > + GFP_KERNEL); kcalloc()? Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds