4242
4343#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
4444
45+ #define APPLESMC_IOMEM_KEY_DATA 0
46+ #define APPLESMC_IOMEM_KEY_STATUS 0x4005
47+ #define APPLESMC_IOMEM_KEY_NAME 0x78
48+ #define APPLESMC_IOMEM_KEY_DATA_LEN 0x7D
49+ #define APPLESMC_IOMEM_KEY_SMC_ID 0x7E
50+ #define APPLESMC_IOMEM_KEY_CMD 0x7F
51+ #define APPLESMC_IOMEM_MIN_SIZE 0x4006
52+
53+ #define APPLESMC_IOMEM_KEY_TYPE_CODE 0
54+ #define APPLESMC_IOMEM_KEY_TYPE_DATA_LEN 5
55+ #define APPLESMC_IOMEM_KEY_TYPE_FLAGS 6
56+
4557#define APPLESMC_MAX_DATA_LENGTH 32
4658
4759/* Apple SMC status bits */
@@ -138,10 +150,13 @@ struct applesmc_registers {
138150
139151struct applesmc_device {
140152 struct acpi_device * dev ;
153+ struct device * ldev ;
141154 struct applesmc_registers reg ;
142155
143- bool port_base_set ;
156+ bool port_base_set , iomem_base_set ;
144157 u16 port_base ;
158+ u8 * __iomem iomem_base ;
159+ u32 iomem_base_addr , iomem_base_size ;
145160
146161 s16 rest_x ;
147162 s16 rest_y ;
@@ -347,16 +362,156 @@ static int port_get_smc_key_info(struct applesmc_device *smc,
347362 return 0 ;
348363}
349364
365+
366+ /*
367+ * MMIO based communication.
368+ * TODO: Use updated mechanism for cmd timeout/retry
369+ */
370+
371+ static void iomem_clear_status (struct applesmc_device * smc )
372+ {
373+ if (ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_STATUS ))
374+ iowrite8 (0 , smc -> iomem_base + APPLESMC_IOMEM_KEY_STATUS );
375+ }
376+
377+ static int iomem_wait_read (struct applesmc_device * smc )
378+ {
379+ u8 status ;
380+ int us ;
381+ int i ;
382+
383+ us = APPLESMC_MIN_WAIT ;
384+ for (i = 0 ; i < 24 ; i ++ ) {
385+ status = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_STATUS );
386+ if (status & 0x20 )
387+ return 0 ;
388+ usleep_range (us , us * 2 );
389+ if (i > 9 )
390+ us <<= 1 ;
391+ }
392+
393+ dev_warn (smc -> ldev , "%s... timeout\n" , __func__ );
394+ return - EIO ;
395+ }
396+
397+ static int iomem_read_smc (struct applesmc_device * smc , u8 cmd , const char * key ,
398+ u8 * buffer , u8 len )
399+ {
400+ u8 err , remote_len ;
401+ u32 key_int = * ((u32 * ) key );
402+
403+ iomem_clear_status (smc );
404+ iowrite32 (key_int , smc -> iomem_base + APPLESMC_IOMEM_KEY_NAME );
405+ iowrite32 (0 , smc -> iomem_base + APPLESMC_IOMEM_KEY_SMC_ID );
406+ iowrite32 (cmd , smc -> iomem_base + APPLESMC_IOMEM_KEY_CMD );
407+
408+ if (iomem_wait_read (smc ))
409+ return - EIO ;
410+
411+ err = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_CMD );
412+ if (err != 0 ) {
413+ dev_warn (smc -> ldev , "read_smc_mmio(%x %8x/%.4s) failed: %u\n" ,
414+ cmd , key_int , key , err );
415+ return - EIO ;
416+ }
417+
418+ if (cmd == APPLESMC_READ_CMD ) {
419+ remote_len = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN );
420+ if (remote_len != len ) {
421+ dev_warn (smc -> ldev ,
422+ "read_smc_mmio(%x %8x/%.4s) failed: buffer length mismatch (remote = %u, requested = %u)\n" ,
423+ cmd , key_int , key , remote_len , len );
424+ return - EINVAL ;
425+ }
426+ } else {
427+ remote_len = len ;
428+ }
429+
430+ memcpy_fromio (buffer , smc -> iomem_base + APPLESMC_IOMEM_KEY_DATA ,
431+ remote_len );
432+
433+ dev_dbg (smc -> ldev , "read_smc_mmio(%x %8x/%.4s): buflen=%u reslen=%u\n" ,
434+ cmd , key_int , key , len , remote_len );
435+ print_hex_dump_bytes ("read_smc_mmio(): " , DUMP_PREFIX_NONE , buffer , remote_len );
436+ return 0 ;
437+ }
438+
439+ static int iomem_get_smc_key_type (struct applesmc_device * smc , const char * key ,
440+ struct applesmc_entry * e )
441+ {
442+ u8 err ;
443+ u8 cmd = APPLESMC_GET_KEY_TYPE_CMD ;
444+ u32 key_int = * ((u32 * ) key );
445+
446+ iomem_clear_status (smc );
447+ iowrite32 (key_int , smc -> iomem_base + APPLESMC_IOMEM_KEY_NAME );
448+ iowrite32 (0 , smc -> iomem_base + APPLESMC_IOMEM_KEY_SMC_ID );
449+ iowrite32 (cmd , smc -> iomem_base + APPLESMC_IOMEM_KEY_CMD );
450+
451+ if (iomem_wait_read (smc ))
452+ return - EIO ;
453+
454+ err = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_CMD );
455+ if (err != 0 ) {
456+ dev_warn (smc -> ldev , "get_smc_key_type_mmio(%.4s) failed: %u\n" , key , err );
457+ return - EIO ;
458+ }
459+
460+ e -> len = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_TYPE_DATA_LEN );
461+ * ((uint32_t * ) e -> type ) = ioread32 (
462+ smc -> iomem_base + APPLESMC_IOMEM_KEY_TYPE_CODE );
463+ e -> flags = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_TYPE_FLAGS );
464+
465+ dev_dbg (smc -> ldev , "get_smc_key_type_mmio(%.4s): len=%u type=%.4s flags=%x\n" ,
466+ key , e -> len , e -> type , e -> flags );
467+ return 0 ;
468+ }
469+
470+ static int iomem_write_smc (struct applesmc_device * smc , u8 cmd , const char * key ,
471+ const u8 * buffer , u8 len )
472+ {
473+ u8 err ;
474+ u32 key_int = * ((u32 * ) key );
475+
476+ iomem_clear_status (smc );
477+ iowrite32 (key_int , smc -> iomem_base + APPLESMC_IOMEM_KEY_NAME );
478+ memcpy_toio (smc -> iomem_base + APPLESMC_IOMEM_KEY_DATA , buffer , len );
479+ iowrite32 (len , smc -> iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN );
480+ iowrite32 (0 , smc -> iomem_base + APPLESMC_IOMEM_KEY_SMC_ID );
481+ iowrite32 (cmd , smc -> iomem_base + APPLESMC_IOMEM_KEY_CMD );
482+
483+ if (iomem_wait_read (smc ))
484+ return - EIO ;
485+
486+ err = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_CMD );
487+ if (err != 0 ) {
488+ dev_warn (smc -> ldev , "write_smc_mmio(%x %.4s) failed: %u\n" , cmd , key , err );
489+ print_hex_dump_bytes ("write_smc_mmio(): " , DUMP_PREFIX_NONE , buffer , len );
490+ return - EIO ;
491+ }
492+
493+ dev_dbg (smc -> ldev , "write_smc_mmio(%x %.4s): buflen=%u\n" , cmd , key , len );
494+ print_hex_dump_bytes ("write_smc_mmio(): " , DUMP_PREFIX_NONE , buffer , len );
495+ return 0 ;
496+ }
497+
498+
350499static int read_smc (struct applesmc_device * smc , const char * key ,
351500 u8 * buffer , u8 len )
352501{
353- return port_read_smc (smc , APPLESMC_READ_CMD , key , buffer , len );
502+ if (smc -> iomem_base_set )
503+ return iomem_read_smc (smc , APPLESMC_READ_CMD , key , buffer , len );
504+ else
505+ return port_read_smc (smc , APPLESMC_READ_CMD , key , buffer , len );
354506}
355507
356508static int write_smc (struct applesmc_device * smc , const char * key ,
357509 const u8 * buffer , u8 len )
358510{
359- return port_write_smc (smc , APPLESMC_WRITE_CMD , key , buffer , len );
511+ if (smc -> iomem_base_set )
512+ return iomem_write_smc (smc , APPLESMC_WRITE_CMD , key , buffer , len );
513+ else
514+ return port_write_smc (smc , APPLESMC_WRITE_CMD , key , buffer , len );
360515}
361516
362517static int get_smc_key_by_index (struct applesmc_device * smc ,
@@ -365,14 +520,21 @@ static int get_smc_key_by_index(struct applesmc_device *smc,
365520 __be32 be ;
366521
367522 be = cpu_to_be32 (index );
368- return port_read_smc (smc , APPLESMC_GET_KEY_BY_INDEX_CMD ,
369- (const char * ) & be , (u8 * ) key , 4 );
523+ if (smc -> iomem_base_set )
524+ return iomem_read_smc (smc , APPLESMC_GET_KEY_BY_INDEX_CMD ,
525+ (const char * ) & be , (u8 * ) key , 4 );
526+ else
527+ return port_read_smc (smc , APPLESMC_GET_KEY_BY_INDEX_CMD ,
528+ (const char * ) & be , (u8 * ) key , 4 );
370529}
371530
372531static int get_smc_key_info (struct applesmc_device * smc , const char * key ,
373532 struct applesmc_entry * info )
374533{
375- return port_get_smc_key_info (smc , key , info );
534+ if (smc -> iomem_base_set )
535+ return iomem_get_smc_key_type (smc , key , info );
536+ else
537+ return port_get_smc_key_info (smc , key , info );
376538}
377539
378540static int read_register_count (struct applesmc_device * smc ,
@@ -746,6 +908,7 @@ static int applesmc_add(struct acpi_device *dev)
746908 if (!smc )
747909 return - ENOMEM ;
748910 smc -> dev = dev ;
911+ smc -> ldev = & dev -> dev ;
749912 mutex_init (& smc -> reg .mutex );
750913
751914 dev_set_drvdata (& dev -> dev , smc );
@@ -807,6 +970,20 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res,
807970 }
808971 return AE_OK ;
809972
973+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32 :
974+ if (!smc -> iomem_base_set ) {
975+ if (res -> data .fixed_memory32 .address_length <
976+ APPLESMC_IOMEM_MIN_SIZE ) {
977+ dev_warn (smc -> ldev , "found iomem but it's too small: %u\n" ,
978+ res -> data .fixed_memory32 .address_length );
979+ return AE_OK ;
980+ }
981+ smc -> iomem_base_addr = res -> data .fixed_memory32 .address ;
982+ smc -> iomem_base_size = res -> data .fixed_memory32 .address_length ;
983+ smc -> iomem_base_set = true;
984+ }
985+ return AE_OK ;
986+
810987 case ACPI_RESOURCE_TYPE_END_TAG :
811988 if (smc -> port_base_set )
812989 return AE_OK ;
@@ -818,6 +995,8 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res,
818995 }
819996}
820997
998+ static int applesmc_try_enable_iomem (struct applesmc_device * smc );
999+
8211000static int applesmc_init_resources (struct applesmc_device * smc )
8221001{
8231002 int ret ;
@@ -830,11 +1009,57 @@ static int applesmc_init_resources(struct applesmc_device *smc)
8301009 if (!request_region (smc -> port_base , APPLESMC_NR_PORTS , "applesmc" ))
8311010 return - ENXIO ;
8321011
1012+ if (smc -> iomem_base_set ) {
1013+ if (applesmc_try_enable_iomem (smc ))
1014+ smc -> iomem_base_set = false;
1015+ }
1016+
8331017 return 0 ;
8341018}
8351019
1020+ static int applesmc_try_enable_iomem (struct applesmc_device * smc )
1021+ {
1022+ u8 test_val , ldkn_version ;
1023+
1024+ dev_dbg (smc -> ldev , "Trying to enable iomem based communication\n" );
1025+ smc -> iomem_base = ioremap (smc -> iomem_base_addr , smc -> iomem_base_size );
1026+ if (!smc -> iomem_base )
1027+ goto out ;
1028+
1029+ /* Apple's driver does this check for some reason */
1030+ test_val = ioread8 (smc -> iomem_base + APPLESMC_IOMEM_KEY_STATUS );
1031+ if (test_val == 0xff ) {
1032+ dev_warn (smc -> ldev ,
1033+ "iomem enable failed: initial status is 0xff (is %x)\n" ,
1034+ test_val );
1035+ goto out_iomem ;
1036+ }
1037+
1038+ if (read_smc (smc , "LDKN" , & ldkn_version , 1 )) {
1039+ dev_warn (smc -> ldev , "iomem enable failed: ldkn read failed\n" );
1040+ goto out_iomem ;
1041+ }
1042+
1043+ if (ldkn_version < 2 ) {
1044+ dev_warn (smc -> ldev ,
1045+ "iomem enable failed: ldkn version %u is less than minimum (2)\n" ,
1046+ ldkn_version );
1047+ goto out_iomem ;
1048+ }
1049+
1050+ return 0 ;
1051+
1052+ out_iomem :
1053+ iounmap (smc -> iomem_base );
1054+
1055+ out :
1056+ return - ENXIO ;
1057+ }
1058+
8361059static void applesmc_free_resources (struct applesmc_device * smc )
8371060{
1061+ if (smc -> iomem_base_set )
1062+ iounmap (smc -> iomem_base );
8381063 release_region (smc -> port_base , APPLESMC_NR_PORTS );
8391064}
8401065
0 commit comments