]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
pinctrl: spacemit: k3: adjust drive strength and schmitter trigger
authorYixun Lan <dlan@gentoo.org>
Fri, 2 Jan 2026 07:00:25 +0000 (15:00 +0800)
committerLinus Walleij <linusw@kernel.org>
Wed, 7 Jan 2026 14:08:13 +0000 (15:08 +0100)
K3 SoC expand drive strength to 4 bits which support even larger
settings table comparing to old SoC generation. Also schmitter trigger
setting is changed to 1 bit.

Signed-off-by: Yixun Lan <dlan@gentoo.org>
Signed-off-by: Linus Walleij <linusw@kernel.org>
drivers/pinctrl/spacemit/pinctrl-k1.c

index 441817f539e3595dc4667f97c7fe1f03467218f9..07267c5f0f4453bcdf5eb2d267eb3148a18bd038 100644 (file)
 #include "pinctrl-k1.h"
 
 /*
- * +---------+----------+-----------+--------+--------+----------+--------+
- * |   pull  |   drive  | schmitter |  slew  |  edge  |  strong  |   mux  |
- * | up/down | strength |  trigger  |  rate  | detect |   pull   |  mode  |
- * +---------+----------+-----------+--------+--------+----------+--------+
- *   3 bits     3 bits     2 bits     1 bit    3 bits     1 bit    3 bits
+ *     |   pull  |   drive  | schmitter | slew  |  edge  | strong |   mux  |
+ * SoC | up/down | strength |  trigger  | rate  | detect |  pull  |  mode  |
+ *-----+---------+----------+-----------+-------+--------+--------+--------+
+ * K1  | 3 bits  |  3 bits  |   2 bits  | 1 bit | 3 bits |  1 bit | 3 bits |
+ *-----+---------+----------+-----------+-------+--------+--------+--------+
+ * K3  | 3 bits  |  4 bits  |   1 bits  | 1 bit | 3 bits |  1 bit | 3 bits |
  */
 
 #define PAD_MUX                        GENMASK(2, 0)
 #define PAD_EDGE_CLEAR         BIT(6)
 #define PAD_SLEW_RATE          GENMASK(12, 11)
 #define PAD_SLEW_RATE_EN       BIT(7)
-#define PAD_SCHMITT            GENMASK(9, 8)
-#define PAD_DRIVE              GENMASK(12, 10)
+#define PAD_SCHMITT_K1         GENMASK(9, 8)
+#define PAD_DRIVE_K1           GENMASK(12, 10)
+#define PAD_SCHMITT_K3         BIT(8)
+#define PAD_DRIVE_K3           GENMASK(12, 9)
 #define PAD_PULLDOWN           BIT(13)
 #define PAD_PULLUP             BIT(14)
 #define PAD_PULL_EN            BIT(15)
 
+struct spacemit_pin_drv_strength {
+       u8              val;
+       u32             mA;
+};
+
+struct spacemit_pinctrl_dconf {
+       u64                             schmitt_mask;
+       u64                             drive_mask;
+
+       struct spacemit_pin_drv_strength *ds_1v8_tbl;
+       size_t                           ds_1v8_tbl_num;
+       struct spacemit_pin_drv_strength *ds_3v3_tbl;
+       size_t                           ds_3v3_tbl_num;
+};
+
 struct spacemit_pin {
        u16                             pin;
        u16                             flags;
@@ -67,6 +85,7 @@ struct spacemit_pinctrl_data {
        const struct spacemit_pin       *data;
        u16                             npins;
        unsigned int                    (*pin_to_offset)(unsigned int pin);
+       const struct spacemit_pinctrl_dconf     *dconf;
 };
 
 struct spacemit_pin_mux_config {
@@ -74,11 +93,6 @@ struct spacemit_pin_mux_config {
        u32                             config;
 };
 
-struct spacemit_pin_drv_strength {
-       u8              val;
-       u32             mA;
-};
-
 /* map pin id to pinctrl register offset, refer MFPR definition */
 static unsigned int spacemit_k1_pin_to_offset(unsigned int pin)
 {
@@ -193,23 +207,70 @@ static void spacemit_pctrl_dbg_show(struct pinctrl_dev *pctldev,
        seq_printf(seq, "mux: %ld reg: 0x%04x", (value & PAD_MUX), value);
 }
 
-/* use IO high level output current as the table */
-static struct spacemit_pin_drv_strength spacemit_ds_1v8_tbl[4] = {
-       { 0, 11 },
-       { 2, 21 },
-       { 4, 32 },
-       { 6, 42 },
+static const struct spacemit_pinctrl_dconf k1_drive_conf = {
+       .drive_mask = PAD_DRIVE_K1,
+       .schmitt_mask = PAD_SCHMITT_K1,
+       .ds_1v8_tbl = (struct spacemit_pin_drv_strength[]) {
+               { 0, 11 },
+               { 2, 21 },
+               { 4, 32 },
+               { 6, 42 },
+       },
+       .ds_1v8_tbl_num = 4,
+       .ds_3v3_tbl = (struct spacemit_pin_drv_strength[]) {
+               { 0,  7 },
+               { 2, 10 },
+               { 4, 13 },
+               { 6, 16 },
+               { 1, 19 },
+               { 3, 23 },
+               { 5, 26 },
+               { 7, 29 },
+       },
+       .ds_3v3_tbl_num = 8,
 };
 
-static struct spacemit_pin_drv_strength spacemit_ds_3v3_tbl[8] = {
-       { 0,  7 },
-       { 2, 10 },
-       { 4, 13 },
-       { 6, 16 },
-       { 1, 19 },
-       { 3, 23 },
-       { 5, 26 },
-       { 7, 29 },
+static const struct spacemit_pinctrl_dconf k3_drive_conf = {
+       .drive_mask = PAD_DRIVE_K3,
+       .schmitt_mask = PAD_SCHMITT_K3,
+       .ds_1v8_tbl = (struct spacemit_pin_drv_strength[]) {
+               { 0,  2 },
+               { 1,  4 },
+               { 2,  6 },
+               { 3,  7 },
+               { 4,  9 },
+               { 5,  11 },
+               { 6,  13 },
+               { 7,  14 },
+               { 8,  21 },
+               { 9,  23 },
+               { 10, 25 },
+               { 11, 26 },
+               { 12, 28 },
+               { 13, 30 },
+               { 14, 31 },
+               { 15, 33 },
+       },
+       .ds_1v8_tbl_num = 16,
+       .ds_3v3_tbl = (struct spacemit_pin_drv_strength[]) {
+               { 0,  3 },
+               { 1,  5 },
+               { 2,  7 },
+               { 3,  9 },
+               { 4,  11 },
+               { 5,  13 },
+               { 6,  15 },
+               { 7,  17 },
+               { 8,  25 },
+               { 9,  27 },
+               { 10, 29 },
+               { 11, 31 },
+               { 12, 33 },
+               { 13, 35 },
+               { 14, 37 },
+               { 15, 38 },
+       },
+       .ds_3v3_tbl_num = 16,
 };
 
 static inline u8 spacemit_get_ds_value(struct spacemit_pin_drv_strength *tbl,
@@ -237,16 +298,17 @@ static inline u32 spacemit_get_ds_mA(struct spacemit_pin_drv_strength *tbl,
 }
 
 static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type,
+                                             const struct spacemit_pinctrl_dconf *dconf,
                                              u32 mA)
 {
        switch (type) {
        case IO_TYPE_1V8:
-               return spacemit_get_ds_value(spacemit_ds_1v8_tbl,
-                                            ARRAY_SIZE(spacemit_ds_1v8_tbl),
+               return spacemit_get_ds_value(dconf->ds_1v8_tbl,
+                                            dconf->ds_1v8_tbl_num,
                                             mA);
        case IO_TYPE_3V3:
-               return spacemit_get_ds_value(spacemit_ds_3v3_tbl,
-                                            ARRAY_SIZE(spacemit_ds_3v3_tbl),
+               return spacemit_get_ds_value(dconf->ds_3v3_tbl,
+                                            dconf->ds_3v3_tbl_num,
                                             mA);
        default:
                return 0;
@@ -254,16 +316,17 @@ static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type,
 }
 
 static inline u32 spacemit_get_drive_strength_mA(enum spacemit_pin_io_type type,
+                                                const struct spacemit_pinctrl_dconf *dconf,
                                                 u32 value)
 {
        switch (type) {
        case IO_TYPE_1V8:
-               return spacemit_get_ds_mA(spacemit_ds_1v8_tbl,
-                                         ARRAY_SIZE(spacemit_ds_1v8_tbl),
-                                         value & 0x6);
+               return spacemit_get_ds_mA(dconf->ds_1v8_tbl,
+                                         dconf->ds_1v8_tbl_num,
+                                         value);
        case IO_TYPE_3V3:
-               return spacemit_get_ds_mA(spacemit_ds_3v3_tbl,
-                                         ARRAY_SIZE(spacemit_ds_3v3_tbl),
+               return spacemit_get_ds_mA(dconf->ds_3v3_tbl,
+                                         dconf->ds_3v3_tbl_num,
                                          value);
        default:
                return 0;
@@ -510,6 +573,7 @@ static int spacemit_pinconf_get(struct pinctrl_dev *pctldev,
 #define ENABLE_DRV_STRENGTH    BIT(1)
 #define ENABLE_SLEW_RATE       BIT(2)
 static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
+                                           const struct spacemit_pinctrl_dconf *dconf,
                                            unsigned long *configs,
                                            unsigned int num_configs,
                                            u32 *value)
@@ -547,8 +611,8 @@ static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
                        drv_strength = arg;
                        break;
                case PIN_CONFIG_INPUT_SCHMITT:
-                       v &= ~PAD_SCHMITT;
-                       v |= FIELD_PREP(PAD_SCHMITT, arg);
+                       v &= ~dconf->schmitt_mask;
+                       v |= (arg << __ffs(dconf->schmitt_mask)) & dconf->schmitt_mask;
                        break;
                case PIN_CONFIG_POWER_SOURCE:
                        voltage = arg;
@@ -584,10 +648,10 @@ static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
                        }
                }
 
-               val = spacemit_get_driver_strength(type, drv_strength);
+               val = spacemit_get_driver_strength(type, dconf, drv_strength);
 
-               v &= ~PAD_DRIVE;
-               v |= FIELD_PREP(PAD_DRIVE, val);
+               v &= ~dconf->drive_mask;
+               v |= (val << __ffs(dconf->drive_mask)) & dconf->drive_mask;
        }
 
        if (flag & ENABLE_SLEW_RATE) {
@@ -637,7 +701,8 @@ static int spacemit_pinconf_set(struct pinctrl_dev *pctldev,
        const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
        u32 value;
 
-       if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
+       if (spacemit_pinconf_generate_config(spin, pctrl->data->dconf,
+                                            configs, num_configs, &value))
                return -EINVAL;
 
        return spacemit_pin_set_config(pctrl, pin, value);
@@ -659,7 +724,8 @@ static int spacemit_pinconf_group_set(struct pinctrl_dev *pctldev,
                return -EINVAL;
 
        spin = spacemit_get_pin(pctrl, group->grp.pins[0]);
-       if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
+       if (spacemit_pinconf_generate_config(spin, pctrl->data->dconf,
+                                            configs, num_configs, &value))
                return -EINVAL;
 
        for (i = 0; i < group->grp.npins; i++)
@@ -693,6 +759,7 @@ static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev,
                                      struct seq_file *seq, unsigned int pin)
 {
        struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       const struct spacemit_pinctrl_dconf *dconf = pctrl->data->dconf;
        const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
        enum spacemit_pin_io_type type = spacemit_to_pin_io_type(spin);
        void __iomem *reg = spacemit_pin_to_reg(pctrl, pin);
@@ -703,17 +770,17 @@ static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev,
 
        seq_printf(seq, ", io type (%s)", io_type_desc[type]);
 
-       tmp = FIELD_GET(PAD_DRIVE, value);
+       tmp = (value & dconf->drive_mask) >> __ffs(dconf->drive_mask);
        if (type == IO_TYPE_1V8 || type == IO_TYPE_3V3) {
-               mA = spacemit_get_drive_strength_mA(type, tmp);
+               mA = spacemit_get_drive_strength_mA(type, dconf, tmp);
                seq_printf(seq, ", drive strength (%d mA)", mA);
        }
 
        /* drive strength depend on power source, so show all values */
        if (type == IO_TYPE_EXTERNAL)
                seq_printf(seq, ", drive strength (%d or %d mA)",
-                          spacemit_get_drive_strength_mA(IO_TYPE_1V8, tmp),
-                          spacemit_get_drive_strength_mA(IO_TYPE_3V3, tmp));
+                          spacemit_get_drive_strength_mA(IO_TYPE_1V8, dconf, tmp),
+                          spacemit_get_drive_strength_mA(IO_TYPE_3V3, dconf, tmp));
 
        seq_printf(seq, ", register (0x%04x)", value);
 }
@@ -1051,6 +1118,7 @@ static const struct spacemit_pinctrl_data k1_pinctrl_data = {
        .data = k1_pin_data,
        .npins = ARRAY_SIZE(k1_pin_desc),
        .pin_to_offset = spacemit_k1_pin_to_offset,
+       .dconf = &k1_drive_conf,
 };
 
 static const struct pinctrl_pin_desc k3_pin_desc[] = {
@@ -1387,6 +1455,7 @@ static const struct spacemit_pinctrl_data k3_pinctrl_data = {
        .data = k3_pin_data,
        .npins = ARRAY_SIZE(k3_pin_desc),
        .pin_to_offset = spacemit_k3_pin_to_offset,
+       .dconf = &k3_drive_conf,
 };
 
 static const struct of_device_id k1_pinctrl_ids[] = {