mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
pinctrl: spacemit: k3: adjust drive strength and schmitter trigger
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>
This commit is contained in:
parent
7412311c46
commit
3f20bdf715
|
|
@ -24,11 +24,12 @@
|
|||
#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)
|
||||
|
|
@ -38,12 +39,29 @@
|
|||
#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[] = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user