81 lines
		
	
	
	
		
			1.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			81 lines
		
	
	
	
		
			1.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright 2012 Freescale Semiconductor, Inc.
							 | 
						||
| 
								 | 
							
								 * Copyright 2012 Linaro Ltd.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The code contained herein is licensed under the GNU General Public
							 | 
						||
| 
								 | 
							
								 * License. You may obtain a copy of the GNU General Public License
							 | 
						||
| 
								 | 
							
								 * Version 2 or later at the following locations:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * http://www.opensource.org/licenses/gpl-license.html
							 | 
						||
| 
								 | 
							
								 * http://www.gnu.org/copyleft/gpl.html
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <linux/cpuidle.h>
							 | 
						||
| 
								 | 
							
								#include <linux/err.h>
							 | 
						||
| 
								 | 
							
								#include <linux/hrtimer.h>
							 | 
						||
| 
								 | 
							
								#include <linux/io.h>
							 | 
						||
| 
								 | 
							
								#include <linux/kernel.h>
							 | 
						||
| 
								 | 
							
								#include <linux/slab.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static struct cpuidle_device __percpu * imx_cpuidle_devices;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void __init imx_cpuidle_devices_uninit(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int cpu_id;
							 | 
						||
| 
								 | 
							
									struct cpuidle_device *dev;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for_each_possible_cpu(cpu_id) {
							 | 
						||
| 
								 | 
							
										dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
							 | 
						||
| 
								 | 
							
										cpuidle_unregister_device(dev);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									free_percpu(imx_cpuidle_devices);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int __init imx_cpuidle_init(struct cpuidle_driver *drv)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct cpuidle_device *dev;
							 | 
						||
| 
								 | 
							
									int cpu_id, ret;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (drv->state_count > CPUIDLE_STATE_MAX) {
							 | 
						||
| 
								 | 
							
										pr_err("%s: state_count exceeds maximum\n", __func__);
							 | 
						||
| 
								 | 
							
										return -EINVAL;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ret = cpuidle_register_driver(drv);
							 | 
						||
| 
								 | 
							
									if (ret) {
							 | 
						||
| 
								 | 
							
										pr_err("%s: Failed to register cpuidle driver with error: %d\n",
							 | 
						||
| 
								 | 
							
											 __func__, ret);
							 | 
						||
| 
								 | 
							
										return ret;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
							 | 
						||
| 
								 | 
							
									if (imx_cpuidle_devices == NULL) {
							 | 
						||
| 
								 | 
							
										ret = -ENOMEM;
							 | 
						||
| 
								 | 
							
										goto unregister_drv;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* initialize state data for each cpuidle_device */
							 | 
						||
| 
								 | 
							
									for_each_possible_cpu(cpu_id) {
							 | 
						||
| 
								 | 
							
										dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
							 | 
						||
| 
								 | 
							
										dev->cpu = cpu_id;
							 | 
						||
| 
								 | 
							
										dev->state_count = drv->state_count;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										ret = cpuidle_register_device(dev);
							 | 
						||
| 
								 | 
							
										if (ret) {
							 | 
						||
| 
								 | 
							
											pr_err("%s: Failed to register cpu %u, error: %d\n",
							 | 
						||
| 
								 | 
							
												__func__, cpu_id, ret);
							 | 
						||
| 
								 | 
							
											goto uninit;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uninit:
							 | 
						||
| 
								 | 
							
									imx_cpuidle_devices_uninit();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								unregister_drv:
							 | 
						||
| 
								 | 
							
									cpuidle_unregister_driver(drv);
							 | 
						||
| 
								 | 
							
									return ret;
							 | 
						||
| 
								 | 
							
								}
							 |