99 * Copyright (C) 2009 Texas Instruments
1010 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
1111 */
12+ #include <linux/cpu_pm.h>
1213#include <linux/irq.h>
1314#include <linux/kernel.h>
1415#include <linux/init.h>
@@ -232,7 +233,10 @@ struct gpmc_device {
232233 int irq ;
233234 struct irq_chip irq_chip ;
234235 struct gpio_chip gpio_chip ;
236+ struct notifier_block nb ;
237+ struct omap3_gpmc_regs context ;
235238 int nirqs ;
239+ unsigned int is_suspended :1 ;
236240};
237241
238242static struct irq_domain * gpmc_irq_domain ;
@@ -2384,6 +2388,106 @@ static int gpmc_gpio_init(struct gpmc_device *gpmc)
23842388 return 0 ;
23852389}
23862390
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+
23872491static int gpmc_probe (struct platform_device * pdev )
23882492{
23892493 int rc ;
@@ -2472,6 +2576,9 @@ static int gpmc_probe(struct platform_device *pdev)
24722576
24732577 gpmc_probe_dt_children (pdev );
24742578
2579+ gpmc -> nb .notifier_call = omap_gpmc_context_notifier ;
2580+ cpu_pm_register_notifier (& gpmc -> nb );
2581+
24752582 return 0 ;
24762583
24772584gpio_init_failed :
@@ -2486,6 +2593,7 @@ static int gpmc_remove(struct platform_device *pdev)
24862593{
24872594 struct gpmc_device * gpmc = platform_get_drvdata (pdev );
24882595
2596+ cpu_pm_unregister_notifier (& gpmc -> nb );
24892597 gpmc_free_irq (gpmc );
24902598 gpmc_mem_exit ();
24912599 pm_runtime_put_sync (& pdev -> dev );
@@ -2497,15 +2605,23 @@ static int gpmc_remove(struct platform_device *pdev)
24972605#ifdef CONFIG_PM_SLEEP
24982606static int gpmc_suspend (struct device * dev )
24992607{
2500- omap3_gpmc_save_context ();
2608+ struct gpmc_device * gpmc = dev_get_drvdata (dev );
2609+
2610+ omap3_gpmc_save_context (gpmc );
25012611 pm_runtime_put_sync (dev );
2612+ gpmc -> is_suspended = 1 ;
2613+
25022614 return 0 ;
25032615}
25042616
25052617static int gpmc_resume (struct device * dev )
25062618{
2619+ struct gpmc_device * gpmc = dev_get_drvdata (dev );
2620+
25072621 pm_runtime_get_sync (dev );
2508- omap3_gpmc_restore_context ();
2622+ omap3_gpmc_restore_context (gpmc );
2623+ gpmc -> is_suspended = 0 ;
2624+
25092625 return 0 ;
25102626}
25112627#endif
@@ -2527,74 +2643,3 @@ static __init int gpmc_init(void)
25272643 return platform_driver_register (& gpmc_driver );
25282644}
25292645postcore_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- }
2599- }
2600- }
0 commit comments