* [PATCH v2 01/14] qcs404: sysmap: Don't map reserved memory ranges
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:43 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 02/14] qcs404-evb: Enable msm_gpio driver support Sumit Garg
` (11 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Currently u-boot maps whole of 1G RAM but there reserved memory ranges on
QCS404 which are reserved for TrustZone, various firmware components etc.
Any access to these reserved memory ranges causes a bus hang issue. So
disable mapping for reserved memory ranges in u-boot.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/mach-snapdragon/sysmap-qcs404.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-snapdragon/sysmap-qcs404.c b/arch/arm/mach-snapdragon/sysmap-qcs404.c
index b7409031a0..64ca4adf1b 100644
--- a/arch/arm/mach-snapdragon/sysmap-qcs404.c
+++ b/arch/arm/mach-snapdragon/sysmap-qcs404.c
@@ -19,7 +19,19 @@ static struct mm_region qcs404_mem_map[] = {
}, {
.virt = 0x80000000UL, /* DDR */
.phys = 0x80000000UL, /* DDR */
- .size = 0x40000000UL,
+ .size = 0x05900000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ .virt = 0x89600000UL, /* DDR */
+ .phys = 0x89600000UL, /* DDR */
+ .size = 0x162000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ .virt = 0xa0000000UL, /* DDR */
+ .phys = 0xa0000000UL, /* DDR */
+ .size = 0x20000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 01/14] qcs404: sysmap: Don't map reserved memory ranges
2023-02-01 13:58 ` [PATCH v2 01/14] qcs404: sysmap: Don't map reserved memory ranges Sumit Garg
@ 2023-02-10 18:43 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:43 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 454 bytes --]
On Wed, Feb 01, 2023 at 07:28:48PM +0530, Sumit Garg wrote:
> Currently u-boot maps whole of 1G RAM but there reserved memory ranges on
> QCS404 which are reserved for TrustZone, various firmware components etc.
> Any access to these reserved memory ranges causes a bus hang issue. So
> disable mapping for reserved memory ranges in u-boot.
>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 02/14] qcs404-evb: Enable msm_gpio driver support
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
2023-02-01 13:58 ` [PATCH v2 01/14] qcs404: sysmap: Don't map reserved memory ranges Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:43 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 03/14] clocks: qcs404: Add support for ethernet clocks Sumit Garg
` (10 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/dts/qcs404-evb.dts | 4 ++++
configs/qcs404evb_defconfig | 1 +
2 files changed, 5 insertions(+)
diff --git a/arch/arm/dts/qcs404-evb.dts b/arch/arm/dts/qcs404-evb.dts
index 0639af8fe3..c8bcf9f71d 100644
--- a/arch/arm/dts/qcs404-evb.dts
+++ b/arch/arm/dts/qcs404-evb.dts
@@ -40,6 +40,10 @@
pinctrl_north@1300000 {
compatible = "qcom,qcs404-pinctrl";
reg = <0x1300000 0x200000>;
+ gpio-controller;
+ gpio-count = <120>;
+ gpio-bank-name="soc";
+ #gpio-cells = <2>;
blsp1_uart2: uart {
pins = "GPIO_17", "GPIO_18";
diff --git a/configs/qcs404evb_defconfig b/configs/qcs404evb_defconfig
index dae1551411..d64cd74269 100644
--- a/configs/qcs404evb_defconfig
+++ b/configs/qcs404evb_defconfig
@@ -44,6 +44,7 @@ CONFIG_DM_PMIC=y
CONFIG_PMIC_QCOM=y
CONFIG_DM_RESET=y
CONFIG_MSM_SERIAL=y
+CONFIG_MSM_GPIO=y
CONFIG_SPMI_MSM=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 02/14] qcs404-evb: Enable msm_gpio driver support
2023-02-01 13:58 ` [PATCH v2 02/14] qcs404-evb: Enable msm_gpio driver support Sumit Garg
@ 2023-02-10 18:43 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:43 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 165 bytes --]
On Wed, Feb 01, 2023 at 07:28:49PM +0530, Sumit Garg wrote:
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 03/14] clocks: qcs404: Add support for ethernet clocks
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
2023-02-01 13:58 ` [PATCH v2 01/14] qcs404: sysmap: Don't map reserved memory ranges Sumit Garg
2023-02-01 13:58 ` [PATCH v2 02/14] qcs404-evb: Enable msm_gpio driver support Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:43 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 04/14] pinctrl: qcs404: Enable ethernet pinmux options Sumit Garg
` (9 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/mach-snapdragon/clock-qcs404.c | 60 +++++++++++++++++++
.../include/mach/sysmap-qcs404.h | 14 +++++
2 files changed, 74 insertions(+)
diff --git a/arch/arm/mach-snapdragon/clock-qcs404.c b/arch/arm/mach-snapdragon/clock-qcs404.c
index 6fe92afe8d..b8f5691aae 100644
--- a/arch/arm/mach-snapdragon/clock-qcs404.c
+++ b/arch/arm/mach-snapdragon/clock-qcs404.c
@@ -18,6 +18,9 @@
/* GPLL0 clock control registers */
#define GPLL0_STATUS_ACTIVE BIT(31)
+#define CFG_CLK_SRC_GPLL1 BIT(8)
+#define GPLL1_STATUS_ACTIVE BIT(31)
+
static struct vote_clk gcc_blsp1_ahb_clk = {
.cbcr_reg = BLSP1_AHB_CBCR,
.ena_vote = APCS_CLOCK_BRANCH_ENA_VOTE,
@@ -47,6 +50,13 @@ static struct pll_vote_clk gpll0_vote_clk = {
.vote_bit = BIT(0),
};
+static struct pll_vote_clk gpll1_vote_clk = {
+ .status = GPLL1_STATUS,
+ .status_bit = GPLL1_STATUS_ACTIVE,
+ .ena_vote = APCS_GPLL_ENA_VOTE,
+ .vote_bit = BIT(1),
+};
+
static const struct bcr_regs usb30_master_regs = {
.cfg_rcgr = USB30_MASTER_CFG_RCGR,
.cmd_rcgr = USB30_MASTER_CMD_RCGR,
@@ -55,6 +65,22 @@ static const struct bcr_regs usb30_master_regs = {
.D = USB30_MASTER_D,
};
+static const struct bcr_regs emac_regs = {
+ .cfg_rcgr = EMAC_CFG_RCGR,
+ .cmd_rcgr = EMAC_CMD_RCGR,
+ .M = EMAC_M,
+ .N = EMAC_N,
+ .D = EMAC_D,
+};
+
+static const struct bcr_regs emac_ptp_regs = {
+ .cfg_rcgr = EMAC_PTP_CFG_RCGR,
+ .cmd_rcgr = EMAC_PTP_CMD_RCGR,
+ .M = EMAC_M,
+ .N = EMAC_N,
+ .D = EMAC_D,
+};
+
ulong msm_set_rate(struct clk *clk, ulong rate)
{
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
@@ -79,6 +105,20 @@ ulong msm_set_rate(struct clk *clk, ulong rate)
case GCC_SDCC1_AHB_CLK:
clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1));
break;
+ case GCC_ETH_RGMII_CLK:
+ if (rate == 250000000)
+ clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0,
+ CFG_CLK_SRC_GPLL1);
+ else if (rate == 125000000)
+ clk_rcg_set_rate_mnd(priv->base, &emac_regs, 4, 0, 0,
+ CFG_CLK_SRC_GPLL1);
+ else if (rate == 50000000)
+ clk_rcg_set_rate_mnd(priv->base, &emac_regs, 10, 0, 0,
+ CFG_CLK_SRC_GPLL1);
+ else if (rate == 5000000)
+ clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 1, 50,
+ CFG_CLK_SRC_GPLL1);
+ break;
default:
return 0;
}
@@ -111,6 +151,26 @@ int msm_enable(struct clk *clk)
case GCC_USB2A_PHY_SLEEP_CLK:
clk_enable_cbc(priv->base + USB_HS_PHY_CFG_AHB_CBCR);
break;
+ case GCC_ETH_PTP_CLK:
+ /* SPEED_1000: freq -> 250MHz */
+ clk_enable_cbc(priv->base + ETH_PTP_CBCR);
+ clk_enable_gpll0(priv->base, &gpll1_vote_clk);
+ clk_rcg_set_rate_mnd(priv->base, &emac_ptp_regs, 2, 0, 0,
+ CFG_CLK_SRC_GPLL1);
+ break;
+ case GCC_ETH_RGMII_CLK:
+ /* SPEED_1000: freq -> 250MHz */
+ clk_enable_cbc(priv->base + ETH_RGMII_CBCR);
+ clk_enable_gpll0(priv->base, &gpll1_vote_clk);
+ clk_rcg_set_rate_mnd(priv->base, &emac_regs, 2, 0, 0,
+ CFG_CLK_SRC_GPLL1);
+ break;
+ case GCC_ETH_SLAVE_AHB_CLK:
+ clk_enable_cbc(priv->base + ETH_SLAVE_AHB_CBCR);
+ break;
+ case GCC_ETH_AXI_CLK:
+ clk_enable_cbc(priv->base + ETH_AXI_CBCR);
+ break;
default:
return 0;
}
diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h b/arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h
index e448faad2d..8920c4ee8f 100644
--- a/arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h
+++ b/arch/arm/mach-snapdragon/include/mach/sysmap-qcs404.h
@@ -12,6 +12,7 @@
/* Clocks: (from CLK_CTL_BASE) */
#define GPLL0_STATUS (0x21000)
+#define GPLL1_STATUS (0x20000)
#define APCS_GPLL_ENA_VOTE (0x45000)
#define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004)
@@ -54,4 +55,17 @@
#define USB2A_PHY_SLEEP_CBCR (0x4102C)
#define USB_HS_PHY_CFG_AHB_CBCR (0x41030)
+/* ETH controller clock control registers */
+#define ETH_PTP_CBCR (0x4e004)
+#define ETH_RGMII_CBCR (0x4e008)
+#define ETH_SLAVE_AHB_CBCR (0x4e00c)
+#define ETH_AXI_CBCR (0x4e010)
+#define EMAC_PTP_CMD_RCGR (0x4e014)
+#define EMAC_PTP_CFG_RCGR (0x4e018)
+#define EMAC_CMD_RCGR (0x4e01c)
+#define EMAC_CFG_RCGR (0x4e020)
+#define EMAC_M (0x4e024)
+#define EMAC_N (0x4e028)
+#define EMAC_D (0x4e02c)
+
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 03/14] clocks: qcs404: Add support for ethernet clocks
2023-02-01 13:58 ` [PATCH v2 03/14] clocks: qcs404: Add support for ethernet clocks Sumit Garg
@ 2023-02-10 18:43 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:43 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 165 bytes --]
On Wed, Feb 01, 2023 at 07:28:50PM +0530, Sumit Garg wrote:
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 04/14] pinctrl: qcs404: Enable ethernet pinmux options
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (2 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 03/14] clocks: qcs404: Add support for ethernet clocks Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:43 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 05/14] pinctrl-snapdragon: Get rid of custom drive-strength values Sumit Garg
` (8 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/mach-snapdragon/pinctrl-qcs404.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-snapdragon/pinctrl-qcs404.c b/arch/arm/mach-snapdragon/pinctrl-qcs404.c
index 889ead0f57..5a7fbfd441 100644
--- a/arch/arm/mach-snapdragon/pinctrl-qcs404.c
+++ b/arch/arm/mach-snapdragon/pinctrl-qcs404.c
@@ -22,6 +22,13 @@ static const char * const msm_pinctrl_pins[] = {
static const struct pinctrl_function msm_pinctrl_functions[] = {
{"blsp_uart2", 1},
+ {"rgmii_int", 1},
+ {"rgmii_ck", 1},
+ {"rgmii_tx", 1},
+ {"rgmii_ctl", 1},
+ {"rgmii_rx", 1},
+ {"rgmii_mdio", 1},
+ {"rgmii_mdc", 1},
};
static const char *qcs404_get_function_name(struct udevice *dev,
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 04/14] pinctrl: qcs404: Enable ethernet pinmux options
2023-02-01 13:58 ` [PATCH v2 04/14] pinctrl: qcs404: Enable ethernet pinmux options Sumit Garg
@ 2023-02-10 18:43 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:43 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 165 bytes --]
On Wed, Feb 01, 2023 at 07:28:51PM +0530, Sumit Garg wrote:
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 05/14] pinctrl-snapdragon: Get rid of custom drive-strength values
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (3 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 04/14] pinctrl: qcs404: Enable ethernet pinmux options Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:43 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 06/14] net: dwc_eth_qos: Make eqos_get_tick_clk_rate callback optional Sumit Garg
` (7 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Use standard pinconf drive-strength values from Linux DT bindings rather
than ones based on custom u-boot header. These changes are in direction
to make u-boot DTs for Qcom SoCs to be compatible with standard Linux
DT bindings.
Also, add support for pinconf bias-pull-up.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/dts/dragonboard410c.dts | 3 +--
arch/arm/dts/dragonboard820c.dts | 3 +--
arch/arm/dts/qcom-ipq4019.dtsi | 1 -
arch/arm/dts/qcs404-evb.dts | 1 -
arch/arm/mach-snapdragon/pinctrl-snapdragon.c | 8 ++++++-
.../dt-bindings/pinctrl/pinctrl-snapdragon.h | 22 -------------------
6 files changed, 9 insertions(+), 29 deletions(-)
delete mode 100644 include/dt-bindings/pinctrl/pinctrl-snapdragon.h
diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts
index 59cf45eb17..9230dd3fd9 100644
--- a/arch/arm/dts/dragonboard410c.dts
+++ b/arch/arm/dts/dragonboard410c.dts
@@ -9,7 +9,6 @@
#include "skeleton64.dtsi"
#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
/ {
model = "Qualcomm Technologies, Inc. Dragonboard 410c";
@@ -71,7 +70,7 @@
blsp1_uart: uart {
function = "blsp1_uart";
pins = "GPIO_4", "GPIO_5";
- drive-strength = <DRIVE_STRENGTH_8MA>;
+ drive-strength = <8>;
bias-disable;
};
};
diff --git a/arch/arm/dts/dragonboard820c.dts b/arch/arm/dts/dragonboard820c.dts
index aaca681d2e..ad201d4874 100644
--- a/arch/arm/dts/dragonboard820c.dts
+++ b/arch/arm/dts/dragonboard820c.dts
@@ -8,7 +8,6 @@
/dts-v1/;
#include "skeleton64.dtsi"
-#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
/ {
model = "Qualcomm Technologies, Inc. DB820c";
@@ -71,7 +70,7 @@
blsp8_uart: uart {
function = "blsp_uart8";
pins = "GPIO_4", "GPIO_5";
- drive-strength = <DRIVE_STRENGTH_8MA>;
+ drive-strength = <8>;
bias-disable;
};
};
diff --git a/arch/arm/dts/qcom-ipq4019.dtsi b/arch/arm/dts/qcom-ipq4019.dtsi
index 181732d262..6edc69da67 100644
--- a/arch/arm/dts/qcom-ipq4019.dtsi
+++ b/arch/arm/dts/qcom-ipq4019.dtsi
@@ -9,7 +9,6 @@
#include "skeleton.dtsi"
#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
#include <dt-bindings/clock/qcom,ipq4019-gcc.h>
#include <dt-bindings/reset/qcom,ipq4019-reset.h>
diff --git a/arch/arm/dts/qcs404-evb.dts b/arch/arm/dts/qcs404-evb.dts
index c8bcf9f71d..cc70afa4c8 100644
--- a/arch/arm/dts/qcs404-evb.dts
+++ b/arch/arm/dts/qcs404-evb.dts
@@ -9,7 +9,6 @@
#include "skeleton64.dtsi"
#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/pinctrl-snapdragon.h>
#include <dt-bindings/clock/qcom,gcc-qcs404.h>
/ {
diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
index ab884ab6bf..826dc51486 100644
--- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
+++ b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
@@ -28,8 +28,9 @@ struct msm_pinctrl_priv {
#define TLMM_GPIO_DISABLE BIT(9)
static const struct pinconf_param msm_conf_params[] = {
- { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 3 },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 2 },
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 3 },
};
static int msm_get_functions_count(struct udevice *dev)
@@ -89,6 +90,7 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
switch (param) {
case PIN_CONFIG_DRIVE_STRENGTH:
+ argument = (argument / 2) - 1;
clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_DRV_STRENGTH_MASK, argument << 6);
break;
@@ -96,6 +98,10 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,
clrbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
TLMM_GPIO_PULL_MASK);
break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ clrsetbits_le32(priv->base + GPIO_CONFIG_OFFSET(pin_selector),
+ TLMM_GPIO_PULL_MASK, argument);
+ break;
default:
return 0;
}
diff --git a/include/dt-bindings/pinctrl/pinctrl-snapdragon.h b/include/dt-bindings/pinctrl/pinctrl-snapdragon.h
deleted file mode 100644
index 615affb6f2..0000000000
--- a/include/dt-bindings/pinctrl/pinctrl-snapdragon.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * This header provides constants for Qualcomm Snapdragon pinctrl bindings.
- *
- * (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com>
- *
- */
-
-#ifndef _DT_BINDINGS_PINCTRL_SNAPDRAGON_H
-#define _DT_BINDINGS_PINCTRL_SNAPDRAGON_H
-
-/* GPIO Drive Strength */
-#define DRIVE_STRENGTH_2MA 0
-#define DRIVE_STRENGTH_4MA 1
-#define DRIVE_STRENGTH_6MA 2
-#define DRIVE_STRENGTH_8MA 3
-#define DRIVE_STRENGTH_10MA 4
-#define DRIVE_STRENGTH_12MA 5
-#define DRIVE_STRENGTH_14MA 6
-#define DRIVE_STRENGTH_16MA 7
-
-#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 05/14] pinctrl-snapdragon: Get rid of custom drive-strength values
2023-02-01 13:58 ` [PATCH v2 05/14] pinctrl-snapdragon: Get rid of custom drive-strength values Sumit Garg
@ 2023-02-10 18:43 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:43 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 460 bytes --]
On Wed, Feb 01, 2023 at 07:28:52PM +0530, Sumit Garg wrote:
> Use standard pinconf drive-strength values from Linux DT bindings rather
> than ones based on custom u-boot header. These changes are in direction
> to make u-boot DTs for Qcom SoCs to be compatible with standard Linux
> DT bindings.
>
> Also, add support for pinconf bias-pull-up.
>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 06/14] net: dwc_eth_qos: Make eqos_get_tick_clk_rate callback optional
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (4 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 05/14] pinctrl-snapdragon: Get rid of custom drive-strength values Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-04 0:41 ` Ramon Fried
2023-02-10 18:43 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 07/14] net: dwc_eth_qos: Allow platform to override tx/rx_fifo_sz Sumit Garg
` (6 subsequent siblings)
12 siblings, 2 replies; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
drivers/net/dwc_eth_qos.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index afc47b56ff..753a912607 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -774,10 +774,13 @@ static int eqos_start(struct udevice *dev)
pr_err("eqos_calibrate_pads() failed: %d", ret);
goto err_stop_resets;
}
- rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
- val = (rate / 1000000) - 1;
- writel(val, &eqos->mac_regs->us_tic_counter);
+ if (eqos->config->ops->eqos_get_tick_clk_rate) {
+ rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
+
+ val = (rate / 1000000) - 1;
+ writel(val, &eqos->mac_regs->us_tic_counter);
+ }
/*
* if PHY was already connected and configured,
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 06/14] net: dwc_eth_qos: Make eqos_get_tick_clk_rate callback optional
2023-02-01 13:58 ` [PATCH v2 06/14] net: dwc_eth_qos: Make eqos_get_tick_clk_rate callback optional Sumit Garg
@ 2023-02-04 0:41 ` Ramon Fried
2023-02-10 18:43 ` Tom Rini
1 sibling, 0 replies; 30+ messages in thread
From: Ramon Fried @ 2023-02-04 0:41 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
On Wed, Feb 1, 2023 at 3:59 PM Sumit Garg <sumit.garg@linaro.org> wrote:
>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
> ---
> drivers/net/dwc_eth_qos.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index afc47b56ff..753a912607 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -774,10 +774,13 @@ static int eqos_start(struct udevice *dev)
> pr_err("eqos_calibrate_pads() failed: %d", ret);
> goto err_stop_resets;
> }
> - rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
>
> - val = (rate / 1000000) - 1;
> - writel(val, &eqos->mac_regs->us_tic_counter);
> + if (eqos->config->ops->eqos_get_tick_clk_rate) {
> + rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
> +
> + val = (rate / 1000000) - 1;
> + writel(val, &eqos->mac_regs->us_tic_counter);
> + }
>
> /*
> * if PHY was already connected and configured,
> --
> 2.34.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [PATCH v2 06/14] net: dwc_eth_qos: Make eqos_get_tick_clk_rate callback optional
2023-02-01 13:58 ` [PATCH v2 06/14] net: dwc_eth_qos: Make eqos_get_tick_clk_rate callback optional Sumit Garg
2023-02-04 0:41 ` Ramon Fried
@ 2023-02-10 18:43 ` Tom Rini
1 sibling, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:43 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 216 bytes --]
On Wed, Feb 01, 2023 at 07:28:53PM +0530, Sumit Garg wrote:
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 07/14] net: dwc_eth_qos: Allow platform to override tx/rx_fifo_sz
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (5 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 06/14] net: dwc_eth_qos: Make eqos_get_tick_clk_rate callback optional Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-04 0:42 ` Ramon Fried
2023-02-10 18:44 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 08/14] net: dwc_eth_qos: Add Qcom ethernet driver glue layer Sumit Garg
` (5 subsequent siblings)
12 siblings, 2 replies; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
The GMAC controller on QCS404 SoC (support added by upcoming patch) fails
to work with maximum tx/rx_fifo_sz supported by the hardware (16K). So
allow platforms to override FIFO size using corresponding DT node
properties.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
drivers/net/dwc_eth_qos.c | 19 +++++++++++++------
drivers/net/dwc_eth_qos.h | 1 +
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 753a912607..65b8556be2 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -852,12 +852,19 @@ static int eqos_start(struct udevice *dev)
rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) &
EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK;
- /*
- * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting.
- * r/tqs is encoded as (n / 256) - 1.
- */
- tqs = (128 << tx_fifo_sz) / 256 - 1;
- rqs = (128 << rx_fifo_sz) / 256 - 1;
+ /* r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting */
+ tx_fifo_sz = 128 << tx_fifo_sz;
+ rx_fifo_sz = 128 << rx_fifo_sz;
+
+ /* Allow platform to override TX/RX fifo size */
+ if (eqos->tx_fifo_sz)
+ tx_fifo_sz = eqos->tx_fifo_sz;
+ if (eqos->rx_fifo_sz)
+ rx_fifo_sz = eqos->rx_fifo_sz;
+
+ /* r/tqs is encoded as (n / 256) - 1 */
+ tqs = tx_fifo_sz / 256 - 1;
+ rqs = rx_fifo_sz / 256 - 1;
clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode,
EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK <<
diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
index 8fccd6f057..466a792de7 100644
--- a/drivers/net/dwc_eth_qos.h
+++ b/drivers/net/dwc_eth_qos.h
@@ -276,6 +276,7 @@ struct eqos_priv {
bool started;
bool reg_access_ok;
bool clk_ck_enabled;
+ unsigned int tx_fifo_sz, rx_fifo_sz;
};
void eqos_inval_desc_generic(void *desc);
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 07/14] net: dwc_eth_qos: Allow platform to override tx/rx_fifo_sz
2023-02-01 13:58 ` [PATCH v2 07/14] net: dwc_eth_qos: Allow platform to override tx/rx_fifo_sz Sumit Garg
@ 2023-02-04 0:42 ` Ramon Fried
2023-02-10 18:44 ` Tom Rini
1 sibling, 0 replies; 30+ messages in thread
From: Ramon Fried @ 2023-02-04 0:42 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
On Wed, Feb 1, 2023 at 3:59 PM Sumit Garg <sumit.garg@linaro.org> wrote:
>
> The GMAC controller on QCS404 SoC (support added by upcoming patch) fails
> to work with maximum tx/rx_fifo_sz supported by the hardware (16K). So
> allow platforms to override FIFO size using corresponding DT node
> properties.
>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
> ---
> drivers/net/dwc_eth_qos.c | 19 +++++++++++++------
> drivers/net/dwc_eth_qos.h | 1 +
> 2 files changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 753a912607..65b8556be2 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -852,12 +852,19 @@ static int eqos_start(struct udevice *dev)
> rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) &
> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK;
>
> - /*
> - * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting.
> - * r/tqs is encoded as (n / 256) - 1.
> - */
> - tqs = (128 << tx_fifo_sz) / 256 - 1;
> - rqs = (128 << rx_fifo_sz) / 256 - 1;
> + /* r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting */
> + tx_fifo_sz = 128 << tx_fifo_sz;
> + rx_fifo_sz = 128 << rx_fifo_sz;
> +
> + /* Allow platform to override TX/RX fifo size */
> + if (eqos->tx_fifo_sz)
> + tx_fifo_sz = eqos->tx_fifo_sz;
> + if (eqos->rx_fifo_sz)
> + rx_fifo_sz = eqos->rx_fifo_sz;
> +
> + /* r/tqs is encoded as (n / 256) - 1 */
> + tqs = tx_fifo_sz / 256 - 1;
> + rqs = rx_fifo_sz / 256 - 1;
>
> clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode,
> EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK <<
> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
> index 8fccd6f057..466a792de7 100644
> --- a/drivers/net/dwc_eth_qos.h
> +++ b/drivers/net/dwc_eth_qos.h
> @@ -276,6 +276,7 @@ struct eqos_priv {
> bool started;
> bool reg_access_ok;
> bool clk_ck_enabled;
> + unsigned int tx_fifo_sz, rx_fifo_sz;
> };
>
> void eqos_inval_desc_generic(void *desc);
> --
> 2.34.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [PATCH v2 07/14] net: dwc_eth_qos: Allow platform to override tx/rx_fifo_sz
2023-02-01 13:58 ` [PATCH v2 07/14] net: dwc_eth_qos: Allow platform to override tx/rx_fifo_sz Sumit Garg
2023-02-04 0:42 ` Ramon Fried
@ 2023-02-10 18:44 ` Tom Rini
1 sibling, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:44 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 455 bytes --]
On Wed, Feb 01, 2023 at 07:28:54PM +0530, Sumit Garg wrote:
> The GMAC controller on QCS404 SoC (support added by upcoming patch) fails
> to work with maximum tx/rx_fifo_sz supported by the hardware (16K). So
> allow platforms to override FIFO size using corresponding DT node
> properties.
>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 08/14] net: dwc_eth_qos: Add Qcom ethernet driver glue layer
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (6 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 07/14] net: dwc_eth_qos: Allow platform to override tx/rx_fifo_sz Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-04 0:42 ` Ramon Fried
2023-02-10 18:44 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 09/14] dts: qcs404-evb: Add ethernet controller node Sumit Garg
` (4 subsequent siblings)
12 siblings, 2 replies; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
The Qualcom ETHQOS hardware supports an RGMII macro which needs to be
configured according to following link speeds:
- SPEED_1000
- SPEED_100
- SPEED_10
So add a corresponding glue driver to configure RGMII macro.
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
drivers/net/Kconfig | 7 +
drivers/net/Makefile | 1 +
drivers/net/dwc_eth_qos.c | 7 +
drivers/net/dwc_eth_qos.h | 3 +
drivers/net/dwc_eth_qos_qcom.c | 612 +++++++++++++++++++++++++++++++++
5 files changed, 630 insertions(+)
create mode 100644 drivers/net/dwc_eth_qos_qcom.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7873538cc2..815e1f9248 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -242,6 +242,13 @@ config DWC_ETH_QOS_TEGRA186
The Synopsys Designware Ethernet QOS IP block with specific
configuration used in NVIDIA's Tegra186 chip.
+config DWC_ETH_QOS_QCOM
+ bool "Synopsys DWC Ethernet QOS device support for Qcom SoCs"
+ depends on DWC_ETH_QOS
+ help
+ The Synopsys Designware Ethernet QOS IP block with specific
+ configuration used in Qcom QCS404 SoC.
+
config E1000
bool "Intel PRO/1000 Gigabit Ethernet support"
depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 5b4e60eea3..b009b10aca 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
+obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
obj-$(CONFIG_E1000) += e1000.o
obj-$(CONFIG_E1000_SPI) += e1000_spi.o
obj-$(CONFIG_EEPRO100) += eepro100.o
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 65b8556be2..112deb546d 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1712,6 +1712,13 @@ static const struct udevice_id eqos_ids[] = {
},
#endif
+#if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
+ {
+ .compatible = "qcom,qcs404-ethqos",
+ .data = (ulong)&eqos_qcom_config
+ },
+#endif
+
{ }
};
diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
index 466a792de7..fddbe9336c 100644
--- a/drivers/net/dwc_eth_qos.h
+++ b/drivers/net/dwc_eth_qos.h
@@ -253,6 +253,7 @@ struct eqos_priv {
struct eqos_mtl_regs *mtl_regs;
struct eqos_dma_regs *dma_regs;
struct eqos_tegra186_regs *tegra186_regs;
+ void *eqos_qcom_rgmii_regs;
struct reset_ctl reset_ctl;
struct gpio_desc phy_reset_gpio;
struct clk clk_master_bus;
@@ -277,6 +278,7 @@ struct eqos_priv {
bool reg_access_ok;
bool clk_ck_enabled;
unsigned int tx_fifo_sz, rx_fifo_sz;
+ u32 reset_delays[3];
};
void eqos_inval_desc_generic(void *desc);
@@ -286,3 +288,4 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
int eqos_null_ops(struct udevice *dev);
extern struct eqos_config eqos_imx_config;
+extern struct eqos_config eqos_qcom_config;
diff --git a/drivers/net/dwc_eth_qos_qcom.c b/drivers/net/dwc_eth_qos_qcom.c
new file mode 100644
index 0000000000..df83f1c5f9
--- /dev/null
+++ b/drivers/net/dwc_eth_qos_qcom.c
@@ -0,0 +1,612 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022-2023 Sumit Garg <sumit.garg@linaro.org>
+ *
+ * Qcom DWMAC specific glue layer
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <phy.h>
+#include <reset.h>
+#include <syscon.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+#include "dwc_eth_qos.h"
+
+/* RGMII_IO_MACRO_CONFIG fields */
+#define RGMII_CONFIG_FUNC_CLK_EN BIT(30)
+#define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23)
+#define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20)
+#define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17)
+#define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8)
+#define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6)
+#define RGMII_CONFIG_INTF_SEL GENMASK(5, 4)
+#define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3)
+#define RGMII_CONFIG_LOOPBACK_EN BIT(2)
+#define RGMII_CONFIG_PROG_SWAP BIT(1)
+#define RGMII_CONFIG_DDR_MODE BIT(0)
+
+/* SDCC_HC_REG_DLL_CONFIG fields */
+#define SDCC_DLL_CONFIG_DLL_RST BIT(30)
+#define SDCC_DLL_CONFIG_PDN BIT(29)
+#define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24)
+#define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20)
+#define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19)
+#define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18)
+#define SDCC_DLL_CONFIG_CDR_EN BIT(17)
+#define SDCC_DLL_CONFIG_DLL_EN BIT(16)
+#define SDCC_DLL_MCLK_GATING_EN BIT(5)
+#define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2)
+
+/* SDCC_HC_REG_DDR_CONFIG fields */
+#define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31)
+#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21)
+#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27)
+#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30)
+#define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0)
+
+/* SDCC_HC_REG_DLL_CONFIG2 fields */
+#define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21)
+#define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10)
+#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2)
+#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1)
+#define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0)
+
+/* SDC4_STATUS bits */
+#define SDC4_STATUS_DLL_LOCK BIT(7)
+
+/* RGMII_IO_MACRO_CONFIG2 fields */
+#define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17)
+#define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16)
+#define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13)
+#define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12)
+#define RGMII_CONFIG2_RX_PROG_SWAP BIT(7)
+#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6)
+#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5)
+
+struct dwmac_rgmii_regs {
+ u32 io_macro_config; /* 0x00 */
+ u32 sdcc_hc_dll_config; /* 0x04 */
+ u32 reserved_1; /* 0x08 */
+ u32 sdcc_hc_ddr_config; /* 0x0c */
+ u32 sdcc_hc_dll_config2; /* 0x10 */
+ u32 sdc4_status; /* 0x14 */
+ u32 sdcc_usr_ctl; /* 0x18 */
+ u32 io_macro_config2; /* 0x1c */
+ u32 io_macro_debug1; /* 0x20 */
+ u32 reserved_2; /* 0x24 */
+ u32 emac_sys_low_power_dbg; /* 0x28 */
+ u32 reserved_3[53]; /* upto 0x100 */
+};
+
+static struct dwmac_rgmii_regs emac_v2_3_0_por = {
+ .io_macro_config = 0x00C01343,
+ .sdcc_hc_dll_config = 0x2004642C,
+ .sdcc_hc_ddr_config = 0x00000000,
+ .sdcc_hc_dll_config2 = 0x00200000,
+ .sdcc_usr_ctl = 0x00010800,
+ .io_macro_config2 = 0x00002060
+};
+
+static void ethqos_set_func_clk_en(struct dwmac_rgmii_regs *regs)
+{
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_FUNC_CLK_EN);
+}
+
+static int ethqos_dll_configure(struct udevice *dev,
+ struct dwmac_rgmii_regs *regs)
+{
+ unsigned int val;
+ int retry = 1000;
+
+ /* Set CDR_EN */
+ setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EN);
+
+ /* Set CDR_EXT_EN */
+ setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EXT_EN);
+
+ /* Clear CK_OUT_EN */
+ clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
+
+ /* Set DLL_EN */
+ setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
+
+ clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_MCLK_GATING_EN);
+
+ clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CDR_FINE_PHASE);
+
+ /* Wait for CK_OUT_EN clear */
+ do {
+ val = readl(®s->sdcc_hc_dll_config);
+ val &= SDCC_DLL_CONFIG_CK_OUT_EN;
+ if (!val)
+ break;
+ mdelay(1);
+ retry--;
+ } while (retry > 0);
+ if (!retry)
+ dev_err(dev, "Clear CK_OUT_EN timedout\n");
+
+ /* Set CK_OUT_EN */
+ setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
+
+ /* Wait for CK_OUT_EN set */
+ retry = 1000;
+ do {
+ val = readl(®s->sdcc_hc_dll_config);
+ val &= SDCC_DLL_CONFIG_CK_OUT_EN;
+ if (val)
+ break;
+ mdelay(1);
+ retry--;
+ } while (retry > 0);
+ if (!retry)
+ dev_err(dev, "Set CK_OUT_EN timedout\n");
+
+ /* Set DDR_CAL_EN */
+ setbits_le32(®s->sdcc_hc_dll_config2, SDCC_DLL_CONFIG2_DDR_CAL_EN);
+
+ clrbits_le32(®s->sdcc_hc_dll_config2,
+ SDCC_DLL_CONFIG2_DLL_CLOCK_DIS);
+
+ clrsetbits_le32(®s->sdcc_hc_dll_config2,
+ SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 0x1A << 10);
+
+ clrsetbits_le32(®s->sdcc_hc_dll_config2,
+ SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, BIT(2));
+
+ setbits_le32(®s->sdcc_hc_dll_config2,
+ SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW);
+
+ return 0;
+}
+
+static int ethqos_rgmii_macro_init(struct udevice *dev,
+ struct dwmac_rgmii_regs *regs,
+ unsigned long speed)
+{
+ /* Disable loopback mode */
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN);
+
+ /* Select RGMII, write 0 to interface select */
+ clrbits_le32(®s->io_macro_config, RGMII_CONFIG_INTF_SEL);
+
+ switch (speed) {
+ case SPEED_1000:
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
+ clrbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_BYPASS_TX_ID_EN);
+ setbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_POS_NEG_DATA_SEL);
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
+
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
+ setbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_RSVD_CONFIG15);
+ setbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_RX_PROG_SWAP);
+
+ /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
+ clrsetbits_le32(®s->sdcc_hc_ddr_config,
+ SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57);
+ setbits_le32(®s->sdcc_hc_ddr_config, SDCC_DDR_CONFIG_PRG_DLY_EN);
+
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
+ break;
+
+ case SPEED_100:
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
+ setbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_BYPASS_TX_ID_EN);
+ clrbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_POS_NEG_DATA_SEL);
+ clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
+ clrsetbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_MAX_SPD_PRG_2, BIT(6));
+
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
+ setbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_RSVD_CONFIG15);
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_RX_PROG_SWAP);
+
+ /* Write 0x5 to PRG_RCLK_DLY_CODE */
+ clrsetbits_le32(®s->sdcc_hc_ddr_config,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
+ (BIT(29) | BIT(27)));
+ setbits_le32(®s->sdcc_hc_ddr_config,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
+ setbits_le32(®s->sdcc_hc_ddr_config,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
+
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
+ break;
+
+ case SPEED_10:
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
+ setbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_BYPASS_TX_ID_EN);
+ clrbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_POS_NEG_DATA_SEL);
+ clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
+ clrsetbits_le32(®s->io_macro_config,
+ RGMII_CONFIG_MAX_SPD_PRG_9,
+ BIT(12) | GENMASK(9, 8));
+
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_RSVD_CONFIG15);
+ clrbits_le32(®s->io_macro_config2,
+ RGMII_CONFIG2_RX_PROG_SWAP);
+
+ /* Write 0x5 to PRG_RCLK_DLY_CODE */
+ clrsetbits_le32(®s->sdcc_hc_ddr_config,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
+ (BIT(29) | BIT(27)));
+ setbits_le32(®s->sdcc_hc_ddr_config,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
+ setbits_le32(®s->sdcc_hc_ddr_config,
+ SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
+
+ setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
+ break;
+
+ default:
+ dev_err(dev, "Invalid speed %ld\n", speed);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ethqos_configure(struct udevice *dev,
+ struct dwmac_rgmii_regs *regs,
+ unsigned long speed)
+{
+ unsigned int retry = 1000;
+
+ /* Reset to POR values and enable clk */
+ writel(emac_v2_3_0_por.io_macro_config, ®s->io_macro_config);
+ writel(emac_v2_3_0_por.sdcc_hc_dll_config, ®s->sdcc_hc_dll_config);
+ writel(emac_v2_3_0_por.sdcc_hc_ddr_config, ®s->sdcc_hc_ddr_config);
+ writel(emac_v2_3_0_por.sdcc_hc_dll_config2, ®s->sdcc_hc_dll_config2);
+ writel(emac_v2_3_0_por.sdcc_usr_ctl, ®s->sdcc_usr_ctl);
+ writel(emac_v2_3_0_por.io_macro_config2, ®s->io_macro_config2);
+
+ ethqos_set_func_clk_en(regs);
+
+ /* Initialize the DLL first */
+
+ /* Set DLL_RST */
+ setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
+
+ /* Set PDN */
+ setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
+
+ /* Clear DLL_RST */
+ clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
+
+ /* Clear PDN */
+ clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
+
+ if (speed == SPEED_1000) {
+ /* Set DLL_EN */
+ setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
+
+ /* Set CK_OUT_EN */
+ setbits_le32(®s->sdcc_hc_dll_config,
+ SDCC_DLL_CONFIG_CK_OUT_EN);
+
+ /* Set USR_CTL bit 26 with mask of 3 bits */
+ clrsetbits_le32(®s->sdcc_usr_ctl, GENMASK(26, 24), BIT(26));
+
+ /* wait for DLL LOCK */
+ do {
+ mdelay(1);
+ if (readl(®s->sdc4_status) & SDC4_STATUS_DLL_LOCK)
+ break;
+ retry--;
+ } while (retry > 0);
+ if (!retry)
+ dev_err(dev, "Timeout while waiting for DLL lock\n");
+
+ ethqos_dll_configure(dev, regs);
+ }
+
+ ethqos_rgmii_macro_init(dev, regs, speed);
+
+ return 0;
+}
+
+static void ethqos_rgmii_dump(struct udevice *dev,
+ struct dwmac_rgmii_regs *regs)
+{
+ dev_dbg(dev, "Rgmii register dump\n");
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %08x\n",
+ readl(®s->io_macro_config));
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %08x\n",
+ readl(®s->sdcc_hc_dll_config));
+ dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %08x\n",
+ readl(®s->sdcc_hc_ddr_config));
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %08x\n",
+ readl(®s->sdcc_hc_dll_config2));
+ dev_dbg(dev, "SDC4_STATUS: %08x\n",
+ readl(®s->sdc4_status));
+ dev_dbg(dev, "SDCC_USR_CTL: %08x\n",
+ readl(®s->sdcc_usr_ctl));
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %08x\n",
+ readl(®s->io_macro_config2));
+ dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %08x\n",
+ readl(®s->io_macro_debug1));
+ dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %08x\n",
+ readl(®s->emac_sys_low_power_dbg));
+}
+
+static int qcom_eqos_rgmii_set_speed(struct udevice *dev,
+ void *rgmii_regs,
+ unsigned long speed)
+{
+ int ret;
+
+ ethqos_rgmii_dump(dev, rgmii_regs);
+
+ ret = ethqos_configure(dev, rgmii_regs, speed);
+ if (ret)
+ return ret;
+
+ ethqos_rgmii_dump(dev, rgmii_regs);
+
+ return 0;
+}
+
+static int qcom_eqos_rgmii_reset(struct udevice *dev, void *rgmii_regs)
+{
+ ethqos_set_func_clk_en(rgmii_regs);
+
+ return 0;
+}
+
+static int eqos_start_clks_qcom(struct udevice *dev)
+{
+ if (IS_ENABLED(CONFIG_CLK)) {
+ struct clk_bulk clocks;
+ int ret;
+
+ ret = clk_get_bulk(dev, &clocks);
+ if (ret)
+ return ret;
+
+ ret = clk_enable_bulk(&clocks);
+ if (ret)
+ return ret;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static int eqos_stop_clks_qcom(struct udevice *dev)
+{
+ if (IS_ENABLED(CONFIG_CLK)) {
+ struct clk_bulk clocks;
+ int ret;
+
+ ret = clk_get_bulk(dev, &clocks);
+ if (ret)
+ return ret;
+
+ ret = clk_disable_bulk(&clocks);
+ if (ret)
+ return ret;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static int eqos_start_resets_qcom(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ int ret;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ if (!eqos->phy) {
+ ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
+ if (ret < 0) {
+ pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret);
+ return ret;
+ }
+
+ udelay(eqos->reset_delays[0]);
+
+ ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
+ if (ret < 0) {
+ pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
+ return ret;
+ }
+
+ udelay(eqos->reset_delays[1]);
+
+ ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
+ if (ret < 0) {
+ pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
+ return ret;
+ }
+
+ udelay(eqos->reset_delays[2]);
+ }
+
+ ret = reset_deassert(&eqos->reset_ctl);
+ if (ret < 0) {
+ pr_err("reset_deassert() failed: %d", ret);
+ return ret;
+ }
+
+ ret = qcom_eqos_rgmii_reset(dev, eqos->eqos_qcom_rgmii_regs);
+ if (ret < 0) {
+ pr_err("qcom rgmii_reset failed: %d", ret);
+ return ret;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+/* Clock rates */
+#define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL)
+#define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL)
+#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL)
+
+static int eqos_set_tx_clk_speed_qcom(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ ulong rate;
+ int ret;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ switch (eqos->phy->speed) {
+ case SPEED_1000:
+ rate = RGMII_1000_NOM_CLK_FREQ;
+ break;
+ case SPEED_100:
+ rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
+ break;
+ case SPEED_10:
+ rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
+ break;
+ default:
+ pr_err("invalid speed %d", eqos->phy->speed);
+ return -EINVAL;
+ }
+
+ ret = clk_set_rate(&eqos->clk_tx, rate);
+ if (ret < 0) {
+ pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret);
+ return ret;
+ }
+
+ ret = qcom_eqos_rgmii_set_speed(dev, eqos->eqos_qcom_rgmii_regs,
+ eqos->phy->speed);
+ if (ret < 0) {
+ pr_err("qcom set_speed: %d, failed: %d", eqos->phy->speed, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int eqos_probe_resources_qcom(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ phy_interface_t interface;
+ int reset_flags = GPIOD_IS_OUT;
+ int ret;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ interface = eqos->config->interface(dev);
+
+ if (interface == PHY_INTERFACE_MODE_NA) {
+ pr_err("Invalid PHY interface\n");
+ return -EINVAL;
+ }
+
+ eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
+
+ eqos->tx_fifo_sz = dev_read_u32_default(dev, "tx-fifo-depth", 0);
+ eqos->rx_fifo_sz = dev_read_u32_default(dev, "rx-fifo-depth", 0);
+
+ ret = reset_get_by_name(dev, "emac", &eqos->reset_ctl);
+ if (ret) {
+ pr_err("reset_get_by_name(rst) failed: %d", ret);
+ return ret;
+ }
+
+ if (dev_read_bool(dev, "snps,reset-active-low"))
+ reset_flags |= GPIOD_ACTIVE_LOW;
+
+ ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
+ &eqos->phy_reset_gpio, reset_flags);
+ if (ret == 0) {
+ ret = dev_read_u32_array(dev, "snps,reset-delays-us",
+ eqos->reset_delays, 3);
+ } else if (ret == -ENOENT) {
+ ret = 0;
+ }
+
+ eqos->eqos_qcom_rgmii_regs = (void *)dev_read_addr_name(dev, "rgmii");
+ if ((fdt_addr_t)eqos->eqos_qcom_rgmii_regs == FDT_ADDR_T_NONE) {
+ pr_err("Invalid RGMII address\n");
+ return -EINVAL;
+ }
+
+ ret = clk_get_by_name(dev, "rgmii", &eqos->clk_tx);
+ if (ret) {
+ pr_err("clk_get_by_name(tx) failed: %d", ret);
+ return -EINVAL;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static int eqos_remove_resources_qcom(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ clk_free(&eqos->clk_tx);
+ dm_gpio_free(dev, &eqos->phy_reset_gpio);
+ reset_free(&eqos->reset_ctl);
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static struct eqos_ops eqos_qcom_ops = {
+ .eqos_inval_desc = eqos_inval_desc_generic,
+ .eqos_flush_desc = eqos_flush_desc_generic,
+ .eqos_inval_buffer = eqos_inval_buffer_generic,
+ .eqos_flush_buffer = eqos_flush_buffer_generic,
+ .eqos_probe_resources = eqos_probe_resources_qcom,
+ .eqos_remove_resources = eqos_remove_resources_qcom,
+ .eqos_stop_resets = eqos_null_ops,
+ .eqos_start_resets = eqos_start_resets_qcom,
+ .eqos_stop_clks = eqos_stop_clks_qcom,
+ .eqos_start_clks = eqos_start_clks_qcom,
+ .eqos_calibrate_pads = eqos_null_ops,
+ .eqos_disable_calibration = eqos_null_ops,
+ .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_qcom,
+ .eqos_get_enetaddr = eqos_null_ops,
+};
+
+struct eqos_config __maybe_unused eqos_qcom_config = {
+ .reg_access_always_ok = false,
+ .mdio_wait = 10,
+ .swr_wait = 50,
+ .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+ .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
+ .axi_bus_width = EQOS_AXI_WIDTH_64,
+ .interface = dev_read_phy_mode,
+ .ops = &eqos_qcom_ops
+};
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 08/14] net: dwc_eth_qos: Add Qcom ethernet driver glue layer
2023-02-01 13:58 ` [PATCH v2 08/14] net: dwc_eth_qos: Add Qcom ethernet driver glue layer Sumit Garg
@ 2023-02-04 0:42 ` Ramon Fried
2023-02-10 18:44 ` Tom Rini
1 sibling, 0 replies; 30+ messages in thread
From: Ramon Fried @ 2023-02-04 0:42 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
On Wed, Feb 1, 2023 at 3:59 PM Sumit Garg <sumit.garg@linaro.org> wrote:
>
> The Qualcom ETHQOS hardware supports an RGMII macro which needs to be
> configured according to following link speeds:
> - SPEED_1000
> - SPEED_100
> - SPEED_10
>
> So add a corresponding glue driver to configure RGMII macro.
>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
> ---
> drivers/net/Kconfig | 7 +
> drivers/net/Makefile | 1 +
> drivers/net/dwc_eth_qos.c | 7 +
> drivers/net/dwc_eth_qos.h | 3 +
> drivers/net/dwc_eth_qos_qcom.c | 612 +++++++++++++++++++++++++++++++++
> 5 files changed, 630 insertions(+)
> create mode 100644 drivers/net/dwc_eth_qos_qcom.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 7873538cc2..815e1f9248 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -242,6 +242,13 @@ config DWC_ETH_QOS_TEGRA186
> The Synopsys Designware Ethernet QOS IP block with specific
> configuration used in NVIDIA's Tegra186 chip.
>
> +config DWC_ETH_QOS_QCOM
> + bool "Synopsys DWC Ethernet QOS device support for Qcom SoCs"
> + depends on DWC_ETH_QOS
> + help
> + The Synopsys Designware Ethernet QOS IP block with specific
> + configuration used in Qcom QCS404 SoC.
> +
> config E1000
> bool "Intel PRO/1000 Gigabit Ethernet support"
> depends on PCI
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 5b4e60eea3..b009b10aca 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
> obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
> obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
> obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
> +obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
> obj-$(CONFIG_E1000) += e1000.o
> obj-$(CONFIG_E1000_SPI) += e1000_spi.o
> obj-$(CONFIG_EEPRO100) += eepro100.o
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 65b8556be2..112deb546d 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1712,6 +1712,13 @@ static const struct udevice_id eqos_ids[] = {
> },
> #endif
>
> +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
> + {
> + .compatible = "qcom,qcs404-ethqos",
> + .data = (ulong)&eqos_qcom_config
> + },
> +#endif
> +
> { }
> };
>
> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
> index 466a792de7..fddbe9336c 100644
> --- a/drivers/net/dwc_eth_qos.h
> +++ b/drivers/net/dwc_eth_qos.h
> @@ -253,6 +253,7 @@ struct eqos_priv {
> struct eqos_mtl_regs *mtl_regs;
> struct eqos_dma_regs *dma_regs;
> struct eqos_tegra186_regs *tegra186_regs;
> + void *eqos_qcom_rgmii_regs;
> struct reset_ctl reset_ctl;
> struct gpio_desc phy_reset_gpio;
> struct clk clk_master_bus;
> @@ -277,6 +278,7 @@ struct eqos_priv {
> bool reg_access_ok;
> bool clk_ck_enabled;
> unsigned int tx_fifo_sz, rx_fifo_sz;
> + u32 reset_delays[3];
> };
>
> void eqos_inval_desc_generic(void *desc);
> @@ -286,3 +288,4 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
> int eqos_null_ops(struct udevice *dev);
>
> extern struct eqos_config eqos_imx_config;
> +extern struct eqos_config eqos_qcom_config;
> diff --git a/drivers/net/dwc_eth_qos_qcom.c b/drivers/net/dwc_eth_qos_qcom.c
> new file mode 100644
> index 0000000000..df83f1c5f9
> --- /dev/null
> +++ b/drivers/net/dwc_eth_qos_qcom.c
> @@ -0,0 +1,612 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022-2023 Sumit Garg <sumit.garg@linaro.org>
> + *
> + * Qcom DWMAC specific glue layer
> + */
> +
> +#include <common.h>
> +#include <asm/global_data.h>
> +#include <asm/gpio.h>
> +#include <asm/io.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <phy.h>
> +#include <reset.h>
> +#include <syscon.h>
> +#include <linux/bitops.h>
> +#include <linux/delay.h>
> +
> +#include "dwc_eth_qos.h"
> +
> +/* RGMII_IO_MACRO_CONFIG fields */
> +#define RGMII_CONFIG_FUNC_CLK_EN BIT(30)
> +#define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23)
> +#define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20)
> +#define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17)
> +#define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8)
> +#define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6)
> +#define RGMII_CONFIG_INTF_SEL GENMASK(5, 4)
> +#define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3)
> +#define RGMII_CONFIG_LOOPBACK_EN BIT(2)
> +#define RGMII_CONFIG_PROG_SWAP BIT(1)
> +#define RGMII_CONFIG_DDR_MODE BIT(0)
> +
> +/* SDCC_HC_REG_DLL_CONFIG fields */
> +#define SDCC_DLL_CONFIG_DLL_RST BIT(30)
> +#define SDCC_DLL_CONFIG_PDN BIT(29)
> +#define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24)
> +#define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20)
> +#define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19)
> +#define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18)
> +#define SDCC_DLL_CONFIG_CDR_EN BIT(17)
> +#define SDCC_DLL_CONFIG_DLL_EN BIT(16)
> +#define SDCC_DLL_MCLK_GATING_EN BIT(5)
> +#define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2)
> +
> +/* SDCC_HC_REG_DDR_CONFIG fields */
> +#define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31)
> +#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21)
> +#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27)
> +#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30)
> +#define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0)
> +
> +/* SDCC_HC_REG_DLL_CONFIG2 fields */
> +#define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21)
> +#define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10)
> +#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2)
> +#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1)
> +#define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0)
> +
> +/* SDC4_STATUS bits */
> +#define SDC4_STATUS_DLL_LOCK BIT(7)
> +
> +/* RGMII_IO_MACRO_CONFIG2 fields */
> +#define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17)
> +#define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16)
> +#define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13)
> +#define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12)
> +#define RGMII_CONFIG2_RX_PROG_SWAP BIT(7)
> +#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6)
> +#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5)
> +
> +struct dwmac_rgmii_regs {
> + u32 io_macro_config; /* 0x00 */
> + u32 sdcc_hc_dll_config; /* 0x04 */
> + u32 reserved_1; /* 0x08 */
> + u32 sdcc_hc_ddr_config; /* 0x0c */
> + u32 sdcc_hc_dll_config2; /* 0x10 */
> + u32 sdc4_status; /* 0x14 */
> + u32 sdcc_usr_ctl; /* 0x18 */
> + u32 io_macro_config2; /* 0x1c */
> + u32 io_macro_debug1; /* 0x20 */
> + u32 reserved_2; /* 0x24 */
> + u32 emac_sys_low_power_dbg; /* 0x28 */
> + u32 reserved_3[53]; /* upto 0x100 */
> +};
> +
> +static struct dwmac_rgmii_regs emac_v2_3_0_por = {
> + .io_macro_config = 0x00C01343,
> + .sdcc_hc_dll_config = 0x2004642C,
> + .sdcc_hc_ddr_config = 0x00000000,
> + .sdcc_hc_dll_config2 = 0x00200000,
> + .sdcc_usr_ctl = 0x00010800,
> + .io_macro_config2 = 0x00002060
> +};
> +
> +static void ethqos_set_func_clk_en(struct dwmac_rgmii_regs *regs)
> +{
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_FUNC_CLK_EN);
> +}
> +
> +static int ethqos_dll_configure(struct udevice *dev,
> + struct dwmac_rgmii_regs *regs)
> +{
> + unsigned int val;
> + int retry = 1000;
> +
> + /* Set CDR_EN */
> + setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EN);
> +
> + /* Set CDR_EXT_EN */
> + setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EXT_EN);
> +
> + /* Clear CK_OUT_EN */
> + clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
> +
> + /* Set DLL_EN */
> + setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
> +
> + clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_MCLK_GATING_EN);
> +
> + clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CDR_FINE_PHASE);
> +
> + /* Wait for CK_OUT_EN clear */
> + do {
> + val = readl(®s->sdcc_hc_dll_config);
> + val &= SDCC_DLL_CONFIG_CK_OUT_EN;
> + if (!val)
> + break;
> + mdelay(1);
> + retry--;
> + } while (retry > 0);
> + if (!retry)
> + dev_err(dev, "Clear CK_OUT_EN timedout\n");
> +
> + /* Set CK_OUT_EN */
> + setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN);
> +
> + /* Wait for CK_OUT_EN set */
> + retry = 1000;
> + do {
> + val = readl(®s->sdcc_hc_dll_config);
> + val &= SDCC_DLL_CONFIG_CK_OUT_EN;
> + if (val)
> + break;
> + mdelay(1);
> + retry--;
> + } while (retry > 0);
> + if (!retry)
> + dev_err(dev, "Set CK_OUT_EN timedout\n");
> +
> + /* Set DDR_CAL_EN */
> + setbits_le32(®s->sdcc_hc_dll_config2, SDCC_DLL_CONFIG2_DDR_CAL_EN);
> +
> + clrbits_le32(®s->sdcc_hc_dll_config2,
> + SDCC_DLL_CONFIG2_DLL_CLOCK_DIS);
> +
> + clrsetbits_le32(®s->sdcc_hc_dll_config2,
> + SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 0x1A << 10);
> +
> + clrsetbits_le32(®s->sdcc_hc_dll_config2,
> + SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, BIT(2));
> +
> + setbits_le32(®s->sdcc_hc_dll_config2,
> + SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW);
> +
> + return 0;
> +}
> +
> +static int ethqos_rgmii_macro_init(struct udevice *dev,
> + struct dwmac_rgmii_regs *regs,
> + unsigned long speed)
> +{
> + /* Disable loopback mode */
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN);
> +
> + /* Select RGMII, write 0 to interface select */
> + clrbits_le32(®s->io_macro_config, RGMII_CONFIG_INTF_SEL);
> +
> + switch (speed) {
> + case SPEED_1000:
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
> + clrbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_BYPASS_TX_ID_EN);
> + setbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_POS_NEG_DATA_SEL);
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
> +
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
> + setbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_RSVD_CONFIG15);
> + setbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_RX_PROG_SWAP);
> +
> + /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
> + clrsetbits_le32(®s->sdcc_hc_ddr_config,
> + SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57);
> + setbits_le32(®s->sdcc_hc_ddr_config, SDCC_DDR_CONFIG_PRG_DLY_EN);
> +
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
> + break;
> +
> + case SPEED_100:
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
> + setbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_BYPASS_TX_ID_EN);
> + clrbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_POS_NEG_DATA_SEL);
> + clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
> + clrsetbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_MAX_SPD_PRG_2, BIT(6));
> +
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
> + setbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_RSVD_CONFIG15);
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_RX_PROG_SWAP);
> +
> + /* Write 0x5 to PRG_RCLK_DLY_CODE */
> + clrsetbits_le32(®s->sdcc_hc_ddr_config,
> + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
> + (BIT(29) | BIT(27)));
> + setbits_le32(®s->sdcc_hc_ddr_config,
> + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
> + setbits_le32(®s->sdcc_hc_ddr_config,
> + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
> +
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
> + break;
> +
> + case SPEED_10:
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE);
> + setbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_BYPASS_TX_ID_EN);
> + clrbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_POS_NEG_DATA_SEL);
> + clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP);
> + clrsetbits_le32(®s->io_macro_config,
> + RGMII_CONFIG_MAX_SPD_PRG_9,
> + BIT(12) | GENMASK(9, 8));
> +
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL);
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN);
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_RSVD_CONFIG15);
> + clrbits_le32(®s->io_macro_config2,
> + RGMII_CONFIG2_RX_PROG_SWAP);
> +
> + /* Write 0x5 to PRG_RCLK_DLY_CODE */
> + clrsetbits_le32(®s->sdcc_hc_ddr_config,
> + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
> + (BIT(29) | BIT(27)));
> + setbits_le32(®s->sdcc_hc_ddr_config,
> + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY);
> + setbits_le32(®s->sdcc_hc_ddr_config,
> + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN);
> +
> + setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN);
> + break;
> +
> + default:
> + dev_err(dev, "Invalid speed %ld\n", speed);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int ethqos_configure(struct udevice *dev,
> + struct dwmac_rgmii_regs *regs,
> + unsigned long speed)
> +{
> + unsigned int retry = 1000;
> +
> + /* Reset to POR values and enable clk */
> + writel(emac_v2_3_0_por.io_macro_config, ®s->io_macro_config);
> + writel(emac_v2_3_0_por.sdcc_hc_dll_config, ®s->sdcc_hc_dll_config);
> + writel(emac_v2_3_0_por.sdcc_hc_ddr_config, ®s->sdcc_hc_ddr_config);
> + writel(emac_v2_3_0_por.sdcc_hc_dll_config2, ®s->sdcc_hc_dll_config2);
> + writel(emac_v2_3_0_por.sdcc_usr_ctl, ®s->sdcc_usr_ctl);
> + writel(emac_v2_3_0_por.io_macro_config2, ®s->io_macro_config2);
> +
> + ethqos_set_func_clk_en(regs);
> +
> + /* Initialize the DLL first */
> +
> + /* Set DLL_RST */
> + setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
> +
> + /* Set PDN */
> + setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
> +
> + /* Clear DLL_RST */
> + clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST);
> +
> + /* Clear PDN */
> + clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN);
> +
> + if (speed == SPEED_1000) {
> + /* Set DLL_EN */
> + setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN);
> +
> + /* Set CK_OUT_EN */
> + setbits_le32(®s->sdcc_hc_dll_config,
> + SDCC_DLL_CONFIG_CK_OUT_EN);
> +
> + /* Set USR_CTL bit 26 with mask of 3 bits */
> + clrsetbits_le32(®s->sdcc_usr_ctl, GENMASK(26, 24), BIT(26));
> +
> + /* wait for DLL LOCK */
> + do {
> + mdelay(1);
> + if (readl(®s->sdc4_status) & SDC4_STATUS_DLL_LOCK)
> + break;
> + retry--;
> + } while (retry > 0);
> + if (!retry)
> + dev_err(dev, "Timeout while waiting for DLL lock\n");
> +
> + ethqos_dll_configure(dev, regs);
> + }
> +
> + ethqos_rgmii_macro_init(dev, regs, speed);
> +
> + return 0;
> +}
> +
> +static void ethqos_rgmii_dump(struct udevice *dev,
> + struct dwmac_rgmii_regs *regs)
> +{
> + dev_dbg(dev, "Rgmii register dump\n");
> + dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %08x\n",
> + readl(®s->io_macro_config));
> + dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %08x\n",
> + readl(®s->sdcc_hc_dll_config));
> + dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %08x\n",
> + readl(®s->sdcc_hc_ddr_config));
> + dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %08x\n",
> + readl(®s->sdcc_hc_dll_config2));
> + dev_dbg(dev, "SDC4_STATUS: %08x\n",
> + readl(®s->sdc4_status));
> + dev_dbg(dev, "SDCC_USR_CTL: %08x\n",
> + readl(®s->sdcc_usr_ctl));
> + dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %08x\n",
> + readl(®s->io_macro_config2));
> + dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %08x\n",
> + readl(®s->io_macro_debug1));
> + dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %08x\n",
> + readl(®s->emac_sys_low_power_dbg));
> +}
> +
> +static int qcom_eqos_rgmii_set_speed(struct udevice *dev,
> + void *rgmii_regs,
> + unsigned long speed)
> +{
> + int ret;
> +
> + ethqos_rgmii_dump(dev, rgmii_regs);
> +
> + ret = ethqos_configure(dev, rgmii_regs, speed);
> + if (ret)
> + return ret;
> +
> + ethqos_rgmii_dump(dev, rgmii_regs);
> +
> + return 0;
> +}
> +
> +static int qcom_eqos_rgmii_reset(struct udevice *dev, void *rgmii_regs)
> +{
> + ethqos_set_func_clk_en(rgmii_regs);
> +
> + return 0;
> +}
> +
> +static int eqos_start_clks_qcom(struct udevice *dev)
> +{
> + if (IS_ENABLED(CONFIG_CLK)) {
> + struct clk_bulk clocks;
> + int ret;
> +
> + ret = clk_get_bulk(dev, &clocks);
> + if (ret)
> + return ret;
> +
> + ret = clk_enable_bulk(&clocks);
> + if (ret)
> + return ret;
> + }
> +
> + debug("%s: OK\n", __func__);
> + return 0;
> +}
> +
> +static int eqos_stop_clks_qcom(struct udevice *dev)
> +{
> + if (IS_ENABLED(CONFIG_CLK)) {
> + struct clk_bulk clocks;
> + int ret;
> +
> + ret = clk_get_bulk(dev, &clocks);
> + if (ret)
> + return ret;
> +
> + ret = clk_disable_bulk(&clocks);
> + if (ret)
> + return ret;
> + }
> +
> + debug("%s: OK\n", __func__);
> + return 0;
> +}
> +
> +static int eqos_start_resets_qcom(struct udevice *dev)
> +{
> + struct eqos_priv *eqos = dev_get_priv(dev);
> + int ret;
> +
> + debug("%s(dev=%p):\n", __func__, dev);
> +
> + if (!eqos->phy) {
> + ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
> + if (ret < 0) {
> + pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret);
> + return ret;
> + }
> +
> + udelay(eqos->reset_delays[0]);
> +
> + ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
> + if (ret < 0) {
> + pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
> + return ret;
> + }
> +
> + udelay(eqos->reset_delays[1]);
> +
> + ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
> + if (ret < 0) {
> + pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
> + return ret;
> + }
> +
> + udelay(eqos->reset_delays[2]);
> + }
> +
> + ret = reset_deassert(&eqos->reset_ctl);
> + if (ret < 0) {
> + pr_err("reset_deassert() failed: %d", ret);
> + return ret;
> + }
> +
> + ret = qcom_eqos_rgmii_reset(dev, eqos->eqos_qcom_rgmii_regs);
> + if (ret < 0) {
> + pr_err("qcom rgmii_reset failed: %d", ret);
> + return ret;
> + }
> +
> + debug("%s: OK\n", __func__);
> + return 0;
> +}
> +
> +/* Clock rates */
> +#define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL)
> +#define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL)
> +#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL)
> +
> +static int eqos_set_tx_clk_speed_qcom(struct udevice *dev)
> +{
> + struct eqos_priv *eqos = dev_get_priv(dev);
> + ulong rate;
> + int ret;
> +
> + debug("%s(dev=%p):\n", __func__, dev);
> +
> + switch (eqos->phy->speed) {
> + case SPEED_1000:
> + rate = RGMII_1000_NOM_CLK_FREQ;
> + break;
> + case SPEED_100:
> + rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
> + break;
> + case SPEED_10:
> + rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
> + break;
> + default:
> + pr_err("invalid speed %d", eqos->phy->speed);
> + return -EINVAL;
> + }
> +
> + ret = clk_set_rate(&eqos->clk_tx, rate);
> + if (ret < 0) {
> + pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret);
> + return ret;
> + }
> +
> + ret = qcom_eqos_rgmii_set_speed(dev, eqos->eqos_qcom_rgmii_regs,
> + eqos->phy->speed);
> + if (ret < 0) {
> + pr_err("qcom set_speed: %d, failed: %d", eqos->phy->speed, ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int eqos_probe_resources_qcom(struct udevice *dev)
> +{
> + struct eqos_priv *eqos = dev_get_priv(dev);
> + phy_interface_t interface;
> + int reset_flags = GPIOD_IS_OUT;
> + int ret;
> +
> + debug("%s(dev=%p):\n", __func__, dev);
> +
> + interface = eqos->config->interface(dev);
> +
> + if (interface == PHY_INTERFACE_MODE_NA) {
> + pr_err("Invalid PHY interface\n");
> + return -EINVAL;
> + }
> +
> + eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
> +
> + eqos->tx_fifo_sz = dev_read_u32_default(dev, "tx-fifo-depth", 0);
> + eqos->rx_fifo_sz = dev_read_u32_default(dev, "rx-fifo-depth", 0);
> +
> + ret = reset_get_by_name(dev, "emac", &eqos->reset_ctl);
> + if (ret) {
> + pr_err("reset_get_by_name(rst) failed: %d", ret);
> + return ret;
> + }
> +
> + if (dev_read_bool(dev, "snps,reset-active-low"))
> + reset_flags |= GPIOD_ACTIVE_LOW;
> +
> + ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
> + &eqos->phy_reset_gpio, reset_flags);
> + if (ret == 0) {
> + ret = dev_read_u32_array(dev, "snps,reset-delays-us",
> + eqos->reset_delays, 3);
> + } else if (ret == -ENOENT) {
> + ret = 0;
> + }
> +
> + eqos->eqos_qcom_rgmii_regs = (void *)dev_read_addr_name(dev, "rgmii");
> + if ((fdt_addr_t)eqos->eqos_qcom_rgmii_regs == FDT_ADDR_T_NONE) {
> + pr_err("Invalid RGMII address\n");
> + return -EINVAL;
> + }
> +
> + ret = clk_get_by_name(dev, "rgmii", &eqos->clk_tx);
> + if (ret) {
> + pr_err("clk_get_by_name(tx) failed: %d", ret);
> + return -EINVAL;
> + }
> +
> + debug("%s: OK\n", __func__);
> + return 0;
> +}
> +
> +static int eqos_remove_resources_qcom(struct udevice *dev)
> +{
> + struct eqos_priv *eqos = dev_get_priv(dev);
> +
> + debug("%s(dev=%p):\n", __func__, dev);
> +
> + clk_free(&eqos->clk_tx);
> + dm_gpio_free(dev, &eqos->phy_reset_gpio);
> + reset_free(&eqos->reset_ctl);
> +
> + debug("%s: OK\n", __func__);
> + return 0;
> +}
> +
> +static struct eqos_ops eqos_qcom_ops = {
> + .eqos_inval_desc = eqos_inval_desc_generic,
> + .eqos_flush_desc = eqos_flush_desc_generic,
> + .eqos_inval_buffer = eqos_inval_buffer_generic,
> + .eqos_flush_buffer = eqos_flush_buffer_generic,
> + .eqos_probe_resources = eqos_probe_resources_qcom,
> + .eqos_remove_resources = eqos_remove_resources_qcom,
> + .eqos_stop_resets = eqos_null_ops,
> + .eqos_start_resets = eqos_start_resets_qcom,
> + .eqos_stop_clks = eqos_stop_clks_qcom,
> + .eqos_start_clks = eqos_start_clks_qcom,
> + .eqos_calibrate_pads = eqos_null_ops,
> + .eqos_disable_calibration = eqos_null_ops,
> + .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_qcom,
> + .eqos_get_enetaddr = eqos_null_ops,
> +};
> +
> +struct eqos_config __maybe_unused eqos_qcom_config = {
> + .reg_access_always_ok = false,
> + .mdio_wait = 10,
> + .swr_wait = 50,
> + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
> + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
> + .axi_bus_width = EQOS_AXI_WIDTH_64,
> + .interface = dev_read_phy_mode,
> + .ops = &eqos_qcom_ops
> +};
> --
> 2.34.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
^ permalink raw reply [flat|nested] 30+ messages in thread* Re: [PATCH v2 08/14] net: dwc_eth_qos: Add Qcom ethernet driver glue layer
2023-02-01 13:58 ` [PATCH v2 08/14] net: dwc_eth_qos: Add Qcom ethernet driver glue layer Sumit Garg
2023-02-04 0:42 ` Ramon Fried
@ 2023-02-10 18:44 ` Tom Rini
1 sibling, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:44 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 456 bytes --]
On Wed, Feb 01, 2023 at 07:28:55PM +0530, Sumit Garg wrote:
> The Qualcom ETHQOS hardware supports an RGMII macro which needs to be
> configured according to following link speeds:
> - SPEED_1000
> - SPEED_100
> - SPEED_10
>
> So add a corresponding glue driver to configure RGMII macro.
>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 09/14] dts: qcs404-evb: Add ethernet controller node
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (7 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 08/14] net: dwc_eth_qos: Add Qcom ethernet driver glue layer Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:44 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 10/14] clock-snapdragon: Add clk_rcg_set_rate() with mnd_width=0 Sumit Garg
` (3 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/dts/qcs404-evb.dts | 98 ++++++++++++++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/qcs404-evb.dts b/arch/arm/dts/qcs404-evb.dts
index cc70afa4c8..2de0e7537b 100644
--- a/arch/arm/dts/qcs404-evb.dts
+++ b/arch/arm/dts/qcs404-evb.dts
@@ -36,7 +36,7 @@
ranges = <0x0 0x0 0x0 0xffffffff>;
compatible = "simple-bus";
- pinctrl_north@1300000 {
+ soc_gpios: pinctrl_north@1300000 {
compatible = "qcom,qcs404-pinctrl";
reg = <0x1300000 0x200000>;
gpio-controller;
@@ -48,6 +48,61 @@
pins = "GPIO_17", "GPIO_18";
function = "blsp_uart2";
};
+
+ ethernet_defaults: ethernet-defaults {
+ int {
+ pins = "GPIO_61";
+ function = "rgmii_int";
+ bias-disable;
+ drive-strength = <2>;
+ };
+ mdc {
+ pins = "GPIO_76";
+ function = "rgmii_mdc";
+ bias-pull-up;
+ };
+ mdio {
+ pins = "GPIO_75";
+ function = "rgmii_mdio";
+ bias-pull-up;
+ };
+ tx {
+ pins = "GPIO_67", "GPIO_66", "GPIO_65", "GPIO_64";
+ function = "rgmii_tx";
+ bias-pull-up;
+ drive-strength = <16>;
+ };
+ rx {
+ pins = "GPIO_73", "GPIO_72", "GPIO_71", "GPIO_70";
+ function = "rgmii_rx";
+ bias-disable;
+ drive-strength = <2>;
+ };
+ tx-ctl {
+ pins = "GPIO_68";
+ function = "rgmii_ctl";
+ bias-pull-up;
+ drive-strength = <16>;
+ };
+ rx-ctl {
+ pins = "GPIO_74";
+ function = "rgmii_ctl";
+ bias-disable;
+ drive-strength = <2>;
+ };
+ tx-ck {
+ pins = "GPIO_63";
+ function = "rgmii_ck";
+ bias-pull-up;
+ drive-strength = <16>;
+ };
+ rx-ck {
+ pins = "GPIO_69";
+ function = "rgmii_ck";
+ bias-disable;
+ drive-strength = <2>;
+ };
+ };
};
gcc: clock-controller@1800000 {
@@ -172,6 +227,47 @@
};
};
+ ethernet: ethernet@7a80000 {
+ compatible = "qcom,qcs404-ethqos";
+ reg = <0x07a80000 0x10000>,
+ <0x07a96000 0x100>;
+ reg-names = "stmmaceth", "rgmii";
+ clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii";
+ clocks = <&gcc GCC_ETH_AXI_CLK>,
+ <&gcc GCC_ETH_SLAVE_AHB_CLK>,
+ <&gcc GCC_ETH_PTP_CLK>,
+ <&gcc GCC_ETH_RGMII_CLK>;
+
+ resets = <&reset GCC_EMAC_BCR>;
+ reset-names = "emac";
+
+ snps,tso;
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <4096>;
+
+ snps,reset-gpio = <&soc_gpios 60 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 10000>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <ðernet_defaults>;
+
+ phy-handle = <&phy1>;
+ phy-mode = "rgmii";
+ max-speed = <1000>;
+
+ mdio {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ compatible = "snps,dwmac-mdio";
+ phy1: phy@3 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ device_type = "ethernet-phy";
+ reg = <0x3>;
+ };
+ };
+ };
+
spmi@200f000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x200f000 0x1000
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 09/14] dts: qcs404-evb: Add ethernet controller node
2023-02-01 13:58 ` [PATCH v2 09/14] dts: qcs404-evb: Add ethernet controller node Sumit Garg
@ 2023-02-10 18:44 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:44 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 165 bytes --]
On Wed, Feb 01, 2023 at 07:28:56PM +0530, Sumit Garg wrote:
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 10/14] clock-snapdragon: Add clk_rcg_set_rate() with mnd_width=0
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (8 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 09/14] dts: qcs404-evb: Add ethernet controller node Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:44 ` Tom Rini
2023-02-01 13:58 ` [PATCH v2 12/14] pinctrl: qcs404: Enable I2C pinmux options Sumit Garg
` (2 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Add clk_rcg_set_rate() which allows to configure clocks without programming
MND values. This is required for configuring I2C clocks on QCS404.
Co-developed-by: Mike Worsfold <mworsfold@impinj.com>
Signed-off-by: Mike Worsfold <mworsfold@impinj.com>
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/mach-snapdragon/clock-snapdragon.c | 24 +++++++++++++++++++++
arch/arm/mach-snapdragon/clock-snapdragon.h | 2 ++
2 files changed, 26 insertions(+)
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.c b/arch/arm/mach-snapdragon/clock-snapdragon.c
index fda7098274..0ac45dce9a 100644
--- a/arch/arm/mach-snapdragon/clock-snapdragon.c
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.c
@@ -111,6 +111,30 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
clk_bcr_update(base + regs->cmd_rcgr);
}
+/* root set rate for clocks with half integer and mnd_width=0 */
+void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div,
+ int source)
+{
+ u32 cfg;
+
+ /* setup src select and divider */
+ cfg = readl(base + regs->cfg_rcgr);
+ cfg &= ~CFG_MASK;
+ cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
+
+ /*
+ * Set the divider; HW permits fraction dividers (+0.5), but
+ * for simplicity, we will support integers only
+ */
+ if (div)
+ cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;
+
+ writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */
+
+ /* Inform h/w to start using the new config. */
+ clk_bcr_update(base + regs->cmd_rcgr);
+}
+
static int msm_clk_probe(struct udevice *dev)
{
struct msm_clk_priv *priv = dev_get_priv(dev);
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.h b/arch/arm/mach-snapdragon/clock-snapdragon.h
index 2ac53b538d..c90bbefa58 100644
--- a/arch/arm/mach-snapdragon/clock-snapdragon.h
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.h
@@ -42,5 +42,7 @@ void clk_enable_cbc(phys_addr_t cbcr);
void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk);
void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
int div, int m, int n, int source);
+void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div,
+ int source);
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 10/14] clock-snapdragon: Add clk_rcg_set_rate() with mnd_width=0
2023-02-01 13:58 ` [PATCH v2 10/14] clock-snapdragon: Add clk_rcg_set_rate() with mnd_width=0 Sumit Garg
@ 2023-02-10 18:44 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:44 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 430 bytes --]
On Wed, Feb 01, 2023 at 07:28:57PM +0530, Sumit Garg wrote:
> Add clk_rcg_set_rate() which allows to configure clocks without programming
> MND values. This is required for configuring I2C clocks on QCS404.
>
> Co-developed-by: Mike Worsfold <mworsfold@impinj.com>
> Signed-off-by: Mike Worsfold <mworsfold@impinj.com>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 12/14] pinctrl: qcs404: Enable I2C pinmux options
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (9 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 10/14] clock-snapdragon: Add clk_rcg_set_rate() with mnd_width=0 Sumit Garg
@ 2023-02-01 13:58 ` Sumit Garg
2023-02-10 18:44 ` Tom Rini
2023-02-01 13:59 ` [PATCH v2 13/14] i2c: Add support for Qualcomm I2C driver Sumit Garg
2023-02-01 13:59 ` [PATCH v2 14/14] dts: qcs404-evb: Add I2C controller nodes Sumit Garg
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:58 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Co-developed-by: Mike Worsfold <mworsfold@impinj.com>
Signed-off-by: Mike Worsfold <mworsfold@impinj.com>
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/mach-snapdragon/pinctrl-qcs404.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/mach-snapdragon/pinctrl-qcs404.c b/arch/arm/mach-snapdragon/pinctrl-qcs404.c
index 5a7fbfd441..a6e53c4412 100644
--- a/arch/arm/mach-snapdragon/pinctrl-qcs404.c
+++ b/arch/arm/mach-snapdragon/pinctrl-qcs404.c
@@ -29,6 +29,12 @@ static const struct pinctrl_function msm_pinctrl_functions[] = {
{"rgmii_rx", 1},
{"rgmii_mdio", 1},
{"rgmii_mdc", 1},
+ {"blsp_i2c0", 3},
+ {"blsp_i2c1", 2},
+ {"blsp_i2c_sda_a2", 3},
+ {"blsp_i2c_scl_a2", 3},
+ {"blsp_i2c3", 2},
+ {"blsp_i2c4", 1},
};
static const char *qcs404_get_function_name(struct udevice *dev,
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 12/14] pinctrl: qcs404: Enable I2C pinmux options
2023-02-01 13:58 ` [PATCH v2 12/14] pinctrl: qcs404: Enable I2C pinmux options Sumit Garg
@ 2023-02-10 18:44 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:44 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 277 bytes --]
On Wed, Feb 01, 2023 at 07:28:59PM +0530, Sumit Garg wrote:
> Co-developed-by: Mike Worsfold <mworsfold@impinj.com>
> Signed-off-by: Mike Worsfold <mworsfold@impinj.com>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 13/14] i2c: Add support for Qualcomm I2C driver
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (10 preceding siblings ...)
2023-02-01 13:58 ` [PATCH v2 12/14] pinctrl: qcs404: Enable I2C pinmux options Sumit Garg
@ 2023-02-01 13:59 ` Sumit Garg
2023-02-10 18:44 ` Tom Rini
2023-02-01 13:59 ` [PATCH v2 14/14] dts: qcs404-evb: Add I2C controller nodes Sumit Garg
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:59 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Add support for Qualcomm I2C QUP driver which is inspired from
corresponding driver in Linux: drivers/i2c/busses/i2c-qup.c.
Currently this driver only support FIFO polling mode which is sufficient
to support devices like eeprom, rtc etc.
Co-developed-by: Mike Worsfold <mworsfold@impinj.com>
Signed-off-by: Mike Worsfold <mworsfold@impinj.com>
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
drivers/i2c/Kconfig | 12 +
drivers/i2c/Makefile | 1 +
drivers/i2c/qup_i2c.c | 579 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 592 insertions(+)
create mode 100644 drivers/i2c/qup_i2c.c
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 76e19918aa..427074bff8 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -580,6 +580,18 @@ config SYS_I2C_OCTEON
chips have several I2C ports and all are provided, controlled by
the device tree.
+config SYS_I2C_QUP
+ bool "Qualcomm QUP I2C controller"
+ depends on ARCH_SNAPDRAGON
+ help
+ Support for Qualcomm QUP I2C controller based on Qualcomm Universal
+ Peripherals (QUP) engine. The QUP engine is an advanced high
+ performance slave port that provides a common data path (an output
+ FIFO and an input FIFO) for I2C and SPI interfaces. The I2C/SPI QUP
+ controller is publicly documented in the Snapdragon 410E (APQ8016E)
+ Technical Reference Manual, chapter "6.1 Qualcomm Universal
+ Peripherals Engine (QUP)".
+
config SYS_I2C_S3C24X0
bool "Samsung I2C driver"
depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && DM_I2C
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 920aafb91c..b024547959 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_SYS_I2C_NPCM) += npcm_i2c.o
obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o
obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
+obj-$(CONFIG_SYS_I2C_QUP) += qup_i2c.o
obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
diff --git a/drivers/i2c/qup_i2c.c b/drivers/i2c/qup_i2c.c
new file mode 100644
index 0000000000..5ae3cccd4a
--- /dev/null
+++ b/drivers/i2c/qup_i2c.c
@@ -0,0 +1,579 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2009-2013, 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, Sony Mobile Communications AB.
+ * Copyright (c) 2022-2023, Sumit Garg <sumit.garg@linaro.org>
+ *
+ * Inspired by corresponding driver in Linux: drivers/i2c/busses/i2c-qup.c
+ */
+
+#include <init.h>
+#include <env.h>
+#include <common.h>
+#include <log.h>
+#include <dm/device_compat.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/compat.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <i2c.h>
+#include <watchdog.h>
+#include <fdtdec.h>
+#include <clk.h>
+#include <reset.h>
+#include <asm/arch/gpio.h>
+#include <cpu_func.h>
+#include <asm/system.h>
+#include <asm/gpio.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+
+/* QUP Registers */
+#define QUP_CONFIG 0x000
+#define QUP_STATE 0x004
+#define QUP_IO_MODE 0x008
+#define QUP_SW_RESET 0x00c
+#define QUP_OPERATIONAL 0x018
+#define QUP_ERROR_FLAGS 0x01c /* NOT USED */
+#define QUP_ERROR_FLAGS_EN 0x020 /* NOT USED */
+#define QUP_TEST_CTRL 0x024 /* NOT USED */
+#define QUP_OPERATIONAL_MASK 0x028 /* NOT USED */
+#define QUP_HW_VERSION 0x030
+#define QUP_MX_OUTPUT_CNT 0x100
+#define QUP_OUT_DEBUG 0x108 /* NOT USED */
+#define QUP_OUT_FIFO_CNT 0x10C /* NOT USED */
+#define QUP_OUT_FIFO_BASE 0x110
+#define QUP_MX_WRITE_CNT 0x150
+#define QUP_MX_INPUT_CNT 0x200
+#define QUP_MX_READ_CNT 0x208
+#define QUP_IN_READ_CUR 0x20C /* NOT USED */
+#define QUP_IN_DEBUG 0x210 /* NOT USED */
+#define QUP_IN_FIFO_CNT 0x214 /* NOT USED */
+#define QUP_IN_FIFO_BASE 0x218
+#define QUP_I2C_CLK_CTL 0x400
+#define QUP_I2C_STATUS 0x404 /* NOT USED */
+#define QUP_I2C_MASTER_GEN 0x408
+#define QUP_I2C_MASTER_BUS_CLR 0x40C /* NOT USED */
+
+/* QUP States and reset values */
+#define QUP_RESET_STATE 0
+#define QUP_RUN_STATE 1
+#define QUP_PAUSE_STATE 3
+#define QUP_STATE_MASK 3
+
+#define QUP_STATE_VALID BIT(2)
+#define QUP_I2C_MAST_GEN BIT(4)
+#define QUP_I2C_FLUSH BIT(6)
+
+#define QUP_OPERATIONAL_RESET 0x000ff0
+#define QUP_I2C_STATUS_RESET 0xfffffc
+
+/* QUP OPERATIONAL FLAGS */
+#define QUP_I2C_NACK_FLAG BIT(3)
+#define QUP_OUT_NOT_EMPTY BIT(4)
+#define QUP_IN_NOT_EMPTY BIT(5)
+#define QUP_OUT_FULL BIT(6)
+#define QUP_OUT_SVC_FLAG BIT(8)
+#define QUP_IN_SVC_FLAG BIT(9)
+#define QUP_MX_OUTPUT_DONE BIT(10)
+#define QUP_MX_INPUT_DONE BIT(11)
+#define OUT_BLOCK_WRITE_REQ BIT(12)
+#define IN_BLOCK_READ_REQ BIT(13)
+
+/*
+ * QUP engine acting as I2C controller is referred to as
+ * I2C mini core, following are related macros.
+ */
+#define QUP_NO_OUTPUT BIT(6)
+#define QUP_NO_INPUT BIT(7)
+#define QUP_CLOCK_AUTO_GATE BIT(13)
+#define QUP_I2C_MINI_CORE (2 << 8)
+#define QUP_I2C_N_VAL_V2 7
+
+/* Packing/Unpacking words in FIFOs, and IO modes */
+#define QUP_OUTPUT_BLK_MODE BIT(10)
+#define QUP_OUTPUT_BAM_MODE (BIT(10) | BIT(11))
+#define QUP_INPUT_BLK_MODE BIT(12)
+#define QUP_INPUT_BAM_MODE (BIT(12) | BIT(13))
+#define QUP_BAM_MODE (QUP_OUTPUT_BAM_MODE | QUP_INPUT_BAM_MODE)
+#define QUP_BLK_MODE (QUP_OUTPUT_BLK_MODE | QUP_INPUT_BLK_MODE)
+#define QUP_UNPACK_EN BIT(14)
+#define QUP_PACK_EN BIT(15)
+
+#define QUP_REPACK_EN (QUP_UNPACK_EN | QUP_PACK_EN)
+#define QUP_V2_TAGS_EN 1
+
+#define QUP_OUTPUT_BLOCK_SIZE(x) (((x) >> 0) & 0x03)
+#define QUP_OUTPUT_FIFO_SIZE(x) (((x) >> 2) & 0x07)
+#define QUP_INPUT_BLOCK_SIZE(x) (((x) >> 5) & 0x03)
+#define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07)
+
+/* QUP v2 tags */
+#define QUP_TAG_V2_START 0x81
+#define QUP_TAG_V2_DATAWR 0x82
+#define QUP_TAG_V2_DATAWR_STOP 0x83
+#define QUP_TAG_V2_DATARD 0x85
+#define QUP_TAG_V2_DATARD_NACK 0x86
+#define QUP_TAG_V2_DATARD_STOP 0x87
+
+#define QUP_I2C_MX_CONFIG_DURING_RUN BIT(31)
+
+/* Minimum transfer timeout for i2c transfers in micro seconds */
+#define TOUT_CNT (2 * 1000 * 1000)
+
+/* Default values. Use these if FW query fails */
+#define DEFAULT_CLK_FREQ I2C_SPEED_STANDARD_RATE
+#define DEFAULT_SRC_CLK 19200000
+
+/*
+ * Max tags length (start, stop and maximum 2 bytes address) for each QUP
+ * data transfer
+ */
+#define QUP_MAX_TAGS_LEN 4
+/* Max data length for each DATARD tags */
+#define RECV_MAX_DATA_LEN 254
+/* TAG length for DATA READ in RX FIFO */
+#define READ_RX_TAGS_LEN 2
+
+struct qup_i2c_priv {
+ phys_addr_t base;
+ struct clk core;
+ struct clk iface;
+ u32 in_fifo_sz;
+ u32 out_fifo_sz;
+ u32 clk_ctl;
+ u32 config_run;
+};
+
+static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
+{
+ return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
+}
+
+static int qup_i2c_poll_state_mask(struct qup_i2c_priv *qup,
+ u32 req_state, u32 req_mask)
+{
+ int retries = 1;
+ u32 state;
+
+ /*
+ * State transition takes 3 AHB clocks cycles + 3 I2C master clock
+ * cycles. So retry once after a 1uS delay.
+ */
+ do {
+ state = readl(qup->base + QUP_STATE);
+
+ if (state & QUP_STATE_VALID &&
+ (state & req_mask) == req_state)
+ return 0;
+
+ udelay(1);
+ } while (retries--);
+
+ return -ETIMEDOUT;
+}
+
+static int qup_i2c_poll_state(struct qup_i2c_priv *qup, u32 req_state)
+{
+ return qup_i2c_poll_state_mask(qup, req_state, QUP_STATE_MASK);
+}
+
+static int qup_i2c_poll_state_valid(struct qup_i2c_priv *qup)
+{
+ return qup_i2c_poll_state_mask(qup, 0, 0);
+}
+
+static int qup_i2c_poll_state_i2c_master(struct qup_i2c_priv *qup)
+{
+ return qup_i2c_poll_state_mask(qup, QUP_I2C_MAST_GEN, QUP_I2C_MAST_GEN);
+}
+
+static int qup_i2c_change_state(struct qup_i2c_priv *qup, u32 state)
+{
+ if (qup_i2c_poll_state_valid(qup) != 0)
+ return -EIO;
+
+ writel(state, qup->base + QUP_STATE);
+
+ if (qup_i2c_poll_state(qup, state) != 0)
+ return -EIO;
+ return 0;
+}
+
+/*
+ * Function to check wheather Input or Output FIFO
+ * has data to be serviced
+ */
+static int qup_i2c_check_fifo_status(struct qup_i2c_priv *qup, u32 reg_addr,
+ u32 flags)
+{
+ unsigned long count = TOUT_CNT;
+ u32 val, status_flag;
+ int ret = 0;
+
+ do {
+ val = readl(qup->base + reg_addr);
+ status_flag = val & flags;
+
+ if (!count) {
+ printf("%s, timeout\n", __func__);
+ ret = -ETIMEDOUT;
+ break;
+ }
+
+ count--;
+ udelay(1);
+ } while (!status_flag);
+
+ return ret;
+}
+
+/*
+ * Function to configure Input and Output enable/disable
+ */
+static void qup_i2c_enable_io_config(struct qup_i2c_priv *qup, u32 write_cnt,
+ u32 read_cnt)
+{
+ u32 qup_config = QUP_I2C_MINI_CORE | QUP_I2C_N_VAL_V2;
+
+ writel(qup->config_run | write_cnt, qup->base + QUP_MX_WRITE_CNT);
+
+ if (read_cnt)
+ writel(qup->config_run | read_cnt, qup->base + QUP_MX_READ_CNT);
+ else
+ qup_config |= QUP_NO_INPUT;
+
+ writel(qup_config, qup->base + QUP_CONFIG);
+}
+
+static unsigned int qup_i2c_read_word(struct qup_i2c_priv *qup)
+{
+ return readl(qup->base + QUP_IN_FIFO_BASE);
+}
+
+static void qup_i2c_write_word(struct qup_i2c_priv *qup, u32 word)
+{
+ writel(word, qup->base + QUP_OUT_FIFO_BASE);
+}
+
+static int qup_i2c_blsp_read(struct qup_i2c_priv *qup, unsigned int addr,
+ bool last, u8 *buffer, unsigned int bytes)
+{
+ unsigned int i, j, word;
+ int ret = 0;
+
+ /* FIFO mode size limitation, for larger size implement block mode */
+ if (bytes > (qup->in_fifo_sz - READ_RX_TAGS_LEN))
+ return -EINVAL;
+
+ qup_i2c_enable_io_config(qup, QUP_MAX_TAGS_LEN,
+ bytes + READ_RX_TAGS_LEN);
+
+ if (last)
+ qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
+ QUP_TAG_V2_DATARD_STOP << 16 |
+ bytes << 24);
+ else
+ qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
+ QUP_TAG_V2_DATARD << 16 | bytes << 24);
+
+ ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+ if (ret)
+ return ret;
+
+ ret = qup_i2c_check_fifo_status(qup, QUP_OPERATIONAL, QUP_OUT_SVC_FLAG);
+ if (ret)
+ return ret;
+ writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL);
+
+ ret = qup_i2c_check_fifo_status(qup, QUP_OPERATIONAL, QUP_IN_SVC_FLAG);
+ if (ret)
+ return ret;
+ writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL);
+
+ word = qup_i2c_read_word(qup);
+ *(buffer++) = (word >> (8 * READ_RX_TAGS_LEN)) & 0xff;
+ if (bytes > 1)
+ *(buffer++) = (word >> (8 * (READ_RX_TAGS_LEN + 1))) & 0xff;
+
+ for (i = 2; i < bytes; i += 4) {
+ word = qup_i2c_read_word(qup);
+
+ for (j = 0; j < 4; j++) {
+ if ((i + j) == bytes)
+ break;
+ *buffer = (word >> (j * 8)) & 0xff;
+ buffer++;
+ }
+ }
+
+ ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
+ return ret;
+}
+
+static int qup_i2c_blsp_write(struct qup_i2c_priv *qup, unsigned int addr,
+ bool first, bool last, const u8 *buffer,
+ unsigned int bytes)
+{
+ unsigned int i;
+ u32 word = 0;
+ int ret = 0;
+
+ /* FIFO mode size limitation, for larger size implement block mode */
+ if (bytes > (qup->out_fifo_sz - QUP_MAX_TAGS_LEN))
+ return -EINVAL;
+
+ qup_i2c_enable_io_config(qup, bytes + QUP_MAX_TAGS_LEN, 0);
+
+ if (first) {
+ ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+ if (ret)
+ return ret;
+
+ writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
+
+ ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
+ if (ret)
+ return ret;
+ }
+
+ if (last)
+ qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
+ QUP_TAG_V2_DATAWR_STOP << 16 |
+ bytes << 24);
+ else
+ qup_i2c_write_word(qup, QUP_TAG_V2_START | addr << 8 |
+ QUP_TAG_V2_DATAWR << 16 | bytes << 24);
+
+ for (i = 0; i < bytes; i++) {
+ /* Write the byte of data */
+ word |= *buffer << ((i % 4) * 8);
+ if ((i % 4) == 3) {
+ qup_i2c_write_word(qup, word);
+ word = 0;
+ }
+ buffer++;
+ }
+
+ if ((i % 4) != 0)
+ qup_i2c_write_word(qup, word);
+
+ ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+ if (ret)
+ return ret;
+
+ ret = qup_i2c_check_fifo_status(qup, QUP_OPERATIONAL, QUP_OUT_SVC_FLAG);
+ if (ret)
+ return ret;
+ writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL);
+
+ ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
+ return ret;
+}
+
+static void qup_i2c_conf_mode_v2(struct qup_i2c_priv *qup)
+{
+ u32 io_mode = QUP_REPACK_EN;
+
+ writel(0, qup->base + QUP_MX_OUTPUT_CNT);
+ writel(0, qup->base + QUP_MX_INPUT_CNT);
+
+ writel(io_mode, qup->base + QUP_IO_MODE);
+}
+
+static int qup_i2c_xfer_v2(struct udevice *bus, struct i2c_msg msgs[], int num)
+{
+ struct qup_i2c_priv *qup = dev_get_priv(bus);
+ int ret, idx = 0;
+ u32 i2c_addr;
+
+ writel(1, qup->base + QUP_SW_RESET);
+ ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
+ if (ret)
+ goto out;
+
+ /* Configure QUP as I2C mini core */
+ writel(QUP_I2C_MINI_CORE | QUP_I2C_N_VAL_V2 | QUP_NO_INPUT,
+ qup->base + QUP_CONFIG);
+ writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
+
+ if (qup_i2c_poll_state_i2c_master(qup)) {
+ ret = -EIO;
+ goto out;
+ }
+
+ qup_i2c_conf_mode_v2(qup);
+
+ for (idx = 0; idx < num; idx++) {
+ struct i2c_msg *m = &msgs[idx];
+
+ qup->config_run = !idx ? 0 : QUP_I2C_MX_CONFIG_DURING_RUN;
+ i2c_addr = i2c_8bit_addr_from_msg(m);
+
+ if (m->flags & I2C_M_RD)
+ ret = qup_i2c_blsp_read(qup, i2c_addr, idx == (num - 1),
+ m->buf, m->len);
+ else
+ ret = qup_i2c_blsp_write(qup, i2c_addr, idx == 0,
+ idx == (num - 1), m->buf,
+ m->len);
+ if (ret)
+ break;
+ }
+out:
+ qup_i2c_change_state(qup, QUP_RESET_STATE);
+ return ret;
+}
+
+static int qup_i2c_enable_clocks(struct udevice *dev, struct qup_i2c_priv *qup)
+{
+ int ret;
+
+ ret = clk_enable(&qup->core);
+ if (ret) {
+ dev_err(dev, "clk_enable failed %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(&qup->iface);
+ if (ret) {
+ dev_err(dev, "clk_enable failed %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int qup_i2c_probe(struct udevice *dev)
+{
+ static const int blk_sizes[] = {4, 16, 32};
+ struct qup_i2c_priv *qup = dev_get_priv(dev);
+ u32 io_mode, hw_ver, size, size_idx;
+ int ret;
+
+ qup->base = (phys_addr_t)dev_read_addr_ptr(dev);
+ if (!qup->base)
+ return -EINVAL;
+
+ ret = clk_get_by_name(dev, "core", &qup->core);
+ if (ret) {
+ pr_err("clk_get_by_name(core) failed: %d\n", ret);
+ return ret;
+ }
+ ret = clk_get_by_name(dev, "iface", &qup->iface);
+ if (ret) {
+ pr_err("clk_get_by_name(iface) failed: %d\n", ret);
+ return ret;
+ }
+ qup_i2c_enable_clocks(dev, qup);
+
+ writel(1, qup->base + QUP_SW_RESET);
+ ret = qup_i2c_poll_state_valid(qup);
+ if (ret)
+ return ret;
+
+ hw_ver = readl(qup->base + QUP_HW_VERSION);
+ dev_dbg(dev, "Revision %x\n", hw_ver);
+
+ io_mode = readl(qup->base + QUP_IO_MODE);
+
+ /*
+ * The block/fifo size w.r.t. 'actual data' is 1/2 due to 'tag'
+ * associated with each byte written/received
+ */
+ size_idx = QUP_OUTPUT_BLOCK_SIZE(io_mode);
+ if (size_idx >= ARRAY_SIZE(blk_sizes)) {
+ ret = -EIO;
+ return ret;
+ }
+ size = QUP_OUTPUT_FIFO_SIZE(io_mode);
+ qup->out_fifo_sz = blk_sizes[size_idx] * (2 << size);
+
+ size_idx = QUP_INPUT_BLOCK_SIZE(io_mode);
+ if (size_idx >= ARRAY_SIZE(blk_sizes)) {
+ ret = -EIO;
+ return ret;
+ }
+ size = QUP_INPUT_FIFO_SIZE(io_mode);
+ qup->in_fifo_sz = blk_sizes[size_idx] * (2 << size);
+
+ dev_dbg(dev, "IN:fifo:%d, OUT:fifo:%d\n", qup->in_fifo_sz,
+ qup->out_fifo_sz);
+
+ return 0;
+}
+
+static int qup_i2c_set_bus_speed(struct udevice *dev, unsigned int clk_freq)
+{
+ struct qup_i2c_priv *qup = dev_get_priv(dev);
+ unsigned int src_clk_freq;
+ int fs_div, hs_div;
+
+ /* We support frequencies up to FAST Mode Plus (1MHz) */
+ if (!clk_freq || clk_freq > I2C_SPEED_FAST_PLUS_RATE) {
+ dev_err(dev, "clock frequency not supported %d\n", clk_freq);
+ return -EINVAL;
+ }
+
+ src_clk_freq = clk_get_rate(&qup->iface);
+ if ((int)src_clk_freq < 0) {
+ src_clk_freq = DEFAULT_SRC_CLK;
+ dev_dbg(dev, "using default core freq %d\n", src_clk_freq);
+ }
+
+ dev_dbg(dev, "src_clk_freq %u\n", src_clk_freq);
+ dev_dbg(dev, "clk_freq %u\n", clk_freq);
+
+ hs_div = 3;
+ if (clk_freq <= I2C_SPEED_STANDARD_RATE) {
+ fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
+ qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
+ } else {
+ /* 33%/66% duty cycle */
+ fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3;
+ qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
+ }
+
+ dev_dbg(dev, "clk_ctl %u\n", qup->clk_ctl);
+
+ return 0;
+}
+
+/* Probe to see if a chip is present. */
+static int qup_i2c_probe_chip(struct udevice *dev, uint chip_addr,
+ uint chip_flags)
+{
+ struct qup_i2c_priv *qup = dev_get_priv(dev);
+ u32 hw_ver = readl(qup->base + QUP_HW_VERSION);
+
+ return hw_ver ? 0 : -1;
+}
+
+static const struct dm_i2c_ops qup_i2c_ops = {
+ .xfer = qup_i2c_xfer_v2,
+ .probe_chip = qup_i2c_probe_chip,
+ .set_bus_speed = qup_i2c_set_bus_speed,
+};
+
+/*
+ * Currently this driver only supports v2.x of QUP I2C controller, hence
+ * functions above are named with a _v2 suffix. So when we have the
+ * v1.1.1 support added as per the Linux counterpart then it should be easy
+ * to add corresponding functions named with a _v1 suffix.
+ */
+static const struct udevice_id qup_i2c_ids[] = {
+ { .compatible = "qcom,i2c-qup-v2.1.1" },
+ { .compatible = "qcom,i2c-qup-v2.2.1" },
+ {}
+};
+
+U_BOOT_DRIVER(i2c_qup) = {
+ .name = "i2c_qup",
+ .id = UCLASS_I2C,
+ .of_match = qup_i2c_ids,
+ .probe = qup_i2c_probe,
+ .priv_auto = sizeof(struct qup_i2c_priv),
+ .ops = &qup_i2c_ops,
+};
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 13/14] i2c: Add support for Qualcomm I2C driver
2023-02-01 13:59 ` [PATCH v2 13/14] i2c: Add support for Qualcomm I2C driver Sumit Garg
@ 2023-02-10 18:44 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:44 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 535 bytes --]
On Wed, Feb 01, 2023 at 07:29:00PM +0530, Sumit Garg wrote:
> Add support for Qualcomm I2C QUP driver which is inspired from
> corresponding driver in Linux: drivers/i2c/busses/i2c-qup.c.
>
> Currently this driver only support FIFO polling mode which is sufficient
> to support devices like eeprom, rtc etc.
>
> Co-developed-by: Mike Worsfold <mworsfold@impinj.com>
> Signed-off-by: Mike Worsfold <mworsfold@impinj.com>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 14/14] dts: qcs404-evb: Add I2C controller nodes
2023-02-01 13:58 [PATCH v2 00/14] QCS404: Add ethernet and I2C drivers Sumit Garg
` (11 preceding siblings ...)
2023-02-01 13:59 ` [PATCH v2 13/14] i2c: Add support for Qualcomm I2C driver Sumit Garg
@ 2023-02-01 13:59 ` Sumit Garg
2023-02-10 18:44 ` Tom Rini
12 siblings, 1 reply; 30+ messages in thread
From: Sumit Garg @ 2023-02-01 13:59 UTC (permalink / raw)
To: u-boot
Cc: rfried.dev, hs, joe.hershberger, stephan, mworsfold, lgillham,
jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson,
Sumit Garg
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
arch/arm/dts/qcs404-evb.dts | 97 +++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/arch/arm/dts/qcs404-evb.dts b/arch/arm/dts/qcs404-evb.dts
index 2de0e7537b..8d7893c116 100644
--- a/arch/arm/dts/qcs404-evb.dts
+++ b/arch/arm/dts/qcs404-evb.dts
@@ -23,6 +23,11 @@
aliases {
serial0 = &debug_uart;
+ i2c0 = &blsp1_i2c0;
+ i2c1 = &blsp1_i2c1;
+ i2c2 = &blsp1_i2c2;
+ i2c3 = &blsp1_i2c3;
+ i2c4 = &blsp1_i2c4;
};
memory {
@@ -49,6 +54,38 @@
function = "blsp_uart2";
};
+ blsp1_i2c0_default: blsp1-i2c0-default {
+ pins = "GPIO_32", "GPIO_33";
+ function = "blsp_i2c0";
+ };
+
+ blsp1_i2c1_default: blsp1-i2c1-default {
+ pins = "GPIO_24", "GPIO_25";
+ function = "blsp_i2c1";
+ };
+
+ blsp1_i2c2_default: blsp1-i2c2-default {
+ sda {
+ pins = "GPIO_19";
+ function = "blsp_i2c_sda_a2";
+ };
+
+ scl {
+ pins = "GPIO_20";
+ function = "blsp_i2c_scl_a2";
+ };
+ };
+
+ blsp1_i2c3_default: blsp1-i2c3-default {
+ pins = "GPIO_84", "GPIO_85";
+ function = "blsp_i2c3";
+ };
+
+ blsp1_i2c4_default: blsp1-i2c4-default {
+ pins = "GPIO_117", "GPIO_118";
+ function = "blsp_i2c4";
+ };
+
ethernet_defaults: ethernet-defaults {
int {
pins = "GPIO_61";
@@ -105,6 +142,66 @@
};
};
+ blsp1_i2c0: i2c@78b5000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b5000 0x600>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP0_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp1_i2c0_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ blsp1_i2c1: i2c@78b6000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b6000 0x600>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp1_i2c1_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ blsp1_i2c2: i2c@78b7000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b7000 0x600>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp1_i2c2_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ blsp1_i2c3: i2c@78b8000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b8000 0x600>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp1_i2c3_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ blsp1_i2c4: i2c@78b9000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b9000 0x600>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp1_i2c4_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
gcc: clock-controller@1800000 {
compatible = "qcom,gcc-qcs404";
reg = <0x1800000 0x80000>;
--
2.34.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v2 14/14] dts: qcs404-evb: Add I2C controller nodes
2023-02-01 13:59 ` [PATCH v2 14/14] dts: qcs404-evb: Add I2C controller nodes Sumit Garg
@ 2023-02-10 18:44 ` Tom Rini
0 siblings, 0 replies; 30+ messages in thread
From: Tom Rini @ 2023-02-10 18:44 UTC (permalink / raw)
To: Sumit Garg
Cc: u-boot, rfried.dev, hs, joe.hershberger, stephan, mworsfold,
lgillham, jbrennan, nicolas.dechesne, vinod.koul, daniel.thompson
[-- Attachment #1: Type: text/plain, Size: 165 bytes --]
On Wed, Feb 01, 2023 at 07:29:01PM +0530, Sumit Garg wrote:
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread