• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Unionman Technology Co., Ltd.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include <linux/init.h>
20 #include <linux/module.h>
21 #include <linux/power_supply.h>
22 
23 struct ac_data {
24     struct power_supply_desc psd;
25     struct power_supply *psy;
26 };
27 
28 struct battery_data {
29     struct power_supply_desc psd;
30     struct power_supply *psy;
31 };
32 
33 static enum power_supply_property ac_props[] = {
34     POWER_SUPPLY_PROP_ONLINE,
35 };
36 
37 static enum power_supply_property battery_props[] = {
38     POWER_SUPPLY_PROP_STATUS,      POWER_SUPPLY_PROP_HEALTH,         POWER_SUPPLY_PROP_PRESENT,
39     POWER_SUPPLY_PROP_CAPACITY,    POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_CHARGE_NOW,
40     POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CURRENT_AVG,    POWER_SUPPLY_PROP_CURRENT_NOW,
41     POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_VOLTAGE_MAX,    POWER_SUPPLY_PROP_VOLTAGE_NOW,
42     POWER_SUPPLY_PROP_VOLTAGE_AVG, POWER_SUPPLY_PROP_TECHNOLOGY,     POWER_SUPPLY_PROP_TEMP,
43     POWER_SUPPLY_PROP_TEMP_MIN,    POWER_SUPPLY_PROP_TEMP_MAX,
44 };
45 
ac_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)46 static int ac_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val)
47 {
48     int ret = 0;
49 
50     switch (psp) {
51         case POWER_SUPPLY_PROP_ONLINE:
52             val->intval = 1;
53             break;
54         default:
55             ret = -EINVAL;
56             break;
57     }
58 
59     return ret;
60 }
61 
battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)62 static int battery_get_property(struct power_supply *psy, enum power_supply_property psp,
63                                 union power_supply_propval *val)
64 {
65     int ret = 0;
66 
67     if (psp == POWER_SUPPLY_PROP_STATUS) {
68         val->intval = POWER_SUPPLY_STATUS_CHARGING;
69     } else if (psp == POWER_SUPPLY_PROP_HEALTH) {
70         val->intval = POWER_SUPPLY_HEALTH_GOOD;
71     } else if (psp == POWER_SUPPLY_PROP_PRESENT) {
72         val->intval = 0;
73     } else if (psp == POWER_SUPPLY_PROP_CAPACITY) {
74         val->intval = 100L;
75     } else if ((psp == POWER_SUPPLY_PROP_CHARGE_COUNTER) || (psp == POWER_SUPPLY_PROP_CHARGE_FULL)) {
76         val->intval = 3000L * 1000L;
77     } else if (psp == POWER_SUPPLY_PROP_CHARGE_NOW) {
78         val->intval = 3000L * 1000L;
79     } else if ((psp == POWER_SUPPLY_PROP_VOLTAGE_NOW) || (psp == POWER_SUPPLY_PROP_VOLTAGE_AVG)) {
80         val->intval = 4200L * 1000L;
81     } else if (psp == POWER_SUPPLY_PROP_TEMP) {
82         val->intval = 25L;
83     } else if (psp == POWER_SUPPLY_PROP_TEMP_MIN) {
84         val->intval = -40L;
85     } else if (psp == POWER_SUPPLY_PROP_TEMP_MAX) {
86         val->intval = 100L;
87     } else if (psp == POWER_SUPPLY_PROP_CURRENT_AVG) {
88         val->intval = 4200L * 1000L;
89     } else if (psp == POWER_SUPPLY_PROP_CURRENT_NOW) {
90         val->intval = 100L * 1000L;
91     } else if (psp == POWER_SUPPLY_PROP_CURRENT_MAX) {
92         val->intval = 3000000L;
93     } else if (psp == POWER_SUPPLY_PROP_VOLTAGE_MAX) {
94         val->intval = 5000000L;
95     } else if (psp == POWER_SUPPLY_PROP_TECHNOLOGY) {
96         val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
97     } else {
98         ret = -EINVAL;
99     }
100 
101     return ret;
102 }
103 
104 static struct ac_data ac_main = {
105     .psd =
106         {
107             .name = "ac",
108             .type = POWER_SUPPLY_TYPE_MAINS,
109             .properties = ac_props,
110             .num_properties = ARRAY_SIZE(ac_props),
111             .get_property = ac_get_property,
112         },
113 };
114 
115 static struct battery_data battery_main = {
116     .psd =
117         {
118             .name = "battery",
119             .type = POWER_SUPPLY_TYPE_BATTERY,
120             .properties = battery_props,
121             .num_properties = ARRAY_SIZE(battery_props),
122             .get_property = battery_get_property,
123         },
124 };
125 
aml_battery_init(void)126 static int __init aml_battery_init(void)
127 {
128     ac_main.psy = power_supply_register(NULL, &ac_main.psd, NULL);
129     if (IS_ERR(ac_main.psy)) {
130         pr_debug("[%s] power_supply_register AC Fail !!\n", __func__);
131         return -1;
132     }
133 
134     battery_main.psy = power_supply_register(NULL, &battery_main.psd, NULL);
135     if (IS_ERR(battery_main.psy)) {
136         pr_debug("[%s] power_supply_register Battery Fail !!\n", __func__);
137         return -1;
138     }
139 
140     pr_debug("power_supply_register AC/Battery Success !!\n");
141 
142     return 0;
143 }
144 
aml_battery_exit(void)145 static void __exit aml_battery_exit(void)
146 {
147     power_supply_unregister(battery_main.psy);
148 }
149 
150 module_init(aml_battery_init);
151 module_exit(aml_battery_exit);
152 
153 MODULE_AUTHOR("AlgoIdeas <yu19881234@163.com>");
154 MODULE_LICENSE("GPL");
155 MODULE_DESCRIPTION("Battery driver for Amlogic");