diff options
| author | saturneric <[email protected]> | 2025-11-24 10:47:44 +0000 |
|---|---|---|
| committer | saturneric <[email protected]> | 2025-11-24 10:47:44 +0000 |
| commit | a373ff64031a27afece24210bd3d53bb912563fd (patch) | |
| tree | 44926a9a3f926febaf968d910db8102f60cf7d63 | |
| parent | refactor(dts): solve node conflicts (diff) | |
| download | kernel-linux-6.18.y.tar.gz kernel-linux-6.18.y.zip | |
fix(driver): sync specific drivers from rpi upstreamlinux-6.18.y
| -rw-r--r-- | drivers/clk/clk-rp1.c | 2092 | ||||
| -rw-r--r-- | drivers/gpio/gpio-brcmstb.c | 152 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mmio.c | 159 | ||||
| -rw-r--r-- | drivers/pinctrl/pinctrl-rp1.c | 713 | ||||
| -rw-r--r-- | include/linux/gpio/generic.h | 1 |
5 files changed, 1677 insertions, 1440 deletions
diff --git a/drivers/clk/clk-rp1.c b/drivers/clk/clk-rp1.c index c19043a90c70..ab74f20d4e5b 100644 --- a/drivers/clk/clk-rp1.c +++ b/drivers/clk/clk-rp1.c @@ -1,284 +1,289 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2023 Raspberry Pi Ltd. * * Clock driver for RP1 PCIe multifunction chip. */ +#include <linux/bitfield.h> #include <linux/clk-provider.h> -#include <linux/clkdev.h> -#include <linux/clk.h> -#include <linux/debugfs.h> -#include <linux/delay.h> -#include <linux/io.h> +#include <linux/regmap.h> #include <linux/math64.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> -#include <linux/rp1_platform.h> -#include <linux/slab.h> +#include <linux/units.h> -#include <asm/div64.h> +#include <dt-bindings/clock/raspberrypi,rp1-clocks.h> -#include <dt-bindings/clock/rp1.h> +#define PLL_SYS_OFFSET 0x08000 +#define PLL_SYS_CS (PLL_SYS_OFFSET + 0x00) +#define PLL_SYS_PWR (PLL_SYS_OFFSET + 0x04) +#define PLL_SYS_FBDIV_INT (PLL_SYS_OFFSET + 0x08) +#define PLL_SYS_FBDIV_FRAC (PLL_SYS_OFFSET + 0x0c) +#define PLL_SYS_PRIM (PLL_SYS_OFFSET + 0x10) +#define PLL_SYS_SEC (PLL_SYS_OFFSET + 0x14) -#define PLL_SYS_CS 0x08000 -#define PLL_SYS_PWR 0x08004 -#define PLL_SYS_FBDIV_INT 0x08008 -#define PLL_SYS_FBDIV_FRAC 0x0800c -#define PLL_SYS_PRIM 0x08010 -#define PLL_SYS_SEC 0x08014 +#define PLL_AUDIO_OFFSET 0x0c000 +#define PLL_AUDIO_CS (PLL_AUDIO_OFFSET + 0x00) +#define PLL_AUDIO_PWR (PLL_AUDIO_OFFSET + 0x04) +#define PLL_AUDIO_FBDIV_INT (PLL_AUDIO_OFFSET + 0x08) +#define PLL_AUDIO_FBDIV_FRAC (PLL_AUDIO_OFFSET + 0x0c) +#define PLL_AUDIO_PRIM (PLL_AUDIO_OFFSET + 0x10) +#define PLL_AUDIO_SEC (PLL_AUDIO_OFFSET + 0x14) +#define PLL_AUDIO_TERN (PLL_AUDIO_OFFSET + 0x18) -#define PLL_AUDIO_CS 0x0c000 -#define PLL_AUDIO_PWR 0x0c004 -#define PLL_AUDIO_FBDIV_INT 0x0c008 -#define PLL_AUDIO_FBDIV_FRAC 0x0c00c -#define PLL_AUDIO_PRIM 0x0c010 -#define PLL_AUDIO_SEC 0x0c014 -#define PLL_AUDIO_TERN 0x0c018 +#define PLL_VIDEO_OFFSET 0x10000 +#define PLL_VIDEO_CS (PLL_VIDEO_OFFSET + 0x00) +#define PLL_VIDEO_PWR (PLL_VIDEO_OFFSET + 0x04) +#define PLL_VIDEO_FBDIV_INT (PLL_VIDEO_OFFSET + 0x08) +#define PLL_VIDEO_FBDIV_FRAC (PLL_VIDEO_OFFSET + 0x0c) +#define PLL_VIDEO_PRIM (PLL_VIDEO_OFFSET + 0x10) +#define PLL_VIDEO_SEC (PLL_VIDEO_OFFSET + 0x14) -#define PLL_VIDEO_CS 0x10000 -#define PLL_VIDEO_PWR 0x10004 -#define PLL_VIDEO_FBDIV_INT 0x10008 -#define PLL_VIDEO_FBDIV_FRAC 0x1000c -#define PLL_VIDEO_PRIM 0x10010 -#define PLL_VIDEO_SEC 0x10014 +#define GPCLK_OE_CTRL 0x00000 -#define GPCLK_OE_CTRL 0x00000 +#define CLK_SYS_OFFSET 0x00014 +#define CLK_SYS_CTRL (CLK_SYS_OFFSET + 0x00) +#define CLK_SYS_DIV_INT (CLK_SYS_OFFSET + 0x04) +#define CLK_SYS_SEL (CLK_SYS_OFFSET + 0x0c) -#define CLK_SYS_CTRL 0x00014 -#define CLK_SYS_DIV_INT 0x00018 -#define CLK_SYS_SEL 0x00020 +#define CLK_SLOW_OFFSET 0x00024 +#define CLK_SLOW_SYS_CTRL (CLK_SLOW_OFFSET + 0x00) +#define CLK_SLOW_SYS_DIV_INT (CLK_SLOW_OFFSET + 0x04) +#define CLK_SLOW_SYS_SEL (CLK_SLOW_OFFSET + 0x0c) -#define CLK_SLOW_SYS_CTRL 0x00024 -#define CLK_SLOW_SYS_DIV_INT 0x00028 -#define CLK_SLOW_SYS_SEL 0x00030 +#define CLK_DMA_OFFSET 0x00044 +#define CLK_DMA_CTRL (CLK_DMA_OFFSET + 0x00) +#define CLK_DMA_DIV_INT (CLK_DMA_OFFSET + 0x04) +#define CLK_DMA_SEL (CLK_DMA_OFFSET + 0x0c) -#define CLK_DMA_CTRL 0x00044 -#define CLK_DMA_DIV_INT 0x00048 -#define CLK_DMA_SEL 0x00050 +#define CLK_UART_OFFSET 0x00054 +#define CLK_UART_CTRL (CLK_UART_OFFSET + 0x00) +#define CLK_UART_DIV_INT (CLK_UART_OFFSET + 0x04) +#define CLK_UART_SEL (CLK_UART_OFFSET + 0x0c) -#define CLK_UART_CTRL 0x00054 -#define CLK_UART_DIV_INT 0x00058 -#define CLK_UART_SEL 0x00060 +#define CLK_ETH_OFFSET 0x00064 +#define CLK_ETH_CTRL (CLK_ETH_OFFSET + 0x00) +#define CLK_ETH_DIV_INT (CLK_ETH_OFFSET + 0x04) +#define CLK_ETH_SEL (CLK_ETH_OFFSET + 0x0c) -#define CLK_ETH_CTRL 0x00064 -#define CLK_ETH_DIV_INT 0x00068 -#define CLK_ETH_SEL 0x00070 +#define CLK_PWM0_OFFSET 0x00074 +#define CLK_PWM0_CTRL (CLK_PWM0_OFFSET + 0x00) +#define CLK_PWM0_DIV_INT (CLK_PWM0_OFFSET + 0x04) +#define CLK_PWM0_DIV_FRAC (CLK_PWM0_OFFSET + 0x08) +#define CLK_PWM0_SEL (CLK_PWM0_OFFSET + 0x0c) -#define CLK_PWM0_CTRL 0x00074 -#define CLK_PWM0_DIV_INT 0x00078 -#define CLK_PWM0_DIV_FRAC 0x0007c -#define CLK_PWM0_SEL 0x00080 +#define CLK_PWM1_OFFSET 0x00084 +#define CLK_PWM1_CTRL (CLK_PWM1_OFFSET + 0x00) +#define CLK_PWM1_DIV_INT (CLK_PWM1_OFFSET + 0x04) +#define CLK_PWM1_DIV_FRAC (CLK_PWM1_OFFSET + 0x08) +#define CLK_PWM1_SEL (CLK_PWM1_OFFSET + 0x0c) -#define CLK_PWM1_CTRL 0x00084 -#define CLK_PWM1_DIV_INT 0x00088 -#define CLK_PWM1_DIV_FRAC 0x0008c -#define CLK_PWM1_SEL 0x00090 +#define CLK_AUDIO_IN_OFFSET 0x00094 +#define CLK_AUDIO_IN_CTRL (CLK_AUDIO_IN_OFFSET + 0x00) +#define CLK_AUDIO_IN_DIV_INT (CLK_AUDIO_IN_OFFSET + 0x04) +#define CLK_AUDIO_IN_SEL (CLK_AUDIO_IN_OFFSET + 0x0c) -#define CLK_AUDIO_IN_CTRL 0x00094 -#define CLK_AUDIO_IN_DIV_INT 0x00098 -#define CLK_AUDIO_IN_SEL 0x000a0 +#define CLK_AUDIO_OUT_OFFSET 0x000a4 +#define CLK_AUDIO_OUT_CTRL (CLK_AUDIO_OUT_OFFSET + 0x00) +#define CLK_AUDIO_OUT_DIV_INT (CLK_AUDIO_OUT_OFFSET + 0x04) +#define CLK_AUDIO_OUT_SEL (CLK_AUDIO_OUT_OFFSET + 0x0c) -#define CLK_AUDIO_OUT_CTRL 0x000a4 -#define CLK_AUDIO_OUT_DIV_INT 0x000a8 -#define CLK_AUDIO_OUT_SEL 0x000b0 +#define CLK_I2S_OFFSET 0x000b4 +#define CLK_I2S_CTRL (CLK_I2S_OFFSET + 0x00) +#define CLK_I2S_DIV_INT (CLK_I2S_OFFSET + 0x04) +#define CLK_I2S_SEL (CLK_I2S_OFFSET + 0x0c) -#define CLK_I2S_CTRL 0x000b4 -#define CLK_I2S_DIV_INT 0x000b8 -#define CLK_I2S_SEL 0x000c0 +#define CLK_MIPI0_CFG_OFFSET 0x000c4 +#define CLK_MIPI0_CFG_CTRL (CLK_MIPI0_CFG_OFFSET + 0x00) +#define CLK_MIPI0_CFG_DIV_INT (CLK_MIPI0_CFG_OFFSET + 0x04) +#define CLK_MIPI0_CFG_SEL (CLK_MIPI0_CFG_OFFSET + 0x0c) -#define CLK_MIPI0_CFG_CTRL 0x000c4 -#define CLK_MIPI0_CFG_DIV_INT 0x000c8 -#define CLK_MIPI0_CFG_SEL 0x000d0 +#define CLK_MIPI1_CFG_OFFSET 0x000d4 +#define CLK_MIPI1_CFG_CTRL (CLK_MIPI1_CFG_OFFSET + 0x00) +#define CLK_MIPI1_CFG_DIV_INT (CLK_MIPI1_CFG_OFFSET + 0x04) +#define CLK_MIPI1_CFG_SEL (CLK_MIPI1_CFG_OFFSET + 0x0c) -#define CLK_MIPI1_CFG_CTRL 0x000d4 -#define CLK_MIPI1_CFG_DIV_INT 0x000d8 -#define CLK_MIPI1_CFG_SEL 0x000e0 +#define CLK_PCIE_AUX_OFFSET 0x000e4 +#define CLK_PCIE_AUX_CTRL (CLK_PCIE_AUX_OFFSET + 0x00) +#define CLK_PCIE_AUX_DIV_INT (CLK_PCIE_AUX_OFFSET + 0x04) +#define CLK_PCIE_AUX_SEL (CLK_PCIE_AUX_OFFSET + 0x0c) -#define CLK_PCIE_AUX_CTRL 0x000e4 -#define CLK_PCIE_AUX_DIV_INT 0x000e8 -#define CLK_PCIE_AUX_SEL 0x000f0 +#define CLK_USBH0_MICROFRAME_OFFSET 0x000f4 +#define CLK_USBH0_MICROFRAME_CTRL (CLK_USBH0_MICROFRAME_OFFSET + 0x00) +#define CLK_USBH0_MICROFRAME_DIV_INT (CLK_USBH0_MICROFRAME_OFFSET + 0x04) +#define CLK_USBH0_MICROFRAME_SEL (CLK_USBH0_MICROFRAME_OFFSET + 0x0c) -#define CLK_USBH0_MICROFRAME_CTRL 0x000f4 -#define CLK_USBH0_MICROFRAME_DIV_INT 0x000f8 -#define CLK_USBH0_MICROFRAME_SEL 0x00100 +#define CLK_USBH1_MICROFRAME_OFFSET 0x00104 +#define CLK_USBH1_MICROFRAME_CTRL (CLK_USBH1_MICROFRAME_OFFSET + 0x00) +#define CLK_USBH1_MICROFRAME_DIV_INT (CLK_USBH1_MICROFRAME_OFFSET + 0x04) +#define CLK_USBH1_MICROFRAME_SEL (CLK_USBH1_MICROFRAME_OFFSET + 0x0c) -#define CLK_USBH1_MICROFRAME_CTRL 0x00104 -#define CLK_USBH1_MICROFRAME_DIV_INT 0x00108 -#define CLK_USBH1_MICROFRAME_SEL 0x00110 +#define CLK_USBH0_SUSPEND_OFFSET 0x00114 +#define CLK_USBH0_SUSPEND_CTRL (CLK_USBH0_SUSPEND_OFFSET + 0x00) +#define CLK_USBH0_SUSPEND_DIV_INT (CLK_USBH0_SUSPEND_OFFSET + 0x04) +#define CLK_USBH0_SUSPEND_SEL (CLK_USBH0_SUSPEND_OFFSET + 0x0c) -#define CLK_USBH0_SUSPEND_CTRL 0x00114 -#define CLK_USBH0_SUSPEND_DIV_INT 0x00118 -#define CLK_USBH0_SUSPEND_SEL 0x00120 +#define CLK_USBH1_SUSPEND_OFFSET 0x00124 +#define CLK_USBH1_SUSPEND_CTRL (CLK_USBH1_SUSPEND_OFFSET + 0x00) +#define CLK_USBH1_SUSPEND_DIV_INT (CLK_USBH1_SUSPEND_OFFSET + 0x04) +#define CLK_USBH1_SUSPEND_SEL (CLK_USBH1_SUSPEND_OFFSET + 0x0c) -#define CLK_USBH1_SUSPEND_CTRL 0x00124 -#define CLK_USBH1_SUSPEND_DIV_INT 0x00128 -#define CLK_USBH1_SUSPEND_SEL 0x00130 +#define CLK_ETH_TSU_OFFSET 0x00134 +#define CLK_ETH_TSU_CTRL (CLK_ETH_TSU_OFFSET + 0x00) +#define CLK_ETH_TSU_DIV_INT (CLK_ETH_TSU_OFFSET + 0x04) +#define CLK_ETH_TSU_SEL (CLK_ETH_TSU_OFFSET + 0x0c) -#define CLK_ETH_TSU_CTRL 0x00134 -#define CLK_ETH_TSU_DIV_INT 0x00138 -#define CLK_ETH_TSU_SEL 0x00140 +#define CLK_ADC_OFFSET 0x00144 +#define CLK_ADC_CTRL (CLK_ADC_OFFSET + 0x00) +#define CLK_ADC_DIV_INT (CLK_ADC_OFFSET + 0x04) +#define CLK_ADC_SEL (CLK_ADC_OFFSET + 0x0c) -#define CLK_ADC_CTRL 0x00144 -#define CLK_ADC_DIV_INT 0x00148 -#define CLK_ADC_SEL 0x00150 +#define CLK_SDIO_TIMER_OFFSET 0x00154 +#define CLK_SDIO_TIMER_CTRL (CLK_SDIO_TIMER_OFFSET + 0x00) +#define CLK_SDIO_TIMER_DIV_INT (CLK_SDIO_TIMER_OFFSET + 0x04) +#define CLK_SDIO_TIMER_SEL (CLK_SDIO_TIMER_OFFSET + 0x0c) -#define CLK_SDIO_TIMER_CTRL 0x00154 -#define CLK_SDIO_TIMER_DIV_INT 0x00158 -#define CLK_SDIO_TIMER_SEL 0x00160 +#define CLK_SDIO_ALT_SRC_OFFSET 0x00164 +#define CLK_SDIO_ALT_SRC_CTRL (CLK_SDIO_ALT_SRC_OFFSET + 0x00) +#define CLK_SDIO_ALT_SRC_DIV_INT (CLK_SDIO_ALT_SRC_OFFSET + 0x04) +#define CLK_SDIO_ALT_SRC_SEL (CLK_SDIO_ALT_SRC_OFFSET + 0x0c) -#define CLK_SDIO_ALT_SRC_CTRL 0x00164 -#define CLK_SDIO_ALT_SRC_DIV_INT 0x00168 -#define CLK_SDIO_ALT_SRC_SEL 0x00170 +#define CLK_GP0_OFFSET 0x00174 +#define CLK_GP0_CTRL (CLK_GP0_OFFSET + 0x00) +#define CLK_GP0_DIV_INT (CLK_GP0_OFFSET + 0x04) +#define CLK_GP0_DIV_FRAC (CLK_GP0_OFFSET + 0x08) +#define CLK_GP0_SEL (CLK_GP0_OFFSET + 0x0c) -#define CLK_GP0_CTRL 0x00174 -#define CLK_GP0_DIV_INT 0x00178 -#define CLK_GP0_DIV_FRAC 0x0017c -#define CLK_GP0_SEL 0x00180 +#define CLK_GP1_OFFSET 0x00184 +#define CLK_GP1_CTRL (CLK_GP1_OFFSET + 0x00) +#define CLK_GP1_DIV_INT (CLK_GP1_OFFSET + 0x04) +#define CLK_GP1_DIV_FRAC (CLK_GP1_OFFSET + 0x08) +#define CLK_GP1_SEL (CLK_GP1_OFFSET + 0x0c) -#define CLK_GP1_CTRL 0x00184 -#define CLK_GP1_DIV_INT 0x00188 -#define CLK_GP1_DIV_FRAC 0x0018c -#define CLK_GP1_SEL 0x00190 +#define CLK_GP2_OFFSET 0x00194 +#define CLK_GP2_CTRL (CLK_GP2_OFFSET + 0x00) +#define CLK_GP2_DIV_INT (CLK_GP2_OFFSET + 0x04) +#define CLK_GP2_DIV_FRAC (CLK_GP2_OFFSET + 0x08) +#define CLK_GP2_SEL (CLK_GP2_OFFSET + 0x0c) -#define CLK_GP2_CTRL 0x00194 -#define CLK_GP2_DIV_INT 0x00198 -#define CLK_GP2_DIV_FRAC 0x0019c -#define CLK_GP2_SEL 0x001a0 +#define CLK_GP3_OFFSET 0x001a4 +#define CLK_GP3_CTRL (CLK_GP3_OFFSET + 0x00) +#define CLK_GP3_DIV_INT (CLK_GP3_OFFSET + 0x04) +#define CLK_GP3_DIV_FRAC (CLK_GP3_OFFSET + 0x08) +#define CLK_GP3_SEL (CLK_GP3_OFFSET + 0x0c) -#define CLK_GP3_CTRL 0x001a4 -#define CLK_GP3_DIV_INT 0x001a8 -#define CLK_GP3_DIV_FRAC 0x001ac -#define CLK_GP3_SEL 0x001b0 +#define CLK_GP4_OFFSET 0x001b4 +#define CLK_GP4_CTRL (CLK_GP4_OFFSET + 0x00) +#define CLK_GP4_DIV_INT (CLK_GP4_OFFSET + 0x04) +#define CLK_GP4_DIV_FRAC (CLK_GP4_OFFSET + 0x08) +#define CLK_GP4_SEL (CLK_GP4_OFFSET + 0x0c) -#define CLK_GP4_CTRL 0x001b4 -#define CLK_GP4_DIV_INT 0x001b8 -#define CLK_GP4_DIV_FRAC 0x001bc -#define CLK_GP4_SEL 0x001c0 +#define CLK_GP5_OFFSET 0x001c4 +#define CLK_GP5_CTRL (CLK_GP5_OFFSET + 0x00) +#define CLK_GP5_DIV_INT (CLK_GP5_OFFSET + 0x04) +#define CLK_GP5_DIV_FRAC (CLK_GP5_OFFSET + 0x08) +#define CLK_GP5_SEL (CLK_GP5_OFFSET + 0x0c) -#define CLK_GP5_CTRL 0x001c4 -#define CLK_GP5_DIV_INT 0x001c8 -#define CLK_GP5_DIV_FRAC 0x001cc -#define CLK_GP5_SEL 0x001d0 +#define CLK_SYS_RESUS_CTRL 0x0020c -#define CLK_SYS_RESUS_CTRL 0x0020c +#define CLK_SLOW_SYS_RESUS_CTRL 0x00214 -#define CLK_SLOW_SYS_RESUS_CTRL 0x00214 +#define FC0_OFFSET 0x0021c +#define FC0_REF_KHZ (FC0_OFFSET + 0x00) +#define FC0_MIN_KHZ (FC0_OFFSET + 0x04) +#define FC0_MAX_KHZ (FC0_OFFSET + 0x08) +#define FC0_DELAY (FC0_OFFSET + 0x0c) +#define FC0_INTERVAL (FC0_OFFSET + 0x10) +#define FC0_SRC (FC0_OFFSET + 0x14) +#define FC0_STATUS (FC0_OFFSET + 0x18) +#define FC0_RESULT (FC0_OFFSET + 0x1c) +#define FC_SIZE 0x20 +#define FC_COUNT 8 +#define FC_NUM(idx, off) ((idx) * 32 + (off)) -#define FC0_REF_KHZ 0x0021c -#define FC0_MIN_KHZ 0x00220 -#define FC0_MAX_KHZ 0x00224 -#define FC0_DELAY 0x00228 -#define FC0_INTERVAL 0x0022c -#define FC0_SRC 0x00230 -#define FC0_STATUS 0x00234 -#define FC0_RESULT 0x00238 -#define FC_SIZE 0x20 -#define FC_COUNT 8 -#define FC_NUM(idx, off) ((idx) * 32 + (off)) +#define AUX_SEL 1 -#define AUX_SEL 1 +#define VIDEO_CLOCKS_OFFSET 0x4000 +#define VIDEO_CLK_VEC_CTRL (VIDEO_CLOCKS_OFFSET + 0x0000) +#define VIDEO_CLK_VEC_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0004) +#define VIDEO_CLK_VEC_SEL (VIDEO_CLOCKS_OFFSET + 0x000c) +#define VIDEO_CLK_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0010) +#define VIDEO_CLK_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0014) +#define VIDEO_CLK_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x001c) +#define VIDEO_CLK_MIPI0_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0020) +#define VIDEO_CLK_MIPI0_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0024) +#define VIDEO_CLK_MIPI0_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0028) +#define VIDEO_CLK_MIPI0_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x002c) +#define VIDEO_CLK_MIPI1_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0030) +#define VIDEO_CLK_MIPI1_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0034) +#define VIDEO_CLK_MIPI1_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0038) +#define VIDEO_CLK_MIPI1_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x003c) -#define VIDEO_CLOCKS_OFFSET 0x4000 -#define VIDEO_CLK_VEC_CTRL (VIDEO_CLOCKS_OFFSET + 0x0000) -#define VIDEO_CLK_VEC_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0004) -#define VIDEO_CLK_VEC_SEL (VIDEO_CLOCKS_OFFSET + 0x000c) -#define VIDEO_CLK_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0010) -#define VIDEO_CLK_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0014) -#define VIDEO_CLK_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x001c) -#define VIDEO_CLK_MIPI0_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0020) -#define VIDEO_CLK_MIPI0_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0024) -#define VIDEO_CLK_MIPI0_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0028) -#define VIDEO_CLK_MIPI0_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x002c) -#define VIDEO_CLK_MIPI1_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0030) -#define VIDEO_CLK_MIPI1_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0034) -#define VIDEO_CLK_MIPI1_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0038) -#define VIDEO_CLK_MIPI1_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x003c) +#define DIV_INT_8BIT_MAX GENMASK(7, 0) /* max divide for most clocks */ +#define DIV_INT_16BIT_MAX GENMASK(15, 0) /* max divide for GPx, PWM */ +#define DIV_INT_24BIT_MAX GENMASK(23, 0) /* max divide for CLK_SYS */ -#define DIV_INT_8BIT_MAX 0x000000ffu /* max divide for most clocks */ -#define DIV_INT_16BIT_MAX 0x0000ffffu /* max divide for GPx, PWM */ -#define DIV_INT_24BIT_MAX 0x00ffffffu /* max divide for CLK_SYS */ +#define FC0_STATUS_DONE BIT(4) +#define FC0_STATUS_RUNNING BIT(8) +#define FC0_RESULT_FRAC_SHIFT 5 -#define FC0_STATUS_DONE BIT(4) -#define FC0_STATUS_RUNNING BIT(8) -#define FC0_RESULT_FRAC_SHIFT 5 +#define PLL_PRIM_DIV1_MASK GENMASK(18, 16) +#define PLL_PRIM_DIV2_MASK GENMASK(14, 12) -#define PLL_PRIM_DIV1_SHIFT 16 -#define PLL_PRIM_DIV1_MASK 0x00070000 -#define PLL_PRIM_DIV2_SHIFT 12 -#define PLL_PRIM_DIV2_MASK 0x00007000 +#define PLL_SEC_DIV_MASK GENMASK(12, 8) -#define PLL_SEC_DIV_SHIFT 8 -#define PLL_SEC_DIV_WIDTH 5 -#define PLL_SEC_DIV_MASK 0x00001f00 +#define PLL_CS_LOCK BIT(31) +#define PLL_CS_REFDIV_MASK BIT(1) -#define PLL_CS_LOCK BIT(31) -#define PLL_CS_REFDIV_SHIFT 0 +#define PLL_PWR_PD BIT(0) +#define PLL_PWR_DACPD BIT(1) +#define PLL_PWR_DSMPD BIT(2) +#define PLL_PWR_POSTDIVPD BIT(3) +#define PLL_PWR_4PHASEPD BIT(4) +#define PLL_PWR_VCOPD BIT(5) +#define PLL_PWR_MASK GENMASK(5, 0) -#define PLL_PWR_PD BIT(0) -#define PLL_PWR_DACPD BIT(1) -#define PLL_PWR_DSMPD BIT(2) -#define PLL_PWR_POSTDIVPD BIT(3) -#define PLL_PWR_4PHASEPD BIT(4) -#define PLL_PWR_VCOPD BIT(5) -#define PLL_PWR_MASK 0x0000003f - -#define PLL_SEC_RST BIT(16) -#define PLL_SEC_IMPL BIT(31) +#define PLL_SEC_RST BIT(16) +#define PLL_SEC_IMPL BIT(31) /* PLL phase output for both PRI and SEC */ -#define PLL_PH_EN BIT(4) -#define PLL_PH_PHASE_SHIFT 0 +#define PLL_PH_EN BIT(4) +#define PLL_PH_PHASE_SHIFT 0 -#define RP1_PLL_PHASE_0 0 -#define RP1_PLL_PHASE_90 1 -#define RP1_PLL_PHASE_180 2 -#define RP1_PLL_PHASE_270 3 +#define RP1_PLL_PHASE_0 0 +#define RP1_PLL_PHASE_90 1 +#define RP1_PLL_PHASE_180 2 +#define RP1_PLL_PHASE_270 3 /* Clock fields for all clocks */ -#define CLK_CTRL_ENABLE BIT(11) -#define CLK_CTRL_AUXSRC_MASK 0x000003e0 -#define CLK_CTRL_AUXSRC_SHIFT 5 -#define CLK_CTRL_SRC_SHIFT 0 -#define CLK_DIV_FRAC_BITS 16 - -#define KHz 1000 -#define MHz (KHz * KHz) -#define LOCK_TIMEOUT_NS 100000000 -#define FC_TIMEOUT_NS 100000000 - -#define MAX_CLK_PARENTS 16 +#define CLK_CTRL_ENABLE BIT(11) +#define CLK_CTRL_AUXSRC_MASK GENMASK(9, 5) +#define CLK_CTRL_SRC_SHIFT 0 +#define CLK_DIV_FRAC_BITS 16 -#define MEASURE_CLOCK_RATE -const char * const fc0_ref_clk_name = "clk_slow_sys"; +#define LOCK_TIMEOUT_US 100000 +#define LOCK_POLL_DELAY_US 5 -#define ABS_DIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) -#define DIV_NEAREST(a, b) (((a) + ((b) >> 1)) / (b)) -#define DIV_U64_NEAREST(a, b) div_u64(((a) + ((b) >> 1)), (b)) - -/* - * Names of the reference clock for the pll cores. This name must match - * the DT reference clock-output-name. - */ -static const char *const ref_clock = "xosc"; +#define MAX_CLK_PARENTS 16 +#define PLL_DIV_INVALID 19 /* * Secondary PLL channel output divider table. - * Divider values range from 8 to 19. - * Invalid values default to 19 + * Divider values range from 8 to 19, where + * 19 means invalid. */ static const struct clk_div_table pll_sec_div_table[] = { - { 0x00, 19 }, - { 0x01, 19 }, - { 0x02, 19 }, - { 0x03, 19 }, - { 0x04, 19 }, - { 0x05, 19 }, - { 0x06, 19 }, - { 0x07, 19 }, - { 0x08, 8 }, - { 0x09, 9 }, + { 0x00, PLL_DIV_INVALID }, + { 0x01, PLL_DIV_INVALID }, + { 0x02, PLL_DIV_INVALID }, + { 0x03, PLL_DIV_INVALID }, + { 0x04, PLL_DIV_INVALID }, + { 0x05, PLL_DIV_INVALID }, + { 0x06, PLL_DIV_INVALID }, + { 0x07, PLL_DIV_INVALID }, + { 0x08, 8 }, + { 0x09, 9 }, { 0x0a, 10 }, { 0x0b, 11 }, { 0x0c, 12 }, @@ -288,25 +293,26 @@ static const struct clk_div_table pll_sec_div_table[] = { { 0x10, 16 }, { 0x11, 17 }, { 0x12, 18 }, - { 0x13, 19 }, - { 0x14, 19 }, - { 0x15, 19 }, - { 0x16, 19 }, - { 0x17, 19 }, - { 0x18, 19 }, - { 0x19, 19 }, - { 0x1a, 19 }, - { 0x1b, 19 }, - { 0x1c, 19 }, - { 0x1d, 19 }, - { 0x1e, 19 }, - { 0x1f, 19 }, + { 0x13, PLL_DIV_INVALID }, + { 0x14, PLL_DIV_INVALID }, + { 0x15, PLL_DIV_INVALID }, + { 0x16, PLL_DIV_INVALID }, + { 0x17, PLL_DIV_INVALID }, + { 0x18, PLL_DIV_INVALID }, + { 0x19, PLL_DIV_INVALID }, + { 0x1a, PLL_DIV_INVALID }, + { 0x1b, PLL_DIV_INVALID }, + { 0x1c, PLL_DIV_INVALID }, + { 0x1d, PLL_DIV_INVALID }, + { 0x1e, PLL_DIV_INVALID }, + { 0x1f, PLL_DIV_INVALID }, { 0 } }; struct rp1_clockman { struct device *dev; void __iomem *regs; + struct regmap *regmap; spinlock_t regs_lock; /* spinlock for all clocks */ /* Must be last */ @@ -314,47 +320,33 @@ struct rp1_clockman { }; struct rp1_pll_core_data { - const char *name; u32 cs_reg; u32 pwr_reg; u32 fbdiv_int_reg; u32 fbdiv_frac_reg; - unsigned long flags; u32 fc0_src; }; struct rp1_pll_data { - const char *name; - const char *source_pll; u32 ctrl_reg; - unsigned long flags; u32 fc0_src; }; struct rp1_pll_ph_data { - const char *name; - const char *source_pll; unsigned int phase; unsigned int fixed_divider; u32 ph_reg; - unsigned long flags; u32 fc0_src; }; struct rp1_pll_divider_data { - const char *name; - const char *source_pll; u32 sec_reg; - unsigned long flags; u32 fc0_src; }; struct rp1_clock_data { - const char *name; - const char *const parents[MAX_CLK_PARENTS]; int num_std_parents; int num_aux_parents; - unsigned long flags; u32 oe_mask; u32 clk_src_mask; u32 ctrl_reg; @@ -366,94 +358,40 @@ struct rp1_clock_data { u32 fc0_src; }; -struct rp1_pll_core { +struct rp1_clk_desc { + struct clk_hw *(*clk_register)(struct rp1_clockman *clockman, + struct rp1_clk_desc *desc); + const void *data; struct clk_hw hw; struct rp1_clockman *clockman; - const struct rp1_pll_core_data *data; unsigned long cached_rate; -}; - -struct rp1_pll { - struct clk_hw hw; struct clk_divider div; }; -static inline -void clockman_write(struct rp1_clockman *clockman, u32 reg, u32 val) -{ - writel(val, clockman->regs + reg); -} +static struct rp1_clk_desc *clk_audio_core; +static struct rp1_clk_desc *clk_audio; +static struct rp1_clk_desc *clk_i2s; +static struct clk_hw *clk_xosc; -static inline u32 clockman_read(struct rp1_clockman *clockman, u32 reg) +static inline void clockman_write(struct rp1_clockman *clockman, u32 reg, + u32 val) { - return readl(clockman->regs + reg); + regmap_write(clockman->regmap, reg, val); } -#ifdef MEASURE_CLOCK_RATE -static unsigned long clockman_measure_clock(struct rp1_clockman *clockman, - const char *clk_name, - unsigned int fc0_src) +static inline u32 clockman_read(struct rp1_clockman *clockman, u32 reg) { - struct clk *ref_clk = __clk_lookup(fc0_ref_clk_name); - unsigned long result; - ktime_t timeout; - unsigned int fc_idx, fc_offset, fc_src; - - fc_idx = fc0_src / 32; - fc_src = fc0_src % 32; - - /* fc_src == 0 is invalid. */ - if (!fc_src || fc_idx >= FC_COUNT) - return 0; - - fc_offset = fc_idx * FC_SIZE; - - /* Ensure the frequency counter is idle. */ - timeout = ktime_add_ns(ktime_get(), FC_TIMEOUT_NS); - while (clockman_read(clockman, fc_offset + FC0_STATUS) & FC0_STATUS_RUNNING) { - if (ktime_after(ktime_get(), timeout)) { - dev_err(clockman->dev, "%s: FC0 busy timeout\n", - clk_name); - return 0; - } - cpu_relax(); - } - - spin_lock(&clockman->regs_lock); - clockman_write(clockman, fc_offset + FC0_REF_KHZ, - clk_get_rate(ref_clk) / KHz); - clockman_write(clockman, fc_offset + FC0_MIN_KHZ, 0); - clockman_write(clockman, fc_offset + FC0_MAX_KHZ, 0x1ffffff); - clockman_write(clockman, fc_offset + FC0_INTERVAL, 8); - clockman_write(clockman, fc_offset + FC0_DELAY, 7); - clockman_write(clockman, fc_offset + FC0_SRC, fc_src); - spin_unlock(&clockman->regs_lock); + u32 val; - /* Ensure the frequency counter is idle. */ - timeout = ktime_add_ns(ktime_get(), FC_TIMEOUT_NS); - while (!(clockman_read(clockman, fc_offset + FC0_STATUS) & FC0_STATUS_DONE)) { - if (ktime_after(ktime_get(), timeout)) { - dev_err(clockman->dev, "%s: FC0 wait timeout\n", - clk_name); - return 0; - } - cpu_relax(); - } - - result = clockman_read(clockman, fc_offset + FC0_RESULT); - - /* Disable FC0 */ - spin_lock(&clockman->regs_lock); - clockman_write(clockman, fc_offset + FC0_SRC, 0); - spin_unlock(&clockman->regs_lock); + regmap_read(clockman->regmap, reg, &val); - return result; + return val; } -#endif static int rp1_pll_core_is_on(struct clk_hw *hw) { - struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); + struct rp1_clk_desc *pll_core = + container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; u32 pwr = clockman_read(clockman, data->pwr_reg); @@ -463,11 +401,12 @@ static int rp1_pll_core_is_on(struct clk_hw *hw) static int rp1_pll_core_on(struct clk_hw *hw) { - struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); + struct rp1_clk_desc *pll_core = + container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; - u32 fbdiv_frac; - ktime_t timeout; + u32 fbdiv_frac, val; + int ret; spin_lock(&clockman->regs_lock); @@ -476,7 +415,7 @@ static int rp1_pll_core_on(struct clk_hw *hw) clockman_write(clockman, data->pwr_reg, PLL_PWR_MASK); clockman_write(clockman, data->fbdiv_int_reg, 20); clockman_write(clockman, data->fbdiv_frac_reg, 0); - clockman_write(clockman, data->cs_reg, 1 << PLL_CS_REFDIV_SHIFT); + clockman_write(clockman, data->cs_reg, PLL_CS_REFDIV_MASK); } /* Come out of reset. */ @@ -485,22 +424,20 @@ static int rp1_pll_core_on(struct clk_hw *hw) spin_unlock(&clockman->regs_lock); /* Wait for the PLL to lock. */ - timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS); - while (!(clockman_read(clockman, data->cs_reg) & PLL_CS_LOCK)) { - if (ktime_after(ktime_get(), timeout)) { - dev_err(clockman->dev, "%s: can't lock PLL\n", - clk_hw_get_name(hw)); - return -ETIMEDOUT; - } - cpu_relax(); - } + ret = regmap_read_poll_timeout(clockman->regmap, data->cs_reg, val, + val & PLL_CS_LOCK, LOCK_POLL_DELAY_US, + LOCK_TIMEOUT_US); + if (ret) + dev_err(clockman->dev, "%s: can't lock PLL\n", + clk_hw_get_name(hw)); - return 0; + return ret; } static void rp1_pll_core_off(struct clk_hw *hw) { - struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); + struct rp1_clk_desc *pll_core = + container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; @@ -514,13 +451,14 @@ static inline unsigned long get_pll_core_divider(struct clk_hw *hw, unsigned long parent_rate, u32 *div_int, u32 *div_frac) { - unsigned long calc_rate; u32 fbdiv_int, fbdiv_frac; + unsigned long calc_rate; + u64 shifted_fbdiv_int; u64 div_fp64; /* 32.32 fixed point fraction. */ /* Factor of reference clock to VCO frequency. */ div_fp64 = (u64)(rate) << 32; - div_fp64 = DIV_U64_NEAREST(div_fp64, parent_rate); + div_fp64 = DIV_ROUND_CLOSEST_ULL(div_fp64, parent_rate); /* Round the fractional component at 24 bits. */ div_fp64 += 1 << (32 - 24 - 1); @@ -528,8 +466,10 @@ static inline unsigned long get_pll_core_divider(struct clk_hw *hw, fbdiv_int = div_fp64 >> 32; fbdiv_frac = (div_fp64 >> (32 - 24)) & 0xffffff; - calc_rate = - ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; + shifted_fbdiv_int = (u64)fbdiv_int << 24; + calc_rate = (u64)parent_rate * (shifted_fbdiv_int + fbdiv_frac); + calc_rate += BIT(23); + calc_rate >>= 24; *div_int = fbdiv_int; *div_frac = fbdiv_frac; @@ -537,25 +477,22 @@ static inline unsigned long get_pll_core_divider(struct clk_hw *hw, return calc_rate; } -static int rp1_pll_core_set_rate(struct clk_hw *hw, - unsigned long rate, unsigned long parent_rate) +static int rp1_pll_core_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { - struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); + struct rp1_clk_desc *pll_core = + container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; u32 fbdiv_int, fbdiv_frac; - // todo: is this needed?? - //rp1_pll_off(hw); - /* Disable dividers to start with. */ spin_lock(&clockman->regs_lock); clockman_write(clockman, data->fbdiv_int_reg, 0); clockman_write(clockman, data->fbdiv_frac_reg, 0); spin_unlock(&clockman->regs_lock); - get_pll_core_divider(hw, rate, parent_rate, - &fbdiv_int, &fbdiv_frac); + get_pll_core_divider(hw, rate, parent_rate, &fbdiv_int, &fbdiv_frac); spin_lock(&clockman->regs_lock); clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD); @@ -564,13 +501,14 @@ static int rp1_pll_core_set_rate(struct clk_hw *hw, spin_unlock(&clockman->regs_lock); /* Check that reference frequency is no greater than VCO / 16. */ - BUG_ON(parent_rate > (rate / 16)); + if (WARN_ON_ONCE(parent_rate > (rate / 16))) + return -ERANGE; spin_lock(&clockman->regs_lock); /* Don't need to divide ref unless parent_rate > (output freq / 16) */ clockman_write(clockman, data->cs_reg, clockman_read(clockman, data->cs_reg) | - (1 << PLL_CS_REFDIV_SHIFT)); + PLL_CS_REFDIV_MASK); spin_unlock(&clockman->regs_lock); return 0; @@ -579,16 +517,21 @@ static int rp1_pll_core_set_rate(struct clk_hw *hw, static unsigned long rp1_pll_core_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); + struct rp1_clk_desc *pll_core = + container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; u32 fbdiv_int, fbdiv_frac; unsigned long calc_rate; + u64 shifted_fbdiv_int; fbdiv_int = clockman_read(clockman, data->fbdiv_int_reg); fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg); - calc_rate = - ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; + + shifted_fbdiv_int = (u64)fbdiv_int << 24; + calc_rate = (u64)parent_rate * (shifted_fbdiv_int + fbdiv_frac); + calc_rate += BIT(23); + calc_rate >>= 24; return calc_rate; } @@ -597,10 +540,11 @@ static int rp1_pll_core_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { u32 fbdiv_int, fbdiv_frac; - long calc_rate; - return get_pll_core_divider(hw, rate, *parent_rate, - &fbdiv_int, &fbdiv_frac); + req->rate = get_pll_core_divider(hw, req->rate, req->best_parent_rate, + &fbdiv_int, &fbdiv_frac); + + return 0; } static void get_pll_prim_dividers(unsigned long rate, unsigned long parent_rate, @@ -608,14 +552,14 @@ static void get_pll_prim_dividers(unsigned long rate, unsigned long parent_rate, { unsigned int div1, div2; unsigned int best_div1 = 7, best_div2 = 7; - unsigned long best_rate_diff = - ABS_DIFF(DIV_ROUND_CLOSEST(parent_rate, best_div1 * best_div2), rate); - long rate_diff, calc_rate; + unsigned long best_rate_diff = abs_diff( + DIV_ROUND_CLOSEST(parent_rate, best_div1 * best_div2), rate); + unsigned long rate_diff, calc_rate; for (div1 = 1; div1 <= 7; div1++) { for (div2 = 1; div2 <= div1; div2++) { calc_rate = DIV_ROUND_CLOSEST(parent_rate, div1 * div2); - rate_diff = ABS_DIFF(calc_rate, rate); + rate_diff = abs_diff(calc_rate, rate); if (calc_rate == rate) { best_div1 = div1; @@ -634,46 +578,44 @@ done: *divider2 = best_div2; } -static int rp1_pll_set_rate(struct clk_hw *hw, - unsigned long rate, unsigned long parent_rate) +static int rp1_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { - struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); + struct rp1_clk_desc *pll = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll->clockman; const struct rp1_pll_data *data = pll->data; + u32 prim, prim_div1, prim_div2; get_pll_prim_dividers(rate, parent_rate, &prim_div1, &prim_div2); spin_lock(&clockman->regs_lock); prim = clockman_read(clockman, data->ctrl_reg); - prim = set_register_field(prim, prim_div1, PLL_PRIM_DIV1_MASK, - PLL_PRIM_DIV1_SHIFT); - prim = set_register_field(prim, prim_div2, PLL_PRIM_DIV2_MASK, - PLL_PRIM_DIV2_SHIFT); + prim &= ~PLL_PRIM_DIV1_MASK; + prim |= FIELD_PREP(PLL_PRIM_DIV1_MASK, prim_div1); + prim &= ~PLL_PRIM_DIV2_MASK; + prim |= FIELD_PREP(PLL_PRIM_DIV2_MASK, prim_div2); clockman_write(clockman, data->ctrl_reg, prim); spin_unlock(&clockman->regs_lock); -#ifdef MEASURE_CLOCK_RATE - clockman_measure_clock(clockman, data->name, data->fc0_src); -#endif return 0; } static unsigned long rp1_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); + struct rp1_clk_desc *pll = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll->clockman; const struct rp1_pll_data *data = pll->data; u32 prim, prim_div1, prim_div2; prim = clockman_read(clockman, data->ctrl_reg); - prim_div1 = (prim & PLL_PRIM_DIV1_MASK) >> PLL_PRIM_DIV1_SHIFT; - prim_div2 = (prim & PLL_PRIM_DIV2_MASK) >> PLL_PRIM_DIV2_SHIFT; + prim_div1 = FIELD_GET(PLL_PRIM_DIV1_MASK, prim); + prim_div2 = FIELD_GET(PLL_PRIM_DIV2_MASK, prim); if (!prim_div1 || !prim_div2) { dev_err(clockman->dev, "%s: (%s) zero divider value\n", - __func__, data->name); + __func__, clk_hw_get_name(hw)); return 0; } @@ -683,50 +625,35 @@ static unsigned long rp1_pll_recalc_rate(struct clk_hw *hw, static int rp1_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { + struct clk_hw *clk_audio_hw = &clk_audio->hw; u32 div1, div2; - get_pll_prim_dividers(rate, *parent_rate, &div1, &div2); + if (hw == clk_audio_hw && clk_audio->cached_rate == req->rate) + req->best_parent_rate = clk_audio_core->cached_rate; + + get_pll_prim_dividers(req->rate, req->best_parent_rate, &div1, &div2); req->rate = DIV_ROUND_CLOSEST(req->best_parent_rate, div1 * div2); return 0; } -static void rp1_pll_debug_init(struct clk_hw *hw, - struct dentry *dentry) -{ - struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); - struct rp1_clockman *clockman = pll->clockman; - const struct rp1_pll_data *data = pll->data; - struct debugfs_reg32 *regs; - - regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); - if (!regs) - return; - - regs[0].name = "prim"; - regs[0].offset = data->ctrl_reg; - - rp1_debugfs_regset(clockman, 0, regs, 1, dentry); -} - static int rp1_pll_ph_is_on(struct clk_hw *hw) { - struct rp1_pll_ph *pll = container_of(hw, struct rp1_pll_ph, hw); - struct rp1_clockman *clockman = pll->clockman; - const struct rp1_pll_ph_data *data = pll->data; + struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clockman *clockman = pll_ph->clockman; + const struct rp1_pll_ph_data *data = pll_ph->data; return !!(clockman_read(clockman, data->ph_reg) & PLL_PH_EN); } static int rp1_pll_ph_on(struct clk_hw *hw) { - struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); + struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll_ph->clockman; const struct rp1_pll_ph_data *data = pll_ph->data; u32 ph_reg; - /* todo: ensure pri/sec is enabled! */ spin_lock(&clockman->regs_lock); ph_reg = clockman_read(clockman, data->ph_reg); ph_reg |= data->phase << PLL_PH_PHASE_SHIFT; @@ -734,15 +661,12 @@ static int rp1_pll_ph_on(struct clk_hw *hw) clockman_write(clockman, data->ph_reg, ph_reg); spin_unlock(&clockman->regs_lock); -#ifdef MEASURE_CLOCK_RATE - clockman_measure_clock(clockman, data->name, data->fc0_src); -#endif return 0; } static void rp1_pll_ph_off(struct clk_hw *hw) { - struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); + struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = pll_ph->clockman; const struct rp1_pll_ph_data *data = pll_ph->data; @@ -752,28 +676,10 @@ static void rp1_pll_ph_off(struct clk_hw *hw) spin_unlock(&clockman->regs_lock); } -static int rp1_pll_ph_set_rate(struct clk_hw *hw, - unsigned long rate, unsigned long parent_rate) -{ - struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); - const struct rp1_pll_ph_data *data = pll_ph->data; - struct rp1_clockman *clockman = pll_ph->clockman; - - /* Nothing really to do here! */ - WARN_ON(data->fixed_divider != 1 && data->fixed_divider != 2); - WARN_ON(rate != parent_rate / data->fixed_divider); - -#ifdef MEASURE_CLOCK_RATE - if (rp1_pll_ph_is_on(hw)) - clockman_measure_clock(clockman, data->name, data->fc0_src); -#endif - return 0; -} - static unsigned long rp1_pll_ph_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); + struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); const struct rp1_pll_ph_data *data = pll_ph->data; return parent_rate / data->fixed_divider; @@ -782,7 +688,7 @@ static unsigned long rp1_pll_ph_recalc_rate(struct clk_hw *hw, static int rp1_pll_ph_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); + struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); const struct rp1_pll_ph_data *data = pll_ph->data; req->rate = req->best_parent_rate / data->fixed_divider; @@ -790,27 +696,10 @@ static int rp1_pll_ph_determine_rate(struct clk_hw *hw, return 0; } -static void rp1_pll_ph_debug_init(struct clk_hw *hw, - struct dentry *dentry) -{ - struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); - const struct rp1_pll_ph_data *data = pll_ph->data; - struct rp1_clockman *clockman = pll_ph->clockman; - struct debugfs_reg32 *regs; - - regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); - if (!regs) - return; - - regs[0].name = "ph_reg"; - regs[0].offset = data->ph_reg; - - rp1_debugfs_regset(clockman, 0, regs, 1, dentry); -} - static int rp1_pll_divider_is_on(struct clk_hw *hw) { - struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); + struct rp1_clk_desc *divider = + container_of(hw, struct rp1_clk_desc, div.hw); struct rp1_clockman *clockman = divider->clockman; const struct rp1_pll_data *data = divider->data; @@ -819,7 +708,8 @@ static int rp1_pll_divider_is_on(struct clk_hw *hw) static int rp1_pll_divider_on(struct clk_hw *hw) { - struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); + struct rp1_clk_desc *divider = + container_of(hw, struct rp1_clk_desc, div.hw); struct rp1_clockman *clockman = divider->clockman; const struct rp1_pll_data *data = divider->data; @@ -830,15 +720,13 @@ static int rp1_pll_divider_on(struct clk_hw *hw) clockman_read(clockman, data->ctrl_reg) & ~PLL_SEC_RST); spin_unlock(&clockman->regs_lock); -#ifdef MEASURE_CLOCK_RATE - clockman_measure_clock(clockman, data->name, data->fc0_src); -#endif return 0; } static void rp1_pll_divider_off(struct clk_hw *hw) { - struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); + struct rp1_clk_desc *divider = + container_of(hw, struct rp1_clk_desc, div.hw); struct rp1_clockman *clockman = divider->clockman; const struct rp1_pll_data *data = divider->data; @@ -848,11 +736,11 @@ static void rp1_pll_divider_off(struct clk_hw *hw) spin_unlock(&clockman->regs_lock); } -static int rp1_pll_divider_set_rate(struct clk_hw *hw, - unsigned long rate, +static int rp1_pll_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); + struct rp1_clk_desc *divider = + container_of(hw, struct rp1_clk_desc, div.hw); struct rp1_clockman *clockman = divider->clockman; const struct rp1_pll_data *data = divider->data; u32 div, sec; @@ -862,21 +750,20 @@ static int rp1_pll_divider_set_rate(struct clk_hw *hw, spin_lock(&clockman->regs_lock); sec = clockman_read(clockman, data->ctrl_reg); - sec = set_register_field(sec, div, PLL_SEC_DIV_MASK, PLL_SEC_DIV_SHIFT); + sec &= ~PLL_SEC_DIV_MASK; + sec |= FIELD_PREP(PLL_SEC_DIV_MASK, div); /* Must keep the divider in reset to change the value. */ sec |= PLL_SEC_RST; clockman_write(clockman, data->ctrl_reg, sec); - // todo: must sleep 10 pll vco cycles + /* must sleep 10 pll vco cycles */ + ndelay(div64_ul(10ULL * div * NSEC_PER_SEC, parent_rate)); + sec &= ~PLL_SEC_RST; clockman_write(clockman, data->ctrl_reg, sec); spin_unlock(&clockman->regs_lock); -#ifdef MEASURE_CLOCK_RATE - if (rp1_pll_divider_is_on(hw)) - clockman_measure_clock(clockman, data->name, data->fc0_src); -#endif return 0; } @@ -894,26 +781,9 @@ static int rp1_pll_divider_determine_rate(struct clk_hw *hw, return 0; } -static void rp1_pll_divider_debug_init(struct clk_hw *hw, struct dentry *dentry) -{ - struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); - struct rp1_clockman *clockman = divider->clockman; - const struct rp1_pll_data *data = divider->data; - struct debugfs_reg32 *regs; - - regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); - if (!regs) - return; - - regs[0].name = "sec"; - regs[0].offset = data->ctrl_reg; - - rp1_debugfs_regset(clockman, 0, regs, 1, dentry); -} - static int rp1_clock_is_on(struct clk_hw *hw) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; @@ -923,17 +793,17 @@ static int rp1_clock_is_on(struct clk_hw *hw) static unsigned long rp1_clock_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; u64 calc_rate; u64 div; - u32 frac; div = clockman_read(clockman, data->div_int_reg); frac = (data->div_frac_reg != 0) ? - clockman_read(clockman, data->div_frac_reg) : 0; + clockman_read(clockman, data->div_frac_reg) : + 0; /* If the integer portion of the divider is 0, treat it as 2^16 */ if (!div) @@ -949,38 +819,39 @@ static unsigned long rp1_clock_recalc_rate(struct clk_hw *hw, static int rp1_clock_on(struct clk_hw *hw) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; spin_lock(&clockman->regs_lock); clockman_write(clockman, data->ctrl_reg, - clockman_read(clockman, data->ctrl_reg) | CLK_CTRL_ENABLE); + clockman_read(clockman, data->ctrl_reg) | + CLK_CTRL_ENABLE); /* If this is a GPCLK, turn on the output-enable */ if (data->oe_mask) clockman_write(clockman, GPCLK_OE_CTRL, - clockman_read(clockman, GPCLK_OE_CTRL) | data->oe_mask); + clockman_read(clockman, GPCLK_OE_CTRL) | + data->oe_mask); spin_unlock(&clockman->regs_lock); -#ifdef MEASURE_CLOCK_RATE - clockman_measure_clock(clockman, data->name, data->fc0_src); -#endif return 0; } static void rp1_clock_off(struct clk_hw *hw) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; spin_lock(&clockman->regs_lock); clockman_write(clockman, data->ctrl_reg, - clockman_read(clockman, data->ctrl_reg) & ~CLK_CTRL_ENABLE); + clockman_read(clockman, data->ctrl_reg) & + ~CLK_CTRL_ENABLE); /* If this is a GPCLK, turn off the output-enable */ if (data->oe_mask) clockman_write(clockman, GPCLK_OE_CTRL, - clockman_read(clockman, GPCLK_OE_CTRL) & ~data->oe_mask); + clockman_read(clockman, GPCLK_OE_CTRL) & + ~data->oe_mask); spin_unlock(&clockman->regs_lock); } @@ -1002,14 +873,13 @@ static u32 rp1_clock_choose_div(unsigned long rate, unsigned long parent_rate, */ if (data->div_frac_reg) { div = (u64)parent_rate << CLK_DIV_FRAC_BITS; - div = DIV_U64_NEAREST(div, rate); + div = DIV_ROUND_CLOSEST_ULL(div, rate); } else { - div = DIV_U64_NEAREST(parent_rate, rate); + div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate); div <<= CLK_DIV_FRAC_BITS; } - div = clamp(div, - 1ull << CLK_DIV_FRAC_BITS, + div = clamp(div, 1ull << CLK_DIV_FRAC_BITS, (u64)data->div_int_max << CLK_DIV_FRAC_BITS); return div; @@ -1017,7 +887,7 @@ static u32 rp1_clock_choose_div(unsigned long rate, unsigned long parent_rate, static u8 rp1_clock_get_parent(struct clk_hw *hw) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; u32 sel, ctrl; @@ -1043,7 +913,7 @@ static u8 rp1_clock_get_parent(struct clk_hw *hw) * the AUXSRC register field. */ ctrl = clockman_read(clockman, data->ctrl_reg); - parent = (ctrl & CLK_CTRL_AUXSRC_MASK) >> CLK_CTRL_AUXSRC_SHIFT; + parent = FIELD_GET(CLK_CTRL_AUXSRC_MASK, ctrl); parent += data->num_std_parents; } @@ -1052,7 +922,7 @@ static u8 rp1_clock_get_parent(struct clk_hw *hw) static int rp1_clock_set_parent(struct clk_hw *hw, u8 index) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; u32 ctrl, sel; @@ -1062,63 +932,53 @@ static int rp1_clock_set_parent(struct clk_hw *hw, u8 index) if (index >= data->num_std_parents) { /* This is an aux source request */ - if (index >= data->num_std_parents + data->num_aux_parents) + if (index >= data->num_std_parents + data->num_aux_parents) { + spin_unlock(&clockman->regs_lock); return -EINVAL; + } /* Select parent from aux list */ - ctrl = set_register_field(ctrl, index - data->num_std_parents, - CLK_CTRL_AUXSRC_MASK, - CLK_CTRL_AUXSRC_SHIFT); + ctrl &= ~CLK_CTRL_AUXSRC_MASK; + ctrl |= FIELD_PREP(CLK_CTRL_AUXSRC_MASK, + index - data->num_std_parents); /* Set src to aux list */ - ctrl = set_register_field(ctrl, AUX_SEL, data->clk_src_mask, - CLK_CTRL_SRC_SHIFT); + ctrl &= ~data->clk_src_mask; + ctrl |= (AUX_SEL << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask; } else { - ctrl = set_register_field(ctrl, index, data->clk_src_mask, - CLK_CTRL_SRC_SHIFT); + ctrl &= ~data->clk_src_mask; + ctrl |= (index << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask; } clockman_write(clockman, data->ctrl_reg, ctrl); spin_unlock(&clockman->regs_lock); sel = rp1_clock_get_parent(hw); - WARN(sel != index, "(%s): Parent index req %u returned back %u\n", - data->name, index, sel); + if (sel != index) + return -EINVAL; return 0; } -static int rp1_clock_set_rate_and_parent(struct clk_hw *hw, - unsigned long rate, - unsigned long parent_rate, - u8 parent) +static int rp1_clock_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate, u8 parent) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; u32 div = rp1_clock_choose_div(rate, parent_rate, data); - WARN(rate > 4000000000ll, "rate is -ve (%d)\n", (int)rate); - - if (WARN(!div, - "clk divider calculated as 0! (%s, rate %ld, parent rate %ld)\n", - data->name, rate, parent_rate)) - div = 1 << CLK_DIV_FRAC_BITS; - spin_lock(&clockman->regs_lock); clockman_write(clockman, data->div_int_reg, div >> CLK_DIV_FRAC_BITS); if (data->div_frac_reg) - clockman_write(clockman, data->div_frac_reg, div << (32 - CLK_DIV_FRAC_BITS)); + clockman_write(clockman, data->div_frac_reg, + div << (32 - CLK_DIV_FRAC_BITS)); spin_unlock(&clockman->regs_lock); if (parent != 0xff) - rp1_clock_set_parent(hw, parent); + return rp1_clock_set_parent(hw, parent); -#ifdef MEASURE_CLOCK_RATE - if (rp1_clock_is_on(hw)) - clockman_measure_clock(clockman, data->name, data->fc0_src); -#endif return 0; } @@ -1128,23 +988,99 @@ static int rp1_clock_set_rate(struct clk_hw *hw, unsigned long rate, return rp1_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff); } -static void rp1_clock_choose_div_and_prate(struct clk_hw *hw, - int parent_idx, +static unsigned long calc_core_pll_rate(struct clk_hw *pll_hw, + unsigned long target_rate, + int *pdiv_prim, int *pdiv_clk) +{ + static const int prim_divs[] = { + 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, + 16, 18, 20, 21, 24, 25, 28, 30, 35, 36, 42, 49, + }; + const unsigned long xosc_rate = clk_hw_get_rate(clk_xosc); + const unsigned long core_min = xosc_rate * 16; + const unsigned long core_max = 2400000000; + int best_div_prim = 1, best_div_clk = 1; + unsigned long best_rate = core_max + 1; + unsigned long core_rate = 0; + int div_int, div_frac; + u64 div; + int i; + + /* Given the target rate, choose a set of divisors/multipliers */ + for (i = 0; i < ARRAY_SIZE(prim_divs); i++) { + int div_prim = prim_divs[i]; + int div_clk; + + for (div_clk = 1; div_clk <= 256; div_clk++) { + core_rate = target_rate * div_clk * div_prim; + if (core_rate >= core_min) { + if (core_rate < best_rate) { + best_rate = core_rate; + best_div_prim = div_prim; + best_div_clk = div_clk; + } + break; + } + } + } + + if (best_rate < core_max) { + div = ((best_rate << 24) + xosc_rate / 2) / xosc_rate; + div_int = div >> 24; + div_frac = div % (1 << 24); + core_rate = (xosc_rate * ((div_int << 24) + div_frac) + + (1 << 23)) >> + 24; + } else { + core_rate = 0; + } + + if (pdiv_prim) + *pdiv_prim = best_div_prim; + if (pdiv_clk) + *pdiv_clk = best_div_clk; + + return core_rate; +} + +static void rp1_clock_choose_div_and_prate(struct clk_hw *hw, int parent_idx, unsigned long rate, unsigned long *prate, unsigned long *calc_rate) { - struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); const struct rp1_clock_data *data = clock->data; struct clk_hw *clk_audio_hw = &clk_audio->hw; struct clk_hw *clk_i2s_hw = &clk_i2s->hw; struct clk_hw *parent; u32 div; u64 tmp; - int i; parent = clk_hw_get_parent_by_index(hw, parent_idx); + if (hw == clk_i2s_hw && clk_i2s->cached_rate == rate && + parent == clk_audio_hw) { + *prate = clk_audio->cached_rate; + *calc_rate = rate; + return; + } + + if (hw == clk_i2s_hw && parent == clk_audio_hw) { + unsigned long core_rate, audio_rate, i2s_rate; + int div_prim, div_clk; + + core_rate = + calc_core_pll_rate(parent, rate, &div_prim, &div_clk); + audio_rate = DIV_ROUND_CLOSEST(core_rate, div_prim); + i2s_rate = DIV_ROUND_CLOSEST(audio_rate, div_clk); + clk_audio_core->cached_rate = core_rate; + clk_audio->cached_rate = audio_rate; + clk_i2s->cached_rate = i2s_rate; + *prate = audio_rate; + *calc_rate = i2s_rate; + return; + } + *prate = clk_hw_get_rate(parent); div = rp1_clock_choose_div(rate, *prate, data); @@ -1156,14 +1092,13 @@ static void rp1_clock_choose_div_and_prate(struct clk_hw *hw, /* Recalculate to account for rounding errors */ tmp = (u64)*prate << CLK_DIV_FRAC_BITS; tmp = div_u64(tmp, div); + /* * Prevent overclocks - if all parent choices result in * a downstream clock in excess of the maximum, then the - * call to set the clock will fail. But due to round-to- - * nearest in the PLL core (which has 24 fractional bits), - * it's expedient to tolerate a tiny error (1Hz/33MHz). + * call to set the clock will fail. */ - if (tmp > clock->data->max_freq + (clock->data->max_freq >> 25)) + if (tmp > data->max_freq) *calc_rate = 0; else *calc_rate = tmp; @@ -1209,11 +1144,11 @@ static int rp1_clock_determine_rate(struct clk_hw *hw, rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate, &calc_rate); - if (ABS_DIFF(calc_rate, req->rate) < best_rate_diff) { + if (abs_diff(calc_rate, req->rate) < best_rate_diff) { best_parent = parent; best_prate = prate; best_rate = calc_rate; - best_rate_diff = ABS_DIFF(calc_rate, req->rate); + best_rate_diff = abs_diff(calc_rate, req->rate); if (best_rate_diff == 0) break; @@ -1230,28 +1165,55 @@ static int rp1_clock_determine_rate(struct clk_hw *hw, return 0; } +static int rp1_varsrc_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + + /* + * "varsrc" exists purely to let clock dividers know the frequency + * of an externally-managed clock source (such as MIPI DSI byte-clock) + * which may change at run-time as a side-effect of some other driver. + */ + clock->cached_rate = rate; + return 0; +} + +static unsigned long rp1_varsrc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + + return clock->cached_rate; +} + +static int rp1_varsrc_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + return 0; +} + static const struct clk_ops rp1_pll_core_ops = { .is_prepared = rp1_pll_core_is_on, .prepare = rp1_pll_core_on, .unprepare = rp1_pll_core_off, .set_rate = rp1_pll_core_set_rate, .recalc_rate = rp1_pll_core_recalc_rate, - .round_rate = rp1_pll_core_round_rate, + .determine_rate = rp1_pll_core_determine_rate, }; static const struct clk_ops rp1_pll_ops = { .set_rate = rp1_pll_set_rate, .recalc_rate = rp1_pll_recalc_rate, - .round_rate = rp1_pll_round_rate, + .determine_rate = rp1_pll_determine_rate, }; static const struct clk_ops rp1_pll_ph_ops = { .is_prepared = rp1_pll_ph_is_on, .prepare = rp1_pll_ph_on, .unprepare = rp1_pll_ph_off, - .set_rate = rp1_pll_ph_set_rate, .recalc_rate = rp1_pll_ph_recalc_rate, - .round_rate = rp1_pll_ph_round_rate, + .determine_rate = rp1_pll_ph_determine_rate, }; static const struct clk_ops rp1_pll_divider_ops = { @@ -1260,7 +1222,7 @@ static const struct clk_ops rp1_pll_divider_ops = { .unprepare = rp1_pll_divider_off, .set_rate = rp1_pll_divider_set_rate, .recalc_rate = rp1_pll_divider_recalc_rate, - .round_rate = rp1_pll_divider_round_rate, + .determine_rate = rp1_pll_divider_determine_rate, }; static const struct clk_ops rp1_clk_ops = { @@ -1273,367 +1235,786 @@ static const struct clk_ops rp1_clk_ops = { .set_rate_and_parent = rp1_clock_set_rate_and_parent, .set_rate = rp1_clock_set_rate, .determine_rate = rp1_clock_determine_rate, - .debug_init = rp1_clk_debug_init, +}; + +static const struct clk_ops rp1_varsrc_ops = { + .set_rate = rp1_varsrc_set_rate, + .recalc_rate = rp1_varsrc_recalc_rate, + .determine_rate = rp1_varsrc_determine_rate, }; static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman, - const void *data) + struct rp1_clk_desc *desc) { - const struct rp1_pll_data *pll_data = data; - struct rp1_pll *pll; - struct clk_init_data init; int ret; - memset(&init, 0, sizeof(init)); + desc->clockman = clockman; - init.parent_names = &pll_data->source_pll; - init.num_parents = 1; - init.name = pll_data->name; - init.ops = &rp1_pll_ops; - init.flags = pll_data->flags; + ret = devm_clk_hw_register(clockman->dev, &desc->hw); + if (ret) + return ERR_PTR(ret); - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) - return NULL; + return &desc->hw; +} - pll->clockman = clockman; - pll->data = pll_data; - pll->hw.init = &init; +static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman, + struct rp1_clk_desc *desc) +{ + const struct rp1_pll_data *divider_data = desc->data; + int ret; - ret = devm_clk_hw_register(clockman->dev, &pll->hw); - if (ret) { - kfree(pll); - return NULL; - } + desc->div.reg = clockman->regs + divider_data->ctrl_reg; + desc->div.shift = __ffs(PLL_SEC_DIV_MASK); + desc->div.width = __ffs(~(PLL_SEC_DIV_MASK >> desc->div.shift)); + desc->div.flags = CLK_DIVIDER_ROUND_CLOSEST; + desc->div.lock = &clockman->regs_lock; + desc->div.hw.init = desc->hw.init; + desc->div.table = pll_sec_div_table; + + desc->clockman = clockman; - return &pll->hw; + ret = devm_clk_hw_register(clockman->dev, &desc->div.hw); + if (ret) + return ERR_PTR(ret); + + return &desc->div.hw; } -static struct clk_hw *rp1_register_pll_ph(struct rp1_clockman *clockman, - const void *data) +static struct clk_hw *rp1_register_clock(struct rp1_clockman *clockman, + struct rp1_clk_desc *desc) { - const struct rp1_pll_ph_data *ph_data = data; - struct rp1_pll_ph *ph; - struct clk_init_data init; + const struct rp1_clock_data *clock_data = desc->data; int ret; - memset(&init, 0, sizeof(init)); + if (WARN_ON_ONCE(MAX_CLK_PARENTS < clock_data->num_std_parents + + clock_data->num_aux_parents)) + return ERR_PTR(-EINVAL); - /* All of the PLLs derive from the external oscillator. */ - init.parent_names = &ph_data->source_pll; - init.num_parents = 1; - init.name = ph_data->name; - init.ops = &rp1_pll_ph_ops; - init.flags = ph_data->flags; + /* There must be a gap for the AUX selector */ + if (WARN_ON_ONCE(clock_data->num_std_parents > AUX_SEL && + desc->hw.init->parent_data[AUX_SEL].index != -1)) + return ERR_PTR(-EINVAL); - ph = kzalloc(sizeof(*ph), GFP_KERNEL); - if (!ph) - return NULL; + desc->clockman = clockman; - ph->clockman = clockman; - ph->data = ph_data; - ph->hw.init = &init; + ret = devm_clk_hw_register(clockman->dev, &desc->hw); + if (ret) + return ERR_PTR(ret); + + return &desc->hw; +} + +/* Assignment helper macros for different clock types. */ +#define _REGISTER(f, ...) { .clk_register = f, __VA_ARGS__ } - ret = devm_clk_hw_register(clockman->dev, &ph->hw); - if (ret) { - kfree(ph); - return NULL; +#define CLK_DATA(type, ...) \ + .data = &(struct type) \ + { \ + __VA_ARGS__ \ } - return &ph->hw; -} +#define REGISTER_PLL(...) _REGISTER(&rp1_register_pll, __VA_ARGS__) -static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman, - const void *data) -{ - const struct rp1_pll_data *divider_data = data; - struct rp1_pll *divider; - struct clk_init_data init; - int ret; +#define REGISTER_PLL_DIV(...) _REGISTER(&rp1_register_pll_divider, __VA_ARGS__) - memset(&init, 0, sizeof(init)); +#define REGISTER_CLK(...) _REGISTER(&rp1_register_clock, __VA_ARGS__) - init.parent_names = ÷r_data->source_pll; - init.num_parents = 1; - init.name = divider_data->name; - init.ops = &rp1_pll_divider_ops; - init.flags = divider_data->flags; +static struct rp1_clk_desc pll_sys_core_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_sys_core", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_pll_core_ops, CLK_IS_CRITICAL), + CLK_DATA(rp1_pll_core_data, .cs_reg = PLL_SYS_CS, + .pwr_reg = PLL_SYS_PWR, + .fbdiv_int_reg = PLL_SYS_FBDIV_INT, + .fbdiv_frac_reg = PLL_SYS_FBDIV_FRAC, )); - divider = devm_kzalloc(clockman->dev, sizeof(*divider), GFP_KERNEL); - if (!divider) - return NULL; +static struct rp1_clk_desc pll_audio_core_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_audio_core", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_pll_core_ops, CLK_IS_CRITICAL), + CLK_DATA(rp1_pll_core_data, .cs_reg = PLL_AUDIO_CS, + .pwr_reg = PLL_AUDIO_PWR, + .fbdiv_int_reg = PLL_AUDIO_FBDIV_INT, + .fbdiv_frac_reg = PLL_AUDIO_FBDIV_FRAC, )); - divider->div.reg = clockman->regs + divider_data->ctrl_reg; - divider->div.shift = PLL_SEC_DIV_SHIFT; - divider->div.width = PLL_SEC_DIV_WIDTH; - divider->div.flags = CLK_DIVIDER_ROUND_CLOSEST; - divider->div.lock = &clockman->regs_lock; - divider->div.hw.init = &init; - divider->div.table = pll_sec_div_table; +static struct rp1_clk_desc pll_video_core_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_video_core", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_pll_core_ops, CLK_IS_CRITICAL), + CLK_DATA(rp1_pll_core_data, .cs_reg = PLL_VIDEO_CS, + .pwr_reg = PLL_VIDEO_PWR, + .fbdiv_int_reg = PLL_VIDEO_FBDIV_INT, + .fbdiv_frac_reg = PLL_VIDEO_FBDIV_FRAC, )); - divider->clockman = clockman; - divider->data = divider_data; +static struct rp1_clk_desc pll_sys_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_sys", + (const struct clk_parent_data[]){ + { .hw = &pll_sys_core_desc.hw } }, + &rp1_pll_ops, 0), + CLK_DATA(rp1_pll_data, .ctrl_reg = PLL_SYS_PRIM, + .fc0_src = FC_NUM(0, 2), )); - ret = devm_clk_hw_register(clockman->dev, ÷r->div.hw); - if (ret) - return ERR_PTR(ret); +static struct rp1_clk_desc pll_audio_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_audio", + (const struct clk_parent_data[]){ + { .hw = &pll_audio_core_desc.hw } }, + &rp1_pll_ops, CLK_SET_RATE_PARENT), + CLK_DATA(rp1_pll_data, .ctrl_reg = PLL_AUDIO_PRIM, + .fc0_src = FC_NUM(4, 2), )); - return ÷r->div.hw; -} +static struct rp1_clk_desc pll_video_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_video", + (const struct clk_parent_data[]){ + { .hw = &pll_video_core_desc.hw } }, + &rp1_pll_ops, 0), + CLK_DATA(rp1_pll_data, .ctrl_reg = PLL_VIDEO_PRIM, + .fc0_src = FC_NUM(3, 2), )); -static struct clk_hw *rp1_register_clock(struct rp1_clockman *clockman, - const void *data) -{ - const struct rp1_clock_data *clock_data = data; - struct rp1_clock *clock; - struct clk_init_data init; - int ret; +static struct rp1_clk_desc pll_sys_sec_desc = + REGISTER_PLL_DIV(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_sys_sec", + (const struct clk_parent_data[]){ + { .hw = &pll_sys_core_desc.hw } }, + &rp1_pll_divider_ops, 0), + CLK_DATA(rp1_pll_data, .ctrl_reg = PLL_SYS_SEC, + .fc0_src = FC_NUM(2, 2), )); - BUG_ON(MAX_CLK_PARENTS < - clock_data->num_std_parents + clock_data->num_aux_parents); - /* There must be a gap for the AUX selector */ - BUG_ON((clock_data->num_std_parents > AUX_SEL) && - strcmp("-", clock_data->parents[AUX_SEL])); +static struct rp1_clk_desc pll_video_sec_desc = + REGISTER_PLL_DIV(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_video_sec", + (const struct clk_parent_data[]){ + { .hw = &pll_video_core_desc.hw } }, + &rp1_pll_divider_ops, 0), + CLK_DATA(rp1_pll_data, .ctrl_reg = PLL_VIDEO_SEC, + .fc0_src = FC_NUM(5, 3), )); - memset(&init, 0, sizeof(init)); - init.parent_names = clock_data->parents; - init.num_parents = - clock_data->num_std_parents + clock_data->num_aux_parents; - init.name = clock_data->name; - init.flags = clock_data->flags; - init.ops = &rp1_clk_ops; +static const struct clk_parent_data clk_eth_tsu_parents[] = { + { .index = 0 }, { .hw = &pll_video_sec_desc.hw }, + { .index = -1 }, { .index = -1 }, + { .index = -1 }, { .index = -1 }, + { .index = -1 }, { .index = -1 }, +}; - clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); - if (!clock) - return NULL; +static struct rp1_clk_desc clk_eth_tsu_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA("clk_eth_tsu", + clk_eth_tsu_parents, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 8, + .ctrl_reg = CLK_ETH_TSU_CTRL, + .div_int_reg = CLK_ETH_TSU_DIV_INT, + .sel_reg = CLK_ETH_TSU_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * HZ_PER_MHZ, + .fc0_src = FC_NUM(5, 7), )); - clock->clockman = clockman; - clock->data = clock_data; - clock->hw.init = &init; +static const struct clk_parent_data clk_eth_parents[] = { + { .hw = &pll_sys_sec_desc.div.hw }, + { .hw = &pll_sys_desc.hw }, + { .hw = &pll_video_sec_desc.hw }, +}; - ret = devm_clk_hw_register(clockman->dev, &clock->hw); - if (ret) - return ERR_PTR(ret); +static struct rp1_clk_desc clk_eth_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_eth", clk_eth_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 3, .ctrl_reg = CLK_ETH_CTRL, + .div_int_reg = CLK_ETH_DIV_INT, + .sel_reg = CLK_ETH_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 125 * HZ_PER_MHZ, + .fc0_src = FC_NUM(4, 6), )); - return &clock->hw; -} +static const struct clk_parent_data clk_sys_parents[] = { + { .index = 0 }, + { .index = -1 }, + { .hw = &pll_sys_desc.hw }, +}; -static struct clk_hw *rp1_register_varsrc(struct rp1_clockman *clockman, - const void *data) -{ - const char *name = *(char const * const *)data; - struct rp1_varsrc *clock; - struct clk_init_data init; - int ret; +static struct rp1_clk_desc clk_sys_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_sys", clk_sys_parents, &rp1_clk_ops, + CLK_IS_CRITICAL), + CLK_DATA(rp1_clock_data, .num_std_parents = 3, + .num_aux_parents = 0, .ctrl_reg = CLK_SYS_CTRL, + .div_int_reg = CLK_SYS_DIV_INT, + .sel_reg = CLK_SYS_SEL, + .div_int_max = DIV_INT_24BIT_MAX, + .max_freq = 200 * HZ_PER_MHZ, + .fc0_src = FC_NUM(0, 4), .clk_src_mask = 0x3, )); - memset(&init, 0, sizeof(init)); - init.parent_names = &ref_clock; - init.num_parents = 1; - init.name = name; - init.ops = &rp1_varsrc_ops; +static struct rp1_clk_desc pll_sys_pri_ph_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_sys_pri_ph", + (const struct clk_parent_data[]){ + { .hw = &pll_sys_desc.hw } }, + &rp1_pll_ph_ops, 0), + CLK_DATA(rp1_pll_ph_data, .ph_reg = PLL_SYS_PRIM, + .fixed_divider = 2, .phase = RP1_PLL_PHASE_0, + .fc0_src = FC_NUM(1, 2), )); - clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); - if (!clock) - return NULL; +static struct rp1_clk_desc pll_audio_pri_ph_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_audio_pri_ph", + (const struct clk_parent_data[]){ + { .hw = &pll_audio_desc.hw } }, + &rp1_pll_ph_ops, 0), + CLK_DATA(rp1_pll_ph_data, .ph_reg = PLL_AUDIO_PRIM, + .fixed_divider = 2, .phase = RP1_PLL_PHASE_0, + .fc0_src = FC_NUM(5, 1), )); - clock->clockman = clockman; - clock->hw.init = &init; +static struct rp1_clk_desc pll_video_pri_ph_desc = + REGISTER_PLL(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_video_pri_ph", + (const struct clk_parent_data[]){ + { .hw = &pll_video_desc.hw } }, + &rp1_pll_ph_ops, 0), + CLK_DATA(rp1_pll_ph_data, .ph_reg = PLL_VIDEO_PRIM, + .fixed_divider = 2, .phase = RP1_PLL_PHASE_0, + .fc0_src = FC_NUM(4, 3), )); - ret = devm_clk_hw_register(clockman->dev, &clock->hw); - if (ret) - return ERR_PTR(ret); +static struct rp1_clk_desc pll_audio_sec_desc = + REGISTER_PLL_DIV(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_audio_sec", + (const struct clk_parent_data[]){ + { .hw = &pll_audio_core_desc.hw } }, + &rp1_pll_divider_ops, 0), + CLK_DATA(rp1_pll_data, .ctrl_reg = PLL_AUDIO_SEC, + .fc0_src = FC_NUM(6, 2), )); - return &clock->hw; -} +static struct rp1_clk_desc pll_audio_tern_desc = + REGISTER_PLL_DIV(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "pll_audio_tern", + (const struct clk_parent_data[]){ + { .hw = &pll_audio_core_desc.hw } }, + &rp1_pll_divider_ops, 0), + CLK_DATA(rp1_pll_data, .ctrl_reg = PLL_AUDIO_TERN, + .fc0_src = FC_NUM(6, 2), )); -struct rp1_clk_desc { - struct clk_hw *(*clk_register)(struct rp1_clockman *clockman, - const void *data); - const void *data; +static struct rp1_clk_desc clk_slow_sys_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_slow_sys", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_clk_ops, CLK_IS_CRITICAL), + CLK_DATA(rp1_clock_data, .num_std_parents = 1, + .num_aux_parents = 0, + .ctrl_reg = CLK_SLOW_SYS_CTRL, + .div_int_reg = CLK_SLOW_SYS_DIV_INT, + .sel_reg = CLK_SLOW_SYS_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * HZ_PER_MHZ, + .fc0_src = FC_NUM(1, 4), .clk_src_mask = 0x1, )); + +static const struct clk_parent_data clk_dma_parents[] = { + { .hw = &pll_sys_pri_ph_desc.hw }, + { .hw = &pll_video_desc.hw }, + { .index = 0 }, }; -/* Assignment helper macros for different clock types. */ -#define _REGISTER(f, ...) { .clk_register = f, .data = __VA_ARGS__ } +static struct rp1_clk_desc clk_dma_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_dma", clk_dma_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 3, .ctrl_reg = CLK_DMA_CTRL, + .div_int_reg = CLK_DMA_DIV_INT, + .sel_reg = CLK_DMA_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(2, 2), )); -#define REGISTER_PLL_CORE(...) _REGISTER(&rp1_register_pll_core, \ - &(struct rp1_pll_core_data) \ - {__VA_ARGS__}) +static const struct clk_parent_data clk_uart_parents[] = { + { .hw = &pll_sys_pri_ph_desc.hw }, + { .hw = &pll_video_desc.hw }, + { .index = 0 }, +}; -#define REGISTER_PLL(...) _REGISTER(&rp1_register_pll, \ - &(struct rp1_pll_data) \ - {__VA_ARGS__}) +static struct rp1_clk_desc clk_uart_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_uart", clk_uart_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 3, .ctrl_reg = CLK_UART_CTRL, + .div_int_reg = CLK_UART_DIV_INT, + .sel_reg = CLK_UART_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(6, 7), )); -#define REGISTER_PLL_PH(...) _REGISTER(&rp1_register_pll_ph, \ - &(struct rp1_pll_ph_data) \ - {__VA_ARGS__}) +static const struct clk_parent_data clk_pwm0_parents[] = { + { .index = -1 }, + { .hw = &pll_video_sec_desc.hw }, + { .index = 0 }, +}; -#define REGISTER_PLL_DIV(...) _REGISTER(&rp1_register_pll_divider, \ - &(struct rp1_pll_data) \ - {__VA_ARGS__}) +static struct rp1_clk_desc clk_pwm0_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_pwm0", clk_pwm0_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 3, .ctrl_reg = CLK_PWM0_CTRL, + .div_int_reg = CLK_PWM0_DIV_INT, + .div_frac_reg = CLK_PWM0_DIV_FRAC, + .sel_reg = CLK_PWM0_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 76800 * HZ_PER_KHZ, + .fc0_src = FC_NUM(0, 5), )); -#define REGISTER_CLK(...) _REGISTER(&rp1_register_clock, \ - __VA_ARGS__) +static const struct clk_parent_data clk_pwm1_parents[] = { + { .index = -1 }, + { .hw = &pll_video_sec_desc.hw }, + { .index = 0 }, +}; -static struct rp1_clk_desc pll_sys_core_desc = REGISTER_PLL( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "pll_sys_core", - (const struct clk_parent_data[]) { { .index = 0 } }, - &rp1_pll_core_ops, - CLK_IS_CRITICAL - ), - CLK_DATA(rp1_pll_core_data, - .cs_reg = PLL_SYS_CS, - .pwr_reg = PLL_SYS_PWR, - .fbdiv_int_reg = PLL_SYS_FBDIV_INT, - .fbdiv_frac_reg = PLL_SYS_FBDIV_FRAC, - ) -); +static struct rp1_clk_desc clk_pwm1_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_pwm1", clk_pwm1_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 3, .ctrl_reg = CLK_PWM1_CTRL, + .div_int_reg = CLK_PWM1_DIV_INT, + .div_frac_reg = CLK_PWM1_DIV_FRAC, + .sel_reg = CLK_PWM1_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 76800 * HZ_PER_KHZ, + .fc0_src = FC_NUM(1, 5), )); -static struct rp1_clk_desc pll_audio_core_desc = REGISTER_PLL( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "pll_audio_core", - (const struct clk_parent_data[]) { { .index = 0 } }, - &rp1_pll_core_ops, - CLK_IS_CRITICAL - ), - CLK_DATA(rp1_pll_core_data, - .cs_reg = PLL_AUDIO_CS, - .pwr_reg = PLL_AUDIO_PWR, - .fbdiv_int_reg = PLL_AUDIO_FBDIV_INT, - .fbdiv_frac_reg = PLL_AUDIO_FBDIV_FRAC, - ) -); +static const struct clk_parent_data clk_audio_in_parents[] = { + { .index = -1 }, { .index = -1 }, + { .index = -1 }, { .hw = &pll_video_sec_desc.hw }, + { .index = 0 }, +}; -static struct rp1_clk_desc pll_video_core_desc = REGISTER_PLL( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "pll_video_core", - (const struct clk_parent_data[]) { { .index = 0 } }, - &rp1_pll_core_ops, - CLK_IS_CRITICAL - ), - CLK_DATA(rp1_pll_core_data, - .cs_reg = PLL_VIDEO_CS, - .pwr_reg = PLL_VIDEO_PWR, - .fbdiv_int_reg = PLL_VIDEO_FBDIV_INT, - .fbdiv_frac_reg = PLL_VIDEO_FBDIV_FRAC, - ) -); +static struct rp1_clk_desc clk_audio_in_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA("clk_audio_in", + clk_audio_in_parents, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 5, + .ctrl_reg = CLK_AUDIO_IN_CTRL, + .div_int_reg = CLK_AUDIO_IN_DIV_INT, + .sel_reg = CLK_AUDIO_IN_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 76800 * HZ_PER_KHZ, + .fc0_src = FC_NUM(2, 5), )); -static struct rp1_clk_desc pll_sys_desc = REGISTER_PLL( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "pll_sys", - (const struct clk_parent_data[]) { - { .hw = &pll_sys_core_desc.hw } - }, - &rp1_pll_ops, - 0 - ), - CLK_DATA(rp1_pll_data, - .ctrl_reg = PLL_SYS_PRIM, - .fc0_src = FC_NUM(0, 2), - ) -); +static const struct clk_parent_data clk_audio_out_parents[] = { + { .index = -1 }, + { .index = -1 }, + { .hw = &pll_video_sec_desc.hw }, + { .index = 0 }, +}; + +static struct rp1_clk_desc clk_audio_out_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA("clk_audio_out", + clk_audio_out_parents, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 4, + .ctrl_reg = CLK_AUDIO_OUT_CTRL, + .div_int_reg = CLK_AUDIO_OUT_DIV_INT, + .sel_reg = CLK_AUDIO_OUT_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 153600 * HZ_PER_KHZ, + .fc0_src = FC_NUM(3, 5), )); + +static const struct clk_parent_data clk_i2s_parents[] = { + { .index = 0 }, + { .hw = &pll_audio_desc.hw }, + { .hw = &pll_audio_sec_desc.hw }, +}; -static struct rp1_clk_desc pll_sys_sec_desc = REGISTER_PLL_DIV( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "pll_sys_sec", - (const struct clk_parent_data[]) { - { .hw = &pll_sys_core_desc.hw } - }, - &rp1_pll_divider_ops, - 0 - ), - CLK_DATA(rp1_pll_data, - .ctrl_reg = PLL_SYS_SEC, - .fc0_src = FC_NUM(2, 2), - ) -); +static struct rp1_clk_desc clk_i2s_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_i2s", clk_i2s_parents, &rp1_clk_ops, + CLK_SET_RATE_PARENT), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 3, .ctrl_reg = CLK_I2S_CTRL, + .div_int_reg = CLK_I2S_DIV_INT, + .sel_reg = CLK_I2S_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * HZ_PER_MHZ, + .fc0_src = FC_NUM(4, 4), )); -static struct rp1_clk_desc clk_eth_tsu_desc = REGISTER_CLK( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "clk_eth_tsu", - (const struct clk_parent_data[]) { { .index = 0 } }, - &rp1_clk_ops, - 0 - ), - CLK_DATA(rp1_clock_data, - .num_std_parents = 0, - .num_aux_parents = 1, - .ctrl_reg = CLK_ETH_TSU_CTRL, - .div_int_reg = CLK_ETH_TSU_DIV_INT, - .sel_reg = CLK_ETH_TSU_SEL, - .div_int_max = DIV_INT_8BIT_MAX, - .max_freq = 50 * HZ_PER_MHZ, - .fc0_src = FC_NUM(5, 7), - ) -); +static struct rp1_clk_desc clk_mipi0_cfg_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_mipi0_cfg", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 1, + .ctrl_reg = CLK_MIPI0_CFG_CTRL, + .div_int_reg = CLK_MIPI0_CFG_DIV_INT, + .sel_reg = CLK_MIPI0_CFG_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * HZ_PER_MHZ, + .fc0_src = FC_NUM(4, 5), )); -static const struct clk_parent_data clk_eth_parents[] = { - { .hw = &pll_sys_sec_desc.div.hw }, +static struct rp1_clk_desc clk_mipi1_cfg_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_mipi1_cfg", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 1, + .ctrl_reg = CLK_MIPI1_CFG_CTRL, + .div_int_reg = CLK_MIPI1_CFG_DIV_INT, + .sel_reg = CLK_MIPI1_CFG_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * HZ_PER_MHZ, + .fc0_src = FC_NUM(5, 6), .clk_src_mask = 0x1, )); + +static struct rp1_clk_desc clk_adc_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_adc", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 1, .ctrl_reg = CLK_ADC_CTRL, + .div_int_reg = CLK_ADC_DIV_INT, + .sel_reg = CLK_ADC_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * HZ_PER_MHZ, + .fc0_src = FC_NUM(5, 5), )); + +static struct rp1_clk_desc clk_sdio_timer_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_sdio_timer", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 1, + .ctrl_reg = CLK_SDIO_TIMER_CTRL, + .div_int_reg = CLK_SDIO_TIMER_DIV_INT, + .sel_reg = CLK_SDIO_TIMER_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * HZ_PER_MHZ, + .fc0_src = FC_NUM(3, 4), )); + +static struct rp1_clk_desc clk_sdio_alt_src_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_sdio_alt_src", + (const struct clk_parent_data[]){ + { .hw = &pll_sys_desc.hw } }, + &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 1, + .ctrl_reg = CLK_SDIO_ALT_SRC_CTRL, + .div_int_reg = CLK_SDIO_ALT_SRC_DIV_INT, + .sel_reg = CLK_SDIO_ALT_SRC_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 200 * HZ_PER_MHZ, + .fc0_src = FC_NUM(5, 4), )); + +static const struct clk_parent_data clk_dpi_parents[] = { { .hw = &pll_sys_desc.hw }, + { .hw = &pll_video_sec_desc.hw }, + { .hw = &pll_video_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, }; -static struct rp1_clk_desc clk_eth_desc = REGISTER_CLK( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "clk_eth", - clk_eth_parents, - &rp1_clk_ops, - 0 - ), - CLK_DATA(rp1_clock_data, - .num_std_parents = 0, - .num_aux_parents = 2, - .ctrl_reg = CLK_ETH_CTRL, - .div_int_reg = CLK_ETH_DIV_INT, - .sel_reg = CLK_ETH_SEL, - .div_int_max = DIV_INT_8BIT_MAX, - .max_freq = 125 * HZ_PER_MHZ, - .fc0_src = FC_NUM(4, 6), - ) -); +static struct rp1_clk_desc clk_dpi_desc = REGISTER_CLK( + .hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_dpi", clk_dpi_parents, &rp1_clk_ops, + CLK_SET_RATE_NO_REPARENT /* Let DPI driver set parent */ + ), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 8, .ctrl_reg = VIDEO_CLK_DPI_CTRL, + .div_int_reg = VIDEO_CLK_DPI_DIV_INT, + .sel_reg = VIDEO_CLK_DPI_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 200 * HZ_PER_MHZ, + .fc0_src = FC_NUM(1, 6), )); -static const struct clk_parent_data clk_sys_parents[] = { +static const struct clk_parent_data clk_gp0_parents[] = { { .index = 0 }, { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &pll_sys_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &clk_i2s_desc.hw }, + { .hw = &clk_adc_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &clk_sys_desc.hw }, +}; + +static struct rp1_clk_desc clk_gp0_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_gp0", clk_gp0_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 16, .oe_mask = BIT(0), + .ctrl_reg = CLK_GP0_CTRL, + .div_int_reg = CLK_GP0_DIV_INT, + .div_frac_reg = CLK_GP0_DIV_FRAC, + .sel_reg = CLK_GP0_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(0, 1), )); + +static const struct clk_parent_data clk_gp1_parents[] = { + { .hw = &clk_sdio_timer_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &pll_sys_pri_ph_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &clk_adc_desc.hw }, + { .hw = &clk_dpi_desc.hw }, + { .hw = &clk_pwm0_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, +}; + +static struct rp1_clk_desc clk_gp1_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_gp1", clk_gp1_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 16, .oe_mask = BIT(1), + .ctrl_reg = CLK_GP1_CTRL, + .div_int_reg = CLK_GP1_DIV_INT, + .div_frac_reg = CLK_GP1_DIV_FRAC, + .sel_reg = CLK_GP1_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(1, 1), )); + +static struct rp1_clk_desc clksrc_mipi0_dsi_byteclk_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clksrc_mipi0_dsi_byteclk", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_varsrc_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 1, + .num_aux_parents = 0, )); + +static struct rp1_clk_desc clksrc_mipi1_dsi_byteclk_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clksrc_mipi1_dsi_byteclk", + (const struct clk_parent_data[]){ { .index = 0 } }, + &rp1_varsrc_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 1, + .num_aux_parents = 0, )); + +static const struct clk_parent_data clk_mipi0_dpi_parents[] = { + { .hw = &pll_sys_desc.hw }, + { .hw = &pll_video_sec_desc.hw }, + { .hw = &pll_video_desc.hw }, + { .hw = &clksrc_mipi0_dsi_byteclk_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, +}; + +static struct rp1_clk_desc clk_mipi0_dpi_desc = REGISTER_CLK( + .hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_mipi0_dpi", clk_mipi0_dpi_parents, &rp1_clk_ops, + CLK_SET_RATE_NO_REPARENT /* Let DSI driver set parent */ + ), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 8, + .ctrl_reg = VIDEO_CLK_MIPI0_DPI_CTRL, + .div_int_reg = VIDEO_CLK_MIPI0_DPI_DIV_INT, + .div_frac_reg = VIDEO_CLK_MIPI0_DPI_DIV_FRAC, + .sel_reg = VIDEO_CLK_MIPI0_DPI_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 200 * HZ_PER_MHZ, + .fc0_src = FC_NUM(2, 6), )); + +static const struct clk_parent_data clk_mipi1_dpi_parents[] = { { .hw = &pll_sys_desc.hw }, + { .hw = &pll_video_sec_desc.hw }, + { .hw = &pll_video_desc.hw }, + { .hw = &clksrc_mipi1_dsi_byteclk_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, }; -static struct rp1_clk_desc clk_sys_desc = REGISTER_CLK( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "clk_sys", - clk_sys_parents, - &rp1_clk_ops, - CLK_IS_CRITICAL - ), - CLK_DATA(rp1_clock_data, - .num_std_parents = 3, - .num_aux_parents = 0, - .ctrl_reg = CLK_SYS_CTRL, - .div_int_reg = CLK_SYS_DIV_INT, - .sel_reg = CLK_SYS_SEL, - .div_int_max = DIV_INT_24BIT_MAX, - .max_freq = 200 * HZ_PER_MHZ, - .fc0_src = FC_NUM(0, 4), - .clk_src_mask = 0x3, - ) -); +static struct rp1_clk_desc clk_mipi1_dpi_desc = REGISTER_CLK( + .hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_mipi1_dpi", clk_mipi1_dpi_parents, &rp1_clk_ops, + CLK_SET_RATE_NO_REPARENT /* Let DSI driver set parent */ + ), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 8, + .ctrl_reg = VIDEO_CLK_MIPI1_DPI_CTRL, + .div_int_reg = VIDEO_CLK_MIPI1_DPI_DIV_INT, + .div_frac_reg = VIDEO_CLK_MIPI1_DPI_DIV_FRAC, + .sel_reg = VIDEO_CLK_MIPI1_DPI_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 200 * HZ_PER_MHZ, + .fc0_src = FC_NUM(3, 6), )); + +static const struct clk_parent_data clk_gp2_parents[] = { + { .hw = &clk_sdio_alt_src_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &pll_sys_sec_desc.hw }, + { .index = -1 }, + { .hw = &pll_video_desc.hw }, + { .hw = &clk_audio_in_desc.hw }, + { .hw = &clk_dpi_desc.hw }, + { .hw = &clk_pwm0_desc.hw }, + { .hw = &clk_pwm1_desc.hw }, + { .hw = &clk_mipi0_dpi_desc.hw }, + { .hw = &clk_mipi1_cfg_desc.hw }, + { .hw = &clk_sys_desc.hw }, +}; + +static struct rp1_clk_desc clk_gp2_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_gp2", clk_gp2_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 16, .oe_mask = BIT(2), + .ctrl_reg = CLK_GP2_CTRL, + .div_int_reg = CLK_GP2_DIV_INT, + .div_frac_reg = CLK_GP2_DIV_FRAC, + .sel_reg = CLK_GP2_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(2, 1), )); + +static const struct clk_parent_data clk_gp3_parents[] = { + { .index = 0 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &pll_video_pri_ph_desc.hw }, + { .hw = &clk_audio_out_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .hw = &clk_mipi1_dpi_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, +}; -static struct rp1_clk_desc pll_sys_pri_ph_desc = REGISTER_PLL( - .hw.init = CLK_HW_INIT_PARENTS_DATA( - "pll_sys_pri_ph", - (const struct clk_parent_data[]) { - { .hw = &pll_sys_desc.hw } - }, - &rp1_pll_ph_ops, - 0 - ), - CLK_DATA(rp1_pll_ph_data, - .ph_reg = PLL_SYS_PRIM, - .fixed_divider = 2, - .phase = RP1_PLL_PHASE_0, - .fc0_src = FC_NUM(1, 2), - ) -); +static struct rp1_clk_desc clk_gp3_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_gp3", clk_gp3_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 16, .oe_mask = BIT(3), + .ctrl_reg = CLK_GP3_CTRL, + .div_int_reg = CLK_GP3_DIV_INT, + .div_frac_reg = CLK_GP3_DIV_FRAC, + .sel_reg = CLK_GP3_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(3, 1), )); + +static const struct clk_parent_data clk_gp4_parents[] = { + { .index = 0 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &pll_video_sec_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &clk_mipi0_cfg_desc.hw }, + { .hw = &clk_uart_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .hw = &clk_sys_desc.hw }, +}; + +static struct rp1_clk_desc clk_gp4_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_gp4", clk_gp4_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 16, .oe_mask = BIT(4), + .ctrl_reg = CLK_GP4_CTRL, + .div_int_reg = CLK_GP4_DIV_INT, + .div_frac_reg = CLK_GP4_DIV_FRAC, + .sel_reg = CLK_GP4_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(4, 1), )); + +static const struct clk_parent_data clk_vec_parents[] = { + { .hw = &pll_sys_pri_ph_desc.hw }, + { .hw = &pll_video_sec_desc.hw }, + { .hw = &pll_video_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, +}; + +static struct rp1_clk_desc clk_vec_desc = REGISTER_CLK( + .hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_vec", clk_vec_parents, &rp1_clk_ops, + CLK_SET_RATE_NO_REPARENT /* Let VEC driver set parent */ + ), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 8, .ctrl_reg = VIDEO_CLK_VEC_CTRL, + .div_int_reg = VIDEO_CLK_VEC_DIV_INT, + .sel_reg = VIDEO_CLK_VEC_SEL, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 108 * HZ_PER_MHZ, + .fc0_src = FC_NUM(0, 6), )); + +static const struct clk_parent_data clk_gp5_parents[] = { + { .index = 0 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .hw = &pll_video_sec_desc.hw }, + { .hw = &clk_eth_tsu_desc.hw }, + { .index = -1 }, + { .hw = &clk_vec_desc.hw }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, + { .index = -1 }, +}; + +static struct rp1_clk_desc clk_gp5_desc = + REGISTER_CLK(.hw.init = CLK_HW_INIT_PARENTS_DATA( + "clk_gp5", clk_gp5_parents, &rp1_clk_ops, 0), + CLK_DATA(rp1_clock_data, .num_std_parents = 0, + .num_aux_parents = 16, .oe_mask = BIT(5), + .ctrl_reg = CLK_GP5_CTRL, + .div_int_reg = CLK_GP5_DIV_INT, + .div_frac_reg = CLK_GP5_DIV_FRAC, + .sel_reg = CLK_GP5_SEL, + .div_int_max = DIV_INT_16BIT_MAX, + .max_freq = 100 * HZ_PER_MHZ, + .fc0_src = FC_NUM(5, 1), )); static struct rp1_clk_desc *const clk_desc_array[] = { [RP1_PLL_SYS_CORE] = &pll_sys_core_desc, @@ -1645,6 +2026,38 @@ static struct rp1_clk_desc *const clk_desc_array[] = { [RP1_CLK_SYS] = &clk_sys_desc, [RP1_PLL_SYS_PRI_PH] = &pll_sys_pri_ph_desc, [RP1_PLL_SYS_SEC] = &pll_sys_sec_desc, + [RP1_PLL_AUDIO] = &pll_audio_desc, + [RP1_PLL_VIDEO] = &pll_video_desc, + [RP1_PLL_AUDIO_PRI_PH] = &pll_audio_pri_ph_desc, + [RP1_PLL_VIDEO_PRI_PH] = &pll_video_pri_ph_desc, + [RP1_PLL_AUDIO_SEC] = &pll_audio_sec_desc, + [RP1_PLL_VIDEO_SEC] = &pll_video_sec_desc, + [RP1_PLL_AUDIO_TERN] = &pll_audio_tern_desc, + [RP1_CLK_SLOW_SYS] = &clk_slow_sys_desc, + [RP1_CLK_DMA] = &clk_dma_desc, + [RP1_CLK_UART] = &clk_uart_desc, + [RP1_CLK_PWM0] = &clk_pwm0_desc, + [RP1_CLK_PWM1] = &clk_pwm1_desc, + [RP1_CLK_AUDIO_IN] = &clk_audio_in_desc, + [RP1_CLK_AUDIO_OUT] = &clk_audio_out_desc, + [RP1_CLK_I2S] = &clk_i2s_desc, + [RP1_CLK_MIPI0_CFG] = &clk_mipi0_cfg_desc, + [RP1_CLK_MIPI1_CFG] = &clk_mipi1_cfg_desc, + [RP1_CLK_ADC] = &clk_adc_desc, + [RP1_CLK_SDIO_TIMER] = &clk_sdio_timer_desc, + [RP1_CLK_SDIO_ALT_SRC] = &clk_sdio_alt_src_desc, + [RP1_CLK_GP0] = &clk_gp0_desc, + [RP1_CLK_GP1] = &clk_gp1_desc, + [RP1_CLK_GP2] = &clk_gp2_desc, + [RP1_CLK_GP3] = &clk_gp3_desc, + [RP1_CLK_GP4] = &clk_gp4_desc, + [RP1_CLK_GP5] = &clk_gp5_desc, + [RP1_CLK_VEC] = &clk_vec_desc, + [RP1_CLK_DPI] = &clk_dpi_desc, + [RP1_CLK_MIPI0_DPI] = &clk_mipi0_dpi_desc, + [RP1_CLK_MIPI1_DPI] = &clk_mipi1_dpi_desc, + [RP1_CLK_MIPI0_DSI_BYTECLOCK] = &clksrc_mipi0_dsi_byteclk_desc, + [RP1_CLK_MIPI1_DSI_BYTECLOCK] = &clksrc_mipi1_dsi_byteclk_desc, }; static const struct regmap_range rp1_reg_ranges[] = { @@ -1676,9 +2089,11 @@ static const struct regmap_range rp1_reg_ranges[] = { regmap_reg_range(CLK_MIPI1_CFG_SEL, CLK_MIPI1_CFG_SEL), regmap_reg_range(CLK_PCIE_AUX_CTRL, CLK_PCIE_AUX_DIV_INT), regmap_reg_range(CLK_PCIE_AUX_SEL, CLK_PCIE_AUX_SEL), - regmap_reg_range(CLK_USBH0_MICROFRAME_CTRL, CLK_USBH0_MICROFRAME_DIV_INT), + regmap_reg_range(CLK_USBH0_MICROFRAME_CTRL, + CLK_USBH0_MICROFRAME_DIV_INT), regmap_reg_range(CLK_USBH0_MICROFRAME_SEL, CLK_USBH0_MICROFRAME_SEL), - regmap_reg_range(CLK_USBH1_MICROFRAME_CTRL, CLK_USBH1_MICROFRAME_DIV_INT), + regmap_reg_range(CLK_USBH1_MICROFRAME_CTRL, + CLK_USBH1_MICROFRAME_DIV_INT), regmap_reg_range(CLK_USBH1_MICROFRAME_SEL, CLK_USBH1_MICROFRAME_SEL), regmap_reg_range(CLK_USBH0_SUSPEND_CTRL, CLK_USBH0_SUSPEND_DIV_INT), regmap_reg_range(CLK_USBH0_SUSPEND_SEL, CLK_USBH0_SUSPEND_SEL), @@ -1723,31 +2138,32 @@ static const struct regmap_config rp1_clk_regmap_cfg = { static int rp1_clk_probe(struct platform_device *pdev) { - const struct rp1_clk_desc *desc; + const size_t asize = ARRAY_SIZE(clk_desc_array); + struct rp1_clk_desc *desc; struct device *dev = &pdev->dev; struct rp1_clockman *clockman; - struct resource *res; struct clk_hw **hws; - const size_t asize = ARRAY_SIZE(clk_desc_array); - u32 chip_id, platform; unsigned int i; - int ret; clockman = devm_kzalloc(dev, struct_size(clockman, onecell.hws, asize), GFP_KERNEL); if (!clockman) return -ENOMEM; - rp1_get_platform(&chip_id, &platform); - spin_lock_init(&clockman->regs_lock); clockman->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - clockman->regs = devm_ioremap_resource(&pdev->dev, res); + + clockman->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(clockman->regs)) return PTR_ERR(clockman->regs); - platform_set_drvdata(pdev, clockman); + clockman->regmap = + devm_regmap_init_mmio(dev, clockman->regs, &rp1_clk_regmap_cfg); + if (IS_ERR(clockman->regmap)) { + dev_err_probe(dev, PTR_ERR(clockman->regmap), + "could not init clock regmap\n"); + return PTR_ERR(clockman->regmap); + } clockman->onecell.num = asize; hws = clockman->onecell.hws; @@ -1758,6 +2174,11 @@ static int rp1_clk_probe(struct platform_device *pdev) hws[i] = desc->clk_register(clockman, desc); } + clk_audio_core = &pll_audio_core_desc; + clk_audio = &pll_audio_desc; + clk_i2s = &clk_i2s_desc; + clk_xosc = clk_hw_get_parent_by_index(&clk_i2s->hw, 0); + platform_set_drvdata(pdev, clockman); return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, @@ -1778,12 +2199,9 @@ static struct platform_driver rp1_clk_driver = { .probe = rp1_clk_probe, }; -static int __init __rp1_clk_driver_init(void) -{ - return platform_driver_register(&rp1_clk_driver); -} -postcore_initcall(__rp1_clk_driver_init); +module_platform_driver(rp1_clk_driver); MODULE_AUTHOR("Naushir Patuck <[email protected]>"); +MODULE_AUTHOR("Andrea della Porta <[email protected]>"); MODULE_DESCRIPTION("RP1 clock driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index db3f079fe695..a078de2b807d 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -24,16 +24,16 @@ enum gio_reg_index { NUMBER_OF_GIO_REGISTERS }; -#define GIO_BANK_SIZE (NUMBER_OF_GIO_REGISTERS * sizeof(u32)) -#define GIO_BANK_OFF(bank, off) (((bank) * GIO_BANK_SIZE) + (off * sizeof(u32))) -#define GIO_ODEN(bank) GIO_BANK_OFF(bank, GIO_REG_ODEN) -#define GIO_DATA(bank) GIO_BANK_OFF(bank, GIO_REG_DATA) -#define GIO_IODIR(bank) GIO_BANK_OFF(bank, GIO_REG_IODIR) -#define GIO_EC(bank) GIO_BANK_OFF(bank, GIO_REG_EC) -#define GIO_EI(bank) GIO_BANK_OFF(bank, GIO_REG_EI) -#define GIO_MASK(bank) GIO_BANK_OFF(bank, GIO_REG_MASK) -#define GIO_LEVEL(bank) GIO_BANK_OFF(bank, GIO_REG_LEVEL) -#define GIO_STAT(bank) GIO_BANK_OFF(bank, GIO_REG_STAT) +#define GIO_BANK_SIZE (NUMBER_OF_GIO_REGISTERS * sizeof(u32)) +#define GIO_BANK_OFF(bank, off) (((bank) * GIO_BANK_SIZE) + (off * sizeof(u32))) +#define GIO_ODEN(bank) GIO_BANK_OFF(bank, GIO_REG_ODEN) +#define GIO_DATA(bank) GIO_BANK_OFF(bank, GIO_REG_DATA) +#define GIO_IODIR(bank) GIO_BANK_OFF(bank, GIO_REG_IODIR) +#define GIO_EC(bank) GIO_BANK_OFF(bank, GIO_REG_EC) +#define GIO_EI(bank) GIO_BANK_OFF(bank, GIO_REG_EI) +#define GIO_MASK(bank) GIO_BANK_OFF(bank, GIO_REG_MASK) +#define GIO_LEVEL(bank) GIO_BANK_OFF(bank, GIO_REG_LEVEL) +#define GIO_STAT(bank) GIO_BANK_OFF(bank, GIO_REG_STAT) struct brcmstb_gpio_bank { struct list_head node; @@ -56,10 +56,10 @@ struct brcmstb_gpio_priv { int parent_wake_irq; }; -#define MAX_GPIO_PER_BANK 32 -#define GPIO_BANK(gpio) ((gpio) >> 5) +#define MAX_GPIO_PER_BANK 32 +#define GPIO_BANK(gpio) ((gpio) >> 5) /* assumes MAX_GPIO_PER_BANK is a multiple of 2 */ -#define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1)) +#define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1)) static inline struct brcmstb_gpio_priv * brcmstb_gpio_gc_to_priv(struct gpio_chip *gc) @@ -73,8 +73,10 @@ __brcmstb_gpio_get_active_irqs(struct brcmstb_gpio_bank *bank) { void __iomem *reg_base = bank->parent_priv->reg_base; - return gpio_generic_read_reg(&bank->chip, reg_base + GIO_STAT(bank->id)) & - gpio_generic_read_reg(&bank->chip, reg_base + GIO_MASK(bank->id)); + return gpio_generic_read_reg(&bank->chip, + reg_base + GIO_STAT(bank->id)) & + gpio_generic_read_reg(&bank->chip, + reg_base + GIO_MASK(bank->id)); } static unsigned long @@ -96,7 +98,7 @@ static int brcmstb_gpio_hwirq_to_offset(irq_hw_number_t hwirq, } static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, - unsigned int hwirq, bool enable) + unsigned int hwirq, bool enable) { struct brcmstb_gpio_priv *priv = bank->parent_priv; u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(hwirq, bank)); @@ -110,8 +112,8 @@ static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, imask |= mask; else imask &= ~mask; - gpio_generic_write_reg(&bank->chip, - priv->reg_base + GIO_MASK(bank->id), imask); + gpio_generic_write_reg(&bank->chip, priv->reg_base + GIO_MASK(bank->id), + imask); } static int brcmstb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) @@ -150,8 +152,8 @@ static void brcmstb_gpio_irq_ack(struct irq_data *d) struct brcmstb_gpio_priv *priv = bank->parent_priv; u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(d->hwirq, bank)); - gpio_generic_write_reg(&bank->chip, - priv->reg_base + GIO_STAT(bank->id), mask); + gpio_generic_write_reg(&bank->chip, priv->reg_base + GIO_STAT(bank->id), + mask); } static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) @@ -187,7 +189,7 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) break; case IRQ_TYPE_EDGE_BOTH: level = 0; - edge_config = 0; /* don't care, but want known value */ + edge_config = 0; /* don't care, but want known value */ edge_insensitive = mask; break; default: @@ -196,18 +198,20 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) guard(gpio_generic_lock_irqsave)(&bank->chip); - iedge_config = gpio_generic_read_reg(&bank->chip, - priv->reg_base + GIO_EC(bank->id)) & ~mask; - iedge_insensitive = gpio_generic_read_reg(&bank->chip, - priv->reg_base + GIO_EI(bank->id)) & ~mask; + iedge_config = gpio_generic_read_reg( + &bank->chip, priv->reg_base + GIO_EC(bank->id)) & + ~mask; + iedge_insensitive = + gpio_generic_read_reg(&bank->chip, + priv->reg_base + GIO_EI(bank->id)) & + ~mask; ilevel = gpio_generic_read_reg(&bank->chip, - priv->reg_base + GIO_LEVEL(bank->id)) & ~mask; + priv->reg_base + GIO_LEVEL(bank->id)) & + ~mask; - gpio_generic_write_reg(&bank->chip, - priv->reg_base + GIO_EC(bank->id), + gpio_generic_write_reg(&bank->chip, priv->reg_base + GIO_EC(bank->id), iedge_config | edge_config); - gpio_generic_write_reg(&bank->chip, - priv->reg_base + GIO_EI(bank->id), + gpio_generic_write_reg(&bank->chip, priv->reg_base + GIO_EI(bank->id), iedge_insensitive | edge_insensitive); gpio_generic_write_reg(&bank->chip, priv->reg_base + GIO_LEVEL(bank->id), @@ -217,7 +221,7 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type) } static int brcmstb_gpio_priv_set_wake(struct brcmstb_gpio_priv *priv, - unsigned int enable) + unsigned int enable) { int ret = 0; @@ -273,9 +277,10 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank) for_each_set_bit(offset, &status, 32) { if (offset >= bank->width) - dev_warn(&priv->pdev->dev, - "IRQ for invalid GPIO (bank=%d, offset=%d)\n", - bank->id, offset); + dev_warn( + &priv->pdev->dev, + "IRQ for invalid GPIO (bank=%d, offset=%d)\n", + bank->id, offset); generic_handle_domain_irq(domain, hwbase + offset); } } @@ -297,8 +302,9 @@ static void brcmstb_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } -static struct brcmstb_gpio_bank *brcmstb_gpio_hwirq_to_bank( - struct brcmstb_gpio_priv *priv, irq_hw_number_t hwirq) +static struct brcmstb_gpio_bank * +brcmstb_gpio_hwirq_to_bank(struct brcmstb_gpio_priv *priv, + irq_hw_number_t hwirq) { struct brcmstb_gpio_bank *bank; int i = 0; @@ -319,9 +325,8 @@ static struct brcmstb_gpio_bank *brcmstb_gpio_hwirq_to_bank( static struct lock_class_key brcmstb_gpio_irq_lock_class; static struct lock_class_key brcmstb_gpio_irq_request_class; - static int brcmstb_gpio_irq_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) + irq_hw_number_t hwirq) { struct brcmstb_gpio_priv *priv = d->host_data; struct brcmstb_gpio_bank *bank = @@ -332,8 +337,8 @@ static int brcmstb_gpio_irq_map(struct irq_domain *d, unsigned int irq, if (!bank) return -EINVAL; - dev_dbg(&pdev->dev, "Mapping irq %d for gpio line %d (bank %d)\n", - irq, (int)hwirq, bank->id); + dev_dbg(&pdev->dev, "Mapping irq %d for gpio line %d (bank %d)\n", irq, + (int)hwirq, bank->id); ret = irq_set_chip_data(irq, &bank->chip.gc); if (ret < 0) return ret; @@ -358,15 +363,17 @@ static const struct irq_domain_ops brcmstb_gpio_irq_domain_ops = { /* Make sure that the number of banks matches up between properties */ static int brcmstb_gpio_sanity_check_banks(struct device *dev, - struct device_node *np, struct resource *res) + struct device_node *np, + struct resource *res) { int res_num_banks = resource_size(res) / GIO_BANK_SIZE; int num_banks = of_property_count_u32_elems(np, "brcm,gpio-bank-widths"); if (res_num_banks != num_banks) { - dev_err(dev, "Mismatch in banks: res had %d, bank-widths had %d\n", - res_num_banks, num_banks); + dev_err(dev, + "Mismatch in banks: res had %d, bank-widths had %d\n", + res_num_banks, num_banks); return -EINVAL; } else { return 0; @@ -400,7 +407,8 @@ static void brcmstb_gpio_remove(struct platform_device *pdev) } static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, u32 *flags) + const struct of_phandle_args *gpiospec, + u32 *flags) { struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); @@ -419,7 +427,8 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, return -EINVAL; if (unlikely(offset >= bank->width)) { - dev_warn_ratelimited(&priv->pdev->dev, + dev_warn_ratelimited( + &priv->pdev->dev, "Received request for invalid GPIO offset %d\n", gpiospec->args[0]); } @@ -432,14 +441,15 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, /* priv->parent_irq and priv->num_gpios must be set before calling */ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, - struct brcmstb_gpio_priv *priv) + struct brcmstb_gpio_priv *priv) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; int err; - priv->irq_domain = irq_domain_create_linear(dev_fwnode(dev), priv->num_gpios, - &brcmstb_gpio_irq_domain_ops, priv); + priv->irq_domain = + irq_domain_create_linear(dev_fwnode(dev), priv->num_gpios, + &brcmstb_gpio_irq_domain_ops, priv); if (!priv->irq_domain) { dev_err(dev, "Couldn't allocate IRQ domain\n"); return -ENXIO; @@ -449,7 +459,8 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, priv->parent_wake_irq = platform_get_irq(pdev, 1); if (priv->parent_wake_irq < 0) { priv->parent_wake_irq = 0; - dev_warn(dev, + dev_warn( + dev, "Couldn't get wake IRQ - GPIOs will not be able to wake from sleep"); } else { /* @@ -460,8 +471,8 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, device_wakeup_enable(dev); err = devm_request_irq(dev, priv->parent_wake_irq, brcmstb_gpio_wake_irq_handler, - IRQF_SHARED, - "brcmstb-gpio-wake", priv); + IRQF_SHARED, "brcmstb-gpio-wake", + priv); if (err < 0) { dev_err(dev, "Couldn't request wake IRQ"); @@ -498,8 +509,9 @@ static void brcmstb_gpio_bank_save(struct brcmstb_gpio_priv *priv, unsigned int i; for (i = 0; i < GIO_REG_STAT; i++) - bank->saved_regs[i] = gpio_generic_read_reg(&bank->chip, - priv->reg_base + GIO_BANK_OFF(bank->id, i)); + bank->saved_regs[i] = gpio_generic_read_reg( + &bank->chip, + priv->reg_base + GIO_BANK_OFF(bank->id, i)); } static void brcmstb_gpio_quiesce(struct device *dev, bool save) @@ -540,9 +552,9 @@ static void brcmstb_gpio_bank_restore(struct brcmstb_gpio_priv *priv, unsigned int i; for (i = 0; i < GIO_REG_STAT; i++) - gpio_generic_write_reg(&bank->chip, - priv->reg_base + GIO_BANK_OFF(bank->id, i), - bank->saved_regs[i]); + gpio_generic_write_reg( + &bank->chip, priv->reg_base + GIO_BANK_OFF(bank->id, i), + bank->saved_regs[i]); } static int brcmstb_gpio_suspend(struct device *dev) @@ -573,12 +585,12 @@ static int brcmstb_gpio_resume(struct device *dev) } #else -#define brcmstb_gpio_suspend NULL -#define brcmstb_gpio_resume NULL +#define brcmstb_gpio_suspend NULL +#define brcmstb_gpio_resume NULL #endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops brcmstb_gpio_pm_ops = { - .suspend_noirq = brcmstb_gpio_suspend, + .suspend_noirq = brcmstb_gpio_suspend, .resume_noirq = brcmstb_gpio_resume, }; @@ -633,7 +645,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) flags = GPIO_GENERIC_BIG_ENDIAN_BYTE_ORDER; #endif if (of_property_read_bool(np, "brcm,gpio-direct")) - flags |= BGPIOF_REG_DIRECT; + flags |= GPIO_GENERIC_REG_DIRECT; of_property_for_each_u32(np, "brcm,gpio-bank-widths", bank_width) { struct brcmstb_gpio_bank *bank; @@ -674,7 +686,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) * and direction bits have 0 = output and 1 = input */ - config = (struct gpio_generic_chip_config) { + config = (struct gpio_generic_chip_config){ .dev = dev, .sz = 4, .dat = reg_base + GIO_DATA(bank->id), @@ -684,14 +696,15 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) err = gpio_generic_chip_init(&bank->chip, &config); if (err) { - dev_err(dev, "failed to initialize generic GPIO chip\n"); + dev_err(dev, + "failed to initialize generic GPIO chip\n"); goto fail; } gc->owner = THIS_MODULE; gc->label = devm_kasprintf(dev, GFP_KERNEL, "gpio-brcmstb@%zx", (size_t)res->start + - GIO_BANK_OFF(bank->id, 0)); + GIO_BANK_OFF(bank->id, 0)); if (!gc->label) { err = -ENOMEM; goto fail; @@ -710,14 +723,17 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) * Mask all interrupts by default, since wakeup interrupts may * be retained from S5 cold boot */ - need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank); - gpio_generic_write_reg(&bank->chip, - reg_base + GIO_MASK(bank->id), 0); + if (priv->parent_irq > 0) { + need_wakeup_event |= + !!__brcmstb_gpio_get_active_irqs(bank); + gpio_generic_write_reg( + &bank->chip, reg_base + GIO_MASK(bank->id), 0); + } err = gpiochip_add_data(gc, bank); if (err) { dev_err(dev, "Could not add gpiochip for bank %d\n", - bank->id); + bank->id); goto fail; } num_gpios += gc->ngpio; @@ -744,7 +760,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) return 0; fail: - (void) brcmstb_gpio_remove(pdev); + (void)brcmstb_gpio_remove(pdev); return err; } diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index 960ef1d4681e..9f6b7fcd4f3f 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -247,21 +247,22 @@ static int bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int bgpio_set_direct(struct gpio_chip *gc, unsigned int gpio, int val) { + struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); unsigned long mask = bgpio_line2mask(gc, gpio); unsigned long flags; - raw_spin_lock_irqsave(&gc->bgpio_lock, flags); + raw_spin_lock_irqsave(&chip->lock, flags); - gc->bgpio_data = gc->read_reg(gc->reg_dat); + chip->sdata = chip->read_reg(chip->reg_dat); if (val) - gc->bgpio_data |= mask; + chip->sdata |= mask; else - gc->bgpio_data &= ~mask; + chip->sdata &= ~mask; - gc->write_reg(gc->reg_dat, gc->bgpio_data); + chip->write_reg(chip->reg_dat, chip->sdata); - raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + raw_spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -298,8 +299,8 @@ static int bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) return 0; } -static void bgpio_multiple_get_masks(struct gpio_chip *gc, - unsigned long *mask, unsigned long *bits, +static void bgpio_multiple_get_masks(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits, unsigned long *set_mask, unsigned long *clear_mask) { @@ -338,7 +339,7 @@ static void bgpio_set_multiple_single_reg(struct gpio_chip *gc, } static int bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, - unsigned long *bits) + unsigned long *bits) { struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); @@ -374,29 +375,30 @@ static int bgpio_set_multiple_with_clear(struct gpio_chip *gc, return 0; } -static int bgpio_set_multiple_direct(struct gpio_chip *gc, - unsigned long *mask, - unsigned long *bits) +static int bgpio_set_multiple_direct(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) { + struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); unsigned long flags; unsigned long set_mask, clear_mask; - raw_spin_lock_irqsave(&gc->bgpio_lock, flags); + raw_spin_lock_irqsave(&chip->lock, flags); bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); - gc->bgpio_data = gc->read_reg(gc->reg_dat); + chip->sdata = chip->read_reg(chip->reg_dat); - gc->bgpio_data |= set_mask; - gc->bgpio_data &= ~clear_mask; + chip->sdata |= set_mask; + chip->sdata &= ~clear_mask; - gc->write_reg(gc->reg_dat, gc->bgpio_data); + chip->write_reg(chip->reg_dat, chip->sdata); - raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + raw_spin_unlock_irqrestore(&chip->lock, flags); return 0; } -static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, bool dir_out) +static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, + bool dir_out) { struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); @@ -419,8 +421,7 @@ static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) return bgpio_dir_return(gc, gpio, false); } -static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, - int val) +static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, int val) { return -EINVAL; } @@ -454,23 +455,24 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int bgpio_dir_in_direct(struct gpio_chip *gc, unsigned int gpio) { + struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); unsigned long flags; - raw_spin_lock_irqsave(&gc->bgpio_lock, flags); + raw_spin_lock_irqsave(&chip->lock, flags); - if (gc->reg_dir_in) - gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); - if (gc->reg_dir_out) - gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); + if (chip->reg_dir_in) + chip->sdir = ~chip->read_reg(chip->reg_dir_in); + if (chip->reg_dir_out) + chip->sdir = chip->read_reg(chip->reg_dir_out); - gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); + chip->sdir &= ~bgpio_line2mask(gc, gpio); - if (gc->reg_dir_in) - gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); - if (gc->reg_dir_out) - gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); + if (chip->reg_dir_in) + chip->write_reg(chip->reg_dir_in, ~chip->sdir); + if (chip->reg_dir_out) + chip->write_reg(chip->reg_dir_out, chip->sdir); - raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + raw_spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -487,13 +489,15 @@ static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) } if (chip->reg_dir_out) { - if (chip->read_reg(chip->reg_dir_out) & bgpio_line2mask(gc, gpio)) + if (chip->read_reg(chip->reg_dir_out) & + bgpio_line2mask(gc, gpio)) return GPIO_LINE_DIRECTION_OUT; return GPIO_LINE_DIRECTION_IN; } if (chip->reg_dir_in) - if (!(chip->read_reg(chip->reg_dir_in) & bgpio_line2mask(gc, gpio))) + if (!(chip->read_reg(chip->reg_dir_in) & + bgpio_line2mask(gc, gpio))) return GPIO_LINE_DIRECTION_OUT; return GPIO_LINE_DIRECTION_IN; @@ -519,23 +523,24 @@ static void bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static void bgpio_dir_out_direct(struct gpio_chip *gc, unsigned int gpio, int val) { + struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); unsigned long flags; - raw_spin_lock_irqsave(&gc->bgpio_lock, flags); + raw_spin_lock_irqsave(&chip->lock, flags); - if (gc->reg_dir_in) - gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); - if (gc->reg_dir_out) - gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); + if (chip->reg_dir_in) + chip->sdir = ~chip->read_reg(chip->reg_dir_in); + if (chip->reg_dir_out) + chip->sdir = chip->read_reg(chip->reg_dir_out); - gc->bgpio_dir |= bgpio_line2mask(gc, gpio); + chip->sdir |= bgpio_line2mask(gc, gpio); - if (gc->reg_dir_in) - gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); - if (gc->reg_dir_out) - gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); + if (chip->reg_dir_in) + chip->write_reg(chip->reg_dir_in, ~chip->sdir); + if (chip->reg_dir_out) + chip->write_reg(chip->reg_dir_out, chip->sdir); - raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + raw_spin_unlock_irqrestore(&chip->lock, flags); } static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, @@ -571,30 +576,29 @@ static int bgpio_dir_out_val_first_direct(struct gpio_chip *gc, } static int bgpio_setup_accessors(struct device *dev, - struct gpio_generic_chip *chip, - bool byte_be) + struct gpio_generic_chip *chip, bool byte_be) { switch (chip->bits) { case 8: - chip->read_reg = bgpio_read8; - chip->write_reg = bgpio_write8; + chip->read_reg = bgpio_read8; + chip->write_reg = bgpio_write8; break; case 16: if (byte_be) { - chip->read_reg = bgpio_read16be; - chip->write_reg = bgpio_write16be; + chip->read_reg = bgpio_read16be; + chip->write_reg = bgpio_write16be; } else { - chip->read_reg = bgpio_read16; - chip->write_reg = bgpio_write16; + chip->read_reg = bgpio_read16; + chip->write_reg = bgpio_write16; } break; case 32: if (byte_be) { - chip->read_reg = bgpio_read32be; - chip->write_reg = bgpio_write32be; + chip->read_reg = bgpio_read32be; + chip->write_reg = bgpio_write32be; } else { - chip->read_reg = bgpio_read32; - chip->write_reg = bgpio_write32; + chip->read_reg = bgpio_read32; + chip->write_reg = bgpio_write32; } break; #if BITS_PER_LONG >= 64 @@ -604,8 +608,8 @@ static int bgpio_setup_accessors(struct device *dev, "64 bit big endian byte order unsupported\n"); return -EINVAL; } else { - chip->read_reg = bgpio_read64; - chip->write_reg = bgpio_write64; + chip->read_reg = bgpio_read64; + chip->write_reg = bgpio_write64; } break; #endif /* BITS_PER_LONG >= 64 */ @@ -660,7 +664,7 @@ static int bgpio_setup_io(struct gpio_generic_chip *chip, } else if (cfg->flags & GPIO_GENERIC_NO_OUTPUT) { gc->set = bgpio_set_none; gc->set_multiple = NULL; - } else if (flags & BGPIOF_REG_DIRECT) { + } else if (cfg->flags & GPIO_GENERIC_REG_DIRECT) { gc->set = bgpio_set_direct; gc->set_multiple = bgpio_set_multiple_direct; } else { @@ -699,11 +703,21 @@ static int bgpio_setup_direction(struct gpio_generic_chip *chip, if (cfg->dirout || cfg->dirin) { chip->reg_dir_out = cfg->dirout; chip->reg_dir_in = cfg->dirin; - if (cfg->flags & GPIO_GENERIC_NO_SET_ON_INPUT) - gc->direction_output = bgpio_dir_out_dir_first; - else - gc->direction_output = bgpio_dir_out_val_first; - gc->direction_input = bgpio_dir_in; + if (cfg->flags & GPIO_GENERIC_REG_DIRECT) { + if (cfg->flags & GPIO_GENERIC_NO_SET_ON_INPUT) + gc->direction_output = + bgpio_dir_out_dir_first_direct; + else + gc->direction_output = + bgpio_dir_out_val_first_direct; + gc->direction_input = bgpio_dir_in_direct; + } else { + if (cfg->flags & GPIO_GENERIC_NO_SET_ON_INPUT) + gc->direction_output = bgpio_dir_out_dir_first; + else + gc->direction_output = bgpio_dir_out_val_first; + gc->direction_input = bgpio_dir_in; + } gc->get_direction = bgpio_get_dir; } else { if (cfg->flags & GPIO_GENERIC_NO_OUTPUT) @@ -787,7 +801,7 @@ int gpio_generic_chip_init(struct gpio_generic_chip *chip, chip->sdata = chip->read_reg(chip->reg_dat); if (gc->set == bgpio_set_set && - !(flags & GPIO_GENERIC_UNREADABLE_REG_SET)) + !(flags & GPIO_GENERIC_UNREADABLE_REG_SET)) chip->sdata = chip->read_reg(chip->reg_set); if (flags & GPIO_GENERIC_UNREADABLE_REG_DIR) @@ -818,8 +832,7 @@ EXPORT_SYMBOL_GPL(gpio_generic_chip_init); #if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM) -static void __iomem *bgpio_map(struct platform_device *pdev, - const char *name, +static void __iomem *bgpio_map(struct platform_device *pdev, const char *name, resource_size_t sane_sz) { struct resource *r; @@ -841,7 +854,7 @@ static const struct of_device_id bgpio_of_match[] = { { .compatible = "wd,mbl-gpio" }, { .compatible = "ni,169445-nand-gpio" }, { .compatible = "intel,ixp4xx-expansion-bus-mmio-gpio" }, - { } + {} }; MODULE_DEVICE_TABLE(of, bgpio_of_match); @@ -898,7 +911,7 @@ static int bgpio_pdev_probe(struct platform_device *pdev) if (device_property_read_bool(dev, "no-output")) flags |= GPIO_GENERIC_NO_OUTPUT; - config = (struct gpio_generic_chip_config) { + config = (struct gpio_generic_chip_config){ .dev = dev, .sz = sz, .dat = dat, @@ -932,10 +945,10 @@ static int bgpio_pdev_probe(struct platform_device *pdev) static const struct platform_device_id bgpio_id_table[] = { { - .name = "basic-mmio-gpio", - .driver_data = 0, + .name = "basic-mmio-gpio", + .driver_data = 0, }, - { } + {} }; MODULE_DEVICE_TABLE(platform, bgpio_id_table); diff --git a/drivers/pinctrl/pinctrl-rp1.c b/drivers/pinctrl/pinctrl-rp1.c index ddc92e79b05b..08d435a6798d 100644 --- a/drivers/pinctrl/pinctrl-rp1.c +++ b/drivers/pinctrl/pinctrl-rp1.c @@ -37,116 +37,114 @@ #include "pinctrl-utils.h" #define MODULE_NAME "pinctrl-rp1" -#define RP1_NUM_GPIOS 54 -#define RP1_NUM_BANKS 3 +#define RP1_NUM_GPIOS 54 +#define RP1_NUM_BANKS 3 -#define RP1_RW_OFFSET 0x0000 -#define RP1_XOR_OFFSET 0x1000 -#define RP1_SET_OFFSET 0x2000 -#define RP1_CLR_OFFSET 0x3000 +#define RP1_RW_OFFSET 0x0000 +#define RP1_XOR_OFFSET 0x1000 +#define RP1_SET_OFFSET 0x2000 +#define RP1_CLR_OFFSET 0x3000 -#define RP1_GPIO_STATUS 0x0000 -#define RP1_GPIO_CTRL 0x0004 +#define RP1_GPIO_STATUS 0x0000 +#define RP1_GPIO_CTRL 0x0004 -#define RP1_GPIO_PCIE_INTE 0x011c -#define RP1_GPIO_PCIE_INTS 0x0124 +#define RP1_GPIO_PCIE_INTE 0x011c +#define RP1_GPIO_PCIE_INTS 0x0124 -#define RP1_GPIO_EVENTS_SHIFT_RAW 20 -#define RP1_GPIO_STATUS_FALLING BIT(20) -#define RP1_GPIO_STATUS_RISING BIT(21) -#define RP1_GPIO_STATUS_LOW BIT(22) -#define RP1_GPIO_STATUS_HIGH BIT(23) +#define RP1_GPIO_EVENTS_SHIFT_RAW 20 +#define RP1_GPIO_STATUS_FALLING BIT(20) +#define RP1_GPIO_STATUS_RISING BIT(21) +#define RP1_GPIO_STATUS_LOW BIT(22) +#define RP1_GPIO_STATUS_HIGH BIT(23) -#define RP1_GPIO_EVENTS_SHIFT_FILTERED 24 -#define RP1_GPIO_STATUS_F_FALLING BIT(24) -#define RP1_GPIO_STATUS_F_RISING BIT(25) -#define RP1_GPIO_STATUS_F_LOW BIT(26) -#define RP1_GPIO_STATUS_F_HIGH BIT(27) +#define RP1_GPIO_EVENTS_SHIFT_FILTERED 24 +#define RP1_GPIO_STATUS_F_FALLING BIT(24) +#define RP1_GPIO_STATUS_F_RISING BIT(25) +#define RP1_GPIO_STATUS_F_LOW BIT(26) +#define RP1_GPIO_STATUS_F_HIGH BIT(27) -#define RP1_GPIO_CTRL_FUNCSEL_LSB 0 -#define RP1_GPIO_CTRL_FUNCSEL_MASK 0x0000001f -#define RP1_GPIO_CTRL_OUTOVER_LSB 12 -#define RP1_GPIO_CTRL_OUTOVER_MASK 0x00003000 -#define RP1_GPIO_CTRL_OEOVER_LSB 14 -#define RP1_GPIO_CTRL_OEOVER_MASK 0x0000c000 -#define RP1_GPIO_CTRL_INOVER_LSB 16 -#define RP1_GPIO_CTRL_INOVER_MASK 0x00030000 -#define RP1_GPIO_CTRL_IRQEN_FALLING BIT(20) -#define RP1_GPIO_CTRL_IRQEN_RISING BIT(21) -#define RP1_GPIO_CTRL_IRQEN_LOW BIT(22) -#define RP1_GPIO_CTRL_IRQEN_HIGH BIT(23) -#define RP1_GPIO_CTRL_IRQEN_F_FALLING BIT(24) -#define RP1_GPIO_CTRL_IRQEN_F_RISING BIT(25) -#define RP1_GPIO_CTRL_IRQEN_F_LOW BIT(26) -#define RP1_GPIO_CTRL_IRQEN_F_HIGH BIT(27) -#define RP1_GPIO_CTRL_IRQRESET BIT(28) -#define RP1_GPIO_CTRL_IRQOVER_LSB 30 -#define RP1_GPIO_CTRL_IRQOVER_MASK 0xc0000000 +#define RP1_GPIO_CTRL_FUNCSEL_LSB 0 +#define RP1_GPIO_CTRL_FUNCSEL_MASK 0x0000001f +#define RP1_GPIO_CTRL_OUTOVER_LSB 12 +#define RP1_GPIO_CTRL_OUTOVER_MASK 0x00003000 +#define RP1_GPIO_CTRL_OEOVER_LSB 14 +#define RP1_GPIO_CTRL_OEOVER_MASK 0x0000c000 +#define RP1_GPIO_CTRL_INOVER_LSB 16 +#define RP1_GPIO_CTRL_INOVER_MASK 0x00030000 +#define RP1_GPIO_CTRL_IRQEN_FALLING BIT(20) +#define RP1_GPIO_CTRL_IRQEN_RISING BIT(21) +#define RP1_GPIO_CTRL_IRQEN_LOW BIT(22) +#define RP1_GPIO_CTRL_IRQEN_HIGH BIT(23) +#define RP1_GPIO_CTRL_IRQEN_F_FALLING BIT(24) +#define RP1_GPIO_CTRL_IRQEN_F_RISING BIT(25) +#define RP1_GPIO_CTRL_IRQEN_F_LOW BIT(26) +#define RP1_GPIO_CTRL_IRQEN_F_HIGH BIT(27) +#define RP1_GPIO_CTRL_IRQRESET BIT(28) +#define RP1_GPIO_CTRL_IRQOVER_LSB 30 +#define RP1_GPIO_CTRL_IRQOVER_MASK 0xc0000000 -#define RP1_INT_EDGE_FALLING BIT(0) -#define RP1_INT_EDGE_RISING BIT(1) -#define RP1_INT_LEVEL_LOW BIT(2) -#define RP1_INT_LEVEL_HIGH BIT(3) -#define RP1_INT_MASK 0xf +#define RP1_INT_EDGE_FALLING BIT(0) +#define RP1_INT_EDGE_RISING BIT(1) +#define RP1_INT_LEVEL_LOW BIT(2) +#define RP1_INT_LEVEL_HIGH BIT(3) +#define RP1_INT_MASK 0xf -#define RP1_INT_EDGE_BOTH (RP1_INT_EDGE_FALLING | \ - RP1_INT_EDGE_RISING) -#define RP1_PUD_OFF 0 -#define RP1_PUD_DOWN 1 -#define RP1_PUD_UP 2 +#define RP1_INT_EDGE_BOTH (RP1_INT_EDGE_FALLING | RP1_INT_EDGE_RISING) +#define RP1_PUD_OFF 0 +#define RP1_PUD_DOWN 1 +#define RP1_PUD_UP 2 -#define RP1_FSEL_COUNT 9 +#define RP1_FSEL_COUNT 9 -#define RP1_FSEL_ALT0 0x00 -#define RP1_FSEL_GPIO 0x05 -#define RP1_FSEL_NONE 0x09 -#define RP1_FSEL_NONE_HW 0x1f +#define RP1_FSEL_ALT0 0x00 +#define RP1_FSEL_GPIO 0x05 +#define RP1_FSEL_NONE 0x09 +#define RP1_FSEL_NONE_HW 0x1f -#define RP1_DIR_OUTPUT 0 -#define RP1_DIR_INPUT 1 +#define RP1_DIR_OUTPUT 0 +#define RP1_DIR_INPUT 1 -#define RP1_OUTOVER_PERI 0 -#define RP1_OUTOVER_INVPERI 1 -#define RP1_OUTOVER_LOW 2 -#define RP1_OUTOVER_HIGH 3 +#define RP1_OUTOVER_PERI 0 +#define RP1_OUTOVER_INVPERI 1 +#define RP1_OUTOVER_LOW 2 +#define RP1_OUTOVER_HIGH 3 -#define RP1_OEOVER_PERI 0 -#define RP1_OEOVER_INVPERI 1 -#define RP1_OEOVER_DISABLE 2 -#define RP1_OEOVER_ENABLE 3 +#define RP1_OEOVER_PERI 0 +#define RP1_OEOVER_INVPERI 1 +#define RP1_OEOVER_DISABLE 2 +#define RP1_OEOVER_ENABLE 3 -#define RP1_INOVER_PERI 0 -#define RP1_INOVER_INVPERI 1 -#define RP1_INOVER_LOW 2 -#define RP1_INOVER_HIGH 3 +#define RP1_INOVER_PERI 0 +#define RP1_INOVER_INVPERI 1 +#define RP1_INOVER_LOW 2 +#define RP1_INOVER_HIGH 3 -#define RP1_RIO_OUT 0x00 -#define RP1_RIO_OE 0x04 -#define RP1_RIO_IN 0x08 +#define RP1_RIO_OUT 0x00 +#define RP1_RIO_OE 0x04 +#define RP1_RIO_IN 0x08 -#define RP1_PAD_SLEWFAST_MASK 0x00000001 -#define RP1_PAD_SLEWFAST_LSB 0 -#define RP1_PAD_SCHMITT_MASK 0x00000002 -#define RP1_PAD_SCHMITT_LSB 1 -#define RP1_PAD_PULL_MASK 0x0000000c -#define RP1_PAD_PULL_LSB 2 -#define RP1_PAD_DRIVE_MASK 0x00000030 -#define RP1_PAD_DRIVE_LSB 4 -#define RP1_PAD_IN_ENABLE_MASK 0x00000040 -#define RP1_PAD_IN_ENABLE_LSB 6 -#define RP1_PAD_OUT_DISABLE_MASK 0x00000080 -#define RP1_PAD_OUT_DISABLE_LSB 7 +#define RP1_PAD_SLEWFAST_MASK 0x00000001 +#define RP1_PAD_SLEWFAST_LSB 0 +#define RP1_PAD_SCHMITT_MASK 0x00000002 +#define RP1_PAD_SCHMITT_LSB 1 +#define RP1_PAD_PULL_MASK 0x0000000c +#define RP1_PAD_PULL_LSB 2 +#define RP1_PAD_DRIVE_MASK 0x00000030 +#define RP1_PAD_DRIVE_LSB 4 +#define RP1_PAD_IN_ENABLE_MASK 0x00000040 +#define RP1_PAD_IN_ENABLE_LSB 6 +#define RP1_PAD_OUT_DISABLE_MASK 0x00000080 +#define RP1_PAD_OUT_DISABLE_LSB 7 -#define RP1_PAD_DRIVE_2MA 0x00000000 -#define RP1_PAD_DRIVE_4MA 0x00000010 -#define RP1_PAD_DRIVE_8MA 0x00000020 -#define RP1_PAD_DRIVE_12MA 0x00000030 +#define RP1_PAD_DRIVE_2MA 0x00000000 +#define RP1_PAD_DRIVE_4MA 0x00000010 +#define RP1_PAD_DRIVE_8MA 0x00000020 +#define RP1_PAD_DRIVE_12MA 0x00000030 -#define FLD_GET(r, f) (((r) & (f ## _MASK)) >> (f ## _LSB)) -#define FLD_SET(r, f, v) r = (((r) & ~(f ## _MASK)) | ((v) << (f ## _LSB))) +#define FLD_GET(r, f) (((r) & (f##_MASK)) >> (f##_LSB)) +#define FLD_SET(r, f, v) r = (((r) & ~(f##_MASK)) | ((v) << (f##_LSB))) -#define FUNC(f) \ - [func_##f] = #f +#define FUNC(f) [func_##f] = #f #define RP1_MAX_FSEL 8 #define PIN(i, f0, f1, f2, f3, f4, f5, f6, f7, f8) \ [i] = { \ @@ -163,16 +161,10 @@ }, \ } -#define LEGACY_MAP(n, f0, f1, f2, f3, f4, f5) \ - [n] = { \ - func_gpio, \ - func_gpio, \ - func_##f5, \ - func_##f4, \ - func_##f0, \ - func_##f1, \ - func_##f2, \ - func_##f3, \ +#define LEGACY_MAP(n, f0, f1, f2, f3, f4, f5) \ + [n] = { \ + func_gpio, func_gpio, func_##f5, func_##f4, \ + func_##f0, func_##f1, func_##f2, func_##f3, \ } struct rp1_iobank_desc { @@ -290,192 +282,64 @@ struct rp1_pinctrl { const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] = { /* gpio inte ints rio pads */ - { 0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 }, - { 28, 6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 }, + { 0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 }, + { 28, 6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 }, { 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 }, }; /* pins are just named GPIO0..GPIO53 */ #define RP1_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a) static struct pinctrl_pin_desc rp1_gpio_pins[] = { - RP1_GPIO_PIN(0), - RP1_GPIO_PIN(1), - RP1_GPIO_PIN(2), - RP1_GPIO_PIN(3), - RP1_GPIO_PIN(4), - RP1_GPIO_PIN(5), - RP1_GPIO_PIN(6), - RP1_GPIO_PIN(7), - RP1_GPIO_PIN(8), - RP1_GPIO_PIN(9), - RP1_GPIO_PIN(10), - RP1_GPIO_PIN(11), - RP1_GPIO_PIN(12), - RP1_GPIO_PIN(13), - RP1_GPIO_PIN(14), - RP1_GPIO_PIN(15), - RP1_GPIO_PIN(16), - RP1_GPIO_PIN(17), - RP1_GPIO_PIN(18), - RP1_GPIO_PIN(19), - RP1_GPIO_PIN(20), - RP1_GPIO_PIN(21), - RP1_GPIO_PIN(22), - RP1_GPIO_PIN(23), - RP1_GPIO_PIN(24), - RP1_GPIO_PIN(25), - RP1_GPIO_PIN(26), - RP1_GPIO_PIN(27), - RP1_GPIO_PIN(28), - RP1_GPIO_PIN(29), - RP1_GPIO_PIN(30), - RP1_GPIO_PIN(31), - RP1_GPIO_PIN(32), - RP1_GPIO_PIN(33), - RP1_GPIO_PIN(34), - RP1_GPIO_PIN(35), - RP1_GPIO_PIN(36), - RP1_GPIO_PIN(37), - RP1_GPIO_PIN(38), - RP1_GPIO_PIN(39), - RP1_GPIO_PIN(40), - RP1_GPIO_PIN(41), - RP1_GPIO_PIN(42), - RP1_GPIO_PIN(43), - RP1_GPIO_PIN(44), - RP1_GPIO_PIN(45), - RP1_GPIO_PIN(46), - RP1_GPIO_PIN(47), - RP1_GPIO_PIN(48), - RP1_GPIO_PIN(49), - RP1_GPIO_PIN(50), - RP1_GPIO_PIN(51), - RP1_GPIO_PIN(52), - RP1_GPIO_PIN(53), + RP1_GPIO_PIN(0), RP1_GPIO_PIN(1), RP1_GPIO_PIN(2), RP1_GPIO_PIN(3), + RP1_GPIO_PIN(4), RP1_GPIO_PIN(5), RP1_GPIO_PIN(6), RP1_GPIO_PIN(7), + RP1_GPIO_PIN(8), RP1_GPIO_PIN(9), RP1_GPIO_PIN(10), RP1_GPIO_PIN(11), + RP1_GPIO_PIN(12), RP1_GPIO_PIN(13), RP1_GPIO_PIN(14), RP1_GPIO_PIN(15), + RP1_GPIO_PIN(16), RP1_GPIO_PIN(17), RP1_GPIO_PIN(18), RP1_GPIO_PIN(19), + RP1_GPIO_PIN(20), RP1_GPIO_PIN(21), RP1_GPIO_PIN(22), RP1_GPIO_PIN(23), + RP1_GPIO_PIN(24), RP1_GPIO_PIN(25), RP1_GPIO_PIN(26), RP1_GPIO_PIN(27), + RP1_GPIO_PIN(28), RP1_GPIO_PIN(29), RP1_GPIO_PIN(30), RP1_GPIO_PIN(31), + RP1_GPIO_PIN(32), RP1_GPIO_PIN(33), RP1_GPIO_PIN(34), RP1_GPIO_PIN(35), + RP1_GPIO_PIN(36), RP1_GPIO_PIN(37), RP1_GPIO_PIN(38), RP1_GPIO_PIN(39), + RP1_GPIO_PIN(40), RP1_GPIO_PIN(41), RP1_GPIO_PIN(42), RP1_GPIO_PIN(43), + RP1_GPIO_PIN(44), RP1_GPIO_PIN(45), RP1_GPIO_PIN(46), RP1_GPIO_PIN(47), + RP1_GPIO_PIN(48), RP1_GPIO_PIN(49), RP1_GPIO_PIN(50), RP1_GPIO_PIN(51), + RP1_GPIO_PIN(52), RP1_GPIO_PIN(53), }; /* one pin per group */ -static const char * const rp1_gpio_groups[] = { - "gpio0", - "gpio1", - "gpio2", - "gpio3", - "gpio4", - "gpio5", - "gpio6", - "gpio7", - "gpio8", - "gpio9", - "gpio10", - "gpio11", - "gpio12", - "gpio13", - "gpio14", - "gpio15", - "gpio16", - "gpio17", - "gpio18", - "gpio19", - "gpio20", - "gpio21", - "gpio22", - "gpio23", - "gpio24", - "gpio25", - "gpio26", - "gpio27", - "gpio28", - "gpio29", - "gpio30", - "gpio31", - "gpio32", - "gpio33", - "gpio34", - "gpio35", - "gpio36", - "gpio37", - "gpio38", - "gpio39", - "gpio40", - "gpio41", - "gpio42", - "gpio43", - "gpio44", - "gpio45", - "gpio46", - "gpio47", - "gpio48", - "gpio49", - "gpio50", - "gpio51", - "gpio52", - "gpio53", +static const char *const rp1_gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", + "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", + "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", + "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", + "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", + "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", + "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", + "gpio49", "gpio50", "gpio51", "gpio52", "gpio53", }; -static const char * const rp1_func_names[] = { - FUNC(alt0), - FUNC(alt1), - FUNC(alt2), - FUNC(alt3), - FUNC(alt4), - FUNC(gpio), - FUNC(alt6), - FUNC(alt7), - FUNC(alt8), - FUNC(none), - FUNC(aaud), - FUNC(dcd0), - FUNC(dpi), - FUNC(dsi0_te_ext), - FUNC(dsi1_te_ext), - FUNC(dsr0), - FUNC(dtr0), - FUNC(gpclk0), - FUNC(gpclk1), - FUNC(gpclk2), - FUNC(gpclk3), - FUNC(gpclk4), - FUNC(gpclk5), - FUNC(i2c0), - FUNC(i2c1), - FUNC(i2c2), - FUNC(i2c3), - FUNC(i2c4), - FUNC(i2c5), - FUNC(i2c6), - FUNC(i2s0), - FUNC(i2s1), - FUNC(i2s2), - FUNC(ir), - FUNC(mic), - FUNC(pcie_clkreq_n), - FUNC(pio), - FUNC(proc_rio), - FUNC(pwm0), - FUNC(pwm1), - FUNC(ri0), - FUNC(sd0), - FUNC(sd1), - FUNC(spi0), - FUNC(spi1), - FUNC(spi2), - FUNC(spi3), - FUNC(spi4), - FUNC(spi5), - FUNC(spi6), - FUNC(spi7), - FUNC(spi8), - FUNC(uart0), - FUNC(uart1), - FUNC(uart2), - FUNC(uart3), - FUNC(uart4), - FUNC(uart5), - FUNC(vbus0), - FUNC(vbus1), - FUNC(vbus2), - FUNC(vbus3), - [func_invalid] = "?" +static const char *const rp1_func_names[] = { + FUNC(alt0), FUNC(alt1), FUNC(alt2), + FUNC(alt3), FUNC(alt4), FUNC(gpio), + FUNC(alt6), FUNC(alt7), FUNC(alt8), + FUNC(none), FUNC(aaud), FUNC(dcd0), + FUNC(dpi), FUNC(dsi0_te_ext), FUNC(dsi1_te_ext), + FUNC(dsr0), FUNC(dtr0), FUNC(gpclk0), + FUNC(gpclk1), FUNC(gpclk2), FUNC(gpclk3), + FUNC(gpclk4), FUNC(gpclk5), FUNC(i2c0), + FUNC(i2c1), FUNC(i2c2), FUNC(i2c3), + FUNC(i2c4), FUNC(i2c5), FUNC(i2c6), + FUNC(i2s0), FUNC(i2s1), FUNC(i2s2), + FUNC(ir), FUNC(mic), FUNC(pcie_clkreq_n), + FUNC(pio), FUNC(proc_rio), FUNC(pwm0), + FUNC(pwm1), FUNC(ri0), FUNC(sd0), + FUNC(sd1), FUNC(spi0), FUNC(spi1), + FUNC(spi2), FUNC(spi3), FUNC(spi4), + FUNC(spi5), FUNC(spi6), FUNC(spi7), + FUNC(spi8), FUNC(uart0), FUNC(uart1), + FUNC(uart2), FUNC(uart3), FUNC(uart4), + FUNC(uart5), FUNC(vbus0), FUNC(vbus1), + FUNC(vbus2), FUNC(vbus3), [func_invalid] = "?" }; static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] = { @@ -566,7 +430,7 @@ static const u8 legacy_fsel_map[][8] = { LEGACY_MAP(27, sd0, _, dpi, _, _, _), }; -static const char * const irq_type_names[] = { +static const char *const irq_type_names[] = { [IRQ_TYPE_NONE] = "none", [IRQ_TYPE_EDGE_RISING] = "edge-rising", [IRQ_TYPE_EDGE_FALLING] = "edge-falling", @@ -577,13 +441,17 @@ static const char * const irq_type_names[] = { static bool persist_gpio_outputs = true; module_param(persist_gpio_outputs, bool, 0644); -MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed"); +MODULE_PARM_DESC(persist_gpio_outputs, + "Enable GPIO_OUT persistence when pin is freed"); static bool pace_pin_updates = true; module_param(pace_pin_updates, bool, 0644); -MODULE_PARM_DESC(pace_pin_updates, "Update pin states with guaranteed monotonicity if PCIe ASPM is enabled"); +MODULE_PARM_DESC( + pace_pin_updates, + "Update pin states with guaranteed monotonicity if PCIe ASPM is enabled"); -static inline void rp1_pin_writel(u32 val, void __iomem *dummy, void __iomem *reg) +static inline void rp1_pin_writel(u32 val, void __iomem *dummy, + void __iomem *reg) { unsigned long flags; @@ -615,9 +483,8 @@ static inline u32 rp1_pin_readl(const void __iomem *ioaddr) return readl(ioaddr); } -static int rp1_pinconf_set(struct pinctrl_dev *pctldev, - unsigned int offset, unsigned long *configs, - unsigned int num_configs); +static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, + unsigned long *configs, unsigned int num_configs); static struct rp1_pin_info *rp1_get_pin(struct gpio_chip *chip, unsigned int offset) @@ -696,14 +563,16 @@ static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel) static int rp1_get_dir(struct rp1_pin_info *pin) { return !(rp1_pin_readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ? - RP1_DIR_INPUT : RP1_DIR_OUTPUT; + RP1_DIR_INPUT : + RP1_DIR_OUTPUT; } static void rp1_set_dir(struct rp1_pin_info *pin, bool is_input) { int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET; - rp1_pin_writel(1 << pin->offset, pin->dummy, pin->rio + RP1_RIO_OE + offset); + rp1_pin_writel(1 << pin->offset, pin->dummy, + pin->rio + RP1_RIO_OE + offset); } static int rp1_get_value(struct rp1_pin_info *pin) @@ -715,7 +584,8 @@ static void rp1_set_value(struct rp1_pin_info *pin, int value) { /* Assume the pin is already an output */ rp1_pin_writel(1 << pin->offset, pin->dummy, - pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); + pin->rio + RP1_RIO_OUT + + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); } static int rp1_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -749,9 +619,8 @@ static int rp1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) fsel = rp1_get_fsel(pin); if (fsel != RP1_FSEL_GPIO) return -EINVAL; - return (rp1_get_dir(pin) == RP1_DIR_OUTPUT) ? - GPIO_LINE_DIRECTION_OUT : - GPIO_LINE_DIRECTION_IN; + return (rp1_get_dir(pin) == RP1_DIR_OUTPUT) ? GPIO_LINE_DIRECTION_OUT : + GPIO_LINE_DIRECTION_IN; } static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned offset) @@ -785,7 +654,7 @@ static int rp1_gpio_set_config(struct gpio_chip *gc, unsigned offset, unsigned long configs[] = { config }; return rp1_pinconf_set(pc->pctl_dev, offset, configs, - ARRAY_SIZE(configs)); + ARRAY_SIZE(configs)); } static const struct gpio_chip rp1_gpio_chip = { @@ -825,12 +694,13 @@ static void rp1_gpio_irq_handler(struct irq_desc *desc) ints = readl(pc->gpio_base + bank->ints_offset); for_each_set_bit(b, &ints, 32) { - struct rp1_pin_info *pin = rp1_get_pin(chip, bank->min_gpio + b); + struct rp1_pin_info *pin = + rp1_get_pin(chip, bank->min_gpio + b); writel(RP1_GPIO_CTRL_IRQRESET, pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); generic_handle_irq(irq_find_mapping(pc->gpio_chip.irq.domain, - bank->min_gpio + b)); + bank->min_gpio + b)); } chained_irq_exit(host_chip, desc); @@ -897,7 +767,7 @@ static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type) pin->gpio + RP1_CLR_OFFSET + RP1_GPIO_CTRL); /* Clear any latched events */ writel(RP1_GPIO_CTRL_IRQRESET, - pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); + pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); /* Enable the events that are needed */ writel(irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW, pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); @@ -938,10 +808,12 @@ static void rp1_gpio_irq_ack(struct irq_data *data) struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); /* Clear any latched events */ - writel(RP1_GPIO_CTRL_IRQRESET, pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); + writel(RP1_GPIO_CTRL_IRQRESET, + pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); } -static int rp1_gpio_irq_set_affinity(struct irq_data *data, const struct cpumask *dest, bool force) +static int rp1_gpio_irq_set_affinity(struct irq_data *data, + const struct cpumask *dest, bool force) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); struct rp1_pinctrl *pc = gpiochip_get_data(chip); @@ -959,7 +831,8 @@ static int rp1_gpio_irq_set_affinity(struct irq_data *data, const struct cpumask } if (parent_data && parent_data->chip->irq_set_affinity) - return parent_data->chip->irq_set_affinity(parent_data, dest, force); + return parent_data->chip->irq_set_affinity(parent_data, dest, + force); return -EINVAL; } @@ -999,8 +872,7 @@ static enum funcs rp1_get_fsel_func(unsigned pin, unsigned fsel) } static int rp1_pctl_get_group_pins(struct pinctrl_dev *pctldev, - unsigned selector, - const unsigned **pins, + unsigned selector, const unsigned **pins, unsigned *num_pins) { *pins = &rp1_gpio_pins[selector].number; @@ -1010,8 +882,7 @@ static int rp1_pctl_get_group_pins(struct pinctrl_dev *pctldev, } static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, - unsigned offset) + struct seq_file *s, unsigned offset) { struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); struct gpio_chip *chip = &pc->gpio_chip; @@ -1023,8 +894,7 @@ static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, "function %s (%s) in %s; irq %d (%s)", rp1_func_names[fsel], rp1_func_names[func], - value ? "hi" : "lo", - irq, irq_type_names[pin->irq_type]); + value ? "hi" : "lo", irq, irq_type_names[pin->irq_type]); } static void rp1_pctl_dt_free_map(struct pinctrl_dev *pctldev, @@ -1057,14 +927,14 @@ static int rp1_pctl_legacy_map_func(struct rp1_pinctrl *pc, } else if (fnum < 2) { func = func_gpio; } else { - dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", - np, pin); + dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", np, pin); return -EINVAL; } if (func == func_invalid) { - dev_err(pc->dev, "%pOF: brcm,function %d not supported on pin %d\n", - np, fnum, pin); + dev_err(pc->dev, + "%pOF: brcm,function %d not supported on pin %d\n", np, + fnum, pin); } map->type = PIN_MAP_TYPE_MUX_GROUP; @@ -1133,7 +1003,8 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, pins = of_find_property(np, "brcm,pins", NULL); if (!pins) /* Assume generic bindings in this node */ - return pinconf_generic_dt_node_to_map_all(pctldev, np, map, num_maps); + return pinconf_generic_dt_node_to_map_all(pctldev, np, map, + num_maps); funcs = of_find_property(np, "brcm,function", NULL); if (!funcs) @@ -1141,7 +1012,8 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, pulls = of_find_property(np, "brcm,pull", NULL); if (!pulls) - pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); + pinconf_generic_parse_dt_config(np, pctldev, &configs, + &num_configs); if (!function && !funcs && !num_configs && !pulls) { dev_err(pc->dev, @@ -1156,14 +1028,13 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, if (num_funcs > 1 && num_funcs != num_pins) { dev_err(pc->dev, - "%pOF: brcm,function must have 1 or %d entries\n", - np, num_pins); + "%pOF: brcm,function must have 1 or %d entries\n", np, + num_pins); return -EINVAL; } if (num_pulls > 1 && num_pulls != num_pins) { - dev_err(pc->dev, - "%pOF: brcm,pull must have 1 or %d entries\n", + dev_err(pc->dev, "%pOF: brcm,pull must have 1 or %d entries\n", np, num_pins); return -EINVAL; } @@ -1185,37 +1056,35 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, if (err) goto out; if (num_funcs) { - err = of_property_read_u32_index(np, "brcm,function", - (num_funcs > 1) ? i : 0, - &func); + err = of_property_read_u32_index( + np, "brcm,function", (num_funcs > 1) ? i : 0, + &func); if (err) goto out; - err = rp1_pctl_legacy_map_func(pc, np, pin, func, - maps, num_maps); + err = rp1_pctl_legacy_map_func(pc, np, pin, func, maps, + num_maps); } else if (function) { - err = pinctrl_utils_add_map_mux(pctldev, &maps, - &reserved_maps, num_maps, - rp1_gpio_groups[pin], - function); + err = pinctrl_utils_add_map_mux( + pctldev, &maps, &reserved_maps, num_maps, + rp1_gpio_groups[pin], function); } if (err) goto out; if (num_pulls) { - err = of_property_read_u32_index(np, "brcm,pull", - (num_pulls > 1) ? i : 0, - &pull); + err = of_property_read_u32_index( + np, "brcm,pull", (num_pulls > 1) ? i : 0, + &pull); if (err) goto out; - err = rp1_pctl_legacy_map_pull(pc, np, pin, pull, - maps, num_maps); + err = rp1_pctl_legacy_map_pull(pc, np, pin, pull, maps, + num_maps); } else if (num_configs) { - err = pinctrl_utils_add_map_configs(pctldev, &maps, - &reserved_maps, num_maps, - rp1_gpio_groups[pin], - configs, num_configs, - PIN_MAP_TYPE_CONFIGS_PIN); + err = pinctrl_utils_add_map_configs( + pctldev, &maps, &reserved_maps, num_maps, + rp1_gpio_groups[pin], configs, num_configs, + PIN_MAP_TYPE_CONFIGS_PIN); } if (err) @@ -1268,8 +1137,8 @@ static const char *rp1_pmx_get_function_name(struct pinctrl_dev *pctldev, static int rp1_pmx_get_function_groups(struct pinctrl_dev *pctldev, unsigned selector, - const char * const **groups, - unsigned * const num_groups) + const char *const **groups, + unsigned *const num_groups) { /* every pin can do every function */ *groups = rp1_gpio_groups; @@ -1315,8 +1184,7 @@ static void rp1_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, static int rp1_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, - unsigned offset, - bool input) + unsigned offset, bool input) { struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); @@ -1470,14 +1338,17 @@ static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned offset, } break; case PIN_CONFIG_BIAS_DISABLE: - arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_OFF << RP1_PAD_PULL_LSB)); + arg = ((padctrl & RP1_PAD_PULL_MASK) == + (RP1_PUD_OFF << RP1_PAD_PULL_LSB)); break; case PIN_CONFIG_BIAS_PULL_DOWN: - arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_DOWN << RP1_PAD_PULL_LSB)); + arg = ((padctrl & RP1_PAD_PULL_MASK) == + (RP1_PUD_DOWN << RP1_PAD_PULL_LSB)); break; case PIN_CONFIG_BIAS_PULL_UP: - arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_UP << RP1_PAD_PULL_LSB)); + arg = ((padctrl & RP1_PAD_PULL_MASK) == + (RP1_PUD_UP << RP1_PAD_PULL_LSB)); break; default: return -ENOTSUPP; @@ -1514,100 +1385,7 @@ static const struct of_device_id rp1_pinctrl_match[] = { .compatible = "raspberrypi,rp1-gpio", .data = &rp1_pinconf_ops, }, - {}, -}; -MODULE_DEVICE_TABLE(of, rp1_pinctrl_match); - -static struct rp1_pinctrl rp1_pinctrl_data = {}; - -static const struct regmap_range rp1_gpio_reg_ranges[] = { - /* BANK 0 */ - regmap_reg_range(0x2004, 0x20dc), - regmap_reg_range(0x3004, 0x30dc), - regmap_reg_range(0x0004, 0x00dc), - regmap_reg_range(0x0124, 0x0124), - regmap_reg_range(0x211c, 0x211c), - regmap_reg_range(0x311c, 0x311c), - /* BANK 1 */ - regmap_reg_range(0x6004, 0x602c), - regmap_reg_range(0x7004, 0x702c), - regmap_reg_range(0x4004, 0x402c), - regmap_reg_range(0x4124, 0x4124), - regmap_reg_range(0x611c, 0x611c), - regmap_reg_range(0x711c, 0x711c), - /* BANK 2 */ - regmap_reg_range(0xa004, 0xa09c), - regmap_reg_range(0xb004, 0xb09c), - regmap_reg_range(0x8004, 0x809c), - regmap_reg_range(0x8124, 0x8124), - regmap_reg_range(0xa11c, 0xa11c), - regmap_reg_range(0xb11c, 0xb11c), -}; - -static const struct regmap_range rp1_rio_reg_ranges[] = { - /* BANK 0 */ - regmap_reg_range(0x2000, 0x2004), - regmap_reg_range(0x3000, 0x3004), - regmap_reg_range(0x0004, 0x0008), - /* BANK 1 */ - regmap_reg_range(0x6000, 0x6004), - regmap_reg_range(0x7000, 0x7004), - regmap_reg_range(0x4004, 0x4008), - /* BANK 2 */ - regmap_reg_range(0xa000, 0xa004), - regmap_reg_range(0xb000, 0xb004), - regmap_reg_range(0x8004, 0x8008), -}; - -static const struct regmap_range rp1_pads_reg_ranges[] = { - /* BANK 0 */ - regmap_reg_range(0x0004, 0x0070), - /* BANK 1 */ - regmap_reg_range(0x4004, 0x4018), - /* BANK 2 */ - regmap_reg_range(0x8004, 0x8050), -}; - -static const struct regmap_access_table rp1_gpio_reg_table = { - .yes_ranges = rp1_gpio_reg_ranges, - .n_yes_ranges = ARRAY_SIZE(rp1_gpio_reg_ranges), -}; - -static const struct regmap_access_table rp1_rio_reg_table = { - .yes_ranges = rp1_rio_reg_ranges, - .n_yes_ranges = ARRAY_SIZE(rp1_rio_reg_ranges), -}; - -static const struct regmap_access_table rp1_pads_reg_table = { - .yes_ranges = rp1_pads_reg_ranges, - .n_yes_ranges = ARRAY_SIZE(rp1_pads_reg_ranges), -}; - -static const struct regmap_config rp1_pinctrl_gpio_regmap_cfg = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .rd_table = &rp1_gpio_reg_table, - .name = "rp1-gpio", - .max_register = 0xb11c, -}; - -static const struct regmap_config rp1_pinctrl_rio_regmap_cfg = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .rd_table = &rp1_rio_reg_table, - .name = "rp1-rio", - .max_register = 0xb004, -}; - -static const struct regmap_config rp1_pinctrl_pads_regmap_cfg = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .rd_table = &rp1_pads_reg_table, - .name = "rp1-pads", - .max_register = 0x8050, + {} }; static inline void __iomem *devm_auto_iomap(struct platform_device *pdev, @@ -1662,32 +1440,42 @@ static int rp1_pinctrl_probe(struct platform_device *pdev) pc->gpio_chip = rp1_gpio_chip; pc->gpio_chip.parent = dev; - pc->gpio_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pc->gpio_base)) - return dev_err_probe(dev, PTR_ERR(pc->gpio_base), "could not get GPIO IO memory\n"); - - pc->rio_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(pc->rio_base)) - return dev_err_probe(dev, PTR_ERR(pc->rio_base), "could not get RIO IO memory\n"); - - pc->pads_base = devm_platform_ioremap_resource(pdev, 2); - if (IS_ERR(pc->pads_base)) - return dev_err_probe(dev, PTR_ERR(pc->pads_base), "could not get PADS IO memory\n"); - - gpio_regmap = devm_regmap_init_mmio(dev, pc->gpio_base, - &rp1_pinctrl_gpio_regmap_cfg); - if (IS_ERR(gpio_regmap)) - return dev_err_probe(dev, PTR_ERR(gpio_regmap), "could not init GPIO regmap\n"); - - rio_regmap = devm_regmap_init_mmio(dev, pc->rio_base, - &rp1_pinctrl_rio_regmap_cfg); - if (IS_ERR(rio_regmap)) - return dev_err_probe(dev, PTR_ERR(rio_regmap), "could not init RIO regmap\n"); - - pads_regmap = devm_regmap_init_mmio(dev, pc->pads_base, - &rp1_pinctrl_pads_regmap_cfg); - if (IS_ERR(pads_regmap)) - return dev_err_probe(dev, PTR_ERR(pads_regmap), "could not init PADS regmap\n"); + /* + * Workaround for the vagaries of PCIe on BCM2712 + * + * If the link to RP1 is in L1, then the BRCMSTB RC will buffer many + * outbound writes - and generate write responses for them, despite the + * fact that the link is not yet active. This has the effect of compressing + * multiple writes to GPIOs together, destroying any pacing that an application + * may require in the 1-10us range. + * + * The RC Slot Control configuration register is special. It emits a + * MsgD for every write to it, will stall further writes until the message + * goes out on the wire. This can be (ab)used to force CPU stalls when the + * link is inactive, at the cost of a small amount of downstream bandwidth + * and some 200ns of added latency for each write. + * + * Several back-to-back configuration writes are necessary to "fill the pipe", + * otherwise the outbound MAC can consume a pending MMIO write and reorder + * it with respect to the config writes - undoing the intent. + * + * of_iomap() is used directly here as the address overlaps with the RC driver's + * usage. + */ + rp1_node = of_find_node_by_name(NULL, "rp1"); + if (!rp1_node) + dev_err(&pdev->dev, "failed to find RP1 DT node\n"); + else if (pace_pin_updates && + of_device_is_compatible(rp1_node->parent, + "brcm,bcm2712-pcie")) { + pc->dummy_base = of_iomap(rp1_node->parent, 0); + if (IS_ERR(pc->dummy_base)) { + dev_warn( + &pdev->dev, + "could not map bcm2712 root complex registers\n"); + pc->dummy_base = NULL; + } + } for (i = 0; i < RP1_NUM_BANKS; i++) { const struct rp1_iobank_desc *bank = &rp1_iobanks[i]; @@ -1705,10 +1493,11 @@ static int rp1_pinctrl_probe(struct platform_device *pdev) j * sizeof(u32) * 2; pin->inte = pc->gpio_base + bank->inte_offset; pin->ints = pc->gpio_base + bank->ints_offset; - pin->rio = pc->rio_base + bank->rio_offset; - pin->pad = pc->pads_base + bank->pads_offset + - j * sizeof(u32); - pin->dummy = pc->dummy_base ? pc->dummy_base + 0xc0 : NULL; + pin->rio = pc->rio_base + bank->rio_offset; + pin->pad = pc->pads_base + bank->pads_offset + + j * sizeof(u32); + pin->dummy = pc->dummy_base ? pc->dummy_base + 0xc0 : + NULL; } raw_spin_lock_init(&pc->irq_lock[i]); diff --git a/include/linux/gpio/generic.h b/include/linux/gpio/generic.h index ff566dc9c3cb..e3625f4cb933 100644 --- a/include/linux/gpio/generic.h +++ b/include/linux/gpio/generic.h @@ -18,6 +18,7 @@ struct device; #define GPIO_GENERIC_NO_SET_ON_INPUT BIT(6) #define GPIO_GENERIC_PINCTRL_BACKEND BIT(7) /* Call pinctrl direction setters */ #define GPIO_GENERIC_NO_INPUT BIT(8) /* only output */ +#define GPIO_GENERIC_REG_DIRECT BIT(15) /* ignore shadow registers */ /** * struct gpio_generic_chip_config - Generic GPIO chip configuration data |
