hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/power/supply/olpc_battery.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Battery driver for One Laptop Per Child board.
34 *
45 * Copyright © 2006-2010 David Woodhouse <dwmw2@infradead.org>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 */
107
118 #include <linux/kernel.h>
....@@ -14,12 +11,12 @@
1411 #include <linux/types.h>
1512 #include <linux/err.h>
1613 #include <linux/device.h>
14
+#include <linux/of.h>
1715 #include <linux/platform_device.h>
1816 #include <linux/power_supply.h>
1917 #include <linux/jiffies.h>
2018 #include <linux/sched.h>
2119 #include <linux/olpc-ec.h>
22
-#include <asm/olpc.h>
2320
2421
2522 #define EC_BAT_VOLTAGE 0x10 /* uint16_t, *9.76/32, mV */
....@@ -52,6 +49,14 @@
5249
5350 #define BAT_ADDR_MFR_TYPE 0x5F
5451
52
+struct olpc_battery_data {
53
+ struct power_supply *olpc_ac;
54
+ struct power_supply *olpc_bat;
55
+ char bat_serial[17];
56
+ bool new_proto;
57
+ bool little_endian;
58
+};
59
+
5560 /*********************************************************************
5661 * Power
5762 *********************************************************************/
....@@ -83,20 +88,17 @@
8388 };
8489
8590 static const struct power_supply_desc olpc_ac_desc = {
86
- .name = "olpc-ac",
91
+ .name = "olpc_ac",
8792 .type = POWER_SUPPLY_TYPE_MAINS,
8893 .properties = olpc_ac_props,
8994 .num_properties = ARRAY_SIZE(olpc_ac_props),
9095 .get_property = olpc_ac_get_prop,
9196 };
9297
93
-static struct power_supply *olpc_ac;
94
-
95
-static char bat_serial[17]; /* Ick */
96
-
97
-static int olpc_bat_get_status(union power_supply_propval *val, uint8_t ec_byte)
98
+static int olpc_bat_get_status(struct olpc_battery_data *data,
99
+ union power_supply_propval *val, uint8_t ec_byte)
98100 {
99
- if (olpc_platform_info.ecver > 0x44) {
101
+ if (data->new_proto) {
100102 if (ec_byte & (BAT_STAT_CHARGING | BAT_STAT_TRICKLE))
101103 val->intval = POWER_SUPPLY_STATUS_CHARGING;
102104 else if (ec_byte & BAT_STAT_DISCHARGING)
....@@ -318,6 +320,14 @@
318320 return ret;
319321 }
320322
323
+static u16 ecword_to_cpu(struct olpc_battery_data *data, u16 ec_word)
324
+{
325
+ if (data->little_endian)
326
+ return le16_to_cpu((__force __le16)ec_word);
327
+ else
328
+ return be16_to_cpu((__force __be16)ec_word);
329
+}
330
+
321331 /*********************************************************************
322332 * Battery properties
323333 *********************************************************************/
....@@ -325,8 +335,9 @@
325335 enum power_supply_property psp,
326336 union power_supply_propval *val)
327337 {
338
+ struct olpc_battery_data *data = power_supply_get_drvdata(psy);
328339 int ret = 0;
329
- __be16 ec_word;
340
+ u16 ec_word;
330341 uint8_t ec_byte;
331342 __be64 ser_buf;
332343
....@@ -346,7 +357,7 @@
346357
347358 switch (psp) {
348359 case POWER_SUPPLY_PROP_STATUS:
349
- ret = olpc_bat_get_status(val, ec_byte);
360
+ ret = olpc_bat_get_status(data, val, ec_byte);
350361 if (ret)
351362 return ret;
352363 break;
....@@ -389,7 +400,7 @@
389400 if (ret)
390401 return ret;
391402
392
- val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32;
403
+ val->intval = ecword_to_cpu(data, ec_word) * 9760L / 32;
393404 break;
394405 case POWER_SUPPLY_PROP_CURRENT_AVG:
395406 case POWER_SUPPLY_PROP_CURRENT_NOW:
....@@ -397,7 +408,7 @@
397408 if (ret)
398409 return ret;
399410
400
- val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120;
411
+ val->intval = ecword_to_cpu(data, ec_word) * 15625L / 120;
401412 break;
402413 case POWER_SUPPLY_PROP_CAPACITY:
403414 ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
....@@ -428,29 +439,29 @@
428439 if (ret)
429440 return ret;
430441
431
- val->intval = (s16)be16_to_cpu(ec_word) * 10 / 256;
442
+ val->intval = ecword_to_cpu(data, ec_word) * 10 / 256;
432443 break;
433444 case POWER_SUPPLY_PROP_TEMP_AMBIENT:
434445 ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
435446 if (ret)
436447 return ret;
437448
438
- val->intval = (int)be16_to_cpu(ec_word) * 10 / 256;
449
+ val->intval = (int)ecword_to_cpu(data, ec_word) * 10 / 256;
439450 break;
440451 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
441452 ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2);
442453 if (ret)
443454 return ret;
444455
445
- val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15;
456
+ val->intval = ecword_to_cpu(data, ec_word) * 6250 / 15;
446457 break;
447458 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
448459 ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
449460 if (ret)
450461 return ret;
451462
452
- sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf));
453
- val->strval = bat_serial;
463
+ sprintf(data->bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf));
464
+ val->strval = data->bat_serial;
454465 break;
455466 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
456467 ret = olpc_bat_get_voltage_max_design(val);
....@@ -536,7 +547,7 @@
536547 return count;
537548 }
538549
539
-static const struct bin_attribute olpc_bat_eeprom = {
550
+static struct bin_attribute olpc_bat_eeprom = {
540551 .attr = {
541552 .name = "eeprom",
542553 .mode = S_IRUGO,
....@@ -560,7 +571,7 @@
560571 return sprintf(buf, "%d\n", ec_byte);
561572 }
562573
563
-static const struct device_attribute olpc_bat_error = {
574
+static struct device_attribute olpc_bat_error = {
564575 .attr = {
565576 .name = "error",
566577 .mode = S_IRUGO,
....@@ -568,27 +579,48 @@
568579 .show = olpc_bat_error_read,
569580 };
570581
582
+static struct attribute *olpc_bat_sysfs_attrs[] = {
583
+ &olpc_bat_error.attr,
584
+ NULL
585
+};
586
+
587
+static struct bin_attribute *olpc_bat_sysfs_bin_attrs[] = {
588
+ &olpc_bat_eeprom,
589
+ NULL
590
+};
591
+
592
+static const struct attribute_group olpc_bat_sysfs_group = {
593
+ .attrs = olpc_bat_sysfs_attrs,
594
+ .bin_attrs = olpc_bat_sysfs_bin_attrs,
595
+
596
+};
597
+
598
+static const struct attribute_group *olpc_bat_sysfs_groups[] = {
599
+ &olpc_bat_sysfs_group,
600
+ NULL
601
+};
602
+
571603 /*********************************************************************
572604 * Initialisation
573605 *********************************************************************/
574606
575607 static struct power_supply_desc olpc_bat_desc = {
576
- .name = "olpc-battery",
608
+ .name = "olpc_battery",
577609 .get_property = olpc_bat_get_property,
578610 .use_for_apm = 1,
579611 };
580612
581
-static struct power_supply *olpc_bat;
582
-
583613 static int olpc_battery_suspend(struct platform_device *pdev,
584614 pm_message_t state)
585615 {
586
- if (device_may_wakeup(&olpc_ac->dev))
616
+ struct olpc_battery_data *data = platform_get_drvdata(pdev);
617
+
618
+ if (device_may_wakeup(&data->olpc_ac->dev))
587619 olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR);
588620 else
589621 olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR);
590622
591
- if (device_may_wakeup(&olpc_bat->dev))
623
+ if (device_may_wakeup(&data->olpc_bat->dev))
592624 olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
593625 | EC_SCI_SRC_BATERR);
594626 else
....@@ -600,16 +632,37 @@
600632
601633 static int olpc_battery_probe(struct platform_device *pdev)
602634 {
603
- int ret;
635
+ struct power_supply_config bat_psy_cfg = {};
636
+ struct power_supply_config ac_psy_cfg = {};
637
+ struct olpc_battery_data *data;
604638 uint8_t status;
639
+ uint8_t ecver;
640
+ int ret;
605641
606
- /*
607
- * We've seen a number of EC protocol changes; this driver requires
608
- * the latest EC protocol, supported by 0x44 and above.
609
- */
610
- if (olpc_platform_info.ecver < 0x44) {
642
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
643
+ if (!data)
644
+ return -ENOMEM;
645
+ platform_set_drvdata(pdev, data);
646
+
647
+ /* See if the EC is already there and get the EC revision */
648
+ ret = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ecver, 1);
649
+ if (ret)
650
+ return ret;
651
+
652
+ if (of_find_compatible_node(NULL, NULL, "olpc,xo1.75-ec")) {
653
+ /* XO 1.75 */
654
+ data->new_proto = true;
655
+ data->little_endian = true;
656
+ } else if (ecver > 0x44) {
657
+ /* XO 1 or 1.5 with a new EC firmware. */
658
+ data->new_proto = true;
659
+ } else if (ecver < 0x44) {
660
+ /*
661
+ * We've seen a number of EC protocol changes; this driver
662
+ * requires the latest EC protocol, supported by 0x44 and above.
663
+ */
611664 printk(KERN_NOTICE "OLPC EC version 0x%02x too old for "
612
- "battery driver.\n", olpc_platform_info.ecver);
665
+ "battery driver.\n", ecver);
613666 return -ENXIO;
614667 }
615668
....@@ -619,59 +672,44 @@
619672
620673 /* Ignore the status. It doesn't actually matter */
621674
622
- olpc_ac = power_supply_register(&pdev->dev, &olpc_ac_desc, NULL);
623
- if (IS_ERR(olpc_ac))
624
- return PTR_ERR(olpc_ac);
675
+ ac_psy_cfg.of_node = pdev->dev.of_node;
676
+ ac_psy_cfg.drv_data = data;
625677
626
- if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */
678
+ data->olpc_ac = devm_power_supply_register(&pdev->dev, &olpc_ac_desc,
679
+ &ac_psy_cfg);
680
+ if (IS_ERR(data->olpc_ac))
681
+ return PTR_ERR(data->olpc_ac);
682
+
683
+ if (of_device_is_compatible(pdev->dev.of_node, "olpc,xo1.5-battery")) {
684
+ /* XO-1.5 */
627685 olpc_bat_desc.properties = olpc_xo15_bat_props;
628686 olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
629
- } else { /* XO-1 */
687
+ } else {
688
+ /* XO-1 */
630689 olpc_bat_desc.properties = olpc_xo1_bat_props;
631690 olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
632691 }
633692
634
- olpc_bat = power_supply_register(&pdev->dev, &olpc_bat_desc, NULL);
635
- if (IS_ERR(olpc_bat)) {
636
- ret = PTR_ERR(olpc_bat);
637
- goto battery_failed;
638
- }
693
+ bat_psy_cfg.of_node = pdev->dev.of_node;
694
+ bat_psy_cfg.drv_data = data;
695
+ bat_psy_cfg.attr_grp = olpc_bat_sysfs_groups;
639696
640
- ret = device_create_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
641
- if (ret)
642
- goto eeprom_failed;
643
-
644
- ret = device_create_file(&olpc_bat->dev, &olpc_bat_error);
645
- if (ret)
646
- goto error_failed;
697
+ data->olpc_bat = devm_power_supply_register(&pdev->dev, &olpc_bat_desc,
698
+ &bat_psy_cfg);
699
+ if (IS_ERR(data->olpc_bat))
700
+ return PTR_ERR(data->olpc_bat);
647701
648702 if (olpc_ec_wakeup_available()) {
649
- device_set_wakeup_capable(&olpc_ac->dev, true);
650
- device_set_wakeup_capable(&olpc_bat->dev, true);
703
+ device_set_wakeup_capable(&data->olpc_ac->dev, true);
704
+ device_set_wakeup_capable(&data->olpc_bat->dev, true);
651705 }
652706
653
- return 0;
654
-
655
-error_failed:
656
- device_remove_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
657
-eeprom_failed:
658
- power_supply_unregister(olpc_bat);
659
-battery_failed:
660
- power_supply_unregister(olpc_ac);
661
- return ret;
662
-}
663
-
664
-static int olpc_battery_remove(struct platform_device *pdev)
665
-{
666
- device_remove_file(&olpc_bat->dev, &olpc_bat_error);
667
- device_remove_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
668
- power_supply_unregister(olpc_bat);
669
- power_supply_unregister(olpc_ac);
670707 return 0;
671708 }
672709
673710 static const struct of_device_id olpc_battery_ids[] = {
674711 { .compatible = "olpc,xo1-battery" },
712
+ { .compatible = "olpc,xo1.5-battery" },
675713 {}
676714 };
677715 MODULE_DEVICE_TABLE(of, olpc_battery_ids);
....@@ -682,7 +720,6 @@
682720 .of_match_table = olpc_battery_ids,
683721 },
684722 .probe = olpc_battery_probe,
685
- .remove = olpc_battery_remove,
686723 .suspend = olpc_battery_suspend,
687724 };
688725