Skip to content

Commit

Permalink
phy: qualcomm: phy-qcom-eusb2-repeater: Use regmap_fields
Browse files Browse the repository at this point in the history
[ Upstream commit 4ba2e52 ]

Switch to regmap_fields, so that the values written into registers are
sanitized by their explicit sizes and the different registers are
structured in an iterable object to make external changes to the init
sequence simpler.

Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Link: https://lore.kernel.org/r/20230830-topic-eusb2_override-v2-2-7d8c893d93f6@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
konradybcio authored and gregkh committed Nov 28, 2023
1 parent 5fe0d30 commit d86b03d
Showing 1 changed file with 61 additions and 30 deletions.
91 changes: 61 additions & 30 deletions drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,42 @@
#define EUSB2_TUNE_SQUELCH_U 0x54
#define EUSB2_TUNE_USB2_PREEM 0x57

#define QCOM_EUSB2_REPEATER_INIT_CFG(o, v) \
#define QCOM_EUSB2_REPEATER_INIT_CFG(r, v) \
{ \
.offset = o, \
.reg = r, \
.val = v, \
}

enum reg_fields {
F_TUNE_USB2_PREEM,
F_TUNE_SQUELCH_U,
F_TUNE_IUSB2,
F_NUM_TUNE_FIELDS,

F_FORCE_VAL_5 = F_NUM_TUNE_FIELDS,
F_FORCE_EN_5,

F_EN_CTL1,

F_RPTR_STATUS,
F_NUM_FIELDS,
};

static struct reg_field eusb2_repeater_tune_reg_fields[F_NUM_FIELDS] = {
[F_TUNE_USB2_PREEM] = REG_FIELD(EUSB2_TUNE_USB2_PREEM, 0, 2),
[F_TUNE_SQUELCH_U] = REG_FIELD(EUSB2_TUNE_SQUELCH_U, 0, 2),
[F_TUNE_IUSB2] = REG_FIELD(EUSB2_TUNE_IUSB2, 0, 3),

[F_FORCE_VAL_5] = REG_FIELD(EUSB2_FORCE_VAL_5, 0, 7),
[F_FORCE_EN_5] = REG_FIELD(EUSB2_FORCE_EN_5, 0, 7),

[F_EN_CTL1] = REG_FIELD(EUSB2_EN_CTL1, 0, 7),

[F_RPTR_STATUS] = REG_FIELD(EUSB2_RPTR_STATUS, 0, 7),
};

struct eusb2_repeater_init_tbl {
unsigned int offset;
unsigned int reg;
unsigned int val;
};

Expand All @@ -49,11 +77,10 @@ struct eusb2_repeater_cfg {

struct eusb2_repeater {
struct device *dev;
struct regmap *regmap;
struct regmap_field *regs[F_NUM_FIELDS];
struct phy *phy;
struct regulator_bulk_data *vregs;
const struct eusb2_repeater_cfg *cfg;
u16 base;
enum phy_mode mode;
};

Expand All @@ -62,9 +89,9 @@ static const char * const pm8550b_vreg_l[] = {
};

static const struct eusb2_repeater_init_tbl pm8550b_init_tbl[] = {
QCOM_EUSB2_REPEATER_INIT_CFG(EUSB2_TUNE_IUSB2, 0x8),
QCOM_EUSB2_REPEATER_INIT_CFG(EUSB2_TUNE_SQUELCH_U, 0x3),
QCOM_EUSB2_REPEATER_INIT_CFG(EUSB2_TUNE_USB2_PREEM, 0x5),
QCOM_EUSB2_REPEATER_INIT_CFG(F_TUNE_IUSB2, 0x8),
QCOM_EUSB2_REPEATER_INIT_CFG(F_TUNE_SQUELCH_U, 0x3),
QCOM_EUSB2_REPEATER_INIT_CFG(F_TUNE_USB2_PREEM, 0x5),
};

static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
Expand Down Expand Up @@ -94,7 +121,6 @@ static int eusb2_repeater_init(struct phy *phy)
{
struct eusb2_repeater *rptr = phy_get_drvdata(phy);
const struct eusb2_repeater_init_tbl *init_tbl = rptr->cfg->init_tbl;
int num = rptr->cfg->init_tbl_num;
u32 val;
int ret;
int i;
Expand All @@ -103,17 +129,14 @@ static int eusb2_repeater_init(struct phy *phy)
if (ret)
return ret;

regmap_update_bits(rptr->regmap, rptr->base + EUSB2_EN_CTL1,
EUSB2_RPTR_EN, EUSB2_RPTR_EN);
regmap_field_update_bits(rptr->regs[F_EN_CTL1], EUSB2_RPTR_EN, EUSB2_RPTR_EN);

for (i = 0; i < num; i++)
regmap_update_bits(rptr->regmap,
rptr->base + init_tbl[i].offset,
init_tbl[i].val, init_tbl[i].val);
for (i = 0; i < rptr->cfg->init_tbl_num; i++)
regmap_field_update_bits(rptr->regs[init_tbl[i].reg],
init_tbl[i].val, init_tbl[i].val);

ret = regmap_read_poll_timeout(rptr->regmap,
rptr->base + EUSB2_RPTR_STATUS, val,
val & RPTR_OK, 10, 5);
ret = regmap_field_read_poll_timeout(rptr->regs[F_RPTR_STATUS],
val, val & RPTR_OK, 10, 5);
if (ret)
dev_err(rptr->dev, "initialization timed-out\n");

Expand All @@ -132,10 +155,10 @@ static int eusb2_repeater_set_mode(struct phy *phy,
* per eUSB 1.2 Spec. Below implement software workaround until
* PHY and controller is fixing seen observation.
*/
regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_EN_5,
F_CLK_19P2M_EN, F_CLK_19P2M_EN);
regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_VAL_5,
V_CLK_19P2M_EN, V_CLK_19P2M_EN);
regmap_field_update_bits(rptr->regs[F_FORCE_EN_5],
F_CLK_19P2M_EN, F_CLK_19P2M_EN);
regmap_field_update_bits(rptr->regs[F_FORCE_VAL_5],
V_CLK_19P2M_EN, V_CLK_19P2M_EN);
break;
case PHY_MODE_USB_DEVICE:
/*
Expand All @@ -144,10 +167,10 @@ static int eusb2_repeater_set_mode(struct phy *phy,
* repeater doesn't clear previous value due to shared
* regulators (say host <-> device mode switch).
*/
regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_EN_5,
F_CLK_19P2M_EN, 0);
regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_VAL_5,
V_CLK_19P2M_EN, 0);
regmap_field_update_bits(rptr->regs[F_FORCE_EN_5],
F_CLK_19P2M_EN, 0);
regmap_field_update_bits(rptr->regs[F_FORCE_VAL_5],
V_CLK_19P2M_EN, 0);
break;
default:
return -EINVAL;
Expand Down Expand Up @@ -176,8 +199,9 @@ static int eusb2_repeater_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
struct device_node *np = dev->of_node;
struct regmap *regmap;
int i, ret;
u32 res;
int ret;

rptr = devm_kzalloc(dev, sizeof(*rptr), GFP_KERNEL);
if (!rptr)
Expand All @@ -190,15 +214,22 @@ static int eusb2_repeater_probe(struct platform_device *pdev)
if (!rptr->cfg)
return -EINVAL;

rptr->regmap = dev_get_regmap(dev->parent, NULL);
if (!rptr->regmap)
regmap = dev_get_regmap(dev->parent, NULL);
if (!regmap)
return -ENODEV;

ret = of_property_read_u32(np, "reg", &res);
if (ret < 0)
return ret;

rptr->base = res;
for (i = 0; i < F_NUM_FIELDS; i++)
eusb2_repeater_tune_reg_fields[i].reg += res;

ret = devm_regmap_field_bulk_alloc(dev, regmap, rptr->regs,
eusb2_repeater_tune_reg_fields,
F_NUM_FIELDS);
if (ret)
return ret;

ret = eusb2_repeater_init_vregs(rptr);
if (ret < 0) {
Expand Down

0 comments on commit d86b03d

Please sign in to comment.