Re: [PATCH v6 2/2] phy: add a driver for the Rockchip SoC internal PCIe PHY
On Thursday 01 September 2016 01:14 PM, Shawn Lin wrote: > This patch to add a generic PHY driver for rockchip PCIe PHY. > Access the PHY via registers provided by GRF (general register > files) module. > > Signed-off-by: Shawn Lin merged, thanks -Kishon > > --- > > Changes in v6: > - use dev_* instead of pr_* > > Changes in v5: > - add COMPILE_TEST and select MFD_SYSCON on Kconfig > > Changes in v4: > - remove laneoff symbol as we still fail to get a workable solution > except for exporting symbol. But I will be back with some other possible > routine once finished. > > Changes in v3: None > Changes in v2: None > > drivers/phy/Kconfig | 8 + > drivers/phy/Makefile| 1 + > drivers/phy/phy-rockchip-pcie.c | 357 > > 3 files changed, 366 insertions(+) > create mode 100644 drivers/phy/phy-rockchip-pcie.c > > diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig > index f9bf981..46e5536 100644 > --- a/drivers/phy/Kconfig > +++ b/drivers/phy/Kconfig > @@ -388,6 +388,14 @@ config PHY_ROCKCHIP_DP > help > Enable this to support the Rockchip Display Port PHY. > > +config PHY_ROCKCHIP_PCIE > + tristate "Rockchip PCIe PHY Driver" > + depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST > + select GENERIC_PHY > + select MFD_SYSCON > + help > + Enable this to support the Rockchip PCIe PHY. > + > config PHY_ST_SPEAR1310_MIPHY > tristate "ST SPEAR1310-MIPHY driver" > select GENERIC_PHY > diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile > index 74b44ef..ce0e526 100644 > --- a/drivers/phy/Makefile > +++ b/drivers/phy/Makefile > @@ -42,6 +42,7 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += > phy-qcom-apq8064-sata.o > obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o > obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o > obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o > +obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o > obj-$(CONFIG_PHY_ROCKCHIP_DP)+= phy-rockchip-dp.o > obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o > obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o > diff --git a/drivers/phy/phy-rockchip-pcie.c b/drivers/phy/phy-rockchip-pcie.c > new file mode 100644 > index 000..a2b4c6b > --- /dev/null > +++ b/drivers/phy/phy-rockchip-pcie.c > @@ -0,0 +1,357 @@ > +/* > + * Rockchip PCIe PHY driver > + * > + * Copyright (C) 2016 Shawn Lin > + * Copyright (C) 2016 ROCKCHIP, Inc. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* > + * The higher 16-bit of this register is used for write protection > + * only if BIT(x + 16) set to 1 the BIT(x) can be written. > + */ > +#define HIWORD_UPDATE(val, mask, shift) \ > + ((val) << (shift) | (mask) << ((shift) + 16)) > + > +#define PHY_MAX_LANE_NUM 4 > +#define PHY_CFG_DATA_SHIFT7 > +#define PHY_CFG_ADDR_SHIFT1 > +#define PHY_CFG_DATA_MASK 0xf > +#define PHY_CFG_ADDR_MASK 0x3f > +#define PHY_CFG_RD_MASK 0x3ff > +#define PHY_CFG_WR_ENABLE 1 > +#define PHY_CFG_WR_DISABLE1 > +#define PHY_CFG_WR_SHIFT 0 > +#define PHY_CFG_WR_MASK 1 > +#define PHY_CFG_PLL_LOCK 0x10 > +#define PHY_CFG_CLK_TEST 0x10 > +#define PHY_CFG_CLK_SCC 0x12 > +#define PHY_CFG_SEPE_RATE BIT(3) > +#define PHY_CFG_PLL_100M BIT(3) > +#define PHY_PLL_LOCKEDBIT(9) > +#define PHY_PLL_OUTPUTBIT(10) > +#define PHY_LANE_A_STATUS 0x30 > +#define PHY_LANE_B_STATUS 0x31 > +#define PHY_LANE_C_STATUS 0x32 > +#define PHY_LANE_D_STATUS 0x33 > +#define PHY_LANE_RX_DET_SHIFT 11 > +#define PHY_LANE_RX_DET_TH0x1 > +#define PHY_LANE_IDLE_OFF 0x1 > +#define PHY_LANE_IDLE_MASK0x1 > +#define PHY_LANE_IDLE_A_SHIFT 3 > +#define PHY_LANE_IDLE_B_SHIFT 4 > +#define PHY_LANE_IDLE_C_SHIFT 5 > +#define PHY_LANE_IDLE_D_SHIFT 6 > + > +struct rockchip_pcie_data { > + unsigned int pcie_conf; > + unsigned int pcie_status; > + unsigned int pcie_laneoff; > +}; > + > +struct rockchip_pcie_phy { > + struct rockchip_pcie_data *phy_data; > + struct regmap *reg_base; > + struct reset_control *phy_rst; > + struct clk *clk_pciephy_ref; > +}; > + > +static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy, > + u32 addr, u32 data) > +{ > + regm
[PATCH v6 2/2] phy: add a driver for the Rockchip SoC internal PCIe PHY
This patch to add a generic PHY driver for rockchip PCIe PHY. Access the PHY via registers provided by GRF (general register files) module. Signed-off-by: Shawn Lin --- Changes in v6: - use dev_* instead of pr_* Changes in v5: - add COMPILE_TEST and select MFD_SYSCON on Kconfig Changes in v4: - remove laneoff symbol as we still fail to get a workable solution except for exporting symbol. But I will be back with some other possible routine once finished. Changes in v3: None Changes in v2: None drivers/phy/Kconfig | 8 + drivers/phy/Makefile| 1 + drivers/phy/phy-rockchip-pcie.c | 357 3 files changed, 366 insertions(+) create mode 100644 drivers/phy/phy-rockchip-pcie.c diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index f9bf981..46e5536 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -388,6 +388,14 @@ config PHY_ROCKCHIP_DP help Enable this to support the Rockchip Display Port PHY. +config PHY_ROCKCHIP_PCIE + tristate "Rockchip PCIe PHY Driver" + depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the Rockchip PCIe PHY. + config PHY_ST_SPEAR1310_MIPHY tristate "ST SPEAR1310-MIPHY driver" select GENERIC_PHY diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 74b44ef..ce0e526 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o +obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)+= phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o diff --git a/drivers/phy/phy-rockchip-pcie.c b/drivers/phy/phy-rockchip-pcie.c new file mode 100644 index 000..a2b4c6b --- /dev/null +++ b/drivers/phy/phy-rockchip-pcie.c @@ -0,0 +1,357 @@ +/* + * Rockchip PCIe PHY driver + * + * Copyright (C) 2016 Shawn Lin + * Copyright (C) 2016 ROCKCHIP, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The higher 16-bit of this register is used for write protection + * only if BIT(x + 16) set to 1 the BIT(x) can be written. + */ +#define HIWORD_UPDATE(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +#define PHY_MAX_LANE_NUM 4 +#define PHY_CFG_DATA_SHIFT7 +#define PHY_CFG_ADDR_SHIFT1 +#define PHY_CFG_DATA_MASK 0xf +#define PHY_CFG_ADDR_MASK 0x3f +#define PHY_CFG_RD_MASK 0x3ff +#define PHY_CFG_WR_ENABLE 1 +#define PHY_CFG_WR_DISABLE1 +#define PHY_CFG_WR_SHIFT 0 +#define PHY_CFG_WR_MASK 1 +#define PHY_CFG_PLL_LOCK 0x10 +#define PHY_CFG_CLK_TEST 0x10 +#define PHY_CFG_CLK_SCC 0x12 +#define PHY_CFG_SEPE_RATE BIT(3) +#define PHY_CFG_PLL_100M BIT(3) +#define PHY_PLL_LOCKEDBIT(9) +#define PHY_PLL_OUTPUTBIT(10) +#define PHY_LANE_A_STATUS 0x30 +#define PHY_LANE_B_STATUS 0x31 +#define PHY_LANE_C_STATUS 0x32 +#define PHY_LANE_D_STATUS 0x33 +#define PHY_LANE_RX_DET_SHIFT 11 +#define PHY_LANE_RX_DET_TH0x1 +#define PHY_LANE_IDLE_OFF 0x1 +#define PHY_LANE_IDLE_MASK0x1 +#define PHY_LANE_IDLE_A_SHIFT 3 +#define PHY_LANE_IDLE_B_SHIFT 4 +#define PHY_LANE_IDLE_C_SHIFT 5 +#define PHY_LANE_IDLE_D_SHIFT 6 + +struct rockchip_pcie_data { + unsigned int pcie_conf; + unsigned int pcie_status; + unsigned int pcie_laneoff; +}; + +struct rockchip_pcie_phy { + struct rockchip_pcie_data *phy_data; + struct regmap *reg_base; + struct reset_control *phy_rst; + struct clk *clk_pciephy_ref; +}; + +static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy, + u32 addr, u32 data) +{ + regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, +HIWORD_UPDATE(data, + PHY_CFG_DATA_MASK, + PHY_CFG_DATA_SHIFT) | +HIWORD_UPDATE(addr, + PHY_CFG_ADDR_MASK, + PHY_C