From nobody Wed Feb 11 09:21:19 2026 Received: from mail-oo1-f45.google.com (mail-oo1-f45.google.com [209.85.161.45]) (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 8FC9117BB3; Wed, 27 Mar 2024 08:29:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528197; cv=none; b=jao0+GTWP5POqwKJG1645aoImqFlioLU12/+KavQWc0KiW261pXEx2Be7Lt4crrWoeRUa+N7A0YYzksc72HnIpCgiT2EnFiXlFfzq7ZTDzcIg5J1YMVtCkn3laP2BXN9T1wKg844/qI/uyfr5+2o0M3F5YOV5XLW1qlUPUBb0MQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528197; c=relaxed/simple; bh=1z2DjnnEUQ8VRVOOj7bX9GFcbA+wqEyxADFf3p99mzE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=SI752wb5vJNsL6KdBpYlTxjPiYABSQ+gRCi7BB46vbiVti7nLPtUpnSlowH+o+k2w+cWFWz3W1HCkF+kHZeApxT49zobWJktvLn3xwdjun4WWgGpmjbAngRnA5MaLhI5V0ltipU/EMHxkq9dm4wWMUOQLv/UvYZKsPpIQ+jhHB8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OzS7plxM; arc=none smtp.client-ip=209.85.161.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OzS7plxM" Received: by mail-oo1-f45.google.com with SMTP id 006d021491bc7-5a47cecb98bso3720403eaf.0; Wed, 27 Mar 2024 01:29:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711528194; x=1712132994; 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=FvyDKytI3LByIiwfwmYUFkoNWJX9ByqcE9gyEaLOuuM=; b=OzS7plxMkFjsWOFFHPZoLYu5Z7RkoZN1qg7KvnVNd1nVFMAStG97JfQffat+uPUSLh fyisHVWlemslvgsQxhFmIP3pN7Zzwutp95sNCd4RnnwnBO6Y7Uii5RZGdRpEmG8uk+MG kgdQ5UyaFSyoTKXgdFLBhq3axV4Mtumt+arjdAlH/Zv/uQMca4Wk+Q5tfBFBsfshH6wI sGqtPDUULhO4+FG/eJerN0e2FZlcLuij1UgOxnw/lLQcRg+xTXYOyY6bTmuuzuM3bQXr cxfg5HF6wS1dY7QypvLjgHz5tW6JGXADFgsdnZ+86kbFVIfhnOsWcW49RDW2BUJ8WWBz EUew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711528194; x=1712132994; 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=FvyDKytI3LByIiwfwmYUFkoNWJX9ByqcE9gyEaLOuuM=; b=V8hOZ/SHlkPbvFRR0wvYM1n5cpBV7di330Fm8LTs8FYNfKp24RXc28boYk1hVKcH0o xnbSS5cy6P76rFmLSO+LtCMslKEzooYG/JoahoMPcNL1OM1DAoASEnx7XQ2DwEofq9fJ FzvVV2GnHdHa9+wwkZB+KK/jtZjuK5erhW50VYSG4j6U0CYISEfZViefi87CVSKZ+4Td ZHtX6vNscJLNoi2gzDij8xztuX6+4535hWlQtpFCzwD3SKuLvyxKg1j3WgoSqdSP08b5 84AcqP20ijqZ0KRzTKGnU/Vl40j46HfnU/9hjrRQLpAFA5fTkwU+riUwAXbbF0mKnGKJ bu8Q== X-Forwarded-Encrypted: i=1; AJvYcCXtBpAF4ckiVlxJ2j3GAxKP3yH8j2EBozSXJB3cawSYkJOkaSPFZF361esT0TMSjsV7qeSeIHwWC360f2DRzR/QqhBwSgpS58LdIz9c8z2LUpsLmD3GyVnTil6SKRKghNHemCjFjrY7HCfg0OlC6Bwc15uwQAxu1caVtDV1u+IQZQhDvA== X-Gm-Message-State: AOJu0Yx0XUDZoNNZkMoPjz1rQGQPGJH0ev8w6/0eL8YuhnbNMituMrqM VY7zv9IuZWJTGK35K8bGyQrLv4mnRLWKj72AT/z58lOhaGRDRNro X-Google-Smtp-Source: AGHT+IEIETJYfm1LeEXZ17gb9zA1z0lN3OnPZ/F9w3Ecsm23rOzisdPobwpL692i6eZcBTxilITALA== X-Received: by 2002:a05:6820:1a07:b0:5a4:71b3:d090 with SMTP id bq7-20020a0568201a0700b005a471b3d090mr483779oob.5.1711528194636; Wed, 27 Mar 2024 01:29:54 -0700 (PDT) Received: from localhost.localdomain ([122.8.183.87]) by smtp.gmail.com with ESMTPSA id bp12-20020a056820198c00b005a1bc9b380esm2229466oob.24.2024.03.27.01.29.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Mar 2024 01:29:54 -0700 (PDT) From: Chen Wang To: aou@eecs.berkeley.edu, chao.wei@sophgo.com, conor@kernel.org, krzysztof.kozlowski+dt@linaro.org, mturquette@baylibre.com, palmer@dabbelt.com, paul.walmsley@sifive.com, richardcochran@gmail.com, robh+dt@kernel.org, sboyd@kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, haijiao.liu@sophgo.com, xiaoguang.xing@sophgo.com, guoren@kernel.org, jszhang@kernel.org, inochiama@outlook.com, samuel.holland@sifive.com Cc: Chen Wang , Rob Herring Subject: [PATCH v12 1/5] dt-bindings: clock: sophgo: add pll clocks for SG2042 Date: Wed, 27 Mar 2024 16:29:47 +0800 Message-Id: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Chen Wang Add bindings for the pll clocks for Sophgo SG2042. Signed-off-by: Chen Wang Reviewed-by: Rob Herring Reviewed-by: Guo Ren --- .../bindings/clock/sophgo,sg2042-pll.yaml | 45 +++++++++++++++++++ include/dt-bindings/clock/sophgo,sg2042-pll.h | 14 ++++++ 2 files changed, 59 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sophgo,sg2042-p= ll.yaml create mode 100644 include/dt-bindings/clock/sophgo,sg2042-pll.h diff --git a/Documentation/devicetree/bindings/clock/sophgo,sg2042-pll.yaml= b/Documentation/devicetree/bindings/clock/sophgo,sg2042-pll.yaml new file mode 100644 index 000000000000..b9af733e8a73 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sophgo,sg2042-pll.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/sophgo,sg2042-pll.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SG2042 PLL Clock Generator + +maintainers: + - Chen Wang + +properties: + compatible: + const: sophgo,sg2042-pll + + reg: + maxItems: 1 + + clocks: + items: + - description: Oscillator(Clock Generation IC) for Main/Fixed PLL (2= 5 MHz) + - description: Oscillator(Clock Generation IC) for DDR PLL 0 (25 MHz) + - description: Oscillator(Clock Generation IC) for DDR PLL 1 (25 MHz) + + '#clock-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@10000000 { + compatible =3D "sophgo,sg2042-pll"; + reg =3D <0x10000000 0x10000>; + clocks =3D <&cgi_main>, <&cgi_dpll0>, <&cgi_dpll1>; + #clock-cells =3D <1>; + }; diff --git a/include/dt-bindings/clock/sophgo,sg2042-pll.h b/include/dt-bin= dings/clock/sophgo,sg2042-pll.h new file mode 100644 index 000000000000..2d519b3bf51c --- /dev/null +++ b/include/dt-bindings/clock/sophgo,sg2042-pll.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_SOPHGO_SG2042_PLL_H__ +#define __DT_BINDINGS_SOPHGO_SG2042_PLL_H__ + +#define MPLL_CLK 0 +#define FPLL_CLK 1 +#define DPLL0_CLK 2 +#define DPLL1_CLK 3 + +#endif /* __DT_BINDINGS_SOPHGO_SG2042_PLL_H__ */ --=20 2.25.1 From nobody Wed Feb 11 09:21:19 2026 Received: from mail-oa1-f43.google.com (mail-oa1-f43.google.com [209.85.160.43]) (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 6003F2E647; Wed, 27 Mar 2024 08:30:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528212; cv=none; b=cOIwz2q1VLxCko7X717lLJXL9KKF1AXMe37i9jvi21uAaE9EO6i9r3lS9CvxRPKGc8rvtQpXT67uakl/B56yh0IlIlFhVdJzFECCoT4MRu/BKReIbnhppM6cB0eJrghiHmHr0Fm7wcA9cGJk8p/HheaTgFKNNxhpPE+9ZgcODgM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528212; c=relaxed/simple; bh=R0ygEHJUj8I1NP/GUex190+DSvdj/sG5voRmaHdDgSQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UKqNSl9rCNXXyO3LZ7+ubkMl/DQA1RV1PnhiFdOLJc8qGLoix/g+YmjmTavPIhVnCRbVR7dCvipNn10waQLhqWAABiJ5Nrs2DPsnzrRntK1VkhG8GBp/prR8DAgqtFjnAcrd1yiTNHwucev45EPmJyNwtNv6fOKZLJ6br+GFy7c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IhySJ50O; arc=none smtp.client-ip=209.85.160.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IhySJ50O" Received: by mail-oa1-f43.google.com with SMTP id 586e51a60fabf-22222357d76so2549223fac.2; Wed, 27 Mar 2024 01:30:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711528210; x=1712133010; 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=auVFVf5TZOUclH6ERFg1awZazyADre7qdwcfKdlYJq8=; b=IhySJ50OMIOx+q0EgZ0VGv8H/sOsBtG4+XU7X/jYFV2OpbpHpjcmp7N/w8at0o5PBQ z1EiMI+6XHNSnnwq+GeuKRG9knx+qRCNw+eS64i5QuJYb4WL/IyuhFxKl4LbdViKhI6R cJZa4IdS4Z1yoQQts3Xwoz+uqnfP2yxyx8EhR61z5uIt5LWbTCb/UOIxp7zH9jfll+5e Zb5N5arqwuUkdNLVjj6KMaAoRpmlvN6RDqWJlADqCqOg4CRwD1BKPIF1JmWXec6r6XCL xKegNJNTIWY4VfbhbjEi6Vl9fc9s2wrq0huKbqtT0laydtqanuszb/dRQ1XExyprfe35 IWSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711528210; x=1712133010; 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=auVFVf5TZOUclH6ERFg1awZazyADre7qdwcfKdlYJq8=; b=PzGaCJSrvUq5N4JfJpdrHUnN/USFFYY54deOo7A7gQp3cODxnp9Sio5OPy5JEuYXTK Q+iXQnpzkUGJgWQqwl+C5owxStMgmJdl03DUCUjHLOXd6aRu9HJo/RVy5EuvwcyRgpFJ zsBklTuDY0qVkawTDB5uu5YEv3BR/TMbXblpHK0E09o+AgTNSpUsLcvPPM8n1lKvX0d5 WkMxME+YUxLQ0USl2kK4V4uOcYZ9leS9bseeyRsy0JOgMGnEYZ8b/dmQQ3A7EXWOm/NT reKyWrujwO4e9rjAn5JP/tVNY5LbIwbNnN64Dy6TipW3e3goe1T5+HVKo8DpwA30wB6O Mufg== X-Forwarded-Encrypted: i=1; AJvYcCUcLG4bEQygwr09N83YvSusDeH3dZBLjYAEGEmg63DkY6mH9iVlx0bjYZXUj2ZJJIxOw98w+F6mABGJULuksbsS3JfgBVyVd/me1RE4GBd/F38YRAH9TDUtnjqfgMqwq//NuA+X8t9lv4PWcT7JIb8cvMWcLoQSwtCPssuB9L4KjwcTqg== X-Gm-Message-State: AOJu0YxYbS4tDIjnMk8+VV0fpR0+1ObMR3ckHlW8rz38VALac4FVAh4H nrt//mP0W8RyqmfWvChB4xMETnvARXo9WjXguj9y2CwHbpjpaQBn X-Google-Smtp-Source: AGHT+IGJDU1xid2QssySH1k1Hs1N7muilac+ajQkwpr9hmbgzkFBd+g+QqlCC0idks1XRDqEixq8KQ== X-Received: by 2002:a05:6870:91d6:b0:22a:1038:39e6 with SMTP id c22-20020a05687091d600b0022a103839e6mr2243406oaf.0.1711528210500; Wed, 27 Mar 2024 01:30:10 -0700 (PDT) Received: from localhost.localdomain ([122.8.183.87]) by smtp.gmail.com with ESMTPSA id xa10-20020a0568707f0a00b00229f553239esm2752241oab.36.2024.03.27.01.30.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Mar 2024 01:30:10 -0700 (PDT) From: Chen Wang To: aou@eecs.berkeley.edu, chao.wei@sophgo.com, conor@kernel.org, krzysztof.kozlowski+dt@linaro.org, mturquette@baylibre.com, palmer@dabbelt.com, paul.walmsley@sifive.com, richardcochran@gmail.com, robh+dt@kernel.org, sboyd@kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, haijiao.liu@sophgo.com, xiaoguang.xing@sophgo.com, guoren@kernel.org, jszhang@kernel.org, inochiama@outlook.com, samuel.holland@sifive.com Cc: Chen Wang , Rob Herring Subject: [PATCH v12 2/5] dt-bindings: clock: sophgo: add RP gate clocks for SG2042 Date: Wed, 27 Mar 2024 16:30:03 +0800 Message-Id: <78ddd5b127860e110f4c782de90025153cdba083.1711527932.git.unicorn_wang@outlook.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Chen Wang Add bindings for the gate clocks of RP subsystem for Sophgo SG2042. Signed-off-by: Chen Wang Reviewed-by: Rob Herring --- .../bindings/clock/sophgo,sg2042-rpgate.yaml | 43 ++++++++++++++ .../dt-bindings/clock/sophgo,sg2042-rpgate.h | 58 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sophgo,sg2042-r= pgate.yaml create mode 100644 include/dt-bindings/clock/sophgo,sg2042-rpgate.h diff --git a/Documentation/devicetree/bindings/clock/sophgo,sg2042-rpgate.y= aml b/Documentation/devicetree/bindings/clock/sophgo,sg2042-rpgate.yaml new file mode 100644 index 000000000000..9a58038b3182 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sophgo,sg2042-rpgate.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/sophgo,sg2042-rpgate.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SG2042 Gate Clock Generator for RP(riscv processors) subsyst= em + +maintainers: + - Chen Wang + +properties: + compatible: + const: sophgo,sg2042-rpgate + + reg: + maxItems: 1 + + clocks: + items: + - description: Gate clock for RP subsystem + + '#clock-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@20000000 { + compatible =3D "sophgo,sg2042-rpgate"; + reg =3D <0x20000000 0x10000>; + clocks =3D <&clkgen 85>; + #clock-cells =3D <1>; + }; diff --git a/include/dt-bindings/clock/sophgo,sg2042-rpgate.h b/include/dt-= bindings/clock/sophgo,sg2042-rpgate.h new file mode 100644 index 000000000000..8b4522d5f559 --- /dev/null +++ b/include/dt-bindings/clock/sophgo,sg2042-rpgate.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_SOPHGO_SG2042_RPGATE_H__ +#define __DT_BINDINGS_SOPHGO_SG2042_RPGATE_H__ + +#define GATE_CLK_RXU0 0 +#define GATE_CLK_RXU1 1 +#define GATE_CLK_RXU2 2 +#define GATE_CLK_RXU3 3 +#define GATE_CLK_RXU4 4 +#define GATE_CLK_RXU5 5 +#define GATE_CLK_RXU6 6 +#define GATE_CLK_RXU7 7 +#define GATE_CLK_RXU8 8 +#define GATE_CLK_RXU9 9 +#define GATE_CLK_RXU10 10 +#define GATE_CLK_RXU11 11 +#define GATE_CLK_RXU12 12 +#define GATE_CLK_RXU13 13 +#define GATE_CLK_RXU14 14 +#define GATE_CLK_RXU15 15 +#define GATE_CLK_RXU16 16 +#define GATE_CLK_RXU17 17 +#define GATE_CLK_RXU18 18 +#define GATE_CLK_RXU19 19 +#define GATE_CLK_RXU20 20 +#define GATE_CLK_RXU21 21 +#define GATE_CLK_RXU22 22 +#define GATE_CLK_RXU23 23 +#define GATE_CLK_RXU24 24 +#define GATE_CLK_RXU25 25 +#define GATE_CLK_RXU26 26 +#define GATE_CLK_RXU27 27 +#define GATE_CLK_RXU28 28 +#define GATE_CLK_RXU29 29 +#define GATE_CLK_RXU30 30 +#define GATE_CLK_RXU31 31 +#define GATE_CLK_MP0 32 +#define GATE_CLK_MP1 33 +#define GATE_CLK_MP2 34 +#define GATE_CLK_MP3 35 +#define GATE_CLK_MP4 36 +#define GATE_CLK_MP5 37 +#define GATE_CLK_MP6 38 +#define GATE_CLK_MP7 39 +#define GATE_CLK_MP8 40 +#define GATE_CLK_MP9 41 +#define GATE_CLK_MP10 42 +#define GATE_CLK_MP11 43 +#define GATE_CLK_MP12 44 +#define GATE_CLK_MP13 45 +#define GATE_CLK_MP14 46 +#define GATE_CLK_MP15 47 + +#endif /* __DT_BINDINGS_SOPHGO_SG2042_RPGATE_H__ */ --=20 2.25.1 From nobody Wed Feb 11 09:21:19 2026 Received: from mail-oo1-f45.google.com (mail-oo1-f45.google.com [209.85.161.45]) (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 BF4B6339A1; Wed, 27 Mar 2024 08:30:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528229; cv=none; b=bOizP9kihlZqHzkjj94xXKYPzufWKJercvx77BgnguAm0YLAenhxzHgSmDf70QMn827sGA3NHtmr+Hevgwh1UesoTfbAM572Pq3ojiQeiE0Eg6HaZtKXmvYzehWNTYi8wGIznSJzFIilLIFTmZmZQuJ1ZNFDCMsE02O9TzUnhs4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528229; c=relaxed/simple; bh=p1DMI/r2cpeir1sctnhIdWVZSjEW/EJombAHWt9fUP8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=A7/OPv9hl0di+MdobqNWqlZ5qHAOxBOd+kh08z3a+yg8n06b5RfFN7AISShg93X4vQSjfr1CiWjejFb+33tiT1OSXgwCmOTUvUziou8SieHBiA6Ab/HxkRSNamCj1R2NJNSOzAXO3Jmiloyqooeyw6lk7VSUM6WSMFZTTA8fpR0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=cJ04hfvN; arc=none smtp.client-ip=209.85.161.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cJ04hfvN" Received: by mail-oo1-f45.google.com with SMTP id 006d021491bc7-5a4817189c8so3793897eaf.1; Wed, 27 Mar 2024 01:30:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711528227; x=1712133027; 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=JkJXNBJTmby2h3ZHeW5LvDqnR7RXSun3VQ0kpcOw0aw=; b=cJ04hfvNFwll0/ChSXNc8k+fZ1o46pT6IB/Fx3o35X/R8fwJUNGNAsuhhh9MV0Mj4I LDvfwTiCnjt824oiTKXbI58l/nfyR8LmRw82ucQJYAuAm0GI3Lu7GP414h/vqhpg8awg FwxWlzok0cPRxc6Rd5ioJlkzJCNzFDtBBWy6uEKlZ50sAfVXfX+eKq+FeZpjjA8WIQXg ziQD0Cy+jQW/uMAnq6WqNhxg+85/h83KsDJ2drC2Y0q06Z4V8BSiEZHMuMpqjHYmG+VS l2y1qp1bfzZbTWLAHDxSHllgfX+sYDi7/DZ64hjFr2FsG7IlS8w+rqUH+gDCfVTvOfd+ uAMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711528227; x=1712133027; 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=JkJXNBJTmby2h3ZHeW5LvDqnR7RXSun3VQ0kpcOw0aw=; b=Wp9s/70ZJi6Hh/GwSaSGnfcp+WSSTxTnrm8Sm2r95Q4uemPP6SgPa2fstgBUnAc1Ou hu2PAdVXEqdYADpmgXPvGBShBArbjIhYfRWICygwkMYp/oglyiaWQK8mFr+XkvCmq1Hv a1amh1o6m0eiqlJCMHGdgYFvUFS0g+et6wEftBehUzLfeHG8IvbAbVaRu4GtYwqwob2O y/hw7JWzkBsFj4wWlbNQ5PmTFs3XdHMuD6WL5m8VspG7oVh/fhYmQS7i1fJ51L+3XxTa UehvhLGIyXwDZD6uMGV74/4toChSCwr5OTLf0F4XDlx9phiU7kXa6mmr8B51rcIABFsA CIJw== X-Forwarded-Encrypted: i=1; AJvYcCUcKWkl1nk9nLtZN3odYOEPhk3R4mLPMe69V9OgOxCu+oA6c8qw1r4QamXdBoNeaW95kNGBrpnBFJ+3fczGiVAvH7Rg4+2ijqmw5PUjMX2gCxGNzN6OXMhEeZzkdqORULCujrOmmk7NXHTtI5VJxCSBcAKA2Fj5UWEJzAE/qluo6JEBwA== X-Gm-Message-State: AOJu0Yx7lo0Ic/UDB0WN+TaOI5nZ3OX884TwQ6C06vY5rPbiXN6I4hYF xgI7/yKmZONXxjuJFlZ9dhrsyG1l7XXqu1hYFn6koPSxUIy1Yo+3 X-Google-Smtp-Source: AGHT+IHQwb1sZ/9jh1rM3RK9V6pZqILXHN7haQ8NeTZ6lIJ3ORJACyCxeZFxK3WaHx5UTLylp26NXQ== X-Received: by 2002:a4a:e902:0:b0:5a5:1fdc:8548 with SMTP id bx2-20020a4ae902000000b005a51fdc8548mr5986475oob.3.1711528226906; Wed, 27 Mar 2024 01:30:26 -0700 (PDT) Received: from localhost.localdomain ([122.8.183.87]) by smtp.gmail.com with ESMTPSA id b27-20020a4a341b000000b005a22f8ae2dfsm2425274ooa.34.2024.03.27.01.30.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Mar 2024 01:30:26 -0700 (PDT) From: Chen Wang To: aou@eecs.berkeley.edu, chao.wei@sophgo.com, conor@kernel.org, krzysztof.kozlowski+dt@linaro.org, mturquette@baylibre.com, palmer@dabbelt.com, paul.walmsley@sifive.com, richardcochran@gmail.com, robh+dt@kernel.org, sboyd@kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, haijiao.liu@sophgo.com, xiaoguang.xing@sophgo.com, guoren@kernel.org, jszhang@kernel.org, inochiama@outlook.com, samuel.holland@sifive.com Cc: Chen Wang , Rob Herring Subject: [PATCH v12 3/5] dt-bindings: clock: sophgo: add clkgen for SG2042 Date: Wed, 27 Mar 2024 16:30:20 +0800 Message-Id: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Chen Wang Add bindings for the clock generator of divider/mux and gates working for other subsystem than RP subsystem for Sophgo SG2042. Signed-off-by: Chen Wang Reviewed-by: Rob Herring --- .../bindings/clock/sophgo,sg2042-clkgen.yaml | 49 ++++++++ .../dt-bindings/clock/sophgo,sg2042-clkgen.h | 111 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sophgo,sg2042-c= lkgen.yaml create mode 100644 include/dt-bindings/clock/sophgo,sg2042-clkgen.h diff --git a/Documentation/devicetree/bindings/clock/sophgo,sg2042-clkgen.y= aml b/Documentation/devicetree/bindings/clock/sophgo,sg2042-clkgen.yaml new file mode 100644 index 000000000000..e31dece67215 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sophgo,sg2042-clkgen.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/sophgo,sg2042-clkgen.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SG2042 Clock Generator for divider/mux/gate + +maintainers: + - Chen Wang + +properties: + compatible: + const: sophgo,sg2042-clkgen + + reg: + maxItems: 1 + + clocks: + items: + - description: Main PLL + - description: Fixed PLL + - description: DDR PLL 0 + - description: DDR PLL 1 + + '#clock-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@30012000 { + compatible =3D "sophgo,sg2042-clkgen"; + reg =3D <0x30012000 0x1000>; + clocks =3D <&pllclk 0>, + <&pllclk 1>, + <&pllclk 2>, + <&pllclk 3>; + #clock-cells =3D <1>; + }; diff --git a/include/dt-bindings/clock/sophgo,sg2042-clkgen.h b/include/dt-= bindings/clock/sophgo,sg2042-clkgen.h new file mode 100644 index 000000000000..84f7857317a2 --- /dev/null +++ b/include/dt-bindings/clock/sophgo,sg2042-clkgen.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_SOPHGO_SG2042_CLKGEN_H__ +#define __DT_BINDINGS_SOPHGO_SG2042_CLKGEN_H__ + +#define DIV_CLK_MPLL_RP_CPU_NORMAL_0 0 +#define DIV_CLK_MPLL_AXI_DDR_0 1 +#define DIV_CLK_FPLL_DDR01_1 2 +#define DIV_CLK_FPLL_DDR23_1 3 +#define DIV_CLK_FPLL_RP_CPU_NORMAL_1 4 +#define DIV_CLK_FPLL_50M_A53 5 +#define DIV_CLK_FPLL_TOP_RP_CMN_DIV2 6 +#define DIV_CLK_FPLL_UART_500M 7 +#define DIV_CLK_FPLL_AHB_LPC 8 +#define DIV_CLK_FPLL_EFUSE 9 +#define DIV_CLK_FPLL_TX_ETH0 10 +#define DIV_CLK_FPLL_PTP_REF_I_ETH0 11 +#define DIV_CLK_FPLL_REF_ETH0 12 +#define DIV_CLK_FPLL_EMMC 13 +#define DIV_CLK_FPLL_SD 14 +#define DIV_CLK_FPLL_TOP_AXI0 15 +#define DIV_CLK_FPLL_TOP_AXI_HSPERI 16 +#define DIV_CLK_FPLL_AXI_DDR_1 17 +#define DIV_CLK_FPLL_DIV_TIMER1 18 +#define DIV_CLK_FPLL_DIV_TIMER2 19 +#define DIV_CLK_FPLL_DIV_TIMER3 20 +#define DIV_CLK_FPLL_DIV_TIMER4 21 +#define DIV_CLK_FPLL_DIV_TIMER5 22 +#define DIV_CLK_FPLL_DIV_TIMER6 23 +#define DIV_CLK_FPLL_DIV_TIMER7 24 +#define DIV_CLK_FPLL_DIV_TIMER8 25 +#define DIV_CLK_FPLL_100K_EMMC 26 +#define DIV_CLK_FPLL_100K_SD 27 +#define DIV_CLK_FPLL_GPIO_DB 28 +#define DIV_CLK_DPLL0_DDR01_0 29 +#define DIV_CLK_DPLL1_DDR23_0 30 + +#define GATE_CLK_RP_CPU_NORMAL_DIV0 31 +#define GATE_CLK_AXI_DDR_DIV0 32 + +#define GATE_CLK_RP_CPU_NORMAL_DIV1 33 +#define GATE_CLK_A53_50M 34 +#define GATE_CLK_TOP_RP_CMN_DIV2 35 +#define GATE_CLK_HSDMA 36 +#define GATE_CLK_EMMC_100M 37 +#define GATE_CLK_SD_100M 38 +#define GATE_CLK_TX_ETH0 39 +#define GATE_CLK_PTP_REF_I_ETH0 40 +#define GATE_CLK_REF_ETH0 41 +#define GATE_CLK_UART_500M 42 +#define GATE_CLK_EFUSE 43 + +#define GATE_CLK_AHB_LPC 44 +#define GATE_CLK_AHB_ROM 45 +#define GATE_CLK_AHB_SF 46 + +#define GATE_CLK_APB_UART 47 +#define GATE_CLK_APB_TIMER 48 +#define GATE_CLK_APB_EFUSE 49 +#define GATE_CLK_APB_GPIO 50 +#define GATE_CLK_APB_GPIO_INTR 51 +#define GATE_CLK_APB_SPI 52 +#define GATE_CLK_APB_I2C 53 +#define GATE_CLK_APB_WDT 54 +#define GATE_CLK_APB_PWM 55 +#define GATE_CLK_APB_RTC 56 + +#define GATE_CLK_AXI_PCIE0 57 +#define GATE_CLK_AXI_PCIE1 58 +#define GATE_CLK_SYSDMA_AXI 59 +#define GATE_CLK_AXI_DBG_I2C 60 +#define GATE_CLK_AXI_SRAM 61 +#define GATE_CLK_AXI_ETH0 62 +#define GATE_CLK_AXI_EMMC 63 +#define GATE_CLK_AXI_SD 64 +#define GATE_CLK_TOP_AXI0 65 +#define GATE_CLK_TOP_AXI_HSPERI 66 + +#define GATE_CLK_TIMER1 67 +#define GATE_CLK_TIMER2 68 +#define GATE_CLK_TIMER3 69 +#define GATE_CLK_TIMER4 70 +#define GATE_CLK_TIMER5 71 +#define GATE_CLK_TIMER6 72 +#define GATE_CLK_TIMER7 73 +#define GATE_CLK_TIMER8 74 +#define GATE_CLK_100K_EMMC 75 +#define GATE_CLK_100K_SD 76 +#define GATE_CLK_GPIO_DB 77 + +#define GATE_CLK_AXI_DDR_DIV1 78 +#define GATE_CLK_DDR01_DIV1 79 +#define GATE_CLK_DDR23_DIV1 80 + +#define GATE_CLK_DDR01_DIV0 81 +#define GATE_CLK_DDR23_DIV0 82 + +#define GATE_CLK_DDR01 83 +#define GATE_CLK_DDR23 84 +#define GATE_CLK_RP_CPU_NORMAL 85 +#define GATE_CLK_AXI_DDR 86 + +#define MUX_CLK_DDR01 87 +#define MUX_CLK_DDR23 88 +#define MUX_CLK_RP_CPU_NORMAL 89 +#define MUX_CLK_AXI_DDR 90 + +#endif /* __DT_BINDINGS_SOPHGO_SG2042_CLKGEN_H__ */ --=20 2.25.1 From nobody Wed Feb 11 09:21:19 2026 Received: from mail-ot1-f45.google.com (mail-ot1-f45.google.com [209.85.210.45]) (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 40F1B1EB2C; Wed, 27 Mar 2024 08:30:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528255; cv=none; b=KSGBZt3Hs8/Lbcc51BEW3SFWDwr+Y/ht6+YCuOgxIqC0/XqTaJkIIFktgUYbUCpBaKp+oErJxm2fKET/otr0Q+Pdg27JfWj5YusyvffDp+CU7jVt/PPLkpNnOannBhWvSuaP5h+SQTYDjbLtPoCdHtXJ0A0d5TtPAaOUdNds/fs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528255; c=relaxed/simple; bh=/Pr8ALsOpwmsABYxqGgHLTb9hh3yvsT0qllCg9IHKsE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=aj652ib85CkO5HvzjXeVEW1jmtCc1+8CgJVhnQ7jTdnSbe+nJ8w5TL3k+h8u6GfaZ2wj/5EhE+kdqiF8YM9lltBprLx/iKhK3v6fxcaYWBBNJfuYp/ddO+RqFsIdfXOZ0pF1D06tfzpZ2e+gBfhjqj0hO2205u/gWYMpJcJe1w8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=na1FrlqU; arc=none smtp.client-ip=209.85.210.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="na1FrlqU" Received: by mail-ot1-f45.google.com with SMTP id 46e09a7af769-6e68a30e6a1so269532a34.1; Wed, 27 Mar 2024 01:30:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711528251; x=1712133051; 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=td7eoHvJQvLFkiISPklx0FpYBo4DOezTHWA7sqELEro=; b=na1FrlqUO/eBKfd8XCHxoyyGqmkn7nymqKZxnlbRkJj5HboDrb1uTzkJFlnlXvi3Ni uhmHp11SkIJh1i0wFGJOdKimsshyn6JMOtb5j5brysoimoRD0jY3nazL/Bxd8pXtsqlo 7VXMe9F4fBBHBOxb2XmAPiL2PfdZRWTCMSTbLJkTe2J96pElLepMmHMuKFhQnjenUv31 CMgPieIHmHl9E3HC2Ell2NoZTKrBkpxQNeTxPwCE5r4ic2orRpyerc1HRRfanssBETE+ NLrM72dyr4u+g88k6XMCbzKd35DEX86/r+aE5izAFjI6wsXtUnck8ZEiKKYr9NgrcUYn oQSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711528251; x=1712133051; 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=td7eoHvJQvLFkiISPklx0FpYBo4DOezTHWA7sqELEro=; b=KOFnQ+jPWr3kGM2UmWsv6Y6pgWgkjTQleooPnZQ2xAKkXG1hNJvIHQo7mbyFY5fNkL Ca3T0wAgsbTQfotHLaUAjlL7kb/u+g3PA29mPm34CNrZXdPBDLsoT4w/R3BeTYTT3UrE Gphm8825O9aGdqiJ3NJKdaBaiPkmayTwmmC0jklW4i3gaH2AWwvZBCOPs6q/PBlKDlEB vpdw3qbWFQhPRWg7k3Q4PJkOqI9u5A0HtPZ2NxxnyFZztjeryIAiWyhwBnPUxu/eUd81 L+9Wz7+QjKXvFsUU7fncmgBIKzk2+3WmKUTlV0TwyvXkmvjmleBjIkoNqvSL9xYDDiN8 WMWQ== X-Forwarded-Encrypted: i=1; AJvYcCWAHBtFrrXqwPmKjeLGsofwgG3Ash7R/4+n6cd0cGT7cfk7zU3coyprTxzJvF+pKGtToM9AfNyaYfaU6tgFZ9VrmPUdjvC8YHTV2efg+xYtbQJ+K6mx8ds0mRkzh15+0KiBembGk16+x8XDcYEH4skQdLaqvrWUk9ctXxuA/XNK7GdfqQ== X-Gm-Message-State: AOJu0YyNKXbRkIwocpEnwiNNaz9VzjRJFI29Ac0UU+086o8O7/MJenzY 1afly7Pes1eg5NvFdAddrf59mo7R5WrsD9AqPdLcVScYYa9V5UkZ X-Google-Smtp-Source: AGHT+IFwL36ECe8LK3oegZ0upil8vs46qtJcNjzxQ+Iqp4cqlcYdEWxk1fkW4rjH/37iaCjrf1mfvA== X-Received: by 2002:a9d:6459:0:b0:6e6:ab41:b335 with SMTP id m25-20020a9d6459000000b006e6ab41b335mr1631103otl.9.1711528250988; Wed, 27 Mar 2024 01:30:50 -0700 (PDT) Received: from localhost.localdomain ([122.8.183.87]) by smtp.gmail.com with ESMTPSA id c25-20020a9d7859000000b006e6a853888fsm1897455otm.36.2024.03.27.01.30.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Mar 2024 01:30:50 -0700 (PDT) From: Chen Wang To: aou@eecs.berkeley.edu, chao.wei@sophgo.com, conor@kernel.org, krzysztof.kozlowski+dt@linaro.org, mturquette@baylibre.com, palmer@dabbelt.com, paul.walmsley@sifive.com, richardcochran@gmail.com, robh+dt@kernel.org, sboyd@kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, haijiao.liu@sophgo.com, xiaoguang.xing@sophgo.com, guoren@kernel.org, jszhang@kernel.org, inochiama@outlook.com, samuel.holland@sifive.com Cc: Chen Wang Subject: [PATCH v12 4/5] clk: sophgo: Add SG2042 clock driver Date: Wed, 27 Mar 2024 16:30:43 +0800 Message-Id: <9d0fbeace76112ec16838199c010ac185347d886.1711527932.git.unicorn_wang@outlook.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Chen Wang Add a driver for the SOPHGO SG2042 clocks. Signed-off-by: Chen Wang --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sophgo/Kconfig | 7 + drivers/clk/sophgo/Makefile | 2 + drivers/clk/sophgo/clk-sophgo-sg2042.c | 1410 ++++++++++++++++++++++++ drivers/clk/sophgo/clk-sophgo-sg2042.h | 216 ++++ 6 files changed, 1637 insertions(+) create mode 100644 drivers/clk/sophgo/Kconfig create mode 100644 drivers/clk/sophgo/Makefile create mode 100644 drivers/clk/sophgo/clk-sophgo-sg2042.c create mode 100644 drivers/clk/sophgo/clk-sophgo-sg2042.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 50af5fc7f570..bc28502ec3c9 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -489,6 +489,7 @@ source "drivers/clk/rockchip/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/sifive/Kconfig" source "drivers/clk/socfpga/Kconfig" +source "drivers/clk/sophgo/Kconfig" source "drivers/clk/sprd/Kconfig" source "drivers/clk/starfive/Kconfig" source "drivers/clk/sunxi/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 14fa8d4ecc1f..4abe16c8ccdf 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -118,6 +118,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) +=3D rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) +=3D samsung/ obj-$(CONFIG_CLK_SIFIVE) +=3D sifive/ obj-y +=3D socfpga/ +obj-y +=3D sophgo/ obj-$(CONFIG_PLAT_SPEAR) +=3D spear/ obj-y +=3D sprd/ obj-$(CONFIG_ARCH_STI) +=3D st/ diff --git a/drivers/clk/sophgo/Kconfig b/drivers/clk/sophgo/Kconfig new file mode 100644 index 000000000000..2523818d64f9 --- /dev/null +++ b/drivers/clk/sophgo/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 + +config CLK_SOPHGO_SG2042 + bool "Sophgo SG2042 clock support" + depends on ARCH_SOPHGO || COMPILE_TEST + help + Say yes here to support the clock controller on the Sophgo SG2042 SoC. diff --git a/drivers/clk/sophgo/Makefile b/drivers/clk/sophgo/Makefile new file mode 100644 index 000000000000..13834cce260c --- /dev/null +++ b/drivers/clk/sophgo/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CLK_SOPHGO_SG2042) +=3D clk-sophgo-sg2042.o diff --git a/drivers/clk/sophgo/clk-sophgo-sg2042.c b/drivers/clk/sophgo/cl= k-sophgo-sg2042.c new file mode 100644 index 000000000000..a5648ff9f8d6 --- /dev/null +++ b/drivers/clk/sophgo/clk-sophgo-sg2042.c @@ -0,0 +1,1410 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sophgo SG2042 Clock Generator Driver + * + * Copyright (C) 2024 Sophgo Technology Inc. All rights reserved. + */ + +#include +#include +#include +#include + +/* + * The clock of SG2042 is composed of three parts. + * The registers of these three parts of the clock are scattered in three + * different memory address spaces: + * - pll clocks + * - gate clocks for RP subsystem + * - div/mux, and gate clocks working for other subsystem than RP subsystem + */ +#include +#include +#include + +#include "clk-sophgo-sg2042.h" + +#define KHZ 1000UL +#define MHZ (KHZ * KHZ) + +#define REFDIV_MIN 1 +#define REFDIV_MAX 63 +#define FBDIV_MIN 16 +#define FBDIV_MAX 320 + +#define PLL_FREF_SG2042 (25 * MHZ) + +#define PLL_FOUTPOSTDIV_MIN (16 * MHZ) +#define PLL_FOUTPOSTDIV_MAX (3200 * MHZ) + +#define PLL_FOUTVCO_MIN (800 * MHZ) +#define PLL_FOUTVCO_MAX (3200 * MHZ) + +struct sg2042_pll_ctrl { + unsigned long freq; + unsigned int fbdiv; + unsigned int postdiv1; + unsigned int postdiv2; + unsigned int refdiv; +}; + +#define PLLCTRL_FBDIV_SHIFT 16 +#define PLLCTRL_FBDIV_MASK (GENMASK(27, 16) >> PLLCTRL_FBDIV_SHIFT) +#define PLLCTRL_POSTDIV2_SHIFT 12 +#define PLLCTRL_POSTDIV2_MASK (GENMASK(14, 12) >> PLLCTRL_POSTDIV2_SHIFT) +#define PLLCTRL_POSTDIV1_SHIFT 8 +#define PLLCTRL_POSTDIV1_MASK (GENMASK(10, 8) >> PLLCTRL_POSTDIV1_SHIFT) +#define PLLCTRL_REFDIV_SHIFT 0 +#define PLLCTRL_REFDIV_MASK (GENMASK(5, 0) >> PLLCTRL_REFDIV_SHIFT) + +static inline u32 sg2042_pll_ctrl_encode(struct sg2042_pll_ctrl *ctrl) +{ + return ((ctrl->fbdiv & PLLCTRL_FBDIV_MASK) << PLLCTRL_FBDIV_SHIFT) | + ((ctrl->postdiv2 & PLLCTRL_POSTDIV2_MASK) << PLLCTRL_POSTDIV2_SHIF= T) | + ((ctrl->postdiv1 & PLLCTRL_POSTDIV1_MASK) << PLLCTRL_POSTDIV1_SHIF= T) | + ((ctrl->refdiv & PLLCTRL_REFDIV_MASK) << PLLCTRL_REFDIV_SHIFT); +} + +static inline void sg2042_pll_ctrl_decode(unsigned int reg_value, + struct sg2042_pll_ctrl *ctrl) +{ + ctrl->fbdiv =3D (reg_value >> PLLCTRL_FBDIV_SHIFT) & PLLCTRL_FBDIV_MASK; + ctrl->refdiv =3D (reg_value >> PLLCTRL_REFDIV_SHIFT) & PLLCTRL_REFDIV_MAS= K; + ctrl->postdiv1 =3D (reg_value >> PLLCTRL_POSTDIV1_SHIFT) & PLLCTRL_POSTDI= V1_MASK; + ctrl->postdiv2 =3D (reg_value >> PLLCTRL_POSTDIV2_SHIFT) & PLLCTRL_POSTDI= V2_MASK; +} + +static inline int sg2042_pll_enable(struct sg2042_pll_clock *pll, bool en) +{ + unsigned int value =3D 0; + + if (en) { + /* wait pll lock */ + if (readl_poll_timeout_atomic(pll->base + pll->offset_status, + value, + ((value >> pll->shift_status_lock) & 0x1), + 0, + 100000)) + pr_warn("%s not locked\n", pll->hw.init->name); + + /* wait pll updating */ + if (readl_poll_timeout_atomic(pll->base + pll->offset_status, + value, + !((value >> pll->shift_status_updating) & 0x1), + 0, + 100000)) + pr_warn("%s still updating\n", pll->hw.init->name); + + /* enable pll */ + value =3D readl(pll->base + pll->offset_enable); + writel(value | (1 << pll->shift_enable), pll->base + pll->offset_enable); + } else { + /* disable pll */ + value =3D readl(pll->base + pll->offset_enable); + writel(value & (~(1 << pll->shift_enable)), pll->base + pll->offset_enab= le); + } + + return 0; +} + +/* + * @reg_value: current register value + * @parent_rate: parent frequency + * + * This function is used to calculate below "rate" in equation + * rate =3D (parent_rate/REFDIV) x FBDIV/POSTDIV1/POSTDIV2 + * =3D (parent_rate x FBDIV) / (REFDIV x POSTDIV1 x POSTDIV2) + */ +static unsigned long sg2042_pll_recalc_rate(unsigned int reg_value, + unsigned long parent_rate) +{ + struct sg2042_pll_ctrl ctrl_table; + u64 rate, numerator, denominator; + + sg2042_pll_ctrl_decode(reg_value, &ctrl_table); + + numerator =3D parent_rate * ctrl_table.fbdiv; + denominator =3D ctrl_table.refdiv * ctrl_table.postdiv1 * ctrl_table.post= div2; + do_div(numerator, denominator); + rate =3D numerator; + + return rate; +} + +/* + * Based on input rate/prate/fbdiv/refdiv, look up the postdiv1_2 table + * to get the closest postdiiv combination. + * postdiv1_2 contains all the possible combination lists of POSTDIV1 and = POSTDIV2 + * for example: + * postdiv1_2[0] =3D {2, 4, 8}, where div1 =3D 2, div2 =3D 4 , div1 * div2= =3D 8 + * + * See TRM: + * FOUTPOSTDIV =3D FREF * FBDIV / REFDIV / (POSTDIV1 * POSTDIV2) + * So we get following formula to get POSTDIV1 and POSTDIV2: + * POSTDIV =3D (prate/REFDIV) x FBDIV/rate + * above POSTDIV =3D POSTDIV1*POSTDIV2 + * + * @rate: FOUTPOSTDIV + * @prate: parent rate, i.e. FREF + * @fbdiv: FBDIV + * @refdiv: REFDIV + * @postdiv1: POSTDIV1, output + * @postdiv2: POSTDIV2, output + */ +static int sg2042_pll_get_postdiv_1_2(unsigned long rate, + unsigned long prate, + unsigned int fbdiv, + unsigned int refdiv, + unsigned int *postdiv1, + unsigned int *postdiv2) +{ + int index; + u64 tmp0; + + /* POSTDIV_RESULT_INDEX point to 3rd element in the array postdiv1_2 */ + #define POSTDIV_RESULT_INDEX 2 + + static int postdiv1_2[][3] =3D { + {2, 4, 8}, {3, 3, 9}, {2, 5, 10}, {2, 6, 12}, + {2, 7, 14}, {3, 5, 15}, {4, 4, 16}, {3, 6, 18}, + {4, 5, 20}, {3, 7, 21}, {4, 6, 24}, {5, 5, 25}, + {4, 7, 28}, {5, 6, 30}, {5, 7, 35}, {6, 6, 36}, + {6, 7, 42}, {7, 7, 49} + }; + + /* prate/REFDIV and result save to tmp0 */ + tmp0 =3D prate; + do_div(tmp0, refdiv); + + /* ((prate/REFDIV) x FBDIV) and result save to tmp0 */ + tmp0 *=3D fbdiv; + + /* ((prate/REFDIV) x FBDIV)/rate and result save to tmp0 */ + do_div(tmp0, rate); + + /* tmp0 is POSTDIV1*POSTDIV2, now we calculate div1 and div2 value */ + if (tmp0 <=3D 7) { + /* (div1 * div2) <=3D 7, no need to use array search */ + *postdiv1 =3D tmp0; + *postdiv2 =3D 1; + return 0; + } + + /* (div1 * div2) > 7, use array search */ + for (index =3D 0; index < ARRAY_SIZE(postdiv1_2); index++) { + if (tmp0 > postdiv1_2[index][POSTDIV_RESULT_INDEX]) { + continue; + } else { + /* found it */ + *postdiv1 =3D postdiv1_2[index][1]; + *postdiv2 =3D postdiv1_2[index][0]; + return 0; + } + } + pr_warn("%s can not find in postdiv array!\n", __func__); + return -EINVAL; +} + +/* + * Based on the given FOUTPISTDIV and the input FREF to calculate + * the REFDIV/FBDIV/PSTDIV1/POSTDIV2 combination for pllctrl register. + * @req_rate: expected output clock rate, i.e. FOUTPISTDIV + * @parent_rate: input parent clock rate, i.e. FREF + * @best: output to hold calculated combination of REFDIV/FBDIV/PSTDIV1/PO= STDIV2 + */ +static int sg2042_get_pll_ctl_setting(struct sg2042_pll_ctrl *best, + unsigned long req_rate, + unsigned long parent_rate) +{ + int ret; + unsigned int fbdiv, refdiv, postdiv1, postdiv2; + unsigned long foutpostdiv; + u64 tmp; + u64 foutvco; + + if (parent_rate !=3D PLL_FREF_SG2042) { + pr_err("INVALID FREF: %ld\n", parent_rate); + return -EINVAL; + } + + if (req_rate < PLL_FOUTPOSTDIV_MIN || req_rate > PLL_FOUTPOSTDIV_MAX) { + pr_alert("INVALID FOUTPOSTDIV: %ld\n", req_rate); + return -EINVAL; + } + + memset(best, 0, sizeof(struct sg2042_pll_ctrl)); + + for (refdiv =3D REFDIV_MIN; refdiv < REFDIV_MAX + 1; refdiv++) { + /* required by hardware: FREF/REFDIV must > 10 */ + tmp =3D parent_rate; + do_div(tmp, refdiv); + if (tmp <=3D 10) + continue; + + for (fbdiv =3D FBDIV_MIN; fbdiv < FBDIV_MAX + 1; fbdiv++) { + /* + * FOUTVCO =3D FREF*FBDIV/REFDIV validation + * required by hardware, FOUTVCO must [800MHz, 3200MHz] + */ + foutvco =3D parent_rate * fbdiv; + do_div(foutvco, refdiv); + if (foutvco < PLL_FOUTVCO_MIN || foutvco > PLL_FOUTVCO_MAX) + continue; + + ret =3D sg2042_pll_get_postdiv_1_2(req_rate, parent_rate, + fbdiv, refdiv, + &postdiv1, &postdiv2); + if (ret) + continue; + + /* + * FOUTPOSTDIV =3D FREF*FBDIV/REFDIV/(POSTDIV1*POSTDIV2) + * =3D FOUTVCO/(POSTDIV1*POSTDIV2) + */ + tmp =3D foutvco; + do_div(tmp, (postdiv1 * postdiv2)); + foutpostdiv =3D (unsigned long)tmp; + /* Iterative to approach the expected value */ + if (abs_diff(foutpostdiv, req_rate) < abs_diff(best->freq, req_rate)) { + best->freq =3D foutpostdiv; + best->refdiv =3D refdiv; + best->fbdiv =3D fbdiv; + best->postdiv1 =3D postdiv1; + best->postdiv2 =3D postdiv2; + if (foutpostdiv =3D=3D req_rate) + return 0; + } + continue; + } + } + + if (best->freq =3D=3D 0) + return -EINVAL; + else + return 0; +} + +/* + * @hw: ccf use to hook get sg2042_pll_clock + * @parent_rate: parent rate + * + * The is function will be called through clk_get_rate + * and return current rate after decoding reg value + */ +static unsigned long sg2042_clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + unsigned int value; + unsigned long rate; + struct sg2042_pll_clock *pll =3D to_sg2042_pll_clk(hw); + + value =3D readl(pll->base + pll->offset_ctrl); + rate =3D sg2042_pll_recalc_rate(value, parent_rate); + + pr_debug("--> %s: pll_recalc_rate: val =3D %ld\n", + clk_hw_get_name(hw), rate); + return rate; +} + +static long sg2042_clk_pll_round_rate(struct clk_hw *hw, + unsigned long req_rate, + unsigned long *prate) +{ + unsigned int value; + struct sg2042_pll_ctrl pctrl_table; + long proper_rate; + int ret; + + ret =3D sg2042_get_pll_ctl_setting(&pctrl_table, req_rate, *prate); + if (ret) { + proper_rate =3D 0; + goto out; + } + + value =3D sg2042_pll_ctrl_encode(&pctrl_table); + proper_rate =3D (long)sg2042_pll_recalc_rate(value, *prate); + +out: + pr_debug("--> %s: pll_round_rate: val =3D %ld\n", + clk_hw_get_name(hw), proper_rate); + return proper_rate; +} + +static int sg2042_clk_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + req->rate =3D sg2042_clk_pll_round_rate(hw, min(req->rate, req->max_rate), + &req->best_parent_rate); + pr_debug("--> %s: pll_determine_rate: val =3D %ld\n", + clk_hw_get_name(hw), req->rate); + return 0; +} + +static int sg2042_clk_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned long flags; + unsigned int value; + int ret =3D 0; + struct sg2042_pll_ctrl pctrl_table; + struct sg2042_pll_clock *pll =3D to_sg2042_pll_clk(hw); + + spin_lock_irqsave(pll->lock, flags); + if (sg2042_pll_enable(pll, 0)) { + pr_warn("Can't disable pll(%s), status error\n", pll->hw.init->name); + goto out; + } + ret =3D sg2042_get_pll_ctl_setting(&pctrl_table, rate, parent_rate); + if (ret) { + pr_warn("%s: Can't find a proper pll setting\n", pll->hw.init->name); + goto out2; + } + + value =3D sg2042_pll_ctrl_encode(&pctrl_table); + + /* write the value to top register */ + writel(value, pll->base + pll->offset_ctrl); + +out2: + sg2042_pll_enable(pll, 1); +out: + spin_unlock_irqrestore(pll->lock, flags); + + pr_debug("--> %s: pll_set_rate: val =3D 0x%x\n", + clk_hw_get_name(hw), value); + return ret; +} + +static const struct clk_ops sg2042_clk_pll_ops =3D { + .recalc_rate =3D sg2042_clk_pll_recalc_rate, + .round_rate =3D sg2042_clk_pll_round_rate, + .determine_rate =3D sg2042_clk_pll_determine_rate, + .set_rate =3D sg2042_clk_pll_set_rate, +}; + +static const struct clk_ops sg2042_clk_pll_ro_ops =3D { + .recalc_rate =3D sg2042_clk_pll_recalc_rate, + .round_rate =3D sg2042_clk_pll_round_rate, +}; + +static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sg2042_divider_clock *divider =3D to_sg2042_clk_divider(hw); + unsigned int val; + unsigned long ret_rate; + + if (!(readl(divider->reg) & BIT(3))) { + val =3D (int)(divider->initval); + } else { + val =3D readl(divider->reg) >> divider->shift; + val &=3D clk_div_mask(divider->width); + } + + ret_rate =3D divider_recalc_rate(hw, parent_rate, val, NULL, + divider->div_flags, divider->width); + + pr_debug("--> %s: divider_recalc_rate: ret_rate =3D %ld\n", + clk_hw_get_name(hw), ret_rate); + return ret_rate; +} + +static long sg2042_clk_divider_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + int bestdiv; + unsigned long ret_rate; + struct sg2042_divider_clock *divider =3D to_sg2042_clk_divider(hw); + + /* if read only, just return current value */ + if (divider->div_flags & CLK_DIVIDER_READ_ONLY) { + if (!(readl(divider->reg) & BIT(3))) { + bestdiv =3D (int)(divider->initval); + } else { + bestdiv =3D readl(divider->reg) >> divider->shift; + bestdiv &=3D clk_div_mask(divider->width); + } + ret_rate =3D DIV_ROUND_UP_ULL((u64)*prate, bestdiv); + } else { + ret_rate =3D divider_round_rate(hw, rate, prate, NULL, + divider->width, divider->div_flags); + } + + pr_debug("--> %s: divider_round_rate: val =3D %ld\n", + clk_hw_get_name(hw), ret_rate); + return ret_rate; +} + +static int sg2042_clk_divider_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned int value; + unsigned int val, val2; + unsigned long flags =3D 0; + struct sg2042_divider_clock *divider =3D to_sg2042_clk_divider(hw); + + value =3D divider_get_val(rate, parent_rate, NULL, + divider->width, divider->div_flags); + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + /* + * The sequence of clock frequency modification is: + * Assert to reset divider. + * Modify the value of Clock Divide Factor (and High Wide if needed). + * De-assert to restore divided clock with new frequency. + */ + val =3D readl(divider->reg); + + /* assert */ + val &=3D ~0x1; + writel(val, divider->reg); + + if (divider->div_flags & CLK_DIVIDER_HIWORD_MASK) { + val =3D clk_div_mask(divider->width) << (divider->shift + 16); + } else { + val =3D readl(divider->reg); + val &=3D ~(clk_div_mask(divider->width) << divider->shift); + } + val |=3D value << divider->shift; + val |=3D 1 << 3; + writel(val, divider->reg); + val2 =3D val; + + /* de-assert */ + val |=3D 1; + writel(val, divider->reg); + + if (divider->lock) + spin_unlock_irqrestore(divider->lock, flags); + else + __release(divider->lock); + + pr_debug("--> %s: divider_set_rate: register val =3D 0x%x\n", + clk_hw_get_name(hw), val2); + return 0; +} + +static const struct clk_ops sg2042_clk_divider_ops =3D { + .recalc_rate =3D sg2042_clk_divider_recalc_rate, + .round_rate =3D sg2042_clk_divider_round_rate, + .set_rate =3D sg2042_clk_divider_set_rate, +}; + +static const struct clk_ops sg2042_clk_divider_ro_ops =3D { + .recalc_rate =3D sg2042_clk_divider_recalc_rate, + .round_rate =3D sg2042_clk_divider_round_rate, +}; + +#define SG2042_PLL(_id, _name, _parent_name, _r_stat, _r_enable, _r_ctrl, = _shift) \ + { \ + .hw.init =3D CLK_HW_INIT( \ + _name, \ + _parent_name, \ + &sg2042_clk_pll_ops, \ + CLK_GET_RATE_NOCACHE | CLK_GET_ACCURACY_NOCACHE),\ + .id =3D _id, \ + .offset_ctrl =3D _r_ctrl, \ + .offset_status =3D _r_stat, \ + .offset_enable =3D _r_enable, \ + .shift_status_lock =3D 8 + (_shift), \ + .shift_status_updating =3D _shift, \ + .shift_enable =3D _shift, \ + } + +#define SG2042_PLL_RO(_id, _name, _parent_name, _r_stat, _r_enable, _r_ctr= l, _shift) \ + { \ + .hw.init =3D CLK_HW_INIT( \ + _name, \ + _parent_name, \ + &sg2042_clk_pll_ro_ops, \ + CLK_GET_RATE_NOCACHE | CLK_GET_ACCURACY_NOCACHE),\ + .id =3D _id, \ + .offset_ctrl =3D _r_ctrl, \ + .offset_status =3D _r_stat, \ + .offset_enable =3D _r_enable, \ + .shift_status_lock =3D 8 + (_shift), \ + .shift_status_updating =3D _shift, \ + .shift_enable =3D _shift, \ + } + +static struct sg2042_pll_clock sg2042_pll_clks[] =3D { + SG2042_PLL(MPLL_CLK, "mpll_clock", "cgi_main", + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_MPLL_CONTROL, 0), + SG2042_PLL_RO(FPLL_CLK, "fpll_clock", "cgi_main", + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_FPLL_CONTROL, 3), + SG2042_PLL_RO(DPLL0_CLK, "dpll0_clock", "cgi_dpll0", + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_DPLL0_CONTROL, 4), + SG2042_PLL_RO(DPLL1_CLK, "dpll1_clock", "cgi_dpll1", + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_DPLL1_CONTROL, 5), +}; + +#define SG2042_DIV(_id, _name, _parent_name, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .hw.init =3D CLK_HW_INIT( \ + _name, \ + _parent_name, \ + &sg2042_clk_divider_ops, \ + 0), \ + .id =3D _id, \ + .offset_ctrl =3D _r_ctrl, \ + .shift =3D _shift, \ + .width =3D _width, \ + .div_flags =3D _div_flag, \ + .initval =3D _initval, \ + } + +#define SG2042_DIV_RO(_id, _name, _parent_name, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .hw.init =3D CLK_HW_INIT( \ + _name, \ + _parent_name, \ + &sg2042_clk_divider_ro_ops, \ + 0), \ + .id =3D _id, \ + .offset_ctrl =3D _r_ctrl, \ + .shift =3D _shift, \ + .width =3D _width, \ + .div_flags =3D (_div_flag) | CLK_DIVIDER_READ_ONLY, \ + .initval =3D _initval, \ + } + +/* + * DIV items in the array are sorted according to the clock-tree diagram, + * from top to bottom, from upstream to downstream. Read TRM for details. + */ +#define DEF_DIVFLAG (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO) +static struct sg2042_divider_clock sg2042_div_clks[] =3D { + SG2042_DIV_RO(DIV_CLK_DPLL0_DDR01_0, + "clk_div_ddr01_0", "clk_gate_ddr01_div0", + R_CLKDIVREG27, 16, 5, DEF_DIVFLAG, 1), + SG2042_DIV_RO(DIV_CLK_FPLL_DDR01_1, + "clk_div_ddr01_1", "clk_gate_ddr01_div1", + R_CLKDIVREG28, 16, 5, DEF_DIVFLAG, 1), + + SG2042_DIV_RO(DIV_CLK_DPLL1_DDR23_0, + "clk_div_ddr23_0", "clk_gate_ddr23_div0", + R_CLKDIVREG29, 16, 5, DEF_DIVFLAG, 1), + SG2042_DIV_RO(DIV_CLK_FPLL_DDR23_1, + "clk_div_ddr23_1", "clk_gate_ddr23_div1", + R_CLKDIVREG30, 16, 5, DEF_DIVFLAG, 1), + + SG2042_DIV(DIV_CLK_MPLL_RP_CPU_NORMAL_0, + "clk_div_rp_cpu_normal_0", "clk_gate_rp_cpu_normal_div0", + R_CLKDIVREG0, 16, 5, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_RP_CPU_NORMAL_1, + "clk_div_rp_cpu_normal_1", "clk_gate_rp_cpu_normal_div1", + R_CLKDIVREG1, 16, 5, DEF_DIVFLAG, 1), + + SG2042_DIV(DIV_CLK_MPLL_AXI_DDR_0, + "clk_div_axi_ddr_0", "clk_gate_axi_ddr_div0", + R_CLKDIVREG25, 16, 5, DEF_DIVFLAG, 2), + SG2042_DIV(DIV_CLK_FPLL_AXI_DDR_1, + "clk_div_axi_ddr_1", "clk_gate_axi_ddr_div1", + R_CLKDIVREG26, 16, 5, DEF_DIVFLAG, 1), + + SG2042_DIV(DIV_CLK_FPLL_TOP_RP_CMN_DIV2, + "clk_div_top_rp_cmn_div2", "clk_mux_rp_cpu_normal", + R_CLKDIVREG3, 16, 16, DEF_DIVFLAG, 2), + + SG2042_DIV(DIV_CLK_FPLL_50M_A53, "clk_div_50m_a53", "fpll_clock", + R_CLKDIVREG2, 16, 8, DEF_DIVFLAG, 20), + /* downstream of div_50m_a53 */ + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER1, "clk_div_timer1", "clk_div_50m_a53", + R_CLKDIVREG6, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER2, "clk_div_timer2", "clk_div_50m_a53", + R_CLKDIVREG7, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER3, "clk_div_timer3", "clk_div_50m_a53", + R_CLKDIVREG8, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER4, "clk_div_timer4", "clk_div_50m_a53", + R_CLKDIVREG9, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER5, "clk_div_timer5", "clk_div_50m_a53", + R_CLKDIVREG10, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER6, "clk_div_timer6", "clk_div_50m_a53", + R_CLKDIVREG11, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER7, "clk_div_timer7", "clk_div_50m_a53", + R_CLKDIVREG12, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER8, "clk_div_timer8", "clk_div_50m_a53", + R_CLKDIVREG13, 16, 16, DEF_DIVFLAG, 1), + + /* + * Set clk_div_uart_500m as RO, because the width of CLKDIVREG4 is too + * narrow for us to produce 115200. Use UART internal divider directly. + */ + SG2042_DIV_RO(DIV_CLK_FPLL_UART_500M, "clk_div_uart_500m", "fpll_clock", + R_CLKDIVREG4, 16, 7, DEF_DIVFLAG, 2), + SG2042_DIV(DIV_CLK_FPLL_AHB_LPC, "clk_div_ahb_lpc", "fpll_clock", + R_CLKDIVREG5, 16, 16, DEF_DIVFLAG, 5), + SG2042_DIV(DIV_CLK_FPLL_EFUSE, "clk_div_efuse", "fpll_clock", + R_CLKDIVREG14, 16, 7, DEF_DIVFLAG, 40), + SG2042_DIV(DIV_CLK_FPLL_TX_ETH0, "clk_div_tx_eth0", "fpll_clock", + R_CLKDIVREG16, 16, 11, DEF_DIVFLAG, 8), + SG2042_DIV(DIV_CLK_FPLL_PTP_REF_I_ETH0, + "clk_div_ptp_ref_i_eth0", "fpll_clock", + R_CLKDIVREG17, 16, 8, DEF_DIVFLAG, 20), + SG2042_DIV(DIV_CLK_FPLL_REF_ETH0, "clk_div_ref_eth0", "fpll_clock", + R_CLKDIVREG18, 16, 8, DEF_DIVFLAG, 40), + SG2042_DIV(DIV_CLK_FPLL_EMMC, "clk_div_emmc", "fpll_clock", + R_CLKDIVREG19, 16, 5, DEF_DIVFLAG, 10), + SG2042_DIV(DIV_CLK_FPLL_SD, "clk_div_sd", "fpll_clock", + R_CLKDIVREG21, 16, 5, DEF_DIVFLAG, 10), + + SG2042_DIV(DIV_CLK_FPLL_TOP_AXI0, "clk_div_top_axi0", "fpll_clock", + R_CLKDIVREG23, 16, 5, DEF_DIVFLAG, 10), + /* downstream of div_top_axi0 */ + SG2042_DIV(DIV_CLK_FPLL_100K_EMMC, "clk_div_100k_emmc", "clk_div_top_axi0= ", + R_CLKDIVREG20, 16, 16, DEF_DIVFLAG, 1000), + SG2042_DIV(DIV_CLK_FPLL_100K_SD, "clk_div_100k_sd", "clk_div_top_axi0", + R_CLKDIVREG22, 16, 16, DEF_DIVFLAG, 1000), + SG2042_DIV(DIV_CLK_FPLL_GPIO_DB, "clk_div_gpio_db", "clk_div_top_axi0", + R_CLKDIVREG15, 16, 16, DEF_DIVFLAG, 1000), + + SG2042_DIV(DIV_CLK_FPLL_TOP_AXI_HSPERI, + "clk_div_top_axi_hsperi", "fpll_clock", + R_CLKDIVREG24, 16, 5, DEF_DIVFLAG, 4), +}; + +#define SG2042_GATE(_id, _name, _parent_name, _flags, \ + _r_enable, _bit_idx) { \ + .hw.init =3D CLK_HW_INIT( \ + _name, \ + _parent_name, \ + NULL, \ + _flags), \ + .id =3D _id, \ + .offset_enable =3D _r_enable, \ + .bit_idx =3D _bit_idx, \ + } + +/* + * GATE items in the array are sorted according to the clock-tree diagram, + * from top to bottom, from upstream to downstream. Read TRM for details. + */ + +/* Gate clocks which control registers are defined in CLOCK. */ +static const struct sg2042_gate_clock sg2042_gate_clks[] =3D { + SG2042_GATE(GATE_CLK_DDR01_DIV0, "clk_gate_ddr01_div0", "dpll0_clock", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + R_CLKDIVREG27, 4), + SG2042_GATE(GATE_CLK_DDR01_DIV1, "clk_gate_ddr01_div1", "fpll_clock", + CLK_IS_CRITICAL, + R_CLKDIVREG28, 4), + + SG2042_GATE(GATE_CLK_DDR23_DIV0, "clk_gate_ddr23_div0", "dpll1_clock", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + R_CLKDIVREG29, 4), + SG2042_GATE(GATE_CLK_DDR23_DIV1, "clk_gate_ddr23_div1", "fpll_clock", + CLK_IS_CRITICAL, + R_CLKDIVREG30, 4), + + SG2042_GATE(GATE_CLK_RP_CPU_NORMAL_DIV0, "clk_gate_rp_cpu_normal_div0", "= mpll_clock", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKDIVREG0, 4), + SG2042_GATE(GATE_CLK_RP_CPU_NORMAL_DIV1, + "clk_gate_rp_cpu_normal_div1", "fpll_clock", + CLK_IS_CRITICAL, + R_CLKDIVREG1, 4), + + SG2042_GATE(GATE_CLK_AXI_DDR_DIV0, "clk_gate_axi_ddr_div0", "mpll_clock", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKDIVREG25, 4), + SG2042_GATE(GATE_CLK_AXI_DDR_DIV1, "clk_gate_axi_ddr_div1", "fpll_clock", + CLK_IS_CRITICAL, + R_CLKDIVREG26, 4), + + /* upon are gate clocks as input source for the muxes */ + + SG2042_GATE(GATE_CLK_DDR01, "clk_gate_ddr01", "clk_mux_ddr01", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 14), + + SG2042_GATE(GATE_CLK_DDR23, "clk_gate_ddr23", "clk_mux_ddr23", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 15), + + SG2042_GATE(GATE_CLK_RP_CPU_NORMAL, + "clk_gate_rp_cpu_normal", "clk_mux_rp_cpu_normal", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG0, 0), + + SG2042_GATE(GATE_CLK_AXI_DDR, "clk_gate_axi_ddr", "clk_mux_axi_ddr", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 13), + + /* upon are gate clocks directly downstream of muxes */ + + /* downstream of clk_div_top_rp_cmn_div2 */ + SG2042_GATE(GATE_CLK_TOP_RP_CMN_DIV2, + "clk_gate_top_rp_cmn_div2", "clk_div_top_rp_cmn_div2", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 2), + SG2042_GATE(GATE_CLK_HSDMA, "clk_gate_hsdma", "clk_gate_top_rp_cmn_div2", + CLK_SET_RATE_PARENT, R_CLKENREG1, 10), + + /* + * downstream of clk_gate_rp_cpu_normal + * + * FIXME: there should be one 1/2 DIV between clk_gate_rp_cpu_normal + * and clk_gate_axi_pcie0/clk_gate_axi_pcie1. + * But the 1/2 DIV is fixed and no configurable register exported, so + * when reading from these two clocks, the rate value are still the + * same as that of clk_gate_rp_cpu_normal, it's not correct. + * This just affects the value read. + */ + SG2042_GATE(GATE_CLK_AXI_PCIE0, + "clk_gate_axi_pcie0", "clk_gate_rp_cpu_normal", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 8), + SG2042_GATE(GATE_CLK_AXI_PCIE1, + "clk_gate_axi_pcie1", "clk_gate_rp_cpu_normal", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 9), + + /* downstream of div_50m_a53 */ + SG2042_GATE(GATE_CLK_A53_50M, "clk_gate_a53_50m", "clk_div_50m_a53", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 1), + SG2042_GATE(GATE_CLK_TIMER1, "clk_gate_timer1", "clk_div_timer1", + CLK_SET_RATE_PARENT, R_CLKENREG0, 12), + SG2042_GATE(GATE_CLK_TIMER2, "clk_gate_timer2", "clk_div_timer2", + CLK_SET_RATE_PARENT, R_CLKENREG0, 13), + SG2042_GATE(GATE_CLK_TIMER3, "clk_gate_timer3", "clk_div_timer3", + CLK_SET_RATE_PARENT, R_CLKENREG0, 14), + SG2042_GATE(GATE_CLK_TIMER4, "clk_gate_timer4", "clk_div_timer4", + CLK_SET_RATE_PARENT, R_CLKENREG0, 15), + SG2042_GATE(GATE_CLK_TIMER5, "clk_gate_timer5", "clk_div_timer5", + CLK_SET_RATE_PARENT, R_CLKENREG0, 16), + SG2042_GATE(GATE_CLK_TIMER6, "clk_gate_timer6", "clk_div_timer6", + CLK_SET_RATE_PARENT, R_CLKENREG0, 17), + SG2042_GATE(GATE_CLK_TIMER7, "clk_gate_timer7", "clk_div_timer7", + CLK_SET_RATE_PARENT, R_CLKENREG0, 18), + SG2042_GATE(GATE_CLK_TIMER8, "clk_gate_timer8", "clk_div_timer8", + CLK_SET_RATE_PARENT, R_CLKENREG0, 19), + + /* gate clocks downstream from div clocks one-to-one */ + SG2042_GATE(GATE_CLK_UART_500M, "clk_gate_uart_500m", "clk_div_uart_500m", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 4), + SG2042_GATE(GATE_CLK_AHB_LPC, "clk_gate_ahb_lpc", "clk_div_ahb_lpc", + CLK_SET_RATE_PARENT, R_CLKENREG0, 7), + SG2042_GATE(GATE_CLK_EFUSE, "clk_gate_efuse", "clk_div_efuse", + CLK_SET_RATE_PARENT, R_CLKENREG0, 20), + SG2042_GATE(GATE_CLK_TX_ETH0, "clk_gate_tx_eth0", "clk_div_tx_eth0", + CLK_SET_RATE_PARENT, R_CLKENREG0, 30), + SG2042_GATE(GATE_CLK_PTP_REF_I_ETH0, + "clk_gate_ptp_ref_i_eth0", "clk_div_ptp_ref_i_eth0", + CLK_SET_RATE_PARENT, R_CLKENREG1, 0), + SG2042_GATE(GATE_CLK_REF_ETH0, "clk_gate_ref_eth0", "clk_div_ref_eth0", + CLK_SET_RATE_PARENT, R_CLKENREG1, 1), + SG2042_GATE(GATE_CLK_EMMC_100M, "clk_gate_emmc", "clk_div_emmc", + CLK_SET_RATE_PARENT, R_CLKENREG1, 3), + SG2042_GATE(GATE_CLK_SD_100M, "clk_gate_sd", "clk_div_sd", + CLK_SET_RATE_PARENT, R_CLKENREG1, 6), + + /* downstream of clk_div_top_axi0 */ + SG2042_GATE(GATE_CLK_AHB_ROM, "clk_gate_ahb_rom", "clk_div_top_axi0", + 0, R_CLKENREG0, 8), + SG2042_GATE(GATE_CLK_AHB_SF, "clk_gate_ahb_sf", "clk_div_top_axi0", + 0, R_CLKENREG0, 9), + SG2042_GATE(GATE_CLK_AXI_SRAM, "clk_gate_axi_sram", "clk_div_top_axi0", + CLK_IGNORE_UNUSED, R_CLKENREG0, 10), + SG2042_GATE(GATE_CLK_APB_TIMER, "clk_gate_apb_timer", "clk_div_top_axi0", + CLK_IGNORE_UNUSED, R_CLKENREG0, 11), + SG2042_GATE(GATE_CLK_APB_EFUSE, "clk_gate_apb_efuse", "clk_div_top_axi0", + 0, R_CLKENREG0, 21), + SG2042_GATE(GATE_CLK_APB_GPIO, "clk_gate_apb_gpio", "clk_div_top_axi0", + 0, R_CLKENREG0, 22), + SG2042_GATE(GATE_CLK_APB_GPIO_INTR, + "clk_gate_apb_gpio_intr", "clk_div_top_axi0", + 0, R_CLKENREG0, 23), + SG2042_GATE(GATE_CLK_APB_I2C, "clk_gate_apb_i2c", "clk_div_top_axi0", + 0, R_CLKENREG0, 26), + SG2042_GATE(GATE_CLK_APB_WDT, "clk_gate_apb_wdt", "clk_div_top_axi0", + 0, R_CLKENREG0, 27), + SG2042_GATE(GATE_CLK_APB_PWM, "clk_gate_apb_pwm", "clk_div_top_axi0", + 0, R_CLKENREG0, 28), + SG2042_GATE(GATE_CLK_APB_RTC, "clk_gate_apb_rtc", "clk_div_top_axi0", + 0, R_CLKENREG0, 29), + SG2042_GATE(GATE_CLK_TOP_AXI0, "clk_gate_top_axi0", "clk_div_top_axi0", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 11), + /* downstream of DIV clocks which are sourced from clk_div_top_axi0 */ + SG2042_GATE(GATE_CLK_GPIO_DB, "clk_gate_gpio_db", "clk_div_gpio_db", + CLK_SET_RATE_PARENT, R_CLKENREG0, 24), + SG2042_GATE(GATE_CLK_100K_EMMC, "clk_gate_100k_emmc", "clk_div_100k_emmc", + CLK_SET_RATE_PARENT, R_CLKENREG1, 4), + SG2042_GATE(GATE_CLK_100K_SD, "clk_gate_100k_sd", "clk_div_100k_sd", + CLK_SET_RATE_PARENT, R_CLKENREG1, 7), + + /* downstream of clk_div_top_axi_hsperi */ + SG2042_GATE(GATE_CLK_SYSDMA_AXI, + "clk_gate_sysdma_axi", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT, R_CLKENREG0, 3), + SG2042_GATE(GATE_CLK_APB_UART, + "clk_gate_apb_uart", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT, R_CLKENREG0, 5), + SG2042_GATE(GATE_CLK_AXI_DBG_I2C, + "clk_gate_axi_dbg_i2c", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT, R_CLKENREG0, 6), + SG2042_GATE(GATE_CLK_APB_SPI, + "clk_gate_apb_spi", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT, R_CLKENREG0, 25), + SG2042_GATE(GATE_CLK_AXI_ETH0, + "clk_gate_axi_eth0", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT, R_CLKENREG0, 31), + SG2042_GATE(GATE_CLK_AXI_EMMC, + "clk_gate_axi_emmc", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT, R_CLKENREG1, 2), + SG2042_GATE(GATE_CLK_AXI_SD, + "clk_gate_axi_sd", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT, R_CLKENREG1, 5), + SG2042_GATE(GATE_CLK_TOP_AXI_HSPERI, + "clk_gate_top_axi_hsperi", "clk_div_top_axi_hsperi", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 12), +}; + +/* + * Gate clocks for RP subsystem (including the MP subsystem), which control + * registers are defined in SYS_CTRL. + */ +static const struct sg2042_gate_clock sg2042_gate_rp[] =3D { + /* downstream of clk_gate_rp_cpu_normal about rxu */ + SG2042_GATE(GATE_CLK_RXU0, "clk_gate_rxu0", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 0), + SG2042_GATE(GATE_CLK_RXU1, "clk_gate_rxu1", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 1), + SG2042_GATE(GATE_CLK_RXU2, "clk_gate_rxu2", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 2), + SG2042_GATE(GATE_CLK_RXU3, "clk_gate_rxu3", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 3), + SG2042_GATE(GATE_CLK_RXU4, "clk_gate_rxu4", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 4), + SG2042_GATE(GATE_CLK_RXU5, "clk_gate_rxu5", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 5), + SG2042_GATE(GATE_CLK_RXU6, "clk_gate_rxu6", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 6), + SG2042_GATE(GATE_CLK_RXU7, "clk_gate_rxu7", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 7), + SG2042_GATE(GATE_CLK_RXU8, "clk_gate_rxu8", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 8), + SG2042_GATE(GATE_CLK_RXU9, "clk_gate_rxu9", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 9), + SG2042_GATE(GATE_CLK_RXU10, "clk_gate_rxu10", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 10), + SG2042_GATE(GATE_CLK_RXU11, "clk_gate_rxu11", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 11), + SG2042_GATE(GATE_CLK_RXU12, "clk_gate_rxu12", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 12), + SG2042_GATE(GATE_CLK_RXU13, "clk_gate_rxu13", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 13), + SG2042_GATE(GATE_CLK_RXU14, "clk_gate_rxu14", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 14), + SG2042_GATE(GATE_CLK_RXU15, "clk_gate_rxu15", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 15), + SG2042_GATE(GATE_CLK_RXU16, "clk_gate_rxu16", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 16), + SG2042_GATE(GATE_CLK_RXU17, "clk_gate_rxu17", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 17), + SG2042_GATE(GATE_CLK_RXU18, "clk_gate_rxu18", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 18), + SG2042_GATE(GATE_CLK_RXU19, "clk_gate_rxu19", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 19), + SG2042_GATE(GATE_CLK_RXU20, "clk_gate_rxu20", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 20), + SG2042_GATE(GATE_CLK_RXU21, "clk_gate_rxu21", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 21), + SG2042_GATE(GATE_CLK_RXU22, "clk_gate_rxu22", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 22), + SG2042_GATE(GATE_CLK_RXU23, "clk_gate_rxu23", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 23), + SG2042_GATE(GATE_CLK_RXU24, "clk_gate_rxu24", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 24), + SG2042_GATE(GATE_CLK_RXU25, "clk_gate_rxu25", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 25), + SG2042_GATE(GATE_CLK_RXU26, "clk_gate_rxu26", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 26), + SG2042_GATE(GATE_CLK_RXU27, "clk_gate_rxu27", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 27), + SG2042_GATE(GATE_CLK_RXU28, "clk_gate_rxu28", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 28), + SG2042_GATE(GATE_CLK_RXU29, "clk_gate_rxu29", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 29), + SG2042_GATE(GATE_CLK_RXU30, "clk_gate_rxu30", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 30), + SG2042_GATE(GATE_CLK_RXU31, "clk_gate_rxu31", "clk_gate_rp_cpu_normal", + 0, R_RP_RXU_CLK_ENABLE, 31), + + /* downstream of clk_gate_rp_cpu_normal about mp */ + SG2042_GATE(GATE_CLK_MP0, "clk_gate_mp0", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP0_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP1, "clk_gate_mp1", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP1_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP2, "clk_gate_mp2", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP2_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP3, "clk_gate_mp3", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP3_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP4, "clk_gate_mp4", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP4_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP5, "clk_gate_mp5", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP5_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP6, "clk_gate_mp6", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP6_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP7, "clk_gate_mp7", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP7_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP8, "clk_gate_mp8", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP8_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP9, "clk_gate_mp9", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP9_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP10, "clk_gate_mp10", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP10_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP11, "clk_gate_mp11", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP11_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP12, "clk_gate_mp12", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP12_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP13, "clk_gate_mp13", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP13_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP14, "clk_gate_mp14", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP14_CONTROL_REG, 0), + SG2042_GATE(GATE_CLK_MP15, "clk_gate_mp15", "clk_gate_rp_cpu_normal", + CLK_IS_CRITICAL, R_MP15_CONTROL_REG, 0), +}; + +#define SG2042_MUX(_id, _name, _parent_names, _flags, _r_select, _shift, _= width) { \ + .hw.init =3D CLK_HW_INIT_PARENTS( \ + _name, \ + _parent_names, \ + NULL, \ + _flags), \ + .id =3D _id, \ + .offset_select =3D _r_select, \ + .shift =3D _shift, \ + .width =3D _width, \ + } + +/* + * Note: regarding names for mux clock, "0/1" or "div0/div1" means the + * first/second parent input source, not the register value. + * For example: + * "clk_div_ddr01_0" is the name of Clock divider 0 control of DDR01, and + * "clk_gate_ddr01_div0" is the gate clock in front of the "clk_div_ddr01_= 0", + * they are both controlled by register CLKDIVREG27; + * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and + * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_= 1", + * they are both controlled by register CLKDIVREG28; + * While for register value of mux selection, use Clock Select for DDR01= =E2=80=99s clock + * as example, see CLKSELREG0, bit[2]. + * 1: Select in_dpll0_clk as clock source, correspondng to the parent input + * source from "clk_div_ddr01_0". + * 0: Select in_fpll_clk as clock source, corresponding to the parent input + * source from "clk_div_ddr01_1". + * So we need a table to define the array of register values corresponding= to + * the parent index and tell CCF about this when registering mux clock. + */ +static const u32 sg2042_mux_table[] =3D {1, 0}; + +static const char *const clk_mux_ddr01_p[] =3D { + "clk_div_ddr01_0", "clk_div_ddr01_1"}; +static const char *const clk_mux_ddr23_p[] =3D { + "clk_div_ddr23_0", "clk_div_ddr23_1"}; +static const char *const clk_mux_rp_cpu_normal_p[] =3D { + "clk_div_rp_cpu_normal_0", "clk_div_rp_cpu_normal_1"}; +static const char *const clk_mux_axi_ddr_p[] =3D { + "clk_div_axi_ddr_0", "clk_div_axi_ddr_1"}; + +static struct sg2042_mux_clock sg2042_mux_clks[] =3D { + SG2042_MUX(MUX_CLK_DDR01, "clk_mux_ddr01", clk_mux_ddr01_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY, + R_CLKSELREG0, 2, 1), + SG2042_MUX(MUX_CLK_DDR23, "clk_mux_ddr23", clk_mux_ddr23_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY, + R_CLKSELREG0, 3, 1), + SG2042_MUX(MUX_CLK_RP_CPU_NORMAL, "clk_mux_rp_cpu_normal", clk_mux_rp_cpu= _normal_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + R_CLKSELREG0, 0, 1), + SG2042_MUX(MUX_CLK_AXI_DDR, "clk_mux_axi_ddr", clk_mux_axi_ddr_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + R_CLKSELREG0, 1, 1), +}; + +static DEFINE_SPINLOCK(sg2042_clk_lock); + +static int sg2042_clk_register_plls(struct sg2042_clk_data *clk_data, + struct sg2042_pll_clock pll_clks[], + int num_pll_clks) +{ + struct clk_hw *hw; + struct sg2042_pll_clock *pll; + int i, ret =3D 0; + + for (i =3D 0; i < num_pll_clks; i++) { + pll =3D &pll_clks[i]; + /* assign these for ops usage during registration */ + pll->base =3D clk_data->iobase; + pll->lock =3D &sg2042_clk_lock; + + hw =3D &pll->hw; + ret =3D clk_hw_register(NULL, hw); + if (ret) { + pr_err("failed to register clock %s\n", pll->hw.init->name); + break; + } + + clk_data->onecell_data.hws[pll->id] =3D hw; + } + + /* leave unregister to outside if failed */ + return ret; +} + +static int sg2042_clk_register_divs(struct sg2042_clk_data *clk_data, + struct sg2042_divider_clock div_clks[], + int num_div_clks) +{ + struct clk_hw *hw; + struct sg2042_divider_clock *div; + int i, ret =3D 0; + + for (i =3D 0; i < num_div_clks; i++) { + div =3D &div_clks[i]; + + if (div->div_flags & CLK_DIVIDER_HIWORD_MASK) { + if (div->width + div->shift > 16) { + pr_warn("divider value exceeds LOWORD field\n"); + ret =3D -EINVAL; + break; + } + } + + div->reg =3D clk_data->iobase + div->offset_ctrl; + div->lock =3D &sg2042_clk_lock; + + hw =3D &div->hw; + ret =3D clk_hw_register(NULL, hw); + if (ret) { + pr_err("failed to register clock %s\n", div->hw.init->name); + break; + } + + clk_data->onecell_data.hws[div->id] =3D hw; + } + + /* leave unregister to outside if failed */ + return ret; +} + +static int sg2042_clk_register_gates(struct sg2042_clk_data *clk_data, + const struct sg2042_gate_clock gate_clks[], + int num_gate_clks) +{ + struct clk_hw *hw; + const struct sg2042_gate_clock *gate; + int i, ret =3D 0; + + for (i =3D 0; i < num_gate_clks; i++) { + gate =3D &gate_clks[i]; + hw =3D clk_hw_register_gate(NULL, + gate->hw.init->name, + gate->hw.init->parent_names[0], + gate->hw.init->flags, + clk_data->iobase + gate->offset_enable, + gate->bit_idx, + 0, + &sg2042_clk_lock); + if (IS_ERR(hw)) { + pr_err("failed to register clock %s\n", gate->hw.init->name); + ret =3D PTR_ERR(hw); + break; + } + + clk_data->onecell_data.hws[gate->id] =3D hw; + } + + /* leave unregister to outside if failed */ + return ret; +} + +static int sg2042_mux_notifier_cb(struct notifier_block *nb, + unsigned long event, + void *data) +{ + int ret =3D 0; + struct clk_notifier_data *ndata =3D data; + struct clk_hw *hw =3D __clk_get_hw(ndata->clk); + const struct clk_ops *ops =3D &clk_mux_ops; + struct sg2042_mux_clock *mux =3D to_sg2042_mux_nb(nb); + + /* To switch to fpll before changing rate and restore after that */ + if (event =3D=3D PRE_RATE_CHANGE) { + mux->original_index =3D ops->get_parent(hw); + + /* + * "1" is the array index of the second parent input source of + * mux. For SG2042, it's fpll for all mux clocks. + * "0" is the array index of the frist parent input source of + * mux, For SG2042, it's mpll. + * FIXME, any good idea to avoid magic number? + */ + if (mux->original_index =3D=3D 0) + ret =3D ops->set_parent(hw, 1); + } else if (event =3D=3D POST_RATE_CHANGE) { + ret =3D ops->set_parent(hw, mux->original_index); + } + + return notifier_from_errno(ret); +} + +static int sg2042_clk_register_muxs(struct sg2042_clk_data *clk_data, + struct sg2042_mux_clock mux_clks[], + int num_mux_clks) +{ + struct clk_hw *hw; + struct sg2042_mux_clock *mux; + int i, ret =3D 0; + + for (i =3D 0; i < num_mux_clks; i++) { + mux =3D &mux_clks[i]; + + hw =3D clk_hw_register_mux_table(NULL, + mux->hw.init->name, + mux->hw.init->parent_names, + mux->hw.init->num_parents, + mux->hw.init->flags, + clk_data->iobase + mux->offset_select, + mux->shift, + BIT(mux->width) - 1, + 0, + sg2042_mux_table, + &sg2042_clk_lock); + if (IS_ERR(hw)) { + pr_err("failed to register clock %s\n", mux->hw.init->name); + ret =3D PTR_ERR(hw); + break; + } + + clk_data->onecell_data.hws[mux->id] =3D hw; + + /* + * FIXME: Theoretically, we should set parent for the + * mux, but seems hardware has done this for us with + * default value, so we don't set parent again here. + */ + + if (!(mux->hw.init->flags & CLK_MUX_READ_ONLY)) { + mux->clk_nb.notifier_call =3D sg2042_mux_notifier_cb; + ret =3D clk_notifier_register(hw->clk, &mux->clk_nb); + if (ret) { + pr_err("failed to register clock notifier for %s\n", + mux->hw.init->name); + goto error_cleanup; + } + } + } + + return 0; + +error_cleanup: + /* unregister notifier and release the memory allocated */ + for (i =3D 0; i < num_mux_clks; i++) { + mux =3D &mux_clks[i]; + + hw =3D clk_data->onecell_data.hws[mux->id]; + + if (hw) + clk_notifier_unregister(hw->clk, &mux->clk_nb); + } + + /* leave clk unregister to outside if failed */ + return ret; +} + +static int sg2042_init_clkdata(struct platform_device *pdev, + int num_clks, + struct sg2042_clk_data **pp_clk_data) +{ + struct sg2042_clk_data *clk_data =3D NULL; + + clk_data =3D devm_kzalloc(&pdev->dev, + struct_size(clk_data, onecell_data.hws, num_clks), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->iobase =3D devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL= ); + if (WARN_ON(IS_ERR(clk_data->iobase))) + return PTR_ERR(clk_data->iobase); + + clk_data->onecell_data.num =3D num_clks; + + *pp_clk_data =3D clk_data; + + return 0; +} + +static int sg2042_clkgen_probe(struct platform_device *pdev) +{ + struct sg2042_clk_data *clk_data =3D NULL; + int i, ret =3D 0; + int num_clks =3D 0; + + num_clks =3D ARRAY_SIZE(sg2042_div_clks) + + ARRAY_SIZE(sg2042_gate_clks) + + ARRAY_SIZE(sg2042_mux_clks); + if (num_clks =3D=3D 0) { + ret =3D -EINVAL; + goto error_out; + } + + ret =3D sg2042_init_clkdata(pdev, num_clks, &clk_data); + if (ret < 0) + goto error_out; + + ret =3D sg2042_clk_register_divs(clk_data, sg2042_div_clks, + ARRAY_SIZE(sg2042_div_clks)); + if (ret) + goto cleanup; + + ret =3D sg2042_clk_register_gates(clk_data, sg2042_gate_clks, + ARRAY_SIZE(sg2042_gate_clks)); + if (ret) + goto cleanup; + + ret =3D sg2042_clk_register_muxs(clk_data, sg2042_mux_clks, + ARRAY_SIZE(sg2042_mux_clks)); + if (ret) + goto cleanup; + + return devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, + &clk_data->onecell_data); + +cleanup: + for (i =3D 0; i < num_clks; i++) { + if (clk_data->onecell_data.hws[i]) + clk_hw_unregister(clk_data->onecell_data.hws[i]); + } + +error_out: + pr_err("%s failed error number %d\n", __func__, ret); + return ret; +} + +static int sg2042_rpgate_probe(struct platform_device *pdev) +{ + struct sg2042_clk_data *clk_data =3D NULL; + int i, ret =3D 0; + int num_clks =3D 0; + + num_clks =3D ARRAY_SIZE(sg2042_gate_rp); + if (num_clks =3D=3D 0) { + ret =3D -EINVAL; + goto error_out; + } + + ret =3D sg2042_init_clkdata(pdev, num_clks, &clk_data); + if (ret < 0) + goto error_out; + + ret =3D sg2042_clk_register_gates(clk_data, sg2042_gate_rp, + ARRAY_SIZE(sg2042_gate_rp)); + if (ret) + goto cleanup; + + return devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, + &clk_data->onecell_data); + +cleanup: + for (i =3D 0; i < num_clks; i++) { + if (clk_data->onecell_data.hws[i]) + clk_hw_unregister(clk_data->onecell_data.hws[i]); + } + +error_out: + pr_err("%s failed error number %d\n", __func__, ret); + return ret; +} + +static int sg2042_pll_probe(struct platform_device *pdev) +{ + struct sg2042_clk_data *clk_data =3D NULL; + int i, ret =3D 0; + int num_clks =3D 0; + + num_clks =3D ARRAY_SIZE(sg2042_pll_clks); + if (num_clks =3D=3D 0) { + ret =3D -EINVAL; + goto error_out; + } + + ret =3D sg2042_init_clkdata(pdev, num_clks, &clk_data); + if (ret < 0) + goto error_out; + + ret =3D sg2042_clk_register_plls(clk_data, sg2042_pll_clks, + ARRAY_SIZE(sg2042_pll_clks)); + if (ret) + goto cleanup; + + return devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, + &clk_data->onecell_data); + +cleanup: + for (i =3D 0; i < num_clks; i++) { + if (clk_data->onecell_data.hws[i]) + clk_hw_unregister(clk_data->onecell_data.hws[i]); + } + +error_out: + pr_err("%s failed error number %d\n", __func__, ret); + return ret; +} + +static const struct of_device_id sg2042_clkgen_match[] =3D { + { .compatible =3D "sophgo,sg2042-clkgen" }, + { /* sentinel */ } +}; + +static struct platform_driver sg2042_clkgen_driver =3D { + .probe =3D sg2042_clkgen_probe, + .driver =3D { + .name =3D "clk-sophgo-sg2042-clkgen", + .of_match_table =3D sg2042_clkgen_match, + .suppress_bind_attrs =3D true, + }, +}; +builtin_platform_driver(sg2042_clkgen_driver); + +static const struct of_device_id sg2042_rpgate_match[] =3D { + { .compatible =3D "sophgo,sg2042-rpgate" }, + { /* sentinel */ } +}; + +static struct platform_driver sg2042_rpgate_driver =3D { + .probe =3D sg2042_rpgate_probe, + .driver =3D { + .name =3D "clk-sophgo-sg2042-rpgate", + .of_match_table =3D sg2042_rpgate_match, + .suppress_bind_attrs =3D true, + }, +}; +builtin_platform_driver(sg2042_rpgate_driver); + +static const struct of_device_id sg2042_pll_match[] =3D { + { .compatible =3D "sophgo,sg2042-pll" }, + { /* sentinel */ } +}; + +static struct platform_driver sg2042_pll_driver =3D { + .probe =3D sg2042_pll_probe, + .driver =3D { + .name =3D "clk-sophgo-sg2042-pll", + .of_match_table =3D sg2042_pll_match, + .suppress_bind_attrs =3D true, + }, +}; +builtin_platform_driver(sg2042_pll_driver); diff --git a/drivers/clk/sophgo/clk-sophgo-sg2042.h b/drivers/clk/sophgo/cl= k-sophgo-sg2042.h new file mode 100644 index 000000000000..407fec6f3f02 --- /dev/null +++ b/drivers/clk/sophgo/clk-sophgo-sg2042.h @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __CLK_SOPHGO_SG2042_H +#define __CLK_SOPHGO_SG2042_H + +/* Registers defined in SYS_CTRL */ +#define R_PLL_BEGIN 0xC0 +#define R_PLL_STAT (0xC0 - R_PLL_BEGIN) +#define R_PLL_CLKEN_CONTROL (0xC4 - R_PLL_BEGIN) +#define R_MPLL_CONTROL (0xE8 - R_PLL_BEGIN) +#define R_FPLL_CONTROL (0xF4 - R_PLL_BEGIN) +#define R_DPLL0_CONTROL (0xF8 - R_PLL_BEGIN) +#define R_DPLL1_CONTROL (0xFC - R_PLL_BEGIN) + +#define R_SYSGATE_BEGIN 0x0368 +#define R_RP_RXU_CLK_ENABLE (0x0368 - R_SYSGATE_BEGIN) +#define R_MP0_STATUS_REG (0x0380 - R_SYSGATE_BEGIN) +#define R_MP0_CONTROL_REG (0x0384 - R_SYSGATE_BEGIN) +#define R_MP1_STATUS_REG (0x0388 - R_SYSGATE_BEGIN) +#define R_MP1_CONTROL_REG (0x038C - R_SYSGATE_BEGIN) +#define R_MP2_STATUS_REG (0x0390 - R_SYSGATE_BEGIN) +#define R_MP2_CONTROL_REG (0x0394 - R_SYSGATE_BEGIN) +#define R_MP3_STATUS_REG (0x0398 - R_SYSGATE_BEGIN) +#define R_MP3_CONTROL_REG (0x039C - R_SYSGATE_BEGIN) +#define R_MP4_STATUS_REG (0x03A0 - R_SYSGATE_BEGIN) +#define R_MP4_CONTROL_REG (0x03A4 - R_SYSGATE_BEGIN) +#define R_MP5_STATUS_REG (0x03A8 - R_SYSGATE_BEGIN) +#define R_MP5_CONTROL_REG (0x03AC - R_SYSGATE_BEGIN) +#define R_MP6_STATUS_REG (0x03B0 - R_SYSGATE_BEGIN) +#define R_MP6_CONTROL_REG (0x03B4 - R_SYSGATE_BEGIN) +#define R_MP7_STATUS_REG (0x03B8 - R_SYSGATE_BEGIN) +#define R_MP7_CONTROL_REG (0x03BC - R_SYSGATE_BEGIN) +#define R_MP8_STATUS_REG (0x03C0 - R_SYSGATE_BEGIN) +#define R_MP8_CONTROL_REG (0x03C4 - R_SYSGATE_BEGIN) +#define R_MP9_STATUS_REG (0x03C8 - R_SYSGATE_BEGIN) +#define R_MP9_CONTROL_REG (0x03CC - R_SYSGATE_BEGIN) +#define R_MP10_STATUS_REG (0x03D0 - R_SYSGATE_BEGIN) +#define R_MP10_CONTROL_REG (0x03D4 - R_SYSGATE_BEGIN) +#define R_MP11_STATUS_REG (0x03D8 - R_SYSGATE_BEGIN) +#define R_MP11_CONTROL_REG (0x03DC - R_SYSGATE_BEGIN) +#define R_MP12_STATUS_REG (0x03E0 - R_SYSGATE_BEGIN) +#define R_MP12_CONTROL_REG (0x03E4 - R_SYSGATE_BEGIN) +#define R_MP13_STATUS_REG (0x03E8 - R_SYSGATE_BEGIN) +#define R_MP13_CONTROL_REG (0x03EC - R_SYSGATE_BEGIN) +#define R_MP14_STATUS_REG (0x03F0 - R_SYSGATE_BEGIN) +#define R_MP14_CONTROL_REG (0x03F4 - R_SYSGATE_BEGIN) +#define R_MP15_STATUS_REG (0x03F8 - R_SYSGATE_BEGIN) +#define R_MP15_CONTROL_REG (0x03FC - R_SYSGATE_BEGIN) + +/* Registers defined in CLOCK */ +#define R_CLKENREG0 0x00 +#define R_CLKENREG1 0x04 +#define R_CLKSELREG0 0x20 +#define R_CLKDIVREG0 0x40 +#define R_CLKDIVREG1 0x44 +#define R_CLKDIVREG2 0x48 +#define R_CLKDIVREG3 0x4C +#define R_CLKDIVREG4 0x50 +#define R_CLKDIVREG5 0x54 +#define R_CLKDIVREG6 0x58 +#define R_CLKDIVREG7 0x5C +#define R_CLKDIVREG8 0x60 +#define R_CLKDIVREG9 0x64 +#define R_CLKDIVREG10 0x68 +#define R_CLKDIVREG11 0x6C +#define R_CLKDIVREG12 0x70 +#define R_CLKDIVREG13 0x74 +#define R_CLKDIVREG14 0x78 +#define R_CLKDIVREG15 0x7C +#define R_CLKDIVREG16 0x80 +#define R_CLKDIVREG17 0x84 +#define R_CLKDIVREG18 0x88 +#define R_CLKDIVREG19 0x8C +#define R_CLKDIVREG20 0x90 +#define R_CLKDIVREG21 0x94 +#define R_CLKDIVREG22 0x98 +#define R_CLKDIVREG23 0x9C +#define R_CLKDIVREG24 0xA0 +#define R_CLKDIVREG25 0xA4 +#define R_CLKDIVREG26 0xA8 +#define R_CLKDIVREG27 0xAC +#define R_CLKDIVREG28 0xB0 +#define R_CLKDIVREG29 0xB4 +#define R_CLKDIVREG30 0xB8 + +/* + * Common data of clock-controller + * Note: this structure will be used both by clkgen & sysclk. + * @iobase: base address of clock-controller + * @onecell_data: used for adding providers. + */ +struct sg2042_clk_data { + void __iomem *iobase; + struct clk_hw_onecell_data onecell_data; +}; + +/* + * PLL clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @base: used for readl/writel. + * **NOTE**: PLL registers are all in SYS_CTRL! + * @lock: spinlock to protect register access, modification + * of frequency can only be served one at the time. + * @offset_status: offset of pll status registers + * @offset_enable: offset of pll enable registers + * @offset_ctrl: offset of pll control registers + * @shift_status_lock: shift of XXX_LOCK in pll status register + * @shift_status_updating: shift of UPDATING_XXX in pll status register + * @shift_enable: shift of XXX_CLK_EN in pll enable register + */ +struct sg2042_pll_clock { + struct clk_hw hw; + + unsigned int id; + void __iomem *base; + /* protect register access */ + spinlock_t *lock; + + u32 offset_status; + u32 offset_enable; + u32 offset_ctrl; + u8 shift_status_lock; + u8 shift_status_updating; + u8 shift_enable; +}; + +#define to_sg2042_pll_clk(_hw) container_of(_hw, struct sg2042_pll_clock, = hw) + +/* + * Divider clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @reg: used for readl/writel. + * **NOTE**: DIV registers are ALL in CLOCK! + * @lock: spinlock to protect register access, modification of + * frequency can only be served one at the time + * @offset_ctrl: offset of divider control registers + * @shift: shift of "Clock Divider Factor" in divider control register + * @width: width of "Clock Divider Factor" in divider control register + * @div_flags: private flags for this clock, not for framework-specific + * @initval: In the divider control register, we can configure whether + * to use the value of "Clock Divider Factor" or just use + * the initial value pre-configured by IC. BIT[3] controls + * this and by default (value is 0), means initial value + * is used. + * **NOTE** that we cannot read the initial value (default + * value when poweron) and default value of "Clock Divider + * Factor" is zero, which I think is a hardware design flaw + * and should be sync-ed with the initial value. So in + * software we have to add a configuration item (initval) + * to manually configure this value and use it when BIT[3] + * is zero. + */ +struct sg2042_divider_clock { + struct clk_hw hw; + + unsigned int id; + + void __iomem *reg; + /* protect register access */ + spinlock_t *lock; + + unsigned long offset_ctrl; + u8 shift; + u8 width; + u8 div_flags; + u32 initval; +}; + +#define to_sg2042_clk_divider(_hw) \ + container_of(_hw, struct sg2042_divider_clock, hw) + +/* + * Gate clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @offset_enable: offset of gate enable registers + * @bit_idx: which bit in the register controls gating of this clock + */ +struct sg2042_gate_clock { + struct clk_hw hw; + + unsigned int id; + + unsigned long offset_enable; + u8 bit_idx; +}; + +/* + * Mux clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @offset_select: offset of mux selection registers + * **NOTE**: MUX registers are ALL in CLOCK! + * @shift: shift of "Clock Select" in mux selection register + * @width: width of "Clock Select" in mux selection register + * @clk_nb: used for notification + * @original_index: set by notifier callback + */ +struct sg2042_mux_clock { + struct clk_hw hw; + + unsigned int id; + + unsigned long offset_select; + u8 shift; + u8 width; + + struct notifier_block clk_nb; + u8 original_index; +}; + +#define to_sg2042_mux_nb(_nb) container_of(_nb, struct sg2042_mux_clock, c= lk_nb) + +#endif /* __CLK_SOPHGO_SG2042_H */ --=20 2.25.1 From nobody Wed Feb 11 09:21:19 2026 Received: from mail-oi1-f174.google.com (mail-oi1-f174.google.com [209.85.167.174]) (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 25EB82E63B; Wed, 27 Mar 2024 08:31:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528273; cv=none; b=dzty4ASNtYJt4Rs+My2sIQvhJfIAyvTqguEs8JqRqBFDyz6EfQWgWo6AXnjpvyF18ihik/FfLMz/RSoR53CYTe/joARH90ZH7Su8X/+ZXurwwD+ba1+l6aE0nwTNi8JTM24+aHWOwwMOe46Ur1FqQVNsMQWxOj22VHTs9hSZjys= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711528273; c=relaxed/simple; bh=Kct7Pjk1WKf/K8JXQ51OPs2q82g4Vs270HKxVBz7YVU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=J9boFSSwCp3pW6+dgwWGO46kKXZH34zGMfTN7iKzZrL2vHRTDscQ9rvlix/BfXxOkUjjdbikKPK13u8MsflZddwxq5lOrmziUvundpdQso6kZsRMw4EitloPMYomIX0/I8sI+uoANJVFgGJ9XNTh6GWfoNo+D69Dxgi6vzdp7vo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RZcH2Bpi; arc=none smtp.client-ip=209.85.167.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RZcH2Bpi" Received: by mail-oi1-f174.google.com with SMTP id 5614622812f47-3c3ceeb2d04so1592208b6e.1; Wed, 27 Mar 2024 01:31:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1711528271; x=1712133071; 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=YPRTTnRNGB6MC8MgLxeQqBqXiKf58UGvbzByUZNl4Io=; b=RZcH2BpiX9/oa0eM66pGghAC141UrN859Fu2LWkHDWu//Em8OExtIwIjhrKz4cJMR2 vEIVJpmus9kHAXUqSIzO+quiy3HGQpr3g3s1GWqPbMkccQ7zNiKsOzdyOYUZ9CpEvBOc 13qFPL9Rocs9WDyQUv4BHPr6EvnEfuipszPHGEZyDrkLXMzqDUUHD5GHerWph+ue/c6b vHac050LTdeb+eYE7iFWAS3Qr4HyjvvOB31lPBpo1sB5BdlBf/Lyt6ETT+xM7ueuvLDN vt1Sfvph4XsdEAMpFaBo+oSJF+1HvmiGwrPlqmdogZaNZ/V7P4vnHRWmbCHBPwTlxdyu LoDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711528271; x=1712133071; 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=YPRTTnRNGB6MC8MgLxeQqBqXiKf58UGvbzByUZNl4Io=; b=N36OUGrCgYpj0Zl3BiqG3xKcEAlAnP4iqzXocwLmQy2p0JHp1V9PiLnDUM0due1lof rtMFaiInXDPVEqh4oQzXvV9b/bCkxC3k0ch1swbAD5ZngTgeStxheiI6yNnfXqb0KA1h 8pnG2JhJ7LlB7zU3n1rf0wlI97LGR8CFSNvvZf4Jd+nAXya1pV/brSYC3nArwona8p4L 9xnZPCVM75IZiwslhI1XwuKp2FcfvGnbeCUh0l+WZfvc29FXeIoJH3qxMBZJlbRhK4+6 blvSGh6xzFSxZGKP/XywcCg4KlYw/4e4fk4FKWC9V+/ctj2jSAGPNlP+4KqMPk9TKiMZ VD/w== X-Forwarded-Encrypted: i=1; AJvYcCWjgVt3778rfSFeCnPlqtoV5kXs5e0JIxupUbdnyjziPkucEkSVsU794M/300s8nvjwTH3MEl154q/G5IXWeBEBL3WFkEcvEYDmWnHEZw35e3ZYGzoVxV5M6oqSbcCnbezEq3jlFj1RxCM0b7RcML08BZhe+ZwiEzxZAOL2iCitiQ71Rg== X-Gm-Message-State: AOJu0Yyeostq2q/9KcTuu2qINf/JxKU86UVlmEhPAJhiVHa98FNf96I2 v1FP1IYWa9HWRnqcoYFF2Pl7vRfBsbZ2KTePa+jAjAtwfMRL7jy/ X-Google-Smtp-Source: AGHT+IGXMC8GI7EHqyzHdc2ep+bX1igihkpaRvHWPRxoLI04zdhk6t5Wq0ZlSdSHmAbGqcu5fH1TAQ== X-Received: by 2002:a05:6808:6293:b0:3c3:cd2e:3074 with SMTP id du19-20020a056808629300b003c3cd2e3074mr4469638oib.26.1711528271233; Wed, 27 Mar 2024 01:31:11 -0700 (PDT) Received: from localhost.localdomain ([122.8.183.87]) by smtp.gmail.com with ESMTPSA id m5-20020aca1e05000000b003c37b40b2easm1793335oic.48.2024.03.27.01.31.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Mar 2024 01:31:10 -0700 (PDT) From: Chen Wang To: aou@eecs.berkeley.edu, chao.wei@sophgo.com, conor@kernel.org, krzysztof.kozlowski+dt@linaro.org, mturquette@baylibre.com, palmer@dabbelt.com, paul.walmsley@sifive.com, richardcochran@gmail.com, robh+dt@kernel.org, sboyd@kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, haijiao.liu@sophgo.com, xiaoguang.xing@sophgo.com, guoren@kernel.org, jszhang@kernel.org, inochiama@outlook.com, samuel.holland@sifive.com Cc: Chen Wang Subject: [PATCH v12 5/5] riscv: dts: add clock generator for Sophgo SG2042 SoC Date: Wed, 27 Mar 2024 16:31:03 +0800 Message-Id: <5d34a5ce93202463bd7b05ec2df93edc8fb1ef1b.1711527932.git.unicorn_wang@outlook.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Chen Wang Add clock generator node to device tree for SG2042, and enable clock for uart. Signed-off-by: Chen Wang Reviewed-by: Guo Ren --- .../boot/dts/sophgo/sg2042-milkv-pioneer.dts | 12 +++++ arch/riscv/boot/dts/sophgo/sg2042.dtsi | 49 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/ris= cv/boot/dts/sophgo/sg2042-milkv-pioneer.dts index 49b4b9c2c101..80cb017974d8 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts +++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts @@ -14,6 +14,18 @@ chosen { }; }; =20 +&cgi_main { + clock-frequency =3D <25000000>; +}; + +&cgi_dpll0 { + clock-frequency =3D <25000000>; +}; + +&cgi_dpll1 { + clock-frequency =3D <25000000>; +}; + &uart0 { status =3D "okay"; }; diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/s= ophgo/sg2042.dtsi index 81fda312f988..8aab027cf730 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -4,8 +4,10 @@ */ =20 /dts-v1/; +#include +#include +#include #include - #include =20 #include "sg2042-cpus.dtsi" @@ -20,12 +22,54 @@ aliases { serial0 =3D &uart0; }; =20 + cgi_main: oscillator0 { + compatible =3D "fixed-clock"; + clock-output-names =3D "cgi_main"; + #clock-cells =3D <0>; + }; + + cgi_dpll0: oscillator1 { + compatible =3D "fixed-clock"; + clock-output-names =3D "cgi_dpll0"; + #clock-cells =3D <0>; + }; + + cgi_dpll1: oscillator2 { + compatible =3D "fixed-clock"; + clock-output-names =3D "cgi_dpll1"; + #clock-cells =3D <0>; + }; + soc: soc { compatible =3D "simple-bus"; #address-cells =3D <2>; #size-cells =3D <2>; ranges; =20 + pllclk: clock-controller@70300100c0 { + compatible =3D "sophgo,sg2042-pll"; + reg =3D <0x70 0x300100c0 0x0 0x40>; + clocks =3D <&cgi_main>, <&cgi_dpll0>, <&cgi_dpll1>; + #clock-cells =3D <1>; + }; + + rpgate: clock-controller@7030010368 { + compatible =3D "sophgo,sg2042-rpgate"; + reg =3D <0x70 0x30010368 0x0 0x98>; + clocks =3D <&clkgen GATE_CLK_RP_CPU_NORMAL>; + #clock-cells =3D <1>; + }; + + clkgen: clock-controller@7030012000 { + compatible =3D "sophgo,sg2042-clkgen"; + reg =3D <0x70 0x30012000 0x0 0x1000>; + clocks =3D <&pllclk MPLL_CLK>, + <&pllclk FPLL_CLK>, + <&pllclk DPLL0_CLK>, + <&pllclk DPLL1_CLK>; + #clock-cells =3D <1>; + }; + clint_mswi: interrupt-controller@7094000000 { compatible =3D "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi"; reg =3D <0x00000070 0x94000000 0x00000000 0x00004000>; @@ -341,6 +385,9 @@ uart0: serial@7040000000 { interrupt-parent =3D <&intc>; interrupts =3D <112 IRQ_TYPE_LEVEL_HIGH>; clock-frequency =3D <500000000>; + clocks =3D <&clkgen GATE_CLK_UART_500M>, + <&clkgen GATE_CLK_APB_UART>; + clock-names =3D "baudclk", "apb_pclk"; reg-shift =3D <2>; reg-io-width =3D <4>; resets =3D <&rstgen RST_UART0>; --=20 2.25.1