0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/acpi.h>
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/io.h>
0014 #include <linux/slab.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/property.h>
0018 #include <linux/notifier.h>
0019 #include <linux/extcon-provider.h>
0020 #include <linux/regmap.h>
0021 #include <linux/mfd/axp20x.h>
0022 #include <linux/usb/role.h>
0023 #include <linux/workqueue.h>
0024
0025 #include <asm/cpu_device_id.h>
0026 #include <asm/intel-family.h>
0027 #include <asm/iosf_mbi.h>
0028
0029
0030 #define PS_STAT_VBUS_TRIGGER BIT(0)
0031 #define PS_STAT_BAT_CHRG_DIR BIT(2)
0032 #define PS_STAT_VBUS_ABOVE_VHOLD BIT(3)
0033 #define PS_STAT_VBUS_VALID BIT(4)
0034 #define PS_STAT_VBUS_PRESENT BIT(5)
0035
0036
0037 #define BC_GLOBAL_RUN BIT(0)
0038 #define BC_GLOBAL_DET_STAT BIT(2)
0039 #define BC_GLOBAL_DBP_TOUT BIT(3)
0040 #define BC_GLOBAL_VLGC_COM_SEL BIT(4)
0041 #define BC_GLOBAL_DCD_TOUT_MASK (BIT(6)|BIT(5))
0042 #define BC_GLOBAL_DCD_TOUT_300MS 0
0043 #define BC_GLOBAL_DCD_TOUT_100MS 1
0044 #define BC_GLOBAL_DCD_TOUT_500MS 2
0045 #define BC_GLOBAL_DCD_TOUT_900MS 3
0046 #define BC_GLOBAL_DCD_DET_SEL BIT(7)
0047
0048
0049 #define VBUS_CNTL_DPDM_PD_EN BIT(4)
0050 #define VBUS_CNTL_DPDM_FD_EN BIT(5)
0051 #define VBUS_CNTL_FIRST_PO_STAT BIT(6)
0052
0053
0054 #define USB_STAT_BUS_STAT_MASK (BIT(3)|BIT(2)|BIT(1)|BIT(0))
0055 #define USB_STAT_BUS_STAT_SHIFT 0
0056 #define USB_STAT_BUS_STAT_ATHD 0
0057 #define USB_STAT_BUS_STAT_CONN 1
0058 #define USB_STAT_BUS_STAT_SUSP 2
0059 #define USB_STAT_BUS_STAT_CONF 3
0060 #define USB_STAT_USB_SS_MODE BIT(4)
0061 #define USB_STAT_DEAD_BAT_DET BIT(6)
0062 #define USB_STAT_DBP_UNCFG BIT(7)
0063
0064
0065 #define DET_STAT_MASK (BIT(7)|BIT(6)|BIT(5))
0066 #define DET_STAT_SHIFT 5
0067 #define DET_STAT_SDP 1
0068 #define DET_STAT_CDP 2
0069 #define DET_STAT_DCP 3
0070
0071 enum axp288_extcon_reg {
0072 AXP288_PS_STAT_REG = 0x00,
0073 AXP288_PS_BOOT_REASON_REG = 0x02,
0074 AXP288_BC_GLOBAL_REG = 0x2c,
0075 AXP288_BC_VBUS_CNTL_REG = 0x2d,
0076 AXP288_BC_USB_STAT_REG = 0x2e,
0077 AXP288_BC_DET_STAT_REG = 0x2f,
0078 };
0079
0080 enum axp288_extcon_irq {
0081 VBUS_FALLING_IRQ = 0,
0082 VBUS_RISING_IRQ,
0083 MV_CHNG_IRQ,
0084 BC_USB_CHNG_IRQ,
0085 EXTCON_IRQ_END,
0086 };
0087
0088 static const unsigned int axp288_extcon_cables[] = {
0089 EXTCON_CHG_USB_SDP,
0090 EXTCON_CHG_USB_CDP,
0091 EXTCON_CHG_USB_DCP,
0092 EXTCON_USB,
0093 EXTCON_NONE,
0094 };
0095
0096 struct axp288_extcon_info {
0097 struct device *dev;
0098 struct regmap *regmap;
0099 struct regmap_irq_chip_data *regmap_irqc;
0100 struct usb_role_switch *role_sw;
0101 struct work_struct role_work;
0102 int irq[EXTCON_IRQ_END];
0103 struct extcon_dev *edev;
0104 struct extcon_dev *id_extcon;
0105 struct notifier_block id_nb;
0106 unsigned int previous_cable;
0107 bool vbus_attach;
0108 };
0109
0110 static const struct x86_cpu_id cherry_trail_cpu_ids[] = {
0111 X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL),
0112 {}
0113 };
0114
0115
0116 static const char * const axp288_pwr_up_down_info[] = {
0117 "Last wake caused by user pressing the power button",
0118 "Last wake caused by a charger insertion",
0119 "Last wake caused by a battery insertion",
0120 "Last wake caused by SOC initiated global reset",
0121 "Last wake caused by cold reset",
0122 "Last shutdown caused by PMIC UVLO threshold",
0123 "Last shutdown caused by SOC initiated cold off",
0124 "Last shutdown caused by user pressing the power button",
0125 };
0126
0127
0128
0129
0130
0131 static void axp288_extcon_log_rsi(struct axp288_extcon_info *info)
0132 {
0133 unsigned int val, i, clear_mask = 0;
0134 unsigned long bits;
0135 int ret;
0136
0137 ret = regmap_read(info->regmap, AXP288_PS_BOOT_REASON_REG, &val);
0138 if (ret < 0) {
0139 dev_err(info->dev, "failed to read reset source indicator\n");
0140 return;
0141 }
0142
0143 bits = val & GENMASK(ARRAY_SIZE(axp288_pwr_up_down_info) - 1, 0);
0144 for_each_set_bit(i, &bits, ARRAY_SIZE(axp288_pwr_up_down_info))
0145 dev_dbg(info->dev, "%s\n", axp288_pwr_up_down_info[i]);
0146 clear_mask = bits;
0147
0148
0149 regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask);
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 static bool axp288_get_id_pin(struct axp288_extcon_info *info)
0167 {
0168 enum usb_role role;
0169
0170 if (info->id_extcon)
0171 return extcon_get_state(info->id_extcon, EXTCON_USB_HOST) <= 0;
0172
0173
0174 role = usb_role_switch_get_role(info->role_sw);
0175 return role != USB_ROLE_HOST;
0176 }
0177
0178 static void axp288_usb_role_work(struct work_struct *work)
0179 {
0180 struct axp288_extcon_info *info =
0181 container_of(work, struct axp288_extcon_info, role_work);
0182 enum usb_role role;
0183 bool id_pin;
0184 int ret;
0185
0186 id_pin = axp288_get_id_pin(info);
0187 if (!id_pin)
0188 role = USB_ROLE_HOST;
0189 else if (info->vbus_attach)
0190 role = USB_ROLE_DEVICE;
0191 else
0192 role = USB_ROLE_NONE;
0193
0194 ret = usb_role_switch_set_role(info->role_sw, role);
0195 if (ret)
0196 dev_err(info->dev, "failed to set role: %d\n", ret);
0197 }
0198
0199 static bool axp288_get_vbus_attach(struct axp288_extcon_info *info)
0200 {
0201 int ret, pwr_stat;
0202
0203 ret = regmap_read(info->regmap, AXP288_PS_STAT_REG, &pwr_stat);
0204 if (ret < 0) {
0205 dev_err(info->dev, "failed to read vbus status\n");
0206 return false;
0207 }
0208
0209 return !!(pwr_stat & PS_STAT_VBUS_VALID);
0210 }
0211
0212 static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
0213 {
0214 int ret, stat, cfg;
0215 u8 chrg_type;
0216 unsigned int cable = info->previous_cable;
0217 bool vbus_attach = false;
0218
0219 ret = iosf_mbi_block_punit_i2c_access();
0220 if (ret < 0)
0221 return ret;
0222
0223 vbus_attach = axp288_get_vbus_attach(info);
0224 if (!vbus_attach)
0225 goto no_vbus;
0226
0227
0228 ret = regmap_read(info->regmap, AXP288_BC_GLOBAL_REG, &cfg);
0229 if (ret < 0)
0230 goto dev_det_ret;
0231 if (cfg & BC_GLOBAL_DET_STAT) {
0232 dev_dbg(info->dev, "can't complete the charger detection\n");
0233 goto dev_det_ret;
0234 }
0235
0236 ret = regmap_read(info->regmap, AXP288_BC_DET_STAT_REG, &stat);
0237 if (ret < 0)
0238 goto dev_det_ret;
0239
0240 chrg_type = (stat & DET_STAT_MASK) >> DET_STAT_SHIFT;
0241
0242 switch (chrg_type) {
0243 case DET_STAT_SDP:
0244 dev_dbg(info->dev, "sdp cable is connected\n");
0245 cable = EXTCON_CHG_USB_SDP;
0246 break;
0247 case DET_STAT_CDP:
0248 dev_dbg(info->dev, "cdp cable is connected\n");
0249 cable = EXTCON_CHG_USB_CDP;
0250 break;
0251 case DET_STAT_DCP:
0252 dev_dbg(info->dev, "dcp cable is connected\n");
0253 cable = EXTCON_CHG_USB_DCP;
0254 break;
0255 default:
0256 dev_warn(info->dev, "unknown (reserved) bc detect result\n");
0257 cable = EXTCON_CHG_USB_SDP;
0258 }
0259
0260 no_vbus:
0261 iosf_mbi_unblock_punit_i2c_access();
0262
0263 extcon_set_state_sync(info->edev, info->previous_cable, false);
0264 if (info->previous_cable == EXTCON_CHG_USB_SDP)
0265 extcon_set_state_sync(info->edev, EXTCON_USB, false);
0266
0267 if (vbus_attach) {
0268 extcon_set_state_sync(info->edev, cable, vbus_attach);
0269 if (cable == EXTCON_CHG_USB_SDP)
0270 extcon_set_state_sync(info->edev, EXTCON_USB,
0271 vbus_attach);
0272
0273 info->previous_cable = cable;
0274 }
0275
0276 if (info->role_sw && info->vbus_attach != vbus_attach) {
0277 info->vbus_attach = vbus_attach;
0278
0279 queue_work(system_long_wq, &info->role_work);
0280 }
0281
0282 return 0;
0283
0284 dev_det_ret:
0285 iosf_mbi_unblock_punit_i2c_access();
0286
0287 if (ret < 0)
0288 dev_err(info->dev, "failed to detect BC Mod\n");
0289
0290 return ret;
0291 }
0292
0293 static int axp288_extcon_id_evt(struct notifier_block *nb,
0294 unsigned long event, void *param)
0295 {
0296 struct axp288_extcon_info *info =
0297 container_of(nb, struct axp288_extcon_info, id_nb);
0298
0299
0300 queue_work(system_long_wq, &info->role_work);
0301
0302 return NOTIFY_OK;
0303 }
0304
0305 static irqreturn_t axp288_extcon_isr(int irq, void *data)
0306 {
0307 struct axp288_extcon_info *info = data;
0308 int ret;
0309
0310 ret = axp288_handle_chrg_det_event(info);
0311 if (ret < 0)
0312 dev_err(info->dev, "failed to handle the interrupt\n");
0313
0314 return IRQ_HANDLED;
0315 }
0316
0317 static int axp288_extcon_enable(struct axp288_extcon_info *info)
0318 {
0319 int ret = 0;
0320
0321 ret = iosf_mbi_block_punit_i2c_access();
0322 if (ret < 0)
0323 return ret;
0324
0325 regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
0326 BC_GLOBAL_RUN, 0);
0327
0328 regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
0329 BC_GLOBAL_RUN, BC_GLOBAL_RUN);
0330
0331 iosf_mbi_unblock_punit_i2c_access();
0332
0333 return ret;
0334 }
0335
0336 static void axp288_put_role_sw(void *data)
0337 {
0338 struct axp288_extcon_info *info = data;
0339
0340 cancel_work_sync(&info->role_work);
0341 usb_role_switch_put(info->role_sw);
0342 }
0343
0344 static int axp288_extcon_find_role_sw(struct axp288_extcon_info *info)
0345 {
0346 const struct software_node *swnode;
0347 struct fwnode_handle *fwnode;
0348
0349 if (!x86_match_cpu(cherry_trail_cpu_ids))
0350 return 0;
0351
0352 swnode = software_node_find_by_name(NULL, "intel-xhci-usb-sw");
0353 if (!swnode)
0354 return -EPROBE_DEFER;
0355
0356 fwnode = software_node_fwnode(swnode);
0357 info->role_sw = usb_role_switch_find_by_fwnode(fwnode);
0358 fwnode_handle_put(fwnode);
0359
0360 return info->role_sw ? 0 : -EPROBE_DEFER;
0361 }
0362
0363 static int axp288_extcon_probe(struct platform_device *pdev)
0364 {
0365 struct axp288_extcon_info *info;
0366 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
0367 struct device *dev = &pdev->dev;
0368 struct acpi_device *adev;
0369 int ret, i, pirq;
0370
0371 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0372 if (!info)
0373 return -ENOMEM;
0374
0375 info->dev = &pdev->dev;
0376 info->regmap = axp20x->regmap;
0377 info->regmap_irqc = axp20x->regmap_irqc;
0378 info->previous_cable = EXTCON_NONE;
0379 INIT_WORK(&info->role_work, axp288_usb_role_work);
0380 info->id_nb.notifier_call = axp288_extcon_id_evt;
0381
0382 platform_set_drvdata(pdev, info);
0383
0384 ret = axp288_extcon_find_role_sw(info);
0385 if (ret)
0386 return ret;
0387
0388 if (info->role_sw) {
0389 ret = devm_add_action_or_reset(dev, axp288_put_role_sw, info);
0390 if (ret)
0391 return ret;
0392
0393 adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1);
0394 if (adev) {
0395 info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev));
0396 put_device(&adev->dev);
0397 if (IS_ERR(info->id_extcon))
0398 return PTR_ERR(info->id_extcon);
0399
0400 dev_info(dev, "controlling USB role\n");
0401 } else {
0402 dev_info(dev, "controlling USB role based on Vbus presence\n");
0403 }
0404 }
0405
0406 ret = iosf_mbi_block_punit_i2c_access();
0407 if (ret < 0)
0408 return ret;
0409
0410 info->vbus_attach = axp288_get_vbus_attach(info);
0411
0412 axp288_extcon_log_rsi(info);
0413
0414 iosf_mbi_unblock_punit_i2c_access();
0415
0416
0417 info->edev = devm_extcon_dev_allocate(&pdev->dev,
0418 axp288_extcon_cables);
0419 if (IS_ERR(info->edev)) {
0420 dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
0421 return PTR_ERR(info->edev);
0422 }
0423
0424
0425 ret = devm_extcon_dev_register(&pdev->dev, info->edev);
0426 if (ret) {
0427 dev_err(&pdev->dev, "failed to register extcon device\n");
0428 return ret;
0429 }
0430
0431 for (i = 0; i < EXTCON_IRQ_END; i++) {
0432 pirq = platform_get_irq(pdev, i);
0433 if (pirq < 0)
0434 return pirq;
0435
0436 info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
0437 if (info->irq[i] < 0) {
0438 dev_err(&pdev->dev,
0439 "failed to get virtual interrupt=%d\n", pirq);
0440 ret = info->irq[i];
0441 return ret;
0442 }
0443
0444 ret = devm_request_threaded_irq(&pdev->dev, info->irq[i],
0445 NULL, axp288_extcon_isr,
0446 IRQF_ONESHOT | IRQF_NO_SUSPEND,
0447 pdev->name, info);
0448 if (ret) {
0449 dev_err(&pdev->dev, "failed to request interrupt=%d\n",
0450 info->irq[i]);
0451 return ret;
0452 }
0453 }
0454
0455 if (info->id_extcon) {
0456 ret = devm_extcon_register_notifier_all(dev, info->id_extcon,
0457 &info->id_nb);
0458 if (ret)
0459 return ret;
0460 }
0461
0462
0463 if (info->role_sw) {
0464 queue_work(system_long_wq, &info->role_work);
0465 flush_work(&info->role_work);
0466 }
0467
0468
0469 ret = axp288_extcon_enable(info);
0470 if (ret < 0)
0471 return ret;
0472
0473 device_init_wakeup(dev, true);
0474 platform_set_drvdata(pdev, info);
0475
0476 return 0;
0477 }
0478
0479 static int __maybe_unused axp288_extcon_suspend(struct device *dev)
0480 {
0481 struct axp288_extcon_info *info = dev_get_drvdata(dev);
0482
0483 if (device_may_wakeup(dev))
0484 enable_irq_wake(info->irq[VBUS_RISING_IRQ]);
0485
0486 return 0;
0487 }
0488
0489 static int __maybe_unused axp288_extcon_resume(struct device *dev)
0490 {
0491 struct axp288_extcon_info *info = dev_get_drvdata(dev);
0492
0493
0494
0495
0496
0497
0498 if (device_may_wakeup(dev))
0499 disable_irq_wake(info->irq[VBUS_RISING_IRQ]);
0500
0501 return 0;
0502 }
0503
0504 static SIMPLE_DEV_PM_OPS(axp288_extcon_pm_ops, axp288_extcon_suspend,
0505 axp288_extcon_resume);
0506
0507 static const struct platform_device_id axp288_extcon_table[] = {
0508 { .name = "axp288_extcon" },
0509 {},
0510 };
0511 MODULE_DEVICE_TABLE(platform, axp288_extcon_table);
0512
0513 static struct platform_driver axp288_extcon_driver = {
0514 .probe = axp288_extcon_probe,
0515 .id_table = axp288_extcon_table,
0516 .driver = {
0517 .name = "axp288_extcon",
0518 .pm = &axp288_extcon_pm_ops,
0519 },
0520 };
0521 module_platform_driver(axp288_extcon_driver);
0522
0523 MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
0524 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0525 MODULE_DESCRIPTION("X-Powers AXP288 extcon driver");
0526 MODULE_LICENSE("GPL v2");