extcon-axp288.c (cbecf716ca618fd44feda6bd9a64a8179d031fc5) extcon-axp288.c (968bd3f0388b8eaf6746336856348dc3ddf2ed39)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * extcon-axp288.c - X-Power AXP288 PMIC extcon cable detection driver
4 *
5 * Copyright (c) 2017-2018 Hans de Goede <hdegoede@redhat.com>
6 * Copyright (C) 2015 Intel Corporation
7 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
8 */

--- 10 unchanged lines hidden (view full) ---

19#include <linux/extcon-provider.h>
20#include <linux/regmap.h>
21#include <linux/mfd/axp20x.h>
22#include <linux/usb/role.h>
23#include <linux/workqueue.h>
24
25#include <asm/cpu_device_id.h>
26#include <asm/intel-family.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * extcon-axp288.c - X-Power AXP288 PMIC extcon cable detection driver
4 *
5 * Copyright (c) 2017-2018 Hans de Goede <hdegoede@redhat.com>
6 * Copyright (C) 2015 Intel Corporation
7 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
8 */

--- 10 unchanged lines hidden (view full) ---

19#include <linux/extcon-provider.h>
20#include <linux/regmap.h>
21#include <linux/mfd/axp20x.h>
22#include <linux/usb/role.h>
23#include <linux/workqueue.h>
24
25#include <asm/cpu_device_id.h>
26#include <asm/intel-family.h>
27#include <asm/iosf_mbi.h>
27
28/* Power source status register */
29#define PS_STAT_VBUS_TRIGGER BIT(0)
30#define PS_STAT_BAT_CHRG_DIR BIT(2)
31#define PS_STAT_VBUS_ABOVE_VHOLD BIT(3)
32#define PS_STAT_VBUS_VALID BIT(4)
33#define PS_STAT_VBUS_PRESENT BIT(5)
34

--- 175 unchanged lines hidden (view full) ---

210
211static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
212{
213 int ret, stat, cfg;
214 u8 chrg_type;
215 unsigned int cable = info->previous_cable;
216 bool vbus_attach = false;
217
28
29/* Power source status register */
30#define PS_STAT_VBUS_TRIGGER BIT(0)
31#define PS_STAT_BAT_CHRG_DIR BIT(2)
32#define PS_STAT_VBUS_ABOVE_VHOLD BIT(3)
33#define PS_STAT_VBUS_VALID BIT(4)
34#define PS_STAT_VBUS_PRESENT BIT(5)
35

--- 175 unchanged lines hidden (view full) ---

211
212static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
213{
214 int ret, stat, cfg;
215 u8 chrg_type;
216 unsigned int cable = info->previous_cable;
217 bool vbus_attach = false;
218
219 ret = iosf_mbi_block_punit_i2c_access();
220 if (ret < 0)
221 return ret;
222
218 vbus_attach = axp288_get_vbus_attach(info);
219 if (!vbus_attach)
220 goto no_vbus;
221
222 /* Check charger detection completion status */
223 ret = regmap_read(info->regmap, AXP288_BC_GLOBAL_REG, &cfg);
224 if (ret < 0)
225 goto dev_det_ret;

--- 22 unchanged lines hidden (view full) ---

248 cable = EXTCON_CHG_USB_DCP;
249 break;
250 default:
251 dev_warn(info->dev, "unknown (reserved) bc detect result\n");
252 cable = EXTCON_CHG_USB_SDP;
253 }
254
255no_vbus:
223 vbus_attach = axp288_get_vbus_attach(info);
224 if (!vbus_attach)
225 goto no_vbus;
226
227 /* Check charger detection completion status */
228 ret = regmap_read(info->regmap, AXP288_BC_GLOBAL_REG, &cfg);
229 if (ret < 0)
230 goto dev_det_ret;

--- 22 unchanged lines hidden (view full) ---

253 cable = EXTCON_CHG_USB_DCP;
254 break;
255 default:
256 dev_warn(info->dev, "unknown (reserved) bc detect result\n");
257 cable = EXTCON_CHG_USB_SDP;
258 }
259
260no_vbus:
261 iosf_mbi_unblock_punit_i2c_access();
262
256 extcon_set_state_sync(info->edev, info->previous_cable, false);
257 if (info->previous_cable == EXTCON_CHG_USB_SDP)
258 extcon_set_state_sync(info->edev, EXTCON_USB, false);
259
260 if (vbus_attach) {
261 extcon_set_state_sync(info->edev, cable, vbus_attach);
262 if (cable == EXTCON_CHG_USB_SDP)
263 extcon_set_state_sync(info->edev, EXTCON_USB,

--- 6 unchanged lines hidden (view full) ---

270 info->vbus_attach = vbus_attach;
271 /* Setting the role can take a while */
272 queue_work(system_long_wq, &info->role_work);
273 }
274
275 return 0;
276
277dev_det_ret:
263 extcon_set_state_sync(info->edev, info->previous_cable, false);
264 if (info->previous_cable == EXTCON_CHG_USB_SDP)
265 extcon_set_state_sync(info->edev, EXTCON_USB, false);
266
267 if (vbus_attach) {
268 extcon_set_state_sync(info->edev, cable, vbus_attach);
269 if (cable == EXTCON_CHG_USB_SDP)
270 extcon_set_state_sync(info->edev, EXTCON_USB,

--- 6 unchanged lines hidden (view full) ---

277 info->vbus_attach = vbus_attach;
278 /* Setting the role can take a while */
279 queue_work(system_long_wq, &info->role_work);
280 }
281
282 return 0;
283
284dev_det_ret:
285 iosf_mbi_unblock_punit_i2c_access();
286
278 if (ret < 0)
279 dev_err(info->dev, "failed to detect BC Mod\n");
280
281 return ret;
282}
283
284static int axp288_extcon_id_evt(struct notifier_block *nb,
285 unsigned long event, void *param)

--- 14 unchanged lines hidden (view full) ---

300
301 ret = axp288_handle_chrg_det_event(info);
302 if (ret < 0)
303 dev_err(info->dev, "failed to handle the interrupt\n");
304
305 return IRQ_HANDLED;
306}
307
287 if (ret < 0)
288 dev_err(info->dev, "failed to detect BC Mod\n");
289
290 return ret;
291}
292
293static int axp288_extcon_id_evt(struct notifier_block *nb,
294 unsigned long event, void *param)

--- 14 unchanged lines hidden (view full) ---

309
310 ret = axp288_handle_chrg_det_event(info);
311 if (ret < 0)
312 dev_err(info->dev, "failed to handle the interrupt\n");
313
314 return IRQ_HANDLED;
315}
316
308static void axp288_extcon_enable(struct axp288_extcon_info *info)
317static int axp288_extcon_enable(struct axp288_extcon_info *info)
309{
318{
319 int ret = 0;
320
321 ret = iosf_mbi_block_punit_i2c_access();
322 if (ret < 0)
323 return ret;
324
310 regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
311 BC_GLOBAL_RUN, 0);
312 /* Enable the charger detection logic */
313 regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
314 BC_GLOBAL_RUN, BC_GLOBAL_RUN);
325 regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
326 BC_GLOBAL_RUN, 0);
327 /* Enable the charger detection logic */
328 regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
329 BC_GLOBAL_RUN, BC_GLOBAL_RUN);
330
331 iosf_mbi_unblock_punit_i2c_access();
332
333 return ret;
315}
316
317static void axp288_put_role_sw(void *data)
318{
319 struct axp288_extcon_info *info = data;
320
321 cancel_work_sync(&info->role_work);
322 usb_role_switch_put(info->role_sw);

--- 56 unchanged lines hidden (view full) ---

379 return -EPROBE_DEFER;
380
381 dev_info(dev, "controlling USB role\n");
382 } else {
383 dev_info(dev, "controlling USB role based on Vbus presence\n");
384 }
385 }
386
334}
335
336static void axp288_put_role_sw(void *data)
337{
338 struct axp288_extcon_info *info = data;
339
340 cancel_work_sync(&info->role_work);
341 usb_role_switch_put(info->role_sw);

--- 56 unchanged lines hidden (view full) ---

398 return -EPROBE_DEFER;
399
400 dev_info(dev, "controlling USB role\n");
401 } else {
402 dev_info(dev, "controlling USB role based on Vbus presence\n");
403 }
404 }
405
406 ret = iosf_mbi_block_punit_i2c_access();
407 if (ret < 0)
408 return ret;
409
387 info->vbus_attach = axp288_get_vbus_attach(info);
388
389 axp288_extcon_log_rsi(info);
390
410 info->vbus_attach = axp288_get_vbus_attach(info);
411
412 axp288_extcon_log_rsi(info);
413
414 iosf_mbi_unblock_punit_i2c_access();
415
391 /* Initialize extcon device */
392 info->edev = devm_extcon_dev_allocate(&pdev->dev,
393 axp288_extcon_cables);
394 if (IS_ERR(info->edev)) {
395 dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
396 return PTR_ERR(info->edev);
397 }
398

--- 37 unchanged lines hidden (view full) ---

436
437 /* Make sure the role-sw is set correctly before doing BC detection */
438 if (info->role_sw) {
439 queue_work(system_long_wq, &info->role_work);
440 flush_work(&info->role_work);
441 }
442
443 /* Start charger cable type detection */
416 /* Initialize extcon device */
417 info->edev = devm_extcon_dev_allocate(&pdev->dev,
418 axp288_extcon_cables);
419 if (IS_ERR(info->edev)) {
420 dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
421 return PTR_ERR(info->edev);
422 }
423

--- 37 unchanged lines hidden (view full) ---

461
462 /* Make sure the role-sw is set correctly before doing BC detection */
463 if (info->role_sw) {
464 queue_work(system_long_wq, &info->role_work);
465 flush_work(&info->role_work);
466 }
467
468 /* Start charger cable type detection */
444 axp288_extcon_enable(info);
469 ret = axp288_extcon_enable(info);
470 if (ret < 0)
471 return ret;
445
446 device_init_wakeup(dev, true);
447 platform_set_drvdata(pdev, info);
448
449 return 0;
450}
451
452static int __maybe_unused axp288_extcon_suspend(struct device *dev)

--- 47 unchanged lines hidden ---
472
473 device_init_wakeup(dev, true);
474 platform_set_drvdata(pdev, info);
475
476 return 0;
477}
478
479static int __maybe_unused axp288_extcon_suspend(struct device *dev)

--- 47 unchanged lines hidden ---