Merge tag '6.4-rc-ksmbd-server-fixes-part2' of git://git.samba.org/ksmbd
[linux-block.git] / drivers / clk / clk-renesas-pcie.c
index ff3a52d48479092257a98ddaaf3b2af701a6bd99..10d31c222a1cb428c3b4e3077adba7193e759c9f 100644 (file)
@@ -6,6 +6,7 @@
  *   - 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ
  * Currently supported:
  *   - 9FGV0241
+ *   - 9FGV0441
  *
  * Copyright (C) 2022 Marek Vasut <marex@denx.de>
  */
@@ -18,7 +19,6 @@
 #include <linux/regmap.h>
 
 #define RS9_REG_OE                             0x0
-#define RS9_REG_OE_DIF_OE(n)                   BIT((n) + 1)
 #define RS9_REG_SS                             0x1
 #define RS9_REG_SS_AMP_0V6                     0x0
 #define RS9_REG_SS_AMP_0V7                     0x1
@@ -31,9 +31,6 @@
 #define RS9_REG_SS_SSC_MASK                    (3 << 3)
 #define RS9_REG_SS_SSC_LOCK                    BIT(5)
 #define RS9_REG_SR                             0x2
-#define RS9_REG_SR_2V0_DIF(n)                  0
-#define RS9_REG_SR_3V0_DIF(n)                  BIT((n) + 1)
-#define RS9_REG_SR_DIF_MASK(n)         BIT((n) + 1)
 #define RS9_REG_REF                            0x3
 #define RS9_REG_REF_OE                         BIT(4)
 #define RS9_REG_REF_OD                         BIT(5)
 #define RS9_REG_DID                            0x6
 #define RS9_REG_BCP                            0x7
 
+#define RS9_REG_VID_IDT                                0x01
+
+#define RS9_REG_DID_TYPE_FGV                   (0x0 << RS9_REG_DID_TYPE_SHIFT)
+#define RS9_REG_DID_TYPE_DBV                   (0x1 << RS9_REG_DID_TYPE_SHIFT)
+#define RS9_REG_DID_TYPE_DMV                   (0x2 << RS9_REG_DID_TYPE_SHIFT)
+#define RS9_REG_DID_TYPE_SHIFT                 0x6
+
 /* Supported Renesas 9-series models. */
 enum rs9_model {
        RENESAS_9FGV0241,
+       RENESAS_9FGV0441,
 };
 
 /* Structure to describe features of a particular 9-series model */
 struct rs9_chip_info {
        const enum rs9_model    model;
        unsigned int            num_clks;
+       u8                      did;
 };
 
 struct rs9_driver_data {
        struct i2c_client       *client;
        struct regmap           *regmap;
        const struct rs9_chip_info *chip_info;
-       struct clk_hw           *clk_dif[2];
+       struct clk_hw           *clk_dif[4];
        u8                      pll_amplitude;
        u8                      pll_ssc;
        u8                      clk_dif_sr;
@@ -152,17 +158,29 @@ static const struct regmap_config rs9_regmap_config = {
        .reg_read = rs9_regmap_i2c_read,
 };
 
+static u8 rs9_calc_dif(const struct rs9_driver_data *rs9, int idx)
+{
+       enum rs9_model model = rs9->chip_info->model;
+
+       if (model == RENESAS_9FGV0241)
+               return BIT(idx) + 1;
+       else if (model == RENESAS_9FGV0441)
+               return BIT(idx);
+
+       return 0;
+}
+
 static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
 {
        struct i2c_client *client = rs9->client;
+       u8 dif = rs9_calc_dif(rs9, idx);
        unsigned char name[5] = "DIF0";
        struct device_node *np;
        int ret;
        u32 sr;
 
        /* Set defaults */
-       rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
-       rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx);
+       rs9->clk_dif_sr |= dif;
 
        snprintf(name, 5, "DIF%d", idx);
        np = of_get_child_by_name(client->dev.of_node, name);
@@ -174,11 +192,9 @@ static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
        of_node_put(np);
        if (!ret) {
                if (sr == 2000000) {            /* 2V/ns */
-                       rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
-                       rs9->clk_dif_sr |= RS9_REG_SR_2V0_DIF(idx);
+                       rs9->clk_dif_sr &= ~dif;
                } else if (sr == 3000000) {     /* 3V/ns (default) */
-                       rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx);
-                       rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx);
+                       rs9->clk_dif_sr |= dif;
                } else
                        ret = dev_err_probe(&client->dev, -EINVAL,
                                            "Invalid renesas,slew-rate value\n");
@@ -249,11 +265,13 @@ static void rs9_update_config(struct rs9_driver_data *rs9)
        }
 
        for (i = 0; i < rs9->chip_info->num_clks; i++) {
-               if (rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i))
+               u8 dif = rs9_calc_dif(rs9, i);
+
+               if (rs9->clk_dif_sr & dif)
                        continue;
 
-               regmap_update_bits(rs9->regmap, RS9_REG_SR, RS9_REG_SR_3V0_DIF(i),
-                                  rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i));
+               regmap_update_bits(rs9->regmap, RS9_REG_SR, dif,
+                                  rs9->clk_dif_sr & dif);
        }
 }
 
@@ -270,6 +288,7 @@ static int rs9_probe(struct i2c_client *client)
 {
        unsigned char name[5] = "DIF0";
        struct rs9_driver_data *rs9;
+       unsigned int vid, did;
        struct clk_hw *hw;
        int i, ret;
 
@@ -306,6 +325,20 @@ static int rs9_probe(struct i2c_client *client)
        if (ret < 0)
                return ret;
 
+       ret = regmap_read(rs9->regmap, RS9_REG_VID, &vid);
+       if (ret < 0)
+               return ret;
+
+       ret = regmap_read(rs9->regmap, RS9_REG_DID, &did);
+       if (ret < 0)
+               return ret;
+
+       if (vid != RS9_REG_VID_IDT || did != rs9->chip_info->did)
+               return dev_err_probe(&client->dev, -ENODEV,
+                                    "Incorrect VID/DID: %#02x, %#02x. Expected %#02x, %#02x\n",
+                                    vid, did, RS9_REG_VID_IDT,
+                                    rs9->chip_info->did);
+
        /* Register clock */
        for (i = 0; i < rs9->chip_info->num_clks; i++) {
                snprintf(name, 5, "DIF%d", i);
@@ -349,16 +382,25 @@ static int __maybe_unused rs9_resume(struct device *dev)
 static const struct rs9_chip_info renesas_9fgv0241_info = {
        .model          = RENESAS_9FGV0241,
        .num_clks       = 2,
+       .did            = RS9_REG_DID_TYPE_FGV | 0x02,
+};
+
+static const struct rs9_chip_info renesas_9fgv0441_info = {
+       .model          = RENESAS_9FGV0441,
+       .num_clks       = 4,
+       .did            = RS9_REG_DID_TYPE_FGV | 0x04,
 };
 
 static const struct i2c_device_id rs9_id[] = {
        { "9fgv0241", .driver_data = RENESAS_9FGV0241 },
+       { "9fgv0441", .driver_data = RENESAS_9FGV0441 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, rs9_id);
 
 static const struct of_device_id clk_rs9_of_match[] = {
        { .compatible = "renesas,9fgv0241", .data = &renesas_9fgv0241_info },
+       { .compatible = "renesas,9fgv0441", .data = &renesas_9fgv0441_info },
        { }
 };
 MODULE_DEVICE_TABLE(of, clk_rs9_of_match);