exynos5422-dmc.c (d51e6a69f4e9e81cf75bbfdccce60d47e31ad901) | exynos5422-dmc.c (bbf918863e183d66adf00ca1b24fb641149a0d3d) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2019 Samsung Electronics Co., Ltd. 4 * Author: Lukasz Luba <l.luba@partner.samsung.com> 5 */ 6 7#include <linux/clk.h> 8#include <linux/devfreq.h> 9#include <linux/devfreq-event.h> 10#include <linux/device.h> | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2019 Samsung Electronics Co., Ltd. 4 * Author: Lukasz Luba <l.luba@partner.samsung.com> 5 */ 6 7#include <linux/clk.h> 8#include <linux/devfreq.h> 9#include <linux/devfreq-event.h> 10#include <linux/device.h> |
11#include <linux/interrupt.h> |
|
11#include <linux/io.h> 12#include <linux/mfd/syscon.h> 13#include <linux/module.h> 14#include <linux/of_device.h> 15#include <linux/pm_opp.h> 16#include <linux/platform_device.h> 17#include <linux/regmap.h> 18#include <linux/regulator/consumer.h> --- 11 unchanged lines hidden (view full) --- 30#define CDREX_PAUSE (0x2091c) 31#define CDREX_LPDDR3PHY_CON3 (0x20a20) 32#define CDREX_LPDDR3PHY_CLKM_SRC (0x20700) 33#define EXYNOS5_TIMING_SET_SWI BIT(28) 34#define USE_MX_MSPLL_TIMINGS (1) 35#define USE_BPLL_TIMINGS (0) 36#define EXYNOS5_AREF_NORMAL (0x2e) 37 | 12#include <linux/io.h> 13#include <linux/mfd/syscon.h> 14#include <linux/module.h> 15#include <linux/of_device.h> 16#include <linux/pm_opp.h> 17#include <linux/platform_device.h> 18#include <linux/regmap.h> 19#include <linux/regulator/consumer.h> --- 11 unchanged lines hidden (view full) --- 31#define CDREX_PAUSE (0x2091c) 32#define CDREX_LPDDR3PHY_CON3 (0x20a20) 33#define CDREX_LPDDR3PHY_CLKM_SRC (0x20700) 34#define EXYNOS5_TIMING_SET_SWI BIT(28) 35#define USE_MX_MSPLL_TIMINGS (1) 36#define USE_BPLL_TIMINGS (0) 37#define EXYNOS5_AREF_NORMAL (0x2e) 38 |
39#define DREX_PPCCLKCON (0x0130) 40#define DREX_PEREV2CONFIG (0x013c) 41#define DREX_PMNC_PPC (0xE000) 42#define DREX_CNTENS_PPC (0xE010) 43#define DREX_CNTENC_PPC (0xE020) 44#define DREX_INTENS_PPC (0xE030) 45#define DREX_INTENC_PPC (0xE040) 46#define DREX_FLAG_PPC (0xE050) 47#define DREX_PMCNT2_PPC (0xE130) 48 49/* 50 * A value for register DREX_PMNC_PPC which should be written to reset 51 * the cycle counter CCNT (a reference wall clock). It sets zero to the 52 * CCNT counter. 53 */ 54#define CC_RESET BIT(2) 55 56/* 57 * A value for register DREX_PMNC_PPC which does the reset of all performance 58 * counters to zero. 59 */ 60#define PPC_COUNTER_RESET BIT(1) 61 62/* 63 * Enables all configured counters (including cycle counter). The value should 64 * be written to the register DREX_PMNC_PPC. 65 */ 66#define PPC_ENABLE BIT(0) 67 68/* A value for register DREX_PPCCLKCON which enables performance events clock. 69 * Must be written before first access to the performance counters register 70 * set, otherwise it could crash. 71 */ 72#define PEREV_CLK_EN BIT(0) 73 74/* 75 * Values which are used to enable counters, interrupts or configure flags of 76 * the performance counters. They configure counter 2 and cycle counter. 77 */ 78#define PERF_CNT2 BIT(2) 79#define PERF_CCNT BIT(31) 80 81/* 82 * Performance event types which are used for setting the preferred event 83 * to track in the counters. 84 * There is a set of different types, the values are from range 0 to 0x6f. 85 * These settings should be written to the configuration register which manages 86 * the type of the event (register DREX_PEREV2CONFIG). 87 */ 88#define READ_TRANSFER_CH0 (0x6d) 89#define READ_TRANSFER_CH1 (0x6f) 90 91#define PERF_COUNTER_START_VALUE 0xff000000 92#define PERF_EVENT_UP_DOWN_THRESHOLD 900000000ULL 93 |
|
38/** 39 * struct dmc_opp_table - Operating level desciption 40 * 41 * Covers frequency and voltage settings of the DMC operating mode. 42 */ 43struct dmc_opp_table { 44 u32 freq_hz; 45 u32 volt_uv; --- 34 unchanged lines hidden (view full) --- 80 struct clk *mout_spll; 81 struct clk *mout_bpll; 82 struct clk *mout_mclk_cdrex; 83 struct clk *mout_mx_mspll_ccore; 84 struct clk *mx_mspll_ccore_phy; 85 struct clk *mout_mx_mspll_ccore_phy; 86 struct devfreq_event_dev **counter; 87 int num_counters; | 94/** 95 * struct dmc_opp_table - Operating level desciption 96 * 97 * Covers frequency and voltage settings of the DMC operating mode. 98 */ 99struct dmc_opp_table { 100 u32 freq_hz; 101 u32 volt_uv; --- 34 unchanged lines hidden (view full) --- 136 struct clk *mout_spll; 137 struct clk *mout_bpll; 138 struct clk *mout_mclk_cdrex; 139 struct clk *mout_mx_mspll_ccore; 140 struct clk *mx_mspll_ccore_phy; 141 struct clk *mout_mx_mspll_ccore_phy; 142 struct devfreq_event_dev **counter; 143 int num_counters; |
144 u64 last_overflow_ts[2]; 145 unsigned long load; 146 unsigned long total; 147 bool in_irq_mode; |
|
88}; 89 90#define TIMING_FIELD(t_name, t_bit_beg, t_bit_end) \ 91 { .name = t_name, .bit_beg = t_bit_beg, .bit_end = t_bit_end } 92 93#define TIMING_VAL2REG(timing, t_val) \ 94({ \ 95 u32 __val; \ --- 553 unchanged lines hidden (view full) --- 649 } 650 651 *total_count = total; 652 653 return 0; 654} 655 656/** | 148}; 149 150#define TIMING_FIELD(t_name, t_bit_beg, t_bit_end) \ 151 { .name = t_name, .bit_beg = t_bit_beg, .bit_end = t_bit_end } 152 153#define TIMING_VAL2REG(timing, t_val) \ 154({ \ 155 u32 __val; \ --- 553 unchanged lines hidden (view full) --- 709 } 710 711 *total_count = total; 712 713 return 0; 714} 715 716/** |
717 * exynos5_dmc_start_perf_events() - Setup and start performance event counters 718 * @dmc: device for which the counters are going to be checked 719 * @beg_value: initial value for the counter 720 * 721 * Function which enables needed counters, interrupts and sets initial values 722 * then starts the counters. 723 */ 724static void exynos5_dmc_start_perf_events(struct exynos5_dmc *dmc, 725 u32 beg_value) 726{ 727 /* Enable interrupts for counter 2 */ 728 writel(PERF_CNT2, dmc->base_drexi0 + DREX_INTENS_PPC); 729 writel(PERF_CNT2, dmc->base_drexi1 + DREX_INTENS_PPC); 730 731 /* Enable counter 2 and CCNT */ 732 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_CNTENS_PPC); 733 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_CNTENS_PPC); 734 735 /* Clear overflow flag for all counters */ 736 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_FLAG_PPC); 737 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_FLAG_PPC); 738 739 /* Reset all counters */ 740 writel(CC_RESET | PPC_COUNTER_RESET, dmc->base_drexi0 + DREX_PMNC_PPC); 741 writel(CC_RESET | PPC_COUNTER_RESET, dmc->base_drexi1 + DREX_PMNC_PPC); 742 743 /* 744 * Set start value for the counters, the number of samples that 745 * will be gathered is calculated as: 0xffffffff - beg_value 746 */ 747 writel(beg_value, dmc->base_drexi0 + DREX_PMCNT2_PPC); 748 writel(beg_value, dmc->base_drexi1 + DREX_PMCNT2_PPC); 749 750 /* Start all counters */ 751 writel(PPC_ENABLE, dmc->base_drexi0 + DREX_PMNC_PPC); 752 writel(PPC_ENABLE, dmc->base_drexi1 + DREX_PMNC_PPC); 753} 754 755/** 756 * exynos5_dmc_perf_events_calc() - Calculate utilization 757 * @dmc: device for which the counters are going to be checked 758 * @diff_ts: time between last interrupt and current one 759 * 760 * Function which calculates needed utilization for the devfreq governor. 761 * It prepares values for 'busy_time' and 'total_time' based on elapsed time 762 * between interrupts, which approximates utilization. 763 */ 764static void exynos5_dmc_perf_events_calc(struct exynos5_dmc *dmc, u64 diff_ts) 765{ 766 /* 767 * This is a simple algorithm for managing traffic on DMC. 768 * When there is almost no load the counters overflow every 4s, 769 * no mater the DMC frequency. 770 * The high load might be approximated using linear function. 771 * Knowing that, simple calculation can provide 'busy_time' and 772 * 'total_time' to the devfreq governor which picks up target 773 * frequency. 774 * We want a fast ramp up and slow decay in frequency change function. 775 */ 776 if (diff_ts < PERF_EVENT_UP_DOWN_THRESHOLD) { 777 /* 778 * Set higher utilization for the simple_ondemand governor. 779 * The governor should increase the frequency of the DMC. 780 */ 781 dmc->load = 70; 782 dmc->total = 100; 783 } else { 784 /* 785 * Set low utilization for the simple_ondemand governor. 786 * The governor should decrease the frequency of the DMC. 787 */ 788 dmc->load = 35; 789 dmc->total = 100; 790 } 791 792 dev_dbg(dmc->dev, "diff_ts=%llu\n", diff_ts); 793} 794 795/** 796 * exynos5_dmc_perf_events_check() - Checks the status of the counters 797 * @dmc: device for which the counters are going to be checked 798 * 799 * Function which is called from threaded IRQ to check the counters state 800 * and to call approximation for the needed utilization. 801 */ 802static void exynos5_dmc_perf_events_check(struct exynos5_dmc *dmc) 803{ 804 u32 val; 805 u64 diff_ts, ts; 806 807 ts = ktime_get_ns(); 808 809 /* Stop all counters */ 810 writel(0, dmc->base_drexi0 + DREX_PMNC_PPC); 811 writel(0, dmc->base_drexi1 + DREX_PMNC_PPC); 812 813 /* Check the source in interrupt flag registers (which channel) */ 814 val = readl(dmc->base_drexi0 + DREX_FLAG_PPC); 815 if (val) { 816 diff_ts = ts - dmc->last_overflow_ts[0]; 817 dmc->last_overflow_ts[0] = ts; 818 dev_dbg(dmc->dev, "drex0 0xE050 val= 0x%08x\n", val); 819 } else { 820 val = readl(dmc->base_drexi1 + DREX_FLAG_PPC); 821 diff_ts = ts - dmc->last_overflow_ts[1]; 822 dmc->last_overflow_ts[1] = ts; 823 dev_dbg(dmc->dev, "drex1 0xE050 val= 0x%08x\n", val); 824 } 825 826 exynos5_dmc_perf_events_calc(dmc, diff_ts); 827 828 exynos5_dmc_start_perf_events(dmc, PERF_COUNTER_START_VALUE); 829} 830 831/** 832 * exynos5_dmc_enable_perf_events() - Enable performance events 833 * @dmc: device for which the counters are going to be checked 834 * 835 * Function which is setup needed environment and enables counters. 836 */ 837static void exynos5_dmc_enable_perf_events(struct exynos5_dmc *dmc) 838{ 839 u64 ts; 840 841 /* Enable Performance Event Clock */ 842 writel(PEREV_CLK_EN, dmc->base_drexi0 + DREX_PPCCLKCON); 843 writel(PEREV_CLK_EN, dmc->base_drexi1 + DREX_PPCCLKCON); 844 845 /* Select read transfers as performance event2 */ 846 writel(READ_TRANSFER_CH0, dmc->base_drexi0 + DREX_PEREV2CONFIG); 847 writel(READ_TRANSFER_CH1, dmc->base_drexi1 + DREX_PEREV2CONFIG); 848 849 ts = ktime_get_ns(); 850 dmc->last_overflow_ts[0] = ts; 851 dmc->last_overflow_ts[1] = ts; 852 853 /* Devfreq shouldn't be faster than initialization, play safe though. */ 854 dmc->load = 99; 855 dmc->total = 100; 856} 857 858/** 859 * exynos5_dmc_disable_perf_events() - Disable performance events 860 * @dmc: device for which the counters are going to be checked 861 * 862 * Function which stops, disables performance event counters and interrupts. 863 */ 864static void exynos5_dmc_disable_perf_events(struct exynos5_dmc *dmc) 865{ 866 /* Stop all counters */ 867 writel(0, dmc->base_drexi0 + DREX_PMNC_PPC); 868 writel(0, dmc->base_drexi1 + DREX_PMNC_PPC); 869 870 /* Disable interrupts for counter 2 */ 871 writel(PERF_CNT2, dmc->base_drexi0 + DREX_INTENC_PPC); 872 writel(PERF_CNT2, dmc->base_drexi1 + DREX_INTENC_PPC); 873 874 /* Disable counter 2 and CCNT */ 875 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_CNTENC_PPC); 876 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_CNTENC_PPC); 877 878 /* Clear overflow flag for all counters */ 879 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_FLAG_PPC); 880 writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_FLAG_PPC); 881} 882 883/** |
|
657 * exynos5_dmc_get_status() - Read current DMC performance statistics. 658 * @dev: device for which the statistics are requested 659 * @stat: structure which has statistic fields 660 * 661 * Function reads the DMC performance counters and calculates 'busy_time' 662 * and 'total_time'. To protect from overflow, the values are shifted right 663 * by 10. After read out the counters are setup to count again. 664 */ 665static int exynos5_dmc_get_status(struct device *dev, 666 struct devfreq_dev_status *stat) 667{ 668 struct exynos5_dmc *dmc = dev_get_drvdata(dev); 669 unsigned long load, total; 670 int ret; 671 | 884 * exynos5_dmc_get_status() - Read current DMC performance statistics. 885 * @dev: device for which the statistics are requested 886 * @stat: structure which has statistic fields 887 * 888 * Function reads the DMC performance counters and calculates 'busy_time' 889 * and 'total_time'. To protect from overflow, the values are shifted right 890 * by 10. After read out the counters are setup to count again. 891 */ 892static int exynos5_dmc_get_status(struct device *dev, 893 struct devfreq_dev_status *stat) 894{ 895 struct exynos5_dmc *dmc = dev_get_drvdata(dev); 896 unsigned long load, total; 897 int ret; 898 |
672 ret = exynos5_counters_get(dmc, &load, &total); 673 if (ret < 0) 674 return -EINVAL; | 899 if (dmc->in_irq_mode) { 900 stat->current_frequency = dmc->curr_rate; 901 stat->busy_time = dmc->load; 902 stat->total_time = dmc->total; 903 } else { 904 ret = exynos5_counters_get(dmc, &load, &total); 905 if (ret < 0) 906 return -EINVAL; |
675 | 907 |
676 /* To protect from overflow in calculation ratios, divide by 1024 */ 677 stat->busy_time = load >> 10; 678 stat->total_time = total >> 10; | 908 /* To protect from overflow, divide by 1024 */ 909 stat->busy_time = load >> 10; 910 stat->total_time = total >> 10; |
679 | 911 |
680 ret = exynos5_counters_set_event(dmc); 681 if (ret < 0) { 682 dev_err(dev, "could not set event counter\n"); 683 return ret; | 912 ret = exynos5_counters_set_event(dmc); 913 if (ret < 0) { 914 dev_err(dev, "could not set event counter\n"); 915 return ret; 916 } |
684 } 685 686 return 0; 687} 688 689/** 690 * exynos5_dmc_get_cur_freq() - Function returns current DMC frequency 691 * @dev: device for which the framework checks operating frequency --- 15 unchanged lines hidden (view full) --- 707} 708 709/** 710 * exynos5_dmc_df_profile - Devfreq governor's profile structure 711 * 712 * It provides to the devfreq framework needed functions and polling period. 713 */ 714static struct devfreq_dev_profile exynos5_dmc_df_profile = { | 917 } 918 919 return 0; 920} 921 922/** 923 * exynos5_dmc_get_cur_freq() - Function returns current DMC frequency 924 * @dev: device for which the framework checks operating frequency --- 15 unchanged lines hidden (view full) --- 940} 941 942/** 943 * exynos5_dmc_df_profile - Devfreq governor's profile structure 944 * 945 * It provides to the devfreq framework needed functions and polling period. 946 */ 947static struct devfreq_dev_profile exynos5_dmc_df_profile = { |
715 .polling_ms = 500, | |
716 .target = exynos5_dmc_target, 717 .get_dev_status = exynos5_dmc_get_status, 718 .get_cur_freq = exynos5_dmc_get_cur_freq, 719}; 720 721/** 722 * exynos5_dmc_align_initial_frequency() - Align initial frequency value 723 * @dmc: device for which the frequency is going to be set --- 379 unchanged lines hidden (view full) --- 1103 return ret; 1104 1105 val |= 1UL; 1106 regmap_write(dmc->clk_regmap, CDREX_PAUSE, val); 1107 1108 return 0; 1109} 1110 | 948 .target = exynos5_dmc_target, 949 .get_dev_status = exynos5_dmc_get_status, 950 .get_cur_freq = exynos5_dmc_get_cur_freq, 951}; 952 953/** 954 * exynos5_dmc_align_initial_frequency() - Align initial frequency value 955 * @dmc: device for which the frequency is going to be set --- 379 unchanged lines hidden (view full) --- 1335 return ret; 1336 1337 val |= 1UL; 1338 regmap_write(dmc->clk_regmap, CDREX_PAUSE, val); 1339 1340 return 0; 1341} 1342 |
1343static irqreturn_t dmc_irq_thread(int irq, void *priv) 1344{ 1345 int res; 1346 struct exynos5_dmc *dmc = priv; 1347 1348 mutex_lock(&dmc->df->lock); 1349 1350 exynos5_dmc_perf_events_check(dmc); 1351 1352 res = update_devfreq(dmc->df); 1353 if (res) 1354 dev_warn(dmc->dev, "devfreq failed with %d\n", res); 1355 1356 mutex_unlock(&dmc->df->lock); 1357 1358 return IRQ_HANDLED; 1359} 1360 |
|
1111/** 1112 * exynos5_dmc_probe() - Probe function for the DMC driver 1113 * @pdev: platform device for which the driver is going to be initialized 1114 * 1115 * Initialize basic components: clocks, regulators, performance counters, etc. 1116 * Read out product version and based on the information setup 1117 * internal structures for the controller (frequency and voltage) and for DRAM 1118 * memory parameters: timings for each operating frequency. 1119 * Register new devfreq device for controlling DVFS of the DMC. 1120 */ 1121static int exynos5_dmc_probe(struct platform_device *pdev) 1122{ 1123 int ret = 0; 1124 struct device *dev = &pdev->dev; 1125 struct device_node *np = dev->of_node; 1126 struct exynos5_dmc *dmc; 1127 struct resource *res; | 1361/** 1362 * exynos5_dmc_probe() - Probe function for the DMC driver 1363 * @pdev: platform device for which the driver is going to be initialized 1364 * 1365 * Initialize basic components: clocks, regulators, performance counters, etc. 1366 * Read out product version and based on the information setup 1367 * internal structures for the controller (frequency and voltage) and for DRAM 1368 * memory parameters: timings for each operating frequency. 1369 * Register new devfreq device for controlling DVFS of the DMC. 1370 */ 1371static int exynos5_dmc_probe(struct platform_device *pdev) 1372{ 1373 int ret = 0; 1374 struct device *dev = &pdev->dev; 1375 struct device_node *np = dev->of_node; 1376 struct exynos5_dmc *dmc; 1377 struct resource *res; |
1378 int irq[2]; |
|
1128 1129 dmc = devm_kzalloc(dev, sizeof(*dmc), GFP_KERNEL); 1130 if (!dmc) 1131 return -ENOMEM; 1132 1133 mutex_init(&dmc->lock); 1134 1135 dmc->dev = dev; --- 31 unchanged lines hidden (view full) --- 1167 return ret; 1168 1169 ret = of_get_dram_timings(dmc); 1170 if (ret) { 1171 dev_warn(dev, "couldn't initialize timings settings\n"); 1172 goto remove_clocks; 1173 } 1174 | 1379 1380 dmc = devm_kzalloc(dev, sizeof(*dmc), GFP_KERNEL); 1381 if (!dmc) 1382 return -ENOMEM; 1383 1384 mutex_init(&dmc->lock); 1385 1386 dmc->dev = dev; --- 31 unchanged lines hidden (view full) --- 1418 return ret; 1419 1420 ret = of_get_dram_timings(dmc); 1421 if (ret) { 1422 dev_warn(dev, "couldn't initialize timings settings\n"); 1423 goto remove_clocks; 1424 } 1425 |
1175 ret = exynos5_performance_counters_init(dmc); | 1426 ret = exynos5_dmc_set_pause_on_switching(dmc); |
1176 if (ret) { | 1427 if (ret) { |
1177 dev_warn(dev, "couldn't probe performance counters\n"); | 1428 dev_warn(dev, "couldn't get access to PAUSE register\n"); |
1178 goto remove_clocks; 1179 } 1180 | 1429 goto remove_clocks; 1430 } 1431 |
1181 ret = exynos5_dmc_set_pause_on_switching(dmc); 1182 if (ret) { 1183 dev_warn(dev, "couldn't get access to PAUSE register\n"); 1184 goto err_devfreq_add; | 1432 /* There is two modes in which the driver works: polling or IRQ */ 1433 irq[0] = platform_get_irq_byname(pdev, "drex_0"); 1434 irq[1] = platform_get_irq_byname(pdev, "drex_1"); 1435 if (irq[0] > 0 && irq[1] > 0) { 1436 ret = devm_request_threaded_irq(dev, irq[0], NULL, 1437 dmc_irq_thread, IRQF_ONESHOT, 1438 dev_name(dev), dmc); 1439 if (ret) { 1440 dev_err(dev, "couldn't grab IRQ\n"); 1441 goto remove_clocks; 1442 } 1443 1444 ret = devm_request_threaded_irq(dev, irq[1], NULL, 1445 dmc_irq_thread, IRQF_ONESHOT, 1446 dev_name(dev), dmc); 1447 if (ret) { 1448 dev_err(dev, "couldn't grab IRQ\n"); 1449 goto remove_clocks; 1450 } 1451 1452 /* 1453 * Setup default thresholds for the devfreq governor. 1454 * The values are chosen based on experiments. 1455 */ 1456 dmc->gov_data.upthreshold = 55; 1457 dmc->gov_data.downdifferential = 5; 1458 1459 exynos5_dmc_enable_perf_events(dmc); 1460 1461 dmc->in_irq_mode = 1; 1462 } else { 1463 ret = exynos5_performance_counters_init(dmc); 1464 if (ret) { 1465 dev_warn(dev, "couldn't probe performance counters\n"); 1466 goto remove_clocks; 1467 } 1468 1469 /* 1470 * Setup default thresholds for the devfreq governor. 1471 * The values are chosen based on experiments. 1472 */ 1473 dmc->gov_data.upthreshold = 30; 1474 dmc->gov_data.downdifferential = 5; 1475 1476 exynos5_dmc_df_profile.polling_ms = 500; |
1185 } 1186 | 1477 } 1478 |
1187 /* 1188 * Setup default thresholds for the devfreq governor. 1189 * The values are chosen based on experiments. 1190 */ 1191 dmc->gov_data.upthreshold = 30; 1192 dmc->gov_data.downdifferential = 5; | |
1193 1194 dmc->df = devm_devfreq_add_device(dev, &exynos5_dmc_df_profile, 1195 DEVFREQ_GOV_SIMPLE_ONDEMAND, 1196 &dmc->gov_data); 1197 1198 if (IS_ERR(dmc->df)) { 1199 ret = PTR_ERR(dmc->df); 1200 goto err_devfreq_add; 1201 } 1202 | 1479 1480 dmc->df = devm_devfreq_add_device(dev, &exynos5_dmc_df_profile, 1481 DEVFREQ_GOV_SIMPLE_ONDEMAND, 1482 &dmc->gov_data); 1483 1484 if (IS_ERR(dmc->df)) { 1485 ret = PTR_ERR(dmc->df); 1486 goto err_devfreq_add; 1487 } 1488 |
1489 if (dmc->in_irq_mode) 1490 exynos5_dmc_start_perf_events(dmc, PERF_COUNTER_START_VALUE); 1491 |
|
1203 dev_info(dev, "DMC initialized\n"); 1204 1205 return 0; 1206 1207err_devfreq_add: | 1492 dev_info(dev, "DMC initialized\n"); 1493 1494 return 0; 1495 1496err_devfreq_add: |
1208 exynos5_counters_disable_edev(dmc); | 1497 if (dmc->in_irq_mode) 1498 exynos5_dmc_disable_perf_events(dmc); 1499 else 1500 exynos5_counters_disable_edev(dmc); |
1209remove_clocks: 1210 clk_disable_unprepare(dmc->mout_bpll); 1211 clk_disable_unprepare(dmc->fout_bpll); 1212 1213 return ret; 1214} 1215 1216/** 1217 * exynos5_dmc_remove() - Remove function for the platform device 1218 * @pdev: platform device which is going to be removed 1219 * 1220 * The function relies on 'devm' framework function which automatically 1221 * clean the device's resources. It just calls explicitly disable function for 1222 * the performance counters. 1223 */ 1224static int exynos5_dmc_remove(struct platform_device *pdev) 1225{ 1226 struct exynos5_dmc *dmc = dev_get_drvdata(&pdev->dev); 1227 | 1501remove_clocks: 1502 clk_disable_unprepare(dmc->mout_bpll); 1503 clk_disable_unprepare(dmc->fout_bpll); 1504 1505 return ret; 1506} 1507 1508/** 1509 * exynos5_dmc_remove() - Remove function for the platform device 1510 * @pdev: platform device which is going to be removed 1511 * 1512 * The function relies on 'devm' framework function which automatically 1513 * clean the device's resources. It just calls explicitly disable function for 1514 * the performance counters. 1515 */ 1516static int exynos5_dmc_remove(struct platform_device *pdev) 1517{ 1518 struct exynos5_dmc *dmc = dev_get_drvdata(&pdev->dev); 1519 |
1228 exynos5_counters_disable_edev(dmc); | 1520 if (dmc->in_irq_mode) 1521 exynos5_dmc_disable_perf_events(dmc); 1522 else 1523 exynos5_counters_disable_edev(dmc); |
1229 1230 clk_disable_unprepare(dmc->mout_bpll); 1231 clk_disable_unprepare(dmc->fout_bpll); 1232 1233 dev_pm_opp_remove_table(dmc->dev); 1234 1235 return 0; 1236} --- 19 unchanged lines hidden --- | 1524 1525 clk_disable_unprepare(dmc->mout_bpll); 1526 clk_disable_unprepare(dmc->fout_bpll); 1527 1528 dev_pm_opp_remove_table(dmc->dev); 1529 1530 return 0; 1531} --- 19 unchanged lines hidden --- |