9
9
* Copyright (C) 2009 Texas Instruments
10
10
* Added OMAP4 support - Santosh Shilimkar <[email protected] >
11
11
*/
12
+ #include <linux/cpu_pm.h>
12
13
#include <linux/irq.h>
13
14
#include <linux/kernel.h>
14
15
#include <linux/init.h>
@@ -232,7 +233,10 @@ struct gpmc_device {
232
233
int irq ;
233
234
struct irq_chip irq_chip ;
234
235
struct gpio_chip gpio_chip ;
236
+ struct notifier_block nb ;
237
+ struct omap3_gpmc_regs context ;
235
238
int nirqs ;
239
+ unsigned int is_suspended :1 ;
236
240
};
237
241
238
242
static struct irq_domain * gpmc_irq_domain ;
@@ -2384,6 +2388,106 @@ static int gpmc_gpio_init(struct gpmc_device *gpmc)
2384
2388
return 0 ;
2385
2389
}
2386
2390
2391
+ static void omap3_gpmc_save_context (struct gpmc_device * gpmc )
2392
+ {
2393
+ struct omap3_gpmc_regs * gpmc_context ;
2394
+ int i ;
2395
+
2396
+ if (!gpmc || !gpmc_base )
2397
+ return ;
2398
+
2399
+ gpmc_context = & gpmc -> context ;
2400
+
2401
+ gpmc_context -> sysconfig = gpmc_read_reg (GPMC_SYSCONFIG );
2402
+ gpmc_context -> irqenable = gpmc_read_reg (GPMC_IRQENABLE );
2403
+ gpmc_context -> timeout_ctrl = gpmc_read_reg (GPMC_TIMEOUT_CONTROL );
2404
+ gpmc_context -> config = gpmc_read_reg (GPMC_CONFIG );
2405
+ gpmc_context -> prefetch_config1 = gpmc_read_reg (GPMC_PREFETCH_CONFIG1 );
2406
+ gpmc_context -> prefetch_config2 = gpmc_read_reg (GPMC_PREFETCH_CONFIG2 );
2407
+ gpmc_context -> prefetch_control = gpmc_read_reg (GPMC_PREFETCH_CONTROL );
2408
+ for (i = 0 ; i < gpmc_cs_num ; i ++ ) {
2409
+ gpmc_context -> cs_context [i ].is_valid = gpmc_cs_mem_enabled (i );
2410
+ if (gpmc_context -> cs_context [i ].is_valid ) {
2411
+ gpmc_context -> cs_context [i ].config1 =
2412
+ gpmc_cs_read_reg (i , GPMC_CS_CONFIG1 );
2413
+ gpmc_context -> cs_context [i ].config2 =
2414
+ gpmc_cs_read_reg (i , GPMC_CS_CONFIG2 );
2415
+ gpmc_context -> cs_context [i ].config3 =
2416
+ gpmc_cs_read_reg (i , GPMC_CS_CONFIG3 );
2417
+ gpmc_context -> cs_context [i ].config4 =
2418
+ gpmc_cs_read_reg (i , GPMC_CS_CONFIG4 );
2419
+ gpmc_context -> cs_context [i ].config5 =
2420
+ gpmc_cs_read_reg (i , GPMC_CS_CONFIG5 );
2421
+ gpmc_context -> cs_context [i ].config6 =
2422
+ gpmc_cs_read_reg (i , GPMC_CS_CONFIG6 );
2423
+ gpmc_context -> cs_context [i ].config7 =
2424
+ gpmc_cs_read_reg (i , GPMC_CS_CONFIG7 );
2425
+ }
2426
+ }
2427
+ }
2428
+
2429
+ static void omap3_gpmc_restore_context (struct gpmc_device * gpmc )
2430
+ {
2431
+ struct omap3_gpmc_regs * gpmc_context ;
2432
+ int i ;
2433
+
2434
+ if (!gpmc || !gpmc_base )
2435
+ return ;
2436
+
2437
+ gpmc_context = & gpmc -> context ;
2438
+
2439
+ gpmc_write_reg (GPMC_SYSCONFIG , gpmc_context -> sysconfig );
2440
+ gpmc_write_reg (GPMC_IRQENABLE , gpmc_context -> irqenable );
2441
+ gpmc_write_reg (GPMC_TIMEOUT_CONTROL , gpmc_context -> timeout_ctrl );
2442
+ gpmc_write_reg (GPMC_CONFIG , gpmc_context -> config );
2443
+ gpmc_write_reg (GPMC_PREFETCH_CONFIG1 , gpmc_context -> prefetch_config1 );
2444
+ gpmc_write_reg (GPMC_PREFETCH_CONFIG2 , gpmc_context -> prefetch_config2 );
2445
+ gpmc_write_reg (GPMC_PREFETCH_CONTROL , gpmc_context -> prefetch_control );
2446
+ for (i = 0 ; i < gpmc_cs_num ; i ++ ) {
2447
+ if (gpmc_context -> cs_context [i ].is_valid ) {
2448
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG1 ,
2449
+ gpmc_context -> cs_context [i ].config1 );
2450
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG2 ,
2451
+ gpmc_context -> cs_context [i ].config2 );
2452
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG3 ,
2453
+ gpmc_context -> cs_context [i ].config3 );
2454
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG4 ,
2455
+ gpmc_context -> cs_context [i ].config4 );
2456
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG5 ,
2457
+ gpmc_context -> cs_context [i ].config5 );
2458
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG6 ,
2459
+ gpmc_context -> cs_context [i ].config6 );
2460
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG7 ,
2461
+ gpmc_context -> cs_context [i ].config7 );
2462
+ } else {
2463
+ gpmc_cs_write_reg (i , GPMC_CS_CONFIG7 , 0 );
2464
+ }
2465
+ }
2466
+ }
2467
+
2468
+ static int omap_gpmc_context_notifier (struct notifier_block * nb ,
2469
+ unsigned long cmd , void * v )
2470
+ {
2471
+ struct gpmc_device * gpmc ;
2472
+
2473
+ gpmc = container_of (nb , struct gpmc_device , nb );
2474
+ if (gpmc -> is_suspended || pm_runtime_suspended (gpmc -> dev ))
2475
+ return NOTIFY_OK ;
2476
+
2477
+ switch (cmd ) {
2478
+ case CPU_CLUSTER_PM_ENTER :
2479
+ omap3_gpmc_save_context (gpmc );
2480
+ break ;
2481
+ case CPU_CLUSTER_PM_ENTER_FAILED : /* No need to restore context */
2482
+ break ;
2483
+ case CPU_CLUSTER_PM_EXIT :
2484
+ omap3_gpmc_restore_context (gpmc );
2485
+ break ;
2486
+ }
2487
+
2488
+ return NOTIFY_OK ;
2489
+ }
2490
+
2387
2491
static int gpmc_probe (struct platform_device * pdev )
2388
2492
{
2389
2493
int rc ;
@@ -2472,6 +2576,9 @@ static int gpmc_probe(struct platform_device *pdev)
2472
2576
2473
2577
gpmc_probe_dt_children (pdev );
2474
2578
2579
+ gpmc -> nb .notifier_call = omap_gpmc_context_notifier ;
2580
+ cpu_pm_register_notifier (& gpmc -> nb );
2581
+
2475
2582
return 0 ;
2476
2583
2477
2584
gpio_init_failed :
@@ -2486,6 +2593,7 @@ static int gpmc_remove(struct platform_device *pdev)
2486
2593
{
2487
2594
struct gpmc_device * gpmc = platform_get_drvdata (pdev );
2488
2595
2596
+ cpu_pm_unregister_notifier (& gpmc -> nb );
2489
2597
gpmc_free_irq (gpmc );
2490
2598
gpmc_mem_exit ();
2491
2599
pm_runtime_put_sync (& pdev -> dev );
@@ -2497,15 +2605,23 @@ static int gpmc_remove(struct platform_device *pdev)
2497
2605
#ifdef CONFIG_PM_SLEEP
2498
2606
static int gpmc_suspend (struct device * dev )
2499
2607
{
2500
- omap3_gpmc_save_context ();
2608
+ struct gpmc_device * gpmc = dev_get_drvdata (dev );
2609
+
2610
+ omap3_gpmc_save_context (gpmc );
2501
2611
pm_runtime_put_sync (dev );
2612
+ gpmc -> is_suspended = 1 ;
2613
+
2502
2614
return 0 ;
2503
2615
}
2504
2616
2505
2617
static int gpmc_resume (struct device * dev )
2506
2618
{
2619
+ struct gpmc_device * gpmc = dev_get_drvdata (dev );
2620
+
2507
2621
pm_runtime_get_sync (dev );
2508
- omap3_gpmc_restore_context ();
2622
+ omap3_gpmc_restore_context (gpmc );
2623
+ gpmc -> is_suspended = 0 ;
2624
+
2509
2625
return 0 ;
2510
2626
}
2511
2627
#endif
@@ -2527,76 +2643,3 @@ static __init int gpmc_init(void)
2527
2643
return platform_driver_register (& gpmc_driver );
2528
2644
}
2529
2645
postcore_initcall (gpmc_init );
2530
-
2531
- static struct omap3_gpmc_regs gpmc_context ;
2532
-
2533
- void omap3_gpmc_save_context (void )
2534
- {
2535
- int i ;
2536
-
2537
- if (!gpmc_base )
2538
- return ;
2539
-
2540
- gpmc_context .sysconfig = gpmc_read_reg (GPMC_SYSCONFIG );
2541
- gpmc_context .irqenable = gpmc_read_reg (GPMC_IRQENABLE );
2542
- gpmc_context .timeout_ctrl = gpmc_read_reg (GPMC_TIMEOUT_CONTROL );
2543
- gpmc_context .config = gpmc_read_reg (GPMC_CONFIG );
2544
- gpmc_context .prefetch_config1 = gpmc_read_reg (GPMC_PREFETCH_CONFIG1 );
2545
- gpmc_context .prefetch_config2 = gpmc_read_reg (GPMC_PREFETCH_CONFIG2 );
2546
- gpmc_context .prefetch_control = gpmc_read_reg (GPMC_PREFETCH_CONTROL );
2547
- for (i = 0 ; i < gpmc_cs_num ; i ++ ) {
2548
- gpmc_context .cs_context [i ].is_valid = gpmc_cs_mem_enabled (i );
2549
- if (gpmc_context .cs_context [i ].is_valid ) {
2550
- gpmc_context .cs_context [i ].config1 =
2551
- gpmc_cs_read_reg (i , GPMC_CS_CONFIG1 );
2552
- gpmc_context .cs_context [i ].config2 =
2553
- gpmc_cs_read_reg (i , GPMC_CS_CONFIG2 );
2554
- gpmc_context .cs_context [i ].config3 =
2555
- gpmc_cs_read_reg (i , GPMC_CS_CONFIG3 );
2556
- gpmc_context .cs_context [i ].config4 =
2557
- gpmc_cs_read_reg (i , GPMC_CS_CONFIG4 );
2558
- gpmc_context .cs_context [i ].config5 =
2559
- gpmc_cs_read_reg (i , GPMC_CS_CONFIG5 );
2560
- gpmc_context .cs_context [i ].config6 =
2561
- gpmc_cs_read_reg (i , GPMC_CS_CONFIG6 );
2562
- gpmc_context .cs_context [i ].config7 =
2563
- gpmc_cs_read_reg (i , GPMC_CS_CONFIG7 );
2564
- }
2565
- }
2566
- }
2567
-
2568
- void omap3_gpmc_restore_context (void )
2569
- {
2570
- int i ;
2571
-
2572
- if (!gpmc_base )
2573
- return ;
2574
-
2575
- gpmc_write_reg (GPMC_SYSCONFIG , gpmc_context .sysconfig );
2576
- gpmc_write_reg (GPMC_IRQENABLE , gpmc_context .irqenable );
2577
- gpmc_write_reg (GPMC_TIMEOUT_CONTROL , gpmc_context .timeout_ctrl );
2578
- gpmc_write_reg (GPMC_CONFIG , gpmc_context .config );
2579
- gpmc_write_reg (GPMC_PREFETCH_CONFIG1 , gpmc_context .prefetch_config1 );
2580
- gpmc_write_reg (GPMC_PREFETCH_CONFIG2 , gpmc_context .prefetch_config2 );
2581
- gpmc_write_reg (GPMC_PREFETCH_CONTROL , gpmc_context .prefetch_control );
2582
- for (i = 0 ; i < gpmc_cs_num ; i ++ ) {
2583
- if (gpmc_context .cs_context [i ].is_valid ) {
2584
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG1 ,
2585
- gpmc_context .cs_context [i ].config1 );
2586
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG2 ,
2587
- gpmc_context .cs_context [i ].config2 );
2588
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG3 ,
2589
- gpmc_context .cs_context [i ].config3 );
2590
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG4 ,
2591
- gpmc_context .cs_context [i ].config4 );
2592
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG5 ,
2593
- gpmc_context .cs_context [i ].config5 );
2594
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG6 ,
2595
- gpmc_context .cs_context [i ].config6 );
2596
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG7 ,
2597
- gpmc_context .cs_context [i ].config7 );
2598
- } else {
2599
- gpmc_cs_write_reg (i , GPMC_CS_CONFIG7 , 0 );
2600
- }
2601
- }
2602
- }
0 commit comments