Blame view

drivers/cpuidle/cpuidle-exynos.c 3.42 KB
712eddf70   Bartlomiej Zolnierkiewicz   cpuidle: exynos: ...
1
2
  /*
   * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
3d7399855   Jaecheol Lee   ARM: EXYNOS4: CPU...
3
4
   *		http://www.samsung.com
   *
712eddf70   Bartlomiej Zolnierkiewicz   cpuidle: exynos: ...
5
6
7
8
   * Coupled cpuidle support based on the work of:
   *	Colin Cross <ccross@android.com>
   *	Daniel Lezcano <daniel.lezcano@linaro.org>
   *
3d7399855   Jaecheol Lee   ARM: EXYNOS4: CPU...
9
10
11
12
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
  */
3d7399855   Jaecheol Lee   ARM: EXYNOS4: CPU...
13
  #include <linux/cpuidle.h>
67173ca49   Amit Daniel Kachhap   ARM: EXYNOS: Add ...
14
  #include <linux/cpu_pm.h>
76ee45571   Kyungmin Park   ARM: EXYNOS: Fix ...
15
  #include <linux/export.h>
84599238e   Paul Gortmaker   drivers/cpuidle: ...
16
  #include <linux/init.h>
35baa3369   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: conv...
17
  #include <linux/platform_device.h>
712eddf70   Bartlomiej Zolnierkiewicz   cpuidle: exynos: ...
18
19
  #include <linux/of.h>
  #include <linux/platform_data/cpuidle-exynos.h>
3d7399855   Jaecheol Lee   ARM: EXYNOS4: CPU...
20

67173ca49   Amit Daniel Kachhap   ARM: EXYNOS: Add ...
21
  #include <asm/suspend.h>
06c77b3ce   Amit Daniel Kachhap   ARM: EXYNOS: Adap...
22
  #include <asm/cpuidle.h>
67173ca49   Amit Daniel Kachhap   ARM: EXYNOS: Add ...
23

712eddf70   Bartlomiej Zolnierkiewicz   cpuidle: exynos: ...
24
25
26
  static atomic_t exynos_idle_barrier;
  
  static struct cpuidle_exynos_data *exynos_cpuidle_pdata;
277f50464   Daniel Lezcano   ARM: EXYNOS: Pass...
27
  static void (*exynos_enter_aftr)(void);
ccd458c15   Kukjin Kim   ARM: EXYNOS: move...
28

712eddf70   Bartlomiej Zolnierkiewicz   cpuidle: exynos: ...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  static int exynos_enter_coupled_lowpower(struct cpuidle_device *dev,
  					 struct cpuidle_driver *drv,
  					 int index)
  {
  	int ret;
  
  	exynos_cpuidle_pdata->pre_enter_aftr();
  
  	/*
  	 * Waiting all cpus to reach this point at the same moment
  	 */
  	cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
  
  	/*
  	 * Both cpus will reach this point at the same time
  	 */
  	ret = dev->cpu ? exynos_cpuidle_pdata->cpu1_powerdown()
  		       : exynos_cpuidle_pdata->cpu0_enter_aftr();
  	if (ret)
  		index = ret;
  
  	/*
  	 * Waiting all cpus to finish the power sequence before going further
  	 */
  	cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
  
  	exynos_cpuidle_pdata->post_enter_aftr();
  
  	return index;
  }
7880e45ed   Daniel Lezcano   ARM: EXYNOS: Chan...
59
  static int exynos_enter_lowpower(struct cpuidle_device *dev,
67173ca49   Amit Daniel Kachhap   ARM: EXYNOS: Add ...
60
61
62
63
  				struct cpuidle_driver *drv,
  				int index)
  {
  	int new_index = index;
118f5c1d5   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: cpui...
64
65
  	/* AFTR can only be entered when cores other than CPU0 are offline */
  	if (num_online_cpus() > 1 || dev->cpu != 0)
67173ca49   Amit Daniel Kachhap   ARM: EXYNOS: Add ...
66
67
68
  		new_index = drv->safe_state_index;
  
  	if (new_index == 0)
06c77b3ce   Amit Daniel Kachhap   ARM: EXYNOS: Adap...
69
  		return arm_cpuidle_simple_enter(dev, drv, new_index);
01601b349   Tomasz Figa   ARM: EXYNOS: Fix ...
70
71
72
73
  
  	exynos_enter_aftr();
  
  	return new_index;
67173ca49   Amit Daniel Kachhap   ARM: EXYNOS: Add ...
74
  }
7880e45ed   Daniel Lezcano   ARM: EXYNOS: Chan...
75
76
  static struct cpuidle_driver exynos_idle_driver = {
  	.name			= "exynos_idle",
53af16a1a   Daniel Lezcano   ARM: EXYNOS: Prev...
77
78
79
80
  	.owner			= THIS_MODULE,
  	.states = {
  		[0] = ARM_CPUIDLE_WFI_STATE,
  		[1] = {
7880e45ed   Daniel Lezcano   ARM: EXYNOS: Chan...
81
  			.enter			= exynos_enter_lowpower,
53af16a1a   Daniel Lezcano   ARM: EXYNOS: Prev...
82
  			.exit_latency		= 300,
c324f43ae   Marek Szyprowski   cpuidle: exynos: ...
83
  			.target_residency	= 10000,
53af16a1a   Daniel Lezcano   ARM: EXYNOS: Prev...
84
85
86
87
88
89
90
  			.name			= "C1",
  			.desc			= "ARM power down",
  		},
  	},
  	.state_count = 2,
  	.safe_state_index = 0,
  };
712eddf70   Bartlomiej Zolnierkiewicz   cpuidle: exynos: ...
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  static struct cpuidle_driver exynos_coupled_idle_driver = {
  	.name			= "exynos_coupled_idle",
  	.owner			= THIS_MODULE,
  	.states = {
  		[0] = ARM_CPUIDLE_WFI_STATE,
  		[1] = {
  			.enter			= exynos_enter_coupled_lowpower,
  			.exit_latency		= 5000,
  			.target_residency	= 10000,
  			.flags			= CPUIDLE_FLAG_COUPLED |
  						  CPUIDLE_FLAG_TIMER_STOP,
  			.name			= "C1",
  			.desc			= "ARM power down",
  		},
  	},
  	.state_count = 2,
  	.safe_state_index = 0,
  };
f612a4fbd   Jingoo Han   ARM: EXYNOS: Remo...
109
  static int exynos_cpuidle_probe(struct platform_device *pdev)
3d7399855   Jaecheol Lee   ARM: EXYNOS4: CPU...
110
  {
043c86b6f   Daniel Lezcano   ARM: EXYNOS: Use ...
111
  	int ret;
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
112

cfdda3535   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: Fix ...
113
  	if (IS_ENABLED(CONFIG_SMP) &&
8919d779f   Marek Szyprowski   cpuidle: Enable c...
114
115
  	    (of_machine_is_compatible("samsung,exynos4210") ||
  	     of_machine_is_compatible("samsung,exynos3250"))) {
712eddf70   Bartlomiej Zolnierkiewicz   cpuidle: exynos: ...
116
117
118
119
120
121
122
123
124
  		exynos_cpuidle_pdata = pdev->dev.platform_data;
  
  		ret = cpuidle_register(&exynos_coupled_idle_driver,
  				       cpu_possible_mask);
  	} else {
  		exynos_enter_aftr = (void *)(pdev->dev.platform_data);
  
  		ret = cpuidle_register(&exynos_idle_driver, NULL);
  	}
277f50464   Daniel Lezcano   ARM: EXYNOS: Pass...
125

5db9f4362   Daniel Lezcano   ARM: EXYNOS: hand...
126
  	if (ret) {
ae7c4c878   Jingoo Han   ARM: EXYNOS: Use ...
127
128
  		dev_err(&pdev->dev, "failed to register cpuidle driver
  ");
5db9f4362   Daniel Lezcano   ARM: EXYNOS: hand...
129
  		return ret;
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
130
  	}
3d7399855   Jaecheol Lee   ARM: EXYNOS4: CPU...
131

3d7399855   Jaecheol Lee   ARM: EXYNOS4: CPU...
132
133
  	return 0;
  }
35baa3369   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: conv...
134
135
136
137
138
  
  static struct platform_driver exynos_cpuidle_driver = {
  	.probe	= exynos_cpuidle_probe,
  	.driver = {
  		.name = "exynos_cpuidle",
35baa3369   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: conv...
139
140
  	},
  };
84599238e   Paul Gortmaker   drivers/cpuidle: ...
141
  builtin_platform_driver(exynos_cpuidle_driver);