@@ -70,6 +70,8 @@ struct lpc_driver_data {
7070/**
7171 * struct cros_ec_lpc - LPC device-specific data
7272 * @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.
7375 * @read: Copy length bytes from EC address offset into buffer dest.
7476 * Returns a negative error code on error, or the 8-bit checksum
7577 * of all bytes read.
@@ -79,6 +81,8 @@ struct lpc_driver_data {
7981 */
8082struct cros_ec_lpc {
8183 u16 mmio_memory_base ;
84+ void __iomem * base ;
85+ struct acpi_resource_fixed_memory32 mem32 ;
8286 int (* read )(struct cros_ec_lpc * ec_lpc , unsigned int offset ,
8387 unsigned int length , u8 * dest );
8488 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
160164 length , (u8 * )msg ) :
161165 cros_ec_lpc_write_bytes (ec_lpc , offset , length , msg );
162166}
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 ;
163206}
164207
165208static 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)
450493 return adev ;
451494}
452495
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+
453510static int cros_ec_lpc_probe (struct platform_device * pdev )
454511{
455512 struct device * dev = & pdev -> dev ;
@@ -498,29 +555,52 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
498555 dev_info (dev , "got AML mutex '%s'" , name );
499556 }
500557 }
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+ }
511579 }
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+ }
512591
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 );
515594
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+ }
524604 ret = ec_lpc -> read (ec_lpc , EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID , 2 , buf );
525605 if (ret < 0 )
526606 return ret ;
@@ -594,7 +674,6 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
594674 * Connect a notify handler to process MKBP messages if we have a
595675 * companion ACPI device.
596676 */
597- adev = ACPI_COMPANION (dev );
598677 if (adev ) {
599678 status = acpi_install_notify_handler (adev -> handle ,
600679 ACPI_ALL_NOTIFY ,
0 commit comments