diff options
| -rw-r--r-- | Documentation/ABI/testing/sysfs-class-devfreq-event | 25 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/devfreq/exynos-bus.txt | 14 | ||||
| -rw-r--r-- | drivers/devfreq/devfreq-event.c | 4 | ||||
| -rw-r--r-- | drivers/devfreq/devfreq.c | 74 | ||||
| -rw-r--r-- | drivers/devfreq/event/exynos-ppmu.c | 329 | ||||
| -rw-r--r-- | drivers/devfreq/exynos-bus.c | 8 | ||||
| -rw-r--r-- | drivers/devfreq/governor.h | 2 | ||||
| -rw-r--r-- | drivers/devfreq/governor_passive.c | 6 | ||||
| -rw-r--r-- | drivers/devfreq/governor_userspace.c | 11 | ||||
| -rw-r--r-- | include/linux/devfreq.h | 3 |
10 files changed, 350 insertions, 126 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-devfreq-event b/Documentation/ABI/testing/sysfs-class-devfreq-event new file mode 100644 index 000000000000..ceaf0f686d4a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-devfreq-event | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | What: /sys/class/devfreq-event/event(x)/ | ||
| 2 | Date: January 2017 | ||
| 3 | Contact: Chanwoo Choi <cw00.choi@samsung.com> | ||
| 4 | Description: | ||
| 5 | Provide a place in sysfs for the devfreq-event objects. | ||
| 6 | This allows accessing various devfreq-event specific variables. | ||
| 7 | The name of devfreq-event object denoted as 'event(x)' which | ||
| 8 | includes the unique number of 'x' for each devfreq-event object. | ||
| 9 | |||
| 10 | What: /sys/class/devfreq-event/event(x)/name | ||
| 11 | Date: January 2017 | ||
| 12 | Contact: Chanwoo Choi <cw00.choi@samsung.com> | ||
| 13 | Description: | ||
| 14 | The /sys/class/devfreq-event/event(x)/name attribute contains | ||
| 15 | the name of the devfreq-event object. This attribute is | ||
| 16 | read-only. | ||
| 17 | |||
| 18 | What: /sys/class/devfreq-event/event(x)/enable_count | ||
| 19 | Date: January 2017 | ||
| 20 | Contact: Chanwoo Choi <cw00.choi@samsung.com> | ||
| 21 | Description: | ||
| 22 | The /sys/class/devfreq-event/event(x)/enable_count attribute | ||
| 23 | contains the reference count to enable the devfreq-event | ||
| 24 | object. If the device is enabled, the value of attribute is | ||
| 25 | greater than zero. | ||
diff --git a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt index d3ec8e676b6b..d085ef90d27c 100644 --- a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt +++ b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt | |||
| @@ -123,6 +123,20 @@ Detailed correlation between sub-blocks and power line according to Exynos SoC: | |||
| 123 | |--- FSYS | 123 | |--- FSYS |
| 124 | |--- FSYS2 | 124 | |--- FSYS2 |
| 125 | 125 | ||
| 126 | - In case of Exynos5433, there is VDD_INT power line as following: | ||
| 127 | VDD_INT |--- G2D (parent device) | ||
| 128 | |--- MSCL | ||
| 129 | |--- GSCL | ||
| 130 | |--- JPEG | ||
| 131 | |--- MFC | ||
| 132 | |--- HEVC | ||
| 133 | |--- BUS0 | ||
| 134 | |--- BUS1 | ||
| 135 | |--- BUS2 | ||
| 136 | |--- PERIS (Fixed clock rate) | ||
| 137 | |--- PERIC (Fixed clock rate) | ||
| 138 | |--- FSYS (Fixed clock rate) | ||
| 139 | |||
| 126 | Example1: | 140 | Example1: |
| 127 | Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to | 141 | Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to |
| 128 | power line (regulator). The MIF (Memory Interface) AXI bus is used to | 142 | power line (regulator). The MIF (Memory Interface) AXI bus is used to |
diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c index 9aea2c7ecbe6..8648b32ebc89 100644 --- a/drivers/devfreq/devfreq-event.c +++ b/drivers/devfreq/devfreq-event.c | |||
| @@ -306,7 +306,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, | |||
| 306 | struct devfreq_event_desc *desc) | 306 | struct devfreq_event_desc *desc) |
| 307 | { | 307 | { |
| 308 | struct devfreq_event_dev *edev; | 308 | struct devfreq_event_dev *edev; |
| 309 | static atomic_t event_no = ATOMIC_INIT(0); | 309 | static atomic_t event_no = ATOMIC_INIT(-1); |
| 310 | int ret; | 310 | int ret; |
| 311 | 311 | ||
| 312 | if (!dev || !desc) | 312 | if (!dev || !desc) |
| @@ -329,7 +329,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, | |||
| 329 | edev->dev.class = devfreq_event_class; | 329 | edev->dev.class = devfreq_event_class; |
| 330 | edev->dev.release = devfreq_event_release_edev; | 330 | edev->dev.release = devfreq_event_release_edev; |
| 331 | 331 | ||
| 332 | dev_set_name(&edev->dev, "event.%d", atomic_inc_return(&event_no) - 1); | 332 | dev_set_name(&edev->dev, "event%d", atomic_inc_return(&event_no)); |
| 333 | ret = device_register(&edev->dev); | 333 | ret = device_register(&edev->dev); |
| 334 | if (ret < 0) { | 334 | if (ret < 0) { |
| 335 | put_device(&edev->dev); | 335 | put_device(&edev->dev); |
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 47206a21bb90..4aa72b5ed660 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
| @@ -130,7 +130,7 @@ static void devfreq_set_freq_table(struct devfreq *devfreq) | |||
| 130 | * @devfreq: the devfreq instance | 130 | * @devfreq: the devfreq instance |
| 131 | * @freq: the update target frequency | 131 | * @freq: the update target frequency |
| 132 | */ | 132 | */ |
| 133 | static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) | 133 | int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) |
| 134 | { | 134 | { |
| 135 | int lev, prev_lev, ret = 0; | 135 | int lev, prev_lev, ret = 0; |
| 136 | unsigned long cur_time; | 136 | unsigned long cur_time; |
| @@ -166,6 +166,7 @@ out: | |||
| 166 | devfreq->last_stat_updated = cur_time; | 166 | devfreq->last_stat_updated = cur_time; |
| 167 | return ret; | 167 | return ret; |
| 168 | } | 168 | } |
| 169 | EXPORT_SYMBOL(devfreq_update_status); | ||
| 169 | 170 | ||
| 170 | /** | 171 | /** |
| 171 | * find_devfreq_governor() - find devfreq governor from name | 172 | * find_devfreq_governor() - find devfreq governor from name |
| @@ -474,11 +475,15 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, | |||
| 474 | } | 475 | } |
| 475 | 476 | ||
| 476 | /** | 477 | /** |
| 477 | * _remove_devfreq() - Remove devfreq from the list and release its resources. | 478 | * devfreq_dev_release() - Callback for struct device to release the device. |
| 478 | * @devfreq: the devfreq struct | 479 | * @dev: the devfreq device |
| 480 | * | ||
| 481 | * Remove devfreq from the list and release its resources. | ||
| 479 | */ | 482 | */ |
| 480 | static void _remove_devfreq(struct devfreq *devfreq) | 483 | static void devfreq_dev_release(struct device *dev) |
| 481 | { | 484 | { |
| 485 | struct devfreq *devfreq = to_devfreq(dev); | ||
| 486 | |||
| 482 | mutex_lock(&devfreq_list_lock); | 487 | mutex_lock(&devfreq_list_lock); |
| 483 | if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) { | 488 | if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) { |
| 484 | mutex_unlock(&devfreq_list_lock); | 489 | mutex_unlock(&devfreq_list_lock); |
| @@ -500,19 +505,6 @@ static void _remove_devfreq(struct devfreq *devfreq) | |||
| 500 | } | 505 | } |
| 501 | 506 | ||
| 502 | /** | 507 | /** |
| 503 | * devfreq_dev_release() - Callback for struct device to release the device. | ||
| 504 | * @dev: the devfreq device | ||
| 505 | * | ||
| 506 | * This calls _remove_devfreq() if _remove_devfreq() is not called. | ||
| 507 | */ | ||
| 508 | static void devfreq_dev_release(struct device *dev) | ||
| 509 | { | ||
| 510 | struct devfreq *devfreq = to_devfreq(dev); | ||
| 511 | |||
| 512 | _remove_devfreq(devfreq); | ||
| 513 | } | ||
| 514 | |||
| 515 | /** | ||
| 516 | * devfreq_add_device() - Add devfreq feature to the device | 508 | * devfreq_add_device() - Add devfreq feature to the device |
| 517 | * @dev: the device to add devfreq feature. | 509 | * @dev: the device to add devfreq feature. |
| 518 | * @profile: device-specific profile to run devfreq. | 510 | * @profile: device-specific profile to run devfreq. |
| @@ -527,6 +519,7 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
| 527 | { | 519 | { |
| 528 | struct devfreq *devfreq; | 520 | struct devfreq *devfreq; |
| 529 | struct devfreq_governor *governor; | 521 | struct devfreq_governor *governor; |
| 522 | static atomic_t devfreq_no = ATOMIC_INIT(-1); | ||
| 530 | int err = 0; | 523 | int err = 0; |
| 531 | 524 | ||
| 532 | if (!dev || !profile || !governor_name) { | 525 | if (!dev || !profile || !governor_name) { |
| @@ -538,15 +531,14 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
| 538 | devfreq = find_device_devfreq(dev); | 531 | devfreq = find_device_devfreq(dev); |
| 539 | mutex_unlock(&devfreq_list_lock); | 532 | mutex_unlock(&devfreq_list_lock); |
| 540 | if (!IS_ERR(devfreq)) { | 533 | if (!IS_ERR(devfreq)) { |
| 541 | dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__); | 534 | dev_err(dev, "%s: Unable to create devfreq for the device.\n", |
| 535 | __func__); | ||
| 542 | err = -EINVAL; | 536 | err = -EINVAL; |
| 543 | goto err_out; | 537 | goto err_out; |
| 544 | } | 538 | } |
| 545 | 539 | ||
| 546 | devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL); | 540 | devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL); |
| 547 | if (!devfreq) { | 541 | if (!devfreq) { |
| 548 | dev_err(dev, "%s: Unable to create devfreq for the device\n", | ||
| 549 | __func__); | ||
| 550 | err = -ENOMEM; | 542 | err = -ENOMEM; |
| 551 | goto err_out; | 543 | goto err_out; |
| 552 | } | 544 | } |
| @@ -569,18 +561,21 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
| 569 | mutex_lock(&devfreq->lock); | 561 | mutex_lock(&devfreq->lock); |
| 570 | } | 562 | } |
| 571 | 563 | ||
| 572 | dev_set_name(&devfreq->dev, "%s", dev_name(dev)); | 564 | dev_set_name(&devfreq->dev, "devfreq%d", |
| 565 | atomic_inc_return(&devfreq_no)); | ||
| 573 | err = device_register(&devfreq->dev); | 566 | err = device_register(&devfreq->dev); |
| 574 | if (err) { | 567 | if (err) { |
| 575 | mutex_unlock(&devfreq->lock); | ||
