.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * extcon-axp288.c - X-Power AXP288 PMIC extcon cable detection driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2017-2018 Hans de Goede <hdegoede@redhat.com> |
---|
5 | 6 | * Copyright (C) 2015 Intel Corporation |
---|
6 | 7 | * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | 8 | */ |
---|
17 | 9 | |
---|
18 | 10 | #include <linux/acpi.h> |
---|
.. | .. |
---|
115 | 107 | }; |
---|
116 | 108 | |
---|
117 | 109 | static const struct x86_cpu_id cherry_trail_cpu_ids[] = { |
---|
118 | | - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT, X86_FEATURE_ANY }, |
---|
| 110 | + X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL), |
---|
119 | 111 | {} |
---|
120 | 112 | }; |
---|
121 | 113 | |
---|
.. | .. |
---|
129 | 121 | "Last shutdown caused by PMIC UVLO threshold", |
---|
130 | 122 | "Last shutdown caused by SOC initiated cold off", |
---|
131 | 123 | "Last shutdown caused by user pressing the power button", |
---|
132 | | - NULL, |
---|
133 | 124 | }; |
---|
134 | 125 | |
---|
135 | 126 | /* |
---|
.. | .. |
---|
138 | 129 | */ |
---|
139 | 130 | static void axp288_extcon_log_rsi(struct axp288_extcon_info *info) |
---|
140 | 131 | { |
---|
141 | | - const char * const *rsi; |
---|
142 | 132 | unsigned int val, i, clear_mask = 0; |
---|
| 133 | + unsigned long bits; |
---|
143 | 134 | int ret; |
---|
144 | 135 | |
---|
145 | 136 | ret = regmap_read(info->regmap, AXP288_PS_BOOT_REASON_REG, &val); |
---|
146 | | - for (i = 0, rsi = axp288_pwr_up_down_info; *rsi; rsi++, i++) { |
---|
147 | | - if (val & BIT(i)) { |
---|
148 | | - dev_dbg(info->dev, "%s\n", *rsi); |
---|
149 | | - clear_mask |= BIT(i); |
---|
150 | | - } |
---|
| 137 | + if (ret < 0) { |
---|
| 138 | + dev_err(info->dev, "failed to read reset source indicator\n"); |
---|
| 139 | + return; |
---|
151 | 140 | } |
---|
| 141 | + |
---|
| 142 | + bits = val & GENMASK(ARRAY_SIZE(axp288_pwr_up_down_info) - 1, 0); |
---|
| 143 | + for_each_set_bit(i, &bits, ARRAY_SIZE(axp288_pwr_up_down_info)) |
---|
| 144 | + dev_dbg(info->dev, "%s\n", axp288_pwr_up_down_info[i]); |
---|
| 145 | + clear_mask = bits; |
---|
152 | 146 | |
---|
153 | 147 | /* Clear the register value for next reboot (write 1 to clear bit) */ |
---|
154 | 148 | regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask); |
---|
.. | .. |
---|
328 | 322 | usb_role_switch_put(info->role_sw); |
---|
329 | 323 | } |
---|
330 | 324 | |
---|
| 325 | +static int axp288_extcon_find_role_sw(struct axp288_extcon_info *info) |
---|
| 326 | +{ |
---|
| 327 | + const struct software_node *swnode; |
---|
| 328 | + struct fwnode_handle *fwnode; |
---|
| 329 | + |
---|
| 330 | + if (!x86_match_cpu(cherry_trail_cpu_ids)) |
---|
| 331 | + return 0; |
---|
| 332 | + |
---|
| 333 | + swnode = software_node_find_by_name(NULL, "intel-xhci-usb-sw"); |
---|
| 334 | + if (!swnode) |
---|
| 335 | + return -EPROBE_DEFER; |
---|
| 336 | + |
---|
| 337 | + fwnode = software_node_fwnode(swnode); |
---|
| 338 | + info->role_sw = usb_role_switch_find_by_fwnode(fwnode); |
---|
| 339 | + fwnode_handle_put(fwnode); |
---|
| 340 | + |
---|
| 341 | + return info->role_sw ? 0 : -EPROBE_DEFER; |
---|
| 342 | +} |
---|
| 343 | + |
---|
331 | 344 | static int axp288_extcon_probe(struct platform_device *pdev) |
---|
332 | 345 | { |
---|
333 | 346 | struct axp288_extcon_info *info; |
---|
334 | 347 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); |
---|
335 | 348 | struct device *dev = &pdev->dev; |
---|
336 | | - const char *name; |
---|
| 349 | + struct acpi_device *adev; |
---|
337 | 350 | int ret, i, pirq; |
---|
338 | 351 | |
---|
339 | 352 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
---|
.. | .. |
---|
349 | 362 | |
---|
350 | 363 | platform_set_drvdata(pdev, info); |
---|
351 | 364 | |
---|
352 | | - info->role_sw = usb_role_switch_get(dev); |
---|
353 | | - if (IS_ERR(info->role_sw)) |
---|
354 | | - return PTR_ERR(info->role_sw); |
---|
| 365 | + ret = axp288_extcon_find_role_sw(info); |
---|
| 366 | + if (ret) |
---|
| 367 | + return ret; |
---|
| 368 | + |
---|
355 | 369 | if (info->role_sw) { |
---|
356 | 370 | ret = devm_add_action_or_reset(dev, axp288_put_role_sw, info); |
---|
357 | 371 | if (ret) |
---|
358 | 372 | return ret; |
---|
359 | 373 | |
---|
360 | | - name = acpi_dev_get_first_match_name("INT3496", NULL, -1); |
---|
361 | | - if (name) { |
---|
362 | | - info->id_extcon = extcon_get_extcon_dev(name); |
---|
| 374 | + adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1); |
---|
| 375 | + if (adev) { |
---|
| 376 | + info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev)); |
---|
| 377 | + put_device(&adev->dev); |
---|
363 | 378 | if (!info->id_extcon) |
---|
364 | 379 | return -EPROBE_DEFER; |
---|
365 | 380 | |
---|
.. | .. |
---|
476 | 491 | .pm = &axp288_extcon_pm_ops, |
---|
477 | 492 | }, |
---|
478 | 493 | }; |
---|
479 | | - |
---|
480 | | -static struct device_connection axp288_extcon_role_sw_conn = { |
---|
481 | | - .endpoint[0] = "axp288_extcon", |
---|
482 | | - .endpoint[1] = "intel_xhci_usb_sw-role-switch", |
---|
483 | | - .id = "usb-role-switch", |
---|
484 | | -}; |
---|
485 | | - |
---|
486 | | -static int __init axp288_extcon_init(void) |
---|
487 | | -{ |
---|
488 | | - if (x86_match_cpu(cherry_trail_cpu_ids)) |
---|
489 | | - device_connection_add(&axp288_extcon_role_sw_conn); |
---|
490 | | - |
---|
491 | | - return platform_driver_register(&axp288_extcon_driver); |
---|
492 | | -} |
---|
493 | | -module_init(axp288_extcon_init); |
---|
494 | | - |
---|
495 | | -static void __exit axp288_extcon_exit(void) |
---|
496 | | -{ |
---|
497 | | - if (x86_match_cpu(cherry_trail_cpu_ids)) |
---|
498 | | - device_connection_remove(&axp288_extcon_role_sw_conn); |
---|
499 | | - |
---|
500 | | - platform_driver_unregister(&axp288_extcon_driver); |
---|
501 | | -} |
---|
502 | | -module_exit(axp288_extcon_exit); |
---|
| 494 | +module_platform_driver(axp288_extcon_driver); |
---|
503 | 495 | |
---|
504 | 496 | MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>"); |
---|
505 | 497 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); |
---|