@@ -39,8 +39,13 @@ struct macsmc_power {
3939 char model_name [MAX_STRING_LENGTH ];
4040 char serial_number [MAX_STRING_LENGTH ];
4141 char mfg_date [MAX_STRING_LENGTH ];
42+
4243 bool has_chwa ;
4344 bool has_chls ;
45+ bool has_ch0i ;
46+ bool has_ch0c ;
47+ bool has_chte ;
48+
4449 u8 num_cells ;
4550 int nominal_voltage_mv ;
4651
@@ -57,8 +62,8 @@ struct macsmc_power {
5762static int macsmc_log_power_set (const char * val , const struct kernel_param * kp );
5863
5964static const struct kernel_param_ops macsmc_log_power_ops = {
60- .set = macsmc_log_power_set ,
61- .get = param_get_bool ,
65+ .set = macsmc_log_power_set ,
66+ .get = param_get_bool ,
6267};
6368
6469static bool log_power = false;
@@ -242,6 +247,7 @@ static int macsmc_battery_get_status(struct macsmc_power *power)
242247 */
243248 if (power -> has_chls ) {
244249 u16 vu16 ;
250+
245251 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (CHLS ), & vu16 );
246252 if (ret == sizeof (vu16 ) && (vu16 & 0xff ) >= CHLS_MIN_END_THRESHOLD )
247253 charge_limit = (vu16 & 0xff ) - CHWA_CHLS_FIXED_START_OFFSET ;
@@ -253,6 +259,7 @@ static int macsmc_battery_get_status(struct macsmc_power *power)
253259
254260 if (charge_limit > 0 ) {
255261 u8 buic = 0 ;
262+
256263 if (apple_smc_read_u8 (power -> smc , SMC_KEY (BUIC ), & buic ) >= 0 &&
257264 buic >= charge_limit )
258265 limited = true;
@@ -291,55 +298,113 @@ static int macsmc_battery_get_status(struct macsmc_power *power)
291298static int macsmc_battery_get_charge_behaviour (struct macsmc_power * power )
292299{
293300 int ret ;
294- u8 val ;
301+ u8 val8 ;
302+ u8 chte_buf [4 ];
303+
304+ if (power -> has_ch0i ) {
305+ /* CH0I returns a bitmask like the low byte of CH0R */
306+ ret = apple_smc_read_u8 (power -> smc , SMC_KEY (CH0I ), & val8 );
307+ if (ret )
308+ return ret ;
309+ if (val8 & CH0R_NOAC_CH0I )
310+ return POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE ;
311+ }
295312
296- /* CH0I returns a bitmask like the low byte of CH0R */
297- ret = apple_smc_read_u8 (power -> smc , SMC_KEY (CH0I ), & val );
298- if (ret )
299- return ret ;
300- if (val & CH0R_NOAC_CH0I )
301- return POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE ;
313+ /* Prefer CHTE available in newer firmwares */
314+ if (power -> has_chte ) {
315+ ret = apple_smc_read (power -> smc , SMC_KEY (CHTE ), chte_buf , 4 );
316+ if (ret < 0 )
317+ return ret ;
318+
319+ if (chte_buf [0 ] == 0x01 )
320+ return POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE ;
321+
322+ } else if (power -> has_ch0c ) {
323+ /* CH0C returns a bitmask containing CH0B/CH0C flags */
324+ ret = apple_smc_read_u8 (power -> smc , SMC_KEY (CH0C ), & val8 );
325+ if (ret )
326+ return ret ;
327+ if (val8 & CH0X_CH0C )
328+ return POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE ;
329+ }
302330
303- /* CH0C returns a bitmask containing CH0B/CH0C flags */
304- ret = apple_smc_read_u8 (power -> smc , SMC_KEY (CH0C ), & val );
305- if (ret )
306- return ret ;
307- if (val & CH0X_CH0C )
308- return POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE ;
309- else
310- return POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO ;
331+ return POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO ;
311332}
312333
313334static int macsmc_battery_set_charge_behaviour (struct macsmc_power * power , int val )
314335{
315- u8 ch0i , ch0c ;
316336 int ret ;
317337
318338 /*
319- * CH0I/CH0C are "hard" controls that will allow the battery to run down to 0.
339+ * apple_smc_write_u32 does weird things with endianess,
340+ * so we write raw bytes to ensure correctness of CHTE
341+ */
342+ u8 chte_inhibit [4 ] = {0x01 , 0x00 , 0x00 , 0x00 };
343+ u8 chte_auto [4 ] = {0x00 , 0x00 , 0x00 , 0x00 };
344+
345+ /*
346+ * CH0I/CH0C/CHTE are "hard" controls that will allow the battery to run down to 0.
320347 * CH0K/CH0B are "soft" controls that are reset to 0 when SOC drops below 50%;
321348 * we don't expose these yet.
322349 */
323350
324351 switch (val ) {
325352 case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO :
326- ch0i = ch0c = 0 ;
353+ if (power -> has_ch0i ) {
354+ ret = apple_smc_write_u8 (power -> smc , SMC_KEY (CH0I ), 0 );
355+ if (ret )
356+ return ret ;
357+ }
358+
359+ if (power -> has_chte ) {
360+ ret = apple_smc_write (power -> smc , SMC_KEY (CHTE ), chte_auto , 4 );
361+ if (ret )
362+ return ret ;
363+ } else if (power -> has_ch0c ) {
364+ ret = apple_smc_write_u8 (power -> smc , SMC_KEY (CH0C ), 0 );
365+ if (ret )
366+ return ret ;
367+ }
327368 break ;
369+
328370 case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE :
329- ch0i = 0 ;
330- ch0c = 1 ;
371+ if (power -> has_ch0i ) {
372+ ret = apple_smc_write_u8 (power -> smc , SMC_KEY (CH0I ), 0 );
373+ if (ret )
374+ return ret ;
375+ }
376+
377+ /* Prefer CHTE available in newer firmwares */
378+ if (power -> has_chte )
379+ return apple_smc_write (power -> smc , SMC_KEY (CHTE ), chte_inhibit , 4 );
380+ else if (power -> has_ch0c )
381+ return apple_smc_write_u8 (power -> smc , SMC_KEY (CH0C ), 1 );
382+ else
383+ return - EINVAL ;
331384 break ;
385+
332386 case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE :
333- ch0i = 1 ;
334- ch0c = 0 ;
335- break ;
387+ if (!power -> has_ch0i )
388+ return - EINVAL ;
389+
390+ /* Prefer CHTE available in newer firmwares */
391+ if (power -> has_chte ) {
392+ ret = apple_smc_write (power -> smc , SMC_KEY (CHTE ), chte_auto , 4 );
393+ if (ret )
394+ return ret ;
395+ } else if (power -> has_ch0c ) {
396+ ret = apple_smc_write_u8 (power -> smc , SMC_KEY (CH0C ), 0 );
397+ if (ret )
398+ return ret ;
399+ }
400+
401+ return apple_smc_write_u8 (power -> smc , SMC_KEY (CH0I ), 1 );
402+
336403 default :
337404 return - EINVAL ;
338405 }
339- ret = apple_smc_write_u8 (power -> smc , SMC_KEY (CH0I ), ch0i );
340- if (ret )
341- return ret ;
342- return apple_smc_write_u8 (power -> smc , SMC_KEY (CH0C ), ch0c );
406+
407+ return 0 ;
343408}
344409
345410static int macsmc_battery_get_date (const char * s , int * out )
@@ -539,8 +604,7 @@ static int macsmc_battery_get_property(struct power_supply *psy,
539604 val -> intval = vu16 & 0xff ;
540605 if (val -> intval < CHLS_MIN_END_THRESHOLD || val -> intval >= 100 )
541606 val -> intval = 100 ;
542- }
543- else if (power -> has_chwa ) {
607+ } else if (power -> has_chwa ) {
544608 flag = false;
545609 ret = apple_smc_read_flag (power -> smc , SMC_KEY (CHWA ), & flag );
546610 val -> intval = flag ? CHWA_FIXED_END_THRESHOLD : 100 ;
@@ -853,8 +917,9 @@ static int macsmc_power_probe(struct platform_device *pdev)
853917 struct power_supply_config psy_cfg = {};
854918 struct macsmc_power * power ;
855919 bool flag ;
856- u32 val ;
920+ u8 val8 ;
857921 u16 vu16 ;
922+ u32 val32 ;
858923 int ret ;
859924
860925 power = devm_kzalloc (& pdev -> dev , sizeof (* power ), GFP_KERNEL );
@@ -876,10 +941,37 @@ static int macsmc_power_probe(struct platform_device *pdev)
876941 apple_smc_read (smc , SMC_KEY (BMSN ), power -> serial_number , sizeof (power -> serial_number ) - 1 );
877942 apple_smc_read (smc , SMC_KEY (BMDT ), power -> mfg_date , sizeof (power -> mfg_date ) - 1 );
878943
944+ if (apple_smc_read_u32 (power -> smc , SMC_KEY (CHTE ), & val32 ) >= 0 )
945+ power -> has_chte = true;
946+
947+ if (apple_smc_read_u8 (power -> smc , SMC_KEY (CH0C ), & val8 ) >= 0 )
948+ power -> has_ch0c = true;
949+
950+ if (apple_smc_read_u8 (power -> smc , SMC_KEY (CH0I ), & val8 ) >= 0 )
951+ power -> has_ch0i = true;
952+
879953 /* Turn off the "optimized battery charging" flags, in case macOS left them on */
954+ if (power -> has_chte )
955+ apple_smc_write_u32 (power -> smc , SMC_KEY (CHTE ), 0 );
956+ else if (power -> has_ch0c )
957+ apple_smc_write_u8 (power -> smc , SMC_KEY (CH0C ), 0 );
958+
959+ if (power -> has_ch0i )
960+ apple_smc_write_u8 (power -> smc , SMC_KEY (CH0I ), 0 );
961+
880962 apple_smc_write_u8 (power -> smc , SMC_KEY (CH0K ), 0 );
881963 apple_smc_write_u8 (power -> smc , SMC_KEY (CH0B ), 0 );
882964
965+ power -> batt_desc .charge_behaviours = BIT (POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO );
966+
967+ /* Newer firmwares do not have force discharge, so check if it's supported */
968+ if (power -> has_ch0i )
969+ power -> batt_desc .charge_behaviours |= BIT (POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE );
970+
971+ /* Older firmware uses CH0C, and newer firmware uses CHTE, so check if at least one is present*/
972+ if (power -> has_chte || power -> has_ch0c )
973+ power -> batt_desc .charge_behaviours |= BIT (POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE );
974+
883975 /*
884976 * Prefer CHWA as the SMC firmware from iBoot-10151.1.1 is not compatible with
885977 * this CHLS usage.
@@ -897,7 +989,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
897989 power -> nominal_voltage_mv = MACSMC_NOMINAL_CELL_VOLTAGE_MV * power -> num_cells ;
898990
899991 /* Doing one read of this flag enables critical shutdown notifications */
900- apple_smc_read_u32 (power -> smc , SMC_KEY (BCF0 ), & val );
992+ apple_smc_read_u32 (power -> smc , SMC_KEY (BCF0 ), & val32 );
901993
902994 psy_cfg .drv_data = power ;
903995 power -> batt = devm_power_supply_register (& pdev -> dev , & power -> batt_desc , & psy_cfg );
0 commit comments