diff mbox series

[U-Boot,2/3] mvebu: pinctrl: Add SD/eMMC PHY selector to the driver

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

Commit Message

xswang@marvell.com May 24, 2018, 8:20 a.m. UTC
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(-)

Comments

Stefan Roese May 24, 2018, 3:03 p.m. UTC | #1
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 mbox series

Patch

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;