From nobody Wed Feb 11 15:25:44 2026 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7750E17BBF for ; Mon, 24 Jun 2024 17:31:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719250276; cv=none; b=rbXmujazmtI7tHCWq6zH5QuTqjjrsXl1kIFq3NjiP0fJiupHUETCsi0xqpc1JsfdgHRIAUll6T1OiRIFyuzyPudhTbM/K7oUG9Ndk8ku73CKa8pj4A5wPkYKO221nO/+JPiMtbZk0SxEkKPFvKPdybekWj1mM67i2iHwQdGlTpQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719250276; c=relaxed/simple; bh=ESiT0v4XPWgKX6yOvx0PCA1YyOo6pgK/BKcUz++fGgw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MVqfZvouXiVWU+5T2UN2URkDkk0hl/o5k/bHxRk6aYxNHFT3NufTlSTyRdORp/msEemuhqqGfUjJQD0OAiDWrH4pW2jMTOI72oAiPv82afwsMWW9G3Y+pEgIQiYkx7PyEjZLmw2pPY6DR6VLteqQIm2tBP3Yi60YU9YHISZiiok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=1lRQq6U1; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="1lRQq6U1" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-42499b98d4cso454815e9.2 for ; Mon, 24 Jun 2024 10:31:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1719250273; x=1719855073; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Nk8NTSSg2UNwZSS0z8KuJvpBdS4vH/E8VAcTr6zFpw4=; b=1lRQq6U1U24WcnKBgOK5f2rJ1tkLyw7mdHQFlmTpnhdUIydS8HNstxbl4lOlev5Z4o OypNBziNEIRM3juIbo3uYmhLgdjc91zW/AXTSvdXFuuVYMcPFjIBh/VnxoUvH2dheWcn 3K3r6ngCjxtpAxHL7ZJJgPHzsoII0QOfUwCv87JRoMNQL5y3LMuPPDGmCox+YkinLrWt a8wRqm7eVTqOrw67ESH5sxWK+zCFrbnBErR26ajqHUCntVMQSSo6WIOuil5eLOMtPxsZ lyZSCfSjv9hdNpo3aDGF7Q9fHHrC2rdMnIpOkVlrTBIhKgWFAEAloLEDe0rv2KNJCFLN X24w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719250273; x=1719855073; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Nk8NTSSg2UNwZSS0z8KuJvpBdS4vH/E8VAcTr6zFpw4=; b=pshMxnk5b/kfuTzkpGa5Fjq6nmoqGpaMtzBQOaMtK08dfIAJnKiOOVyI8kh2ZCyo1U 7oyMkH2pnHuptHclx8t5RHSQdmD1TjLwCvvGoAxXcHiLqT5wgM8bRJlkPNxxa4bLQ3ZY EGbYU8a+2UP2Dbe0PaZSeeH8DzyXIQYdj0jrOYSW1ITfk/ezXrH66dDwZw3vntBqRot/ 3d8NiM2yCdEeBS+Qtlmg5HzIUQuknWnxcJAgTZFNNDx4TA3y7Y5vbzlGwEqdoZq46hwu AUeUr8Nqn/VpnGS4D8+e9BpyWNMROJ4aAGXOhzNSOI0RLgNwtYPG6h5+kJzYAe6o41pF vtAA== X-Forwarded-Encrypted: i=1; AJvYcCXr8HHfEItDdqLVAkGFd9/nQxGl+oHjSfTV7tS9m2Ulo8wTC5VKJtoxUURyficTbBan5W3dJBSQElgJ6Nm19nF6NGw6/FJBCzmOX2EP X-Gm-Message-State: AOJu0YyUQZmirnh6NwtpzVJ3uMtKNadTGtoxVq1nj++RSFPWPMYFCv83 aO3YcKK5NSsqcyZ+fjbcyWGb4syFaDvbn3JV6IF+Ae0FRTmC2R9j520UN718TEM= X-Google-Smtp-Source: AGHT+IEzdlJ7HFwRpLJJZgautx8tzjBGUtxs5fy5hAahIcqiziqFJibaNlYJW9Zd5bqWuU4GuS++yg== X-Received: by 2002:a05:600c:1ca2:b0:424:8e12:9ef3 with SMTP id 5b1f17b1804b1-4248e129f6fmr34103285e9.0.1719250272804; Mon, 24 Jun 2024 10:31:12 -0700 (PDT) Received: from toaster.lan ([2a01:e0a:3c5:5fb1:e4ee:e6f8:8fcc:a63b]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-4247d210ff9sm183742385e9.39.2024.06.24.10.31.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 10:31:12 -0700 (PDT) From: Jerome Brunet To: Jonathan Cameron , Lars-Peter Clausen , Neil Armstrong Cc: Jerome Brunet , Kevin Hilman , linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-iio@vger.kernel.org, Rob Herring , Krzysztof Kozlowski , Conor Dooley Subject: [PATCH 1/2] dt-bindings: iio: frequency: add clock measure support Date: Mon, 24 Jun 2024 19:31:02 +0200 Message-ID: <20240624173105.909554-2-jbrunet@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240624173105.909554-1-jbrunet@baylibre.com> References: <20240624173105.909554-1-jbrunet@baylibre.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Bot: notify Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce new bindings for the clock measure IP found Amlogic SoCs. These new bindings help bring IIO support to AML clock measure. Signed-off-by: Jerome Brunet --- NOTE: #1: Splitting the register space looks odd. This is done to help support future SoCs. From meson8 to sm1, duty register comes first, then the reg space. On s4 and c3, duty comes after the reg space. #2: 'reg' may look like a poor choice of name. This comes from the documentation. - MSR_CLK_REGx for the 'reg' space (x being a number) - MSR_CLK_DUTY for the 'duty' space .../iio/frequency/amlogic,clk-msr-io.yaml | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/frequency/amlogic= ,clk-msr-io.yaml diff --git a/Documentation/devicetree/bindings/iio/frequency/amlogic,clk-ms= r-io.yaml b/Documentation/devicetree/bindings/iio/frequency/amlogic,clk-msr= -io.yaml new file mode 100644 index 000000000000..eeb268b4a607 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/frequency/amlogic,clk-msr-io.ya= ml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/frequency/amlogic,clk-msr-io.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic System Clock Measurer + +description: + Internal clock rate sensor within Amlogic SoCs + +maintainers: + - Neil Armstrong + +properties: + compatible: + enum: + - amlogic,meson8-clk-msr-io + - amlogic,gx-clk-msr-io + - amlogic,axg-clk-msr-io + - amlogic,g12a-clk-msr-io + - amlogic,sm1-clk-msr-io + + reg: + maxItems: 2 + + reg-names: + items: + - const: reg + - const: duty + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - reg-names + +unevaluatedProperties: false + +examples: + - | + clk_msr: rate-sensor@18000 { + compatible =3D "amlogic,axg-clk-msr-io"; + reg =3D <0x18004 0xc>, + <0x18000 0x4>; + reg-names =3D "reg", "duty"; + #io-channel-cells =3D <1>; + }; --=20 2.43.0 From nobody Wed Feb 11 15:25:44 2026 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A08319D8A5 for ; Mon, 24 Jun 2024 17:31:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719250277; cv=none; b=KhW9NiLYNI7j/8qHiSTyOcDWgU8QYoMIWkd/YEuKg3H+8L70/PVx+XsoCKsYeX2wbDv9CVjDtuv7bZ1m32nNa4OG33N14wHWs6TcSNVNY/K+7+JBqjwV9KubC4ugSjfG86OfinawnSIEcmuUvp/L1RyI31WbyAI3yHqwKL+YfEE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719250277; c=relaxed/simple; bh=xOPNZnnN4l9IiDBBQWaVQUddXzvIyX6IwLvRqPfBopQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QFYDHhfdfHTQHQqXbo6Bk0vcpe8OGklODhvxk0cPNwZkE57f5/Yefr2uyehQvI538BlWOyaKiaATusmELnztzUJ1HtMn+OVHS+CDHFCr5IedEAn4sPWRg/gxlOpRZKIbNbY5jP+i2l4ml6LqqATNAmYe6bDtkJX7ULYJYkzKsEA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=CtCqyibD; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="CtCqyibD" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-42198492353so38469865e9.1 for ; Mon, 24 Jun 2024 10:31:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1719250274; x=1719855074; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=EyUzSKKBWAIU7D+W6BU/HhAkpHoZpwJrNeeENeOr2zc=; b=CtCqyibDuRUIHJBHFsDxaWqNh7rxuIU7rQo5fXgKEhPQ1nhK/2Wf6DzDXfBLfDn7tK zSwM0B+Mu3Z2uMdvcgfpUwL95QDkAaoXbSVGLkH9UjuqU/WPrGJv81rUXtNedUVLMjXT rtASs6Ex06nhyqoECYm6gbX6aXDGtSpRE984ZwPKne0W33kFGtRgGzsIMo331B22JnrC xubASwOWKUJV2PSof2qhZJEB/jfhaO89uo4seosQjR3mi9yAXm7s4Ya5dUbiPosD+no5 0hMRQHR72yDa0oKogbNuYYSS2XyZN6wXJ289+4Rvts/UmpMdYB4GNQrotN+T9d00dRD9 vyDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719250274; x=1719855074; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EyUzSKKBWAIU7D+W6BU/HhAkpHoZpwJrNeeENeOr2zc=; b=ZleBInQqOQPPCHwXEE3+zml2yNweA8hKjW0BurF/f90BwNxoRhrjRRJjhbtbAvXvvA yXt3WeY+uP9oypyNzJQb9vldOpe03Knr/dvjxYkRlVSmrp7ZuAjsiZ4VWeBvvd7irdA/ 0e0tugC5yneFQJfIHgOW5ctqxDZLxvXRffYAIcL5kKBX6wInoFeJjRWNG325QheBdaV6 kS3Ia57CQ3eJDm8mlgEo1NBUkX5zGvej+qVZxIXLovmm4n3Vmw4fk8x9tEzBuMqD/b98 UhcBaPM7HqHikXCKe/ZFFAZz4to1nVKzIct3Tb6hUmFJDNQmNcwQa4Xi+JnPUzdcerTD swdA== X-Forwarded-Encrypted: i=1; AJvYcCURhxRlG+z9RPEjUc6EiYy+S3+udiELy94OI2ZFym9OeSfaoiu/1JaegF5irs6TzAznLo8swA8O43VcvYUbs4zH8j8c56xeIn+bwNR8 X-Gm-Message-State: AOJu0YxJWK12mzK/nr6K2r4TWWuVx9lu6aDgC193F/2Kj/uljH1JCey6 ugz43/k+Spkt5G1+GZRHh9xu70oZBYfJ/MQNFd6XMKCssOGIX0fM8Mx98mMbNnQ= X-Google-Smtp-Source: AGHT+IH9Le2Z83zzr03nxEAjY/rvbBfj6K+lspfdVSmGSmUqqLI6jwX/aUNW7OOKMxoc4Nmgu0ezRQ== X-Received: by 2002:a05:600c:1c1e:b0:424:7e1e:9080 with SMTP id 5b1f17b1804b1-4248cc2b868mr38774005e9.13.1719250273696; Mon, 24 Jun 2024 10:31:13 -0700 (PDT) Received: from toaster.lan ([2a01:e0a:3c5:5fb1:e4ee:e6f8:8fcc:a63b]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-4247d210ff9sm183742385e9.39.2024.06.24.10.31.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 10:31:13 -0700 (PDT) From: Jerome Brunet To: Jonathan Cameron , Lars-Peter Clausen , Neil Armstrong Cc: Jerome Brunet , Kevin Hilman , linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-iio@vger.kernel.org, Rob Herring , Krzysztof Kozlowski , Conor Dooley Subject: [PATCH 2/2] iio: frequency: add amlogic clock measure support Date: Mon, 24 Jun 2024 19:31:03 +0200 Message-ID: <20240624173105.909554-3-jbrunet@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240624173105.909554-1-jbrunet@baylibre.com> References: <20240624173105.909554-1-jbrunet@baylibre.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Bot: notify Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for the HW found in most Amlogic SoC dedicated to measure system clocks. This drivers aims to replace the one found in drivers/soc/amlogic/meson-clk-measure.c with following improvements: * Access to the measurements through the IIO API: Easier re-use of the results in userspace and other drivers * Controllable scale with raw measurements * Higher precision with processed measurements Signed-off-by: Jerome Brunet --- drivers/iio/frequency/Kconfig | 15 + drivers/iio/frequency/Makefile | 1 + drivers/iio/frequency/amlogic-clk-msr-io.c | 802 +++++++++++++++++++++ 3 files changed, 818 insertions(+) create mode 100644 drivers/iio/frequency/amlogic-clk-msr-io.c diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig index c455be7d4a1c..1682cbec0edf 100644 --- a/drivers/iio/frequency/Kconfig +++ b/drivers/iio/frequency/Kconfig @@ -7,6 +7,21 @@ # # When adding new entries keep the list in alphabetical order =20 +menu "Frequency Measurements" + +config AMLOGIC_CLK_MSR_IO + tristate "Amlogic IO Clock Measure" + default ARCH_MESON + depends on REGMAP_MMIO && COMMON_CLK + help + Say yes here to build support for Amlogic Clock Measure + HW found in Amlogic SoC, with IIO support + + To compile this driver as a module, choose M here: the + module will be called amlogic-clk-msr-io. + +endmenu + menu "Frequency Synthesizers DDS/PLL" =20 menu "Clock Generator/Distribution" diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile index 70d0e0b70e80..3939970cccf3 100644 --- a/drivers/iio/frequency/Makefile +++ b/drivers/iio/frequency/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_ADMV1013) +=3D admv1013.o obj-$(CONFIG_ADMV1014) +=3D admv1014.o obj-$(CONFIG_ADMV4420) +=3D admv4420.o obj-$(CONFIG_ADRF6780) +=3D adrf6780.o +obj-$(CONFIG_AMLOGIC_CLK_MSR_IO) +=3D amlogic-clk-msr-io.o diff --git a/drivers/iio/frequency/amlogic-clk-msr-io.c b/drivers/iio/frequ= ency/amlogic-clk-msr-io.c new file mode 100644 index 000000000000..16a15dd346d8 --- /dev/null +++ b/drivers/iio/frequency/amlogic-clk-msr-io.c @@ -0,0 +1,802 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2024 BayLibre, SAS. +// Author: Jerome Brunet + +#include +#include +#include +#include +#include +#include + +#define MSR_CLK_REG0 0x0 +#define MSR_BUSY BIT(31) +#define MSR_CLK_SRC GENMASK(26, 20) +#define MSR_CLK_EN BIT(19) +#define MSR_CONT BIT(17) +#define MSR_ENABLE BIT(16) +#define MSR_TIME GENMASK(15, 0) +#define MSR_TIME_MAX (MSR_TIME + 1) +#define MSR_CLK_REG1 0x4 +#define MSR_CLK_REG2 0x8 +#define MSR_MEASURED GENMASK(19, 0) + +#define CLK_MIN_TIME 64 /* This allows to measure up to 8GHz */ +#define CLK_MSR_MAX 128 + +/* + * Note this driver aims to replace drivers/soc/amlogic/meson-clk-measure.c + * It provides the same functionality and adds support for the IIO API. + * The only thing missing is the clock summary which is very handy for + * debugging purpose. It is easy to reproduce the summary in userspace, + * from the iio device sysfs directory: + * + * for i in $(seq 0 127); do + * printf "%20s: %11dHz +/- %.0fHz\n" \ + * $(cat in_altvoltage${i}_label) \ + * $(cat in_altvoltage${i}_input) \ + * $(cat in_altvoltage_scale); + * done + */ + +struct amlogic_cmsr { + struct regmap *reg; + struct regmap *duty; + struct mutex lock; +}; + +static const char *cmsr_m8[CLK_MSR_MAX] =3D { + [0] =3D "ring_osc_out_ee0", + [1] =3D "ring_osc_out_ee1", + [2] =3D "ring_osc_out_ee2", + [3] =3D "a9_ring_osck", + [6] =3D "vid_pll", + [7] =3D "clk81", + [8] =3D "encp", + [9] =3D "encl", + [11] =3D "eth_rmii", + [13] =3D "amclk", + [14] =3D "fec_clk_0", + [15] =3D "fec_clk_1", + [16] =3D "fec_clk_2", + [18] =3D "a9_clk_div16", + [19] =3D "hdmi_sys", + [20] =3D "rtc_osc_clk_out", + [21] =3D "i2s_clk_in_src0", + [22] =3D "clk_rmii_from_pad", + [23] =3D "hdmi_ch0_tmds", + [24] =3D "lvds_fifo", + [26] =3D "sc_clk_int", + [28] =3D "sar_adc", + [30] =3D "mpll_clk_test_out", + [31] =3D "audac_clkpi", + [32] =3D "vdac", + [33] =3D "sdhc_rx", + [34] =3D "sdhc_sd", + [35] =3D "mali", + [36] =3D "hdmi_tx_pixel", + [38] =3D "vdin_meas", + [39] =3D "pcm_sclk", + [40] =3D "pcm_mclk", + [41] =3D "eth_rx_tx", + [42] =3D "pwm_d", + [43] =3D "pwm_c", + [44] =3D "pwm_b", + [45] =3D "pwm_a", + [46] =3D "pcm2_sclk", + [47] =3D "ddr_dpll_pt", + [48] =3D "pwm_f", + [49] =3D "pwm_e", + [59] =3D "hcodec", + [60] =3D "usb_32k_alt", + [61] =3D "gpio", + [62] =3D "vid2_pll", + [63] =3D "mipi_csi_cfg", +}; + +static const char *cmsr_gx[CLK_MSR_MAX] =3D { + [0] =3D "ring_osc_out_ee_0", + [1] =3D "ring_osc_out_ee_1", + [2] =3D "ring_osc_out_ee_2", + [3] =3D "a53_ring_osc", + [4] =3D "gp0_pll", + [6] =3D "enci", + [7] =3D "clk81", + [8] =3D "encp", + [9] =3D "encl", + [10] =3D "vdac", + [11] =3D "rgmii_tx", + [12] =3D "pdm", + [13] =3D "amclk", + [14] =3D "fec_0", + [15] =3D "fec_1", + [16] =3D "fec_2", + [17] =3D "sys_pll_div16", + [18] =3D "sys_cpu_div16", + [19] =3D "hdmitx_sys", + [20] =3D "rtc_osc_out", + [21] =3D "i2s_in_src0", + [22] =3D "eth_phy_ref", + [23] =3D "hdmi_todig", + [26] =3D "sc_int", + [28] =3D "sar_adc", + [31] =3D "mpll_test_out", + [32] =3D "vdec", + [35] =3D "mali", + [36] =3D "hdmi_tx_pixel", + [37] =3D "i958", + [38] =3D "vdin_meas", + [39] =3D "pcm_sclk", + [40] =3D "pcm_mclk", + [41] =3D "eth_rx_or_rmii", + [42] =3D "mp0_out", + [43] =3D "fclk_div5", + [44] =3D "pwm_b", + [45] =3D "pwm_a", + [46] =3D "vpu", + [47] =3D "ddr_dpll_pt", + [48] =3D "mp1_out", + [49] =3D "mp2_out", + [50] =3D "mp3_out", + [51] =3D "nand_core", + [52] =3D "sd_emmc_b", + [53] =3D "sd_emmc_a", + [55] =3D "vid_pll_div_out", + [56] =3D "cci", + [57] =3D "wave420l_c", + [58] =3D "wave420l_b", + [59] =3D "hcodec", + [60] =3D "alt_32k", + [61] =3D "gpio_msr", + [62] =3D "hevc", + [66] =3D "vid_lock", + [70] =3D "pwm_f", + [71] =3D "pwm_e", + [72] =3D "pwm_d", + [73] =3D "pwm_c", + [75] =3D "aoclkx2_int", + [76] =3D "aoclk_int", + [77] =3D "rng_ring_osc_0", + [78] =3D "rng_ring_osc_1", + [79] =3D "rng_ring_osc_2", + [80] =3D "rng_ring_osc_3", + [81] =3D "vapb", + [82] =3D "ge2d", +}; + +static const char *cmsr_axg[CLK_MSR_MAX] =3D { + [0] =3D "ring_osc_out_ee_0", + [1] =3D "ring_osc_out_ee_1", + [2] =3D "ring_osc_out_ee_2", + [3] =3D "a53_ring_osc", + [4] =3D "gp0_pll", + [5] =3D "gp1_pll", + [7] =3D "clk81", + [9] =3D "encl", + [17] =3D "sys_pll_div16", + [18] =3D "sys_cpu_div16", + [20] =3D "rtc_osc_out", + [23] =3D "mmc_clk", + [28] =3D "sar_adc", + [31] =3D "mpll_test_out", + [40] =3D "mod_eth_tx_clk", + [41] =3D "mod_eth_rx_clk_rmii", + [42] =3D "mp0_out", + [43] =3D "fclk_div5", + [44] =3D "pwm_b", + [45] =3D "pwm_a", + [46] =3D "vpu", + [47] =3D "ddr_dpll_pt", + [48] =3D "mp1_out", + [49] =3D "mp2_out", + [50] =3D "mp3_out", + [51] =3D "sd_emmm_c", + [52] =3D "sd_emmc_b", + [61] =3D "gpio_msr", + [66] =3D "audio_slv_lrclk_c", + [67] =3D "audio_slv_lrclk_b", + [68] =3D "audio_slv_lrclk_a", + [69] =3D "audio_slv_sclk_c", + [70] =3D "audio_slv_sclk_b", + [71] =3D "audio_slv_sclk_a", + [72] =3D "pwm_d", + [73] =3D "pwm_c", + [74] =3D "wifi_beacon", + [75] =3D "tdmin_lb_lrcl", + [76] =3D "tdmin_lb_sclk", + [77] =3D "rng_ring_osc_0", + [78] =3D "rng_ring_osc_1", + [79] =3D "rng_ring_osc_2", + [80] =3D "rng_ring_osc_3", + [81] =3D "vapb", + [82] =3D "ge2d", + [84] =3D "audio_resample", + [85] =3D "audio_pdm_sys", + [86] =3D "audio_spdifout", + [87] =3D "audio_spdifin", + [88] =3D "audio_lrclk_f", + [89] =3D "audio_lrclk_e", + [90] =3D "audio_lrclk_d", + [91] =3D "audio_lrclk_c", + [92] =3D "audio_lrclk_b", + [93] =3D "audio_lrclk_a", + [94] =3D "audio_sclk_f", + [95] =3D "audio_sclk_e", + [96] =3D "audio_sclk_d", + [97] =3D "audio_sclk_c", + [98] =3D "audio_sclk_b", + [99] =3D "audio_sclk_a", + [100] =3D "audio_mclk_f", + [101] =3D "audio_mclk_e", + [102] =3D "audio_mclk_d", + [103] =3D "audio_mclk_c", + [104] =3D "audio_mclk_b", + [105] =3D "audio_mclk_a", + [106] =3D "pcie_refclk_n", + [107] =3D "pcie_refclk_p", + [108] =3D "audio_locker_out", + [109] =3D "audio_locker_in", +}; + +static const char *cmsr_g12a[CLK_MSR_MAX] =3D { + [0] =3D "ring_osc_out_ee_0", + [1] =3D "ring_osc_out_ee_1", + [2] =3D "ring_osc_out_ee_2", + [3] =3D "sys_cpu_ring_osc", + [4] =3D "gp0_pll", + [6] =3D "enci", + [7] =3D "clk81", + [8] =3D "encp", + [9] =3D "encl", + [10] =3D "vdac", + [11] =3D "eth_tx", + [12] =3D "hifi_pll", + [13] =3D "mod_tcon", + [14] =3D "fec_0", + [15] =3D "fec_1", + [16] =3D "fec_2", + [17] =3D "sys_pll_div16", + [18] =3D "sys_cpu_div16", + [19] =3D "lcd_an_ph2", + [20] =3D "rtc_osc_out", + [21] =3D "lcd_an_ph3", + [22] =3D "eth_phy_ref", + [23] =3D "mpll_50m", + [24] =3D "eth_125m", + [25] =3D "eth_rmii", + [26] =3D "sc_int", + [27] =3D "in_mac", + [28] =3D "sar_adc", + [29] =3D "pcie_inp", + [30] =3D "pcie_inn", + [31] =3D "mpll_test_out", + [32] =3D "vdec", + [33] =3D "sys_cpu_ring_osc_1", + [34] =3D "eth_mpll_50m", + [35] =3D "mali", + [36] =3D "hdmi_tx_pixel", + [37] =3D "cdac", + [38] =3D "vdin_meas", + [39] =3D "bt656", + [41] =3D "eth_rx_or_rmii", + [42] =3D "mp0_out", + [43] =3D "fclk_div5", + [44] =3D "pwm_b", + [45] =3D "pwm_a", + [46] =3D "vpu", + [47] =3D "ddr_dpll_pt", + [48] =3D "mp1_out", + [49] =3D "mp2_out", + [50] =3D "mp3_out", + [51] =3D "sd_emmc_c", + [52] =3D "sd_emmc_b", + [53] =3D "sd_emmc_a", + [54] =3D "vpu_clkc", + [55] =3D "vid_pll_div_out", + [56] =3D "wave420l_a", + [57] =3D "wave420l_c", + [58] =3D "wave420l_b", + [59] =3D "hcodec", + [61] =3D "gpio_msr", + [62] =3D "hevcb", + [63] =3D "dsi_meas", + [64] =3D "spicc_1", + [65] =3D "spicc_0", + [66] =3D "vid_lock", + [67] =3D "dsi_phy", + [68] =3D "hdcp22_esm", + [69] =3D "hdcp22_skp", + [70] =3D "pwm_f", + [71] =3D "pwm_e", + [72] =3D "pwm_d", + [73] =3D "pwm_c", + [75] =3D "hevcf", + [77] =3D "rng_ring_osc_0", + [78] =3D "rng_ring_osc_1", + [79] =3D "rng_ring_osc_2", + [80] =3D "rng_ring_osc_3", + [81] =3D "vapb", + [82] =3D "ge2d", + [83] =3D "co_rx", + [84] =3D "co_tx", + [89] =3D "hdmi_todig", + [90] =3D "hdmitx_sys", + [91] =3D "sys_cpub_div16", + [92] =3D "sys_pll_cpub_div16", + [94] =3D "eth_phy_rx", + [95] =3D "eth_phy_pll", + [96] =3D "vpu_b", + [97] =3D "cpu_b_tmp", + [98] =3D "ts", + [99] =3D "ring_osc_out_ee_3", + [100] =3D "ring_osc_out_ee_4", + [101] =3D "ring_osc_out_ee_5", + [102] =3D "ring_osc_out_ee_6", + [103] =3D "ring_osc_out_ee_7", + [104] =3D "ring_osc_out_ee_8", + [105] =3D "ring_osc_out_ee_9", + [106] =3D "ephy_test", + [107] =3D "au_dac_g128x", + [108] =3D "audio_locker_out", + [109] =3D "audio_locker_in", + [110] =3D "audio_tdmout_c_sclk", + [111] =3D "audio_tdmout_b_sclk", + [112] =3D "audio_tdmout_a_sclk", + [113] =3D "audio_tdmin_lb_sclk", + [114] =3D "audio_tdmin_c_sclk", + [115] =3D "audio_tdmin_b_sclk", + [116] =3D "audio_tdmin_a_sclk", + [117] =3D "audio_resample", + [118] =3D "audio_pdm_sys", + [119] =3D "audio_spdifout_b", + [120] =3D "audio_spdifout", + [121] =3D "audio_spdifin", + [122] =3D "audio_pdm_dclk", +}; + +static const char *cmsr_sm1[CLK_MSR_MAX] =3D { + [0] =3D "ring_osc_out_ee_0", + [1] =3D "ring_osc_out_ee_1", + [2] =3D "ring_osc_out_ee_2", + [3] =3D "ring_osc_out_ee_3", + [4] =3D "gp0_pll", + [5] =3D "gp1_pll", + [6] =3D "enci", + [7] =3D "clk81", + [8] =3D "encp", + [9] =3D "encl", + [10] =3D "vdac", + [11] =3D "eth_tx", + [12] =3D "hifi_pll", + [13] =3D "mod_tcon", + [14] =3D "fec_0", + [15] =3D "fec_1", + [16] =3D "fec_2", + [17] =3D "sys_pll_div16", + [18] =3D "sys_cpu_div16", + [19] =3D "lcd_an_ph2", + [20] =3D "rtc_osc_out", + [21] =3D "lcd_an_ph3", + [22] =3D "eth_phy_ref", + [23] =3D "mpll_50m", + [24] =3D "eth_125m", + [25] =3D "eth_rmii", + [26] =3D "sc_int", + [27] =3D "in_mac", + [28] =3D "sar_adc", + [29] =3D "pcie_inp", + [30] =3D "pcie_inn", + [31] =3D "mpll_test_out", + [32] =3D "vdec", + [34] =3D "eth_mpll_50m", + [35] =3D "mali", + [36] =3D "hdmi_tx_pixel", + [37] =3D "cdac", + [38] =3D "vdin_meas", + [39] =3D "bt656", + [40] =3D "arm_ring_osc_out_4", + [41] =3D "eth_rx_or_rmii", + [42] =3D "mp0_out", + [43] =3D "fclk_div5", + [44] =3D "pwm_b", + [45] =3D "pwm_a", + [46] =3D "vpu", + [47] =3D "ddr_dpll_pt", + [48] =3D "mp1_out", + [49] =3D "mp2_out", + [50] =3D "mp3_out", + [51] =3D "sd_emmc_c", + [52] =3D "sd_emmc_b", + [53] =3D "sd_emmc_a", + [54] =3D "vpu_clkc", + [55] =3D "vid_pll_div_out", + [56] =3D "wave420l_a", + [57] =3D "wave420l_c", + [58] =3D "wave420l_b", + [59] =3D "hcodec", + [60] =3D "arm_ring_osc_out_5", + [61] =3D "gpio_msr", + [62] =3D "hevcb", + [63] =3D "dsi_meas", + [64] =3D "spicc_1", + [65] =3D "spicc_0", + [66] =3D "vid_lock", + [67] =3D "dsi_phy", + [68] =3D "hdcp22_esm", + [69] =3D "hdcp22_skp", + [70] =3D "pwm_f", + [71] =3D "pwm_e", + [72] =3D "pwm_d", + [73] =3D "pwm_c", + [74] =3D "arm_ring_osc_out_6", + [75] =3D "hevcf", + [76] =3D "arm_ring_osc_out_7", + [77] =3D "rng_ring_osc_0", + [78] =3D "rng_ring_osc_1", + [79] =3D "rng_ring_osc_2", + [80] =3D "rng_ring_osc_3", + [81] =3D "vapb", + [82] =3D "ge2d", + [83] =3D "co_rx", + [84] =3D "co_tx", + [85] =3D "arm_ring_osc_out_8", + [86] =3D "arm_ring_osc_out_9", + [87] =3D "mipi_dsi_phy", + [88] =3D "cis2_adapt", + [89] =3D "hdmi_todig", + [90] =3D "hdmitx_sys", + [91] =3D "nna_core", + [92] =3D "nna_axi", + [93] =3D "vad", + [94] =3D "eth_phy_rx", + [95] =3D "eth_phy_pll", + [96] =3D "vpu_b", + [97] =3D "cpu_b_tmp", + [98] =3D "ts", + [99] =3D "arm_ring_osc_out_10", + [100] =3D "arm_ring_osc_out_11", + [101] =3D "arm_ring_osc_out_12", + [102] =3D "arm_ring_osc_out_13", + [103] =3D "arm_ring_osc_out_14", + [104] =3D "arm_ring_osc_out_15", + [105] =3D "arm_ring_osc_out_16", + [106] =3D "ephy_test", + [107] =3D "au_dac_g128x", + [108] =3D "audio_locker_out", + [109] =3D "audio_locker_in", + [110] =3D "audio_tdmout_c_sclk", + [111] =3D "audio_tdmout_b_sclk", + [112] =3D "audio_tdmout_a_sclk", + [113] =3D "audio_tdmin_lb_sclk", + [114] =3D "audio_tdmin_c_sclk", + [115] =3D "audio_tdmin_b_sclk", + [116] =3D "audio_tdmin_a_sclk", + [117] =3D "audio_resample", + [118] =3D "audio_pdm_sys", + [119] =3D "audio_spdifout_b", + [120] =3D "audio_spdifout", + [121] =3D "audio_spdifin", + [122] =3D "audio_pdm_dclk", + [123] =3D "audio_resampled", + [124] =3D "earcrx_pll", + [125] =3D "earcrx_pll_test", + [126] =3D "csi_phy0", + [127] =3D "csi2_data", +}; + +static struct iio_chan_spec *cmsr_populate_channels(struct device *dev, + const char * const *conf) +{ + struct iio_chan_spec *chan; + int i; + + chan =3D devm_kzalloc(dev, sizeof(*chan) * CLK_MSR_MAX, GFP_KERNEL); + if (!chan) + return ERR_PTR(-ENOMEM); + + for (i =3D 0; i < CLK_MSR_MAX; i++) { + chan[i].type =3D IIO_ALTVOLTAGE; + chan[i].indexed =3D 1; + chan[i].channel =3D i; + chan[i].info_mask_separate =3D (BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_PROCESSED)); + chan[i].info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE); + chan[i].datasheet_name =3D conf[i]; + } + + return chan; +} + +static int cmsr_get_time_unlocked(struct amlogic_cmsr *cm) +{ + unsigned int raw; + + regmap_read(cm->reg, MSR_CLK_REG0, &raw); + + /* Field register value is time =3D val + 1 */ + return FIELD_GET(MSR_TIME, raw) + 1; +} + +static int cmsr_set_time_unlocked(struct amlogic_cmsr *cm, + unsigned int time) +{ + time -=3D 1; + + if (time < 0 || time > MSR_TIME) + return -EINVAL; + + regmap_update_bits(cm->reg, MSR_CLK_REG0, MSR_TIME, + FIELD_PREP(MSR_TIME, time)); + + return 0; +} + +static int cmsr_measure_unlocked(struct amlogic_cmsr *cm, + unsigned int idx) +{ + unsigned int raw; + int ret; + + regmap_update_bits(cm->reg, MSR_CLK_REG0, + MSR_ENABLE | MSR_CONT | MSR_CLK_EN | MSR_CLK_SRC, + MSR_CLK_EN | FIELD_PREP(MSR_CLK_SRC, idx)); + + regmap_set_bits(cm->reg, MSR_CLK_REG0, MSR_ENABLE); + ret =3D regmap_read_poll_timeout(cm->reg, MSR_CLK_REG0, raw, + !(raw & MSR_BUSY), 10, 70000); + regmap_clear_bits(cm->reg, MSR_CLK_REG0, MSR_ENABLE | MSR_CLK_EN); + + if (ret) + return ret; + + regmap_read(cm->reg, MSR_CLK_REG2, &raw); + ret =3D FIELD_GET(MSR_MEASURED, raw); + + /* Check for overflow */ + if (ret =3D=3D MSR_MEASURED) + return -EINVAL; + + return ret; +} + +static int cmsr_measure_processed_unlocked(struct amlogic_cmsr *cm, + unsigned int idx, + int *val2) +{ + unsigned int time =3D CLK_MIN_TIME; + u64 rate; + int ret; + + /* + * The challenge here is to provide the best accuracy + * while not spending to much time doing it. + * - Starting with a short duration risk not detecting + * slow clocks, but it is fast. All 128 can be done in ~8ms + * - Starting with a long duration risk overflowing the + * measurement counter and would be way to long, especially + * considering the number of disabled clocks. ~4s for all + * 128 worst case. + * + * This IP measures system clocks so all clock are expected + * to be 1kHz < f < 8GHz. We can compromise based on this, + * doing it in 3 pass: + * #1 Starting if 64us window: detects 30kHz < f < 8GHz + * - Go to #2 if no detection, Go to #3 otherwise + * #2 Extend duration to 1024us (f > 1kHz) + - Assume f =3D 0Hz if no detection, Go to #3 otherwise + * #3 Clock has been detected, adjust window for best accuracy + * + * Doing the range detection takes ~1ms per clock, including disabled + clocks. + * Actual measurement takes at most ~65ms in step #3 for slow clocks, + * when the full range the HW is used. + */ + + /* Step #1 - quick measurement */ + cmsr_set_time_unlocked(cm, time); + ret =3D cmsr_measure_unlocked(cm, idx); + if (ret < 0) + return ret; + + else if (ret =3D=3D 0) { + /* Step #2 - extend the window if necessary */ + time *=3D 16; + cmsr_set_time_unlocked(cm, time); + ret =3D cmsr_measure_unlocked(cm, idx); + if (ret < 0) + return ret; + + else if (ret =3D=3D 0) { + /* Still nothing - assume no clock */ + *val2 =3D 0; + return 0; + } + } + + /* Step #3: Adapt scale for better precision */ + time =3D time * MSR_MEASURED * 3 / (ret * 4); /* 25% margin */ + time =3D min_t(unsigned int, MSR_TIME_MAX, time); + + /* Actually measure rate with an optimized scale */ + cmsr_set_time_unlocked(cm, time); + ret =3D cmsr_measure_unlocked(cm, idx); + if (ret < 0) + return ret; + + rate =3D DIV_ROUND_CLOSEST_ULL(ret * 1000000ULL, time); + *val2 =3D rate >> 32ULL; + return (int)rate; +} + +static int cmsr_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct amlogic_cmsr *cm =3D iio_priv(indio_dev); + + guard(mutex)(&cm->lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + *val =3D cmsr_measure_unlocked(cm, chan->channel); + if (*val < 0) + return *val; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_PROCESSED: /* Result in Hz */ + *val =3D cmsr_measure_processed_unlocked(cm, chan->channel, val2); + if (*val < 0) + return *val; + return IIO_VAL_INT_64; + + case IIO_CHAN_INFO_SCALE: + *val2 =3D cmsr_get_time_unlocked(cm); + *val =3D 1000000; + return IIO_VAL_FRACTIONAL; + + default: + return -EINVAL; + } +} + +static int cmsr_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long info) +{ + struct amlogic_cmsr *cm =3D iio_priv(indio_dev); + unsigned int time; + + guard(mutex)(&cm->lock); + + switch (info) { + case IIO_CHAN_INFO_SCALE: + time =3D DIV_ROUND_CLOSEST(1000000U, val); + return cmsr_set_time_unlocked(cm, time); + default: + return -EINVAL; + } +} + +static int cmsr_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long info) +{ + switch (info) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT; + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + +static int cmsr_read_label(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + char *label) +{ + return sprintf(label, "%s\n", chan->datasheet_name); +} + +static const struct of_device_id cmsr_of_match[] =3D { + { + .compatible =3D "amlogic,gx-clk-msr-io", + .data =3D cmsr_gx, + }, { + .compatible =3D "amlogic,meson8-clk-msr-io", + .data =3D cmsr_m8, + }, { + .compatible =3D "amlogic,axg-clk-msr-io", + .data =3D cmsr_axg, + }, { + .compatible =3D "amlogic,g12a-clk-msr-io", + .data =3D cmsr_g12a, + }, { + .compatible =3D "amlogic,sm1-clk-msr-io", + .data =3D cmsr_sm1, + }, {} +}; +MODULE_DEVICE_TABLE(of, cmsr_of_match); + +static const struct iio_info cmsr_info =3D { + .read_raw =3D cmsr_read_raw, + .read_label =3D cmsr_read_label, + .write_raw =3D cmsr_write_raw, + .write_raw_get_fmt =3D cmsr_write_raw_get_fmt, +}; + +static const struct regmap_config cmsr_regmap_cfg =3D { + .reg_bits =3D 32, + .val_bits =3D 32, + .reg_stride =3D 4, +}; + +static int cmsr_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct iio_dev *indio_dev; + struct amlogic_cmsr *cm; + const char * const *conf; + void __iomem *regs; + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*cm)); + if (!indio_dev) + return -ENOMEM; + platform_set_drvdata(pdev, indio_dev); + cm =3D iio_priv(indio_dev); + + conf =3D of_device_get_match_data(dev); + if (!conf) { + dev_err(dev, "failed to match device\n"); + return -ENODEV; + } + + regs =3D devm_platform_ioremap_resource_byname(pdev, "reg"); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + cm->reg =3D devm_regmap_init_mmio(dev, regs, &cmsr_regmap_cfg); + if (IS_ERR(cm->reg)) { + dev_err(dev, "failed to init main regmap: %ld\n", + PTR_ERR(cm->reg)); + return PTR_ERR(cm->reg); + } + + regs =3D devm_platform_ioremap_resource_byname(pdev, "duty"); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + cm->duty =3D devm_regmap_init_mmio(dev, regs, &cmsr_regmap_cfg); + if (IS_ERR(cm->duty)) { + dev_err(dev, "failed to init duty regmap: %ld\n", + PTR_ERR(cm->duty)); + return PTR_ERR(cm->duty); + } + + mutex_init(&cm->lock); + + /* Init scale with a sane default */ + cmsr_set_time_unlocked(cm, CLK_MIN_TIME); + + indio_dev->name =3D "amlogic-clk-msr"; + indio_dev->info =3D &cmsr_info; + indio_dev->modes =3D INDIO_DIRECT_MODE; + indio_dev->num_channels =3D CLK_MSR_MAX; + indio_dev->channels =3D cmsr_populate_channels(dev, conf); + if (IS_ERR(indio_dev->channels)) + return PTR_ERR(indio_dev->channels); + + return devm_iio_device_register(dev, indio_dev); +} + +static struct platform_driver amlogic_cmsr_driver =3D { + .probe =3D cmsr_probe, + .driver =3D { + .name =3D "amlogic-clk-msr-io", + .of_match_table =3D cmsr_of_match, + }, +}; +module_platform_driver(amlogic_cmsr_driver); + +MODULE_DESCRIPTION("Amlogic Clock Measure IO driver"); +MODULE_AUTHOR("Jerome Brunet "); +MODULE_LICENSE("GPL"); --=20 2.43.0