diff options
author | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 04:48:30 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 04:48:30 -0500 |
commit | 617677295b53a40d0e54aac4cbbc216ffbc755dd (patch) | |
tree | 51b9e87213243ed5efff252c8e8d8fec4eebc588 /drivers/devfreq/exynos4_bus.c | |
parent | 5c8d1b68e01a144813e38795fe6dbe7ebb506131 (diff) | |
parent | 6abb7c25775b7fb2225ad0508236d63ca710e65f (diff) |
Merge branch 'master' into for-next
Conflicts:
drivers/devfreq/exynos4_bus.c
Sync with Linus' tree to be able to apply patches that are
against newer code (mvneta).
Diffstat (limited to 'drivers/devfreq/exynos4_bus.c')
-rw-r--r-- | drivers/devfreq/exynos4_bus.c | 145 |
1 files changed, 83 insertions, 62 deletions
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index e1ac076c2917..3f37f3b3f268 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c | |||
@@ -73,6 +73,16 @@ enum busclk_level_idx { | |||
73 | #define EX4210_LV_NUM (LV_2 + 1) | 73 | #define EX4210_LV_NUM (LV_2 + 1) |
74 | #define EX4x12_LV_NUM (LV_4 + 1) | 74 | #define EX4x12_LV_NUM (LV_4 + 1) |
75 | 75 | ||
76 | /** | ||
77 | * struct busfreq_opp_info - opp information for bus | ||
78 | * @rate: Frequency in hertz | ||
79 | * @volt: Voltage in microvolts corresponding to this OPP | ||
80 | */ | ||
81 | struct busfreq_opp_info { | ||
82 | unsigned long rate; | ||
83 | unsigned long volt; | ||
84 | }; | ||
85 | |||
76 | struct busfreq_data { | 86 | struct busfreq_data { |
77 | enum exynos4_busf_type type; | 87 | enum exynos4_busf_type type; |
78 | struct device *dev; | 88 | struct device *dev; |
@@ -80,7 +90,7 @@ struct busfreq_data { | |||
80 | bool disabled; | 90 | bool disabled; |
81 | struct regulator *vdd_int; | 91 | struct regulator *vdd_int; |
82 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ | 92 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ |
83 | struct opp *curr_opp; | 93 | struct busfreq_opp_info curr_oppinfo; |
84 | struct exynos4_ppmu dmc[2]; | 94 | struct exynos4_ppmu dmc[2]; |
85 | 95 | ||
86 | struct notifier_block pm_notifier; | 96 | struct notifier_block pm_notifier; |
@@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = { | |||
296 | }; | 306 | }; |
297 | 307 | ||
298 | 308 | ||
299 | static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | 309 | static int exynos4210_set_busclk(struct busfreq_data *data, |
310 | struct busfreq_opp_info *oppi) | ||
300 | { | 311 | { |
301 | unsigned int index; | 312 | unsigned int index; |
302 | unsigned int tmp; | 313 | unsigned int tmp; |
303 | 314 | ||
304 | for (index = LV_0; index < EX4210_LV_NUM; index++) | 315 | for (index = LV_0; index < EX4210_LV_NUM; index++) |
305 | if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk) | 316 | if (oppi->rate == exynos4210_busclk_table[index].clk) |
306 | break; | 317 | break; |
307 | 318 | ||
308 | if (index == EX4210_LV_NUM) | 319 | if (index == EX4210_LV_NUM) |
@@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | |||
361 | return 0; | 372 | return 0; |
362 | } | 373 | } |
363 | 374 | ||
364 | static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp) | 375 | static int exynos4x12_set_busclk(struct busfreq_data *data, |
376 | struct busfreq_opp_info *oppi) | ||
365 | { | 377 | { |
366 | unsigned int index; | 378 | unsigned int index; |
367 | unsigned int tmp; | 379 | unsigned int tmp; |
368 | 380 | ||
369 | for (index = LV_0; index < EX4x12_LV_NUM; index++) | 381 | for (index = LV_0; index < EX4x12_LV_NUM; index++) |
370 | if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk) | 382 | if (oppi->rate == exynos4x12_mifclk_table[index].clk) |
371 | break; | 383 | break; |
372 | 384 | ||
373 | if (index == EX4x12_LV_NUM) | 385 | if (index == EX4x12_LV_NUM) |
@@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk) | |||
576 | return -EINVAL; | 588 | return -EINVAL; |
577 | } | 589 | } |
578 | 590 | ||
579 | static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | 591 | static int exynos4_bus_setvolt(struct busfreq_data *data, |
580 | struct opp *oldopp) | 592 | struct busfreq_opp_info *oppi, |
593 | struct busfreq_opp_info *oldoppi) | ||
581 | { | 594 | { |
582 | int err = 0, tmp; | 595 | int err = 0, tmp; |
583 | unsigned long volt = opp_get_voltage(opp); | 596 | unsigned long volt = oppi->volt; |
584 | 597 | ||
585 | switch (data->type) { | 598 | switch (data->type) { |
586 | case TYPE_BUSF_EXYNOS4210: | 599 | case TYPE_BUSF_EXYNOS4210: |
@@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
595 | if (err) | 608 | if (err) |
596 | break; | 609 | break; |
597 | 610 | ||
598 | tmp = exynos4x12_get_intspec(opp_get_freq(opp)); | 611 | tmp = exynos4x12_get_intspec(oppi->rate); |
599 | if (tmp < 0) { | 612 | if (tmp < 0) { |
600 | err = tmp; | 613 | err = tmp; |
601 | regulator_set_voltage(data->vdd_mif, | 614 | regulator_set_voltage(data->vdd_mif, |
602 | opp_get_voltage(oldopp), | 615 | oldoppi->volt, |
603 | MAX_SAFEVOLT); | 616 | MAX_SAFEVOLT); |
604 | break; | 617 | break; |
605 | } | 618 | } |
@@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
609 | /* Try to recover */ | 622 | /* Try to recover */ |
610 | if (err) | 623 | if (err) |
611 | regulator_set_voltage(data->vdd_mif, | 624 | regulator_set_voltage(data->vdd_mif, |
612 | opp_get_voltage(oldopp), | 625 | oldoppi->volt, |
613 | MAX_SAFEVOLT); | 626 | MAX_SAFEVOLT); |
614 | break; | 627 | break; |
615 | default: | 628 | default: |
@@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
626 | struct platform_device *pdev = container_of(dev, struct platform_device, | 639 | struct platform_device *pdev = container_of(dev, struct platform_device, |
627 | dev); | 640 | dev); |
628 | struct busfreq_data *data = platform_get_drvdata(pdev); | 641 | struct busfreq_data *data = platform_get_drvdata(pdev); |
629 | struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); | 642 | struct opp *opp; |
630 | unsigned long freq = opp_get_freq(opp); | 643 | unsigned long freq; |
631 | unsigned long old_freq = opp_get_freq(data->curr_opp); | 644 | unsigned long old_freq = data->curr_oppinfo.rate; |
645 | struct busfreq_opp_info new_oppinfo; | ||
632 | 646 | ||
633 | if (IS_ERR(opp)) | 647 | rcu_read_lock(); |
648 | opp = devfreq_recommended_opp(dev, _freq, flags); | ||
649 | if (IS_ERR(opp)) { | ||
650 | rcu_read_unlock(); | ||
634 | return PTR_ERR(opp); | 651 | return PTR_ERR(opp); |
652 | } | ||
653 | new_oppinfo.rate = opp_get_freq(opp); | ||
654 | new_oppinfo.volt = opp_get_voltage(opp); | ||
655 | rcu_read_unlock(); | ||
656 | freq = new_oppinfo.rate; | ||
635 | 657 | ||
636 | if (old_freq == freq) | 658 | if (old_freq == freq) |
637 | return 0; | 659 | return 0; |
638 | 660 | ||
639 | dev_dbg(dev, "targeting %lukHz %luuV\n", freq, opp_get_voltage(opp)); | 661 | dev_dbg(dev, "targeting %lukHz %luuV\n", freq, new_oppinfo.volt); |
640 | 662 | ||
641 | mutex_lock(&data->lock); | 663 | mutex_lock(&data->lock); |
642 | 664 | ||
@@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
644 | goto out; | 666 | goto out; |
645 | 667 | ||
646 | if (old_freq < freq) | 668 | if (old_freq < freq) |
647 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 669 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
670 | &data->curr_oppinfo); | ||
648 | if (err) | 671 | if (err) |
649 | goto out; | 672 | goto out; |
650 | 673 | ||
651 | if (old_freq != freq) { | 674 | if (old_freq != freq) { |
652 | switch (data->type) { | 675 | switch (data->type) { |
653 | case TYPE_BUSF_EXYNOS4210: | 676 | case TYPE_BUSF_EXYNOS4210: |
654 | err = exynos4210_set_busclk(data, opp); | 677 | err = exynos4210_set_busclk(data, &new_oppinfo); |
655 | break; | 678 | break; |
656 | case TYPE_BUSF_EXYNOS4x12: | 679 | case TYPE_BUSF_EXYNOS4x12: |
657 | err = exynos4x12_set_busclk(data, opp); | 680 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
658 | break; | 681 | break; |
659 | default: | 682 | default: |
660 | err = -EINVAL; | 683 | err = -EINVAL; |
@@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
664 | goto out; | 687 | goto out; |
665 | 688 | ||
666 | if (old_freq > freq) | 689 | if (old_freq > freq) |
667 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 690 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
691 | &data->curr_oppinfo); | ||
668 | if (err) | 692 | if (err) |
669 | goto out; | 693 | goto out; |
670 | 694 | ||
671 | data->curr_opp = opp; | 695 | data->curr_oppinfo = new_oppinfo; |
672 | out: | 696 | out: |
673 | mutex_unlock(&data->lock); | 697 | mutex_unlock(&data->lock); |
674 | return err; | 698 | return err; |
@@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev, | |||
702 | 726 | ||
703 | exynos4_read_ppmu(data); | 727 | exynos4_read_ppmu(data); |
704 | busier_dmc = exynos4_get_busier_dmc(data); | 728 | busier_dmc = exynos4_get_busier_dmc(data); |
705 | stat->current_frequency = opp_get_freq(data->curr_opp); | 729 | stat->current_frequency = data->curr_oppinfo.rate; |
706 | 730 | ||
707 | if (busier_dmc) | 731 | if (busier_dmc) |
708 | addr = S5P_VA_DMC1; | 732 | addr = S5P_VA_DMC1; |
@@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
933 | struct busfreq_data *data = container_of(this, struct busfreq_data, | 957 | struct busfreq_data *data = container_of(this, struct busfreq_data, |
934 | pm_notifier); | 958 | pm_notifier); |
935 | struct opp *opp; | 959 | struct opp *opp; |
960 | struct busfreq_opp_info new_oppinfo; | ||
936 | unsigned long maxfreq = ULONG_MAX; | 961 | unsigned long maxfreq = ULONG_MAX; |
937 | int err = 0; | 962 | int err = 0; |
938 | 963 | ||
@@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
943 | 968 | ||
944 | data->disabled = true; | 969 | data->disabled = true; |
945 | 970 | ||
971 | rcu_read_lock(); | ||
946 | opp = opp_find_freq_floor(data->dev, &maxfreq); | 972 | opp = opp_find_freq_floor(data->dev, &maxfreq); |
973 | if (IS_ERR(opp)) { | ||
974 | rcu_read_unlock(); | ||
975 | dev_err(data->dev, "%s: unable to find a min freq\n", | ||
976 | __func__); | ||
977 | return PTR_ERR(opp); | ||
978 | } | ||
979 | new_oppinfo.rate = opp_get_freq(opp); | ||
980 | new_oppinfo.volt = opp_get_voltage(opp); | ||
981 | rcu_read_unlock(); | ||
947 | 982 | ||
948 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 983 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
984 | &data->curr_oppinfo); | ||
949 | if (err) | 985 | if (err) |
950 | goto unlock; | 986 | goto unlock; |
951 | 987 | ||
952 | switch (data->type) { | 988 | switch (data->type) { |
953 | case TYPE_BUSF_EXYNOS4210: | 989 | case TYPE_BUSF_EXYNOS4210: |
954 | err = exynos4210_set_busclk(data, opp); | 990 | err = exynos4210_set_busclk(data, &new_oppinfo); |
955 | break; | 991 | break; |
956 | case TYPE_BUSF_EXYNOS4x12: | 992 | case TYPE_BUSF_EXYNOS4x12: |
957 | err = exynos4x12_set_busclk(data, opp); | 993 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
958 | break; | 994 | break; |
959 | default: | 995 | default: |
960 | err = -EINVAL; | 996 | err = -EINVAL; |
@@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
962 | if (err) | 998 | if (err) |
963 | goto unlock; | 999 | goto unlock; |
964 | 1000 | ||
965 | data->curr_opp = opp; | 1001 | data->curr_oppinfo = new_oppinfo; |
966 | unlock: | 1002 | unlock: |
967 | mutex_unlock(&data->lock); | 1003 | mutex_unlock(&data->lock); |
968 | if (err) | 1004 | if (err) |
@@ -980,14 +1016,14 @@ unlock: | |||
980 | return NOTIFY_DONE; | 1016 | return NOTIFY_DONE; |
981 | } | 1017 | } |
982 | 1018 | ||
983 | static __devinit int exynos4_busfreq_probe(struct platform_device *pdev) | 1019 | static int exynos4_busfreq_probe(struct platform_device *pdev) |
984 | { | 1020 | { |
985 | struct busfreq_data *data; | 1021 | struct busfreq_data *data; |
986 | struct opp *opp; | 1022 | struct opp *opp; |
987 | struct device *dev = &pdev->dev; | 1023 | struct device *dev = &pdev->dev; |
988 | int err = 0; | 1024 | int err = 0; |
989 | 1025 | ||
990 | data = kzalloc(sizeof(struct busfreq_data), GFP_KERNEL); | 1026 | data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL); |
991 | if (data == NULL) { | 1027 | if (data == NULL) { |
992 | dev_err(dev, "Cannot allocate memory.\n"); | 1028 | dev_err(dev, "Cannot allocate memory.\n"); |
993 | return -ENOMEM; | 1029 | return -ENOMEM; |
@@ -1012,75 +1048,60 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev) | |||
1012 | err = -EINVAL; | 1048 | err = -EINVAL; |
1013 | } | 1049 | } |
1014 | if (err) | 1050 | if (err) |
1015 | goto err_regulator; | 1051 | return err; |
1016 | 1052 | ||
1017 | data->vdd_int = regulator_get(dev, "vdd_int"); | 1053 | data->vdd_int = devm_regulator_get(dev, "vdd_int"); |
1018 | if (IS_ERR(data->vdd_int)) { | 1054 | if (IS_ERR(data->vdd_int)) { |
1019 | dev_err(dev, "Cannot get the regulator \"vdd_int\"\n"); | 1055 | dev_err(dev, "Cannot get the regulator \"vdd_int\"\n"); |
1020 | err = PTR_ERR(data->vdd_int); | 1056 | return PTR_ERR(data->vdd_int); |
1021 | goto err_regulator; | ||
1022 | } | 1057 | } |
1023 | if (data->type == TYPE_BUSF_EXYNOS4x12) { | 1058 | if (data->type == TYPE_BUSF_EXYNOS4x12) { |
1024 | data->vdd_mif = regulator_get(dev, "vdd_mif"); | 1059 | data->vdd_mif = devm_regulator_get(dev, "vdd_mif"); |
1025 | if (IS_ERR(data->vdd_mif)) { | 1060 | if (IS_ERR(data->vdd_mif)) { |
1026 | dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n"); | 1061 | dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n"); |
1027 | err = PTR_ERR(data->vdd_mif); | 1062 | return PTR_ERR(data->vdd_mif); |
1028 | regulator_put(data->vdd_int); | ||
1029 | goto err_regulator; | ||
1030 | |||
1031 | } | 1063 | } |
1032 | } | 1064 | } |
1033 | 1065 | ||
1066 | rcu_read_lock(); | ||
1034 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); | 1067 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); |
1035 | if (IS_ERR(opp)) { | 1068 | if (IS_ERR(opp)) { |
1069 | rcu_read_unlock(); | ||
1036 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", | 1070 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", |
1037 | exynos4_devfreq_profile.initial_freq); | 1071 | exynos4_devfreq_profile.initial_freq); |
1038 | err = PTR_ERR(opp); | 1072 | return PTR_ERR(opp); |
1039 | goto err_opp_add; | ||
1040 | } | 1073 | } |
1041 | data->curr_opp = opp; | 1074 | data->curr_oppinfo.rate = opp_get_freq(opp); |
1075 | data->curr_oppinfo.volt = opp_get_voltage(opp); | ||
1076 | rcu_read_unlock(); | ||
1042 | 1077 | ||
1043 | platform_set_drvdata(pdev, data); | 1078 | platform_set_drvdata(pdev, data); |
1044 | 1079 | ||
1045 | busfreq_mon_reset(data); | 1080 | busfreq_mon_reset(data); |
1046 | 1081 | ||
1047 | data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile, | 1082 | data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile, |
1048 | &devfreq_simple_ondemand, NULL); | 1083 | "simple_ondemand", NULL); |
1049 | if (IS_ERR(data->devfreq)) { | 1084 | if (IS_ERR(data->devfreq)) |
1050 | err = PTR_ERR(data->devfreq); | 1085 | return PTR_ERR(data->devfreq); |
1051 | goto err_opp_add; | ||
1052 | } | ||
1053 | 1086 | ||
1054 | devfreq_register_opp_notifier(dev, data->devfreq); | 1087 | devfreq_register_opp_notifier(dev, data->devfreq); |
1055 | 1088 | ||
1056 | err = register_pm_notifier(&data->pm_notifier); | 1089 | err = register_pm_notifier(&data->pm_notifier); |
1057 | if (err) { | 1090 | if (err) { |
1058 | dev_err(dev, "Failed to setup pm notifier\n"); | 1091 | dev_err(dev, "Failed to setup pm notifier\n"); |
1059 | goto err_devfreq_add; | 1092 | devfreq_remove_device(data->devfreq); |
1093 | return err; | ||
1060 | } | 1094 | } |
1061 | 1095 | ||
1062 | return 0; | 1096 | return 0; |
1063 | err_devfreq_add: | ||
1064 | devfreq_remove_device(data->devfreq); | ||
1065 | err_opp_add: | ||
1066 | if (data->vdd_mif) | ||
1067 | regulator_put(data->vdd_mif); | ||
1068 | regulator_put(data->vdd_int); | ||
1069 | err_regulator: | ||
1070 | kfree(data); | ||
1071 | return err; | ||
1072 | } | 1097 | } |
1073 | 1098 | ||
1074 | static __devexit int exynos4_busfreq_remove(struct platform_device *pdev) | 1099 | static int exynos4_busfreq_remove(struct platform_device *pdev) |
1075 | { | 1100 | { |
1076 | struct busfreq_data *data = platform_get_drvdata(pdev); | 1101 | struct busfreq_data *data = platform_get_drvdata(pdev); |
1077 | 1102 | ||
1078 | unregister_pm_notifier(&data->pm_notifier); | 1103 | unregister_pm_notifier(&data->pm_notifier); |
1079 | devfreq_remove_device(data->devfreq); | 1104 | devfreq_remove_device(data->devfreq); |
1080 | regulator_put(data->vdd_int); | ||
1081 | if (data->vdd_mif) | ||
1082 | regulator_put(data->vdd_mif); | ||
1083 | kfree(data); | ||
1084 | 1105 | ||
1085 | return 0; | 1106 | return 0; |
1086 | } | 1107 | } |
@@ -1106,7 +1127,7 @@ static const struct platform_device_id exynos4_busfreq_id[] = { | |||
1106 | 1127 | ||
1107 | static struct platform_driver exynos4_busfreq_driver = { | 1128 | static struct platform_driver exynos4_busfreq_driver = { |
1108 | .probe = exynos4_busfreq_probe, | 1129 | .probe = exynos4_busfreq_probe, |
1109 | .remove = __devexit_p(exynos4_busfreq_remove), | 1130 | .remove = exynos4_busfreq_remove, |
1110 | .id_table = exynos4_busfreq_id, | 1131 | .id_table = exynos4_busfreq_id, |
1111 | .driver = { | 1132 | .driver = { |
1112 | .name = "exynos4-busfreq", | 1133 | .name = "exynos4-busfreq", |