28
28
* DOC: Overview
29
29
*
30
30
* gmux is a microcontroller built into the MacBook Pro to support dual GPUs:
31
- * A `Lattice XP2`_ on pre-retinas, a `Renesas R4F2113`_ on retinas.
31
+ * A `Lattice XP2`_ on pre-retinas, a `Renesas R4F2113`_ on pre-T2 retinas.
32
+ *
33
+ * On T2 Macbooks, the gmux is part of the T2 Coprocessor's SMC. The SMC has
34
+ * an I2C connection to a `NXP PCAL6524` GPIO expander, which enables/disables
35
+ * the voltage regulators of the discrete GPU, drives the display panel power,
36
+ * and has a GPIO to switch the eDP mux. The Intel CPU can interact with
37
+ * gmux through MMIO, similar to how the main SMC interface is controlled.
32
38
*
33
39
* (The MacPro6,1 2013 also has a gmux, however it is unclear why since it has
34
40
* dual GPUs but no built-in display.)
35
41
*
36
42
* gmux is connected to the LPC bus of the southbridge. Its I/O ports are
37
43
* accessed differently depending on the microcontroller: Driver functions
38
- * to access a pre-retina gmux are infixed ``_pio_``, those for a retina gmux
39
- * are infixed ``_index_``.
44
+ * to access a pre-retina gmux are infixed ``_pio_``, those for a pre-T2
45
+ * retina gmux are infixed ``_index_``, and those on T2 Macs are infixed
46
+ * with ``_mmio_``.
40
47
*
41
48
* .. _Lattice XP2:
42
49
* http://www.latticesemi.com/en/Products/FPGAandCPLD/LatticeXP2.aspx
43
50
* .. _Renesas R4F2113:
44
51
* http://www.renesas.com/products/mpumcu/h8s/h8s2100/h8s2113/index.jsp
52
+ * .. _NXP PCAL6524:
53
+ * https://www.nxp.com/docs/en/data-sheet/PCAL6524.pdf
45
54
*/
46
55
47
56
struct apple_gmux_config ;
48
57
49
58
struct apple_gmux_data {
59
+ u8 * __iomem iomem_base ;
50
60
unsigned long iostart ;
51
61
unsigned long iolen ;
52
62
const struct apple_gmux_config * config ;
@@ -208,6 +218,79 @@ static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port,
208
218
mutex_unlock (& gmux_data -> index_lock );
209
219
}
210
220
221
+ static int gmux_mmio_wait (struct apple_gmux_data * gmux_data )
222
+ {
223
+ int i = 200 ;
224
+ u8 gwr = ioread8 (gmux_data -> iomem_base + GMUX_MMIO_COMMAND_SEND );
225
+
226
+ while (i && gwr ) {
227
+ gwr = ioread8 (gmux_data -> iomem_base + GMUX_MMIO_COMMAND_SEND );
228
+ udelay (100 );
229
+ i -- ;
230
+ }
231
+
232
+ return !!i ;
233
+ }
234
+
235
+ static u8 gmux_mmio_read8 (struct apple_gmux_data * gmux_data , int port )
236
+ {
237
+ u8 val ;
238
+
239
+ mutex_lock (& gmux_data -> index_lock );
240
+ gmux_mmio_wait (gmux_data );
241
+ iowrite8 ((port & 0xff ), gmux_data -> iomem_base + GMUX_MMIO_PORT_SELECT );
242
+ iowrite8 (GMUX_MMIO_READ | sizeof (val ),
243
+ gmux_data -> iomem_base + GMUX_MMIO_COMMAND_SEND );
244
+ gmux_mmio_wait (gmux_data );
245
+ val = ioread8 (gmux_data -> iomem_base );
246
+ mutex_unlock (& gmux_data -> index_lock );
247
+
248
+ return val ;
249
+ }
250
+
251
+ static void gmux_mmio_write8 (struct apple_gmux_data * gmux_data , int port ,
252
+ u8 val )
253
+ {
254
+ mutex_lock (& gmux_data -> index_lock );
255
+ gmux_mmio_wait (gmux_data );
256
+ iowrite8 (val , gmux_data -> iomem_base );
257
+
258
+ iowrite8 (port & 0xff , gmux_data -> iomem_base + GMUX_MMIO_PORT_SELECT );
259
+ iowrite8 (GMUX_MMIO_WRITE | sizeof (val ),
260
+ gmux_data -> iomem_base + GMUX_MMIO_COMMAND_SEND );
261
+
262
+ gmux_mmio_wait (gmux_data );
263
+ mutex_unlock (& gmux_data -> index_lock );
264
+ }
265
+
266
+ static u32 gmux_mmio_read32 (struct apple_gmux_data * gmux_data , int port )
267
+ {
268
+ u32 val ;
269
+
270
+ mutex_lock (& gmux_data -> index_lock );
271
+ gmux_mmio_wait (gmux_data );
272
+ iowrite8 ((port & 0xff ), gmux_data -> iomem_base + GMUX_MMIO_PORT_SELECT );
273
+ iowrite8 (GMUX_MMIO_READ | sizeof (val ),
274
+ gmux_data -> iomem_base + GMUX_MMIO_COMMAND_SEND );
275
+ gmux_mmio_wait (gmux_data );
276
+ val = be32_to_cpu (ioread32 (gmux_data -> iomem_base ));
277
+ mutex_unlock (& gmux_data -> index_lock );
278
+
279
+ return val ;
280
+ }
281
+
282
+ static void gmux_mmio_write32 (struct apple_gmux_data * gmux_data , int port ,
283
+ u32 val )
284
+ {
285
+ mutex_lock (& gmux_data -> index_lock );
286
+ iowrite32 (cpu_to_be32 (val ), gmux_data -> iomem_base );
287
+ iowrite8 (port & 0xff , gmux_data -> iomem_base + GMUX_MMIO_PORT_SELECT );
288
+ iowrite8 (GMUX_MMIO_WRITE | sizeof (val ),
289
+ gmux_data -> iomem_base + GMUX_MMIO_COMMAND_SEND );
290
+ gmux_mmio_wait (gmux_data );
291
+ mutex_unlock (& gmux_data -> index_lock );
292
+ }
293
+
211
294
static u8 gmux_read8 (struct apple_gmux_data * gmux_data , int port )
212
295
{
213
296
return gmux_data -> config -> read8 (gmux_data , port );
@@ -236,8 +319,8 @@ static void gmux_write32(struct apple_gmux_data *gmux_data, int port,
236
319
* the GPU. On dual GPU MacBook Pros by contrast, either GPU may be suspended
237
320
* to conserve energy. Hence the PWM signal needs to be generated by a separate
238
321
* backlight driver which is controlled by gmux. The earliest generation
239
- * MBP5 2008/09 uses a `TI LP8543`_ backlight driver. All newer models
240
- * use a `TI LP8545`_.
322
+ * MBP5 2008/09 uses a `TI LP8543`_ backlight driver. Newer models
323
+ * use a `TI LP8545`_ or a TI LP8548 .
241
324
*
242
325
* .. _TI LP8543: https://www.ti.com/lit/ds/symlink/lp8543.pdf
243
326
* .. _TI LP8545: https://www.ti.com/lit/ds/symlink/lp8545.pdf
@@ -301,8 +384,8 @@ static const struct backlight_ops gmux_bl_ops = {
301
384
* connecting it either to the discrete GPU or the Thunderbolt controller.
302
385
* Oddly enough, while the full port is no longer switchable, AUX and HPD
303
386
* are still switchable by way of an `NXP CBTL03062`_ (on pre-retinas
304
- * MBP8 2011 and MBP9 2012) or two `TI TS3DS10224`_ (on retinas) under the
305
- * control of gmux. Since the integrated GPU is missing the main link,
387
+ * MBP8 2011 and MBP9 2012) or two `TI TS3DS10224`_ (on pre-t2 retinas) under
388
+ * the control of gmux. Since the integrated GPU is missing the main link,
306
389
* external displays appear to it as phantoms which fail to link-train.
307
390
*
308
391
* gmux receives the HPD signal of all display connectors and sends an
@@ -503,14 +586,42 @@ static const struct apple_gmux_config apple_gmux_index = {
503
586
.name = "indexed"
504
587
};
505
588
589
+ static const struct apple_gmux_config apple_gmux_mmio = {
590
+ .read8 = & gmux_mmio_read8 ,
591
+ .write8 = & gmux_mmio_write8 ,
592
+ .read32 = & gmux_mmio_read32 ,
593
+ .write32 = & gmux_mmio_write32 ,
594
+ .gmux_handler = & gmux_handler_no_ddc ,
595
+ .handler_flags = VGA_SWITCHEROO_NEEDS_EDP_CONFIG ,
596
+ .resource_type = IORESOURCE_MEM ,
597
+ .read_version_as_u32 = true,
598
+ .name = "T2"
599
+ };
600
+
601
+
506
602
/**
507
603
* DOC: Interrupt
508
604
*
509
605
* gmux is also connected to a GPIO pin of the southbridge and thereby is able
510
- * to trigger an ACPI GPE. On the MBP5 2008/09 it's GPIO pin 22 of the Nvidia
511
- * MCP79, on all following generations it's GPIO pin 6 of the Intel PCH.
606
+ * to trigger an ACPI GPE. ACPI name GMGP holds this GPIO pin's number. On the
607
+ * MBP5 2008/09 it's GPIO pin 22 of the Nvidia MCP79, on following generations
608
+ * it's GPIO pin 6 of the Intel PCH, on MMIO gmux's it's pin 21.
609
+ *
512
610
* The GPE merely signals that an interrupt occurred, the actual type of event
513
611
* is identified by reading a gmux register.
612
+ *
613
+ * In addition to the GMGP name, gmux's ACPI device also has two methods GMSP
614
+ * and GMLV. GMLV likely means "GMUX Level", and reads the value of the GPIO,
615
+ * while GMSP likely means "GMUX Set Polarity", and seems to write to the GPIO's
616
+ * value. On newer Macbooks (This was introduced with or sometime before the
617
+ * MacBookPro14,3), the ACPI GPE method differentiates between the OS type: On
618
+ * Darwin, only a notification is signaled, whereas on other OSes, the GPIO's
619
+ * value is read and then inverted.
620
+ *
621
+ * Because Linux masquerades as Darwin, it ends up in the notification-only code
622
+ * path. On MMIO gmux's, this seems to lead to us being unable to clear interrupts,
623
+ * unless we call GMSP(0). Without this, there is a flood of status=0 interrupts
624
+ * that can't be cleared. This issue seems to be unique to MMIO gmux's.
514
625
*/
515
626
516
627
static inline void gmux_disable_interrupts (struct apple_gmux_data * gmux_data )
@@ -537,6 +648,9 @@ static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data)
537
648
/* to clear interrupts write back current status */
538
649
status = gmux_interrupt_get_status (gmux_data );
539
650
gmux_write8 (gmux_data , GMUX_PORT_INTERRUPT_STATUS , status );
651
+ /* Prevent flood of status=0 interrupts */
652
+ if (gmux_data -> config == & apple_gmux_mmio )
653
+ acpi_execute_simple_method (gmux_data -> dhandle , "GMSP" , 0 );
540
654
}
541
655
542
656
static void gmux_notify_handler (acpi_handle device , u32 value , void * context )
@@ -609,6 +723,25 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
609
723
pnp_set_drvdata (pnp , gmux_data );
610
724
611
725
switch (type ) {
726
+ case APPLE_GMUX_TYPE_MMIO :
727
+ gmux_data -> config = & apple_gmux_mmio ;
728
+ mutex_init (& gmux_data -> index_lock );
729
+
730
+ res = pnp_get_resource (pnp , IORESOURCE_MEM , 0 );
731
+ gmux_data -> iostart = res -> start ;
732
+ /* Although the ACPI table only allocates 8 bytes, we need 16. */
733
+ gmux_data -> iolen = 16 ;
734
+ if (!request_mem_region (gmux_data -> iostart , gmux_data -> iolen ,
735
+ "Apple gmux" )) {
736
+ pr_err ("gmux I/O already in use\n" );
737
+ goto err_free ;
738
+ }
739
+ gmux_data -> iomem_base = ioremap (gmux_data -> iostart , gmux_data -> iolen );
740
+ if (!gmux_data -> iomem_base ) {
741
+ pr_err ("couldn't remap gmux mmio region" );
742
+ goto err_release ;
743
+ }
744
+ goto get_version ;
612
745
case APPLE_GMUX_TYPE_INDEXED :
613
746
gmux_data -> config = & apple_gmux_index ;
614
747
mutex_init (& gmux_data -> index_lock );
@@ -628,6 +761,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
628
761
goto err_free ;
629
762
}
630
763
764
+ get_version :
631
765
if (gmux_data -> config -> read_version_as_u32 ) {
632
766
version = gmux_read32 (gmux_data , GMUX_PORT_VERSION_MAJOR );
633
767
ver_major = (version >> 24 ) & 0xff ;
@@ -658,7 +792,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
658
792
gmux_data , & gmux_bl_ops , & props );
659
793
if (IS_ERR (bdev )) {
660
794
ret = PTR_ERR (bdev );
661
- goto err_release ;
795
+ goto err_unmap ;
662
796
}
663
797
664
798
gmux_data -> bdev = bdev ;
@@ -725,7 +859,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
725
859
/*
726
860
* Retina MacBook Pros cannot switch the panel's AUX separately
727
861
* and need eDP pre-calibration. They are distinguishable from
728
- * pre-retinas by having an "indexed" gmux.
862
+ * pre-retinas by having an "indexed" or "T2" gmux.
729
863
*
730
864
* Pre-retina MacBook Pros can switch the panel's DDC separately.
731
865
*/
@@ -750,8 +884,14 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
750
884
& gmux_notify_handler );
751
885
err_notify :
752
886
backlight_device_unregister (bdev );
887
+ err_unmap :
888
+ if (gmux_data -> iomem_base )
889
+ iounmap (gmux_data -> iomem_base );
753
890
err_release :
754
- release_region (gmux_data -> iostart , gmux_data -> iolen );
891
+ if (gmux_data -> config -> resource_type == IORESOURCE_MEM )
892
+ release_mem_region (gmux_data -> iostart , gmux_data -> iolen );
893
+ else
894
+ release_region (gmux_data -> iostart , gmux_data -> iolen );
755
895
err_free :
756
896
kfree (gmux_data );
757
897
return ret ;
@@ -772,7 +912,11 @@ static void gmux_remove(struct pnp_dev *pnp)
772
912
773
913
backlight_device_unregister (gmux_data -> bdev );
774
914
775
- release_region (gmux_data -> iostart , gmux_data -> iolen );
915
+ if (gmux_data -> iomem_base ) {
916
+ iounmap (gmux_data -> iomem_base );
917
+ release_mem_region (gmux_data -> iostart , gmux_data -> iolen );
918
+ } else
919
+ release_region (gmux_data -> iostart , gmux_data -> iolen );
776
920
apple_gmux_data = NULL ;
777
921
kfree (gmux_data );
778
922
0 commit comments