From patchwork Tue Apr 14 19:36:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Ford X-Patchwork-Id: 202068 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 854AEC2BB1D for ; Tue, 14 Apr 2020 19:38:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 55E21206E9 for ; Tue, 14 Apr 2020 19:38:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ouFvZ19W" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504932AbgDNThH (ORCPT ); Tue, 14 Apr 2020 15:37:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58702 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S2504928AbgDNThA (ORCPT ); Tue, 14 Apr 2020 15:37:00 -0400 Received: from mail-qt1-x844.google.com (mail-qt1-x844.google.com [IPv6:2607:f8b0:4864:20::844]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A42D2C061A10; Tue, 14 Apr 2020 12:37:00 -0700 (PDT) Received: by mail-qt1-x844.google.com with SMTP id x2so11298160qtr.0; Tue, 14 Apr 2020 12:37:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=/x+59wQD9qt9jVTB3z6iHmEFF7JHhCgx/hYlUVzL/CE=; b=ouFvZ19WZE6FIrXgBiOAvzefMfOTA/9N+8QZJGURxDuyXKcv674CLUt5FLv2dsTSRc JnKnJbJCXwCHCDqlpSXiH+eSPtc8Yd/3mOt2U17swQm/cwdE+XWdXvN/7ZXz8QEGGQIZ 2lVWqWoTovre9qwlQ0YCkY+bHSZ2Ww11doNNQwHZT9BP9VHUqyh7RBlbtotKjtbIQ/vM BEF80jJCX5zlygfAoRXYxh7lVoTURTLzyqhW1tz61uPlglogPsO7S8YnQX4Jiy8m40wP N6FG+By+cWoD7To5sAQO/aFiDF8JP871D1FO0GIM7AVj+N46C0wouexCJpHSs2tbcS0W 3J0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=/x+59wQD9qt9jVTB3z6iHmEFF7JHhCgx/hYlUVzL/CE=; b=CP+LetDqujyEMxFab8O94lWHt4/yvwSs7OL6gG2EY6WkrkIxzMjr12T9UGQ5AwnjLU VBBQKbluHQVokRXdW3fh8KhNIa53fBxvrIa8XuVRiLs5IJZTPR4ffV6kPsLByuDSqbaH P/SbRnqOv9L51/ojHUNQNIMc80PLK6cL+mUhKhSD1wEnUOt21MoJoqOd8Go+r8V+2TVi 3mSnYOS430e3Khbek7IsEA4fMYRzeLyE1iunDQsEEs0hxvad/Escq+YFqnqbRI3oQXZL 8Koyi4H8Qf6rZCYGKHiLaSbb5i6fiGrreh+BEyKs3b8SH2b315J87EXvXTtrx9wufY/0 nEvQ== X-Gm-Message-State: AGi0PuYCquUTBWRKoUcDJz2n81jYDOLMiDYv2SdVv/EcKE62hQYEUZwp M5LhewqR+hoxTkHr7J15OhOAswdC/jY= X-Google-Smtp-Source: APiQypKcNHIW372nQRoj76+O69JmPgnHAWxxkDjPGIyJ8esh/xMgfqvjqK8vvBNsnNBcGYah6Jp2rg== X-Received: by 2002:ac8:51cb:: with SMTP id d11mr17156350qtn.370.1586893019278; Tue, 14 Apr 2020 12:36:59 -0700 (PDT) Received: from localhost.localdomain (c-73-37-219-234.hsd1.mn.comcast.net. [73.37.219.234]) by smtp.gmail.com with ESMTPSA id t15sm11960197qtc.64.2020.04.14.12.36.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Apr 2020 12:36:58 -0700 (PDT) From: Adam Ford To: linux-clk@vger.kernel.org Cc: aford@beaconembedded.com, charles.stevens@logicpd.com, Adam Ford , Michael Turquette , Stephen Boyd , Rob Herring , Marek Vasut , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/3] clk: vc5: Allow Versaclock driver to support multiple instances Date: Tue, 14 Apr 2020 14:36:14 -0500 Message-Id: <20200414193616.1368209-1-aford173@gmail.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Currently, the Versaclock driver is only expecting one instance and uses hard-coded names for the various clock names. Unfortunately, this is a problem when there is more than one instance of the driver, because the subsequent instantiations of the driver use the identical name. Each clock after the fist fails to load, because the clock subsystem cannot handle two clocks with identical name. This patch removes the hard-coded name arrays and uses kasprintf to assign clock names based on names of their respective node and parent node which gives each clock a unique identifying name. For a verasaclock node with a name like: versaclock5: versaclock_som@6a The updated clock names would appear like: versaclock_som.mux versaclock_som.out0_sel_i2cb versaclock_som.pfd versaclock_som.pll versaclock_som.fod3 versaclock_som.out4 versaclock_som.fod2 versaclock_som.out3 versaclock_som.fod1 versaclock_som.out2 versaclock_som.fod0 versaclock_som.out1 Signed-off-by: Adam Ford diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index fa96659f8023..6e4b09f1f074 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -161,30 +161,6 @@ struct vc5_driver_data { struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; }; -static const char * const vc5_mux_names[] = { - "mux" -}; - -static const char * const vc5_dbl_names[] = { - "dbl" -}; - -static const char * const vc5_pfd_names[] = { - "pfd" -}; - -static const char * const vc5_pll_names[] = { - "pll" -}; - -static const char * const vc5_fod_names[] = { - "fod0", "fod1", "fod2", "fod3", -}; - -static const char * const vc5_clk_out_names[] = { - "out0_sel_i2cb", "out1", "out2", "out3", "out4", -}; - /* * VersaClock5 i2c regmap */ @@ -750,12 +726,13 @@ static int vc5_probe(struct i2c_client *client, return -EINVAL; } - init.name = vc5_mux_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node); init.ops = &vc5_mux_ops; init.flags = 0; init.parent_names = parent_names; vc5->clk_mux.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); goto err_clk; @@ -764,13 +741,16 @@ static int vc5_probe(struct i2c_client *client, if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) { /* Register frequency doubler */ memset(&init, 0, sizeof(init)); - init.name = vc5_dbl_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl", + client->dev.of_node); init.ops = &vc5_dbl_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_mux_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mux); init.num_parents = 1; vc5->clk_mul.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); @@ -780,16 +760,18 @@ static int vc5_probe(struct i2c_client *client, /* Register PFD */ memset(&init, 0, sizeof(init)); - init.name = vc5_pfd_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node); init.ops = &vc5_pfd_ops; init.flags = CLK_SET_RATE_PARENT; + init.parent_names = parent_names; if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) - init.parent_names = vc5_dbl_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mul); else - init.parent_names = vc5_mux_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mux); init.num_parents = 1; vc5->clk_pfd.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); goto err_clk; @@ -797,15 +779,17 @@ static int vc5_probe(struct i2c_client *client, /* Register PLL */ memset(&init, 0, sizeof(init)); - init.name = vc5_pll_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node); init.ops = &vc5_pll_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_pfd_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_pfd); init.num_parents = 1; vc5->clk_pll.num = 0; vc5->clk_pll.vc5 = vc5; vc5->clk_pll.hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); goto err_clk; @@ -815,15 +799,18 @@ static int vc5_probe(struct i2c_client *client, for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) { idx = vc5_map_index_to_output(vc5->chip_info->model, n); memset(&init, 0, sizeof(init)); - init.name = vc5_fod_names[idx]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d", + client->dev.of_node, idx); init.ops = &vc5_fod_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_pll_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_pll.hw); init.num_parents = 1; vc5->clk_fod[n].num = idx; vc5->clk_fod[n].vc5 = vc5; vc5->clk_fod[n].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); @@ -833,15 +820,18 @@ static int vc5_probe(struct i2c_client *client, /* Register MUX-connected OUT0_I2C_SELB output */ memset(&init, 0, sizeof(init)); - init.name = vc5_clk_out_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb", + client->dev.of_node); init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_mux_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mux); init.num_parents = 1; vc5->clk_out[0].num = idx; vc5->clk_out[0].vc5 = vc5; vc5->clk_out[0].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); @@ -851,14 +841,15 @@ static int vc5_probe(struct i2c_client *client, /* Register FOD-connected OUTx outputs */ for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) { idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1); - parent_names[0] = vc5_fod_names[idx]; + parent_names[0] = clk_hw_get_name(&vc5->clk_fod[idx].hw); if (n == 1) - parent_names[1] = vc5_mux_names[0]; + parent_names[1] = clk_hw_get_name(&vc5->clk_mux); else - parent_names[1] = vc5_clk_out_names[n - 1]; + parent_names[1] = clk_hw_get_name(&vc5->clk_out[n-1].hw); memset(&init, 0, sizeof(init)); - init.name = vc5_clk_out_names[idx + 1]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d", + client->dev.of_node, idx + 1); init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -868,6 +859,7 @@ static int vc5_probe(struct i2c_client *client, vc5->clk_out[n].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); From patchwork Tue Apr 14 19:36:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Adam Ford X-Patchwork-Id: 202067 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BDF1EC3815B for ; Tue, 14 Apr 2020 19:38:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9D4F42074D for ; Tue, 14 Apr 2020 19:38:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="vYrrSX6i" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504927AbgDNTiY (ORCPT ); Tue, 14 Apr 2020 15:38:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S2504929AbgDNThC (ORCPT ); Tue, 14 Apr 2020 15:37:02 -0400 Received: from mail-qk1-x744.google.com (mail-qk1-x744.google.com [IPv6:2607:f8b0:4864:20::744]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A0CB5C061A10; Tue, 14 Apr 2020 12:37:02 -0700 (PDT) Received: by mail-qk1-x744.google.com with SMTP id j4so14623303qkc.11; Tue, 14 Apr 2020 12:37:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Fjl04AvGatFBHs3F8PNak+0QD1cADS1DXagU55OwTUQ=; b=vYrrSX6iKHo+375LeUlauc+9yfd+cy2+mZcXdyJb9JFCH5sGbPKNseAeeaNSDaTvUe 74sGtZyA2XuNV/O/by7jASGq7Wwax6SKW3AAkmWwdo8Ztg792L3v0QPa0NTYIrR6sX9Y ufeZOx/ZidFNjLkTjXxq8GfadKz2FITyeboElMaOCkPSjErVx/JZy2Z/m0fA0ShebKkt OlgWxjpFZz8favxunmaL5uAtUoDmsKrcVtUZ5fwIxLkBTCIn6NOJJjhYgbE+G/WALxOq 43og3ppvNpYUSiyDOQBC2avrr/+HfIKe6FslVl6E/JBQx1s34HoXIkkY5zyEwDqaU5L2 /gwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Fjl04AvGatFBHs3F8PNak+0QD1cADS1DXagU55OwTUQ=; b=GrOIIFZ0fxd/AuiflzQ5XCvKXXHQmSqgddRUr7b5qk1Ocbvt4uOPDK80DAhdJr0nmj gQgFppxK0FEr0qE91CMs09OAOYgLdrzc5Cy9+wnTtsOy3cnhyU6MJYiqFJtjx9soS3Ha oTHdEXxEMhonnHBz3cpR3PecxUGMeZUCFO3yWrIbyFOYTNp52Nsccx6FXJCejgBXwuO5 8MURuUOM+P1TF0UR1onuvAfem8M8dPJZxIP/eUursUf6hk+GdpheBUsyAwqtcI80EVPE jZ29jaZA8B+zQh0ykBjMpVGX3/S8PlvDn5alGXbhjlJ/uv52mCaqf1q12NtukdtYUMex zsfQ== X-Gm-Message-State: AGi0PuZDBaEkDO7UR/smxqJ/c0lwm9K38FFcSDS0M7HI/1FsUA+mB560 Hx1BILhcT8Bmfunh9wjNUWP632z18dM= X-Google-Smtp-Source: APiQypKT/2xifUqJEDMjmJ3zkyuIFDEixFL+aFsuWFlDc0qW731t9b6jgeTEeHlmy3FlokbDLqhLlw== X-Received: by 2002:a37:a3d8:: with SMTP id m207mr3185830qke.371.1586893021348; Tue, 14 Apr 2020 12:37:01 -0700 (PDT) Received: from localhost.localdomain (c-73-37-219-234.hsd1.mn.comcast.net. [73.37.219.234]) by smtp.gmail.com with ESMTPSA id t15sm11960197qtc.64.2020.04.14.12.36.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Apr 2020 12:37:00 -0700 (PDT) From: Adam Ford To: linux-clk@vger.kernel.org Cc: aford@beaconembedded.com, charles.stevens@logicpd.com, Adam Ford , Michael Turquette , Stephen Boyd , Rob Herring , Marek Vasut , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/3] clk: vc5: Enable addition output configurations of the Versaclock Date: Tue, 14 Apr 2020 14:36:15 -0500 Message-Id: <20200414193616.1368209-2-aford173@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200414193616.1368209-1-aford173@gmail.com> References: <20200414193616.1368209-1-aford173@gmail.com> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The existing driver is expecting the Versaclock to be pre-programmed, and only sets the output frequency. Unfortunately, not all devices are pre-programmed, and the Versaclock chip has more options beyond just the frequency. This patch enables the following additional features: - Programmable voltage: 1.8V, 2.5V, or 3.3V​ - Slew Percentage of normal: 85%, 90%, or 100% - Output Type: LVPECL, CMOS, HCSL, or LVDS Signed-off-by: Adam Ford diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 6e4b09f1f074..a1da88baf28c 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -24,6 +24,8 @@ #include #include +#include + /* VersaClock5 registers */ #define VC5_OTP_CONTROL 0x00 @@ -89,6 +91,28 @@ /* Clock control register for clock 1,2 */ #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n)) +#define VC5_CLK_OUTPUT_CFG0_CFG_SHIFT 5 +#define VC5_CLK_OUTPUT_CFG0_CFG_MASK GENMASK(7, VC5_CLK_OUTPUT_CFG0_CFG_SHIFT) + +#define VC5_CLK_OUTPUT_CFG0_CFG_LVPECL (VC5_LVPECL) +#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS (VC5_CMOS) +#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL33 (VC5_HCSL33) +#define VC5_CLK_OUTPUT_CFG0_CFG_LVDS (VC5_LVDS) +#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS2 (VC5_CMOS2) +#define VC5_CLK_OUTPUT_CFG0_CFG_CMOSD (VC5_CMOSD) +#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL25 (VC5_HCSL25) + +#define VC5_CLK_OUTPUT_CFG0_PWR_SHIFT 3 +#define VC5_CLK_OUTPUT_CFG0_PWR_MASK GENMASK(4, VC5_CLK_OUTPUT_CFG0_PWR_SHIFT) +#define VC5_CLK_OUTPUT_CFG0_PWR_18 (0<regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), VC5_CLK_OUTPUT_CFG1_EN_CLKBUF, VC5_CLK_OUTPUT_CFG1_EN_CLKBUF); + if (hwdata->clk_output_cfg0_mask) { + dev_dbg(&vc5->client->dev, "Update output %d mask 0x%0X val 0x%0X\n", + hwdata->num, hwdata->clk_output_cfg0_mask, + hwdata->clk_output_cfg0); + + regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 0), + hwdata->clk_output_cfg0_mask, + hwdata->clk_output_cfg0); + } + return 0; } @@ -675,6 +711,9 @@ static int vc5_probe(struct i2c_client *client, struct clk_init_data init; const char *parent_names[2]; unsigned int n, idx = 0; + u32 value; + struct device_node *np_output; + char *child_name; int ret; vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL); @@ -865,6 +904,77 @@ static int vc5_probe(struct i2c_client *client, init.name); goto err_clk; } + + /* Fetch Clock Output configuration from DT (if specified) */ + child_name = kasprintf(GFP_KERNEL, "OUT%d", n); + np_output = of_get_child_by_name(client->dev.of_node, child_name); + kfree(child_name); + if (!np_output) + continue; + if (!(ret || of_property_read_u32(np_output, + "idt,mode", &value))) { + vc5->clk_out[n].clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_CFG_MASK; + switch (value) { + case VC5_CLK_OUTPUT_CFG0_CFG_LVPECL: + case VC5_CLK_OUTPUT_CFG0_CFG_CMOS: + case VC5_CLK_OUTPUT_CFG0_CFG_HCSL33: + case VC5_CLK_OUTPUT_CFG0_CFG_LVDS: + case VC5_CLK_OUTPUT_CFG0_CFG_CMOS2: + case VC5_CLK_OUTPUT_CFG0_CFG_CMOSD: + case VC5_CLK_OUTPUT_CFG0_CFG_HCSL25: + vc5->clk_out[n].clk_output_cfg0 |= value << VC5_CLK_OUTPUT_CFG0_CFG_SHIFT; + break; + default: + ret = -EINVAL; + break; + } + } + if (!(ret || of_property_read_u32(np_output, + "idt,voltage-microvolts", &value))) { + vc5->clk_out[n].clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_PWR_MASK; + switch (value) { + case 1800000: + vc5->clk_out[n].clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_18; + break; + case 2500000: + vc5->clk_out[n].clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_25; + break; + case 3300000: + vc5->clk_out[n].clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_33; + break; + default: + ret = -EINVAL; + break; + } + } + if (!(ret || of_property_read_u32(np_output, + "idt,slew-percent", &value))) { + vc5->clk_out[n].clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_SLEW_MASK; + switch (value) { + case 80: + vc5->clk_out[n].clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_80; + break; + case 85: + vc5->clk_out[n].clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_85; + break; + case 90: + vc5->clk_out[n].clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_90; + break; + case 100: + vc5->clk_out[n].clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_100; + break; + default: + ret = -EINVAL; + break; + } + } + of_node_put(np_output); + if (ret) { + dev_err(&client->dev, + "Invalid clock output configuration OUT%d\n", + n); + goto err_clk; + } } ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5); diff --git a/include/dt-bindings/clk/versaclock.h b/include/dt-bindings/clk/versaclock.h new file mode 100644 index 000000000000..30add3488713 --- /dev/null +++ b/include/dt-bindings/clk/versaclock.h @@ -0,0 +1,13 @@ +/* HEADER */ + +/* This file defines field values used by the versaclock 6 family + * for defining output type + */ + +#define VC5_LVPECL 0 +#define VC5_CMOS 1 +#define VC5_HCSL33 2 +#define VC5_LVDS 3 +#define VC5_CMOS2 4 +#define VC5_CMOSD 5 +#define VC5_HCSL25 6