156d77c9aSAbel Vesa // SPDX-License-Identifier: GPL-2.0 256d77c9aSAbel Vesa /* 356d77c9aSAbel Vesa * Copyright (c) 2023, Linaro Limited 456d77c9aSAbel Vesa */ 556d77c9aSAbel Vesa 656d77c9aSAbel Vesa #include <linux/module.h> 756d77c9aSAbel Vesa #include <linux/platform_device.h> 856d77c9aSAbel Vesa #include <linux/regulator/consumer.h> 956d77c9aSAbel Vesa #include <linux/regmap.h> 1056d77c9aSAbel Vesa #include <linux/of.h> 1156d77c9aSAbel Vesa #include <linux/phy/phy.h> 1256d77c9aSAbel Vesa 1356d77c9aSAbel Vesa /* eUSB2 status registers */ 1456d77c9aSAbel Vesa #define EUSB2_RPTR_STATUS 0x08 1556d77c9aSAbel Vesa #define RPTR_OK BIT(7) 1656d77c9aSAbel Vesa 1756d77c9aSAbel Vesa /* eUSB2 control registers */ 1856d77c9aSAbel Vesa #define EUSB2_EN_CTL1 0x46 1956d77c9aSAbel Vesa #define EUSB2_RPTR_EN BIT(7) 2056d77c9aSAbel Vesa 2156d77c9aSAbel Vesa #define EUSB2_FORCE_EN_5 0xe8 2256d77c9aSAbel Vesa #define F_CLK_19P2M_EN BIT(6) 2356d77c9aSAbel Vesa 2456d77c9aSAbel Vesa #define EUSB2_FORCE_VAL_5 0xeD 2556d77c9aSAbel Vesa #define V_CLK_19P2M_EN BIT(6) 2656d77c9aSAbel Vesa 2799a517a5SKonrad Dybcio #define EUSB2_TUNE_USB2_CROSSOVER 0x50 2856d77c9aSAbel Vesa #define EUSB2_TUNE_IUSB2 0x51 2999a517a5SKonrad Dybcio #define EUSB2_TUNE_RES_FSDIF 0x52 3099a517a5SKonrad Dybcio #define EUSB2_TUNE_HSDISC 0x53 3156d77c9aSAbel Vesa #define EUSB2_TUNE_SQUELCH_U 0x54 3299a517a5SKonrad Dybcio #define EUSB2_TUNE_USB2_SLEW 0x55 3399a517a5SKonrad Dybcio #define EUSB2_TUNE_USB2_EQU 0x56 3456d77c9aSAbel Vesa #define EUSB2_TUNE_USB2_PREEM 0x57 3599a517a5SKonrad Dybcio #define EUSB2_TUNE_USB2_HS_COMP_CUR 0x58 3699a517a5SKonrad Dybcio #define EUSB2_TUNE_EUSB_SLEW 0x59 3799a517a5SKonrad Dybcio #define EUSB2_TUNE_EUSB_EQU 0x5A 3899a517a5SKonrad Dybcio #define EUSB2_TUNE_EUSB_HS_COMP_CUR 0x5B 3956d77c9aSAbel Vesa 404ba2e527SKonrad Dybcio #define QCOM_EUSB2_REPEATER_INIT_CFG(r, v) \ 4156d77c9aSAbel Vesa { \ 424ba2e527SKonrad Dybcio .reg = r, \ 4356d77c9aSAbel Vesa .val = v, \ 4456d77c9aSAbel Vesa } 4556d77c9aSAbel Vesa 464ba2e527SKonrad Dybcio enum reg_fields { 4799a517a5SKonrad Dybcio F_TUNE_EUSB_HS_COMP_CUR, 4899a517a5SKonrad Dybcio F_TUNE_EUSB_EQU, 4999a517a5SKonrad Dybcio F_TUNE_EUSB_SLEW, 5099a517a5SKonrad Dybcio F_TUNE_USB2_HS_COMP_CUR, 514ba2e527SKonrad Dybcio F_TUNE_USB2_PREEM, 5299a517a5SKonrad Dybcio F_TUNE_USB2_EQU, 5399a517a5SKonrad Dybcio F_TUNE_USB2_SLEW, 544ba2e527SKonrad Dybcio F_TUNE_SQUELCH_U, 5599a517a5SKonrad Dybcio F_TUNE_HSDISC, 5699a517a5SKonrad Dybcio F_TUNE_RES_FSDIF, 574ba2e527SKonrad Dybcio F_TUNE_IUSB2, 5899a517a5SKonrad Dybcio F_TUNE_USB2_CROSSOVER, 594ba2e527SKonrad Dybcio F_NUM_TUNE_FIELDS, 604ba2e527SKonrad Dybcio 614ba2e527SKonrad Dybcio F_FORCE_VAL_5 = F_NUM_TUNE_FIELDS, 624ba2e527SKonrad Dybcio F_FORCE_EN_5, 634ba2e527SKonrad Dybcio 644ba2e527SKonrad Dybcio F_EN_CTL1, 654ba2e527SKonrad Dybcio 664ba2e527SKonrad Dybcio F_RPTR_STATUS, 674ba2e527SKonrad Dybcio F_NUM_FIELDS, 684ba2e527SKonrad Dybcio }; 694ba2e527SKonrad Dybcio 704ba2e527SKonrad Dybcio static struct reg_field eusb2_repeater_tune_reg_fields[F_NUM_FIELDS] = { 7199a517a5SKonrad Dybcio [F_TUNE_EUSB_HS_COMP_CUR] = REG_FIELD(EUSB2_TUNE_EUSB_HS_COMP_CUR, 0, 1), 7299a517a5SKonrad Dybcio [F_TUNE_EUSB_EQU] = REG_FIELD(EUSB2_TUNE_EUSB_EQU, 0, 1), 7399a517a5SKonrad Dybcio [F_TUNE_EUSB_SLEW] = REG_FIELD(EUSB2_TUNE_EUSB_SLEW, 0, 1), 7499a517a5SKonrad Dybcio [F_TUNE_USB2_HS_COMP_CUR] = REG_FIELD(EUSB2_TUNE_USB2_HS_COMP_CUR, 0, 1), 754ba2e527SKonrad Dybcio [F_TUNE_USB2_PREEM] = REG_FIELD(EUSB2_TUNE_USB2_PREEM, 0, 2), 7699a517a5SKonrad Dybcio [F_TUNE_USB2_EQU] = REG_FIELD(EUSB2_TUNE_USB2_EQU, 0, 1), 7799a517a5SKonrad Dybcio [F_TUNE_USB2_SLEW] = REG_FIELD(EUSB2_TUNE_USB2_SLEW, 0, 1), 784ba2e527SKonrad Dybcio [F_TUNE_SQUELCH_U] = REG_FIELD(EUSB2_TUNE_SQUELCH_U, 0, 2), 7999a517a5SKonrad Dybcio [F_TUNE_HSDISC] = REG_FIELD(EUSB2_TUNE_HSDISC, 0, 2), 8099a517a5SKonrad Dybcio [F_TUNE_RES_FSDIF] = REG_FIELD(EUSB2_TUNE_RES_FSDIF, 0, 2), 814ba2e527SKonrad Dybcio [F_TUNE_IUSB2] = REG_FIELD(EUSB2_TUNE_IUSB2, 0, 3), 8299a517a5SKonrad Dybcio [F_TUNE_USB2_CROSSOVER] = REG_FIELD(EUSB2_TUNE_USB2_CROSSOVER, 0, 2), 834ba2e527SKonrad Dybcio 844ba2e527SKonrad Dybcio [F_FORCE_VAL_5] = REG_FIELD(EUSB2_FORCE_VAL_5, 0, 7), 854ba2e527SKonrad Dybcio [F_FORCE_EN_5] = REG_FIELD(EUSB2_FORCE_EN_5, 0, 7), 864ba2e527SKonrad Dybcio 874ba2e527SKonrad Dybcio [F_EN_CTL1] = REG_FIELD(EUSB2_EN_CTL1, 0, 7), 884ba2e527SKonrad Dybcio 894ba2e527SKonrad Dybcio [F_RPTR_STATUS] = REG_FIELD(EUSB2_RPTR_STATUS, 0, 7), 904ba2e527SKonrad Dybcio }; 914ba2e527SKonrad Dybcio 9256d77c9aSAbel Vesa struct eusb2_repeater_cfg { 9399a517a5SKonrad Dybcio const u32 *init_tbl; 9456d77c9aSAbel Vesa int init_tbl_num; 9556d77c9aSAbel Vesa const char * const *vreg_list; 9656d77c9aSAbel Vesa int num_vregs; 9756d77c9aSAbel Vesa }; 9856d77c9aSAbel Vesa 9956d77c9aSAbel Vesa struct eusb2_repeater { 10056d77c9aSAbel Vesa struct device *dev; 1014ba2e527SKonrad Dybcio struct regmap_field *regs[F_NUM_FIELDS]; 10256d77c9aSAbel Vesa struct phy *phy; 10356d77c9aSAbel Vesa struct regulator_bulk_data *vregs; 10456d77c9aSAbel Vesa const struct eusb2_repeater_cfg *cfg; 10556d77c9aSAbel Vesa enum phy_mode mode; 10656d77c9aSAbel Vesa }; 10756d77c9aSAbel Vesa 10856d77c9aSAbel Vesa static const char * const pm8550b_vreg_l[] = { 10956d77c9aSAbel Vesa "vdd18", "vdd3", 11056d77c9aSAbel Vesa }; 11156d77c9aSAbel Vesa 11299a517a5SKonrad Dybcio static const u32 pm8550b_init_tbl[F_NUM_TUNE_FIELDS] = { 11399a517a5SKonrad Dybcio [F_TUNE_IUSB2] = 0x8, 11499a517a5SKonrad Dybcio [F_TUNE_SQUELCH_U] = 0x3, 11599a517a5SKonrad Dybcio [F_TUNE_USB2_PREEM] = 0x5, 11656d77c9aSAbel Vesa }; 11756d77c9aSAbel Vesa 11856d77c9aSAbel Vesa static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = { 11956d77c9aSAbel Vesa .init_tbl = pm8550b_init_tbl, 12056d77c9aSAbel Vesa .init_tbl_num = ARRAY_SIZE(pm8550b_init_tbl), 12156d77c9aSAbel Vesa .vreg_list = pm8550b_vreg_l, 12256d77c9aSAbel Vesa .num_vregs = ARRAY_SIZE(pm8550b_vreg_l), 12356d77c9aSAbel Vesa }; 12456d77c9aSAbel Vesa 12556d77c9aSAbel Vesa static int eusb2_repeater_init_vregs(struct eusb2_repeater *rptr) 12656d77c9aSAbel Vesa { 12756d77c9aSAbel Vesa int num = rptr->cfg->num_vregs; 12856d77c9aSAbel Vesa struct device *dev = rptr->dev; 12956d77c9aSAbel Vesa int i; 13056d77c9aSAbel Vesa 13156d77c9aSAbel Vesa rptr->vregs = devm_kcalloc(dev, num, sizeof(*rptr->vregs), GFP_KERNEL); 13256d77c9aSAbel Vesa if (!rptr->vregs) 13356d77c9aSAbel Vesa return -ENOMEM; 13456d77c9aSAbel Vesa 13556d77c9aSAbel Vesa for (i = 0; i < num; i++) 13656d77c9aSAbel Vesa rptr->vregs[i].supply = rptr->cfg->vreg_list[i]; 13756d77c9aSAbel Vesa 13856d77c9aSAbel Vesa return devm_regulator_bulk_get(dev, num, rptr->vregs); 13956d77c9aSAbel Vesa } 14056d77c9aSAbel Vesa 14156d77c9aSAbel Vesa static int eusb2_repeater_init(struct phy *phy) 14256d77c9aSAbel Vesa { 14399a517a5SKonrad Dybcio struct reg_field *regfields = eusb2_repeater_tune_reg_fields; 14456d77c9aSAbel Vesa struct eusb2_repeater *rptr = phy_get_drvdata(phy); 145*56156a76SKonrad Dybcio struct device_node *np = rptr->dev->of_node; 146*56156a76SKonrad Dybcio u32 init_tbl[F_NUM_TUNE_FIELDS] = { 0 }; 147*56156a76SKonrad Dybcio u8 override; 14856d77c9aSAbel Vesa u32 val; 14956d77c9aSAbel Vesa int ret; 15056d77c9aSAbel Vesa int i; 15156d77c9aSAbel Vesa 15256d77c9aSAbel Vesa ret = regulator_bulk_enable(rptr->cfg->num_vregs, rptr->vregs); 15356d77c9aSAbel Vesa if (ret) 15456d77c9aSAbel Vesa return ret; 15556d77c9aSAbel Vesa 1564ba2e527SKonrad Dybcio regmap_field_update_bits(rptr->regs[F_EN_CTL1], EUSB2_RPTR_EN, EUSB2_RPTR_EN); 15756d77c9aSAbel Vesa 15899a517a5SKonrad Dybcio for (i = 0; i < F_NUM_TUNE_FIELDS; i++) { 15999a517a5SKonrad Dybcio if (init_tbl[i]) { 16099a517a5SKonrad Dybcio regmap_field_update_bits(rptr->regs[i], init_tbl[i], init_tbl[i]); 16199a517a5SKonrad Dybcio } else { 16299a517a5SKonrad Dybcio /* Write 0 if there's no value set */ 16399a517a5SKonrad Dybcio u32 mask = GENMASK(regfields[i].msb, regfields[i].lsb); 16499a517a5SKonrad Dybcio 16599a517a5SKonrad Dybcio regmap_field_update_bits(rptr->regs[i], mask, 0); 16699a517a5SKonrad Dybcio } 16799a517a5SKonrad Dybcio } 168*56156a76SKonrad Dybcio memcpy(init_tbl, rptr->cfg->init_tbl, sizeof(init_tbl)); 169*56156a76SKonrad Dybcio 170*56156a76SKonrad Dybcio if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &override)) 171*56156a76SKonrad Dybcio init_tbl[F_TUNE_IUSB2] = override; 172*56156a76SKonrad Dybcio 173*56156a76SKonrad Dybcio if (!of_property_read_u8(np, "qcom,tune-usb2-disc-thres", &override)) 174*56156a76SKonrad Dybcio init_tbl[F_TUNE_HSDISC] = override; 175*56156a76SKonrad Dybcio 176*56156a76SKonrad Dybcio if (!of_property_read_u8(np, "qcom,tune-usb2-preem", &override)) 177*56156a76SKonrad Dybcio init_tbl[F_TUNE_USB2_PREEM] = override; 178*56156a76SKonrad Dybcio 179*56156a76SKonrad Dybcio for (i = 0; i < F_NUM_TUNE_FIELDS; i++) 180*56156a76SKonrad Dybcio regmap_field_update_bits(rptr->regs[i], init_tbl[i], init_tbl[i]); 18156d77c9aSAbel Vesa 1824ba2e527SKonrad Dybcio ret = regmap_field_read_poll_timeout(rptr->regs[F_RPTR_STATUS], 1834ba2e527SKonrad Dybcio val, val & RPTR_OK, 10, 5); 18456d77c9aSAbel Vesa if (ret) 18556d77c9aSAbel Vesa dev_err(rptr->dev, "initialization timed-out\n"); 18656d77c9aSAbel Vesa 18756d77c9aSAbel Vesa return ret; 18856d77c9aSAbel Vesa } 18956d77c9aSAbel Vesa 19056d77c9aSAbel Vesa static int eusb2_repeater_set_mode(struct phy *phy, 19156d77c9aSAbel Vesa enum phy_mode mode, int submode) 19256d77c9aSAbel Vesa { 19356d77c9aSAbel Vesa struct eusb2_repeater *rptr = phy_get_drvdata(phy); 19456d77c9aSAbel Vesa 19556d77c9aSAbel Vesa switch (mode) { 19656d77c9aSAbel Vesa case PHY_MODE_USB_HOST: 19756d77c9aSAbel Vesa /* 19856d77c9aSAbel Vesa * CM.Lx is prohibited when repeater is already into Lx state as 19956d77c9aSAbel Vesa * per eUSB 1.2 Spec. Below implement software workaround until 20056d77c9aSAbel Vesa * PHY and controller is fixing seen observation. 20156d77c9aSAbel Vesa */ 2024ba2e527SKonrad Dybcio regmap_field_update_bits(rptr->regs[F_FORCE_EN_5], 20356d77c9aSAbel Vesa F_CLK_19P2M_EN, F_CLK_19P2M_EN); 2044ba2e527SKonrad Dybcio regmap_field_update_bits(rptr->regs[F_FORCE_VAL_5], 20556d77c9aSAbel Vesa V_CLK_19P2M_EN, V_CLK_19P2M_EN); 20656d77c9aSAbel Vesa break; 20756d77c9aSAbel Vesa case PHY_MODE_USB_DEVICE: 20856d77c9aSAbel Vesa /* 20956d77c9aSAbel Vesa * In device mode clear host mode related workaround as there 21056d77c9aSAbel Vesa * is no repeater reset available, and enable/disable of 21156d77c9aSAbel Vesa * repeater doesn't clear previous value due to shared 21256d77c9aSAbel Vesa * regulators (say host <-> device mode switch). 21356d77c9aSAbel Vesa */ 2144ba2e527SKonrad Dybcio regmap_field_update_bits(rptr->regs[F_FORCE_EN_5], 21556d77c9aSAbel Vesa F_CLK_19P2M_EN, 0); 2164ba2e527SKonrad Dybcio regmap_field_update_bits(rptr->regs[F_FORCE_VAL_5], 21756d77c9aSAbel Vesa V_CLK_19P2M_EN, 0); 21856d77c9aSAbel Vesa break; 21956d77c9aSAbel Vesa default: 22056d77c9aSAbel Vesa return -EINVAL; 22156d77c9aSAbel Vesa } 22256d77c9aSAbel Vesa 22356d77c9aSAbel Vesa return 0; 22456d77c9aSAbel Vesa } 22556d77c9aSAbel Vesa 22656d77c9aSAbel Vesa static int eusb2_repeater_exit(struct phy *phy) 22756d77c9aSAbel Vesa { 22856d77c9aSAbel Vesa struct eusb2_repeater *rptr = phy_get_drvdata(phy); 22956d77c9aSAbel Vesa 23056d77c9aSAbel Vesa return regulator_bulk_disable(rptr->cfg->num_vregs, rptr->vregs); 23156d77c9aSAbel Vesa } 23256d77c9aSAbel Vesa 23356d77c9aSAbel Vesa static const struct phy_ops eusb2_repeater_ops = { 23456d77c9aSAbel Vesa .init = eusb2_repeater_init, 23556d77c9aSAbel Vesa .exit = eusb2_repeater_exit, 23656d77c9aSAbel Vesa .set_mode = eusb2_repeater_set_mode, 23756d77c9aSAbel Vesa .owner = THIS_MODULE, 23856d77c9aSAbel Vesa }; 23956d77c9aSAbel Vesa 24056d77c9aSAbel Vesa static int eusb2_repeater_probe(struct platform_device *pdev) 24156d77c9aSAbel Vesa { 24256d77c9aSAbel Vesa struct eusb2_repeater *rptr; 24356d77c9aSAbel Vesa struct device *dev = &pdev->dev; 24456d77c9aSAbel Vesa struct phy_provider *phy_provider; 24556d77c9aSAbel Vesa struct device_node *np = dev->of_node; 2464ba2e527SKonrad Dybcio struct regmap *regmap; 2474ba2e527SKonrad Dybcio int i, ret; 24856d77c9aSAbel Vesa u32 res; 24956d77c9aSAbel Vesa 25056d77c9aSAbel Vesa rptr = devm_kzalloc(dev, sizeof(*rptr), GFP_KERNEL); 25156d77c9aSAbel Vesa if (!rptr) 25256d77c9aSAbel Vesa return -ENOMEM; 25356d77c9aSAbel Vesa 25456d77c9aSAbel Vesa rptr->dev = dev; 25556d77c9aSAbel Vesa dev_set_drvdata(dev, rptr); 25656d77c9aSAbel Vesa 25756d77c9aSAbel Vesa rptr->cfg = of_device_get_match_data(dev); 25856d77c9aSAbel Vesa if (!rptr->cfg) 25956d77c9aSAbel Vesa return -EINVAL; 26056d77c9aSAbel Vesa 2614ba2e527SKonrad Dybcio regmap = dev_get_regmap(dev->parent, NULL); 2624ba2e527SKonrad Dybcio if (!regmap) 26356d77c9aSAbel Vesa return -ENODEV; 26456d77c9aSAbel Vesa 26556d77c9aSAbel Vesa ret = of_property_read_u32(np, "reg", &res); 26656d77c9aSAbel Vesa if (ret < 0) 26756d77c9aSAbel Vesa return ret; 26856d77c9aSAbel Vesa 2694ba2e527SKonrad Dybcio for (i = 0; i < F_NUM_FIELDS; i++) 2704ba2e527SKonrad Dybcio eusb2_repeater_tune_reg_fields[i].reg += res; 2714ba2e527SKonrad Dybcio 2724ba2e527SKonrad Dybcio ret = devm_regmap_field_bulk_alloc(dev, regmap, rptr->regs, 2734ba2e527SKonrad Dybcio eusb2_repeater_tune_reg_fields, 2744ba2e527SKonrad Dybcio F_NUM_FIELDS); 2754ba2e527SKonrad Dybcio if (ret) 2764ba2e527SKonrad Dybcio return ret; 27756d77c9aSAbel Vesa 27856d77c9aSAbel Vesa ret = eusb2_repeater_init_vregs(rptr); 27956d77c9aSAbel Vesa if (ret < 0) { 28056d77c9aSAbel Vesa dev_err(dev, "unable to get supplies\n"); 28156d77c9aSAbel Vesa return ret; 28256d77c9aSAbel Vesa } 28356d77c9aSAbel Vesa 28456d77c9aSAbel Vesa rptr->phy = devm_phy_create(dev, np, &eusb2_repeater_ops); 28556d77c9aSAbel Vesa if (IS_ERR(rptr->phy)) { 28656d77c9aSAbel Vesa dev_err(dev, "failed to create PHY: %d\n", ret); 28756d77c9aSAbel Vesa return PTR_ERR(rptr->phy); 28856d77c9aSAbel Vesa } 28956d77c9aSAbel Vesa 29056d77c9aSAbel Vesa phy_set_drvdata(rptr->phy, rptr); 29156d77c9aSAbel Vesa 29256d77c9aSAbel Vesa phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 29356d77c9aSAbel Vesa if (IS_ERR(phy_provider)) 29456d77c9aSAbel Vesa return PTR_ERR(phy_provider); 29556d77c9aSAbel Vesa 29656d77c9aSAbel Vesa dev_info(dev, "Registered Qcom-eUSB2 repeater\n"); 29756d77c9aSAbel Vesa 29856d77c9aSAbel Vesa return 0; 29956d77c9aSAbel Vesa } 30056d77c9aSAbel Vesa 301e5ce6d9dSUwe Kleine-König static void eusb2_repeater_remove(struct platform_device *pdev) 30256d77c9aSAbel Vesa { 30356d77c9aSAbel Vesa struct eusb2_repeater *rptr = platform_get_drvdata(pdev); 30456d77c9aSAbel Vesa 30556d77c9aSAbel Vesa if (!rptr) 306e5ce6d9dSUwe Kleine-König return; 30756d77c9aSAbel Vesa 30856d77c9aSAbel Vesa eusb2_repeater_exit(rptr->phy); 30956d77c9aSAbel Vesa } 31056d77c9aSAbel Vesa 31156d77c9aSAbel Vesa static const struct of_device_id eusb2_repeater_of_match_table[] = { 31256d77c9aSAbel Vesa { 31356d77c9aSAbel Vesa .compatible = "qcom,pm8550b-eusb2-repeater", 31456d77c9aSAbel Vesa .data = &pm8550b_eusb2_cfg, 31556d77c9aSAbel Vesa }, 31656d77c9aSAbel Vesa { }, 31756d77c9aSAbel Vesa }; 31856d77c9aSAbel Vesa MODULE_DEVICE_TABLE(of, eusb2_repeater_of_match_table); 31956d77c9aSAbel Vesa 32056d77c9aSAbel Vesa static struct platform_driver eusb2_repeater_driver = { 32156d77c9aSAbel Vesa .probe = eusb2_repeater_probe, 322e5ce6d9dSUwe Kleine-König .remove_new = eusb2_repeater_remove, 32356d77c9aSAbel Vesa .driver = { 32456d77c9aSAbel Vesa .name = "qcom-eusb2-repeater", 32556d77c9aSAbel Vesa .of_match_table = eusb2_repeater_of_match_table, 32656d77c9aSAbel Vesa }, 32756d77c9aSAbel Vesa }; 32856d77c9aSAbel Vesa 32956d77c9aSAbel Vesa module_platform_driver(eusb2_repeater_driver); 33056d77c9aSAbel Vesa 33156d77c9aSAbel Vesa MODULE_DESCRIPTION("Qualcomm PMIC eUSB2 Repeater driver"); 33256d77c9aSAbel Vesa MODULE_LICENSE("GPL"); 333