[PATCH 7/9] phy: renesas: ethernet serdes: add support for R-Car SoC X5H (r8a78000)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Adding support for a new SOC device.

Signed-off-by: Michael Dege <michael.dege@xxxxxxxxxxx>
---
 drivers/phy/renesas/renesas-ether-serdes.c | 55 +++++++++++++++++-----
 1 file changed, 44 insertions(+), 11 deletions(-)

diff --git a/drivers/phy/renesas/renesas-ether-serdes.c b/drivers/phy/renesas/renesas-ether-serdes.c
index 683409d5e0f9..4c53c81903ef 100644
--- a/drivers/phy/renesas/renesas-ether-serdes.c
+++ b/drivers/phy/renesas/renesas-ether-serdes.c
@@ -14,11 +14,13 @@
 #include <linux/platform_device.h>
 #include <linux/reset.h>

+#define RENESAS_ETH_SERDES_MAX_NUM             R8A78000_ETH_SERDES_NUM
 #define R8A779F0_ETH_SERDES_NUM                        3
+#define R8A78000_ETH_SERDES_NUM                        8
 #define RENESAS_ETH_SERDES_OFFSET              0x0400
 #define RENESAS_ETH_SERDES_BANK_SELECT         0x03fc
 #define RENESAS_ETH_SERDES_TIMEOUT_US          100000
-#define RENESAS_ETH_SERDES_LOCAL_OFFSET        0x2600
+#define RENESAS_ETH_SERDES_LOCAL_OFFSET                0x2600
 #define RENESAS_ETH_SERDES_NUM_RETRY_LINKUP    3

 struct renesas_eth_serdes_drv_data;
@@ -35,10 +37,21 @@ struct renesas_eth_serdes_drv_data {
        void __iomem *addr;
        struct platform_device *pdev;
        struct reset_control *reset;
-       struct renesas_eth_serdes_channel channel[R8A779F0_ETH_SERDES_NUM];
+       struct renesas_eth_serdes_channel channel[RENESAS_ETH_SERDES_MAX_NUM];
+       const struct renesas_serdes_hw_info *info;
        bool initialized;
 };

+enum DEVICE_CODE {
+       r8a779f0,
+       r8a78000,
+};
+
+struct renesas_serdes_hw_info {
+       int renesas_eth_serdes_num;
+       int device_type;
+};
+
 /*
  * The datasheet describes initialization procedure without any information
  * about registers' name/bits. So, this is all black magic to initialize
@@ -82,7 +95,7 @@ renesas_eth_serdes_common_init_ram(struct renesas_eth_serdes_drv_data *dd)
        struct renesas_eth_serdes_channel *channel;
        int i, ret;

-       for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
+       for (i = 0; i < dd->info->renesas_eth_serdes_num; i++) {
                channel = &dd->channel[i];
                ret = renesas_eth_serdes_reg_wait(channel, 0x026c, 0x180, BIT(0), 0x01);
                if (ret)
@@ -265,32 +278,34 @@ static int renesas_eth_serdes_hw_init(struct renesas_eth_serdes_channel *channel

        reset_control_reset(dd->reset);

+       mdelay(1);
+
        /* There is a slight difference in SerDes hardware behavior between
         * each version after resetting. This step is to ensure the stable
         * condition of initialization, especially for R-Car S4 v1.1.
         */
-       mdelay(1);
-       iowrite32(0, dd->addr + RENESAS_ETH_SERDES_LOCAL_OFFSET);
+       if (dd->info->renesas_eth_serdes_num == r8a779f0)
+               iowrite32(0, dd->addr + RENESAS_ETH_SERDES_LOCAL_OFFSET);

        ret = renesas_eth_serdes_common_init_ram(dd);
        if (ret)
                return ret;

-       for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
+       for (i = 0; i < dd->info->renesas_eth_serdes_num; i++) {
                ret = renesas_eth_serdes_reg_wait(&dd->channel[i], 0x0000,
                                                   0x300, BIT(15), 0);
                if (ret)
                        return ret;
        }

-       for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++)
+       for (i = 0; i < dd->info->renesas_eth_serdes_num; i++)
                renesas_eth_serdes_write32(dd->channel[i].addr, 0x03d4, 0x380, 0x0443);

        ret = renesas_eth_serdes_common_setting(channel);
        if (ret)
                return ret;

-       for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++)
+       for (i = 0; i < dd->info->renesas_eth_serdes_num; i++)
                renesas_eth_serdes_write32(dd->channel[i].addr, 0x03d0, 0x380, 0x0001);


@@ -414,14 +429,25 @@ static struct phy *renesas_eth_serdes_xlate(struct device *dev,
 {
        struct renesas_eth_serdes_drv_data *dd = dev_get_drvdata(dev);

-       if (args->args[0] >= R8A779F0_ETH_SERDES_NUM)
+       if (args->args[0] >= dd->info->renesas_eth_serdes_num)
                return ERR_PTR(-ENODEV);

        return dd->channel[args->args[0]].phy;
 }

+static const struct renesas_serdes_hw_info r8a779f0_hw_info = {
+               .renesas_eth_serdes_num = R8A779F0_ETH_SERDES_NUM,
+               .device_type = r8a779f0,
+};
+
+static const struct renesas_serdes_hw_info r8a78000_hw_info = {
+               .renesas_eth_serdes_num = R8A78000_ETH_SERDES_NUM,
+               .device_type = r8a78000,
+};
+
 static const struct of_device_id renesas_eth_serdes_of_table[] = {
-       { .compatible = "renesas,r8a779f0-ether-serdes", },
+       { .compatible = "renesas,r8a779f0-ether-serdes", .data = &r8a779f0_hw_info },
+       { .compatible = "renesas,r8a78000-ether-serdes", .data = &r8a78000_hw_info },
        { }
 };
 MODULE_DEVICE_TABLE(of, renesas_eth_serdes_of_table);
@@ -430,12 +456,19 @@ static int renesas_eth_serdes_probe(struct platform_device *pdev)
 {
        struct renesas_eth_serdes_drv_data *dd;
        struct phy_provider *provider;
+       const struct renesas_serdes_hw_info *info;
        int i;

        dd = devm_kzalloc(&pdev->dev, sizeof(*dd), GFP_KERNEL);
        if (!dd)
                return -ENOMEM;

+       info = of_device_get_match_data(&pdev->dev);
+       if (info > 0)
+               dd->info = info;
+       else
+               return PTR_ERR(info);
+
        platform_set_drvdata(pdev, dd);
        dd->pdev = pdev;
        dd->addr = devm_platform_ioremap_resource(pdev, 0);
@@ -446,7 +479,7 @@ static int renesas_eth_serdes_probe(struct platform_device *pdev)
        if (IS_ERR(dd->reset))
                return PTR_ERR(dd->reset);

-       for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
+       for (i = 0; i < dd->info->renesas_eth_serdes_num; i++) {
                struct renesas_eth_serdes_channel *channel = &dd->channel[i];

                channel->phy = devm_phy_create(&pdev->dev, NULL,
--
2.34.1

________________________________

Renesas Electronics Europe GmbH
Registered Office: Arcadiastrasse 10
DE-40472 Duesseldorf
Commercial Registry: Duesseldorf, HRB 3708
Managing Director: Carsten Jauch
VAT-No.: DE 14978647
Tax-ID-No: 105/5839/1793

Legal Disclaimer: This e-mail communication (and any attachment/s) is confidential and contains proprietary information, some or all of which may be legally privileged. It is intended solely for the use of the individual or entity to which it is addressed. Access to this email by anyone else is unauthorized. If you are not the intended recipient, any disclosure, copying, distribution or any action taken or omitted to be taken in reliance on it, is prohibited and may be unlawful.





[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux