drivers: clock_control: Added clock driver for Raspberry Pi Pico

Added clock driver for Raspberry Pi Pico platform

Signed-off-by: Andrei-Edward Popa <andrei.popa105@yahoo.com>
Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
diff --git a/boards/arm/adafruit_kb2040/adafruit_kb2040.dts b/boards/arm/adafruit_kb2040/adafruit_kb2040.dts
index 2d9c815..227bb53 100644
--- a/boards/arm/adafruit_kb2040/adafruit_kb2040.dts
+++ b/boards/arm/adafruit_kb2040/adafruit_kb2040.dts
@@ -25,12 +25,6 @@
 	aliases {
 		watchdog0 = &wdt0;
 	};
-
-	xtal_clk: xtal-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <12000000>;
-		#clock-cells = <0>;
-	};
 };
 
 &flash0 {
diff --git a/boards/arm/adafruit_kb2040/adafruit_kb2040_defconfig b/boards/arm/adafruit_kb2040/adafruit_kb2040_defconfig
index 735148f..6ce0691 100644
--- a/boards/arm/adafruit_kb2040/adafruit_kb2040_defconfig
+++ b/boards/arm/adafruit_kb2040/adafruit_kb2040_defconfig
@@ -17,6 +17,9 @@
 # Enable reset by default
 CONFIG_RESET=y
 
+# Enable clock control by default
+CONFIG_CLOCK_CONTROL=y
+
 # Code partition needed to target the correct flash range
 CONFIG_USE_DT_CODE_PARTITION=y
 
diff --git a/boards/arm/rpi_pico/rpi_pico-common.dtsi b/boards/arm/rpi_pico/rpi_pico-common.dtsi
index 680d203..aee3e14 100644
--- a/boards/arm/rpi_pico/rpi_pico-common.dtsi
+++ b/boards/arm/rpi_pico/rpi_pico-common.dtsi
@@ -23,12 +23,6 @@
 		zephyr,code-partition = &code_partition;
 	};
 
-	xtal_clk: xtal-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <12000000>;
-		#clock-cells = <0>;
-	};
-
 	aliases {
 		watchdog0 = &wdt0;
 	};
diff --git a/boards/arm/rpi_pico/rpi_pico_defconfig b/boards/arm/rpi_pico/rpi_pico_defconfig
index 2a27689..111edce 100644
--- a/boards/arm/rpi_pico/rpi_pico_defconfig
+++ b/boards/arm/rpi_pico/rpi_pico_defconfig
@@ -11,3 +11,4 @@
 CONFIG_BUILD_OUTPUT_HEX=y
 CONFIG_UART_INTERRUPT_DRIVEN=y
 CONFIG_RESET=y
+CONFIG_CLOCK_CONTROL=y
diff --git a/boards/arm/rpi_pico/rpi_pico_w_defconfig b/boards/arm/rpi_pico/rpi_pico_w_defconfig
index a035561..9b38685 100644
--- a/boards/arm/rpi_pico/rpi_pico_w_defconfig
+++ b/boards/arm/rpi_pico/rpi_pico_w_defconfig
@@ -11,3 +11,4 @@
 CONFIG_BUILD_OUTPUT_HEX=y
 CONFIG_UART_INTERRUPT_DRIVEN=y
 CONFIG_RESET=y
+CONFIG_CLOCK_CONTROL=y
diff --git a/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.dts b/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.dts
index 1bd5e22..50b92f6 100644
--- a/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.dts
+++ b/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040.dts
@@ -23,12 +23,6 @@
 	aliases {
 		watchdog0 = &wdt0;
 	};
-
-	xtal_clk: xtal-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <12000000>;
-		#clock-cells = <0>;
-	};
 };
 
 &flash0 {
diff --git a/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040_defconfig b/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040_defconfig
index 4ec1c6c..36aba34 100644
--- a/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040_defconfig
+++ b/boards/arm/sparkfun_pro_micro_rp2040/sparkfun_pro_micro_rp2040_defconfig
@@ -15,6 +15,9 @@
 CONFIG_CONSOLE=y
 CONFIG_UART_CONSOLE=y
 
+# Enable clock control by default
+CONFIG_CLOCK_CONTROL=y
+
 # Code partition needed to target the correct flash range
 CONFIG_USE_DT_CODE_PARTITION=y
 
diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt
index 219aac7..14f6c60 100644
--- a/drivers/clock_control/CMakeLists.txt
+++ b/drivers/clock_control/CMakeLists.txt
@@ -29,6 +29,7 @@
 zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RA                  clock_control_ra.c)
 zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AMBIQ               clock_control_ambiq.c)
 zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_PWM                 clock_control_pwm.c)
+zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RPI_PICO            clock_control_rpi_pico.c)
 
 
 if(CONFIG_CLOCK_CONTROL_STM32_CUBE)
diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig
index 37cbb2e..9f7412c 100644
--- a/drivers/clock_control/Kconfig
+++ b/drivers/clock_control/Kconfig
@@ -86,4 +86,6 @@
 
 source "drivers/clock_control/Kconfig.pwm"
 
+source "drivers/clock_control/Kconfig.rpi_pico"
+
 endif # CLOCK_CONTROL
diff --git a/drivers/clock_control/Kconfig.rpi_pico b/drivers/clock_control/Kconfig.rpi_pico
new file mode 100644
index 0000000..3c7c871
--- /dev/null
+++ b/drivers/clock_control/Kconfig.rpi_pico
@@ -0,0 +1,19 @@
+# Raspberry Pi Pico Clock Controller Driver configuration options
+
+# Copyright (c) 2022 Andrei-Edward Popa
+# SPDX-License-Identifier: Apache-2.0
+
+config CLOCK_CONTROL_RPI_PICO
+	bool "Raspberry Pi Pico Clock Controller Driver"
+	default y
+	depends on DT_HAS_RASPBERRYPI_PICO_CLOCK_CONTROLLER_ENABLED
+
+if CLOCK_CONTROL_RPI_PICO
+
+config RPI_PICO_ROSC_USE_MEASURED_FREQ
+	bool "Use measured frequency for ring oscillator"
+	help
+	 Instead of the dts value, use the value measured by
+	 the frequency counter as the rosc frequency.
+
+endif # CLOCK_CONTROL_RPI_PICO
diff --git a/drivers/clock_control/clock_control_rpi_pico.c b/drivers/clock_control/clock_control_rpi_pico.c
new file mode 100644
index 0000000..0313ee2
--- /dev/null
+++ b/drivers/clock_control/clock_control_rpi_pico.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (c) 2022 Andrei-Edward Popa
+ * Copyright (c) 2023 TOKITA Hiroshi
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define DT_DRV_COMPAT raspberrypi_pico_clock_controller
+
+#include <zephyr/drivers/clock_control.h>
+#include <zephyr/drivers/reset.h>
+#include <zephyr/dt-bindings/clock/rpi_pico_clock.h>
+
+#include <hardware/clocks.h>
+#include <hardware/xosc.h>
+#include <hardware/structs/rosc.h>
+#include <hardware/pll.h>
+#include <hardware/watchdog.h>
+#include <hardware/resets.h>
+
+/* Undefine to prevent conflicts with header definitions */
+#undef pll_sys
+#undef pll_usb
+
+#define CTRL_SRC_LSB     CLOCKS_CLK_REF_CTRL_SRC_LSB
+#define CTRL_SRC_BITS    CLOCKS_CLK_REF_CTRL_SRC_BITS
+#define CTRL_AUXSRC_LSB  CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_LSB
+#define CTRL_AUXSRC_BITS CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_BITS
+#define CTRL_ENABLE_BITS CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS
+#define DIV_FRAC_BITS    CLOCKS_CLK_GPOUT0_DIV_FRAC_BITS
+#define DIV_INT_BITS     CLOCKS_CLK_GPOUT0_DIV_INT_BITS
+#define DIV_INT_LSB      CLOCKS_CLK_GPOUT0_DIV_INT_LSB
+
+#define PLL_VCO_FREQ_MIN 750000000
+#define PLL_VCO_FREQ_MAX 1600000000
+#define PLL_FB_DIV_MIN   16
+#define PLL_FB_DIV_MAX   320
+#define PLL_POST_DIV_MIN 1
+#define PLL_POST_DIV_MAX 7
+
+#define ROSC_PHASE_PASSWD_VALUE_PASS _u(0xAA)
+
+#define STAGE_DS(n)                                                                                \
+	(COND_CODE_1(                                                                              \
+		 DT_PROP_HAS_IDX(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc), stage_drive_strength, n),   \
+		 (DT_PROP_BY_IDX(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc), stage_drive_strength, n) &  \
+		  ROSC_FREQA_DS0_BITS),                                                            \
+		 (0))                                                                              \
+	 << (n * 3))
+
+#define CLK_SRC_IS(clk, src)                                                                       \
+	DT_SAME_NODE(DT_CLOCKS_CTLR_BY_IDX(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk), 0),                \
+		     DT_INST_CLOCKS_CTLR_BY_NAME(0, src))
+
+#define REF_DIV(pll)   DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll), clock_div)
+#define FB_DIV(pll)    DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll), fb_div)
+#define POST_DIV1(pll) DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll), post_div1)
+#define POST_DIV2(pll) DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll), post_div2)
+#define VCO_FREQ(pll)  ((CLOCK_FREQ_xosc / REF_DIV(pll)) * FB_DIV(pll))
+
+/*
+ * Using the 'clock-names[0]' for expanding macro to frequency value.
+ * The 'clock-names[0]' is set same as label value that given to the node itself.
+ * Use it for traverse clock tree to find root of clock source.
+ */
+#define CLOCK_FREQ(clk)     _CONCAT(CLOCK_FREQ_, clk)
+#define SRC_CLOCK(clk)      DT_STRING_TOKEN_BY_IDX(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk),            \
+						   clock_names, 0)
+#define SRC_CLOCK_FREQ(clk) _CONCAT(CLOCK_FREQ_, SRC_CLOCK(clk))
+
+#define PLL_FREQ(pll)                                                                              \
+	(DT_PROP(DT_CLOCKS_CTLR_BY_IDX(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll), 0), clock_frequency) / \
+	 REF_DIV(pll) * FB_DIV(pll) / POST_DIV1(pll) / POST_DIV2(pll))
+
+#define CLOCK_FREQ_clk_gpout0 DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_gpout0), clock_frequency)
+#define CLOCK_FREQ_clk_gpout1 DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_gpout1), clock_frequency)
+#define CLOCK_FREQ_clk_gpout2 DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_gpout2), clock_frequency)
+#define CLOCK_FREQ_clk_gpout3 DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_gpout3), clock_frequency)
+#define CLOCK_FREQ_clk_ref    DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_ref), clock_frequency)
+#define CLOCK_FREQ_clk_sys    DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_sys), clock_frequency)
+#define CLOCK_FREQ_clk_usb    DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_usb), clock_frequency)
+#define CLOCK_FREQ_clk_adc    DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_adc), clock_frequency)
+#define CLOCK_FREQ_clk_rtc    DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_rtc), clock_frequency)
+#define CLOCK_FREQ_clk_peri   DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk_peri), clock_frequency)
+#define CLOCK_FREQ_xosc       DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, xosc), clock_frequency)
+#define CLOCK_FREQ_rosc       DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc), clock_frequency)
+#define CLOCK_FREQ_rosc_ph    DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc), clock_frequency)
+#define CLOCK_FREQ_gpin0      DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, gpin0), clock_frequency)
+#define CLOCK_FREQ_gpin1      DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, gpin1), clock_frequency)
+#define CLOCK_FREQ_pll_sys    PLL_FREQ(pll_sys)
+#define CLOCK_FREQ_pll_usb    PLL_FREQ(pll_usb)
+
+#define CLOCK_AUX_SOURCE(clk) _CONCAT(_CONCAT(AUXSTEM_, clk), _CONCAT(AUXSRC_, SRC_CLOCK(clk)))
+
+#define AUXSRC_xosc      XOSC_CLKSRC
+#define AUXSRC_rosc      ROSC_CLKSRC
+#define AUXSRC_rosc_ph   ROSC_CLKSRC_PH
+#define AUXSRC_pll_sys   CLKSRC_PLL_SYS
+#define AUXSRC_pll_usb   CLKSRC_PLL_USB
+#define AUXSRC_clk_ref   CLK_REF
+#define AUXSRC_clk_sys   CLK_SYS
+#define AUXSRC_clk_usb   CLK_USB
+#define AUXSRC_clk_adc   CLK_ADC
+#define AUXSRC_clk_rtc   CLK_RTC
+#define AUXSRC_clk_gpin0 CLKSRC_GPIN0
+#define AUXSRC_clk_gpin1 CLKSRC_GPIN1
+
+#define AUXSTEM_clk_gpout0 CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_gpout1 CLOCKS_CLK_GPOUT1_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_gpout2 CLOCKS_CLK_GPOUT2_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_gpout3 CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_ref    CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_sys    CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_usb    CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_adc    CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_rtc    CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_
+#define AUXSTEM_clk_peri   CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_
+
+#define TUPLE_ENTRY(n, p, i)                                                                       \
+	{                                                                                          \
+		_CONCAT(RPI_PICO_CLKID_, DT_INST_STRING_UPPER_TOKEN_BY_IDX(0, clock_names, i)),    \
+			COND_CODE_1(                                                               \
+				DT_PROP_HAS_IDX(DT_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(clocks), i),    \
+						clocks, 0),                                        \
+				(_CONCAT(RPI_PICO_CLKID_,                                          \
+					 DT_STRING_UPPER_TOKEN_BY_IDX(                             \
+						 DT_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(clocks), i),   \
+						 clock_names, 0))),                                \
+				(-1))                                                              \
+	}
+
+enum rpi_pico_clkid {
+	rpi_pico_clkid_none = -1,
+	rpi_pico_clkid_clk_gpout0 = RPI_PICO_CLKID_CLK_GPOUT0,
+	rpi_pico_clkid_clk_gpout1 = RPI_PICO_CLKID_CLK_GPOUT1,
+	rpi_pico_clkid_clk_gpout2 = RPI_PICO_CLKID_CLK_GPOUT2,
+	rpi_pico_clkid_clk_gpout3 = RPI_PICO_CLKID_CLK_GPOUT3,
+	rpi_pico_clkid_clk_ref = RPI_PICO_CLKID_CLK_REF,
+	rpi_pico_clkid_clk_sys = RPI_PICO_CLKID_CLK_SYS,
+	rpi_pico_clkid_clk_peri = RPI_PICO_CLKID_CLK_PERI,
+	rpi_pico_clkid_clk_usb = RPI_PICO_CLKID_CLK_USB,
+	rpi_pico_clkid_clk_adc = RPI_PICO_CLKID_CLK_ADC,
+	rpi_pico_clkid_clk_rtc = RPI_PICO_CLKID_CLK_RTC,
+	rpi_pico_clkid_pll_sys = RPI_PICO_CLKID_PLL_SYS,
+	rpi_pico_clkid_pll_usb = RPI_PICO_CLKID_PLL_USB,
+	rpi_pico_clkid_xosc = RPI_PICO_CLKID_XOSC,
+	rpi_pico_clkid_rosc = RPI_PICO_CLKID_ROSC,
+	rpi_pico_clkid_rosc_ph = RPI_PICO_CLKID_ROSC_PH,
+	rpi_pico_clkid_gpin0 = RPI_PICO_CLKID_GPIN0,
+	rpi_pico_clkid_gpin1 = RPI_PICO_CLKID_GPIN1,
+	END_OF_RPI_PICO_CLKID,
+};
+
+struct rpi_pico_clkid_tuple {
+	enum rpi_pico_clkid clk;
+	enum rpi_pico_clkid parent;
+};
+
+struct rpi_pico_clk_config {
+	uint32_t source;
+	uint32_t aux_source;
+	uint32_t rate;
+	uint32_t source_rate;
+};
+
+struct rpi_pico_pll_config {
+	uint32_t ref_div;
+	uint32_t fb_div;
+	uint32_t post_div1;
+	uint32_t post_div2;
+};
+
+struct rpi_pico_rosc_config {
+	uint32_t phase;
+	uint32_t range;
+	uint32_t div;
+	uint32_t code;
+};
+
+struct rpi_pico_gpin_config {
+	uint32_t frequency;
+};
+
+struct clock_control_rpi_pico_config {
+	clocks_hw_t *const clocks_regs;
+	xosc_hw_t *const xosc_regs;
+	pll_hw_t *const pll_sys_regs;
+	pll_hw_t *const pll_usb_regs;
+	rosc_hw_t *const rosc_regs;
+	const struct pinctrl_dev_config *pcfg;
+	struct rpi_pico_pll_config plls_data[RPI_PICO_PLL_COUNT];
+	struct rpi_pico_clk_config clocks_data[RPI_PICO_CLOCK_COUNT];
+	struct rpi_pico_rosc_config rosc_data;
+	struct rpi_pico_gpin_config gpin_data[RPI_PICO_GPIN_COUNT];
+};
+
+struct clock_control_rpi_pico_data {
+	uint32_t rosc_freq;
+	uint32_t rosc_ph_freq;
+};
+
+uint64_t rpi_pico_frequency_count(const struct device *dev, clock_control_subsys_t sys)
+{
+	const struct clock_control_rpi_pico_config *config = dev->config;
+	enum rpi_pico_clkid clkid = (enum rpi_pico_clkid)sys;
+	fc_hw_t *fc0 = &config->clocks_regs->fc0;
+	uint32_t fc0_id;
+
+	switch (clkid) {
+	case rpi_pico_clkid_clk_ref:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLK_REF;
+		break;
+	case rpi_pico_clkid_clk_sys:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLK_SYS;
+		break;
+	case rpi_pico_clkid_clk_peri:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLK_PERI;
+		break;
+	case rpi_pico_clkid_clk_usb:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLK_USB;
+		break;
+	case rpi_pico_clkid_clk_adc:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLK_ADC;
+		break;
+	case rpi_pico_clkid_clk_rtc:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLK_RTC;
+		break;
+	case rpi_pico_clkid_pll_sys:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY;
+		break;
+	case rpi_pico_clkid_pll_usb:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY;
+		break;
+	case rpi_pico_clkid_xosc:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_XOSC_CLKSRC;
+		break;
+	case rpi_pico_clkid_rosc:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC;
+		break;
+	case rpi_pico_clkid_rosc_ph:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC_PH;
+		break;
+	case rpi_pico_clkid_gpin0:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLKSRC_GPIN0;
+		break;
+	case rpi_pico_clkid_gpin1:
+		fc0_id = CLOCKS_FC0_SRC_VALUE_CLKSRC_GPIN0;
+		break;
+	default:
+		return -1;
+	}
+
+	(void)frequency_count_khz(fc0_id);
+
+	return ((fc0->result >> CLOCKS_FC0_RESULT_KHZ_LSB) * 1000) +
+	       ((fc0->result & CLOCKS_FC0_RESULT_FRAC_BITS) * 1000 / CLOCKS_FC0_RESULT_FRAC_BITS);
+}
+
+static int rpi_pico_rosc_write(const struct device *dev, io_rw_32 *addr, uint32_t value)
+{
+	hw_clear_bits(&rosc_hw->status, ROSC_STATUS_BADWRITE_BITS);
+
+	if (rosc_hw->status & ROSC_STATUS_BADWRITE_BITS) {
+		return -EINVAL;
+	}
+
+	*addr = value;
+
+	if (rosc_hw->status & ROSC_STATUS_BADWRITE_BITS) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * Get source clock id of this clock
+ *
+ * @param dev pointer to clock device
+ * @param id id of this clock
+ * @return parent clock id
+ */
+static enum rpi_pico_clkid rpi_pico_get_clock_src(const struct device *dev, enum rpi_pico_clkid id)
+{
+	const struct clock_control_rpi_pico_config *config = dev->config;
+	enum rpi_pico_clkid srcid = rpi_pico_clkid_none;
+
+	if (id == rpi_pico_clkid_clk_gpout0 || id == rpi_pico_clkid_clk_gpout1 ||
+	    id == rpi_pico_clkid_clk_gpout2 || id == rpi_pico_clkid_clk_gpout3) {
+		const static enum rpi_pico_clkid table[] = {
+			rpi_pico_clkid_pll_sys,
+			rpi_pico_clkid_gpin0,
+			rpi_pico_clkid_gpin1,
+			rpi_pico_clkid_pll_usb,
+			rpi_pico_clkid_rosc_ph,
+			rpi_pico_clkid_xosc,
+			rpi_pico_clkid_clk_sys,
+			rpi_pico_clkid_clk_usb,
+			rpi_pico_clkid_clk_adc,
+			rpi_pico_clkid_clk_rtc,
+			rpi_pico_clkid_clk_ref,
+		};
+
+		clock_hw_t *clock_hw = &config->clocks_regs->clk[id];
+		uint32_t aux = ((clock_hw->ctrl & CTRL_AUXSRC_BITS) >> CTRL_AUXSRC_LSB);
+
+		srcid = table[aux];
+	} else if (id == rpi_pico_clkid_clk_ref) {
+		const static enum rpi_pico_clkid table[] = {
+			rpi_pico_clkid_pll_usb,
+			rpi_pico_clkid_gpin0,
+			rpi_pico_clkid_gpin1,
+		};
+
+		clock_hw_t *clock_hw = &clocks_hw->clk[id];
+		uint32_t aux = ((clock_hw->ctrl & CTRL_AUXSRC_BITS) >> CTRL_AUXSRC_LSB);
+		uint32_t src = ((clock_hw->ctrl >> CTRL_SRC_LSB) & CTRL_SRC_BITS);
+
+		if (src == CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH) {
+			srcid = rpi_pico_clkid_rosc_ph;
+		} else if (src == CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC) {
+			srcid = rpi_pico_clkid_xosc;
+		} else {
+			srcid = table[aux];
+		}
+	} else if (id == rpi_pico_clkid_clk_sys) {
+		const static enum rpi_pico_clkid table[] = {
+			rpi_pico_clkid_pll_sys,
+			rpi_pico_clkid_pll_usb,
+			rpi_pico_clkid_rosc,
+			rpi_pico_clkid_xosc,
+			rpi_pico_clkid_gpin0,
+			rpi_pico_clkid_gpin1,
+		};
+
+		clock_hw_t *clock_hw = &clocks_hw->clk[id];
+		uint32_t aux = ((clock_hw->ctrl & CTRL_AUXSRC_BITS) >> CTRL_AUXSRC_LSB);
+		uint32_t src = ((clock_hw->ctrl >> CTRL_SRC_LSB) & CTRL_SRC_BITS);
+
+		if (src == CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF) {
+			srcid = rpi_pico_clkid_clk_ref;
+		} else {
+			srcid = table[aux];
+		}
+	} else if (id == rpi_pico_clkid_clk_peri) {
+		const static enum rpi_pico_clkid table[] = {
+			rpi_pico_clkid_clk_sys,
+			rpi_pico_clkid_pll_sys,
+			rpi_pico_clkid_pll_usb,
+			rpi_pico_clkid_rosc_ph,
+			rpi_pico_clkid_xosc,
+			rpi_pico_clkid_gpin0,
+			rpi_pico_clkid_gpin1,
+		};
+
+		clock_hw_t *clock_hw = &clocks_hw->clk[id];
+		uint32_t aux = ((clock_hw->ctrl & CTRL_AUXSRC_BITS) >> CTRL_AUXSRC_LSB);
+
+		srcid = table[aux];
+	} else if (id == rpi_pico_clkid_clk_usb || id == rpi_pico_clkid_clk_adc ||
+		   id == rpi_pico_clkid_clk_rtc) {
+		const static enum rpi_pico_clkid table[] = {
+			rpi_pico_clkid_pll_usb,
+			rpi_pico_clkid_pll_sys,
+			rpi_pico_clkid_rosc_ph,
+			rpi_pico_clkid_xosc,
+			rpi_pico_clkid_gpin0,
+			rpi_pico_clkid_gpin1,
+		};
+
+		clock_hw_t *clock_hw = &clocks_hw->clk[id];
+		uint32_t aux = ((clock_hw->ctrl & CTRL_AUXSRC_BITS) >> CTRL_AUXSRC_LSB);
+
+		srcid = table[aux];
+	} else if (id == rpi_pico_clkid_pll_sys || id == rpi_pico_clkid_pll_usb) {
+		srcid = rpi_pico_clkid_xosc;
+	}
+
+	return srcid;
+}
+
+/**
+ * Query clock is enabled or not
+ *
+ * @param dev pointer to clock device
+ * @param id id of clock
+ * @return true if the clock enabled, otherwith false
+ */
+static bool rpi_pico_is_clock_enabled(const struct device *dev, enum rpi_pico_clkid id)
+{
+	const struct clock_control_rpi_pico_config *config = dev->config;
+
+	if (id == rpi_pico_clkid_clk_sys || id == rpi_pico_clkid_clk_ref) {
+		return true;
+	} else if (id == rpi_pico_clkid_clk_usb ||
+		   id == rpi_pico_clkid_clk_peri ||
+		   id == rpi_pico_clkid_clk_adc ||
+		   id == rpi_pico_clkid_clk_rtc ||
+		   id == rpi_pico_clkid_clk_gpout0 ||
+		   id == rpi_pico_clkid_clk_gpout1 ||
+		   id == rpi_pico_clkid_clk_gpout2 ||
+		   id == rpi_pico_clkid_clk_gpout3) {
+		clock_hw_t *clock_hw = &config->clocks_regs->clk[id];
+
+		if (clock_hw->ctrl & CTRL_ENABLE_BITS) {
+			return true;
+		}
+	} else if (id == rpi_pico_clkid_pll_sys || id == rpi_pico_clkid_pll_usb) {
+		pll_hw_t *pll = (id == rpi_pico_clkid_pll_sys) ? config->pll_sys_regs
+							       : config->pll_usb_regs;
+
+		if (!(pll->pwr & (PLL_PWR_VCOPD_BITS | PLL_PWR_POSTDIVPD_BITS | PLL_PWR_PD_BITS))) {
+			return true;
+		}
+	} else if (id == rpi_pico_clkid_xosc) {
+		if (config->xosc_regs->status & XOSC_STATUS_ENABLED_BITS) {
+			return true;
+		}
+	} else if (id == rpi_pico_clkid_rosc || id == rpi_pico_clkid_rosc_ph) {
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * Calculate clock frequency with traversing clock tree.
+ *
+ * @param dev pointer to clock device
+ * @param id id of clock
+ * @return frequency value or 0 if disabled
+ */
+static float rpi_pico_calc_clock_freq(const struct device *dev, enum rpi_pico_clkid id)
+{
+	const struct clock_control_rpi_pico_config *config = dev->config;
+	struct clock_control_rpi_pico_data *data = dev->data;
+	float freq = 0.f;
+
+	if (!rpi_pico_is_clock_enabled(dev, id)) {
+		return freq;
+	}
+
+	if (id == rpi_pico_clkid_clk_sys ||
+	    id == rpi_pico_clkid_clk_usb ||
+	    id == rpi_pico_clkid_clk_adc ||
+	    id == rpi_pico_clkid_clk_rtc ||
+	    id == rpi_pico_clkid_clk_ref ||
+	    id == rpi_pico_clkid_clk_gpout0 ||
+	    id == rpi_pico_clkid_clk_gpout1 ||
+	    id == rpi_pico_clkid_clk_gpout2 ||
+	    id == rpi_pico_clkid_clk_gpout3) {
+		clock_hw_t *clock_hw = &config->clocks_regs->clk[id];
+
+		freq = rpi_pico_calc_clock_freq(dev, rpi_pico_get_clock_src(dev, id)) /
+		       (((clock_hw->div & DIV_INT_BITS) >> DIV_INT_LSB) +
+			((clock_hw->div & DIV_FRAC_BITS) / (float)DIV_FRAC_BITS));
+	} else if (id == rpi_pico_clkid_clk_peri) {
+		freq = rpi_pico_calc_clock_freq(dev, rpi_pico_get_clock_src(dev, id));
+	} else if (id == rpi_pico_clkid_pll_sys || id == rpi_pico_clkid_pll_usb) {
+		pll_hw_t *pll = (id == rpi_pico_clkid_pll_sys) ? config->pll_sys_regs
+							       : config->pll_usb_regs;
+		freq = rpi_pico_calc_clock_freq(dev, rpi_pico_get_clock_src(dev, id)) *
+		       (pll->fbdiv_int) / (pll->cs & PLL_CS_REFDIV_BITS) /
+		       ((pll->prim & PLL_PRIM_POSTDIV1_BITS) >> PLL_PRIM_POSTDIV1_LSB) /
+		       ((pll->prim & PLL_PRIM_POSTDIV2_BITS) >> PLL_PRIM_POSTDIV2_LSB);
+	} else if (id == rpi_pico_clkid_xosc) {
+		freq = CLOCK_FREQ_xosc;
+	} else if (id == rpi_pico_clkid_rosc) {
+		freq = data->rosc_freq;
+	} else if (id == rpi_pico_clkid_rosc_ph) {
+		freq = data->rosc_ph_freq;
+	}
+
+	return freq;
+}
+
+static int rpi_pico_is_valid_clock_index(enum rpi_pico_clkid index)
+{
+	if (index >= END_OF_RPI_PICO_CLKID) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int clock_control_rpi_pico_on(const struct device *dev, clock_control_subsys_t sys)
+{
+	const struct clock_control_rpi_pico_config *config = dev->config;
+	enum rpi_pico_clkid clkid = (enum rpi_pico_clkid)sys;
+	clocks_hw_t *clocks_regs = config->clocks_regs;
+
+	if (rpi_pico_is_valid_clock_index(clkid) < 0) {
+		return -EINVAL;
+	}
+
+	hw_set_bits(&clocks_regs->clk[clkid].ctrl, CTRL_ENABLE_BITS);
+
+	return 0;
+}
+
+static int clock_control_rpi_pico_off(const struct device *dev, clock_control_subsys_t sys)
+{
+	const struct clock_control_rpi_pico_config *config = dev->config;
+	enum rpi_pico_clkid clkid = (enum rpi_pico_clkid)sys;
+	clocks_hw_t *clocks_regs = config->clocks_regs;
+
+	if (rpi_pico_is_valid_clock_index(clkid) < 0) {
+		return -EINVAL;
+	}
+
+	hw_clear_bits(&clocks_regs->clk[clkid].ctrl, CTRL_ENABLE_BITS);
+
+	return 0;
+}
+
+static enum clock_control_status clock_control_rpi_pico_get_status(const struct device *dev,
+								   clock_control_subsys_t sys)
+{
+	enum rpi_pico_clkid clkid = (enum rpi_pico_clkid)sys;
+
+	if (rpi_pico_is_valid_clock_index(clkid) < 0) {
+		return -EINVAL;
+	}
+
+	if (rpi_pico_is_clock_enabled(dev, clkid)) {
+		return CLOCK_CONTROL_STATUS_ON;
+	}
+
+	return CLOCK_CONTROL_STATUS_OFF;
+}
+
+static int clock_control_rpi_pico_get_rate(const struct device *dev, clock_control_subsys_t sys,
+					   uint32_t *rate)
+{
+	struct clock_control_rpi_pico_data *data = dev->data;
+	enum rpi_pico_clkid clkid = (enum rpi_pico_clkid)sys;
+
+	if (rpi_pico_is_valid_clock_index(clkid) < 0) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_RPI_PICO_ROSC_USE_MEASURED_FREQ)) {
+		if (clkid == rpi_pico_clkid_rosc) {
+			data->rosc_freq = rpi_pico_frequency_count(dev, sys);
+		} else if (clkid == rpi_pico_clkid_rosc_ph) {
+			data->rosc_ph_freq = rpi_pico_frequency_count(dev, sys);
+		}
+	}
+
+	*rate = (int)rpi_pico_calc_clock_freq(dev, clkid);
+
+	return 0;
+}
+
+void rpi_pico_clkid_tuple_swap(struct rpi_pico_clkid_tuple *lhs, struct rpi_pico_clkid_tuple *rhs)
+{
+	struct rpi_pico_clkid_tuple tmp = *lhs;
+	*lhs = *rhs;
+	*rhs = tmp;
+}
+
+void rpi_pico_clkid_tuple_reorder_by_dependencies(struct rpi_pico_clkid_tuple *tuples, size_t len)
+{
+	uint32_t sorted_idx = 0;
+	uint32_t checked_idx = 0;
+	uint32_t target = -1;
+
+	while (sorted_idx < len) {
+		for (uint32_t i = sorted_idx; i < len; i++) {
+			if (tuples[i].parent == target) {
+				rpi_pico_clkid_tuple_swap(&tuples[sorted_idx], &tuples[i]);
+				sorted_idx++;
+			}
+		}
+		target = tuples[checked_idx++].clk;
+	}
+}
+
+static int clock_control_rpi_pico_init(const struct device *dev)
+{
+	const struct clock_control_rpi_pico_config *config = dev->config;
+	struct clock_control_rpi_pico_data *data = dev->data;
+	clocks_hw_t *clocks_regs = config->clocks_regs;
+	rosc_hw_t *rosc_regs = config->rosc_regs;
+	pll_hw_t *plls[] = {config->pll_sys_regs, config->pll_usb_regs};
+	struct rpi_pico_clkid_tuple tuples[] = {
+		DT_INST_FOREACH_PROP_ELEM_SEP(0, clock_names, TUPLE_ENTRY, (,))};
+	uint32_t rosc_div;
+	int ret;
+
+	/* Reset all function before clock configuring */
+	reset_block(~(RESETS_RESET_IO_QSPI_BITS | RESETS_RESET_PADS_QSPI_BITS |
+		      RESETS_RESET_PLL_USB_BITS | RESETS_RESET_USBCTRL_BITS |
+		      RESETS_RESET_PLL_USB_BITS | RESETS_RESET_SYSCFG_BITS |
+		      RESETS_RESET_PLL_SYS_BITS));
+
+	unreset_block_wait(RESETS_RESET_BITS &
+			   ~(RESETS_RESET_ADC_BITS | RESETS_RESET_RTC_BITS |
+			     RESETS_RESET_SPI0_BITS | RESETS_RESET_SPI1_BITS |
+			     RESETS_RESET_UART0_BITS | RESETS_RESET_UART1_BITS |
+			     RESETS_RESET_USBCTRL_BITS | RESETS_RESET_PWM_BITS));
+
+	/* Start tick in watchdog */
+	watchdog_hw->tick = ((CLOCK_FREQ_xosc/1000000) | WATCHDOG_TICK_ENABLE_BITS);
+
+	clocks_regs->resus.ctrl = 0;
+
+	/* Configure xosc */
+	xosc_init();
+
+	/* Before we touch PLLs, switch sys and ref cleanly away from their aux sources. */
+	clocks_hw->clk[RPI_PICO_CLKID_CLK_SYS].ctrl &= ~CTRL_SRC_BITS;
+	while (clocks_hw->clk[RPI_PICO_CLKID_CLK_SYS].selected != 0x1) {
+		;
+	}
+	clocks_hw->clk[RPI_PICO_CLKID_CLK_REF].ctrl &= ~CTRL_SRC_BITS;
+	while (clocks_hw->clk[RPI_PICO_CLKID_CLK_REF].selected != 0x1) {
+		;
+	}
+
+	/* Configure pll */
+	for (uint32_t i = 0; i < RPI_PICO_PLL_COUNT; i++) {
+		pll_init(plls[i], config->plls_data[i].ref_div,
+			 CLOCK_FREQ_xosc * config->plls_data[i].fb_div,
+			 config->plls_data[i].post_div1, config->plls_data[i].post_div2);
+	}
+
+	/* Configure clocks */
+	rpi_pico_clkid_tuple_reorder_by_dependencies(tuples, ARRAY_SIZE(tuples));
+	for (uint32_t i = 0; i < ARRAY_SIZE(tuples); i++) {
+		if (tuples[i].clk < 0 || tuples[i].clk >= RPI_PICO_CLOCK_COUNT) {
+			continue;
+		}
+
+		if (!(clock_configure(tuples[i].clk, config->clocks_data[tuples[i].clk].source,
+				      config->clocks_data[tuples[i].clk].aux_source,
+				      config->clocks_data[tuples[i].clk].source_rate,
+				      config->clocks_data[tuples[i].clk].rate))) {
+			return -EINVAL;
+		}
+	}
+
+	hw_clear_bits(&clocks_regs->clk[rpi_pico_clkid_clk_gpout0].ctrl, CTRL_ENABLE_BITS);
+	hw_clear_bits(&clocks_regs->clk[rpi_pico_clkid_clk_gpout1].ctrl, CTRL_ENABLE_BITS);
+	hw_clear_bits(&clocks_regs->clk[rpi_pico_clkid_clk_gpout2].ctrl, CTRL_ENABLE_BITS);
+	hw_clear_bits(&clocks_regs->clk[rpi_pico_clkid_clk_gpout3].ctrl, CTRL_ENABLE_BITS);
+
+	/* Configure rosc */
+	ret = rpi_pico_rosc_write(dev, &rosc_regs->phase,
+				  (ROSC_PHASE_PASSWD_VALUE_PASS << ROSC_PHASE_PASSWD_LSB) |
+					  config->rosc_data.phase);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = rpi_pico_rosc_write(dev, &rosc_regs->ctrl,
+				  (ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB) |
+					  config->rosc_data.range);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (config->rosc_data.div <= 0) {
+		rosc_div = ROSC_DIV_VALUE_PASS + 1;
+	} else if (config->rosc_data.div > 31) {
+		rosc_div = ROSC_DIV_VALUE_PASS;
+	} else {
+		rosc_div = ROSC_DIV_VALUE_PASS + config->rosc_data.div;
+	}
+
+	ret = rpi_pico_rosc_write(dev, &rosc_regs->div, rosc_div);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = rpi_pico_rosc_write(dev, &rosc_regs->freqa,
+				  (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) |
+					  (config->rosc_data.code & UINT16_MAX));
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = rpi_pico_rosc_write(dev, &rosc_regs->freqb,
+				  (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) |
+					  (config->rosc_data.code >> 16));
+	if (ret < 0) {
+		return ret;
+	}
+
+	unreset_block_wait(RESETS_RESET_BITS);
+
+	if (IS_ENABLED(CONFIG_RPI_PICO_ROSC_USE_MEASURED_FREQ)) {
+		data->rosc_freq =
+			rpi_pico_frequency_count(dev, (clock_control_subsys_t)rpi_pico_clkid_rosc);
+		data->rosc_ph_freq = rpi_pico_frequency_count(
+			dev, (clock_control_subsys_t)rpi_pico_clkid_rosc_ph);
+	}
+
+	return 0;
+}
+
+static const struct clock_control_driver_api clock_control_rpi_pico_api = {
+	.on = clock_control_rpi_pico_on,
+	.off = clock_control_rpi_pico_off,
+	.get_rate = clock_control_rpi_pico_get_rate,
+	.get_status = clock_control_rpi_pico_get_status,
+};
+
+BUILD_ASSERT((VCO_FREQ(pll_sys) >= PLL_VCO_FREQ_MIN) && (VCO_FREQ(pll_sys) <= PLL_VCO_FREQ_MAX) &&
+		     (VCO_FREQ(pll_sys) >= (CLOCK_FREQ_xosc / REF_DIV(pll_sys) * 16)),
+	     "pll_sys: vco_freq is out of range");
+BUILD_ASSERT((FB_DIV(pll_sys) >= PLL_FB_DIV_MIN) && (FB_DIV(pll_sys) <= PLL_FB_DIV_MAX),
+	     "pll_sys: fb-div is out of range");
+BUILD_ASSERT((POST_DIV1(pll_sys) >= PLL_POST_DIV_MIN) && (POST_DIV1(pll_sys) <= PLL_POST_DIV_MAX),
+	     "pll_sys: post-div1 is out of range");
+BUILD_ASSERT((POST_DIV2(pll_sys) >= PLL_POST_DIV_MIN) && (POST_DIV2(pll_sys) <= PLL_POST_DIV_MAX),
+	     "pll_sys: post-div2 is out of range");
+
+BUILD_ASSERT((VCO_FREQ(pll_usb) >= PLL_VCO_FREQ_MIN) && (VCO_FREQ(pll_usb) <= PLL_VCO_FREQ_MAX) &&
+		     (VCO_FREQ(pll_usb) >= (CLOCK_FREQ_xosc / REF_DIV(pll_usb) * 16)),
+	     "pll_usb: vco_freq is out of range");
+BUILD_ASSERT((FB_DIV(pll_usb) >= PLL_FB_DIV_MIN) && (FB_DIV(pll_usb) <= PLL_FB_DIV_MAX),
+	     "pll_usb: fb-div is out of range");
+BUILD_ASSERT((POST_DIV1(pll_usb) >= PLL_POST_DIV_MIN) && (POST_DIV1(pll_usb) <= PLL_POST_DIV_MAX),
+	     "pll_usb: post-div is out of range");
+BUILD_ASSERT((POST_DIV2(pll_usb) >= PLL_POST_DIV_MIN) && (POST_DIV2(pll_usb) <= PLL_POST_DIV_MAX),
+	     "pll_usb: post-div is out of range");
+
+BUILD_ASSERT(SRC_CLOCK_FREQ(clk_ref) >= CLOCK_FREQ_clk_ref,
+	     "clk_ref: clock divider is out of range");
+BUILD_ASSERT(SRC_CLOCK_FREQ(clk_sys) >= CLOCK_FREQ_clk_sys,
+	     "clk_sys: clock divider is out of range");
+BUILD_ASSERT(SRC_CLOCK_FREQ(clk_usb) >= CLOCK_FREQ_clk_usb,
+	     "clk_usb: clock divider is out of range");
+BUILD_ASSERT(SRC_CLOCK_FREQ(clk_adc) >= CLOCK_FREQ_clk_adc,
+	     "clk_adc: clock divider is out of range");
+BUILD_ASSERT(SRC_CLOCK_FREQ(clk_rtc) >= CLOCK_FREQ_clk_rtc,
+	     "clk_rtc: clock divider is out of range");
+BUILD_ASSERT(SRC_CLOCK_FREQ(clk_peri) >= CLOCK_FREQ_clk_peri,
+	     "clk_peri: clock divider is out of range");
+
+BUILD_ASSERT(CLOCK_FREQ(rosc_ph) == CLOCK_FREQ(rosc), "rosc_ph: frequency must be equal to rosc");
+
+static const struct clock_control_rpi_pico_config clock_control_rpi_pico_config = {
+	.clocks_regs = (clocks_hw_t *)DT_INST_REG_ADDR_BY_NAME(0, clocks),
+	.xosc_regs = (xosc_hw_t *)DT_INST_REG_ADDR_BY_NAME(0, xosc),
+	.pll_sys_regs = (pll_hw_t *)DT_INST_REG_ADDR_BY_NAME(0, pll_sys),
+	.pll_usb_regs = (pll_hw_t *)DT_INST_REG_ADDR_BY_NAME(0, pll_usb),
+	.rosc_regs = (rosc_hw_t *)DT_INST_REG_ADDR_BY_NAME(0, rosc),
+	.clocks_data = {
+		[RPI_PICO_CLKID_CLK_GPOUT0] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_gpout0),
+			.source_rate = SRC_CLOCK_FREQ(clk_gpout0),
+			.rate = CLOCK_FREQ(clk_gpout0),
+		},
+		[RPI_PICO_CLKID_CLK_GPOUT1] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_gpout1),
+			.source_rate = SRC_CLOCK_FREQ(clk_gpout1),
+			.rate = CLOCK_FREQ(clk_gpout1),
+		},
+		[RPI_PICO_CLKID_CLK_GPOUT2] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_gpout2),
+			.source_rate = SRC_CLOCK_FREQ(clk_gpout2),
+			.rate = CLOCK_FREQ(clk_gpout2),
+		},
+		[RPI_PICO_CLKID_CLK_GPOUT3] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_gpout3),
+			.source_rate = SRC_CLOCK_FREQ(clk_gpout3),
+			.rate = CLOCK_FREQ(clk_gpout3),
+		},
+		[RPI_PICO_CLKID_CLK_REF] = {
+#if CLK_SRC_IS(clk_ref, rosc_ph)
+			.source = CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH,
+			.aux_source = 0,
+#elif CLK_SRC_IS(clk_ref, xosc)
+			.source = CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC,
+			.aux_source = 0,
+#else
+			.source = CLOCKS_CLK_REF_CTRL_SRC_VALUE_CLKSRC_CLK_REF_AUX,
+#endif
+			.source_rate = SRC_CLOCK_FREQ(clk_ref),
+			.rate = CLOCK_FREQ(clk_ref),
+		},
+		[RPI_PICO_CLKID_CLK_SYS] = {
+#if CLK_SRC_IS(clk_sys, clk_ref)
+			.source = CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF,
+			.aux_source = 0,
+#else
+			.source = CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
+			.aux_source = CLOCK_AUX_SOURCE(clk_sys),
+#endif
+			.source_rate = SRC_CLOCK_FREQ(clk_sys),
+			.rate = CLOCK_FREQ(clk_sys),
+		},
+		[RPI_PICO_CLKID_CLK_PERI] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_peri),
+			.source_rate = SRC_CLOCK_FREQ(clk_peri),
+			.rate = CLOCK_FREQ(clk_peri),
+		},
+		[RPI_PICO_CLKID_CLK_USB] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_usb),
+			.source_rate = SRC_CLOCK_FREQ(clk_usb),
+			.rate = CLOCK_FREQ(clk_usb),
+		},
+		[RPI_PICO_CLKID_CLK_ADC] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_adc),
+			.source_rate = SRC_CLOCK_FREQ(clk_adc),
+			.rate = CLOCK_FREQ(clk_adc),
+		},
+		[RPI_PICO_CLKID_CLK_RTC] = {
+			.source = 0,
+			.aux_source = CLOCK_AUX_SOURCE(clk_rtc),
+			.source_rate = SRC_CLOCK_FREQ(clk_rtc),
+			.rate = CLOCK_FREQ(clk_rtc),
+		},
+	},
+	.plls_data = {
+		[RPI_PICO_PLL_SYS] = {
+			.ref_div = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_sys), clock_div),
+			.fb_div = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_sys), fb_div),
+			.post_div1 = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_sys), post_div1),
+			.post_div2 = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_sys), post_div2),
+		},
+		[RPI_PICO_PLL_USB] = {
+			.ref_div = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_usb), clock_div),
+			.fb_div = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_usb), fb_div),
+			.post_div1 = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_usb), post_div1),
+			.post_div2 = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_usb), post_div2),
+		},
+	},
+	.rosc_data = {
+		.phase = (COND_CODE_1(DT_NODE_HAS_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc),
+						       phase_flip),
+				      (ROSC_PHASE_FLIP_BITS), (0x0)) |
+			  COND_CODE_1(DT_NODE_HAS_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc),
+						       phase),
+				      ((DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc), phase) &
+					ROSC_PHASE_SHIFT_BITS) | ROSC_PHASE_ENABLE_BITS), (0x0))),
+		.div = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc), clock_div),
+		.range = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rosc), range),
+		.code = (STAGE_DS(0) | STAGE_DS(1) | STAGE_DS(2) | STAGE_DS(3) |
+			 STAGE_DS(4) | STAGE_DS(5) | STAGE_DS(6) | STAGE_DS(7)),
+	},
+	.gpin_data = {
+		[RPI_PICO_GPIN_0] = {
+			COND_CODE_1(DT_NODE_HAS_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, gpin0),
+						 clock_frequency),
+				    (.frequency = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, gpin0),
+							  clock_frequency),),
+				    (.frequency = 0,))
+		},
+		[RPI_PICO_GPIN_1] = {
+			COND_CODE_1(DT_NODE_HAS_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, gpin1),
+						     clock_frequency),
+				    (.frequency = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, gpin1),
+							  clock_frequency),),
+				    (.frequency = 0,))
+		},
+	},
+};
+
+static struct clock_control_rpi_pico_data clock_control_rpi_pico_data = {
+	.rosc_freq = CLOCK_FREQ(rosc),
+	.rosc_ph_freq = CLOCK_FREQ(rosc_ph),
+};
+
+DEVICE_DT_INST_DEFINE(0, &clock_control_rpi_pico_init, NULL, &clock_control_rpi_pico_data,
+		      &clock_control_rpi_pico_config, PRE_KERNEL_1,
+		      CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_control_rpi_pico_api);
diff --git a/dts/arm/rpi_pico/rp2040.dtsi b/dts/arm/rpi_pico/rp2040.dtsi
index 34a09a2..72c71bf 100644
--- a/dts/arm/rpi_pico/rp2040.dtsi
+++ b/dts/arm/rpi_pico/rp2040.dtsi
@@ -7,6 +7,7 @@
 #include <arm/armv6-m.dtsi>
 #include <zephyr/dt-bindings/adc/adc.h>
 #include <zephyr/dt-bindings/gpio/gpio.h>
+#include <zephyr/dt-bindings/clock/rpi_pico_clock.h>
 #include <zephyr/dt-bindings/i2c/i2c.h>
 #include <zephyr/dt-bindings/regulator/rpi_pico.h>
 #include <mem.h>
@@ -33,6 +34,149 @@
 		};
 	};
 
+	clocks {
+		clk_gpout0: clk-gpout0 {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_sys>;
+			clock-names = "pll_sys";
+			clock-frequency = <125000000>;
+			#clock-cells = <0>;
+			#address-cells = <0>;
+		};
+
+		clk_gpout1: clk-gpout1 {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_sys>;
+			clock-names = "pll_sys";
+			clock-frequency = <125000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_gpout2: clk-gpout2 {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_sys>;
+			clock-names = "pll_sys";
+			clock-frequency = <125000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_gpout3: clk-gpout3 {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_sys>;
+			clock-names = "pll_sys";
+			clock-frequency = <125000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_ref: clk-ref {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&xosc>;
+			clock-names = "xosc";
+			clock-frequency = <12000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_sys: clk-sys {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_sys>;
+			clock-names = "pll_sys";
+			clock-frequency = <125000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_usb: clk-usb {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_usb>;
+			clock-names = "pll_usb";
+			clock-frequency = <48000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_adc: clk-adc {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_usb>;
+			clock-names = "pll_usb";
+			clock-frequency = <48000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_rtc: clk-rtc {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&pll_usb>;
+			clock-names = "pll_usb";
+			clock-frequency = <46875>;
+			#clock-cells = <0>;
+		};
+
+		clk_peri: clk-peri {
+			compatible = "raspberrypi,pico-clock";
+			clocks = <&clk_sys>;
+			clock-names = "clk_sys";
+			clock-frequency = <125000000>;
+			#clock-cells = <0>;
+		};
+
+		pll_sys: pll-sys {
+			compatible = "raspberrypi,pico-pll";
+			clocks = <&xosc>;
+			clock-names = "xosc";
+			clock-div= <1>;
+			fb-div= <125>;
+			post-div1 = <6>;
+			post-div2 = <2>;
+			#clock-cells = <0>;
+		};
+
+		pll_usb: pll-usb {
+			compatible = "raspberrypi,pico-pll";
+			clocks = <&xosc>;
+			clock-names = "xosc";
+			clock-div= <1>;
+			fb-div = <100>;
+			post-div1 = <5>;
+			post-div2 = <5>;
+			#clock-cells = <0>;
+		};
+
+		rosc: rosc {
+			compatible = "raspberrypi,pico-rosc";
+			clock-frequency = <6500000>;
+			range = <RPI_PICO_ROSC_RANGE_RESET>;
+			stage-drive-strength = <0>, <0>, <0>, <0>, <0>, <0>, <0>, <0>;
+			clock-div = <16>;
+			phase = <0>;
+			#clock-cells = <0>;
+		};
+
+		rosc_ph: rosc-ph {
+			compatible = "raspberrypi,pico-clock";
+			clock-frequency = <6500000>;
+			clocks = <&rosc>;
+			clock-names = "rosc";
+			#clock-cells = <0>;
+		};
+
+		xosc: xosc {
+			compatible = "raspberrypi,pico-clock";
+			clock-frequency = <12000000>;
+			#clock-cells = <0>;
+		};
+
+		gpin0: gpin0 {
+			compatible = "raspberrypi,pico-clock";
+			status = "disabled";
+			clock-frequency = <0>;
+			#clock-cells = <0>;
+		};
+
+		gpin1: gpin1 {
+			compatible = "raspberrypi,pico-clock";
+			status = "disabled";
+			clock-frequency = <0>;
+			#clock-cells = <0>;
+		};
+	};
+
 	soc {
 		compatible = "raspberrypi,rp2040", "simple-bus";
 
@@ -55,18 +199,6 @@
 			};
 		};
 
-		peripheral_clk: peripheral-clk {
-			compatible = "fixed-clock";
-			clock-frequency = <125000000>;
-			#clock-cells = <0>;
-		};
-
-		system_clk: system-clk {
-			compatible = "fixed-clock";
-			clock-frequency = <125000000>;
-			#clock-cells = <0>;
-		};
-
 		reset: reset-controller@4000c000 {
 			compatible = "raspberrypi,pico-reset";
 			reg = <0x4000c000 DT_SIZE_K(4)>;
@@ -75,6 +207,28 @@
 			#reset-cells = <1>;
 		};
 
+		clocks: clock-controller@40008000 {
+			compatible = "raspberrypi,pico-clock-controller";
+			reg = <0x40008000 DT_SIZE_K(4)
+			       0x40024000 DT_SIZE_K(4)
+			       0x40028000 DT_SIZE_K(4)
+			       0x4002c000 DT_SIZE_K(4)
+			       0x40060000 DT_SIZE_K(4)>;
+			reg-names = "clocks", "xosc", "pll_sys", "pll_usb", "rosc";
+			#clock-cells = <1>;
+			status = "okay";
+			clocks = <&clk_gpout0>, <&clk_gpout1>, <&clk_gpout2>, <&clk_gpout3>,
+				 <&clk_ref>, <&clk_sys>, <&clk_peri>,
+				 <&clk_usb>, <&clk_adc>, <&clk_rtc>,
+				 <&pll_sys>, <&pll_usb>, <&xosc>, <&rosc>, <&rosc_ph>,
+				 <&gpin0>, <&gpin1>;
+			clock-names = "clk_gpout0", "clk_gpout1", "clk_gpout2", "clk_gpout3",
+				 "clk_ref", "clk_sys", "clk_peri",
+				 "clk_usb", "clk_adc", "clk_rtc",
+				 "pll_sys", "pll_usb", "xosc", "rosc", "rosc_ph",
+				 "gpin0", "gpin1";
+		};
+
 		gpio0: gpio@40014000 {
 			compatible = "raspberrypi,pico-gpio";
 			reg = <0x40014000 DT_SIZE_K(4)>;
@@ -88,7 +242,7 @@
 		uart0: uart@40034000 {
 			compatible = "raspberrypi,pico-uart";
 			reg = <0x40034000 DT_SIZE_K(4)>;
-			clocks = <&peripheral_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_PERI>;
 			resets = <&reset RPI_PICO_RESETS_RESET_UART0>;
 			interrupts = <20 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "uart0";
@@ -98,7 +252,7 @@
 		uart1: uart@40038000 {
 			compatible = "raspberrypi,pico-uart";
 			reg = <0x40038000 DT_SIZE_K(4)>;
-			clocks = <&peripheral_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_PERI>;
 			resets = <&reset RPI_PICO_RESETS_RESET_UART1>;
 			interrupts = <21 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "uart1";
@@ -110,7 +264,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x4003c000 DT_SIZE_K(4)>;
-			clocks = <&peripheral_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_PERI>;
 			resets = <&reset RPI_PICO_RESETS_RESET_SPI0>;
 			interrupts = <18 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "spi0";
@@ -123,7 +277,7 @@
 			#size-cells = <0>;
 			reg = <0x40040000 DT_SIZE_K(4)>;
 			resets = <&reset RPI_PICO_RESETS_RESET_SPI1>;
-			clocks = <&peripheral_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_PERI>;
 			interrupts = <19 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "spi1";
 			status = "disabled";
@@ -133,6 +287,7 @@
 			compatible = "raspberrypi,pico-adc";
 			reg = <0x4004c000 DT_SIZE_K(4)>;
 			resets = <&reset RPI_PICO_RESETS_RESET_ADC>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_ADC>;
 			interrupts = <22 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "adc0";
 			status = "disabled";
@@ -145,7 +300,7 @@
 			#size-cells = <0>;
 			reg = <0x40044000 DT_SIZE_K(4)>;
 			resets = <&reset RPI_PICO_RESETS_RESET_I2C0>;
-			clocks = <&system_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_SYS>;
 			interrupts = <23 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "i2c0";
 			status = "disabled";
@@ -157,7 +312,7 @@
 			#size-cells = <0>;
 			reg = <0x40048000 DT_SIZE_K(4)>;
 			resets = <&reset RPI_PICO_RESETS_RESET_I2C0>;
-			clocks = <&system_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_SYS>;
 			interrupts = <24 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "i2c1";
 			status = "disabled";
@@ -166,7 +321,7 @@
 		wdt0: watchdog@40058000 {
 			compatible = "raspberrypi,pico-watchdog";
 			reg = <0x40058000 DT_SIZE_K(4)>;
-			clocks = <&xtal_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_REF>;
 			status = "disabled";
 		};
 
@@ -174,6 +329,7 @@
 			compatible = "raspberrypi,pico-usbd";
 			reg = <0x50100000 0x10000>;
 			resets = <&reset RPI_PICO_RESETS_RESET_USBCTRL>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_USB>;
 			interrupts = <5 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "usbctrl";
 			num-bidir-endpoints = <16>;
@@ -184,7 +340,7 @@
 			compatible = "raspberrypi,pico-pwm";
 			reg = <0x40050000 DT_SIZE_K(4)>;
 			resets = <&reset RPI_PICO_RESETS_RESET_PWM>;
-			clocks = <&system_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_SYS>;
 			interrupts = <4 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "PWM_IRQ_WRAP";
 			status = "disabled";
@@ -195,7 +351,7 @@
 			compatible = "raspberrypi,pico-timer";
 			reg = <0x40054000 DT_SIZE_K(4)>;
 			resets = <&reset RPI_PICO_RESETS_RESET_TIMER>;
-			clocks = <&xtal_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_REF>;
 			interrupts = <0 RPI_PICO_DEFAULT_IRQ_PRIORITY>,
 				     <1 RPI_PICO_DEFAULT_IRQ_PRIORITY>,
 				     <2 RPI_PICO_DEFAULT_IRQ_PRIORITY>,
@@ -211,7 +367,7 @@
 			compatible = "raspberrypi,pico-dma";
 			reg = <0x50000000 DT_SIZE_K(64)>;
 			resets = <&reset RPI_PICO_RESETS_RESET_DMA>;
-			clocks = <&system_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_SYS>;
 			interrupts = <11 RPI_PICO_DEFAULT_IRQ_PRIORITY>,
 				     <12 RPI_PICO_DEFAULT_IRQ_PRIORITY>;
 			interrupt-names = "dma0", "dma1";
@@ -231,7 +387,7 @@
 		pio0: pio@50200000 {
 			compatible = "raspberrypi,pico-pio";
 			reg = <0x50200000 DT_SIZE_K(4)>;
-			clocks = <&system_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_SYS>;
 			resets = <&reset RPI_PICO_RESETS_RESET_PIO0>;
 			status = "disabled";
 		};
@@ -239,7 +395,7 @@
 		pio1: pio@50300000 {
 			compatible = "raspberrypi,pico-pio";
 			reg = <0x50300000 DT_SIZE_K(4)>;
-			clocks = <&system_clk>;
+			clocks = <&clocks RPI_PICO_CLKID_CLK_SYS>;
 			resets = <&reset RPI_PICO_RESETS_RESET_PIO1>;
 			status = "disabled";
 		};
diff --git a/dts/bindings/clock/raspberrypi,pico-clock-controller.yaml b/dts/bindings/clock/raspberrypi,pico-clock-controller.yaml
new file mode 100644
index 0000000..cf74065
--- /dev/null
+++ b/dts/bindings/clock/raspberrypi,pico-clock-controller.yaml
@@ -0,0 +1,18 @@
+# Copyright (c) 2022 Andrei-Edward Popa
+# SPDX-License-Identifier: Apache-2.0
+
+description: Raspberry Pi Pico clock controller node
+
+compatible: "raspberrypi,pico-clock-controller"
+
+include: [base.yaml, clock-controller.yaml]
+
+properties:
+  reg:
+    required: true
+
+  "#clock-cells":
+    const: 1
+
+clock-cells:
+  - clk-id
diff --git a/dts/bindings/clock/raspberrypi,pico-clock.yaml b/dts/bindings/clock/raspberrypi,pico-clock.yaml
new file mode 100644
index 0000000..c787f3c
--- /dev/null
+++ b/dts/bindings/clock/raspberrypi,pico-clock.yaml
@@ -0,0 +1,18 @@
+# Copyright (c) 2023 TOKITA Hiroshi
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  The representation of Raspberry Pi Pico's clock
+
+compatible: "raspberrypi,pico-clock"
+
+include: fixed-clock.yaml
+
+properties:
+  clocks:
+    type: phandle-array
+    description: Clock gate information
+
+  clock-names:
+    type: string-array
+    description: name of each clock
diff --git a/dts/bindings/clock/raspberrypi,pico-pll.yaml b/dts/bindings/clock/raspberrypi,pico-pll.yaml
new file mode 100644
index 0000000..d385980
--- /dev/null
+++ b/dts/bindings/clock/raspberrypi,pico-pll.yaml
@@ -0,0 +1,31 @@
+# Copyright (c) 2023 TOKITA Hiroshi
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  The representation of Raspberry Pi Pico's PLL.
+
+compatible: "raspberrypi,pico-pll"
+
+include: [base.yaml, fixed-factor-clock.yaml]
+
+properties:
+  fb-div:
+    type: int
+    required: true
+    description: |
+      The feedback divider value.
+      The valid range is 16 to 320.
+
+  post-div1:
+    type: int
+    required: true
+    description: |
+      The post clock divider.
+      The valid range is 1 to 49.
+
+  post-div2:
+    type: int
+    required: true
+    description: |
+      The post clock divider.
+      The valid range is 1 to 49.
diff --git a/dts/bindings/clock/raspberrypi,pico-rosc.yaml b/dts/bindings/clock/raspberrypi,pico-rosc.yaml
new file mode 100644
index 0000000..189ba12
--- /dev/null
+++ b/dts/bindings/clock/raspberrypi,pico-rosc.yaml
@@ -0,0 +1,38 @@
+# Copyright (c) 2023 TOKITA Hiroshi
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  The representation of Raspberry Pi Pico ring oscillator.
+
+compatible: "raspberrypi,pico-rosc"
+
+include: [fixed-clock.yaml, fixed-factor-clock.yaml]
+
+properties:
+  range:
+    type: int
+    required: true
+    description: |
+      Specify the number of ring oscillator stages to use.
+        - LOW: 8 (default)
+        - MEDIUM: 6
+        - HIGH: 4
+        - TOOHIGH: 2
+
+  stage-drive-strength:
+    type: array
+    required: true
+    description: |
+      Specifies the drive strength of the eight stages of the ring oscillator.
+      The valid range of each value is between 0 and 7.
+
+  phase-flip:
+    type: boolean
+    description: |
+      Flipping phase-shifter output.
+
+  phase:
+    type: int
+    description: |
+      The phase-shift vlaue.
+      The valid range is 0 to 3
diff --git a/include/zephyr/dt-bindings/clock/rpi_pico_clock.h b/include/zephyr/dt-bindings/clock/rpi_pico_clock.h
new file mode 100644
index 0000000..07522be
--- /dev/null
+++ b/include/zephyr/dt-bindings/clock/rpi_pico_clock.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 Andrei-Edward Popa
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RPI_PICO_CLOCK_H_
+#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RPI_PICO_CLOCK_H_
+
+#define RPI_PICO_PLL_SYS   0
+#define RPI_PICO_PLL_USB   1
+#define RPI_PICO_PLL_COUNT 2
+
+#define RPI_PICO_GPIN_0     0
+#define RPI_PICO_GPIN_1     1
+#define RPI_PICO_GPIN_COUNT 2
+
+#define RPI_PICO_CLKID_CLK_GPOUT0 0
+#define RPI_PICO_CLKID_CLK_GPOUT1 1
+#define RPI_PICO_CLKID_CLK_GPOUT2 2
+#define RPI_PICO_CLKID_CLK_GPOUT3 3
+#define RPI_PICO_CLKID_CLK_REF    4
+#define RPI_PICO_CLKID_CLK_SYS    5
+#define RPI_PICO_CLKID_CLK_PERI   6
+#define RPI_PICO_CLKID_CLK_USB    7
+#define RPI_PICO_CLKID_CLK_ADC    8
+#define RPI_PICO_CLKID_CLK_RTC    9
+
+#define RPI_PICO_CLKID_PLL_SYS 10
+#define RPI_PICO_CLKID_PLL_USB 11
+#define RPI_PICO_CLKID_XOSC    12
+#define RPI_PICO_CLKID_ROSC    13
+#define RPI_PICO_CLKID_ROSC_PH 14
+#define RPI_PICO_CLKID_GPIN0   15
+#define RPI_PICO_CLKID_GPIN1   16
+
+#define RPI_PICO_ROSC_RANGE_RESET   0xAA0
+#define RPI_PICO_ROSC_RANGE_LOW     0xFA4
+#define RPI_PICO_ROSC_RANGE_MEDIUM  0xFA5
+#define RPI_PICO_ROSC_RANGE_HIGH    0xFA7
+#define RPI_PICO_ROSC_RANGE_TOOHIGH 0xFA6
+
+#define RPI_PICO_CLOCK_COUNT 10
+
+#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RPI_PICO_CLOCK_H_ */
diff --git a/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h
index 4249fd2..c7870a2 100644
--- a/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h
+++ b/include/zephyr/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h
@@ -219,4 +219,11 @@
 #define PIO1_P28 RP2040_PINMUX(28, RP2_PINCTRL_GPIO_FUNC_PIO1)
 #define PIO1_P29 RP2040_PINMUX(29, RP2_PINCTRL_GPIO_FUNC_PIO1)
 
+#define GPIN0_P20 RP2040_PINMUX(20, RP2_PINCTRL_GPIO_FUNC_GPCK)
+#define GPIN1_P22 RP2040_PINMUX(22, RP2_PINCTRL_GPIO_FUNC_GPCK)
+#define GPOUT0_P21 RP2040_PINMUX(21, RP2_PINCTRL_GPIO_FUNC_GPCK)
+#define GPOUT1_P23 RP2040_PINMUX(23, RP2_PINCTRL_GPIO_FUNC_GPCK)
+#define GPOUT2_P24 RP2040_PINMUX(24, RP2_PINCTRL_GPIO_FUNC_GPCK)
+#define GPOUT3_P25 RP2040_PINMUX(25, RP2_PINCTRL_GPIO_FUNC_GPCK)
+
 #endif /* __RP2040_PINCTRL_H__ */
diff --git a/samples/sensor/bme280/rpi_pico_spi_pio.overlay b/samples/sensor/bme280/rpi_pico_spi_pio.overlay
index 473cfae..a555e93 100644
--- a/samples/sensor/bme280/rpi_pico_spi_pio.overlay
+++ b/samples/sensor/bme280/rpi_pico_spi_pio.overlay
@@ -22,7 +22,7 @@
 		status = "okay";
 		#address-cells = <1>;
 		#size-cells = <0>;
-		clocks = < &system_clk >;
+		clocks = <&clocks RPI_PICO_CLKID_CLK_SYS>;
 		miso-gpios = <&gpio0 12 0>;
 		cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
 		clk-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
diff --git a/soc/arm/rpi_pico/rp2/soc.c b/soc/arm/rpi_pico/rp2/soc.c
index d953436..012f543 100644
--- a/soc/arm/rpi_pico/rp2/soc.c
+++ b/soc/arm/rpi_pico/rp2/soc.c
@@ -26,24 +26,6 @@
 
 LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);
 
-static int rp2040_init(void)
-{
-	reset_block(~(RESETS_RESET_IO_QSPI_BITS | RESETS_RESET_PADS_QSPI_BITS |
-		      RESETS_RESET_PLL_USB_BITS | RESETS_RESET_PLL_SYS_BITS));
-
-	unreset_block_wait(RESETS_RESET_BITS &
-			   ~(RESETS_RESET_ADC_BITS | RESETS_RESET_RTC_BITS |
-			     RESETS_RESET_SPI0_BITS | RESETS_RESET_SPI1_BITS |
-			     RESETS_RESET_UART0_BITS | RESETS_RESET_UART1_BITS |
-			     RESETS_RESET_USBCTRL_BITS | RESETS_RESET_PWM_BITS));
-
-	clocks_init();
-
-	unreset_block_wait(RESETS_RESET_BITS);
-
-	return 0;
-}
-
 /*
  * Some pico-sdk drivers call panic on fatal error.
  * This alternative implementation of panic handles the panic
@@ -57,5 +39,3 @@
 	vprintf(fmt, args);
 	k_fatal_halt(K_ERR_CPU_EXCEPTION);
 }
-
-SYS_INIT(rp2040_init, PRE_KERNEL_1, 0);