Linux Audio

Check our new training course

Loading...
v3.15
  1/*
  2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  3 *		http://www.samsung.com/
  4 *
  5 * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework
  6 * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com>
  7 * Support for only EXYNOS5250 is present.
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License version 2 as
 11 * published by the Free Software Foundation.
 12 *
 13 */
 14
 15#include <linux/module.h>
 16#include <linux/devfreq.h>
 17#include <linux/io.h>
 18#include <linux/pm_opp.h>
 19#include <linux/slab.h>
 20#include <linux/suspend.h>
 21#include <linux/clk.h>
 22#include <linux/delay.h>
 23#include <linux/platform_device.h>
 24#include <linux/pm_qos.h>
 25#include <linux/regulator/consumer.h>
 26#include <linux/of_address.h>
 27#include <linux/of_platform.h>
 28
 29#include "exynos_ppmu.h"
 30
 31#define MAX_SAFEVOLT			1100000 /* 1.10V */
 32/* Assume that the bus is saturated if the utilization is 25% */
 33#define INT_BUS_SATURATION_RATIO	25
 34
 35enum int_level_idx {
 36	LV_0,
 37	LV_1,
 38	LV_2,
 39	LV_3,
 40	LV_4,
 41	_LV_END
 42};
 43
 44enum exynos_ppmu_list {
 45	PPMU_RIGHT,
 46	PPMU_END,
 47};
 48
 49struct busfreq_data_int {
 50	struct device *dev;
 51	struct devfreq *devfreq;
 52	struct regulator *vdd_int;
 53	struct exynos_ppmu ppmu[PPMU_END];
 54	unsigned long curr_freq;
 55	bool disabled;
 56
 57	struct notifier_block pm_notifier;
 58	struct mutex lock;
 59	struct pm_qos_request int_req;
 60	struct clk *int_clk;
 61};
 62
 63struct int_bus_opp_table {
 64	unsigned int idx;
 65	unsigned long clk;
 66	unsigned long volt;
 67};
 68
 69static struct int_bus_opp_table exynos5_int_opp_table[] = {
 70	{LV_0, 266000, 1025000},
 71	{LV_1, 200000, 1025000},
 72	{LV_2, 160000, 1025000},
 73	{LV_3, 133000, 1025000},
 74	{LV_4, 100000, 1025000},
 75	{0, 0, 0},
 76};
 77
 78static void busfreq_mon_reset(struct busfreq_data_int *data)
 79{
 80	unsigned int i;
 81
 82	for (i = PPMU_RIGHT; i < PPMU_END; i++) {
 83		void __iomem *ppmu_base = data->ppmu[i].hw_base;
 84
 85		/* Reset the performance and cycle counters */
 86		exynos_ppmu_reset(ppmu_base);
 87
 88		/* Setup count registers to monitor read/write transactions */
 89		data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT;
 90		exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3,
 91					data->ppmu[i].event[PPMU_PMNCNT3]);
 92
 93		exynos_ppmu_start(ppmu_base);
 94	}
 95}
 96
 97static void exynos5_read_ppmu(struct busfreq_data_int *data)
 98{
 99	int i, j;
100
101	for (i = PPMU_RIGHT; i < PPMU_END; i++) {
102		void __iomem *ppmu_base = data->ppmu[i].hw_base;
103
104		exynos_ppmu_stop(ppmu_base);
105
106		/* Update local data from PPMU */
107		data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT);
108
109		for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
110			if (data->ppmu[i].event[j] == 0)
111				data->ppmu[i].count[j] = 0;
112			else
113				data->ppmu[i].count[j] =
114					exynos_ppmu_read(ppmu_base, j);
115		}
116	}
117
118	busfreq_mon_reset(data);
119}
120
121static int exynos5_int_setvolt(struct busfreq_data_int *data,
122				unsigned long volt)
123{
124	return regulator_set_voltage(data->vdd_int, volt, MAX_SAFEVOLT);
125}
126
127static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
128			      u32 flags)
129{
130	int err = 0;
131	struct platform_device *pdev = container_of(dev, struct platform_device,
132						    dev);
133	struct busfreq_data_int *data = platform_get_drvdata(pdev);
134	struct dev_pm_opp *opp;
135	unsigned long old_freq, freq;
136	unsigned long volt;
137
138	rcu_read_lock();
139	opp = devfreq_recommended_opp(dev, _freq, flags);
140	if (IS_ERR(opp)) {
141		rcu_read_unlock();
142		dev_err(dev, "%s: Invalid OPP.\n", __func__);
143		return PTR_ERR(opp);
144	}
145
146	freq = dev_pm_opp_get_freq(opp);
147	volt = dev_pm_opp_get_voltage(opp);
148	rcu_read_unlock();
149
150	old_freq = data->curr_freq;
151
152	if (old_freq == freq)
153		return 0;
154
155	dev_dbg(dev, "targeting %lukHz %luuV\n", freq, volt);
156
157	mutex_lock(&data->lock);
158
159	if (data->disabled)
160		goto out;
161
162	if (freq > exynos5_int_opp_table[0].clk)
163		pm_qos_update_request(&data->int_req, freq * 16 / 1000);
164	else
165		pm_qos_update_request(&data->int_req, -1);
166
167	if (old_freq < freq)
168		err = exynos5_int_setvolt(data, volt);
169	if (err)
170		goto out;
171
172	err = clk_set_rate(data->int_clk, freq * 1000);
173
174	if (err)
175		goto out;
176
177	if (old_freq > freq)
178		err = exynos5_int_setvolt(data, volt);
179	if (err)
180		goto out;
181
182	data->curr_freq = freq;
183out:
184	mutex_unlock(&data->lock);
185	return err;
186}
187
188static int exynos5_get_busier_dmc(struct busfreq_data_int *data)
189{
190	int i, j;
191	int busy = 0;
192	unsigned int temp = 0;
193
194	for (i = PPMU_RIGHT; i < PPMU_END; i++) {
195		for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
196			if (data->ppmu[i].count[j] > temp) {
197				temp = data->ppmu[i].count[j];
198				busy = i;
199			}
200		}
201	}
202
203	return busy;
204}
205
206static int exynos5_int_get_dev_status(struct device *dev,
207				      struct devfreq_dev_status *stat)
208{
209	struct platform_device *pdev = container_of(dev, struct platform_device,
210						    dev);
211	struct busfreq_data_int *data = platform_get_drvdata(pdev);
 
212	int busier_dmc;
213
214	exynos5_read_ppmu(data);
215	busier_dmc = exynos5_get_busier_dmc(data);
216
217	stat->current_frequency = data->curr_freq;
218
219	/* Number of cycles spent on memory access */
220	stat->busy_time = data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
221	stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO;
222	stat->total_time = data->ppmu[busier_dmc].ccnt;
223
224	return 0;
225}
226static void exynos5_int_exit(struct device *dev)
227{
228	struct platform_device *pdev = container_of(dev, struct platform_device,
229						    dev);
230	struct busfreq_data_int *data = platform_get_drvdata(pdev);
231
232	devfreq_unregister_opp_notifier(dev, data->devfreq);
233}
234
235static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
236	.initial_freq		= 160000,
237	.polling_ms		= 100,
238	.target			= exynos5_busfreq_int_target,
239	.get_dev_status		= exynos5_int_get_dev_status,
240	.exit			= exynos5_int_exit,
241};
242
243static int exynos5250_init_int_tables(struct busfreq_data_int *data)
244{
245	int i, err = 0;
246
247	for (i = LV_0; i < _LV_END; i++) {
248		err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
249				exynos5_int_opp_table[i].volt);
250		if (err) {
251			dev_err(data->dev, "Cannot add opp entries.\n");
252			return err;
253		}
254	}
255
256	return 0;
257}
258
259static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
260		unsigned long event, void *ptr)
261{
262	struct busfreq_data_int *data = container_of(this,
263					struct busfreq_data_int, pm_notifier);
264	struct dev_pm_opp *opp;
265	unsigned long maxfreq = ULONG_MAX;
266	unsigned long freq;
267	unsigned long volt;
268	int err = 0;
269
270	switch (event) {
271	case PM_SUSPEND_PREPARE:
272		/* Set Fastest and Deactivate DVFS */
273		mutex_lock(&data->lock);
274
275		data->disabled = true;
276
277		rcu_read_lock();
278		opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
279		if (IS_ERR(opp)) {
280			rcu_read_unlock();
281			err = PTR_ERR(opp);
282			goto unlock;
283		}
284		freq = dev_pm_opp_get_freq(opp);
285		volt = dev_pm_opp_get_voltage(opp);
286		rcu_read_unlock();
287
288		err = exynos5_int_setvolt(data, volt);
289		if (err)
290			goto unlock;
291
292		err = clk_set_rate(data->int_clk, freq * 1000);
293
294		if (err)
295			goto unlock;
296
297		data->curr_freq = freq;
298unlock:
299		mutex_unlock(&data->lock);
300		if (err)
301			return NOTIFY_BAD;
302		return NOTIFY_OK;
303	case PM_POST_RESTORE:
304	case PM_POST_SUSPEND:
305		/* Reactivate */
306		mutex_lock(&data->lock);
307		data->disabled = false;
308		mutex_unlock(&data->lock);
309		return NOTIFY_OK;
310	}
311
312	return NOTIFY_DONE;
313}
314
315static int exynos5_busfreq_int_probe(struct platform_device *pdev)
316{
317	struct busfreq_data_int *data;
 
318	struct dev_pm_opp *opp;
319	struct device *dev = &pdev->dev;
320	struct device_node *np;
321	unsigned long initial_freq;
322	unsigned long initial_volt;
323	int err = 0;
324	int i;
325
326	data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data_int),
327				GFP_KERNEL);
328	if (data == NULL) {
329		dev_err(dev, "Cannot allocate memory.\n");
330		return -ENOMEM;
331	}
332
 
 
 
 
 
 
 
 
 
 
333	np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
334	if (np == NULL) {
335		pr_err("Unable to find PPMU node\n");
336		return -ENOENT;
337	}
338
339	for (i = PPMU_RIGHT; i < PPMU_END; i++) {
340		/* map PPMU memory region */
341		data->ppmu[i].hw_base = of_iomap(np, i);
342		if (data->ppmu[i].hw_base == NULL) {
343			dev_err(&pdev->dev, "failed to map memory region\n");
344			return -ENOMEM;
345		}
346	}
347	data->pm_notifier.notifier_call = exynos5_busfreq_int_pm_notifier_event;
348	data->dev = dev;
349	mutex_init(&data->lock);
350
351	err = exynos5250_init_int_tables(data);
352	if (err)
353		return err;
354
355	data->vdd_int = devm_regulator_get(dev, "vdd_int");
356	if (IS_ERR(data->vdd_int)) {
357		dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
358		return PTR_ERR(data->vdd_int);
359	}
360
361	data->int_clk = devm_clk_get(dev, "int_clk");
362	if (IS_ERR(data->int_clk)) {
363		dev_err(dev, "Cannot get clock \"int_clk\"\n");
364		return PTR_ERR(data->int_clk);
365	}
366
367	rcu_read_lock();
368	opp = dev_pm_opp_find_freq_floor(dev,
369			&exynos5_devfreq_int_profile.initial_freq);
370	if (IS_ERR(opp)) {
371		rcu_read_unlock();
372		dev_err(dev, "Invalid initial frequency %lu kHz.\n",
373		       exynos5_devfreq_int_profile.initial_freq);
374		return PTR_ERR(opp);
375	}
376	initial_freq = dev_pm_opp_get_freq(opp);
377	initial_volt = dev_pm_opp_get_voltage(opp);
378	rcu_read_unlock();
379	data->curr_freq = initial_freq;
380
381	err = clk_set_rate(data->int_clk, initial_freq * 1000);
382	if (err) {
383		dev_err(dev, "Failed to set initial frequency\n");
384		return err;
385	}
386
387	err = exynos5_int_setvolt(data, initial_volt);
388	if (err)
389		return err;
390
391	platform_set_drvdata(pdev, data);
392
393	busfreq_mon_reset(data);
394
395	data->devfreq = devfreq_add_device(dev, &exynos5_devfreq_int_profile,
396					   "simple_ondemand", NULL);
 
 
397
398	if (IS_ERR(data->devfreq)) {
399		err = PTR_ERR(data->devfreq);
400		goto err_devfreq_add;
 
401	}
402
403	devfreq_register_opp_notifier(dev, data->devfreq);
404
405	err = register_pm_notifier(&data->pm_notifier);
406	if (err) {
407		dev_err(dev, "Failed to setup pm notifier\n");
408		goto err_devfreq_add;
409	}
410
411	/* TODO: Add a new QOS class for int/mif bus */
412	pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
413
414	return 0;
415
416err_devfreq_add:
417	devfreq_remove_device(data->devfreq);
418	return err;
419}
420
421static int exynos5_busfreq_int_remove(struct platform_device *pdev)
422{
423	struct busfreq_data_int *data = platform_get_drvdata(pdev);
424
425	pm_qos_remove_request(&data->int_req);
426	unregister_pm_notifier(&data->pm_notifier);
427	devfreq_remove_device(data->devfreq);
428
429	return 0;
430}
431
 
432static int exynos5_busfreq_int_resume(struct device *dev)
433{
434	struct platform_device *pdev = container_of(dev, struct platform_device,
435						    dev);
436	struct busfreq_data_int *data = platform_get_drvdata(pdev);
 
437
438	busfreq_mon_reset(data);
439	return 0;
440}
441
442static const struct dev_pm_ops exynos5_busfreq_int_pm = {
443	.resume	= exynos5_busfreq_int_resume,
444};
 
 
 
445
446/* platform device pointer for exynos5 devfreq device. */
447static struct platform_device *exynos5_devfreq_pdev;
448
449static struct platform_driver exynos5_busfreq_int_driver = {
450	.probe		= exynos5_busfreq_int_probe,
451	.remove		= exynos5_busfreq_int_remove,
452	.driver		= {
453		.name		= "exynos5-bus-int",
454		.owner		= THIS_MODULE,
455		.pm		= &exynos5_busfreq_int_pm,
456	},
457};
458
459static int __init exynos5_busfreq_int_init(void)
460{
461	int ret;
462
463	ret = platform_driver_register(&exynos5_busfreq_int_driver);
464	if (ret < 0)
465		goto out;
466
467	exynos5_devfreq_pdev =
468		platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
469	if (IS_ERR(exynos5_devfreq_pdev)) {
470		ret = PTR_ERR(exynos5_devfreq_pdev);
471		goto out1;
472	}
473
474	return 0;
475out1:
476	platform_driver_unregister(&exynos5_busfreq_int_driver);
477out:
478	return ret;
479}
480late_initcall(exynos5_busfreq_int_init);
481
482static void __exit exynos5_busfreq_int_exit(void)
483{
484	platform_device_unregister(exynos5_devfreq_pdev);
485	platform_driver_unregister(&exynos5_busfreq_int_driver);
486}
487module_exit(exynos5_busfreq_int_exit);
488
489MODULE_LICENSE("GPL");
490MODULE_DESCRIPTION("EXYNOS5 busfreq driver with devfreq framework");
v4.6
  1/*
  2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  3 *		http://www.samsung.com/
  4 *
  5 * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework
  6 * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com>
  7 * Support for only EXYNOS5250 is present.
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License version 2 as
 11 * published by the Free Software Foundation.
 12 *
 13 */
 14
 15#include <linux/module.h>
 16#include <linux/devfreq.h>
 17#include <linux/io.h>
 18#include <linux/pm_opp.h>
 19#include <linux/slab.h>
 20#include <linux/suspend.h>
 21#include <linux/clk.h>
 22#include <linux/delay.h>
 23#include <linux/platform_device.h>
 24#include <linux/pm_qos.h>
 25#include <linux/regulator/consumer.h>
 26#include <linux/of_address.h>
 27#include <linux/of_platform.h>
 28
 29#include "exynos_ppmu.h"
 30
 31#define MAX_SAFEVOLT			1100000 /* 1.10V */
 32/* Assume that the bus is saturated if the utilization is 25% */
 33#define INT_BUS_SATURATION_RATIO	25
 34
 35enum int_level_idx {
 36	LV_0,
 37	LV_1,
 38	LV_2,
 39	LV_3,
 40	LV_4,
 41	_LV_END
 42};
 43
 44enum exynos_ppmu_list {
 45	PPMU_RIGHT,
 46	PPMU_END,
 47};
 48
 49struct busfreq_data_int {
 50	struct device *dev;
 51	struct devfreq *devfreq;
 52	struct regulator *vdd_int;
 53	struct busfreq_ppmu_data ppmu_data;
 54	unsigned long curr_freq;
 55	bool disabled;
 56
 57	struct notifier_block pm_notifier;
 58	struct mutex lock;
 59	struct pm_qos_request int_req;
 60	struct clk *int_clk;
 61};
 62
 63struct int_bus_opp_table {
 64	unsigned int idx;
 65	unsigned long clk;
 66	unsigned long volt;
 67};
 68
 69static struct int_bus_opp_table exynos5_int_opp_table[] = {
 70	{LV_0, 266000, 1025000},
 71	{LV_1, 200000, 1025000},
 72	{LV_2, 160000, 1025000},
 73	{LV_3, 133000, 1025000},
 74	{LV_4, 100000, 1025000},
 75	{0, 0, 0},
 76};
 77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 78static int exynos5_int_setvolt(struct busfreq_data_int *data,
 79				unsigned long volt)
 80{
 81	return regulator_set_voltage(data->vdd_int, volt, MAX_SAFEVOLT);
 82}
 83
 84static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
 85			      u32 flags)
 86{
 87	int err = 0;
 88	struct platform_device *pdev = container_of(dev, struct platform_device,
 89						    dev);
 90	struct busfreq_data_int *data = platform_get_drvdata(pdev);
 91	struct dev_pm_opp *opp;
 92	unsigned long old_freq, freq;
 93	unsigned long volt;
 94
 95	rcu_read_lock();
 96	opp = devfreq_recommended_opp(dev, _freq, flags);
 97	if (IS_ERR(opp)) {
 98		rcu_read_unlock();
 99		dev_err(dev, "%s: Invalid OPP.\n", __func__);
100		return PTR_ERR(opp);
101	}
102
103	freq = dev_pm_opp_get_freq(opp);
104	volt = dev_pm_opp_get_voltage(opp);
105	rcu_read_unlock();
106
107	old_freq = data->curr_freq;
108
109	if (old_freq == freq)
110		return 0;
111
112	dev_dbg(dev, "targeting %lukHz %luuV\n", freq, volt);
113
114	mutex_lock(&data->lock);
115
116	if (data->disabled)
117		goto out;
118
119	if (freq > exynos5_int_opp_table[0].clk)
120		pm_qos_update_request(&data->int_req, freq * 16 / 1000);
121	else
122		pm_qos_update_request(&data->int_req, -1);
123
124	if (old_freq < freq)
125		err = exynos5_int_setvolt(data, volt);
126	if (err)
127		goto out;
128
129	err = clk_set_rate(data->int_clk, freq * 1000);
130
131	if (err)
132		goto out;
133
134	if (old_freq > freq)
135		err = exynos5_int_setvolt(data, volt);
136	if (err)
137		goto out;
138
139	data->curr_freq = freq;
140out:
141	mutex_unlock(&data->lock);
142	return err;
143}
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145static int exynos5_int_get_dev_status(struct device *dev,
146				      struct devfreq_dev_status *stat)
147{
148	struct platform_device *pdev = container_of(dev, struct platform_device,
149						    dev);
150	struct busfreq_data_int *data = platform_get_drvdata(pdev);
151	struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
152	int busier_dmc;
153
154	exynos_read_ppmu(ppmu_data);
155	busier_dmc = exynos_get_busier_ppmu(ppmu_data);
156
157	stat->current_frequency = data->curr_freq;
158
159	/* Number of cycles spent on memory access */
160	stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
161	stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO;
162	stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt;
163
164	return 0;
165}
 
 
 
 
 
 
 
 
166
167static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
168	.initial_freq		= 160000,
169	.polling_ms		= 100,
170	.target			= exynos5_busfreq_int_target,
171	.get_dev_status		= exynos5_int_get_dev_status,
 
172};
173
174static int exynos5250_init_int_tables(struct busfreq_data_int *data)
175{
176	int i, err = 0;
177
178	for (i = LV_0; i < _LV_END; i++) {
179		err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
180				exynos5_int_opp_table[i].volt);
181		if (err) {
182			dev_err(data->dev, "Cannot add opp entries.\n");
183			return err;
184		}
185	}
186
187	return 0;
188}
189
190static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
191		unsigned long event, void *ptr)
192{
193	struct busfreq_data_int *data = container_of(this,
194					struct busfreq_data_int, pm_notifier);
195	struct dev_pm_opp *opp;
196	unsigned long maxfreq = ULONG_MAX;
197	unsigned long freq;
198	unsigned long volt;
199	int err = 0;
200
201	switch (event) {
202	case PM_SUSPEND_PREPARE:
203		/* Set Fastest and Deactivate DVFS */
204		mutex_lock(&data->lock);
205
206		data->disabled = true;
207
208		rcu_read_lock();
209		opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
210		if (IS_ERR(opp)) {
211			rcu_read_unlock();
212			err = PTR_ERR(opp);
213			goto unlock;
214		}
215		freq = dev_pm_opp_get_freq(opp);
216		volt = dev_pm_opp_get_voltage(opp);
217		rcu_read_unlock();
218
219		err = exynos5_int_setvolt(data, volt);
220		if (err)
221			goto unlock;
222
223		err = clk_set_rate(data->int_clk, freq * 1000);
224
225		if (err)
226			goto unlock;
227
228		data->curr_freq = freq;
229unlock:
230		mutex_unlock(&data->lock);
231		if (err)
232			return NOTIFY_BAD;
233		return NOTIFY_OK;
234	case PM_POST_RESTORE:
235	case PM_POST_SUSPEND:
236		/* Reactivate */
237		mutex_lock(&data->lock);
238		data->disabled = false;
239		mutex_unlock(&data->lock);
240		return NOTIFY_OK;
241	}
242
243	return NOTIFY_DONE;
244}
245
246static int exynos5_busfreq_int_probe(struct platform_device *pdev)
247{
248	struct busfreq_data_int *data;
249	struct busfreq_ppmu_data *ppmu_data;
250	struct dev_pm_opp *opp;
251	struct device *dev = &pdev->dev;
252	struct device_node *np;
253	unsigned long initial_freq;
254	unsigned long initial_volt;
255	int err = 0;
256	int i;
257
258	data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data_int),
259				GFP_KERNEL);
260	if (data == NULL) {
261		dev_err(dev, "Cannot allocate memory.\n");
262		return -ENOMEM;
263	}
264
265	ppmu_data = &data->ppmu_data;
266	ppmu_data->ppmu_end = PPMU_END;
267	ppmu_data->ppmu = devm_kzalloc(dev,
268				       sizeof(struct exynos_ppmu) * PPMU_END,
269				       GFP_KERNEL);
270	if (!ppmu_data->ppmu) {
271		dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
272		return -ENOMEM;
273	}
274
275	np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
276	if (np == NULL) {
277		pr_err("Unable to find PPMU node\n");
278		return -ENOENT;
279	}
280
281	for (i = 0; i < ppmu_data->ppmu_end; i++) {
282		/* map PPMU memory region */
283		ppmu_data->ppmu[i].hw_base = of_iomap(np, i);
284		if (ppmu_data->ppmu[i].hw_base == NULL) {
285			dev_err(&pdev->dev, "failed to map memory region\n");
286			return -ENOMEM;
287		}
288	}
289	data->pm_notifier.notifier_call = exynos5_busfreq_int_pm_notifier_event;
290	data->dev = dev;
291	mutex_init(&data->lock);
292
293	err = exynos5250_init_int_tables(data);
294	if (err)
295		return err;
296
297	data->vdd_int = devm_regulator_get(dev, "vdd_int");
298	if (IS_ERR(data->vdd_int)) {
299		dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
300		return PTR_ERR(data->vdd_int);
301	}
302
303	data->int_clk = devm_clk_get(dev, "int_clk");
304	if (IS_ERR(data->int_clk)) {
305		dev_err(dev, "Cannot get clock \"int_clk\"\n");
306		return PTR_ERR(data->int_clk);
307	}
308
309	rcu_read_lock();
310	opp = dev_pm_opp_find_freq_floor(dev,
311			&exynos5_devfreq_int_profile.initial_freq);
312	if (IS_ERR(opp)) {
313		rcu_read_unlock();
314		dev_err(dev, "Invalid initial frequency %lu kHz.\n",
315		       exynos5_devfreq_int_profile.initial_freq);
316		return PTR_ERR(opp);
317	}
318	initial_freq = dev_pm_opp_get_freq(opp);
319	initial_volt = dev_pm_opp_get_voltage(opp);
320	rcu_read_unlock();
321	data->curr_freq = initial_freq;
322
323	err = clk_set_rate(data->int_clk, initial_freq * 1000);
324	if (err) {
325		dev_err(dev, "Failed to set initial frequency\n");
326		return err;
327	}
328
329	err = exynos5_int_setvolt(data, initial_volt);
330	if (err)
331		return err;
332
333	platform_set_drvdata(pdev, data);
334
335	busfreq_mon_reset(ppmu_data);
336
337	data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile,
338					   "simple_ondemand", NULL);
339	if (IS_ERR(data->devfreq))
340		return PTR_ERR(data->devfreq);
341
342	err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
343	if (err < 0) {
344		dev_err(dev, "Failed to register opp notifier\n");
345		return err;
346	}
347
 
 
348	err = register_pm_notifier(&data->pm_notifier);
349	if (err) {
350		dev_err(dev, "Failed to setup pm notifier\n");
351		return err;
352	}
353
354	/* TODO: Add a new QOS class for int/mif bus */
355	pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
356
357	return 0;
 
 
 
 
358}
359
360static int exynos5_busfreq_int_remove(struct platform_device *pdev)
361{
362	struct busfreq_data_int *data = platform_get_drvdata(pdev);
363
364	pm_qos_remove_request(&data->int_req);
365	unregister_pm_notifier(&data->pm_notifier);
 
366
367	return 0;
368}
369
370#ifdef CONFIG_PM_SLEEP
371static int exynos5_busfreq_int_resume(struct device *dev)
372{
373	struct platform_device *pdev = container_of(dev, struct platform_device,
374						    dev);
375	struct busfreq_data_int *data = platform_get_drvdata(pdev);
376	struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
377
378	busfreq_mon_reset(ppmu_data);
379	return 0;
380}
 
381static const struct dev_pm_ops exynos5_busfreq_int_pm = {
382	.resume	= exynos5_busfreq_int_resume,
383};
384#endif
385static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL,
386			 exynos5_busfreq_int_resume);
387
388/* platform device pointer for exynos5 devfreq device. */
389static struct platform_device *exynos5_devfreq_pdev;
390
391static struct platform_driver exynos5_busfreq_int_driver = {
392	.probe		= exynos5_busfreq_int_probe,
393	.remove		= exynos5_busfreq_int_remove,
394	.driver		= {
395		.name		= "exynos5-bus-int",
396		.pm		= &exynos5_busfreq_int_pm_ops,
 
397	},
398};
399
400static int __init exynos5_busfreq_int_init(void)
401{
402	int ret;
403
404	ret = platform_driver_register(&exynos5_busfreq_int_driver);
405	if (ret < 0)
406		goto out;
407
408	exynos5_devfreq_pdev =
409		platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
410	if (IS_ERR(exynos5_devfreq_pdev)) {
411		ret = PTR_ERR(exynos5_devfreq_pdev);
412		goto out1;
413	}
414
415	return 0;
416out1:
417	platform_driver_unregister(&exynos5_busfreq_int_driver);
418out:
419	return ret;
420}
421late_initcall(exynos5_busfreq_int_init);
422
423static void __exit exynos5_busfreq_int_exit(void)
424{
425	platform_device_unregister(exynos5_devfreq_pdev);
426	platform_driver_unregister(&exynos5_busfreq_int_driver);
427}
428module_exit(exynos5_busfreq_int_exit);
429
430MODULE_LICENSE("GPL");
431MODULE_DESCRIPTION("EXYNOS5 busfreq driver with devfreq framework");