[PATCH v4 2/2] phy: bcm-sr-pcie: Add Stingray PCIe PHY driver
Add Stingray PCIe PHY driver for both PAXB and PAXC root complex Signed-off-by: Ray Jui --- drivers/phy/broadcom/Kconfig | 10 ++ drivers/phy/broadcom/Makefile | 2 + drivers/phy/broadcom/phy-bcm-sr-pcie.c | 305 + 3 files changed, 317 insertions(+) create mode 100644 drivers/phy/broadcom/phy-bcm-sr-pcie.c diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig index 97d27b0d5..8786a96 100644 --- a/drivers/phy/broadcom/Kconfig +++ b/drivers/phy/broadcom/Kconfig @@ -80,3 +80,13 @@ config PHY_BRCM_USB This driver is required by the USB XHCI, EHCI and OHCI drivers. If unsure, say N. + +config PHY_BCM_SR_PCIE + tristate "Broadcom Stingray PCIe PHY driver" + depends on OF && (ARCH_BCM_IPROC || COMPILE_TEST) + select GENERIC_PHY + select MFD_SYSCON + default ARCH_BCM_IPROC + help + Enable this to support the Broadcom Stingray PCIe PHY + If unsure, say N. diff --git a/drivers/phy/broadcom/Makefile b/drivers/phy/broadcom/Makefile index 13e000c..0f60184 100644 --- a/drivers/phy/broadcom/Makefile +++ b/drivers/phy/broadcom/Makefile @@ -9,3 +9,5 @@ obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o obj-$(CONFIG_PHY_BRCM_USB) += phy-brcm-usb-dvr.o phy-brcm-usb-dvr-objs := phy-brcm-usb.o phy-brcm-usb-init.o + +obj-$(CONFIG_PHY_BCM_SR_PCIE) += phy-bcm-sr-pcie.o diff --git a/drivers/phy/broadcom/phy-bcm-sr-pcie.c b/drivers/phy/broadcom/phy-bcm-sr-pcie.c new file mode 100644 index 000..c10e95f --- /dev/null +++ b/drivers/phy/broadcom/phy-bcm-sr-pcie.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Broadcom + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* we have up to 8 PAXB based RC. The 9th one is always PAXC */ +#define SR_NR_PCIE_PHYS 9 +#define SR_PAXC_PHY_IDX (SR_NR_PCIE_PHYS - 1) + +#define PCIE_PIPEMUX_CFG_OFFSET 0x10c +#define PCIE_PIPEMUX_SELECT_STRAP 0xf + +#define CDRU_STRAP_DATA_LSW_OFFSET0x5c +#define PCIE_PIPEMUX_SHIFT19 +#define PCIE_PIPEMUX_MASK 0xf + +#define MHB_MEM_PW_PAXC_OFFSET0x1c0 +#define MHB_PWR_ARR_POWERON 0x8 +#define MHB_PWR_ARR_POWEROK 0x4 +#define MHB_PWR_POWERON 0x2 +#define MHB_PWR_POWEROK 0x1 +#define MHB_PWR_STATUS_MASK (MHB_PWR_ARR_POWERON | \ + MHB_PWR_ARR_POWEROK | \ + MHB_PWR_POWERON | \ + MHB_PWR_POWEROK) + +struct sr_pcie_phy_core; + +/** + * struct sr_pcie_phy - Stingray PCIe PHY + * + * @core: pointer to the Stingray PCIe PHY core control + * @index: PHY index + * @phy: pointer to the kernel PHY device + */ +struct sr_pcie_phy { + struct sr_pcie_phy_core *core; + unsigned int index; + struct phy *phy; +}; + +/** + * struct sr_pcie_phy_core - Stingray PCIe PHY core control + * + * @dev: pointer to device + * @base: base register of PCIe SS + * @cdru: regmap to the CDRU device + * @mhb: regmap to the MHB device + * @pipemux: pipemuex strap + * @phys: array of PCIe PHYs + */ +struct sr_pcie_phy_core { + struct device *dev; + void __iomem *base; + struct regmap *cdru; + struct regmap *mhb; + u32 pipemux; + struct sr_pcie_phy phys[SR_NR_PCIE_PHYS]; +}; + +/* + * PCIe PIPEMUX lookup table + * + * Each array index represents a PIPEMUX strap setting + * The array element represents a bitmap where a set bit means the PCIe + * core and associated serdes has been enabled as RC and is available for use + */ +static const u8 pipemux_table[] = { + /* PIPEMUX = 0, EP 1x16 */ + 0x00, + /* PIPEMUX = 1, EP 2x8 */ + 0x00, + /* PIPEMUX = 2, EP 4x4 */ + 0x00, + /* PIPEMUX = 3, RC 2x8, cores 0, 7 */ + 0x81, + /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */ + 0xc3, + /* PIPEMUX = 5, RC 8x2, all 8 cores */ + 0xff, + /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */ + 0xcd, + /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */ + 0xfd, + /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */ + 0xf0, + /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */ + 0xc0, + /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */ + 0x42, + /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */ + 0x3c, + /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */ + 0xfc, + /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */ + 0x4c, +}; + +/* + * Return true if the strap setting is valid + */ +static bool pipemux_strap_is_valid(u32 pipemux) +{ + return !!(pipemux < ARRAY_SIZE(pipemux_table)); +} + +/* + * Read the PCIe PIPEMUX from strap + */ +static u32
[PATCH v4 2/2] phy: bcm-sr-pcie: Add Stingray PCIe PHY driver
Add Stingray PCIe PHY driver for both PAXB and PAXC root complex Signed-off-by: Ray Jui --- drivers/phy/broadcom/Kconfig | 10 ++ drivers/phy/broadcom/Makefile | 2 + drivers/phy/broadcom/phy-bcm-sr-pcie.c | 305 + 3 files changed, 317 insertions(+) create mode 100644 drivers/phy/broadcom/phy-bcm-sr-pcie.c diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig index 97d27b0d5..8786a96 100644 --- a/drivers/phy/broadcom/Kconfig +++ b/drivers/phy/broadcom/Kconfig @@ -80,3 +80,13 @@ config PHY_BRCM_USB This driver is required by the USB XHCI, EHCI and OHCI drivers. If unsure, say N. + +config PHY_BCM_SR_PCIE + tristate "Broadcom Stingray PCIe PHY driver" + depends on OF && (ARCH_BCM_IPROC || COMPILE_TEST) + select GENERIC_PHY + select MFD_SYSCON + default ARCH_BCM_IPROC + help + Enable this to support the Broadcom Stingray PCIe PHY + If unsure, say N. diff --git a/drivers/phy/broadcom/Makefile b/drivers/phy/broadcom/Makefile index 13e000c..0f60184 100644 --- a/drivers/phy/broadcom/Makefile +++ b/drivers/phy/broadcom/Makefile @@ -9,3 +9,5 @@ obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o obj-$(CONFIG_PHY_BRCM_USB) += phy-brcm-usb-dvr.o phy-brcm-usb-dvr-objs := phy-brcm-usb.o phy-brcm-usb-init.o + +obj-$(CONFIG_PHY_BCM_SR_PCIE) += phy-bcm-sr-pcie.o diff --git a/drivers/phy/broadcom/phy-bcm-sr-pcie.c b/drivers/phy/broadcom/phy-bcm-sr-pcie.c new file mode 100644 index 000..c10e95f --- /dev/null +++ b/drivers/phy/broadcom/phy-bcm-sr-pcie.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Broadcom + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* we have up to 8 PAXB based RC. The 9th one is always PAXC */ +#define SR_NR_PCIE_PHYS 9 +#define SR_PAXC_PHY_IDX (SR_NR_PCIE_PHYS - 1) + +#define PCIE_PIPEMUX_CFG_OFFSET 0x10c +#define PCIE_PIPEMUX_SELECT_STRAP 0xf + +#define CDRU_STRAP_DATA_LSW_OFFSET0x5c +#define PCIE_PIPEMUX_SHIFT19 +#define PCIE_PIPEMUX_MASK 0xf + +#define MHB_MEM_PW_PAXC_OFFSET0x1c0 +#define MHB_PWR_ARR_POWERON 0x8 +#define MHB_PWR_ARR_POWEROK 0x4 +#define MHB_PWR_POWERON 0x2 +#define MHB_PWR_POWEROK 0x1 +#define MHB_PWR_STATUS_MASK (MHB_PWR_ARR_POWERON | \ + MHB_PWR_ARR_POWEROK | \ + MHB_PWR_POWERON | \ + MHB_PWR_POWEROK) + +struct sr_pcie_phy_core; + +/** + * struct sr_pcie_phy - Stingray PCIe PHY + * + * @core: pointer to the Stingray PCIe PHY core control + * @index: PHY index + * @phy: pointer to the kernel PHY device + */ +struct sr_pcie_phy { + struct sr_pcie_phy_core *core; + unsigned int index; + struct phy *phy; +}; + +/** + * struct sr_pcie_phy_core - Stingray PCIe PHY core control + * + * @dev: pointer to device + * @base: base register of PCIe SS + * @cdru: regmap to the CDRU device + * @mhb: regmap to the MHB device + * @pipemux: pipemuex strap + * @phys: array of PCIe PHYs + */ +struct sr_pcie_phy_core { + struct device *dev; + void __iomem *base; + struct regmap *cdru; + struct regmap *mhb; + u32 pipemux; + struct sr_pcie_phy phys[SR_NR_PCIE_PHYS]; +}; + +/* + * PCIe PIPEMUX lookup table + * + * Each array index represents a PIPEMUX strap setting + * The array element represents a bitmap where a set bit means the PCIe + * core and associated serdes has been enabled as RC and is available for use + */ +static const u8 pipemux_table[] = { + /* PIPEMUX = 0, EP 1x16 */ + 0x00, + /* PIPEMUX = 1, EP 2x8 */ + 0x00, + /* PIPEMUX = 2, EP 4x4 */ + 0x00, + /* PIPEMUX = 3, RC 2x8, cores 0, 7 */ + 0x81, + /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */ + 0xc3, + /* PIPEMUX = 5, RC 8x2, all 8 cores */ + 0xff, + /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */ + 0xcd, + /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */ + 0xfd, + /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */ + 0xf0, + /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */ + 0xc0, + /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */ + 0x42, + /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */ + 0x3c, + /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */ + 0xfc, + /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */ + 0x4c, +}; + +/* + * Return true if the strap setting is valid + */ +static bool pipemux_strap_is_valid(u32 pipemux) +{ + return !!(pipemux < ARRAY_SIZE(pipemux_table)); +} + +/* + * Read the PCIe PIPEMUX from strap + */ +static u32