diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig index a983458dfd3153..6d901f23997084 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig @@ -168,18 +168,22 @@ CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m @@ -263,18 +267,9 @@ CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_SYNPROXY=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_NFT_DUP_IPV6=m CONFIG_NFT_FIB_IPV6=m @@ -289,22 +284,12 @@ CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_MATCH_SRH=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_SYNPROXY=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_NPT=m CONFIG_NF_TABLES_BRIDGE=m CONFIG_NFT_BRIDGE_REJECT=m CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_802_3=m CONFIG_BRIDGE_EBT_AMONG=m CONFIG_BRIDGE_EBT_ARP=m @@ -1087,6 +1072,7 @@ CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m CONFIG_SND_PISOUND=m CONFIG_SND_DACBERRY400=m +CONFIG_SND_SIMPLE_CARD=m CONFIG_SND_SOC_AD193X_SPI=m CONFIG_SND_SOC_AD193X_I2C=m CONFIG_SND_SOC_ADAU1701=m @@ -1101,7 +1087,6 @@ CONFIG_SND_SOC_TLV320AIC23_I2C=m CONFIG_SND_SOC_WM8804_I2C=m CONFIG_SND_SOC_WM8904=m CONFIG_SND_SOC_WM8960=m -CONFIG_SND_SIMPLE_CARD=m CONFIG_HID_BATTERY_STRENGTH=y CONFIG_HIDRAW=y CONFIG_UHID=m @@ -1347,7 +1332,6 @@ CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_ISL12022=m CONFIG_RTC_DRV_X1205=m CONFIG_RTC_DRV_PCF8523=m -CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_PCF85363=m CONFIG_RTC_DRV_PCF8563=m CONFIG_RTC_DRV_PCF8583=m @@ -1374,6 +1358,7 @@ CONFIG_RTC_DRV_MAX6902=m CONFIG_RTC_DRV_PCF2123=m CONFIG_RTC_DRV_DS3232=m CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_RV3029C2=m CONFIG_DMADEVICES=y CONFIG_DMA_BCM2835=y @@ -1608,7 +1593,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_NHPOLY1305_NEON=m -CONFIG_CRYPTO_SHA1_ARM_NEON=m CONFIG_CRYPTO_AES_ARM_BS=m # CONFIG_CRYPTO_HW is not set CONFIG_PKCS8_PRIVATE_KEY_PARSER=m diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig index ef5a7f71f25112..b03387dc46e527 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig @@ -162,18 +162,22 @@ CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m @@ -257,18 +261,9 @@ CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_SYNPROXY=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_NFT_DUP_IPV6=m CONFIG_NFT_FIB_IPV6=m @@ -283,22 +278,12 @@ CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_MATCH_SRH=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_SYNPROXY=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_NPT=m CONFIG_NF_TABLES_BRIDGE=m CONFIG_NFT_BRIDGE_REJECT=m CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_802_3=m CONFIG_BRIDGE_EBT_AMONG=m CONFIG_BRIDGE_EBT_ARP=m @@ -1079,6 +1064,7 @@ CONFIG_SND_BCM2708_SOC_ALLO_DIGIONE=m CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC=m CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m CONFIG_SND_PISOUND=m +CONFIG_SND_SIMPLE_CARD=m CONFIG_SND_SOC_AD193X_SPI=m CONFIG_SND_SOC_AD193X_I2C=m CONFIG_SND_SOC_ADAU1701=m @@ -1093,7 +1079,6 @@ CONFIG_SND_SOC_TLV320AIC23_I2C=m CONFIG_SND_SOC_WM8804_I2C=m CONFIG_SND_SOC_WM8904=m CONFIG_SND_SOC_WM8960=m -CONFIG_SND_SIMPLE_CARD=m CONFIG_HID_BATTERY_STRENGTH=y CONFIG_HIDRAW=y CONFIG_UHID=m @@ -1339,7 +1324,6 @@ CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_ISL12022=m CONFIG_RTC_DRV_X1205=m CONFIG_RTC_DRV_PCF8523=m -CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_PCF85363=m CONFIG_RTC_DRV_PCF8563=m CONFIG_RTC_DRV_PCF8583=m @@ -1366,6 +1350,7 @@ CONFIG_RTC_DRV_MAX6902=m CONFIG_RTC_DRV_PCF2123=m CONFIG_RTC_DRV_DS3232=m CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_RV3029C2=m CONFIG_DMADEVICES=y CONFIG_DMA_BCM2835=y @@ -1601,7 +1586,6 @@ CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m -CONFIG_CRYPTO_SHA1_ARM=m CONFIG_CRYPTO_AES_ARM=m # CONFIG_CRYPTO_HW is not set CONFIG_PKCS8_PRIVATE_KEY_PARSER=m diff --git a/arch/arm64/boot/dts/broadcom/rp1-common.dtsi b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi new file mode 100644 index 00000000000000..5002a375eb0b2d --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +#include +#include +#include + +pci_ep_bus: pci-ep-bus@1 { + compatible = "simple-bus"; + ranges = <0x00 0x40000000 0x01 0x00 0x00000000 0x00 0x00400000>; + dma-ranges = <0x10 0x00000000 0x43000000 0x10 0x00000000 0x10 0x00000000>; + #address-cells = <2>; + #size-cells = <2>; + + rp1_clocks: clocks@40018000 { + compatible = "raspberrypi,rp1-clocks"; + reg = <0x00 0x40018000 0x0 0x10038>; + #clock-cells = <1>; + clocks = <&clk_rp1_xosc>; + assigned-clocks = <&rp1_clocks RP1_PLL_SYS_CORE>, + <&rp1_clocks RP1_PLL_SYS>, + <&rp1_clocks RP1_PLL_SYS_SEC>, + <&rp1_clocks RP1_CLK_SYS>; + assigned-clock-rates = <1000000000>, // RP1_PLL_SYS_CORE + <200000000>, // RP1_PLL_SYS + <125000000>, // RP1_PLL_SYS_SEC + <200000000>; // RP1_CLK_SYS + }; + + rp1_gpio: pinctrl@400d0000 { + compatible = "raspberrypi,rp1-gpio"; + reg = <0x00 0x400d0000 0x0 0xc000>, + <0x00 0x400e0000 0x0 0xc000>, + <0x00 0x400f0000 0x0 0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, + <1 IRQ_TYPE_LEVEL_HIGH>, + <2 IRQ_TYPE_LEVEL_HIGH>; + }; +}; diff --git a/arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi b/arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi new file mode 100644 index 00000000000000..0ef30d7f1c3521 --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/rp1-nexus.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +rp1_nexus { + compatible = "pci1de4,1"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01 0x00 0x00000000 + 0x02000000 0x00 0x00000000 + 0x0 0x400000>; + interrupt-controller; + #interrupt-cells = <2>; + + #include "rp1-common.dtsi" +}; diff --git a/arch/arm64/configs/bcm2711_defconfig b/arch/arm64/configs/bcm2711_defconfig index e0e913178e76c0..d7f6230da7074f 100644 --- a/arch/arm64/configs/bcm2711_defconfig +++ b/arch/arm64/configs/bcm2711_defconfig @@ -189,18 +189,22 @@ CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m @@ -284,18 +288,9 @@ CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_SYNPROXY=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_NFT_DUP_IPV6=m CONFIG_NFT_FIB_IPV6=m @@ -310,22 +305,12 @@ CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_MATCH_SRH=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_SYNPROXY=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_NPT=m CONFIG_NF_TABLES_BRIDGE=m CONFIG_NFT_BRIDGE_REJECT=m CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_802_3=m CONFIG_BRIDGE_EBT_AMONG=m CONFIG_BRIDGE_EBT_ARP=m @@ -463,6 +448,7 @@ CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y CONFIG_PCIEASPM_POWERSAVE=y CONFIG_PCIE_DPC=y +CONFIG_PCI_DYNAMIC_OF_NODES=y CONFIG_UEVENT_HELPER=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -1188,6 +1174,7 @@ CONFIG_SND_PISOUND=m CONFIG_SND_DACBERRY400=m CONFIG_SND_DESIGNWARE_I2S=m CONFIG_SND_DESIGNWARE_PCM=y +CONFIG_SND_SIMPLE_CARD=m CONFIG_SND_RP1_AUDIO_OUT=m CONFIG_SND_SOC_AD193X_SPI=m CONFIG_SND_SOC_AD193X_I2C=m @@ -1203,7 +1190,6 @@ CONFIG_SND_SOC_TLV320AIC23_I2C=m CONFIG_SND_SOC_WM8804_I2C=m CONFIG_SND_SOC_WM8904=m CONFIG_SND_SOC_WM8960=m -CONFIG_SND_SIMPLE_CARD=m CONFIG_HID_BATTERY_STRENGTH=y CONFIG_HIDRAW=y CONFIG_UHID=m @@ -1454,7 +1440,6 @@ CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_ISL12022=m CONFIG_RTC_DRV_X1205=m CONFIG_RTC_DRV_PCF8523=m -CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_PCF85363=m CONFIG_RTC_DRV_PCF8563=m CONFIG_RTC_DRV_PCF8583=m @@ -1481,6 +1466,7 @@ CONFIG_RTC_DRV_MAX6902=m CONFIG_RTC_DRV_PCF2123=m CONFIG_RTC_DRV_DS3232=m CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_RV3029C2=m CONFIG_DMADEVICES=y CONFIG_DMA_BCM2835=y @@ -1732,8 +1718,6 @@ CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_NHPOLY1305_NEON=m CONFIG_CRYPTO_GHASH_ARM64_CE=m -CONFIG_CRYPTO_SHA1_ARM64_CE=m -CONFIG_CRYPTO_SHA512_ARM64_CE=m CONFIG_CRYPTO_SHA3_ARM64=m CONFIG_CRYPTO_SM3_ARM64_CE=m CONFIG_CRYPTO_AES_ARM64=m diff --git a/arch/arm64/configs/bcm2711_rt_defconfig b/arch/arm64/configs/bcm2711_rt_defconfig index e6fffda85a5d75..e6f5919f277ef9 100644 --- a/arch/arm64/configs/bcm2711_rt_defconfig +++ b/arch/arm64/configs/bcm2711_rt_defconfig @@ -189,18 +189,22 @@ CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m @@ -284,18 +288,9 @@ CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_SYNPROXY=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_NFT_DUP_IPV6=m CONFIG_NFT_FIB_IPV6=m @@ -310,22 +305,12 @@ CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_MATCH_SRH=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_SYNPROXY=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_NPT=m CONFIG_NF_TABLES_BRIDGE=m CONFIG_NFT_BRIDGE_REJECT=m CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_802_3=m CONFIG_BRIDGE_EBT_AMONG=m CONFIG_BRIDGE_EBT_ARP=m @@ -463,6 +448,7 @@ CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y CONFIG_PCIEASPM_POWERSAVE=y CONFIG_PCIE_DPC=y +CONFIG_PCI_DYNAMIC_OF_NODES=y CONFIG_UEVENT_HELPER=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -1187,6 +1173,7 @@ CONFIG_SND_PISOUND=m CONFIG_SND_DACBERRY400=m CONFIG_SND_DESIGNWARE_I2S=m CONFIG_SND_DESIGNWARE_PCM=y +CONFIG_SND_SIMPLE_CARD=m CONFIG_SND_RP1_AUDIO_OUT=m CONFIG_SND_SOC_AD193X_SPI=m CONFIG_SND_SOC_AD193X_I2C=m @@ -1202,7 +1189,6 @@ CONFIG_SND_SOC_TLV320AIC23_I2C=m CONFIG_SND_SOC_WM8804_I2C=m CONFIG_SND_SOC_WM8904=m CONFIG_SND_SOC_WM8960=m -CONFIG_SND_SIMPLE_CARD=m CONFIG_HID_BATTERY_STRENGTH=y CONFIG_HIDRAW=y CONFIG_UHID=m @@ -1452,7 +1438,6 @@ CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_ISL12022=m CONFIG_RTC_DRV_X1205=m CONFIG_RTC_DRV_PCF8523=m -CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_PCF85363=m CONFIG_RTC_DRV_PCF8563=m CONFIG_RTC_DRV_PCF8583=m @@ -1479,6 +1464,7 @@ CONFIG_RTC_DRV_MAX6902=m CONFIG_RTC_DRV_PCF2123=m CONFIG_RTC_DRV_DS3232=m CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_RV3029C2=m CONFIG_DMADEVICES=y CONFIG_DMA_BCM2835=y @@ -1730,8 +1716,6 @@ CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_NHPOLY1305_NEON=m CONFIG_CRYPTO_GHASH_ARM64_CE=m -CONFIG_CRYPTO_SHA1_ARM64_CE=m -CONFIG_CRYPTO_SHA512_ARM64_CE=m CONFIG_CRYPTO_SHA3_ARM64=m CONFIG_CRYPTO_SM3_ARM64_CE=m CONFIG_CRYPTO_AES_ARM64=m diff --git a/arch/arm64/configs/bcm2712_defconfig b/arch/arm64/configs/bcm2712_defconfig index 0d17366c010b01..51c3201431bef0 100644 --- a/arch/arm64/configs/bcm2712_defconfig +++ b/arch/arm64/configs/bcm2712_defconfig @@ -192,18 +192,22 @@ CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m @@ -287,18 +291,9 @@ CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_SYNPROXY=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_NFT_DUP_IPV6=m CONFIG_NFT_FIB_IPV6=m @@ -313,22 +308,12 @@ CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_MATCH_SRH=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_SYNPROXY=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_NPT=m CONFIG_NF_TABLES_BRIDGE=m CONFIG_NFT_BRIDGE_REJECT=m CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_802_3=m CONFIG_BRIDGE_EBT_AMONG=m CONFIG_BRIDGE_EBT_ARP=m @@ -466,6 +451,7 @@ CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y CONFIG_PCIEASPM_POWERSAVE=y CONFIG_PCIE_DPC=y +CONFIG_PCI_DYNAMIC_OF_NODES=y CONFIG_UEVENT_HELPER=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -1190,6 +1176,7 @@ CONFIG_SND_PISOUND=m CONFIG_SND_DACBERRY400=m CONFIG_SND_DESIGNWARE_I2S=m CONFIG_SND_DESIGNWARE_PCM=y +CONFIG_SND_SIMPLE_CARD=m CONFIG_SND_RP1_AUDIO_OUT=m CONFIG_SND_SOC_AD193X_SPI=m CONFIG_SND_SOC_AD193X_I2C=m @@ -1205,7 +1192,6 @@ CONFIG_SND_SOC_TLV320AIC23_I2C=m CONFIG_SND_SOC_WM8804_I2C=m CONFIG_SND_SOC_WM8904=m CONFIG_SND_SOC_WM8960=m -CONFIG_SND_SIMPLE_CARD=m CONFIG_HID_BATTERY_STRENGTH=y CONFIG_HIDRAW=y CONFIG_UHID=m @@ -1456,7 +1442,6 @@ CONFIG_RTC_DRV_ISL1208=m CONFIG_RTC_DRV_ISL12022=m CONFIG_RTC_DRV_X1205=m CONFIG_RTC_DRV_PCF8523=m -CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_PCF85363=m CONFIG_RTC_DRV_PCF8563=m CONFIG_RTC_DRV_PCF8583=m @@ -1483,6 +1468,7 @@ CONFIG_RTC_DRV_MAX6902=m CONFIG_RTC_DRV_PCF2123=m CONFIG_RTC_DRV_DS3232=m CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF85063=m CONFIG_RTC_DRV_RV3029C2=m CONFIG_DMADEVICES=y CONFIG_DMA_BCM2835=y @@ -1734,8 +1720,6 @@ CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_NHPOLY1305_NEON=m CONFIG_CRYPTO_GHASH_ARM64_CE=m -CONFIG_CRYPTO_SHA1_ARM64_CE=m -CONFIG_CRYPTO_SHA512_ARM64_CE=m CONFIG_CRYPTO_SHA3_ARM64=m CONFIG_CRYPTO_SM3_ARM64_CE=m CONFIG_CRYPTO_AES_ARM64=m diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 0b457145d1658e..8cd6e5bdfb5b16 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -89,7 +89,7 @@ config COMMON_CLK_RK808 config COMMON_CLK_RP1 tristate "Raspberry Pi RP1-based clock support" - depends on MISC_RP1 || COMPILE_TEST + depends on MISC_RP1 || MFD_RP1 || COMPILE_TEST default MISC_RP1 help Enable common clock framework support for Raspberry Pi RP1. diff --git a/drivers/clk/clk-rp1.c b/drivers/clk/clk-rp1.c index afff90d487341c..a04d218dd3846a 100644 --- a/drivers/clk/clk-rp1.c +++ b/drivers/clk/clk-rp1.c @@ -1,203 +1,179 @@ -// 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 #include -#include +#include +#include +#include +#include +#include #include #include +#include #include -#include - -#include - -#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_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_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) +#include +#include + +#include + +#include + +#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_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_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 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_SYS_CTRL 0x00014 +#define CLK_SYS_DIV_INT 0x00018 +#define CLK_SYS_SEL 0x00020 + +#define CLK_SLOW_SYS_CTRL 0x00024 +#define CLK_SLOW_SYS_DIV_INT 0x00028 +#define CLK_SLOW_SYS_SEL 0x00030 + +#define CLK_DMA_CTRL 0x00044 +#define CLK_DMA_DIV_INT 0x00048 +#define CLK_DMA_SEL 0x00050 + +#define CLK_UART_CTRL 0x00054 +#define CLK_UART_DIV_INT 0x00058 +#define CLK_UART_SEL 0x00060 + +#define CLK_ETH_CTRL 0x00064 +#define CLK_ETH_DIV_INT 0x00068 +#define CLK_ETH_SEL 0x00070 + +#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_CTRL 0x00084 +#define CLK_PWM1_DIV_INT 0x00088 +#define CLK_PWM1_DIV_FRAC 0x0008c +#define CLK_PWM1_SEL 0x00090 + +#define CLK_AUDIO_IN_CTRL 0x00094 +#define CLK_AUDIO_IN_DIV_INT 0x00098 +#define CLK_AUDIO_IN_SEL 0x000a0 + +#define CLK_AUDIO_OUT_CTRL 0x000a4 +#define CLK_AUDIO_OUT_DIV_INT 0x000a8 +#define CLK_AUDIO_OUT_SEL 0x000b0 + +#define CLK_I2S_CTRL 0x000b4 +#define CLK_I2S_DIV_INT 0x000b8 +#define CLK_I2S_SEL 0x000c0 + +#define CLK_MIPI0_CFG_CTRL 0x000c4 +#define CLK_MIPI0_CFG_DIV_INT 0x000c8 +#define CLK_MIPI0_CFG_SEL 0x000d0 + +#define CLK_MIPI1_CFG_CTRL 0x000d4 +#define CLK_MIPI1_CFG_DIV_INT 0x000d8 +#define CLK_MIPI1_CFG_SEL 0x000e0 + +#define CLK_PCIE_AUX_CTRL 0x000e4 +#define CLK_PCIE_AUX_DIV_INT 0x000e8 +#define CLK_PCIE_AUX_SEL 0x000f0 + +#define CLK_USBH0_MICROFRAME_CTRL 0x000f4 +#define CLK_USBH0_MICROFRAME_DIV_INT 0x000f8 +#define CLK_USBH0_MICROFRAME_SEL 0x00100 + +#define CLK_USBH1_MICROFRAME_CTRL 0x00104 +#define CLK_USBH1_MICROFRAME_DIV_INT 0x00108 +#define CLK_USBH1_MICROFRAME_SEL 0x00110 + +#define CLK_USBH0_SUSPEND_CTRL 0x00114 +#define CLK_USBH0_SUSPEND_DIV_INT 0x00118 +#define CLK_USBH0_SUSPEND_SEL 0x00120 + +#define CLK_USBH1_SUSPEND_CTRL 0x00124 +#define CLK_USBH1_SUSPEND_DIV_INT 0x00128 +#define CLK_USBH1_SUSPEND_SEL 0x00130 + +#define CLK_ETH_TSU_CTRL 0x00134 +#define CLK_ETH_TSU_DIV_INT 0x00138 +#define CLK_ETH_TSU_SEL 0x00140 + +#define CLK_ADC_CTRL 0x00144 +#define CLK_ADC_DIV_INT 0x00148 +#define CLK_ADC_SEL 0x00150 + +#define CLK_SDIO_TIMER_CTRL 0x00154 +#define CLK_SDIO_TIMER_DIV_INT 0x00158 +#define CLK_SDIO_TIMER_SEL 0x00160 + +#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_CTRL 0x00174 +#define CLK_GP0_DIV_INT 0x00178 +#define CLK_GP0_DIV_FRAC 0x0017c +#define CLK_GP0_SEL 0x00180 + +#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_CTRL 0x00194 +#define CLK_GP2_DIV_INT 0x00198 +#define CLK_GP2_DIV_FRAC 0x0019c +#define CLK_GP2_SEL 0x001a0 + +#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_CTRL 0x001b4 +#define CLK_GP4_DIV_INT 0x001b8 +#define CLK_GP4_DIV_FRAC 0x001bc +#define CLK_GP4_SEL 0x001c0 + +#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_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 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)) @@ -220,21 +196,25 @@ #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 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_REFDIV_SHIFT 0 #define PLL_PWR_PD BIT(0) #define PLL_PWR_DACPD BIT(1) @@ -242,7 +222,7 @@ #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_MASK 0x0000003f #define PLL_SEC_RST BIT(16) #define PLL_SEC_IMPL BIT(31) @@ -258,30 +238,45 @@ /* Clock fields for all clocks */ #define CLK_CTRL_ENABLE BIT(11) -#define CLK_CTRL_AUXSRC_MASK GENMASK(9, 5) +#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 LOCK_TIMEOUT_US 100000 -#define LOCK_POLL_DELAY_US 5 +#define KHz 1000 +#define MHz (KHz * KHz) +#define LOCK_TIMEOUT_NS 100000000 +#define FC_TIMEOUT_NS 100000000 -#define MAX_CLK_PARENTS 16 +#define MAX_CLK_PARENTS 16 + +#define MEASURE_CLOCK_RATE +const char * const fc0_ref_clk_name = "clk_slow_sys"; + +#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 PLL_DIV_INVALID 19 /* * Secondary PLL channel output divider table. - * Divider values range from 8 to 19, where - * 19 means invalid. + * Divider values range from 8 to 19. + * Invalid values default to 19 */ static const struct clk_div_table pll_sec_div_table[] = { - { 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 }, + { 0x00, 19 }, + { 0x01, 19 }, + { 0x02, 19 }, + { 0x03, 19 }, + { 0x04, 19 }, + { 0x05, 19 }, + { 0x06, 19 }, + { 0x07, 19 }, { 0x08, 8 }, { 0x09, 9 }, { 0x0a, 10 }, @@ -293,26 +288,25 @@ static const struct clk_div_table pll_sec_div_table[] = { { 0x10, 16 }, { 0x11, 17 }, { 0x12, 18 }, - { 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 }, + { 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 }, { 0 } }; struct rp1_clockman { struct device *dev; void __iomem *regs; - struct regmap *regmap; spinlock_t regs_lock; /* spinlock for all clocks */ /* Must be last */ @@ -320,33 +314,47 @@ 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; @@ -358,34 +366,151 @@ struct rp1_clock_data { u32 fc0_src; }; -struct rp1_clk_desc { - struct clk_hw *(*clk_register)(struct rp1_clockman *clockman, - struct rp1_clk_desc *desc); - const void *data; +struct rp1_pll_core { 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; + struct rp1_clockman *clockman; + const struct rp1_pll_data *data; + unsigned long cached_rate; }; +struct rp1_pll_ph { + struct clk_hw hw; + struct rp1_clockman *clockman; + const struct rp1_pll_ph_data *data; +}; + +struct rp1_clock { + struct clk_hw hw; + struct rp1_clockman *clockman; + const struct rp1_clock_data *data; + unsigned long cached_rate; +}; + +struct rp1_varsrc { + struct clk_hw hw; + struct rp1_clockman *clockman; + unsigned long rate; +}; + +struct rp1_clk_change { + struct clk_hw *hw; + unsigned long new_rate; +}; + +struct rp1_clk_change rp1_clk_chg_tree[3]; + +static struct clk_hw *clk_xosc; +static struct clk_hw *clk_audio; +static struct clk_hw *clk_i2s; + +static void rp1_debugfs_regset(struct rp1_clockman *clockman, u32 base, + const struct debugfs_reg32 *regs, + size_t nregs, struct dentry *dentry) +{ + struct debugfs_regset32 *regset; + + regset = devm_kzalloc(clockman->dev, sizeof(*regset), GFP_KERNEL); + if (!regset) + return; + + regset->regs = regs; + regset->nregs = nregs; + regset->base = clockman->regs + base; + + debugfs_create_regset32("regdump", 0444, dentry, regset); +} + +static inline u32 set_register_field(u32 reg, u32 val, u32 mask, u32 shift) +{ + reg &= ~mask; + reg |= (val << shift) & mask; + return reg; +} + static inline void clockman_write(struct rp1_clockman *clockman, u32 reg, u32 val) { - regmap_write(clockman->regmap, reg, val); + writel(val, clockman->regs + reg); } static inline u32 clockman_read(struct rp1_clockman *clockman, u32 reg) { - u32 val; + return readl(clockman->regs + reg); +} + +#ifdef MEASURE_CLOCK_RATE +static unsigned long clockman_measure_clock(struct rp1_clockman *clockman, + const char *clk_name, + unsigned int fc0_src) +{ + 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; - regmap_read(clockman->regmap, reg, &val); + fc_offset = fc_idx * FC_SIZE; - return 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_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); + + /* 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); + + return result; } +#endif static int rp1_pll_core_is_on(struct clk_hw *hw) { - struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, 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); @@ -395,11 +520,11 @@ static int rp1_pll_core_is_on(struct clk_hw *hw) static int rp1_pll_core_on(struct clk_hw *hw) { - struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; - u32 fbdiv_frac, val; - int ret; + u32 fbdiv_frac; + ktime_t timeout; spin_lock(&clockman->regs_lock); @@ -408,7 +533,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, PLL_CS_REFDIV_MASK); + clockman_write(clockman, data->cs_reg, 1 << PLL_CS_REFDIV_SHIFT); } /* Come out of reset. */ @@ -417,19 +542,22 @@ static int rp1_pll_core_on(struct clk_hw *hw) spin_unlock(&clockman->regs_lock); /* Wait for the PLL to lock. */ - 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)); + 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(); + } - return ret; + return 0; } static void rp1_pll_core_off(struct clk_hw *hw) { - struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; @@ -443,14 +571,13 @@ static inline unsigned long get_pll_core_divider(struct clk_hw *hw, unsigned long parent_rate, u32 *div_int, u32 *div_frac) { - u32 fbdiv_int, fbdiv_frac; unsigned long calc_rate; - u64 shifted_fbdiv_int; + u32 fbdiv_int, fbdiv_frac; u64 div_fp64; /* 32.32 fixed point fraction. */ /* Factor of reference clock to VCO frequency. */ div_fp64 = (u64)(rate) << 32; - div_fp64 = DIV_ROUND_CLOSEST_ULL(div_fp64, parent_rate); + div_fp64 = DIV_U64_NEAREST(div_fp64, parent_rate); /* Round the fractional component at 24 bits. */ div_fp64 += 1 << (32 - 24 - 1); @@ -458,10 +585,8 @@ static inline unsigned long get_pll_core_divider(struct clk_hw *hw, fbdiv_int = div_fp64 >> 32; fbdiv_frac = (div_fp64 >> (32 - 24)) & 0xffffff; - shifted_fbdiv_int = (u64)fbdiv_int << 24; - calc_rate = (u64)parent_rate * (shifted_fbdiv_int + fbdiv_frac); - calc_rate += BIT(23); - calc_rate >>= 24; + calc_rate = + ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; *div_int = fbdiv_int; *div_frac = fbdiv_frac; @@ -472,12 +597,15 @@ static inline unsigned long get_pll_core_divider(struct clk_hw *hw, static int rp1_pll_core_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct rp1_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); struct rp1_clockman *clockman = pll_core->clockman; const struct rp1_pll_core_data *data = pll_core->data; unsigned long calc_rate; 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); @@ -494,8 +622,7 @@ 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. */ - if (WARN_ON_ONCE(parent_rate > (rate / 16))) - return -ERANGE; + BUG_ON(parent_rate > (rate / 16)); pll_core->cached_rate = calc_rate; @@ -503,7 +630,7 @@ static int rp1_pll_core_set_rate(struct clk_hw *hw, /* Don't need to divide ref unless parent_rate > (output freq / 16) */ clockman_write(clockman, data->cs_reg, clockman_read(clockman, data->cs_reg) | - PLL_CS_REFDIV_MASK); + (1 << PLL_CS_REFDIV_SHIFT)); spin_unlock(&clockman->regs_lock); return 0; @@ -512,20 +639,16 @@ 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_clk_desc *pll_core = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, 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); - - shifted_fbdiv_int = (u64)fbdiv_int << 24; - calc_rate = (u64)parent_rate * (shifted_fbdiv_int + fbdiv_frac); - calc_rate += BIT(23); - calc_rate >>= 24; + calc_rate = + ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; return calc_rate; } @@ -534,9 +657,34 @@ static long rp1_pll_core_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { u32 fbdiv_int, fbdiv_frac; + long calc_rate; - return get_pll_core_divider(hw, rate, *parent_rate, - &fbdiv_int, &fbdiv_frac); + calc_rate = get_pll_core_divider(hw, rate, *parent_rate, + &fbdiv_int, &fbdiv_frac); + return calc_rate; +} + +static void rp1_pll_core_debug_init(struct clk_hw *hw, struct dentry *dentry) +{ + struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); + struct rp1_clockman *clockman = pll_core->clockman; + const struct rp1_pll_core_data *data = pll_core->data; + struct debugfs_reg32 *regs; + + regs = devm_kcalloc(clockman->dev, 4, sizeof(*regs), GFP_KERNEL); + if (!regs) + return; + + regs[0].name = "cs"; + regs[0].offset = data->cs_reg; + regs[1].name = "pwr"; + regs[1].offset = data->pwr_reg; + regs[2].name = "fbdiv_int"; + regs[2].offset = data->fbdiv_int_reg; + regs[3].name = "fbdiv_frac"; + regs[3].offset = data->fbdiv_frac_reg; + + rp1_debugfs_regset(clockman, 0, regs, 4, dentry); } static void get_pll_prim_dividers(unsigned long rate, unsigned long parent_rate, @@ -545,13 +693,13 @@ 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); - unsigned long rate_diff, calc_rate; + ABS_DIFF(DIV_ROUND_CLOSEST(parent_rate, best_div1 * best_div2), rate); + 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; @@ -573,41 +721,43 @@ static void get_pll_prim_dividers(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_clk_desc *pll = container_of(hw, struct rp1_clk_desc, hw); + 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; - 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 &= ~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); + 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); 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_clk_desc *pll = container_of(hw, struct rp1_clk_desc, hw); + 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; u32 prim, prim_div1, prim_div2; prim = clockman_read(clockman, data->ctrl_reg); - prim_div1 = FIELD_GET(PLL_PRIM_DIV1_MASK, prim); - prim_div2 = FIELD_GET(PLL_PRIM_DIV2_MASK, prim); + prim_div1 = (prim & PLL_PRIM_DIV1_MASK) >> PLL_PRIM_DIV1_SHIFT; + prim_div2 = (prim & PLL_PRIM_DIV2_MASK) >> PLL_PRIM_DIV2_SHIFT; if (!prim_div1 || !prim_div2) { dev_err(clockman->dev, "%s: (%s) zero divider value\n", - __func__, clk_hw_get_name(hw)); + __func__, data->name); return 0; } @@ -617,29 +767,52 @@ static unsigned long rp1_pll_recalc_rate(struct clk_hw *hw, static long rp1_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { + const struct rp1_clk_change *chg = &rp1_clk_chg_tree[1]; u32 div1, div2; + if (chg->hw == hw && chg->new_rate == rate) + *parent_rate = chg[1].new_rate; + get_pll_prim_dividers(rate, *parent_rate, &div1, &div2); return DIV_ROUND_CLOSEST(*parent_rate, div1 * div2); } +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_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; + 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; return !!(clockman_read(clockman, data->ph_reg) & PLL_PH_EN); } static int rp1_pll_ph_on(struct clk_hw *hw) { - struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, 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; @@ -647,12 +820,15 @@ 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_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); struct rp1_clockman *clockman = pll_ph->clockman; const struct rp1_pll_ph_data *data = pll_ph->data; @@ -662,10 +838,28 @@ 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_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); const struct rp1_pll_ph_data *data = pll_ph->data; return parent_rate / data->fixed_divider; @@ -674,15 +868,33 @@ static unsigned long rp1_pll_ph_recalc_rate(struct clk_hw *hw, static long rp1_pll_ph_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct rp1_clk_desc *pll_ph = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); const struct rp1_pll_ph_data *data = pll_ph->data; return *parent_rate / data->fixed_divider; } +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_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw); + 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; @@ -691,7 +903,7 @@ static int rp1_pll_divider_is_on(struct clk_hw *hw) static int rp1_pll_divider_on(struct clk_hw *hw) { - struct rp1_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw); + 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; @@ -702,12 +914,15 @@ 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_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw); + 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; @@ -721,7 +936,7 @@ static int rp1_pll_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct rp1_clk_desc *divider = container_of(hw, struct rp1_clk_desc, div.hw); + 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; u32 div, sec; @@ -731,20 +946,21 @@ static int rp1_pll_divider_set_rate(struct clk_hw *hw, spin_lock(&clockman->regs_lock); sec = clockman_read(clockman, data->ctrl_reg); - sec &= ~PLL_SEC_DIV_MASK; - sec |= FIELD_PREP(PLL_SEC_DIV_MASK, div); + sec = set_register_field(sec, div, PLL_SEC_DIV_MASK, PLL_SEC_DIV_SHIFT); /* Must keep the divider in reset to change the value. */ sec |= PLL_SEC_RST; clockman_write(clockman, data->ctrl_reg, sec); - /* must sleep 10 pll vco cycles */ - ndelay(div64_ul(10ULL * div * NSEC_PER_SEC, parent_rate)); - + // todo: must sleep 10 pll vco cycles 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; } @@ -761,9 +977,26 @@ static long rp1_pll_divider_round_rate(struct clk_hw *hw, return clk_divider_ops.round_rate(hw, rate, parent_rate); } +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_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; @@ -773,11 +1006,12 @@ 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_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, 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); @@ -798,7 +1032,7 @@ static unsigned long rp1_clock_recalc_rate(struct clk_hw *hw, static int rp1_clock_on(struct clk_hw *hw) { - struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; @@ -811,12 +1045,15 @@ static int rp1_clock_on(struct clk_hw *hw) 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_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; @@ -848,9 +1085,9 @@ 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_ROUND_CLOSEST_ULL(div, rate); + div = DIV_U64_NEAREST(div, rate); } else { - div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate); + div = DIV_U64_NEAREST(parent_rate, rate); div <<= CLK_DIV_FRAC_BITS; } @@ -863,7 +1100,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_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; u32 sel, ctrl; @@ -889,7 +1126,7 @@ static u8 rp1_clock_get_parent(struct clk_hw *hw) * the AUXSRC register field. */ ctrl = clockman_read(clockman, data->ctrl_reg); - parent = FIELD_GET(CLK_CTRL_AUXSRC_MASK, ctrl); + parent = (ctrl & CLK_CTRL_AUXSRC_MASK) >> CLK_CTRL_AUXSRC_SHIFT; parent += data->num_std_parents; } @@ -898,7 +1135,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_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); struct rp1_clockman *clockman = clock->clockman; const struct rp1_clock_data *data = clock->data; u32 ctrl, sel; @@ -908,28 +1145,27 @@ 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) { - spin_unlock(&clockman->regs_lock); + if (index >= data->num_std_parents + data->num_aux_parents) return -EINVAL; - } /* Select parent from aux list */ - ctrl &= ~CLK_CTRL_AUXSRC_MASK; - ctrl |= FIELD_PREP(CLK_CTRL_AUXSRC_MASK, index - data->num_std_parents); + ctrl = set_register_field(ctrl, index - data->num_std_parents, + CLK_CTRL_AUXSRC_MASK, + CLK_CTRL_AUXSRC_SHIFT); /* Set src to aux list */ - ctrl &= ~data->clk_src_mask; - ctrl |= (AUX_SEL << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask; + ctrl = set_register_field(ctrl, AUX_SEL, data->clk_src_mask, + CLK_CTRL_SRC_SHIFT); } else { - ctrl &= ~data->clk_src_mask; - ctrl |= (index << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask; + ctrl = set_register_field(ctrl, index, data->clk_src_mask, + CLK_CTRL_SRC_SHIFT); } clockman_write(clockman, data->ctrl_reg, ctrl); spin_unlock(&clockman->regs_lock); sel = rp1_clock_get_parent(hw); - if (sel != index) - return -EINVAL; + WARN(sel != index, "(%s): Parent index req %u returned back %u\n", + data->name, index, sel); return 0; } @@ -939,11 +1175,18 @@ static int rp1_clock_set_rate_and_parent(struct clk_hw *hw, unsigned long parent_rate, u8 parent) { - struct rp1_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, 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); @@ -953,8 +1196,12 @@ static int rp1_clock_set_rate_and_parent(struct clk_hw *hw, spin_unlock(&clockman->regs_lock); if (parent != 0xff) - return rp1_clock_set_parent(hw, parent); + 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; } @@ -964,20 +1211,107 @@ 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 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_max = 2400000000; + const unsigned long core_min = xosc_rate * 16; + unsigned long best_rate = core_max + 1; + int best_div_prim = 1, best_div_clk = 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_clk_desc *clock = container_of(hw, struct rp1_clk_desc, hw); + struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); const struct rp1_clock_data *data = clock->data; struct clk_hw *parent; u32 div; u64 tmp; + int i; parent = clk_hw_get_parent_by_index(hw, parent_idx); + for (i = 0; i < ARRAY_SIZE(rp1_clk_chg_tree); i++) { + const struct rp1_clk_change *chg = &rp1_clk_chg_tree[i]; + + if (chg->hw == hw && chg->new_rate == rate) { + if (i == 2) + *prate = clk_hw_get_rate(clk_xosc); + else if (parent == rp1_clk_chg_tree[i + 1].hw) + *prate = rp1_clk_chg_tree[i + 1].new_rate; + else + continue; + *calc_rate = chg->new_rate; + return; + } + } + + if (hw == clk_i2s && parent == clk_audio) { + 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_NEAREST(core_rate, div_prim); + i2s_rate = DIV_NEAREST(audio_rate, div_clk); + rp1_clk_chg_tree[2].hw = clk_hw_get_parent(parent); + rp1_clk_chg_tree[2].new_rate = core_rate; + rp1_clk_chg_tree[1].hw = clk_audio; + rp1_clk_chg_tree[1].new_rate = audio_rate; + rp1_clk_chg_tree[0].hw = clk_i2s; + rp1_clk_chg_tree[0].new_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); @@ -989,13 +1323,14 @@ 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. + * 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). */ - if (tmp > data->max_freq) + if (tmp > clock->data->max_freq + (clock->data->max_freq >> 25)) *calc_rate = 0; else *calc_rate = tmp; @@ -1041,11 +1376,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; @@ -1062,6 +1397,59 @@ static int rp1_clock_determine_rate(struct clk_hw *hw, return 0; } +static void rp1_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) +{ + struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); + struct rp1_clockman *clockman = clock->clockman; + const struct rp1_clock_data *data = clock->data; + struct debugfs_reg32 *regs; + int i; + + regs = devm_kcalloc(clockman->dev, 4, sizeof(*regs), GFP_KERNEL); + if (!regs) + return; + + i = 0; + regs[i].name = "ctrl"; + regs[i++].offset = data->ctrl_reg; + regs[i].name = "div_int"; + regs[i++].offset = data->div_int_reg; + regs[i].name = "div_frac"; + regs[i++].offset = data->div_frac_reg; + regs[i].name = "sel"; + regs[i++].offset = data->sel_reg; + + rp1_debugfs_regset(clockman, 0, regs, i, dentry); +} + +static int rp1_varsrc_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate) +{ + struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, 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. + */ + varsrc->rate = rate; + return 0; +} + +static unsigned long rp1_varsrc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, hw); + + return varsrc->rate; +} + +static long rp1_varsrc_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + return rate; +} + static const struct clk_ops rp1_pll_core_ops = { .is_prepared = rp1_pll_core_is_on, .prepare = rp1_pll_core_on, @@ -1069,20 +1457,24 @@ static const struct clk_ops rp1_pll_core_ops = { .set_rate = rp1_pll_core_set_rate, .recalc_rate = rp1_pll_core_recalc_rate, .round_rate = rp1_pll_core_round_rate, + .debug_init = rp1_pll_core_debug_init, }; 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, + .debug_init = rp1_pll_debug_init, }; 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, + .debug_init = rp1_pll_ph_debug_init, }; static const struct clk_ops rp1_pll_divider_ops = { @@ -1092,6 +1484,7 @@ static const struct clk_ops rp1_pll_divider_ops = { .set_rate = rp1_pll_divider_set_rate, .recalc_rate = rp1_pll_divider_recalc_rate, .round_rate = rp1_pll_divider_round_rate, + .debug_init = rp1_pll_divider_debug_init, }; static const struct clk_ops rp1_clk_ops = { @@ -1104,372 +1497,976 @@ 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, + .round_rate = rp1_varsrc_round_rate, }; +static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman, + const void *data) +{ + const struct rp1_pll_core_data *pll_core_data = data; + struct rp1_pll_core *pll_core; + struct clk_init_data init; + int ret; + + memset(&init, 0, sizeof(init)); + + /* All of the PLL cores derive from the external oscillator. */ + init.parent_names = &ref_clock; + init.num_parents = 1; + init.name = pll_core_data->name; + init.ops = &rp1_pll_core_ops; + init.flags = pll_core_data->flags | CLK_IS_CRITICAL; + + pll_core = kzalloc(sizeof(*pll_core), GFP_KERNEL); + if (!pll_core) + return NULL; + + pll_core->clockman = clockman; + pll_core->data = pll_core_data; + pll_core->hw.init = &init; + + ret = devm_clk_hw_register(clockman->dev, &pll_core->hw); + if (ret) { + kfree(pll_core); + return NULL; + } + + return &pll_core->hw; +} + static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman, - struct rp1_clk_desc *desc) + const void *data) { + const struct rp1_pll_data *pll_data = data; + struct rp1_pll *pll; + struct clk_init_data init; int ret; - desc->clockman = clockman; + memset(&init, 0, sizeof(init)); - ret = devm_clk_hw_register(clockman->dev, &desc->hw); - if (ret) - return ERR_PTR(ret); + 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; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return NULL; + + pll->clockman = clockman; + pll->data = pll_data; + pll->hw.init = &init; + + ret = devm_clk_hw_register(clockman->dev, &pll->hw); + if (ret) { + kfree(pll); + return NULL; + } + + return &pll->hw; +} + +static struct clk_hw *rp1_register_pll_ph(struct rp1_clockman *clockman, + const void *data) +{ + const struct rp1_pll_ph_data *ph_data = data; + struct rp1_pll_ph *ph; + struct clk_init_data init; + int ret; + + memset(&init, 0, sizeof(init)); + + /* 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; + + ph = kzalloc(sizeof(*ph), GFP_KERNEL); + if (!ph) + return NULL; + + ph->clockman = clockman; + ph->data = ph_data; + ph->hw.init = &init; + + ret = devm_clk_hw_register(clockman->dev, &ph->hw); + if (ret) { + kfree(ph); + return NULL; + } - return &desc->hw; + return &ph->hw; } static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman, - struct rp1_clk_desc *desc) + const void *data) { - const struct rp1_pll_data *divider_data = desc->data; + const struct rp1_pll_data *divider_data = data; + struct rp1_pll *divider; + struct clk_init_data init; int ret; - 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; + memset(&init, 0, sizeof(init)); + + 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; + + divider = devm_kzalloc(clockman->dev, sizeof(*divider), GFP_KERNEL); + if (!divider) + return NULL; + + 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; - desc->clockman = clockman; + divider->clockman = clockman; + divider->data = divider_data; - ret = devm_clk_hw_register(clockman->dev, &desc->div.hw); + ret = devm_clk_hw_register(clockman->dev, ÷r->div.hw); if (ret) return ERR_PTR(ret); - return &desc->div.hw; + return ÷r->div.hw; } static struct clk_hw *rp1_register_clock(struct rp1_clockman *clockman, - struct rp1_clk_desc *desc) + const void *data) { - const struct rp1_clock_data *clock_data = desc->data; + const struct rp1_clock_data *clock_data = data; + struct rp1_clock *clock; + struct clk_init_data init; int ret; - if (WARN_ON_ONCE(MAX_CLK_PARENTS < - clock_data->num_std_parents + clock_data->num_aux_parents)) - return ERR_PTR(-EINVAL); - + BUG_ON(MAX_CLK_PARENTS < + clock_data->num_std_parents + clock_data->num_aux_parents); /* 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); - - desc->clockman = clockman; - - ret = devm_clk_hw_register(clockman->dev, &desc->hw); + BUG_ON((clock_data->num_std_parents > AUX_SEL) && + strcmp("-", clock_data->parents[AUX_SEL])); + + 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; + + clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); + if (!clock) + return NULL; + + clock->clockman = clockman; + clock->data = clock_data; + clock->hw.init = &init; + + ret = devm_clk_hw_register(clockman->dev, &clock->hw); if (ret) return ERR_PTR(ret); - return &desc->hw; + return &clock->hw; } -/* Assignment helper macros for different clock types. */ -#define _REGISTER(f, ...) { .clk_register = f, __VA_ARGS__ } +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; -#define CLK_DATA(type, ...) .data = &(struct type) { __VA_ARGS__ } + memset(&init, 0, sizeof(init)); + init.parent_names = &ref_clock; + init.num_parents = 1; + init.name = name; + init.ops = &rp1_varsrc_ops; -#define REGISTER_PLL(...) _REGISTER(&rp1_register_pll, \ - __VA_ARGS__) + clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); + if (!clock) + return NULL; -#define REGISTER_PLL_DIV(...) _REGISTER(&rp1_register_pll_divider, \ - __VA_ARGS__) + clock->clockman = clockman; + clock->hw.init = &init; -#define REGISTER_CLK(...) _REGISTER(&rp1_register_clock, \ - __VA_ARGS__) - -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 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 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 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 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_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 const struct clk_parent_data clk_eth_parents[] = { - { .hw = &pll_sys_sec_desc.div.hw }, - { .hw = &pll_sys_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 = 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 const struct clk_parent_data clk_sys_parents[] = { - { .index = 0 }, - { .index = -1 }, - { .hw = &pll_sys_desc.hw }, -}; + return &clock->hw; +} -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 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 *const clk_desc_array[] = { - [RP1_PLL_SYS_CORE] = &pll_sys_core_desc, - [RP1_PLL_AUDIO_CORE] = &pll_audio_core_desc, - [RP1_PLL_VIDEO_CORE] = &pll_video_core_desc, - [RP1_PLL_SYS] = &pll_sys_desc, - [RP1_CLK_ETH_TSU] = &clk_eth_tsu_desc, - [RP1_CLK_ETH] = &clk_eth_desc, - [RP1_CLK_SYS] = &clk_sys_desc, - [RP1_PLL_SYS_PRI_PH] = &pll_sys_pri_ph_desc, - [RP1_PLL_SYS_SEC] = &pll_sys_sec_desc, +struct rp1_clk_desc { + struct clk_hw *(*clk_register)(struct rp1_clockman *clockman, + const void *data); + const void *data; }; -static const struct regmap_range rp1_reg_ranges[] = { - regmap_reg_range(PLL_SYS_CS, PLL_SYS_SEC), - regmap_reg_range(PLL_AUDIO_CS, PLL_AUDIO_TERN), - regmap_reg_range(PLL_VIDEO_CS, PLL_VIDEO_SEC), - regmap_reg_range(GPCLK_OE_CTRL, GPCLK_OE_CTRL), - regmap_reg_range(CLK_SYS_CTRL, CLK_SYS_DIV_INT), - regmap_reg_range(CLK_SYS_SEL, CLK_SYS_SEL), - regmap_reg_range(CLK_SLOW_SYS_CTRL, CLK_SLOW_SYS_DIV_INT), - regmap_reg_range(CLK_SLOW_SYS_SEL, CLK_SLOW_SYS_SEL), - regmap_reg_range(CLK_DMA_CTRL, CLK_DMA_DIV_INT), - regmap_reg_range(CLK_DMA_SEL, CLK_DMA_SEL), - regmap_reg_range(CLK_UART_CTRL, CLK_UART_DIV_INT), - regmap_reg_range(CLK_UART_SEL, CLK_UART_SEL), - regmap_reg_range(CLK_ETH_CTRL, CLK_ETH_DIV_INT), - regmap_reg_range(CLK_ETH_SEL, CLK_ETH_SEL), - regmap_reg_range(CLK_PWM0_CTRL, CLK_PWM0_SEL), - regmap_reg_range(CLK_PWM1_CTRL, CLK_PWM1_SEL), - regmap_reg_range(CLK_AUDIO_IN_CTRL, CLK_AUDIO_IN_DIV_INT), - regmap_reg_range(CLK_AUDIO_IN_SEL, CLK_AUDIO_IN_SEL), - regmap_reg_range(CLK_AUDIO_OUT_CTRL, CLK_AUDIO_OUT_DIV_INT), - regmap_reg_range(CLK_AUDIO_OUT_SEL, CLK_AUDIO_OUT_SEL), - regmap_reg_range(CLK_I2S_CTRL, CLK_I2S_DIV_INT), - regmap_reg_range(CLK_I2S_SEL, CLK_I2S_SEL), - regmap_reg_range(CLK_MIPI0_CFG_CTRL, CLK_MIPI0_CFG_DIV_INT), - regmap_reg_range(CLK_MIPI0_CFG_SEL, CLK_MIPI0_CFG_SEL), - regmap_reg_range(CLK_MIPI1_CFG_CTRL, CLK_MIPI1_CFG_DIV_INT), - 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_SEL, CLK_USBH0_MICROFRAME_SEL), - 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), - regmap_reg_range(CLK_USBH1_SUSPEND_CTRL, CLK_USBH1_SUSPEND_DIV_INT), - regmap_reg_range(CLK_USBH1_SUSPEND_SEL, CLK_USBH1_SUSPEND_SEL), - regmap_reg_range(CLK_ETH_TSU_CTRL, CLK_ETH_TSU_DIV_INT), - regmap_reg_range(CLK_ETH_TSU_SEL, CLK_ETH_TSU_SEL), - regmap_reg_range(CLK_ADC_CTRL, CLK_ADC_DIV_INT), - regmap_reg_range(CLK_ADC_SEL, CLK_ADC_SEL), - regmap_reg_range(CLK_SDIO_TIMER_CTRL, CLK_SDIO_TIMER_DIV_INT), - regmap_reg_range(CLK_SDIO_TIMER_SEL, CLK_SDIO_TIMER_SEL), - regmap_reg_range(CLK_SDIO_ALT_SRC_CTRL, CLK_SDIO_ALT_SRC_DIV_INT), - regmap_reg_range(CLK_SDIO_ALT_SRC_SEL, CLK_SDIO_ALT_SRC_SEL), - regmap_reg_range(CLK_GP0_CTRL, CLK_GP0_SEL), - regmap_reg_range(CLK_GP1_CTRL, CLK_GP1_SEL), - regmap_reg_range(CLK_GP2_CTRL, CLK_GP2_SEL), - regmap_reg_range(CLK_GP3_CTRL, CLK_GP3_SEL), - regmap_reg_range(CLK_GP4_CTRL, CLK_GP4_SEL), - regmap_reg_range(CLK_GP5_CTRL, CLK_GP5_SEL), - regmap_reg_range(CLK_SYS_RESUS_CTRL, CLK_SYS_RESUS_CTRL), - regmap_reg_range(CLK_SLOW_SYS_RESUS_CTRL, CLK_SLOW_SYS_RESUS_CTRL), - regmap_reg_range(FC0_REF_KHZ, FC0_RESULT), - regmap_reg_range(VIDEO_CLK_VEC_CTRL, VIDEO_CLK_VEC_DIV_INT), - regmap_reg_range(VIDEO_CLK_VEC_SEL, VIDEO_CLK_DPI_DIV_INT), - regmap_reg_range(VIDEO_CLK_DPI_SEL, VIDEO_CLK_MIPI1_DPI_SEL), -}; +/* Assignment helper macros for different clock types. */ +#define _REGISTER(f, ...) { .clk_register = f, .data = __VA_ARGS__ } -static const struct regmap_access_table rp1_reg_table = { - .yes_ranges = rp1_reg_ranges, - .n_yes_ranges = ARRAY_SIZE(rp1_reg_ranges), -}; +#define REGISTER_PLL_CORE(...) _REGISTER(&rp1_register_pll_core, \ + &(struct rp1_pll_core_data) \ + {__VA_ARGS__}) + +#define REGISTER_PLL(...) _REGISTER(&rp1_register_pll, \ + &(struct rp1_pll_data) \ + {__VA_ARGS__}) + +#define REGISTER_PLL_PH(...) _REGISTER(&rp1_register_pll_ph, \ + &(struct rp1_pll_ph_data) \ + {__VA_ARGS__}) -static const struct regmap_config rp1_clk_regmap_cfg = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = PLL_VIDEO_SEC, - .name = "rp1-clk", - .rd_table = &rp1_reg_table, - .disable_locking = true, +#define REGISTER_PLL_DIV(...) _REGISTER(&rp1_register_pll_divider, \ + &(struct rp1_pll_data) \ + {__VA_ARGS__}) + +#define REGISTER_CLK(...) _REGISTER(&rp1_register_clock, \ + &(struct rp1_clock_data) \ + {__VA_ARGS__}) + +#define REGISTER_VARSRC(n) _REGISTER(&rp1_register_varsrc, &(const char *){n}) + +static const struct rp1_clk_desc clk_desc_array[] = { + [RP1_PLL_SYS_CORE] = REGISTER_PLL_CORE( + .name = "pll_sys_core", + .cs_reg = PLL_SYS_CS, + .pwr_reg = PLL_SYS_PWR, + .fbdiv_int_reg = PLL_SYS_FBDIV_INT, + .fbdiv_frac_reg = PLL_SYS_FBDIV_FRAC, + ), + + [RP1_PLL_AUDIO_CORE] = REGISTER_PLL_CORE( + .name = "pll_audio_core", + .cs_reg = PLL_AUDIO_CS, + .pwr_reg = PLL_AUDIO_PWR, + .fbdiv_int_reg = PLL_AUDIO_FBDIV_INT, + .fbdiv_frac_reg = PLL_AUDIO_FBDIV_FRAC, + ), + + [RP1_PLL_VIDEO_CORE] = REGISTER_PLL_CORE( + .name = "pll_video_core", + .cs_reg = PLL_VIDEO_CS, + .pwr_reg = PLL_VIDEO_PWR, + .fbdiv_int_reg = PLL_VIDEO_FBDIV_INT, + .fbdiv_frac_reg = PLL_VIDEO_FBDIV_FRAC, + ), + + [RP1_PLL_SYS] = REGISTER_PLL( + .name = "pll_sys", + .source_pll = "pll_sys_core", + .ctrl_reg = PLL_SYS_PRIM, + .fc0_src = FC_NUM(0, 2), + ), + + [RP1_PLL_AUDIO] = REGISTER_PLL( + .name = "pll_audio", + .source_pll = "pll_audio_core", + .ctrl_reg = PLL_AUDIO_PRIM, + .fc0_src = FC_NUM(4, 2), + .flags = CLK_SET_RATE_PARENT, + ), + + [RP1_PLL_VIDEO] = REGISTER_PLL( + .name = "pll_video", + .source_pll = "pll_video_core", + .ctrl_reg = PLL_VIDEO_PRIM, + .fc0_src = FC_NUM(3, 2), + ), + + [RP1_PLL_SYS_PRI_PH] = REGISTER_PLL_PH( + .name = "pll_sys_pri_ph", + .source_pll = "pll_sys", + .ph_reg = PLL_SYS_PRIM, + .fixed_divider = 2, + .phase = RP1_PLL_PHASE_0, + .fc0_src = FC_NUM(1, 2), + ), + + [RP1_PLL_AUDIO_PRI_PH] = REGISTER_PLL_PH( + .name = "pll_audio_pri_ph", + .source_pll = "pll_audio", + .ph_reg = PLL_AUDIO_PRIM, + .fixed_divider = 2, + .phase = RP1_PLL_PHASE_0, + .fc0_src = FC_NUM(5, 1), + ), + + [RP1_PLL_VIDEO_PRI_PH] = REGISTER_PLL_PH( + .name = "pll_video_pri_ph", + .source_pll = "pll_video", + .ph_reg = PLL_VIDEO_PRIM, + .fixed_divider = 2, + .phase = RP1_PLL_PHASE_0, + .fc0_src = FC_NUM(4, 3), + ), + + [RP1_PLL_SYS_SEC] = REGISTER_PLL_DIV( + .name = "pll_sys_sec", + .source_pll = "pll_sys_core", + .ctrl_reg = PLL_SYS_SEC, + .fc0_src = FC_NUM(2, 2), + ), + + [RP1_PLL_AUDIO_SEC] = REGISTER_PLL_DIV( + .name = "pll_audio_sec", + .source_pll = "pll_audio_core", + .ctrl_reg = PLL_AUDIO_SEC, + .fc0_src = FC_NUM(6, 2), + ), + + [RP1_PLL_VIDEO_SEC] = REGISTER_PLL_DIV( + .name = "pll_video_sec", + .source_pll = "pll_video_core", + .ctrl_reg = PLL_VIDEO_SEC, + .fc0_src = FC_NUM(5, 3), + ), + + [RP1_PLL_AUDIO_TERN] = REGISTER_PLL_DIV( + .name = "pll_audio_tern", + .source_pll = "pll_audio_core", + .ctrl_reg = PLL_AUDIO_TERN, + .fc0_src = FC_NUM(6, 2), + ), + + [RP1_CLK_SYS] = REGISTER_CLK( + .name = "clk_sys", + .parents = {"xosc", "-", "pll_sys"}, + .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 * MHz, + .fc0_src = FC_NUM(0, 4), + .clk_src_mask = 0x3, + /* Always enabled in hardware */ + .flags = CLK_IS_CRITICAL, + ), + + [RP1_CLK_SLOW_SYS] = REGISTER_CLK( + .name = "clk_slow_sys", + .parents = {"xosc"}, + .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 * MHz, + .fc0_src = FC_NUM(1, 4), + .clk_src_mask = 0x1, + /* Always enabled in hardware */ + .flags = CLK_IS_CRITICAL, + ), + + [RP1_CLK_DMA] = REGISTER_CLK( + .name = "clk_dma", + .parents = {"pll_sys_pri_ph", + "pll_video", + "xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 9, + .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 * MHz, + .fc0_src = FC_NUM(2, 2), + ), + + [RP1_CLK_UART] = REGISTER_CLK( + .name = "clk_uart", + .parents = {"pll_sys_pri_ph", + "pll_video", + "xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 9, + .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 * MHz, + .fc0_src = FC_NUM(6, 7), + ), + + [RP1_CLK_ETH] = REGISTER_CLK( + .name = "clk_eth", + .parents = {"pll_sys_sec", + "pll_sys", + "pll_video_sec", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 9, + .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 * MHz, + .fc0_src = FC_NUM(4, 6), + ), + + [RP1_CLK_PWM0] = REGISTER_CLK( + .name = "clk_pwm0", + .parents = {"", // "pll_audio_pri_ph", + "pll_video_sec", + "xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 9, + .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 * KHz, + .fc0_src = FC_NUM(0, 5), + ), + + [RP1_CLK_PWM1] = REGISTER_CLK( + .name = "clk_pwm1", + .parents = {"", // "pll_audio_pri_ph", + "pll_video_sec", + "xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 9, + .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 * KHz, + .fc0_src = FC_NUM(1, 5), + ), + + [RP1_CLK_AUDIO_IN] = REGISTER_CLK( + .name = "clk_audio_in", + .parents = {"", //"pll_audio", + "", //"pll_audio_pri_ph", + "", //"pll_audio_sec", + "pll_video_sec", + "xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 11, + .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 * KHz, + .fc0_src = FC_NUM(2, 5), + ), + + [RP1_CLK_AUDIO_OUT] = REGISTER_CLK( + .name = "clk_audio_out", + .parents = {"", //"pll_audio", + "pll_audio_sec", + "pll_video_sec", + "xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 10, + .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 * KHz, + .fc0_src = FC_NUM(3, 5), + ), + + [RP1_CLK_I2S] = REGISTER_CLK( + .name = "clk_i2s", + .parents = {"xosc", + "pll_audio", + "pll_audio_sec", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 9, + .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 * MHz, + .fc0_src = FC_NUM(4, 4), + .flags = CLK_SET_RATE_PARENT, + ), + + [RP1_CLK_MIPI0_CFG] = REGISTER_CLK( + .name = "clk_mipi0_cfg", + .parents = {"xosc"}, + .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 * MHz, + .fc0_src = FC_NUM(4, 5), + ), + + [RP1_CLK_MIPI1_CFG] = REGISTER_CLK( + .name = "clk_mipi1_cfg", + .parents = {"xosc"}, + .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, + .clk_src_mask = 1, + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 50 * MHz, + .fc0_src = FC_NUM(5, 6), + ), + + [RP1_CLK_ETH_TSU] = REGISTER_CLK( + .name = "clk_eth_tsu", + .parents = {"xosc", + "pll_video_sec", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .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 * MHz, + .fc0_src = FC_NUM(5, 7), + ), + + [RP1_CLK_ADC] = REGISTER_CLK( + .name = "clk_adc", + .parents = {"xosc", + "", //"pll_audio_tern", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5"}, + .num_std_parents = 0, + .num_aux_parents = 8, + .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 * MHz, + .fc0_src = FC_NUM(5, 5), + ), + + [RP1_CLK_SDIO_TIMER] = REGISTER_CLK( + .name = "clk_sdio_timer", + .parents = {"xosc"}, + .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 * MHz, + .fc0_src = FC_NUM(3, 4), + ), + + [RP1_CLK_SDIO_ALT_SRC] = REGISTER_CLK( + .name = "clk_sdio_alt_src", + .parents = {"pll_sys"}, + .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 * MHz, + .fc0_src = FC_NUM(5, 4), + ), + + [RP1_CLK_GP0] = REGISTER_CLK( + .name = "clk_gp0", + .parents = {"xosc", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5", + "pll_sys", + "", //"pll_audio", + "", + "", + "clk_i2s", + "clk_adc", + "", + "", + "", + "clk_sys"}, + .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 * MHz, + .fc0_src = FC_NUM(0, 1), + ), + + [RP1_CLK_GP1] = REGISTER_CLK( + .name = "clk_gp1", + .parents = {"clk_sdio_timer", + "clksrc_gp0", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5", + "pll_sys_pri_ph", + "", //"pll_audio_pri_ph", + "", + "", + "clk_adc", + "clk_dpi", + "clk_pwm0", + "", + "", + ""}, + .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 * MHz, + .fc0_src = FC_NUM(1, 1), + ), + + [RP1_CLK_GP2] = REGISTER_CLK( + .name = "clk_gp2", + .parents = {"clk_sdio_alt_src", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp3", + "clksrc_gp4", + "clksrc_gp5", + "pll_sys_sec", + "", //"pll_audio_sec", + "pll_video", + "clk_audio_in", + "clk_dpi", + "clk_pwm0", + "clk_pwm1", + "clk_mipi0_dpi", + "clk_mipi1_cfg", + "clk_sys"}, + .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 * MHz, + .fc0_src = FC_NUM(2, 1), + ), + + [RP1_CLK_GP3] = REGISTER_CLK( + .name = "clk_gp3", + .parents = {"xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp4", + "clksrc_gp5", + "", + "", + "pll_video_pri_ph", + "clk_audio_out", + "", + "", + "clk_mipi1_dpi", + "", + "", + ""}, + .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 * MHz, + .fc0_src = FC_NUM(3, 1), + ), + + [RP1_CLK_GP4] = REGISTER_CLK( + .name = "clk_gp4", + .parents = {"xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp5", + "", //"pll_audio_tern", + "pll_video_sec", + "", + "", + "", + "clk_mipi0_cfg", + "clk_uart", + "", + "", + "clk_sys", + }, + .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 * MHz, + .fc0_src = FC_NUM(4, 1), + ), + + [RP1_CLK_GP5] = REGISTER_CLK( + .name = "clk_gp5", + .parents = {"xosc", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4", + "", //"pll_audio_tern", + "pll_video_sec", + "clk_eth_tsu", + "", + "clk_vec", + "", + "", + "", + "", + ""}, + .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 * MHz, + .fc0_src = FC_NUM(5, 1), + ), + + [RP1_CLK_VEC] = REGISTER_CLK( + .name = "clk_vec", + .parents = {"pll_sys_pri_ph", + "pll_video_sec", + "pll_video", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4"}, + .num_std_parents = 0, + .num_aux_parents = 8, /* XXX in fact there are more than 8 */ + .ctrl_reg = VIDEO_CLK_VEC_CTRL, + .div_int_reg = VIDEO_CLK_VEC_DIV_INT, + .sel_reg = VIDEO_CLK_VEC_SEL, + .flags = CLK_SET_RATE_NO_REPARENT, /* Let VEC driver set parent */ + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 108 * MHz, + .fc0_src = FC_NUM(0, 6), + ), + + [RP1_CLK_DPI] = REGISTER_CLK( + .name = "clk_dpi", + .parents = {"pll_sys", + "pll_video_sec", + "pll_video", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3", + "clksrc_gp4"}, + .num_std_parents = 0, + .num_aux_parents = 8, /* XXX in fact there are more than 8 */ + .ctrl_reg = VIDEO_CLK_DPI_CTRL, + .div_int_reg = VIDEO_CLK_DPI_DIV_INT, + .sel_reg = VIDEO_CLK_DPI_SEL, + .flags = CLK_SET_RATE_NO_REPARENT, /* Let DPI driver set parent */ + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 200 * MHz, + .fc0_src = FC_NUM(1, 6), + ), + + [RP1_CLK_MIPI0_DPI] = REGISTER_CLK( + .name = "clk_mipi0_dpi", + .parents = {"pll_sys", + "pll_video_sec", + "pll_video", + "clksrc_mipi0_dsi_byteclk", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3"}, + .num_std_parents = 0, + .num_aux_parents = 8, /* XXX in fact there are more than 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, + .flags = CLK_SET_RATE_NO_REPARENT, /* Let DSI driver set parent */ + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 200 * MHz, + .fc0_src = FC_NUM(2, 6), + ), + + [RP1_CLK_MIPI1_DPI] = REGISTER_CLK( + .name = "clk_mipi1_dpi", + .parents = {"pll_sys", + "pll_video_sec", + "pll_video", + "clksrc_mipi1_dsi_byteclk", + "clksrc_gp0", + "clksrc_gp1", + "clksrc_gp2", + "clksrc_gp3"}, + .num_std_parents = 0, + .num_aux_parents = 8, /* XXX in fact there are more than 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, + .flags = CLK_SET_RATE_NO_REPARENT, /* Let DSI driver set parent */ + .div_int_max = DIV_INT_8BIT_MAX, + .max_freq = 200 * MHz, + .fc0_src = FC_NUM(3, 6), + ), + + [RP1_CLK_MIPI0_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi0_dsi_byteclk"), + [RP1_CLK_MIPI1_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi1_dsi_byteclk"), }; static int rp1_clk_probe(struct platform_device *pdev) { - const size_t asize = ARRAY_SIZE(clk_desc_array); - struct rp1_clk_desc *desc; + const 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; - - clockman->regs = devm_platform_ioremap_resource(pdev, 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + clockman->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(clockman->regs)) return PTR_ERR(clockman->regs); - 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); - } + platform_set_drvdata(pdev, clockman); clockman->onecell.num = asize; hws = clockman->onecell.hws; for (i = 0; i < asize; i++) { - desc = clk_desc_array[i]; - if (desc && desc->clk_register && desc->data) - hws[i] = desc->clk_register(clockman, desc); + desc = &clk_desc_array[i]; + if (desc->clk_register && desc->data) { + hws[i] = desc->clk_register(clockman, desc->data); + if (IS_ERR_OR_NULL(hws[i])) { + pr_err("Failed to register RP1 clock '%s' (%ld) - wrong dtbs?\n", *(char **)desc->data, PTR_ERR(hws[i])); + hws[i] = NULL; + continue; + } + if (!strcmp(clk_hw_get_name(hws[i]), "clk_i2s")) { + clk_i2s = hws[i]; + clk_xosc = clk_hw_get_parent_by_index(clk_i2s, 0); + clk_audio = clk_hw_get_parent_by_index(clk_i2s, 1); + } + } } - platform_set_drvdata(pdev, clockman); + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + &clockman->onecell); + if (ret) + return ret; - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, - &clockman->onecell); + return 0; } static const struct of_device_id rp1_clk_of_match[] = { @@ -1486,9 +2483,12 @@ static struct platform_driver rp1_clk_driver = { .probe = rp1_clk_probe, }; -module_platform_driver(rp1_clk_driver); +static int __init __rp1_clk_driver_init(void) +{ + return platform_driver_register(&rp1_clk_driver); +} +postcore_initcall(__rp1_clk_driver_init); MODULE_AUTHOR("Naushir Patuck "); -MODULE_AUTHOR("Andrea della Porta "); MODULE_DESCRIPTION("RP1 clock driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index f67484bff8a53f..bbfc0dfafe48ba 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -653,6 +653,11 @@ hdmi_compute_config(const struct drm_connector *connector, ret = hdmi_compute_format_bpc(connector, conn_state, mode, max_bpc, HDMI_COLORSPACE_RGB); + + if (ret) + ret = hdmi_compute_format_bpc(connector, conn_state, mode, + max_bpc, HDMI_COLORSPACE_YUV422); + if (ret) { if (connector->ycbcr_420_allowed) { ret = hdmi_compute_format_bpc(connector, conn_state, diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index f4a7264c341237..764831e404e1a0 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1622,7 +1622,16 @@ static int lan78xx_mac_reset(struct lan78xx_net *dev) */ static int lan78xx_phy_int_ack(struct lan78xx_net *dev) { - return lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_); + struct phy_device *phydev = dev->net->phydev; + int ret = lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_); + + if (unlikely(ret < 0)) + return ret; + + /* Acknowledge any pending PHY interrupt, lest it be the last */ + phy_read(phydev, LAN88XX_INT_STS); + + return 0; } /* some work can't be done in tasklets, so we use keventd @@ -1798,15 +1807,34 @@ static int lan78xx_set_wol(struct net_device *netdev, static int lan78xx_get_eee(struct net_device *net, struct ethtool_keee *edata) { struct lan78xx_net *dev = netdev_priv(net); + u32 buf; + int ret; + + ret = phylink_ethtool_get_eee(dev->phylink, edata); + if (ret < 0) + return ret; + + ret = lan78xx_read_reg(dev, EEE_TX_LPI_REQ_DLY, &buf); + if (ret >= 0) + edata->tx_lpi_timer = buf; + else + edata->tx_lpi_timer = 0; - return phylink_ethtool_get_eee(dev->phylink, edata); + return 0; } static int lan78xx_set_eee(struct net_device *net, struct ethtool_keee *edata) { struct lan78xx_net *dev = netdev_priv(net); + u32 buf; + int ret; + + ret = phylink_ethtool_set_eee(dev->phylink, edata); + if (ret < 0) + return ret; - return phylink_ethtool_set_eee(dev->phylink, edata); + buf = (u32)edata->tx_lpi_timer; + return lan78xx_write_reg(dev, EEE_TX_LPI_REQ_DLY, buf); } static void lan78xx_get_drvinfo(struct net_device *net, @@ -2879,6 +2907,27 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) goto phylink_uninit; } + if (of_property_read_bool(phydev->mdio.dev.of_node, + "microchip,eee-enabled")) { + struct ethtool_keee edata; + memset(&edata, 0, sizeof(edata)); + + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + edata.advertised); + linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + edata.advertised); + + edata.eee_enabled = true; + edata.tx_lpi_enabled = true; + if (of_property_read_u32(phydev->mdio.dev.of_node, + "microchip,tx-lpi-timer", + &edata.tx_lpi_timer)) + edata.tx_lpi_timer = 600; /* non-aggressive */ + (void)lan78xx_set_eee(dev->net, &edata); + + phy_support_eee(phydev); + } + ret = lan78xx_configure_leds_from_dt(dev, phydev); if (ret < 0) goto phylink_uninit; @@ -3227,6 +3276,11 @@ static int lan78xx_reset(struct lan78xx_net *dev) unsigned long timeout; int ret; u32 buf; + bool has_eeprom; + bool has_otp; + + has_eeprom = !lan78xx_read_eeprom(dev, 0, 0, NULL); + has_otp = !lan78xx_read_otp(dev, 0, 0, NULL); ret = lan78xx_read_reg(dev, HW_CFG, &buf); if (ret < 0) @@ -3297,6 +3351,10 @@ static int lan78xx_reset(struct lan78xx_net *dev) buf |= HW_CFG_CLK125_EN_; buf |= HW_CFG_REFCLK25_EN_; + /* If no valid EEPROM and no valid OTP, enable the LEDs by default */ + if (!has_eeprom && !has_otp) + buf |= HW_CFG_LED0_EN_ | HW_CFG_LED1_EN_; + ret = lan78xx_write_reg(dev, HW_CFG, buf); if (ret < 0) return ret; @@ -3389,6 +3447,10 @@ static int lan78xx_reset(struct lan78xx_net *dev) if (dev->chipid == ID_REV_CHIP_ID_7801_) buf &= ~MAC_CR_GMII_EN_; + /* If no valid EEPROM and no valid OTP, enable AUTO negotiation */ + if (!has_eeprom && !has_otp) + buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; + ret = lan78xx_write_reg(dev, MAC_CR, buf); if (ret < 0) return ret; diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index b06764c6140a6c..ca8be4c1f46d12 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -667,7 +667,8 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie, MSI_FLAG_NO_AFFINITY) #define BRCM_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ - MSI_FLAG_MULTI_PCI_MSI) + MSI_FLAG_MULTI_PCI_MSI | \ + MSI_FLAG_PCI_MSIX) static const struct msi_parent_ops brcm_msi_parent_ops = { .required_flags = BRCM_MSI_FLAGS_REQUIRED, diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index ddd11668457ced..ecda7e930a1dc4 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -639,7 +639,7 @@ config PINCTRL_MLXBF3 config PINCTRL_RP1 tristate "Pinctrl driver for RP1" - depends on MISC_RP1 + depends on MISC_RP1 || MFD_RP1 default MISC_RP1 select PINMUX select PINCONF diff --git a/drivers/pinctrl/pinctrl-rp1.c b/drivers/pinctrl/pinctrl-rp1.c index dadafc935dbb28..16320049b5c55e 100644 --- a/drivers/pinctrl/pinctrl-rp1.c +++ b/drivers/pinctrl/pinctrl-rp1.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Driver for Raspberry Pi RP1 GPIO unit + * Driver for Raspberry Pi RP1 GPIO unit (pinctrl + GPIO) * * Copyright (C) 2023 Raspberry Pi Ltd. * @@ -8,15 +8,31 @@ * pinctrl-bcm2835.c, please see original file for copyright information */ +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include #include +#include #include +#include #include #include -#include - -#include "pinmux.h" +#include +#include +#include "core.h" #include "pinconf.h" #include "pinctrl-utils.h" @@ -24,13 +40,60 @@ #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_GPIO_STATUS 0x0000 +#define RP1_GPIO_CTRL 0x0004 + +#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_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_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 GENMASK(3, 0) +#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_FSEL_COUNT 9 @@ -39,108 +102,48 @@ #define RP1_FSEL_NONE 0x09 #define RP1_FSEL_NONE_HW 0x1f -#define RP1_PAD_DRIVE_2MA 0x0 -#define RP1_PAD_DRIVE_4MA 0x1 -#define RP1_PAD_DRIVE_8MA 0x2 -#define RP1_PAD_DRIVE_12MA 0x3 - -enum { - RP1_PUD_OFF = 0, - RP1_PUD_DOWN = 1, - RP1_PUD_UP = 2, -}; - -enum { - RP1_DIR_OUTPUT = 0, - RP1_DIR_INPUT = 1, -}; - -enum { - RP1_OUTOVER_PERI = 0, - RP1_OUTOVER_INVPERI = 1, - RP1_OUTOVER_LOW = 2, - RP1_OUTOVER_HIGH = 3, -}; - -enum { - RP1_OEOVER_PERI = 0, - RP1_OEOVER_INVPERI = 1, - RP1_OEOVER_DISABLE = 2, - RP1_OEOVER_ENABLE = 3, -}; - -enum { - RP1_INOVER_PERI = 0, - RP1_INOVER_INVPERI = 1, - RP1_INOVER_LOW = 2, - RP1_INOVER_HIGH = 3, -}; - -enum { - RP1_GPIO_CTRL_IRQRESET_SET = 0, - RP1_GPIO_CTRL_INT_CLR = 1, - RP1_GPIO_CTRL_INT_SET = 2, - RP1_GPIO_CTRL_OEOVER = 3, - RP1_GPIO_CTRL_FUNCSEL = 4, - RP1_GPIO_CTRL_OUTOVER = 5, - RP1_GPIO_CTRL = 6, -}; - -enum { - RP1_INTE_SET = 0, - RP1_INTE_CLR = 1, -}; - -enum { - RP1_RIO_OUT_SET = 0, - RP1_RIO_OUT_CLR = 1, - RP1_RIO_OE = 2, - RP1_RIO_OE_SET = 3, - RP1_RIO_OE_CLR = 4, - RP1_RIO_IN = 5, -}; - -enum { - RP1_PAD_SLEWFAST = 0, - RP1_PAD_SCHMITT = 1, - RP1_PAD_PULL = 2, - RP1_PAD_DRIVE = 3, - RP1_PAD_IN_ENABLE = 4, - RP1_PAD_OUT_DISABLE = 5, -}; - -static const struct reg_field rp1_gpio_fields[] = { - [RP1_GPIO_CTRL_IRQRESET_SET] = REG_FIELD(0x2004, 28, 28), - [RP1_GPIO_CTRL_INT_CLR] = REG_FIELD(0x3004, 20, 23), - [RP1_GPIO_CTRL_INT_SET] = REG_FIELD(0x2004, 20, 23), - [RP1_GPIO_CTRL_OEOVER] = REG_FIELD(0x0004, 14, 15), - [RP1_GPIO_CTRL_FUNCSEL] = REG_FIELD(0x0004, 0, 4), - [RP1_GPIO_CTRL_OUTOVER] = REG_FIELD(0x0004, 12, 13), - [RP1_GPIO_CTRL] = REG_FIELD(0x0004, 0, 31), -}; - -static const struct reg_field rp1_inte_fields[] = { - [RP1_INTE_SET] = REG_FIELD(0x2000, 0, 0), - [RP1_INTE_CLR] = REG_FIELD(0x3000, 0, 0), -}; - -static const struct reg_field rp1_rio_fields[] = { - [RP1_RIO_OUT_SET] = REG_FIELD(0x2000, 0, 0), - [RP1_RIO_OUT_CLR] = REG_FIELD(0x3000, 0, 0), - [RP1_RIO_OE] = REG_FIELD(0x0004, 0, 0), - [RP1_RIO_OE_SET] = REG_FIELD(0x2004, 0, 0), - [RP1_RIO_OE_CLR] = REG_FIELD(0x3004, 0, 0), - [RP1_RIO_IN] = REG_FIELD(0x0008, 0, 0), -}; - -static const struct reg_field rp1_pad_fields[] = { - [RP1_PAD_SLEWFAST] = REG_FIELD(0, 0, 0), - [RP1_PAD_SCHMITT] = REG_FIELD(0, 1, 1), - [RP1_PAD_PULL] = REG_FIELD(0, 2, 3), - [RP1_PAD_DRIVE] = REG_FIELD(0, 4, 5), - [RP1_PAD_IN_ENABLE] = REG_FIELD(0, 6, 6), - [RP1_PAD_OUT_DISABLE] = REG_FIELD(0, 7, 7), -}; +#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_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_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_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 FUNC(f) \ [func_##f] = #f @@ -172,6 +175,31 @@ static const struct reg_field rp1_pad_fields[] = { func_##f3, \ } +struct rp1_iobank_desc { + int min_gpio; + int num_gpios; + int gpio_offset; + int inte_offset; + int ints_offset; + int rio_offset; + int pads_offset; +}; + +struct rp1_pin_info { + u8 num; + u8 bank; + u8 offset; + u8 fsel; + u8 irq_type; + + void __iomem *gpio; + void __iomem *rio; + void __iomem *inte; + void __iomem *ints; + void __iomem *pad; + void __iomem *dummy; +}; + enum funcs { func_alt0, func_alt1, @@ -184,9 +212,12 @@ enum funcs { 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, @@ -210,6 +241,7 @@ enum funcs { func_proc_rio, func_pwm0, func_pwm1, + func_ri0, func_sd0, func_sd1, func_spi0, @@ -240,34 +272,12 @@ struct rp1_pin_funcs { u8 funcs[RP1_FSEL_COUNT]; }; -struct rp1_iobank_desc { - int min_gpio; - int num_gpios; - int gpio_offset; - int inte_offset; - int ints_offset; - int rio_offset; - int pads_offset; -}; - -struct rp1_pin_info { - u8 num; - u8 bank; - u8 offset; - u8 fsel; - u8 irq_type; - - struct regmap_field *gpio[ARRAY_SIZE(rp1_gpio_fields)]; - struct regmap_field *rio[ARRAY_SIZE(rp1_rio_fields)]; - struct regmap_field *inte[ARRAY_SIZE(rp1_inte_fields)]; - struct regmap_field *pad[ARRAY_SIZE(rp1_pad_fields)]; -}; - struct rp1_pinctrl { struct device *dev; void __iomem *gpio_base; void __iomem *rio_base; void __iomem *pads_base; + void __iomem *dummy_base; int irq[RP1_NUM_BANKS]; struct rp1_pin_info pins[RP1_NUM_GPIOS]; @@ -278,6 +288,13 @@ struct rp1_pinctrl { raw_spinlock_t irq_lock[RP1_NUM_BANKS]; }; +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 }, + { 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[] = { @@ -337,227 +354,128 @@ static struct pinctrl_pin_desc rp1_gpio_pins[] = { RP1_GPIO_PIN(53), }; -#define PIN_ARRAY(...) \ - (const unsigned int []) {__VA_ARGS__} -#define PIN_ARRAY_SIZE(...) \ - (sizeof((unsigned int[]) {__VA_ARGS__}) / sizeof(unsigned int)) -#define RP1_GROUP(name, ...) \ - PINCTRL_PINGROUP(#name, PIN_ARRAY(__VA_ARGS__), \ - PIN_ARRAY_SIZE(__VA_ARGS__)) - -static const struct pingroup rp1_gpio_groups[] = { - RP1_GROUP(uart0, 14, 15), - RP1_GROUP(uart0_ctrl, 4, 5, 6, 7, 16, 17), - RP1_GROUP(uart1, 0, 1), - RP1_GROUP(uart1_ctrl, 2, 3), - RP1_GROUP(uart2, 4, 5), - RP1_GROUP(uart2_ctrl, 6, 7), - RP1_GROUP(uart3, 8, 9), - RP1_GROUP(uart3_ctrl, 10, 11), - RP1_GROUP(uart4, 12, 13), - RP1_GROUP(uart4_ctrl, 14, 15), - RP1_GROUP(uart5_0, 30, 31), - RP1_GROUP(uart5_0_ctrl, 32, 33), - RP1_GROUP(uart5_1, 36, 37), - RP1_GROUP(uart5_1_ctrl, 38, 39), - RP1_GROUP(uart5_2, 40, 41), - RP1_GROUP(uart5_2_ctrl, 42, 43), - RP1_GROUP(uart5_3, 48, 49), - RP1_GROUP(sd0, 22, 23, 24, 25, 26, 27), - RP1_GROUP(sd1, 28, 29, 30, 31, 32, 33), - RP1_GROUP(i2s0, 18, 19, 20, 21), - RP1_GROUP(i2s0_dual, 18, 19, 20, 21, 22, 23), - RP1_GROUP(i2s0_quad, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27), - RP1_GROUP(i2s1, 18, 19, 20, 21), - RP1_GROUP(i2s1_dual, 18, 19, 20, 21, 22, 23), - RP1_GROUP(i2s1_quad, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27), - RP1_GROUP(i2s2_0, 28, 29, 30, 31), - RP1_GROUP(i2s2_0_dual, 28, 29, 30, 31, 32, 33), - RP1_GROUP(i2s2_1, 42, 43, 44, 45), - RP1_GROUP(i2s2_1_dual, 42, 43, 44, 45, 46, 47), - RP1_GROUP(i2c4_0, 28, 29), - RP1_GROUP(i2c4_1, 34, 35), - RP1_GROUP(i2c4_2, 40, 41), - RP1_GROUP(i2c4_3, 46, 47), - RP1_GROUP(i2c6_0, 38, 39), - RP1_GROUP(i2c6_1, 51, 52), - RP1_GROUP(i2c5_0, 30, 31), - RP1_GROUP(i2c5_1, 36, 37), - RP1_GROUP(i2c5_2, 44, 45), - RP1_GROUP(i2c5_3, 49, 50), - RP1_GROUP(i2c0_0, 0, 1), - RP1_GROUP(i2c0_1, 8, 9), - RP1_GROUP(i2c1_0, 2, 3), - RP1_GROUP(i2c1_1, 10, 11), - RP1_GROUP(i2c2_0, 4, 5), - RP1_GROUP(i2c2_1, 12, 13), - RP1_GROUP(i2c3_0, 6, 7), - RP1_GROUP(i2c3_1, 14, 15), - RP1_GROUP(i2c3_2, 22, 23), - RP1_GROUP(dpi_16bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19), - RP1_GROUP(dpi_16bit_cpadhi, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24), - RP1_GROUP(dpi_16bit_pad666, 0, 1, 2, 3, 5, 6, 7, 8, 9, - 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25), - RP1_GROUP(dpi_18bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21), - RP1_GROUP(dpi_18bit_cpadhi, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, - 25), - RP1_GROUP(dpi_24bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27), - RP1_GROUP(spi0, 9, 10, 11), - RP1_GROUP(spi0_quad, 0, 1, 9, 10, 11), - RP1_GROUP(spi1, 19, 20, 21), - RP1_GROUP(spi2, 1, 2, 3), - RP1_GROUP(spi3, 5, 6, 7), - RP1_GROUP(spi4, 9, 10, 11), - RP1_GROUP(spi5, 13, 14, 15), - RP1_GROUP(spi6_0, 28, 29, 30), - RP1_GROUP(spi6_1, 40, 41, 42), - RP1_GROUP(spi7_0, 46, 47, 48), - RP1_GROUP(spi7_1, 49, 50, 51), - RP1_GROUP(spi8_0, 37, 38, 39), - RP1_GROUP(spi8_1, 49, 50, 51), - RP1_GROUP(aaud_0, 12, 13), - RP1_GROUP(aaud_1, 38, 39), - RP1_GROUP(aaud_2, 40, 41), - RP1_GROUP(aaud_3, 49, 50), - RP1_GROUP(aaud_4, 51, 52), - RP1_GROUP(vbus0_0, 28, 29), - RP1_GROUP(vbus0_1, 34, 35), - RP1_GROUP(vbus1, 42, 43), - RP1_GROUP(vbus2, 50, 51), - RP1_GROUP(vbus3, 52, 53), - RP1_GROUP(mic_0, 25, 26, 27), - RP1_GROUP(mic_1, 34, 35, 36), - RP1_GROUP(mic_2, 37, 38, 39), - RP1_GROUP(mic_3, 46, 47, 48), - RP1_GROUP(ir, 2, 3), +/* 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", }; -#define GRP_ARRAY(...) \ - (const char * []) {__VA_ARGS__} -#define GRP_ARRAY_SIZE(...) \ - (sizeof((char *[]) {__VA_ARGS__}) / sizeof(char *)) -#define RP1_FNC(f, ...) \ - [func_##f] = PINCTRL_PINFUNCTION(#f, GRP_ARRAY(__VA_ARGS__), \ - GRP_ARRAY_SIZE(__VA_ARGS__)) -#define RP1_NULL_FNC(f) \ - [func_##f] = PINCTRL_PINFUNCTION(#f, NULL, 0) -#define RP1_ALL_LEGACY_PINS \ - "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", \ - "gpio5", "gpio6", "gpio7", "gpio8", "gpio9", \ - "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", \ - "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", \ - "gpio20", "gpio21", "gpio22", "gpio32", "gpio24", \ - "gpio25", "gpio26", "gpio27" -#define RP1_ALL_PINS RP1_ALL_LEGACY_PINS, \ - "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 struct pinfunction rp1_func_names[] = { - RP1_NULL_FNC(alt0), - RP1_NULL_FNC(alt1), - RP1_NULL_FNC(alt2), - RP1_NULL_FNC(alt3), - RP1_NULL_FNC(alt4), - RP1_FNC(gpio, RP1_ALL_PINS), - RP1_NULL_FNC(alt6), - RP1_NULL_FNC(alt7), - RP1_NULL_FNC(alt8), - RP1_NULL_FNC(none), - RP1_FNC(aaud, "aaud_0", "aaud_1", "aaud_2", "aaud_3", "aaud_4", - "gpio12", "gpio13", "gpio38", "gpio39", "gpio40", "gpio41", - "gpio49", "gpio50", "gpio51", "gpio52"), - RP1_FNC(dpi, "dpi_16bit", "dpi_16bit_cpadhi", - "dpi_16bit_pad666", "dpi_18bit, dpi_18bit_cpadhi", - "dpi_24bit", RP1_ALL_LEGACY_PINS), - RP1_FNC(dsi0_te_ext, "gpio16", "gpio38", "gpio46"), - RP1_FNC(dsi1_te_ext, "gpio17", "gpio39", "gpio47"), - RP1_FNC(gpclk0, "gpio4", "gpio20"), - RP1_FNC(gpclk1, "gpio5", "gpio18", "gpio21"), - RP1_FNC(gpclk2, "gpio6"), - RP1_FNC(gpclk3, "gpio32", "gpio34", "gpio46"), - RP1_FNC(gpclk4, "gpio33", "gpio43"), - RP1_FNC(gpclk5, "gpio42", "gpio44", "gpio47"), - RP1_FNC(i2c0, "i2c0_0", "i2c0_1", "gpio0", "gpio1", "gpio8", "gpio9"), - RP1_FNC(i2c1, "i2c1_0", "i2c1_1", "gpio2", "gpio3", "gpio10", "gpio11"), - RP1_FNC(i2c2, "i2c2_0", "i2c2_1", "gpio4", "gpio5", "gpio12", "gpio13"), - RP1_FNC(i2c3, "i2c3_0", "i2c3_1", "i2c3_2", "gpio6", "gpio7", "gpio14", - "gpio15", "gpio22", "gpio23"), - RP1_FNC(i2c4, "i2c4_0", "i2c4_1", "i2c4_2", "i2c4_3", "gpio28", - "gpio29", "gpio34", "gpio35", "gpio40", "gpio41", "gpio46", - "gpio47"), - RP1_FNC(i2c5, "i2c5_0", "i2c5_1", "i2c5_2", "i2c5_3", "gpio30", - "gpio31", "gpio36", "gpio37", "gpio44", "gpio45", "gpio49", - "gpio50"), - RP1_FNC(i2c6, "i2c6_0", "i2c6_1", "gpio38", "gpio39", "gpio51", - "gpio52"), - RP1_FNC(i2s0, "i2s0", "i2s0_dual", "i2s0_quad", "gpio18", "gpio19", - "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", - "gpio26", "gpio27"), - RP1_FNC(i2s1, "i2s1", "i2s1_dual", "i2s1_quad", "gpio18", "gpio19", - "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", - "gpio26", "gpio27"), - RP1_FNC(i2s2, "i2s2_0", "i2s2_0_dual", "i2s2_1", "i2s2_1_dual", - "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", - "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47"), - RP1_FNC(ir, "gpio2", "gpio3"), - RP1_FNC(mic, "mic_0", "mic_1", "mic_2", "mic_3", "gpio25", "gpio26", - "gpio27", "gpio34", "gpio35", "gpio36", "gpio37", "gpio38", - "gpio39", "gpio46", "gpio47", "gpio48"), - RP1_FNC(pcie_clkreq_n, "gpio36", "gpio37", "gpio48", "gpio53"), - RP1_FNC(pio, RP1_ALL_LEGACY_PINS), - RP1_FNC(proc_rio, RP1_ALL_PINS), - RP1_FNC(pwm0, "gpio12", "gpio13", "gpio14", "gpio15", "gpio18", - "gpio19"), - RP1_FNC(pwm1, "gpio34", "gpio35", "gpio40", "gpio41", "gpio44", - "gpio45", "gpio48"), - RP1_FNC(sd0, "sd0", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", - "gpio27"), - RP1_FNC(sd1, "sd1", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio33"), - RP1_FNC(spi0, "spi0", "spi0_quad", "gpio0", "gpio1", "gpio2", "gpio3", - "gpio7", "gpio8", "gpio9", "gpio10", "gpio11"), - RP1_FNC(spi1, "spi1", "gpio19", "gpio20", "gpio21", "gpio16", "gpio17", - "gpio18", "gpio27"), - RP1_FNC(spi2, "spi2", "gpio0", "gpio1", "gpio2", "gpio3", "gpio24"), - RP1_FNC(spi3, "spi3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio25"), - RP1_FNC(spi4, "spi4", "gpio8", "gpio9", "gpio10", "gpio11"), - RP1_FNC(spi5, "spi5", "gpio12", "gpio13", "gpio14", "gpio15", "gpio26"), - RP1_FNC(spi6, "spi6_0", "spi6_1", "gpio28", "gpio29", "gpio30", - "gpio31", "gpio32", "gpio33", "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45"), - RP1_FNC(spi7, "spi7_0", "spi7_1", "gpio45", "gpio46", "gpio47", - "gpio48", "gpio49", "gpio50", "gpio51", "gpio53"), - RP1_FNC(spi8, "spi8_0", "spi8_1", "gpio35", "gpio36", "gpio37", - "gpio38", "gpio39", "gpio49", "gpio50", "gpio51", "gpio52", - "gpio53"), - RP1_FNC(uart0, "uart0", "uart0_ctrl", "gpio4", "gpio5", "gpio6", - "gpio7", "gpio14", "gpio15", "gpio16", "gpio17"), - RP1_FNC(uart1, "uart1", "uart1_ctrl", "gpio0", "gpio1", "gpio2", - "gpio3"), - RP1_FNC(uart2, "uart2", "uart2_ctrl", "gpio4", "gpio5", "gpio6", - "gpio7"), - RP1_FNC(uart3, "uart3", "uart3_ctrl", "gpio8", "gpio9", "gpio10", - "gpio11"), - RP1_FNC(uart4, "uart4", "uart4_ctrl", "gpio12", "gpio13", "gpio14", - "gpio15"), - RP1_FNC(uart5, "uart5_0", "uart5_0_ctrl", "uart5_1", "uart5_1_ctrl", - "uart5_2", "uart5_2_ctrl", "uart5_3"), - RP1_FNC(vbus0, "vbus0_0", "vbus0_1", "gpio28", "gpio29", "gpio34", - "gpio35"), - RP1_FNC(vbus1, "vbus1", "gpio42", "gpio43"), - RP1_FNC(vbus2, "vbus2", "gpio50", "gpio51"), - RP1_FNC(vbus3, "vbus3", "gpio52", "gpio53"), - RP1_NULL_FNC(invalid), //[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[] = { @@ -565,10 +483,10 @@ static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] = { PIN(1, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2), PIN(2, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2), PIN(3, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2), - PIN(4, gpclk0, dpi, uart2, i2c2, uart0, gpio, proc_rio, pio, spi3), - PIN(5, gpclk1, dpi, uart2, i2c2, uart0, gpio, proc_rio, pio, spi3), - PIN(6, gpclk2, dpi, uart2, i2c3, uart0, gpio, proc_rio, pio, spi3), - PIN(7, spi0, dpi, uart2, i2c3, uart0, gpio, proc_rio, pio, spi3), + PIN(4, gpclk0, dpi, uart2, i2c2, ri0, gpio, proc_rio, pio, spi3), + PIN(5, gpclk1, dpi, uart2, i2c2, dtr0, gpio, proc_rio, pio, spi3), + PIN(6, gpclk2, dpi, uart2, i2c3, dcd0, gpio, proc_rio, pio, spi3), + PIN(7, spi0, dpi, uart2, i2c3, dsr0, gpio, proc_rio, pio, spi3), PIN(8, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4), PIN(9, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4), PIN(10, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4), @@ -661,12 +579,41 @@ 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"); -static 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 }, - { 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 }, -}; +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"); + +static inline void rp1_pin_writel(u32 val, void __iomem *dummy, void __iomem *reg) +{ + unsigned long flags; + + local_irq_save(flags); + /* + * Issuing 6 pipelined writes to the RC's Slot Control register will stall the + * peripheral bus inside 2712 if the link is in L1. This acts as a lightweight + * "fence" operation preventing back-to-back writes arriving at RP1 on a wake. + */ + if (dummy) { + writel_relaxed(0, dummy); + writel_relaxed(0, dummy); + writel_relaxed(0, dummy); + writel_relaxed(0, dummy); + writel_relaxed(0, dummy); + writel_relaxed(0, dummy); + } + writel_relaxed(val, reg); + local_irq_restore(flags); +} + +static inline u32 rp1_pin_readl(const void __iomem *ioaddr) +{ + /* + * Prior posted writes may not yet have been emitted by the CPU - do a store-flush + * before reading GPIO state, as this will serialise writes versus the next issued read. + */ + __dma_wmb(); + return readl(ioaddr); +} static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, unsigned long *configs, @@ -692,22 +639,33 @@ static struct rp1_pin_info *rp1_get_pin_pctl(struct pinctrl_dev *pctldev, return NULL; } +static void rp1_pad_update(struct rp1_pin_info *pin, u32 clr, u32 set) +{ + u32 padctrl = rp1_pin_readl(pin->pad); + + padctrl &= ~clr; + padctrl |= set; + + rp1_pin_writel(padctrl, pin->dummy, pin->pad); +} + static void rp1_input_enable(struct rp1_pin_info *pin, int value) { - regmap_field_write(pin->pad[RP1_PAD_IN_ENABLE], !!value); + rp1_pad_update(pin, RP1_PAD_IN_ENABLE_MASK, + value ? RP1_PAD_IN_ENABLE_MASK : 0); } static void rp1_output_enable(struct rp1_pin_info *pin, int value) { - regmap_field_write(pin->pad[RP1_PAD_OUT_DISABLE], !value); + rp1_pad_update(pin, RP1_PAD_OUT_DISABLE_MASK, + value ? 0 : RP1_PAD_OUT_DISABLE_MASK); } static u32 rp1_get_fsel(struct rp1_pin_info *pin) { - u32 oeover, fsel; - - regmap_field_read(pin->gpio[RP1_GPIO_CTRL_OEOVER], &oeover); - regmap_field_read(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], &fsel); + u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL); + u32 oeover = FLD_GET(ctrl, RP1_GPIO_CTRL_OEOVER); + u32 fsel = FLD_GET(ctrl, RP1_GPIO_CTRL_FUNCSEL); if (oeover != RP1_OEOVER_PERI || fsel >= RP1_FSEL_COUNT) fsel = RP1_FSEL_NONE; @@ -717,6 +675,8 @@ static u32 rp1_get_fsel(struct rp1_pin_info *pin) static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel) { + u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL); + if (fsel >= RP1_FSEL_COUNT) fsel = RP1_FSEL_NONE_HW; @@ -724,62 +684,52 @@ static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel) rp1_output_enable(pin, 1); if (fsel == RP1_FSEL_NONE) { - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_DISABLE); + FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_DISABLE); } else { - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OUTOVER], RP1_OUTOVER_PERI); - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_PERI); + FLD_SET(ctrl, RP1_GPIO_CTRL_OUTOVER, RP1_OUTOVER_PERI); + FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_PERI); } - - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], fsel); + FLD_SET(ctrl, RP1_GPIO_CTRL_FUNCSEL, fsel); + rp1_pin_writel(ctrl, pin->dummy, pin->gpio + RP1_GPIO_CTRL); } static int rp1_get_dir(struct rp1_pin_info *pin) { - unsigned int val; - - regmap_field_read(pin->rio[RP1_RIO_OE], &val); - - return !val ? RP1_DIR_INPUT : RP1_DIR_OUTPUT; + return !(rp1_pin_readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ? + RP1_DIR_INPUT : RP1_DIR_OUTPUT; } static void rp1_set_dir(struct rp1_pin_info *pin, bool is_input) { - int reg = is_input ? RP1_RIO_OE_CLR : RP1_RIO_OE_SET; + int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET; - regmap_field_write(pin->rio[reg], 1); + rp1_pin_writel(1 << pin->offset, pin->dummy, pin->rio + RP1_RIO_OE + offset); } static int rp1_get_value(struct rp1_pin_info *pin) { - unsigned int val; - - regmap_field_read(pin->rio[RP1_RIO_IN], &val); - - return !!val; + return !!(rp1_pin_readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset)); } static void rp1_set_value(struct rp1_pin_info *pin, int value) { /* Assume the pin is already an output */ - int reg = value ? RP1_RIO_OUT_SET : RP1_RIO_OUT_CLR; - - regmap_field_write(pin->rio[reg], 1); + rp1_pin_writel(1 << pin->offset, pin->dummy, + pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); } -static int rp1_gpio_get(struct gpio_chip *chip, unsigned int offset) +static int rp1_gpio_get(struct gpio_chip *chip, unsigned offset) { struct rp1_pin_info *pin = rp1_get_pin(chip, offset); int ret; if (!pin) return -EINVAL; - ret = rp1_get_value(pin); - return ret; } -static int rp1_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +static int rp1_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct rp1_pin_info *pin = rp1_get_pin(chip, offset); @@ -796,17 +746,15 @@ static int rp1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) if (!pin) return -EINVAL; - 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; } -static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) +static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct rp1_pin_info *pin = rp1_get_pin(chip, offset); @@ -814,11 +762,10 @@ static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) return -EINVAL; rp1_set_dir(pin, RP1_DIR_INPUT); rp1_set_fsel(pin, RP1_FSEL_GPIO); - return 0; } -static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, +static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { struct rp1_pin_info *pin = rp1_get_pin(chip, offset); @@ -828,18 +775,17 @@ static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned int offset rp1_set_value(pin, value); rp1_set_dir(pin, RP1_DIR_OUTPUT); rp1_set_fsel(pin, RP1_FSEL_GPIO); - return 0; } -static int rp1_gpio_set_config(struct gpio_chip *chip, unsigned int offset, +static int rp1_gpio_set_config(struct gpio_chip *gc, unsigned offset, unsigned long config) { - struct rp1_pinctrl *pc = gpiochip_get_data(chip); + struct rp1_pinctrl *pc = gpiochip_get_data(gc); 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 = { @@ -861,12 +807,12 @@ static const struct gpio_chip rp1_gpio_chip = { static void rp1_gpio_irq_handler(struct irq_desc *desc) { struct gpio_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *host_chip = irq_desc_get_chip(desc); struct rp1_pinctrl *pc = gpiochip_get_data(chip); + struct irq_chip *host_chip = irq_desc_get_chip(desc); const struct rp1_iobank_desc *bank; int irq = irq_desc_get_irq(desc); unsigned long ints; - int bit_pos; + int b; if (pc->irq[0] == irq) bank = &rp1_iobanks[0]; @@ -878,12 +824,13 @@ static void rp1_gpio_irq_handler(struct irq_desc *desc) chained_irq_enter(host_chip, desc); ints = readl(pc->gpio_base + bank->ints_offset); - for_each_set_bit(bit_pos, &ints, 32) { - struct rp1_pin_info *pin = rp1_get_pin(chip, bit_pos); + for_each_set_bit(b, &ints, 32) { + struct rp1_pin_info *pin = rp1_get_pin(chip, bank->min_gpio + b); - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1); + 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->gpio_offset + bit_pos)); + bank->min_gpio + b)); } chained_irq_exit(host_chip, desc); @@ -891,18 +838,18 @@ static void rp1_gpio_irq_handler(struct irq_desc *desc) static void rp1_gpio_irq_config(struct rp1_pin_info *pin, bool enable) { - int reg = enable ? RP1_INTE_SET : RP1_INTE_CLR; - - regmap_field_write(pin->inte[reg], 1); + writel(1 << pin->offset, + pin->inte + (enable ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); if (!enable) /* Clear any latched events */ - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1); + writel(RP1_GPIO_CTRL_IRQRESET, + pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); } static void rp1_gpio_irq_enable(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - unsigned int gpio = irqd_to_hwirq(data); + unsigned gpio = irqd_to_hwirq(data); struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); rp1_gpio_irq_config(pin, true); @@ -911,7 +858,7 @@ static void rp1_gpio_irq_enable(struct irq_data *data) static void rp1_gpio_irq_disable(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - unsigned int gpio = irqd_to_hwirq(data); + unsigned gpio = irqd_to_hwirq(data); struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); rp1_gpio_irq_config(pin, false); @@ -945,11 +892,15 @@ static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type) return -EINVAL; } - /* Clear them all */ - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_CLR], RP1_INT_MASK); - - /* Set those that are needed */ - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_SET], irq_flags); + /* Clear the event enables */ + writel(RP1_INT_MASK << RP1_GPIO_EVENTS_SHIFT_RAW, + 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); + /* Enable the events that are needed */ + writel(irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW, + pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); pin->irq_type = type; return 0; @@ -958,9 +909,9 @@ static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type) static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - unsigned int gpio = irqd_to_hwirq(data); - struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); struct rp1_pinctrl *pc = gpiochip_get_data(chip); + unsigned gpio = irqd_to_hwirq(data); + struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); int bank = pin->bank; unsigned long flags; int ret; @@ -983,11 +934,11 @@ static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type) static void rp1_gpio_irq_ack(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - unsigned int gpio = irqd_to_hwirq(data); + unsigned gpio = irqd_to_hwirq(data); struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); /* Clear any latched events */ - regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1); + 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) @@ -1023,26 +974,20 @@ static struct irq_chip rp1_gpio_irq_chip = { .irq_unmask = rp1_gpio_irq_enable, .irq_set_affinity = rp1_gpio_irq_set_affinity, .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int rp1_pctl_get_groups_count(struct pinctrl_dev *pctldev) { - return ARRAY_SIZE(rp1_gpio_groups) + ARRAY_SIZE(rp1_gpio_pins); + return ARRAY_SIZE(rp1_gpio_groups); } static const char *rp1_pctl_get_group_name(struct pinctrl_dev *pctldev, - unsigned int selector) + unsigned selector) { - unsigned int ngroups = ARRAY_SIZE(rp1_gpio_groups); - - if (selector < ngroups) - return rp1_gpio_groups[selector].name; - - return rp1_gpio_pins[selector - ngroups].name; + return rp1_gpio_groups[selector]; } -static enum funcs rp1_get_fsel_func(unsigned int pin, unsigned int fsel) +static enum funcs rp1_get_fsel_func(unsigned pin, unsigned fsel) { if (pin < RP1_NUM_GPIOS) { if (fsel < RP1_FSEL_COUNT) @@ -1054,26 +999,19 @@ static enum funcs rp1_get_fsel_func(unsigned int pin, unsigned int fsel) } static int rp1_pctl_get_group_pins(struct pinctrl_dev *pctldev, - unsigned int selector, - const unsigned int **pins, - unsigned int *num_pins) + unsigned selector, + const unsigned **pins, + unsigned *num_pins) { - unsigned int ngroups = ARRAY_SIZE(rp1_gpio_groups); - - if (selector < ngroups) { - *pins = rp1_gpio_groups[selector].pins; - *num_pins = rp1_gpio_groups[selector].npins; - } else { - *pins = &rp1_gpio_pins[selector - ngroups].number; - *num_pins = 1; - } + *pins = &rp1_gpio_pins[selector].number; + *num_pins = 1; return 0; } static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, - unsigned int offset) + unsigned offset) { struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); struct gpio_chip *chip = &pc->gpio_chip; @@ -1084,13 +1022,13 @@ static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, int irq = irq_find_mapping(chip->irq.domain, offset); seq_printf(s, "function %s (%s) in %s; irq %d (%s)", - rp1_func_names[fsel].name, rp1_func_names[func].name, + rp1_func_names[fsel], rp1_func_names[func], value ? "hi" : "lo", irq, irq_type_names[pin->irq_type]); } static void rp1_pctl_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *maps, unsigned int num_maps) + struct pinctrl_map *maps, unsigned num_maps) { int i; @@ -1124,11 +1062,14 @@ static int rp1_pctl_legacy_map_func(struct rp1_pinctrl *pc, return -EINVAL; } + if (func == func_invalid) { + dev_err(pc->dev, "%pOF: brcm,function %d not supported on pin %d\n", + np, fnum, pin); + } + map->type = PIN_MAP_TYPE_MUX_GROUP; - map->data.mux.group = rp1_pctl_get_group_name(pc->pctl_dev, - ARRAY_SIZE(rp1_gpio_groups) - + pin); - map->data.mux.function = rp1_func_names[func].name; + map->data.mux.group = rp1_gpio_groups[pin]; + map->data.mux.function = rp1_func_names[func]; (*num_maps)++; return 0; @@ -1254,7 +1195,7 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } else if (function) { err = pinctrl_utils_add_map_mux(pctldev, &maps, &reserved_maps, num_maps, - rp1_gpio_groups[pin].name, + rp1_gpio_groups[pin], function); } @@ -1272,7 +1213,7 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } else if (num_configs) { err = pinctrl_utils_add_map_configs(pctldev, &maps, &reserved_maps, num_maps, - rp1_gpio_groups[pin].name, + rp1_gpio_groups[pin], configs, num_configs, PIN_MAP_TYPE_CONFIGS_PIN); } @@ -1299,7 +1240,7 @@ static const struct pinctrl_ops rp1_pctl_ops = { .dt_free_map = rp1_pctl_dt_free_map, }; -static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned int offset) +static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned offset) { struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); u32 fsel = rp1_get_fsel(pin); @@ -1320,66 +1261,61 @@ static int rp1_pmx_get_functions_count(struct pinctrl_dev *pctldev) } static const char *rp1_pmx_get_function_name(struct pinctrl_dev *pctldev, - unsigned int selector) + unsigned selector) { - return (selector < func_count) ? rp1_func_names[selector].name : NULL; + return (selector < func_count) ? rp1_func_names[selector] : NULL; } static int rp1_pmx_get_function_groups(struct pinctrl_dev *pctldev, - unsigned int selector, + unsigned selector, const char * const **groups, unsigned * const num_groups) { - *groups = rp1_func_names[selector].groups; - *num_groups = rp1_func_names[selector].ngroups; + /* every pin can do every function */ + *groups = rp1_gpio_groups; + *num_groups = ARRAY_SIZE(rp1_gpio_groups); return 0; } -static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned int func_selector, - unsigned int group_selector) +static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned func_selector, + unsigned group_selector) { - struct rp1_pin_info *pin; - const unsigned int *pins; + struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, group_selector); const u8 *pin_funcs; - unsigned int num_pins; - int offset, fsel; - - rp1_pctl_get_group_pins(pctldev, group_selector, &pins, &num_pins); - - for (offset = 0; offset < num_pins; ++offset) { - pin = rp1_get_pin_pctl(pctldev, pins[offset]); - /* func_selector is an enum funcs, so needs translation */ - if (func_selector >= RP1_FSEL_COUNT) { - /* Convert to an fsel number */ - pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs; - for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) { - if (pin_funcs[fsel] == func_selector) - break; - } - } else { - fsel = (int)func_selector; - } + int fsel; - if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE) - return -EINVAL; + /* func_selector is an enum funcs, so needs translation */ - rp1_set_fsel(pin, fsel); + if (func_selector >= RP1_FSEL_COUNT) { + /* Convert to an fsel number */ + pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs; + for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) { + if (pin_funcs[fsel] == func_selector) + break; + } + } else { + fsel = (int)func_selector; } + if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE) + return -EINVAL; + + rp1_set_fsel(pin, fsel); + return 0; } static void rp1_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, - unsigned int offset) + unsigned offset) { (void)rp1_pmx_free(pctldev, offset); } static int rp1_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, - unsigned int offset, + unsigned offset, bool input) { struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); @@ -1402,9 +1338,15 @@ static const struct pinmux_ops rp1_pmx_ops = { static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg) { - regmap_field_write(pin->pad[RP1_PAD_PULL], arg & 0x3); + u32 padctrl = rp1_pin_readl(pin->pad); + + FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3); + + writel(padctrl, pin->pad); } +/* Generic pinconf methods */ + static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, unsigned long *configs, unsigned int num_configs) { @@ -1447,11 +1389,13 @@ static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - regmap_field_write(pin->pad[RP1_PAD_SCHMITT], !!arg); + rp1_pad_update(pin, RP1_PAD_SCHMITT_MASK, + arg ? RP1_PAD_SCHMITT_MASK : 0); break; case PIN_CONFIG_SLEW_RATE: - regmap_field_write(pin->pad[RP1_PAD_SLEWFAST], !!arg); + rp1_pad_update(pin, RP1_PAD_SLEWFAST_MASK, + arg ? RP1_PAD_SLEWFAST_MASK : 0); break; case PIN_CONFIG_DRIVE_STRENGTH: @@ -1471,7 +1415,7 @@ static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, default: return -ENOTSUPP; } - regmap_field_write(pin->pad[RP1_PAD_DRIVE], arg); + rp1_pad_update(pin, RP1_PAD_DRIVE_MASK, arg); break; default: @@ -1483,7 +1427,7 @@ static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, return 0; } -static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset, +static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned offset, unsigned long *config) { struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); @@ -1494,26 +1438,23 @@ static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset, if (!pin) return -EINVAL; + padctrl = rp1_pin_readl(pin->pad); + switch (param) { case PIN_CONFIG_INPUT_ENABLE: - regmap_field_read(pin->pad[RP1_PAD_IN_ENABLE], &padctrl); - arg = !!padctrl; + arg = !!(padctrl & RP1_PAD_IN_ENABLE_MASK); break; case PIN_CONFIG_OUTPUT_ENABLE: - regmap_field_read(pin->pad[RP1_PAD_OUT_DISABLE], &padctrl); - arg = !padctrl; + arg = !(padctrl & RP1_PAD_OUT_DISABLE_MASK); break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - regmap_field_read(pin->pad[RP1_PAD_SCHMITT], &padctrl); - arg = !!padctrl; + arg = !!(padctrl & RP1_PAD_SCHMITT_MASK); break; case PIN_CONFIG_SLEW_RATE: - regmap_field_read(pin->pad[RP1_PAD_SLEWFAST], &padctrl); - arg = !!padctrl; + arg = !!(padctrl & RP1_PAD_SLEWFAST_MASK); break; case PIN_CONFIG_DRIVE_STRENGTH: - regmap_field_read(pin->pad[RP1_PAD_DRIVE], &padctrl); - switch (padctrl) { + switch (padctrl & RP1_PAD_DRIVE_MASK) { case RP1_PAD_DRIVE_2MA: arg = 2; break; @@ -1529,17 +1470,14 @@ static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset, } break; case PIN_CONFIG_BIAS_DISABLE: - regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl); - arg = ((padctrl == RP1_PUD_OFF)); + arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_OFF << RP1_PAD_PULL_LSB)); break; case PIN_CONFIG_BIAS_PULL_DOWN: - regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl); - arg = ((padctrl == RP1_PUD_DOWN)); + arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_DOWN << RP1_PAD_PULL_LSB)); break; case PIN_CONFIG_BIAS_PULL_UP: - regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl); - arg = ((padctrl == RP1_PUD_UP)); + arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_UP << RP1_PAD_PULL_LSB)); break; default: return -ENOTSUPP; @@ -1550,51 +1488,10 @@ static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset, return 0; } -static int rp1_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned int selector, - unsigned long *config) -{ - const unsigned int *pins; - unsigned int npins; - int ret; - - ret = rp1_pctl_get_group_pins(pctldev, selector, &pins, &npins); - if (ret < 0) - return ret; - - if (!npins) - return -ENODEV; - - ret = rp1_pinconf_get(pctldev, pins[0], config); - - return ret; -} - -static int rp1_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned int selector, - unsigned long *configs, unsigned int num_configs) -{ - const unsigned int *pins; - unsigned int npins; - int ret, i; - - ret = rp1_pctl_get_group_pins(pctldev, selector, &pins, &npins); - if (ret < 0) - return ret; - - for (i = 0; i < npins; i++) { - ret = rp1_pinconf_set(pctldev, pins[i], configs, num_configs); - if (ret < 0) - return ret; - } - - return 0; -} - static const struct pinconf_ops rp1_pinconf_ops = { .is_generic = true, .pin_config_get = rp1_pinconf_get, .pin_config_set = rp1_pinconf_set, - .pin_config_group_get = rp1_pinconf_group_get, - .pin_config_group_set = rp1_pinconf_group_set, }; static struct pinctrl_desc rp1_pinctrl_desc = { @@ -1617,87 +1514,94 @@ 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_config rp1_pinctrl_regmap_cfg = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .fast_io = true, - .name = "rp1-pinctrl", -}; - -static int rp1_gen_regfield(struct device *dev, - const struct reg_field *array, - size_t array_size, - int reg_off, - int pin_off, - bool additive_offset, - struct regmap *regmap, - struct regmap_field *out[]) +static inline void __iomem *devm_auto_iomap(struct platform_device *pdev, + unsigned int index) { - struct reg_field regfield; - int k; - - for (k = 0; k < array_size; k++) { - regfield = array[k]; - regfield.reg = (additive_offset ? regfield.reg : 0) + reg_off; - if (pin_off >= 0) { - regfield.lsb = pin_off; - regfield.msb = regfield.lsb; - } - out[k] = devm_regmap_field_alloc(dev, regmap, regfield); - - if (IS_ERR(out[k])) - return PTR_ERR(out[k]); - } + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; - return 0; + if (np) + return devm_of_iomap(dev, np, (int)index, NULL); + else + return devm_platform_ioremap_resource(pdev, index); } static int rp1_pinctrl_probe(struct platform_device *pdev) { - struct regmap *gpio_regmap, *rio_regmap, *pads_regmap; - struct rp1_pinctrl *pc = &rp1_pinctrl_data; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + struct device_node *rp1_node = NULL; + struct rp1_pinctrl *pc; struct gpio_irq_chip *girq; int err, i; - pc->dev = dev; - pc->gpio_chip = rp1_gpio_chip; - pc->gpio_chip.parent = dev; + BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_pins) != RP1_NUM_GPIOS); + BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_groups) != RP1_NUM_GPIOS); + + pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); + if (!pc) + return -ENOMEM; - 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"); + platform_set_drvdata(pdev, pc); + pc->dev = dev; - 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->gpio_base = devm_auto_iomap(pdev, 0); + if (IS_ERR(pc->gpio_base)) { + dev_err(dev, "could not get GPIO IO memory\n"); + return PTR_ERR(pc->gpio_base); + } - 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"); + pc->rio_base = devm_auto_iomap(pdev, 1); + if (IS_ERR(pc->rio_base)) { + dev_err(dev, "could not get RIO IO memory\n"); + return PTR_ERR(pc->rio_base); + } - gpio_regmap = devm_regmap_init_mmio(dev, pc->gpio_base, - &rp1_pinctrl_regmap_cfg); - if (IS_ERR(gpio_regmap)) - return dev_err_probe(dev, PTR_ERR(gpio_regmap), "could not init GPIO regmap\n"); + pc->pads_base = devm_auto_iomap(pdev, 2); + if (IS_ERR(pc->pads_base)) { + dev_err(dev, "could not get PADS IO memory\n"); + return PTR_ERR(pc->pads_base); + } - rio_regmap = devm_regmap_init_mmio(dev, pc->rio_base, - &rp1_pinctrl_regmap_cfg); - if (IS_ERR(rio_regmap)) - return dev_err_probe(dev, PTR_ERR(rio_regmap), "could not init RIO regmap\n"); + pc->gpio_chip = rp1_gpio_chip; + pc->gpio_chip.parent = dev; - pads_regmap = devm_regmap_init_mmio(dev, pc->pads_base, - &rp1_pinctrl_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]; @@ -1706,85 +1610,35 @@ static int rp1_pinctrl_probe(struct platform_device *pdev) for (j = 0; j < bank->num_gpios; j++) { struct rp1_pin_info *pin = &pc->pins[bank->min_gpio + j]; - int reg_off; pin->num = bank->min_gpio + j; pin->bank = i; pin->offset = j; - reg_off = bank->gpio_offset + pin->offset * - sizeof(u32) * 2; - err = rp1_gen_regfield(dev, - rp1_gpio_fields, - ARRAY_SIZE(rp1_gpio_fields), - reg_off, - -1, - true, - gpio_regmap, - pin->gpio); - - if (err) - return dev_err_probe(dev, err, - "Unable to allocate regmap for gpio\n"); - - reg_off = bank->inte_offset; - err = rp1_gen_regfield(dev, - rp1_inte_fields, - ARRAY_SIZE(rp1_inte_fields), - reg_off, - pin->offset, - true, - gpio_regmap, - pin->inte); - - if (err) - return dev_err_probe(dev, err, - "Unable to allocate regmap for inte\n"); - - reg_off = bank->rio_offset; - err = rp1_gen_regfield(dev, - rp1_rio_fields, - ARRAY_SIZE(rp1_rio_fields), - reg_off, - pin->offset, - true, - rio_regmap, - pin->rio); - - if (err) - return dev_err_probe(dev, err, - "Unable to allocate regmap for rio\n"); - - reg_off = bank->pads_offset + pin->offset * sizeof(u32); - err = rp1_gen_regfield(dev, - rp1_pad_fields, - ARRAY_SIZE(rp1_pad_fields), - reg_off, - -1, - false, - pads_regmap, - pin->pad); - - if (err) - return dev_err_probe(dev, err, - "Unable to allocate regmap for pad\n"); + pin->gpio = pc->gpio_base + bank->gpio_offset + + 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; } raw_spin_lock_init(&pc->irq_lock[i]); } pc->pctl_dev = devm_pinctrl_register(dev, &rp1_pinctrl_desc, pc); - if (IS_ERR(pc->pctl_dev)) - return dev_err_probe(dev, PTR_ERR(pc->pctl_dev), - "Could not register pin controller\n"); + if (IS_ERR(pc->pctl_dev)) { + err = PTR_ERR(pc->pctl_dev); + goto out_iounmap; + } girq = &pc->gpio_chip.irq; girq->chip = &rp1_gpio_irq_chip; girq->parent_handler = rp1_gpio_irq_handler; girq->num_parents = RP1_NUM_BANKS; girq->parents = pc->irq; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_level_irq; /* * Use the same handler for all groups: this is necessary @@ -1801,11 +1655,14 @@ static int rp1_pinctrl_probe(struct platform_device *pdev) } } - platform_set_drvdata(pdev, pc); + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc); - if (err) - return dev_err_probe(dev, err, "could not add GPIO chip\n"); + if (err) { + dev_err(dev, "could not add GPIO chip\n"); + goto out_iounmap; + } pc->gpio_range = rp1_pinctrl_gpio_range; pc->gpio_range.base = pc->gpio_chip.base; @@ -1813,19 +1670,28 @@ static int rp1_pinctrl_probe(struct platform_device *pdev) pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); return 0; + +out_iounmap: + if (pc->dummy_base) + iounmap(pc->dummy_base); + return err; +} + +static void rp1_pinctrl_remove(struct platform_device *pdev) +{ + struct rp1_pinctrl *pc = platform_get_drvdata(pdev); + + if (pc->dummy_base) + iounmap(pc->dummy_base); } static struct platform_driver rp1_pinctrl_driver = { .probe = rp1_pinctrl_probe, + .remove = rp1_pinctrl_remove, .driver = { .name = MODULE_NAME, .of_match_table = rp1_pinctrl_match, .suppress_bind_attrs = true, }, }; -module_platform_driver(rp1_pinctrl_driver); - -MODULE_AUTHOR("Phil Elwell "); -MODULE_AUTHOR("Andrea della Porta "); -MODULE_DESCRIPTION("RP1 pinctrl/gpio driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(rp1_pinctrl_driver); diff --git a/drivers/power/supply/rpi_poe_power.c b/drivers/power/supply/rpi_poe_power.c index 4f9f5b58916761..80f59fc8266cfb 100644 --- a/drivers/power/supply/rpi_poe_power.c +++ b/drivers/power/supply/rpi_poe_power.c @@ -186,13 +186,13 @@ static int rpi_poe_power_supply_probe(struct platform_device *pdev) if (device_property_read_u32(&pdev->dev, "reg", &ctx->offset)) return -EINVAL; } else { - fw_node = NULL; // hack xxx fwnode_find_reference(pdev->dev.fwnode, "firmware", 0); + fw_node = of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware"); if (!fw_node) { dev_err(&pdev->dev, "Missing firmware node\n"); return -ENOENT; } - ctx->fw = NULL; // hack xxx rpi_firmware_get(fw_node); + ctx->fw = rpi_firmware_get(fw_node); if (!ctx->fw) return -EPROBE_DEFER; if (rpi_firmware_property(ctx->fw,