@@ -70,6 +70,8 @@ struct lpc_driver_data {
70
70
/**
71
71
* struct cros_ec_lpc - LPC device-specific data
72
72
* @mmio_memory_base: The first I/O port addressing EC mapped memory.
73
+ * @base: For EC supporting memory mapping, base address of the mapped region.
74
+ * @mem32: Information about the memory mapped register region, if present.
73
75
* @read: Copy length bytes from EC address offset into buffer dest.
74
76
* Returns a negative error code on error, or the 8-bit checksum
75
77
* of all bytes read.
@@ -79,6 +81,8 @@ struct lpc_driver_data {
79
81
*/
80
82
struct cros_ec_lpc {
81
83
u16 mmio_memory_base ;
84
+ void __iomem * base ;
85
+ struct acpi_resource_fixed_memory32 mem32 ;
82
86
int (* read )(struct cros_ec_lpc * ec_lpc , unsigned int offset ,
83
87
unsigned int length , u8 * dest );
84
88
int (* write )(struct cros_ec_lpc * ec_lpc , unsigned int offset ,
@@ -160,6 +164,45 @@ static int cros_ec_lpc_mec_write_bytes(struct cros_ec_lpc *ec_lpc, unsigned int
160
164
length , (u8 * )msg ) :
161
165
cros_ec_lpc_write_bytes (ec_lpc , offset , length , msg );
162
166
}
167
+
168
+ static int cros_ec_lpc_direct_read (struct cros_ec_lpc * ec_lpc , unsigned int offset ,
169
+ unsigned int length , u8 * dest )
170
+ {
171
+ int sum = 0 ;
172
+ int i ;
173
+
174
+ if (offset < EC_HOST_CMD_REGION0 || offset > EC_LPC_ADDR_MEMMAP +
175
+ EC_MEMMAP_SIZE ) {
176
+ return cros_ec_lpc_read_bytes (ec_lpc , offset , length , dest );
177
+ }
178
+
179
+ for (i = 0 ; i < length ; ++ i ) {
180
+ dest [i ] = readb (ec_lpc -> base + offset - EC_HOST_CMD_REGION0 + i );
181
+ sum += dest [i ];
182
+ }
183
+
184
+ /* Return checksum of all bytes read */
185
+ return sum ;
186
+ }
187
+
188
+ static int cros_ec_lpc_direct_write (struct cros_ec_lpc * ec_lpc , unsigned int offset ,
189
+ unsigned int length , const u8 * msg )
190
+ {
191
+ int sum = 0 ;
192
+ int i ;
193
+
194
+ if (offset < EC_HOST_CMD_REGION0 || offset > EC_LPC_ADDR_MEMMAP +
195
+ EC_MEMMAP_SIZE ) {
196
+ return cros_ec_lpc_write_bytes (ec_lpc , offset , length , msg );
197
+ }
198
+
199
+ for (i = 0 ; i < length ; ++ i ) {
200
+ writeb (msg [i ], ec_lpc -> base + offset - EC_HOST_CMD_REGION0 + i );
201
+ sum += msg [i ];
202
+ }
203
+
204
+ /* Return checksum of all bytes written */
205
+ return sum ;
163
206
}
164
207
165
208
static int ec_response_timed_out (struct cros_ec_lpc * ec_lpc )
@@ -450,6 +493,20 @@ static struct acpi_device *cros_ec_lpc_get_device(const char *id)
450
493
return adev ;
451
494
}
452
495
496
+ static acpi_status cros_ec_lpc_resources (struct acpi_resource * res , void * data )
497
+ {
498
+ struct cros_ec_lpc * ec_lpc = data ;
499
+
500
+ switch (res -> type ) {
501
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32 :
502
+ ec_lpc -> mem32 = res -> data .fixed_memory32 ;
503
+ break ;
504
+ default :
505
+ break ;
506
+ }
507
+ return AE_OK ;
508
+ }
509
+
453
510
static int cros_ec_lpc_probe (struct platform_device * pdev )
454
511
{
455
512
struct device * dev = & pdev -> dev ;
@@ -498,29 +555,52 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
498
555
dev_info (dev , "got AML mutex '%s'" , name );
499
556
}
500
557
}
501
-
502
- /*
503
- * The Framework Laptop (and possibly other non-ChromeOS devices)
504
- * only exposes the eight I/O ports that are required for the Microchip EC.
505
- * Requesting a larger reservation will fail.
506
- */
507
- if (!devm_request_region (dev , EC_HOST_CMD_REGION0 ,
508
- EC_HOST_CMD_MEC_REGION_SIZE , dev_name (dev ))) {
509
- dev_err (dev , "couldn't reserve MEC region\n" );
510
- return - EBUSY ;
558
+ adev = ACPI_COMPANION (dev );
559
+ if (adev ) {
560
+ /*
561
+ * Retrieve the resource information in the CRS register, if available.
562
+ */
563
+ status = acpi_walk_resources (adev -> handle , METHOD_NAME__CRS ,
564
+ cros_ec_lpc_resources , ec_lpc );
565
+ if (ACPI_FAILURE (status )) {
566
+ dev_err (dev , "failed to get resources\n" );
567
+ return - ENODEV ;
568
+ }
569
+ if (ec_lpc -> mem32 .address_length ) {
570
+ ec_lpc -> base = devm_ioremap (dev ,
571
+ ec_lpc -> mem32 .address ,
572
+ ec_lpc -> mem32 .address_length );
573
+ if (!ec_lpc -> base )
574
+ return - EINVAL ;
575
+
576
+ ec_lpc -> read = cros_ec_lpc_direct_read ;
577
+ ec_lpc -> write = cros_ec_lpc_direct_write ;
578
+ }
511
579
}
580
+ if (!ec_lpc -> read ) {
581
+ /*
582
+ * The Framework Laptop (and possibly other non-ChromeOS devices)
583
+ * only exposes the eight I/O ports that are required for the Microchip EC.
584
+ * Requesting a larger reservation will fail.
585
+ */
586
+ if (!devm_request_region (dev , EC_HOST_CMD_REGION0 ,
587
+ EC_HOST_CMD_MEC_REGION_SIZE , dev_name (dev ))) {
588
+ dev_err (dev , "couldn't reserve MEC region\n" );
589
+ return - EBUSY ;
590
+ }
512
591
513
- cros_ec_lpc_mec_init (EC_HOST_CMD_REGION0 ,
514
- EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE );
592
+ cros_ec_lpc_mec_init (EC_HOST_CMD_REGION0 ,
593
+ EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE );
515
594
516
- /*
517
- * Read the mapped ID twice, the first one is assuming the
518
- * EC is a Microchip Embedded Controller (MEC) variant, if the
519
- * protocol fails, fallback to the non MEC variant and try to
520
- * read again the ID.
521
- */
522
- ec_lpc -> read = cros_ec_lpc_mec_read_bytes ;
523
- ec_lpc -> write = cros_ec_lpc_mec_write_bytes ;
595
+ /*
596
+ * Read the mapped ID twice, the first one is assuming the
597
+ * EC is a Microchip Embedded Controller (MEC) variant, if the
598
+ * protocol fails, fallback to the non MEC variant and try to
599
+ * read again the ID.
600
+ */
601
+ ec_lpc -> read = cros_ec_lpc_mec_read_bytes ;
602
+ ec_lpc -> write = cros_ec_lpc_mec_write_bytes ;
603
+ }
524
604
ret = ec_lpc -> read (ec_lpc , EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID , 2 , buf );
525
605
if (ret < 0 )
526
606
return ret ;
@@ -594,7 +674,6 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
594
674
* Connect a notify handler to process MKBP messages if we have a
595
675
* companion ACPI device.
596
676
*/
597
- adev = ACPI_COMPANION (dev );
598
677
if (adev ) {
599
678
status = acpi_install_notify_handler (adev -> handle ,
600
679
ACPI_ALL_NOTIFY ,
0 commit comments