root/drivers/devfreq/event/exynos-ppmu.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __exynos_ppmu_find_ppmu_id
  2. exynos_ppmu_find_ppmu_id
  3. exynos_ppmu_disable
  4. exynos_ppmu_set_event
  5. exynos_ppmu_get_event
  6. exynos_ppmu_v2_disable
  7. exynos_ppmu_v2_set_event
  8. exynos_ppmu_v2_get_event
  9. of_get_devfreq_events
  10. exynos_ppmu_parse_dt
  11. exynos_ppmu_probe
  12. exynos_ppmu_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * exynos_ppmu.c - EXYNOS PPMU (Platform Performance Monitoring Unit) support
   4  *
   5  * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
   6  * Author : Chanwoo Choi <cw00.choi@samsung.com>
   7  *
   8  * This driver is based on drivers/devfreq/exynos/exynos_ppmu.c
   9  */
  10 
  11 #include <linux/clk.h>
  12 #include <linux/io.h>
  13 #include <linux/kernel.h>
  14 #include <linux/module.h>
  15 #include <linux/of_address.h>
  16 #include <linux/of_device.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/regmap.h>
  19 #include <linux/suspend.h>
  20 #include <linux/devfreq-event.h>
  21 
  22 #include "exynos-ppmu.h"
  23 
  24 enum exynos_ppmu_type {
  25         EXYNOS_TYPE_PPMU,
  26         EXYNOS_TYPE_PPMU_V2,
  27 };
  28 
  29 struct exynos_ppmu_data {
  30         struct clk *clk;
  31 };
  32 
  33 struct exynos_ppmu {
  34         struct devfreq_event_dev **edev;
  35         struct devfreq_event_desc *desc;
  36         unsigned int num_events;
  37 
  38         struct device *dev;
  39         struct regmap *regmap;
  40 
  41         struct exynos_ppmu_data ppmu;
  42         enum exynos_ppmu_type ppmu_type;
  43 };
  44 
  45 #define PPMU_EVENT(name)                        \
  46         { "ppmu-event0-"#name, PPMU_PMNCNT0 },  \
  47         { "ppmu-event1-"#name, PPMU_PMNCNT1 },  \
  48         { "ppmu-event2-"#name, PPMU_PMNCNT2 },  \
  49         { "ppmu-event3-"#name, PPMU_PMNCNT3 }
  50 
  51 static struct __exynos_ppmu_events {
  52         char *name;
  53         int id;
  54 } ppmu_events[] = {
  55         /* For Exynos3250, Exynos4 and Exynos5260 */
  56         PPMU_EVENT(g3d),
  57         PPMU_EVENT(fsys),
  58 
  59         /* For Exynos4 SoCs and Exynos3250 */
  60         PPMU_EVENT(dmc0),
  61         PPMU_EVENT(dmc1),
  62         PPMU_EVENT(cpu),
  63         PPMU_EVENT(rightbus),
  64         PPMU_EVENT(leftbus),
  65         PPMU_EVENT(lcd0),
  66         PPMU_EVENT(camif),
  67 
  68         /* Only for Exynos3250 and Exynos5260 */
  69         PPMU_EVENT(mfc),
  70 
  71         /* Only for Exynos4 SoCs */
  72         PPMU_EVENT(mfc-left),
  73         PPMU_EVENT(mfc-right),
  74 
  75         /* Only for Exynos5260 SoCs */
  76         PPMU_EVENT(drex0-s0),
  77         PPMU_EVENT(drex0-s1),
  78         PPMU_EVENT(drex1-s0),
  79         PPMU_EVENT(drex1-s1),
  80         PPMU_EVENT(eagle),
  81         PPMU_EVENT(kfc),
  82         PPMU_EVENT(isp),
  83         PPMU_EVENT(fimc),
  84         PPMU_EVENT(gscl),
  85         PPMU_EVENT(mscl),
  86         PPMU_EVENT(fimd0x),
  87         PPMU_EVENT(fimd1x),
  88 
  89         /* Only for Exynos5433 SoCs */
  90         PPMU_EVENT(d0-cpu),
  91         PPMU_EVENT(d0-general),
  92         PPMU_EVENT(d0-rt),
  93         PPMU_EVENT(d1-cpu),
  94         PPMU_EVENT(d1-general),
  95         PPMU_EVENT(d1-rt),
  96 
  97         /* For Exynos5422 SoC */
  98         PPMU_EVENT(dmc0_0),
  99         PPMU_EVENT(dmc0_1),
 100         PPMU_EVENT(dmc1_0),
 101         PPMU_EVENT(dmc1_1),
 102 };
 103 
 104 static int __exynos_ppmu_find_ppmu_id(const char *edev_name)
 105 {
 106         int i;
 107 
 108         for (i = 0; i < ARRAY_SIZE(ppmu_events); i++)
 109                 if (!strcmp(edev_name, ppmu_events[i].name))
 110                         return ppmu_events[i].id;
 111 
 112         return -EINVAL;
 113 }
 114 
 115 static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
 116 {
 117         return __exynos_ppmu_find_ppmu_id(edev->desc->name);
 118 }
 119 
 120 /*
 121  * The devfreq-event ops structure for PPMU v1.1
 122  */
 123 static int exynos_ppmu_disable(struct devfreq_event_dev *edev)
 124 {
 125         struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
 126         int ret;
 127         u32 pmnc;
 128 
 129         /* Disable all counters */
 130         ret = regmap_write(info->regmap, PPMU_CNTENC,
 131                                 PPMU_CCNT_MASK |
 132                                 PPMU_PMCNT0_MASK |
 133                                 PPMU_PMCNT1_MASK |
 134                                 PPMU_PMCNT2_MASK |
 135                                 PPMU_PMCNT3_MASK);
 136         if (ret < 0)
 137                 return ret;
 138 
 139         /* Disable PPMU */
 140         ret = regmap_read(info->regmap, PPMU_PMNC, &pmnc);
 141         if (ret < 0)
 142                 return ret;
 143 
 144         pmnc &= ~PPMU_PMNC_ENABLE_MASK;
 145         ret = regmap_write(info->regmap, PPMU_PMNC, pmnc);
 146         if (ret < 0)
 147                 return ret;
 148 
 149         return 0;
 150 }
 151 
 152 static int exynos_ppmu_set_event(struct devfreq_event_dev *edev)
 153 {
 154         struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
 155         int id = exynos_ppmu_find_ppmu_id(edev);
 156         int ret;
 157         u32 pmnc, cntens;
 158 
 159         if (id < 0)
 160                 return id;
 161 
 162         /* Enable specific counter */
 163         ret = regmap_read(info->regmap, PPMU_CNTENS, &cntens);
 164         if (ret < 0)
 165                 return ret;
 166 
 167         cntens |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
 168         ret = regmap_write(info->regmap, PPMU_CNTENS, cntens);
 169         if (ret < 0)
 170                 return ret;
 171 
 172         /* Set the event of proper data type monitoring */
 173         ret = regmap_write(info->regmap, PPMU_BEVTxSEL(id),
 174                            edev->desc->event_type);
 175         if (ret < 0)
 176                 return ret;
 177 
 178         /* Reset cycle counter/performance counter and enable PPMU */
 179         ret = regmap_read(info->regmap, PPMU_PMNC, &pmnc);
 180         if (ret < 0)
 181                 return ret;
 182 
 183         pmnc &= ~(PPMU_PMNC_ENABLE_MASK
 184                         | PPMU_PMNC_COUNTER_RESET_MASK
 185                         | PPMU_PMNC_CC_RESET_MASK);
 186         pmnc |= (PPMU_ENABLE << PPMU_PMNC_ENABLE_SHIFT);
 187         pmnc |= (PPMU_ENABLE << PPMU_PMNC_COUNTER_RESET_SHIFT);
 188         pmnc |= (PPMU_ENABLE << PPMU_PMNC_CC_RESET_SHIFT);
 189         ret = regmap_write(info->regmap, PPMU_PMNC, pmnc);
 190         if (ret < 0)
 191                 return ret;
 192 
 193         return 0;
 194 }
 195 
 196 static int exynos_ppmu_get_event(struct devfreq_event_dev *edev,
 197                                 struct devfreq_event_data *edata)
 198 {
 199         struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
 200         int id = exynos_ppmu_find_ppmu_id(edev);
 201         unsigned int total_count, load_count;
 202         unsigned int pmcnt3_high, pmcnt3_low;
 203         unsigned int pmnc, cntenc;
 204         int ret;
 205 
 206         if (id < 0)
 207                 return -EINVAL;
 208 
 209         /* Disable PPMU */
 210         ret = regmap_read(info->regmap, PPMU_PMNC, &pmnc);
 211         if (ret < 0)
 212                 return ret;
 213 
 214         pmnc &= ~PPMU_PMNC_ENABLE_MASK;
 215         ret = regmap_write(info->regmap, PPMU_PMNC, pmnc);
 216         if (ret < 0)
 217                 return ret;
 218 
 219         /* Read cycle count */
 220         ret = regmap_read(info->regmap, PPMU_CCNT, &total_count);
 221         if (ret < 0)
 222                 return ret;
 223         edata->total_count = total_count;
 224 
 225         /* Read performance count */
 226         switch (id) {
 227         case PPMU_PMNCNT0:
 228         case PPMU_PMNCNT1:
 229         case PPMU_PMNCNT2:
 230                 ret = regmap_read(info->regmap, PPMU_PMNCT(id), &load_count);
 231                 if (ret < 0)
 232                         return ret;
 233                 edata->load_count = load_count;
 234                 break;
 235         case PPMU_PMNCNT3:
 236                 ret = regmap_read(info->regmap, PPMU_PMCNT3_HIGH, &pmcnt3_high);
 237                 if (ret < 0)
 238                         return ret;
 239 
 240                 ret = regmap_read(info->regmap, PPMU_PMCNT3_LOW, &pmcnt3_low);
 241                 if (ret < 0)
 242                         return ret;
 243 
 244                 edata->load_count = ((pmcnt3_high << 8) | pmcnt3_low);
 245                 break;
 246         default:
 247                 return -EINVAL;
 248         }
 249 
 250         /* Disable specific counter */
 251         ret = regmap_read(info->regmap, PPMU_CNTENC, &cntenc);
 252         if (ret < 0)
 253                 return ret;
 254 
 255         cntenc |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
 256         ret = regmap_write(info->regmap, PPMU_CNTENC, cntenc);
 257         if (ret < 0)
 258                 return ret;
 259 
 260         dev_dbg(&edev->dev, "%s (event: %ld/%ld)\n", edev->desc->name,
 261                                         edata->load_count, edata->total_count);
 262 
 263         return 0;
 264 }
 265 
 266 static const struct devfreq_event_ops exynos_ppmu_ops = {
 267         .disable = exynos_ppmu_disable,
 268         .set_event = exynos_ppmu_set_event,
 269         .get_event = exynos_ppmu_get_event,
 270 };
 271 
 272 /*
 273  * The devfreq-event ops structure for PPMU v2.0
 274  */
 275 static int exynos_ppmu_v2_disable(struct devfreq_event_dev *edev)
 276 {
 277         struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
 278         int ret;
 279         u32 pmnc, clear;
 280 
 281         /* Disable all counters */
 282         clear = (PPMU_CCNT_MASK | PPMU_PMCNT0_MASK | PPMU_PMCNT1_MASK
 283                 | PPMU_PMCNT2_MASK | PPMU_PMCNT3_MASK);
 284         ret = regmap_write(info->regmap, PPMU_V2_FLAG, clear);
 285         if (ret < 0)
 286                 return ret;
 287 
 288         ret = regmap_write(info->regmap, PPMU_V2_INTENC, clear);
 289         if (ret < 0)
 290                 return ret;
 291 
 292         ret = regmap_write(info->regmap, PPMU_V2_CNTENC, clear);
 293         if (ret < 0)
 294                 return ret;
 295 
 296         ret = regmap_write(info->regmap, PPMU_V2_CNT_RESET, clear);
 297         if (ret < 0)
 298                 return ret;
 299 
 300         ret = regmap_write(info->regmap, PPMU_V2_CIG_CFG0, 0x0);
 301         if (ret < 0)
 302                 return ret;
 303 
 304         ret = regmap_write(info->regmap, PPMU_V2_CIG_CFG1, 0x0);
 305         if (ret < 0)
 306                 return ret;
 307 
 308         ret = regmap_write(info->regmap, PPMU_V2_CIG_CFG2, 0x0);
 309         if (ret < 0)
 310                 return ret;
 311 
 312         ret = regmap_write(info->regmap, PPMU_V2_CIG_RESULT, 0x0);
 313         if (ret < 0)
 314                 return ret;
 315 
 316         ret = regmap_write(info->regmap, PPMU_V2_CNT_AUTO, 0x0);
 317         if (ret < 0)
 318                 return ret;
 319 
 320         ret = regmap_write(info->regmap, PPMU_V2_CH_EV0_TYPE, 0x0);
 321         if (ret < 0)
 322                 return ret;
 323 
 324         ret = regmap_write(info->regmap, PPMU_V2_CH_EV1_TYPE, 0x0);
 325         if (ret < 0)
 326                 return ret;
 327 
 328         ret = regmap_write(info->regmap, PPMU_V2_CH_EV2_TYPE, 0x0);
 329         if (ret < 0)
 330                 return ret;
 331 
 332         ret = regmap_write(info->regmap, PPMU_V2_CH_EV3_TYPE, 0x0);
 333         if (ret < 0)
 334                 return ret;
 335 
 336         ret = regmap_write(info->regmap, PPMU_V2_SM_ID_V, 0x0);
 337         if (ret < 0)
 338                 return ret;
 339 
 340         ret = regmap_write(info->regmap, PPMU_V2_SM_ID_A, 0x0);
 341         if (ret < 0)
 342                 return ret;
 343 
 344         ret = regmap_write(info->regmap, PPMU_V2_SM_OTHERS_V, 0x0);
 345         if (ret < 0)
 346                 return ret;
 347 
 348         ret = regmap_write(info->regmap, PPMU_V2_SM_OTHERS_A, 0x0);
 349         if (ret < 0)
 350                 return ret;
 351 
 352         ret = regmap_write(info->regmap, PPMU_V2_INTERRUPT_RESET, 0x0);
 353         if (ret < 0)
 354                 return ret;
 355 
 356         /* Disable PPMU */
 357         ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc);
 358         if (ret < 0)
 359                 return ret;
 360 
 361         pmnc &= ~PPMU_PMNC_ENABLE_MASK;
 362         ret = regmap_write(info->regmap, PPMU_V2_PMNC, pmnc);
 363         if (ret < 0)
 364                 return ret;
 365 
 366         return 0;
 367 }
 368 
 369 static int exynos_ppmu_v2_set_event(struct devfreq_event_dev *edev)
 370 {
 371         struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
 372         unsigned int pmnc, cntens;
 373         int id = exynos_ppmu_find_ppmu_id(edev);
 374         int ret;
 375 
 376         /* Enable all counters */
 377         ret = regmap_read(info->regmap, PPMU_V2_CNTENS, &cntens);
 378         if (ret < 0)
 379                 return ret;
 380 
 381         cntens |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
 382         ret = regmap_write(info->regmap, PPMU_V2_CNTENS, cntens);
 383         if (ret < 0)
 384                 return ret;
 385 
 386         /* Set the event of proper data type monitoring */
 387         ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id),
 388                            edev->desc->event_type);
 389         if (ret < 0)
 390                 return ret;
 391 
 392         /* Reset cycle counter/performance counter and enable PPMU */
 393         ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc);
 394         if (ret < 0)
 395                 return ret;
 396 
 397         pmnc &= ~(PPMU_PMNC_ENABLE_MASK
 398                         | PPMU_PMNC_COUNTER_RESET_MASK
 399                         | PPMU_PMNC_CC_RESET_MASK
 400                         | PPMU_PMNC_CC_DIVIDER_MASK
 401                         | PPMU_V2_PMNC_START_MODE_MASK);
 402         pmnc |= (PPMU_ENABLE << PPMU_PMNC_ENABLE_SHIFT);
 403         pmnc |= (PPMU_ENABLE << PPMU_PMNC_COUNTER_RESET_SHIFT);
 404         pmnc |= (PPMU_ENABLE << PPMU_PMNC_CC_RESET_SHIFT);
 405         pmnc |= (PPMU_V2_MODE_MANUAL << PPMU_V2_PMNC_START_MODE_SHIFT);
 406 
 407         ret = regmap_write(info->regmap, PPMU_V2_PMNC, pmnc);
 408         if (ret < 0)
 409                 return ret;
 410 
 411         return 0;
 412 }
 413 
 414 static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev,
 415                                     struct devfreq_event_data *edata)
 416 {
 417         struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
 418         int id = exynos_ppmu_find_ppmu_id(edev);
 419         int ret;
 420         unsigned int pmnc, cntenc;
 421         unsigned int pmcnt_high, pmcnt_low;
 422         unsigned int total_count, count;
 423         unsigned long load_count = 0;
 424 
 425         /* Disable PPMU */
 426         ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc);
 427         if (ret < 0)
 428                 return ret;
 429 
 430         pmnc &= ~PPMU_PMNC_ENABLE_MASK;
 431         ret = regmap_write(info->regmap, PPMU_V2_PMNC, pmnc);
 432         if (ret < 0)
 433                 return ret;
 434 
 435         /* Read cycle count and performance count */
 436         ret = regmap_read(info->regmap, PPMU_V2_CCNT, &total_count);
 437         if (ret < 0)
 438                 return ret;
 439         edata->total_count = total_count;
 440 
 441         switch (id) {
 442         case PPMU_PMNCNT0:
 443         case PPMU_PMNCNT1:
 444         case PPMU_PMNCNT2:
 445                 ret = regmap_read(info->regmap, PPMU_V2_PMNCT(id), &count);
 446                 if (ret < 0)
 447                         return ret;
 448                 load_count = count;
 449                 break;
 450         case PPMU_PMNCNT3:
 451                 ret = regmap_read(info->regmap, PPMU_V2_PMCNT3_HIGH,
 452                                                 &pmcnt_high);
 453                 if (ret < 0)
 454                         return ret;
 455 
 456                 ret = regmap_read(info->regmap, PPMU_V2_PMCNT3_LOW, &pmcnt_low);
 457                 if (ret < 0)
 458                         return ret;
 459 
 460                 load_count = ((u64)((pmcnt_high & 0xff)) << 32)+ (u64)pmcnt_low;
 461                 break;
 462         }
 463         edata->load_count = load_count;
 464 
 465         /* Disable all counters */
 466         ret = regmap_read(info->regmap, PPMU_V2_CNTENC, &cntenc);
 467         if (ret < 0)
 468                 return 0;
 469 
 470         cntenc |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
 471         ret = regmap_write(info->regmap, PPMU_V2_CNTENC, cntenc);
 472         if (ret < 0)
 473                 return ret;
 474 
 475         dev_dbg(&edev->dev, "%25s (load: %ld / %ld)\n", edev->desc->name,
 476                                         edata->load_count, edata->total_count);
 477         return 0;
 478 }
 479 
 480 static const struct devfreq_event_ops exynos_ppmu_v2_ops = {
 481         .disable = exynos_ppmu_v2_disable,
 482         .set_event = exynos_ppmu_v2_set_event,
 483         .get_event = exynos_ppmu_v2_get_event,
 484 };
 485 
 486 static const struct of_device_id exynos_ppmu_id_match[] = {
 487         {
 488                 .compatible = "samsung,exynos-ppmu",
 489                 .data = (void *)EXYNOS_TYPE_PPMU,
 490         }, {
 491                 .compatible = "samsung,exynos-ppmu-v2",
 492                 .data = (void *)EXYNOS_TYPE_PPMU_V2,
 493         },
 494         { /* sentinel */ },
 495 };
 496 MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match);
 497 
 498 static int of_get_devfreq_events(struct device_node *np,
 499                                  struct exynos_ppmu *info)
 500 {
 501         struct devfreq_event_desc *desc;
 502         struct device *dev = info->dev;
 503         struct device_node *events_np, *node;
 504         int i, j, count;
 505         const struct of_device_id *of_id;
 506         int ret;
 507 
 508         events_np = of_get_child_by_name(np, "events");
 509         if (!events_np) {
 510                 dev_err(dev,
 511                         "failed to get child node of devfreq-event devices\n");
 512                 return -EINVAL;
 513         }
 514 
 515         count = of_get_child_count(events_np);
 516         desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
 517         if (!desc)
 518                 return -ENOMEM;
 519         info->num_events = count;
 520 
 521         of_id = of_match_device(exynos_ppmu_id_match, dev);
 522         if (of_id)
 523                 info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
 524         else
 525                 return -EINVAL;
 526 
 527         j = 0;
 528         for_each_child_of_node(events_np, node) {
 529                 for (i = 0; i < ARRAY_SIZE(ppmu_events); i++) {
 530                         if (!ppmu_events[i].name)
 531                                 continue;
 532 
 533                         if (of_node_name_eq(node, ppmu_events[i].name))
 534                                 break;
 535                 }
 536 
 537                 if (i == ARRAY_SIZE(ppmu_events)) {
 538                         dev_warn(dev,
 539                                 "don't know how to configure events : %pOFn\n",
 540                                 node);
 541                         continue;
 542                 }
 543 
 544                 switch (info->ppmu_type) {
 545                 case EXYNOS_TYPE_PPMU:
 546                         desc[j].ops = &exynos_ppmu_ops;
 547                         break;
 548                 case EXYNOS_TYPE_PPMU_V2:
 549                         desc[j].ops = &exynos_ppmu_v2_ops;
 550                         break;
 551                 }
 552 
 553                 desc[j].driver_data = info;
 554 
 555                 of_property_read_string(node, "event-name", &desc[j].name);
 556                 ret = of_property_read_u32(node, "event-data-type",
 557                                            &desc[j].event_type);
 558                 if (ret) {
 559                         /* Set the event of proper data type counting.
 560                          * Check if the data type has been defined in DT,
 561                          * use default if not.
 562                          */
 563                         if (info->ppmu_type == EXYNOS_TYPE_PPMU_V2) {
 564                                 int id;
 565                                 /* Not all registers take the same value for
 566                                  * read+write data count.
 567                                  */
 568                                 id = __exynos_ppmu_find_ppmu_id(desc[j].name);
 569 
 570                                 switch (id) {
 571                                 case PPMU_PMNCNT0:
 572                                 case PPMU_PMNCNT1:
 573                                 case PPMU_PMNCNT2:
 574                                         desc[j].event_type = PPMU_V2_RO_DATA_CNT
 575                                                 | PPMU_V2_WO_DATA_CNT;
 576                                         break;
 577                                 case PPMU_PMNCNT3:
 578                                         desc[j].event_type =
 579                                                 PPMU_V2_EVT3_RW_DATA_CNT;
 580                                         break;
 581                                 }
 582                         } else {
 583                                 desc[j].event_type = PPMU_RO_DATA_CNT |
 584                                         PPMU_WO_DATA_CNT;
 585                         }
 586                 }
 587 
 588                 j++;
 589         }
 590         info->desc = desc;
 591 
 592         of_node_put(events_np);
 593 
 594         return 0;
 595 }
 596 
 597 static struct regmap_config exynos_ppmu_regmap_config = {
 598         .reg_bits = 32,
 599         .val_bits = 32,
 600         .reg_stride = 4,
 601 };
 602 
 603 static int exynos_ppmu_parse_dt(struct platform_device *pdev,
 604                                 struct exynos_ppmu *info)
 605 {
 606         struct device *dev = info->dev;
 607         struct device_node *np = dev->of_node;
 608         struct resource *res;
 609         void __iomem *base;
 610         int ret = 0;
 611 
 612         if (!np) {
 613                 dev_err(dev, "failed to find devicetree node\n");
 614                 return -EINVAL;
 615         }
 616 
 617         /* Maps the memory mapped IO to control PPMU register */
 618         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 619         base = devm_ioremap_resource(dev, res);
 620         if (IS_ERR(base))
 621                 return PTR_ERR(base);
 622 
 623         exynos_ppmu_regmap_config.max_register = resource_size(res) - 4;
 624         info->regmap = devm_regmap_init_mmio(dev, base,
 625                                         &exynos_ppmu_regmap_config);
 626         if (IS_ERR(info->regmap)) {
 627                 dev_err(dev, "failed to initialize regmap\n");
 628                 return PTR_ERR(info->regmap);
 629         }
 630 
 631         info->ppmu.clk = devm_clk_get(dev, "ppmu");
 632         if (IS_ERR(info->ppmu.clk)) {
 633                 info->ppmu.clk = NULL;
 634                 dev_warn(dev, "cannot get PPMU clock\n");
 635         }
 636 
 637         ret = of_get_devfreq_events(np, info);
 638         if (ret < 0) {
 639                 dev_err(dev, "failed to parse exynos ppmu dt node\n");
 640                 return ret;
 641         }
 642 
 643         return 0;
 644 }
 645 
 646 static int exynos_ppmu_probe(struct platform_device *pdev)
 647 {
 648         struct exynos_ppmu *info;
 649         struct devfreq_event_dev **edev;
 650         struct devfreq_event_desc *desc;
 651         int i, ret = 0, size;
 652 
 653         info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 654         if (!info)
 655                 return -ENOMEM;
 656 
 657         info->dev = &pdev->dev;
 658 
 659         /* Parse dt data to get resource */
 660         ret = exynos_ppmu_parse_dt(pdev, info);
 661         if (ret < 0) {
 662                 dev_err(&pdev->dev,
 663                         "failed to parse devicetree for resource\n");
 664                 return ret;
 665         }
 666         desc = info->desc;
 667 
 668         size = sizeof(struct devfreq_event_dev *) * info->num_events;
 669         info->edev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 670         if (!info->edev)
 671                 return -ENOMEM;
 672 
 673         edev = info->edev;
 674         platform_set_drvdata(pdev, info);
 675 
 676         for (i = 0; i < info->num_events; i++) {
 677                 edev[i] = devm_devfreq_event_add_edev(&pdev->dev, &desc[i]);
 678                 if (IS_ERR(edev[i])) {
 679                         ret = PTR_ERR(edev[i]);
 680                         dev_err(&pdev->dev,
 681                                 "failed to add devfreq-event device\n");
 682                         return PTR_ERR(edev[i]);
 683                 }
 684 
 685                 pr_info("exynos-ppmu: new PPMU device registered %s (%s)\n",
 686                         dev_name(&pdev->dev), desc[i].name);
 687         }
 688 
 689         ret = clk_prepare_enable(info->ppmu.clk);
 690         if (ret) {
 691                 dev_err(&pdev->dev, "failed to prepare ppmu clock\n");
 692                 return ret;
 693         }
 694 
 695         return 0;
 696 }
 697 
 698 static int exynos_ppmu_remove(struct platform_device *pdev)
 699 {
 700         struct exynos_ppmu *info = platform_get_drvdata(pdev);
 701 
 702         clk_disable_unprepare(info->ppmu.clk);
 703 
 704         return 0;
 705 }
 706 
 707 static struct platform_driver exynos_ppmu_driver = {
 708         .probe  = exynos_ppmu_probe,
 709         .remove = exynos_ppmu_remove,
 710         .driver = {
 711                 .name   = "exynos-ppmu",
 712                 .of_match_table = exynos_ppmu_id_match,
 713         },
 714 };
 715 module_platform_driver(exynos_ppmu_driver);
 716 
 717 MODULE_DESCRIPTION("Exynos PPMU(Platform Performance Monitoring Unit) driver");
 718 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
 719 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */