0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/io.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/of_address.h>
0016 #include <linux/of_device.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/regmap.h>
0019 #include <linux/suspend.h>
0020 #include <linux/devfreq-event.h>
0021
0022 #include "exynos-ppmu.h"
0023
0024 enum exynos_ppmu_type {
0025 EXYNOS_TYPE_PPMU,
0026 EXYNOS_TYPE_PPMU_V2,
0027 };
0028
0029 struct exynos_ppmu_data {
0030 struct clk *clk;
0031 };
0032
0033 struct exynos_ppmu {
0034 struct devfreq_event_dev **edev;
0035 struct devfreq_event_desc *desc;
0036 unsigned int num_events;
0037
0038 struct device *dev;
0039 struct regmap *regmap;
0040
0041 struct exynos_ppmu_data ppmu;
0042 enum exynos_ppmu_type ppmu_type;
0043 };
0044
0045 #define PPMU_EVENT(name) \
0046 { "ppmu-event0-"#name, PPMU_PMNCNT0 }, \
0047 { "ppmu-event1-"#name, PPMU_PMNCNT1 }, \
0048 { "ppmu-event2-"#name, PPMU_PMNCNT2 }, \
0049 { "ppmu-event3-"#name, PPMU_PMNCNT3 }
0050
0051 static struct __exynos_ppmu_events {
0052 char *name;
0053 int id;
0054 } ppmu_events[] = {
0055
0056 PPMU_EVENT(g3d),
0057 PPMU_EVENT(fsys),
0058
0059
0060 PPMU_EVENT(dmc0),
0061 PPMU_EVENT(dmc1),
0062 PPMU_EVENT(cpu),
0063 PPMU_EVENT(rightbus),
0064 PPMU_EVENT(leftbus),
0065 PPMU_EVENT(lcd0),
0066 PPMU_EVENT(camif),
0067
0068
0069 PPMU_EVENT(mfc),
0070
0071
0072 PPMU_EVENT(mfc-left),
0073 PPMU_EVENT(mfc-right),
0074
0075
0076 PPMU_EVENT(drex0-s0),
0077 PPMU_EVENT(drex0-s1),
0078 PPMU_EVENT(drex1-s0),
0079 PPMU_EVENT(drex1-s1),
0080 PPMU_EVENT(eagle),
0081 PPMU_EVENT(kfc),
0082 PPMU_EVENT(isp),
0083 PPMU_EVENT(fimc),
0084 PPMU_EVENT(gscl),
0085 PPMU_EVENT(mscl),
0086 PPMU_EVENT(fimd0x),
0087 PPMU_EVENT(fimd1x),
0088
0089
0090 PPMU_EVENT(d0-cpu),
0091 PPMU_EVENT(d0-general),
0092 PPMU_EVENT(d0-rt),
0093 PPMU_EVENT(d1-cpu),
0094 PPMU_EVENT(d1-general),
0095 PPMU_EVENT(d1-rt),
0096
0097
0098 PPMU_EVENT(dmc0_0),
0099 PPMU_EVENT(dmc0_1),
0100 PPMU_EVENT(dmc1_0),
0101 PPMU_EVENT(dmc1_1),
0102
0103 PPMU_EVENT(dmc0-0),
0104 PPMU_EVENT(dmc0-1),
0105 PPMU_EVENT(dmc1-0),
0106 PPMU_EVENT(dmc1-1),
0107 };
0108
0109 static int __exynos_ppmu_find_ppmu_id(const char *edev_name)
0110 {
0111 int i;
0112
0113 for (i = 0; i < ARRAY_SIZE(ppmu_events); i++)
0114 if (!strcmp(edev_name, ppmu_events[i].name))
0115 return ppmu_events[i].id;
0116
0117 return -EINVAL;
0118 }
0119
0120 static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
0121 {
0122 return __exynos_ppmu_find_ppmu_id(edev->desc->name);
0123 }
0124
0125
0126
0127
0128 static int exynos_ppmu_disable(struct devfreq_event_dev *edev)
0129 {
0130 struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
0131 int ret;
0132 u32 pmnc;
0133
0134
0135 ret = regmap_write(info->regmap, PPMU_CNTENC,
0136 PPMU_CCNT_MASK |
0137 PPMU_PMCNT0_MASK |
0138 PPMU_PMCNT1_MASK |
0139 PPMU_PMCNT2_MASK |
0140 PPMU_PMCNT3_MASK);
0141 if (ret < 0)
0142 return ret;
0143
0144
0145 ret = regmap_read(info->regmap, PPMU_PMNC, &pmnc);
0146 if (ret < 0)
0147 return ret;
0148
0149 pmnc &= ~PPMU_PMNC_ENABLE_MASK;
0150 ret = regmap_write(info->regmap, PPMU_PMNC, pmnc);
0151 if (ret < 0)
0152 return ret;
0153
0154 return 0;
0155 }
0156
0157 static int exynos_ppmu_set_event(struct devfreq_event_dev *edev)
0158 {
0159 struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
0160 int id = exynos_ppmu_find_ppmu_id(edev);
0161 int ret;
0162 u32 pmnc, cntens;
0163
0164 if (id < 0)
0165 return id;
0166
0167
0168 ret = regmap_read(info->regmap, PPMU_CNTENS, &cntens);
0169 if (ret < 0)
0170 return ret;
0171
0172 cntens |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
0173 ret = regmap_write(info->regmap, PPMU_CNTENS, cntens);
0174 if (ret < 0)
0175 return ret;
0176
0177
0178 ret = regmap_write(info->regmap, PPMU_BEVTxSEL(id),
0179 edev->desc->event_type);
0180 if (ret < 0)
0181 return ret;
0182
0183
0184 ret = regmap_read(info->regmap, PPMU_PMNC, &pmnc);
0185 if (ret < 0)
0186 return ret;
0187
0188 pmnc &= ~(PPMU_PMNC_ENABLE_MASK
0189 | PPMU_PMNC_COUNTER_RESET_MASK
0190 | PPMU_PMNC_CC_RESET_MASK);
0191 pmnc |= (PPMU_ENABLE << PPMU_PMNC_ENABLE_SHIFT);
0192 pmnc |= (PPMU_ENABLE << PPMU_PMNC_COUNTER_RESET_SHIFT);
0193 pmnc |= (PPMU_ENABLE << PPMU_PMNC_CC_RESET_SHIFT);
0194 ret = regmap_write(info->regmap, PPMU_PMNC, pmnc);
0195 if (ret < 0)
0196 return ret;
0197
0198 return 0;
0199 }
0200
0201 static int exynos_ppmu_get_event(struct devfreq_event_dev *edev,
0202 struct devfreq_event_data *edata)
0203 {
0204 struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
0205 int id = exynos_ppmu_find_ppmu_id(edev);
0206 unsigned int total_count, load_count;
0207 unsigned int pmcnt3_high, pmcnt3_low;
0208 unsigned int pmnc, cntenc;
0209 int ret;
0210
0211 if (id < 0)
0212 return -EINVAL;
0213
0214
0215 ret = regmap_read(info->regmap, PPMU_PMNC, &pmnc);
0216 if (ret < 0)
0217 return ret;
0218
0219 pmnc &= ~PPMU_PMNC_ENABLE_MASK;
0220 ret = regmap_write(info->regmap, PPMU_PMNC, pmnc);
0221 if (ret < 0)
0222 return ret;
0223
0224
0225 ret = regmap_read(info->regmap, PPMU_CCNT, &total_count);
0226 if (ret < 0)
0227 return ret;
0228 edata->total_count = total_count;
0229
0230
0231 switch (id) {
0232 case PPMU_PMNCNT0:
0233 case PPMU_PMNCNT1:
0234 case PPMU_PMNCNT2:
0235 ret = regmap_read(info->regmap, PPMU_PMNCT(id), &load_count);
0236 if (ret < 0)
0237 return ret;
0238 edata->load_count = load_count;
0239 break;
0240 case PPMU_PMNCNT3:
0241 ret = regmap_read(info->regmap, PPMU_PMCNT3_HIGH, &pmcnt3_high);
0242 if (ret < 0)
0243 return ret;
0244
0245 ret = regmap_read(info->regmap, PPMU_PMCNT3_LOW, &pmcnt3_low);
0246 if (ret < 0)
0247 return ret;
0248
0249 edata->load_count = ((pmcnt3_high << 8) | pmcnt3_low);
0250 break;
0251 default:
0252 return -EINVAL;
0253 }
0254
0255
0256 ret = regmap_read(info->regmap, PPMU_CNTENC, &cntenc);
0257 if (ret < 0)
0258 return ret;
0259
0260 cntenc |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
0261 ret = regmap_write(info->regmap, PPMU_CNTENC, cntenc);
0262 if (ret < 0)
0263 return ret;
0264
0265 dev_dbg(&edev->dev, "%s (event: %ld/%ld)\n", edev->desc->name,
0266 edata->load_count, edata->total_count);
0267
0268 return 0;
0269 }
0270
0271 static const struct devfreq_event_ops exynos_ppmu_ops = {
0272 .disable = exynos_ppmu_disable,
0273 .set_event = exynos_ppmu_set_event,
0274 .get_event = exynos_ppmu_get_event,
0275 };
0276
0277
0278
0279
0280 static int exynos_ppmu_v2_disable(struct devfreq_event_dev *edev)
0281 {
0282 struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
0283 int ret;
0284 u32 pmnc, clear;
0285
0286
0287 clear = (PPMU_CCNT_MASK | PPMU_PMCNT0_MASK | PPMU_PMCNT1_MASK
0288 | PPMU_PMCNT2_MASK | PPMU_PMCNT3_MASK);
0289 ret = regmap_write(info->regmap, PPMU_V2_FLAG, clear);
0290 if (ret < 0)
0291 return ret;
0292
0293 ret = regmap_write(info->regmap, PPMU_V2_INTENC, clear);
0294 if (ret < 0)
0295 return ret;
0296
0297 ret = regmap_write(info->regmap, PPMU_V2_CNTENC, clear);
0298 if (ret < 0)
0299 return ret;
0300
0301 ret = regmap_write(info->regmap, PPMU_V2_CNT_RESET, clear);
0302 if (ret < 0)
0303 return ret;
0304
0305 ret = regmap_write(info->regmap, PPMU_V2_CIG_CFG0, 0x0);
0306 if (ret < 0)
0307 return ret;
0308
0309 ret = regmap_write(info->regmap, PPMU_V2_CIG_CFG1, 0x0);
0310 if (ret < 0)
0311 return ret;
0312
0313 ret = regmap_write(info->regmap, PPMU_V2_CIG_CFG2, 0x0);
0314 if (ret < 0)
0315 return ret;
0316
0317 ret = regmap_write(info->regmap, PPMU_V2_CIG_RESULT, 0x0);
0318 if (ret < 0)
0319 return ret;
0320
0321 ret = regmap_write(info->regmap, PPMU_V2_CNT_AUTO, 0x0);
0322 if (ret < 0)
0323 return ret;
0324
0325 ret = regmap_write(info->regmap, PPMU_V2_CH_EV0_TYPE, 0x0);
0326 if (ret < 0)
0327 return ret;
0328
0329 ret = regmap_write(info->regmap, PPMU_V2_CH_EV1_TYPE, 0x0);
0330 if (ret < 0)
0331 return ret;
0332
0333 ret = regmap_write(info->regmap, PPMU_V2_CH_EV2_TYPE, 0x0);
0334 if (ret < 0)
0335 return ret;
0336
0337 ret = regmap_write(info->regmap, PPMU_V2_CH_EV3_TYPE, 0x0);
0338 if (ret < 0)
0339 return ret;
0340
0341 ret = regmap_write(info->regmap, PPMU_V2_SM_ID_V, 0x0);
0342 if (ret < 0)
0343 return ret;
0344
0345 ret = regmap_write(info->regmap, PPMU_V2_SM_ID_A, 0x0);
0346 if (ret < 0)
0347 return ret;
0348
0349 ret = regmap_write(info->regmap, PPMU_V2_SM_OTHERS_V, 0x0);
0350 if (ret < 0)
0351 return ret;
0352
0353 ret = regmap_write(info->regmap, PPMU_V2_SM_OTHERS_A, 0x0);
0354 if (ret < 0)
0355 return ret;
0356
0357 ret = regmap_write(info->regmap, PPMU_V2_INTERRUPT_RESET, 0x0);
0358 if (ret < 0)
0359 return ret;
0360
0361
0362 ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc);
0363 if (ret < 0)
0364 return ret;
0365
0366 pmnc &= ~PPMU_PMNC_ENABLE_MASK;
0367 ret = regmap_write(info->regmap, PPMU_V2_PMNC, pmnc);
0368 if (ret < 0)
0369 return ret;
0370
0371 return 0;
0372 }
0373
0374 static int exynos_ppmu_v2_set_event(struct devfreq_event_dev *edev)
0375 {
0376 struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
0377 unsigned int pmnc, cntens;
0378 int id = exynos_ppmu_find_ppmu_id(edev);
0379 int ret;
0380
0381
0382 ret = regmap_read(info->regmap, PPMU_V2_CNTENS, &cntens);
0383 if (ret < 0)
0384 return ret;
0385
0386 cntens |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
0387 ret = regmap_write(info->regmap, PPMU_V2_CNTENS, cntens);
0388 if (ret < 0)
0389 return ret;
0390
0391
0392 ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id),
0393 edev->desc->event_type);
0394 if (ret < 0)
0395 return ret;
0396
0397
0398 ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc);
0399 if (ret < 0)
0400 return ret;
0401
0402 pmnc &= ~(PPMU_PMNC_ENABLE_MASK
0403 | PPMU_PMNC_COUNTER_RESET_MASK
0404 | PPMU_PMNC_CC_RESET_MASK
0405 | PPMU_PMNC_CC_DIVIDER_MASK
0406 | PPMU_V2_PMNC_START_MODE_MASK);
0407 pmnc |= (PPMU_ENABLE << PPMU_PMNC_ENABLE_SHIFT);
0408 pmnc |= (PPMU_ENABLE << PPMU_PMNC_COUNTER_RESET_SHIFT);
0409 pmnc |= (PPMU_ENABLE << PPMU_PMNC_CC_RESET_SHIFT);
0410 pmnc |= (PPMU_V2_MODE_MANUAL << PPMU_V2_PMNC_START_MODE_SHIFT);
0411
0412 ret = regmap_write(info->regmap, PPMU_V2_PMNC, pmnc);
0413 if (ret < 0)
0414 return ret;
0415
0416 return 0;
0417 }
0418
0419 static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev,
0420 struct devfreq_event_data *edata)
0421 {
0422 struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
0423 int id = exynos_ppmu_find_ppmu_id(edev);
0424 int ret;
0425 unsigned int pmnc, cntenc;
0426 unsigned int pmcnt_high, pmcnt_low;
0427 unsigned int total_count, count;
0428 unsigned long load_count = 0;
0429
0430
0431 ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc);
0432 if (ret < 0)
0433 return ret;
0434
0435 pmnc &= ~PPMU_PMNC_ENABLE_MASK;
0436 ret = regmap_write(info->regmap, PPMU_V2_PMNC, pmnc);
0437 if (ret < 0)
0438 return ret;
0439
0440
0441 ret = regmap_read(info->regmap, PPMU_V2_CCNT, &total_count);
0442 if (ret < 0)
0443 return ret;
0444 edata->total_count = total_count;
0445
0446 switch (id) {
0447 case PPMU_PMNCNT0:
0448 case PPMU_PMNCNT1:
0449 case PPMU_PMNCNT2:
0450 ret = regmap_read(info->regmap, PPMU_V2_PMNCT(id), &count);
0451 if (ret < 0)
0452 return ret;
0453 load_count = count;
0454 break;
0455 case PPMU_PMNCNT3:
0456 ret = regmap_read(info->regmap, PPMU_V2_PMCNT3_HIGH,
0457 &pmcnt_high);
0458 if (ret < 0)
0459 return ret;
0460
0461 ret = regmap_read(info->regmap, PPMU_V2_PMCNT3_LOW, &pmcnt_low);
0462 if (ret < 0)
0463 return ret;
0464
0465 load_count = ((u64)((pmcnt_high & 0xff)) << 32)+ (u64)pmcnt_low;
0466 break;
0467 }
0468 edata->load_count = load_count;
0469
0470
0471 ret = regmap_read(info->regmap, PPMU_V2_CNTENC, &cntenc);
0472 if (ret < 0)
0473 return 0;
0474
0475 cntenc |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
0476 ret = regmap_write(info->regmap, PPMU_V2_CNTENC, cntenc);
0477 if (ret < 0)
0478 return ret;
0479
0480 dev_dbg(&edev->dev, "%25s (load: %ld / %ld)\n", edev->desc->name,
0481 edata->load_count, edata->total_count);
0482 return 0;
0483 }
0484
0485 static const struct devfreq_event_ops exynos_ppmu_v2_ops = {
0486 .disable = exynos_ppmu_v2_disable,
0487 .set_event = exynos_ppmu_v2_set_event,
0488 .get_event = exynos_ppmu_v2_get_event,
0489 };
0490
0491 static const struct of_device_id exynos_ppmu_id_match[] = {
0492 {
0493 .compatible = "samsung,exynos-ppmu",
0494 .data = (void *)EXYNOS_TYPE_PPMU,
0495 }, {
0496 .compatible = "samsung,exynos-ppmu-v2",
0497 .data = (void *)EXYNOS_TYPE_PPMU_V2,
0498 },
0499 { },
0500 };
0501 MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match);
0502
0503 static int of_get_devfreq_events(struct device_node *np,
0504 struct exynos_ppmu *info)
0505 {
0506 struct devfreq_event_desc *desc;
0507 struct device *dev = info->dev;
0508 struct device_node *events_np, *node;
0509 int i, j, count;
0510 const struct of_device_id *of_id;
0511 int ret;
0512
0513 events_np = of_get_child_by_name(np, "events");
0514 if (!events_np) {
0515 dev_err(dev,
0516 "failed to get child node of devfreq-event devices\n");
0517 return -EINVAL;
0518 }
0519
0520 count = of_get_child_count(events_np);
0521 desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
0522 if (!desc) {
0523 of_node_put(events_np);
0524 return -ENOMEM;
0525 }
0526 info->num_events = count;
0527
0528 of_id = of_match_device(exynos_ppmu_id_match, dev);
0529 if (of_id)
0530 info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
0531 else {
0532 of_node_put(events_np);
0533 return -EINVAL;
0534 }
0535
0536 j = 0;
0537 for_each_child_of_node(events_np, node) {
0538 for (i = 0; i < ARRAY_SIZE(ppmu_events); i++) {
0539 if (!ppmu_events[i].name)
0540 continue;
0541
0542 if (of_node_name_eq(node, ppmu_events[i].name))
0543 break;
0544 }
0545
0546 if (i == ARRAY_SIZE(ppmu_events)) {
0547 dev_warn(dev,
0548 "don't know how to configure events : %pOFn\n",
0549 node);
0550 continue;
0551 }
0552
0553 switch (info->ppmu_type) {
0554 case EXYNOS_TYPE_PPMU:
0555 desc[j].ops = &exynos_ppmu_ops;
0556 break;
0557 case EXYNOS_TYPE_PPMU_V2:
0558 desc[j].ops = &exynos_ppmu_v2_ops;
0559 break;
0560 }
0561
0562 desc[j].driver_data = info;
0563
0564 of_property_read_string(node, "event-name", &desc[j].name);
0565 ret = of_property_read_u32(node, "event-data-type",
0566 &desc[j].event_type);
0567 if (ret) {
0568
0569
0570
0571
0572 if (info->ppmu_type == EXYNOS_TYPE_PPMU_V2) {
0573
0574
0575
0576 switch (ppmu_events[i].id) {
0577 case PPMU_PMNCNT0:
0578 case PPMU_PMNCNT1:
0579 case PPMU_PMNCNT2:
0580 desc[j].event_type = PPMU_V2_RO_DATA_CNT
0581 | PPMU_V2_WO_DATA_CNT;
0582 break;
0583 case PPMU_PMNCNT3:
0584 desc[j].event_type =
0585 PPMU_V2_EVT3_RW_DATA_CNT;
0586 break;
0587 }
0588 } else {
0589 desc[j].event_type = PPMU_RO_DATA_CNT |
0590 PPMU_WO_DATA_CNT;
0591 }
0592 }
0593
0594 j++;
0595 }
0596 info->desc = desc;
0597
0598 of_node_put(events_np);
0599
0600 return 0;
0601 }
0602
0603 static struct regmap_config exynos_ppmu_regmap_config = {
0604 .reg_bits = 32,
0605 .val_bits = 32,
0606 .reg_stride = 4,
0607 };
0608
0609 static int exynos_ppmu_parse_dt(struct platform_device *pdev,
0610 struct exynos_ppmu *info)
0611 {
0612 struct device *dev = info->dev;
0613 struct device_node *np = dev->of_node;
0614 struct resource *res;
0615 void __iomem *base;
0616 int ret = 0;
0617
0618 if (!np) {
0619 dev_err(dev, "failed to find devicetree node\n");
0620 return -EINVAL;
0621 }
0622
0623
0624 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0625 base = devm_ioremap_resource(dev, res);
0626 if (IS_ERR(base))
0627 return PTR_ERR(base);
0628
0629 exynos_ppmu_regmap_config.max_register = resource_size(res) - 4;
0630 info->regmap = devm_regmap_init_mmio(dev, base,
0631 &exynos_ppmu_regmap_config);
0632 if (IS_ERR(info->regmap)) {
0633 dev_err(dev, "failed to initialize regmap\n");
0634 return PTR_ERR(info->regmap);
0635 }
0636
0637 info->ppmu.clk = devm_clk_get(dev, "ppmu");
0638 if (IS_ERR(info->ppmu.clk)) {
0639 info->ppmu.clk = NULL;
0640 dev_warn(dev, "cannot get PPMU clock\n");
0641 }
0642
0643 ret = of_get_devfreq_events(np, info);
0644 if (ret < 0) {
0645 dev_err(dev, "failed to parse exynos ppmu dt node\n");
0646 return ret;
0647 }
0648
0649 return 0;
0650 }
0651
0652 static int exynos_ppmu_probe(struct platform_device *pdev)
0653 {
0654 struct exynos_ppmu *info;
0655 struct devfreq_event_dev **edev;
0656 struct devfreq_event_desc *desc;
0657 int i, ret = 0, size;
0658
0659 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0660 if (!info)
0661 return -ENOMEM;
0662
0663 info->dev = &pdev->dev;
0664
0665
0666 ret = exynos_ppmu_parse_dt(pdev, info);
0667 if (ret < 0) {
0668 dev_err(&pdev->dev,
0669 "failed to parse devicetree for resource\n");
0670 return ret;
0671 }
0672 desc = info->desc;
0673
0674 size = sizeof(struct devfreq_event_dev *) * info->num_events;
0675 info->edev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
0676 if (!info->edev)
0677 return -ENOMEM;
0678
0679 edev = info->edev;
0680 platform_set_drvdata(pdev, info);
0681
0682 for (i = 0; i < info->num_events; i++) {
0683 edev[i] = devm_devfreq_event_add_edev(&pdev->dev, &desc[i]);
0684 if (IS_ERR(edev[i])) {
0685 dev_err(&pdev->dev,
0686 "failed to add devfreq-event device\n");
0687 return PTR_ERR(edev[i]);
0688 }
0689
0690 pr_info("exynos-ppmu: new PPMU device registered %s (%s)\n",
0691 dev_name(&pdev->dev), desc[i].name);
0692 }
0693
0694 ret = clk_prepare_enable(info->ppmu.clk);
0695 if (ret) {
0696 dev_err(&pdev->dev, "failed to prepare ppmu clock\n");
0697 return ret;
0698 }
0699
0700 return 0;
0701 }
0702
0703 static int exynos_ppmu_remove(struct platform_device *pdev)
0704 {
0705 struct exynos_ppmu *info = platform_get_drvdata(pdev);
0706
0707 clk_disable_unprepare(info->ppmu.clk);
0708
0709 return 0;
0710 }
0711
0712 static struct platform_driver exynos_ppmu_driver = {
0713 .probe = exynos_ppmu_probe,
0714 .remove = exynos_ppmu_remove,
0715 .driver = {
0716 .name = "exynos-ppmu",
0717 .of_match_table = exynos_ppmu_id_match,
0718 },
0719 };
0720 module_platform_driver(exynos_ppmu_driver);
0721
0722 MODULE_DESCRIPTION("Exynos PPMU(Platform Performance Monitoring Unit) driver");
0723 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
0724 MODULE_LICENSE("GPL");