Message ID | 1527150004-15764-2-git-send-email-xswang@marvell.com |
---|---|
State | Superseded |
Delegated to: | Stefan Roese |
Headers | show |
Series | [U-Boot,1/3] mvebu: pinctrl: sync compatible string with Linux 4.17-rc4 | expand |
On 24.05.2018 10:20, xswang@marvell.com wrote: > From: Konstantin Porotchkin <kostap@marvell.com> > > When the pin control driver selects SD/eMMC function for > a pin group, there is additional configuration to be done > for this case - switch the PHY to work with SDHCI interface. > This patch adds the missing functionality into the pin > control driver. > > Signed-off-by: Konstantin Porotchkin <kostap@marvell.com> > Signed-off-by: Evan Wang <xswang@marvell.com> > --- > > drivers/pinctrl/mvebu/pinctrl-mvebu.c | 59 +++++++++++++++++++++++++++++++++-- > 1 file changed, 57 insertions(+), 2 deletions(-) > > diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c > index 556bf78..7d8a0b0 100644 > --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c > +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c > @@ -17,8 +17,48 @@ > #include <asm/arch-armada8k/soc-info.h> > #include "pinctrl-mvebu.h" > > +#define AP_EMMC_PHY_CTRL_REG 0x100 > +#define CP_EMMC_PHY_CTRL_REG 0x424 > +#define EMMC_PHY_CTRL_SDPHY_EN BIT(0) > + > +#define AP806_EMMC_CLK_PIN_ID 0 > +#define AP806_EMMC_CLK_FUNC 0x1 > +#define CP110_EMMC_CLK_PIN_ID 56 > +#define CP110_EMMC_CLK_FUNC 0xe > + > DECLARE_GLOBAL_DATA_PTR; > > +/* mvebu_pinctl_emmc_set_mux: configure sd/mmc PHY mux > + * To enable SDIO/eMMC in Armada-APN806/CP110, need to configure PHY mux. > + * eMMC/SD PHY register responsible for muxing between MPPs and SD/eMMC > + * controller: > + * - Bit0 enabled SDIO/eMMC PHY is used as a MPP muxltiplexer, > + * - Bit0 disabled SDIO/eMMC PHY is connected to SDIO/eMMC controller > + * If pin function is set to eMMC/SD, then configure the eMMC/SD PHY > + * muxltiplexer register to be on SDIO/eMMC controller > + */ > +void mvebu_pinctl_emmc_set_mux(struct udevice *dev, u32 pin, u32 func) > +{ > + const void *blob = gd->fdt_blob; > + int node = dev_of_offset(dev); > + struct mvebu_pinctrl_priv *priv = dev_get_priv(dev); > + > + if (!fdt_node_check_compatible(blob, node, "marvell,ap806-pinctrl")) { > + if ((pin == AP806_EMMC_CLK_PIN_ID) && > + (func == AP806_EMMC_CLK_FUNC)) { > + clrbits_le32(priv->base_reg + AP_EMMC_PHY_CTRL_REG, > + EMMC_PHY_CTRL_SDPHY_EN); > + } > + } else if (!fdt_node_check_compatible(blob, node, > + "marvell,armada-8k-cpm-pinctrl")) { > + if ((pin == CP110_EMMC_CLK_PIN_ID) && > + (func == CP110_EMMC_CLK_FUNC)) { > + clrbits_le32(priv->base_reg + CP_EMMC_PHY_CTRL_REG, > + EMMC_PHY_CTRL_SDPHY_EN); > + } > + } > +} > + > /* > * mvebu_pinctrl_set_state: configure pin functions. > * @dev: the pinctrl device to be configured. > @@ -48,9 +88,16 @@ int mvebu_pinctrl_set_state(struct udevice *dev, struct udevice *config) > > function = fdtdec_get_int(blob, node, "marvell,function", 0xff); > > + /* > + * Check if setup of PHY mux is needed for this pins group. > + * Only the first pin id in array is tested, all the rest use the same > + * pin function. > + */ > + mvebu_pinctl_emmc_set_mux(dev, pin_arr[0], function); > + > for (i = 0; i < pin_count; i++) { > - int reg_offset; > - int field_offset; > + int reg_offset; > + int field_offset; > int pin = pin_arr[i]; > > if (function > priv->max_func) { > @@ -97,6 +144,14 @@ static int mvebu_pinctrl_set_state_all(struct udevice *dev, > return -EINVAL; > } > > + /* Check if setup of PHY mux is needed for this pins group. */ > + if (priv->pin_cnt < CP110_EMMC_CLK_PIN_ID) > + mvebu_pinctl_emmc_set_mux(dev, AP806_EMMC_CLK_PIN_ID, > + func_arr[AP806_EMMC_CLK_PIN_ID]); > + else > + mvebu_pinctl_emmc_set_mux(dev, CP110_EMMC_CLK_PIN_ID, > + func_arr[CP110_EMMC_CLK_PIN_ID]); > + > for (pin = 0; pin < priv->pin_cnt; pin++) { > int reg_offset; > int field_offset; > Reviewed-by: Stefan Roese <sr@denx.de> Thanks, Stefan
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 556bf78..7d8a0b0 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -17,8 +17,48 @@ #include <asm/arch-armada8k/soc-info.h> #include "pinctrl-mvebu.h" +#define AP_EMMC_PHY_CTRL_REG 0x100 +#define CP_EMMC_PHY_CTRL_REG 0x424 +#define EMMC_PHY_CTRL_SDPHY_EN BIT(0) + +#define AP806_EMMC_CLK_PIN_ID 0 +#define AP806_EMMC_CLK_FUNC 0x1 +#define CP110_EMMC_CLK_PIN_ID 56 +#define CP110_EMMC_CLK_FUNC 0xe + DECLARE_GLOBAL_DATA_PTR; +/* mvebu_pinctl_emmc_set_mux: configure sd/mmc PHY mux + * To enable SDIO/eMMC in Armada-APN806/CP110, need to configure PHY mux. + * eMMC/SD PHY register responsible for muxing between MPPs and SD/eMMC + * controller: + * - Bit0 enabled SDIO/eMMC PHY is used as a MPP muxltiplexer, + * - Bit0 disabled SDIO/eMMC PHY is connected to SDIO/eMMC controller + * If pin function is set to eMMC/SD, then configure the eMMC/SD PHY + * muxltiplexer register to be on SDIO/eMMC controller + */ +void mvebu_pinctl_emmc_set_mux(struct udevice *dev, u32 pin, u32 func) +{ + const void *blob = gd->fdt_blob; + int node = dev_of_offset(dev); + struct mvebu_pinctrl_priv *priv = dev_get_priv(dev); + + if (!fdt_node_check_compatible(blob, node, "marvell,ap806-pinctrl")) { + if ((pin == AP806_EMMC_CLK_PIN_ID) && + (func == AP806_EMMC_CLK_FUNC)) { + clrbits_le32(priv->base_reg + AP_EMMC_PHY_CTRL_REG, + EMMC_PHY_CTRL_SDPHY_EN); + } + } else if (!fdt_node_check_compatible(blob, node, + "marvell,armada-8k-cpm-pinctrl")) { + if ((pin == CP110_EMMC_CLK_PIN_ID) && + (func == CP110_EMMC_CLK_FUNC)) { + clrbits_le32(priv->base_reg + CP_EMMC_PHY_CTRL_REG, + EMMC_PHY_CTRL_SDPHY_EN); + } + } +} + /* * mvebu_pinctrl_set_state: configure pin functions. * @dev: the pinctrl device to be configured. @@ -48,9 +88,16 @@ int mvebu_pinctrl_set_state(struct udevice *dev, struct udevice *config) function = fdtdec_get_int(blob, node, "marvell,function", 0xff); + /* + * Check if setup of PHY mux is needed for this pins group. + * Only the first pin id in array is tested, all the rest use the same + * pin function. + */ + mvebu_pinctl_emmc_set_mux(dev, pin_arr[0], function); + for (i = 0; i < pin_count; i++) { - int reg_offset; - int field_offset; + int reg_offset; + int field_offset; int pin = pin_arr[i]; if (function > priv->max_func) { @@ -97,6 +144,14 @@ static int mvebu_pinctrl_set_state_all(struct udevice *dev, return -EINVAL; } + /* Check if setup of PHY mux is needed for this pins group. */ + if (priv->pin_cnt < CP110_EMMC_CLK_PIN_ID) + mvebu_pinctl_emmc_set_mux(dev, AP806_EMMC_CLK_PIN_ID, + func_arr[AP806_EMMC_CLK_PIN_ID]); + else + mvebu_pinctl_emmc_set_mux(dev, CP110_EMMC_CLK_PIN_ID, + func_arr[CP110_EMMC_CLK_PIN_ID]); + for (pin = 0; pin < priv->pin_cnt; pin++) { int reg_offset; int field_offset;