11
11
#include <linux/vexpress.h>
12
12
13
13
#include "pl111_versatile.h"
14
- #include "pl111_vexpress.h"
15
14
#include "pl111_drm.h"
16
15
17
16
static struct regmap * versatile_syscon_map ;
@@ -362,13 +361,110 @@ static const struct pl111_variant_data pl111_vexpress = {
362
361
.broken_clockdivider = true,
363
362
};
364
363
364
+ #define VEXPRESS_FPGAMUX_MOTHERBOARD 0x00
365
+ #define VEXPRESS_FPGAMUX_DAUGHTERBOARD_1 0x01
366
+ #define VEXPRESS_FPGAMUX_DAUGHTERBOARD_2 0x02
367
+
368
+ static int pl111_vexpress_clcd_init (struct device * dev , struct device_node * np ,
369
+ struct pl111_drm_dev_private * priv )
370
+ {
371
+ struct platform_device * pdev ;
372
+ struct device_node * root ;
373
+ struct device_node * child ;
374
+ struct device_node * ct_clcd = NULL ;
375
+ struct regmap * map ;
376
+ bool has_coretile_clcd = false;
377
+ bool has_coretile_hdlcd = false;
378
+ bool mux_motherboard = true;
379
+ u32 val ;
380
+ int ret ;
381
+
382
+ if (!IS_ENABLED (CONFIG_VEXPRESS_CONFIG ))
383
+ return - ENODEV ;
384
+
385
+ /*
386
+ * Check if we have a CLCD or HDLCD on the core tile by checking if a
387
+ * CLCD or HDLCD is available in the root of the device tree.
388
+ */
389
+ root = of_find_node_by_path ("/" );
390
+ if (!root )
391
+ return - EINVAL ;
392
+
393
+ for_each_available_child_of_node (root , child ) {
394
+ if (of_device_is_compatible (child , "arm,pl111" )) {
395
+ has_coretile_clcd = true;
396
+ ct_clcd = child ;
397
+ break ;
398
+ }
399
+ if (of_device_is_compatible (child , "arm,hdlcd" )) {
400
+ has_coretile_hdlcd = true;
401
+ of_node_put (child );
402
+ break ;
403
+ }
404
+ }
405
+
406
+ of_node_put (root );
407
+
408
+ /*
409
+ * If there is a coretile HDLCD and it has a driver,
410
+ * do not mux the CLCD on the motherboard to the DVI.
411
+ */
412
+ if (has_coretile_hdlcd && IS_ENABLED (CONFIG_DRM_HDLCD ))
413
+ mux_motherboard = false;
414
+
415
+ /*
416
+ * On the Vexpress CA9 we let the CLCD on the coretile
417
+ * take precedence, so also in this case do not mux the
418
+ * motherboard to the DVI.
419
+ */
420
+ if (has_coretile_clcd )
421
+ mux_motherboard = false;
422
+
423
+ if (mux_motherboard ) {
424
+ dev_info (dev , "DVI muxed to motherboard CLCD\n" );
425
+ val = VEXPRESS_FPGAMUX_MOTHERBOARD ;
426
+ } else if (ct_clcd == dev -> of_node ) {
427
+ dev_info (dev ,
428
+ "DVI muxed to daughterboard 1 (core tile) CLCD\n" );
429
+ val = VEXPRESS_FPGAMUX_DAUGHTERBOARD_1 ;
430
+ } else {
431
+ dev_info (dev , "core tile graphics present\n" );
432
+ dev_info (dev , "this device will be deactivated\n" );
433
+ return - ENODEV ;
434
+ }
435
+
436
+ /* Call into deep Vexpress configuration API */
437
+ pdev = of_find_device_by_node (np );
438
+ if (!pdev ) {
439
+ dev_err (dev , "can't find the sysreg device, deferring\n" );
440
+ return - EPROBE_DEFER ;
441
+ }
442
+
443
+ map = devm_regmap_init_vexpress_config (& pdev -> dev );
444
+ if (IS_ERR (map )) {
445
+ platform_device_put (pdev );
446
+ return PTR_ERR (map );
447
+ }
448
+
449
+ ret = regmap_write (map , 0 , val );
450
+ platform_device_put (pdev );
451
+ if (ret ) {
452
+ dev_err (dev , "error setting DVI muxmode\n" );
453
+ return - ENODEV ;
454
+ }
455
+
456
+ priv -> variant = & pl111_vexpress ;
457
+ dev_info (dev , "initializing Versatile Express PL111\n" );
458
+
459
+ return 0 ;
460
+ }
461
+
365
462
int pl111_versatile_init (struct device * dev , struct pl111_drm_dev_private * priv )
366
463
{
367
464
const struct of_device_id * clcd_id ;
368
465
enum versatile_clcd versatile_clcd_type ;
369
466
struct device_node * np ;
370
467
struct regmap * map ;
371
- int ret ;
372
468
373
469
np = of_find_matching_node_and_match (NULL , versatile_clcd_of_match ,
374
470
& clcd_id );
@@ -379,6 +475,15 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
379
475
380
476
versatile_clcd_type = (enum versatile_clcd )clcd_id -> data ;
381
477
478
+ /* Versatile Express special handling */
479
+ if (versatile_clcd_type == VEXPRESS_CLCD_V2M ) {
480
+ int ret = pl111_vexpress_clcd_init (dev , np , priv );
481
+ of_node_put (np );
482
+ if (ret )
483
+ dev_err (dev , "Versatile Express init failed - %d" , ret );
484
+ return ret ;
485
+ }
486
+
382
487
/*
383
488
* On the Integrator, check if we should use the IM-PD1 instead,
384
489
* if we find it, it will take precedence. This is on the Integrator/AP
@@ -391,23 +496,8 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
391
496
versatile_clcd_type = (enum versatile_clcd )clcd_id -> data ;
392
497
}
393
498
394
- /* Versatile Express special handling */
395
- if (IS_ENABLED (CONFIG_VEXPRESS_CONFIG ) && versatile_clcd_type == VEXPRESS_CLCD_V2M ) {
396
- struct platform_device * pdev ;
397
- /* Call into deep Vexpress configuration API */
398
- pdev = of_find_device_by_node (np );
399
- if (!pdev ) {
400
- dev_err (dev , "can't find the sysreg device, deferring\n" );
401
- of_node_put (np );
402
- return - EPROBE_DEFER ;
403
- }
404
- map = devm_regmap_init_vexpress_config (& pdev -> dev );
405
- platform_device_put (pdev );
406
- } else {
407
- map = syscon_node_to_regmap (np );
408
- }
499
+ map = syscon_node_to_regmap (np );
409
500
of_node_put (np );
410
-
411
501
if (IS_ERR (map )) {
412
502
dev_err (dev , "no Versatile syscon regmap\n" );
413
503
return PTR_ERR (map );
@@ -453,13 +543,6 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
453
543
priv -> variant_display_disable = pl111_realview_clcd_disable ;
454
544
dev_info (dev , "set up callbacks for RealView PL111\n" );
455
545
break ;
456
- case VEXPRESS_CLCD_V2M :
457
- priv -> variant = & pl111_vexpress ;
458
- dev_info (dev , "initializing Versatile Express PL111\n" );
459
- ret = pl111_vexpress_clcd_init (dev , priv , map );
460
- if (ret )
461
- return ret ;
462
- break ;
463
546
default :
464
547
dev_info (dev , "unknown Versatile system controller\n" );
465
548
break ;
0 commit comments