diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-04-17 04:17:43 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-04-17 04:17:43 -0400 |
| commit | e32d93926477c426d42b3207d814196f2bb0a720 (patch) | |
| tree | 8b69be5eb3ee8aaaf9212ab565b2333f3ce6b261 | |
| parent | dc4060a5dc2557e6b5aa813bf5b73677299d62d2 (diff) | |
| parent | cf451adfa392bd9ba36f31659dbe6a5010b46ef9 (diff) | |
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq into pm-devfreq
Pull devfreq material for 5.2 from MyungJoo Ham:
"This includes:
- Number of bugfixes (mainly on exception handling or styles)
- Exynos-bus: fix issues related with shutdown/reboot
- Rockchip-dfi: code refactoring
- RK3399: support trusted firmware
- Added trace support for devfreq-event"
* 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq:
PM / devfreq: add tracing for scheduling work
trace: events: add devfreq trace event file
PM / devfreq: rk3399_dmc: Pass ODT and auto power down parameters to TF-A.
PM / devfreq: rockchip-dfi: Move GRF definitions to a common place.
PM / devfreq: exynos-bus: Suspend all devices on system shutdown
PM / devfreq: Fix static checker warning in try_then_request_governor
PM / devfreq: Restart previous governor if new governor fails to start
PM / devfreq: tegra: remove unneeded variable
PM / devfreq: rockchip-dfi: remove unneeded semicolon
PM / devfreq: rk3399_dmc: remove unneeded semicolon
PM / devfreq: consistent indentation
PM / devfreq: fix missing check of return value in devfreq_add_device()
PM / devfreq: fix mem leak in devfreq_add_device()
PM / devfreq: Use of_node_name_eq for node name comparisons
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -rw-r--r-- | drivers/devfreq/devfreq-event.c | 2 | ||||
| -rw-r--r-- | drivers/devfreq/devfreq.c | 90 | ||||
| -rw-r--r-- | drivers/devfreq/event/exynos-ppmu.c | 2 | ||||
| -rw-r--r-- | drivers/devfreq/event/rockchip-dfi.c | 25 | ||||
| -rw-r--r-- | drivers/devfreq/exynos-bus.c | 8 | ||||
| -rw-r--r-- | drivers/devfreq/rk3399_dmc.c | 73 | ||||
| -rw-r--r-- | drivers/devfreq/tegra-devfreq.c | 7 | ||||
| -rw-r--r-- | include/soc/rockchip/rk3399_grf.h | 21 | ||||
| -rw-r--r-- | include/soc/rockchip/rockchip_sip.h | 1 | ||||
| -rw-r--r-- | include/trace/events/devfreq.h | 40 |
11 files changed, 213 insertions, 57 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 3671fdea5010..27ed10966c81 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -4552,6 +4552,7 @@ S: Maintained | |||
| 4552 | F: drivers/devfreq/ | 4552 | F: drivers/devfreq/ |
| 4553 | F: include/linux/devfreq.h | 4553 | F: include/linux/devfreq.h |
| 4554 | F: Documentation/devicetree/bindings/devfreq/ | 4554 | F: Documentation/devicetree/bindings/devfreq/ |
| 4555 | F: include/trace/events/devfreq.h | ||
| 4555 | 4556 | ||
| 4556 | DEVICE FREQUENCY EVENT (DEVFREQ-EVENT) | 4557 | DEVICE FREQUENCY EVENT (DEVFREQ-EVENT) |
| 4557 | M: Chanwoo Choi <cw00.choi@samsung.com> | 4558 | M: Chanwoo Choi <cw00.choi@samsung.com> |
diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c index d67242d87744..87e93406d7cd 100644 --- a/drivers/devfreq/devfreq-event.c +++ b/drivers/devfreq/devfreq-event.c | |||
| @@ -240,7 +240,7 @@ struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev, | |||
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | list_for_each_entry(edev, &devfreq_event_list, node) { | 242 | list_for_each_entry(edev, &devfreq_event_list, node) { |
| 243 | if (!strcmp(edev->desc->name, node->name)) | 243 | if (of_node_name_eq(node, edev->desc->name)) |
| 244 | goto out; | 244 | goto out; |
| 245 | } | 245 | } |
| 246 | edev = NULL; | 246 | edev = NULL; |
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 0ae3de76833b..6b6991f0e873 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
| @@ -29,6 +29,9 @@ | |||
| 29 | #include <linux/of.h> | 29 | #include <linux/of.h> |
| 30 | #include "governor.h" | 30 | #include "governor.h" |
| 31 | 31 | ||
| 32 | #define CREATE_TRACE_POINTS | ||
| 33 | #include <trace/events/devfreq.h> | ||
| 34 | |||
| 32 | static struct class *devfreq_class; | 35 | static struct class *devfreq_class; |
| 33 | 36 | ||
| 34 | /* | 37 | /* |
| @@ -228,7 +231,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name) | |||
| 228 | * if is not found. This can happen when both drivers (the governor driver | 231 | * if is not found. This can happen when both drivers (the governor driver |
| 229 | * and the driver that call devfreq_add_device) are built as modules. | 232 | * and the driver that call devfreq_add_device) are built as modules. |
| 230 | * devfreq_list_lock should be held by the caller. Returns the matched | 233 | * devfreq_list_lock should be held by the caller. Returns the matched |
| 231 | * governor's pointer. | 234 | * governor's pointer or an error pointer. |
| 232 | */ | 235 | */ |
| 233 | static struct devfreq_governor *try_then_request_governor(const char *name) | 236 | static struct devfreq_governor *try_then_request_governor(const char *name) |
| 234 | { | 237 | { |
| @@ -254,7 +257,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name) | |||
| 254 | /* Restore previous state before return */ | 257 | /* Restore previous state before return */ |
| 255 | mutex_lock(&devfreq_list_lock); | 258 | mutex_lock(&devfreq_list_lock); |
| 256 | if (err) | 259 | if (err) |
| 257 | return NULL; | 260 | return ERR_PTR(err); |
| 258 | 261 | ||
| 259 | governor = find_devfreq_governor(name); | 262 | governor = find_devfreq_governor(name); |
| 260 | } | 263 | } |
| @@ -394,6 +397,8 @@ static void devfreq_monitor(struct work_struct *work) | |||
| 394 | queue_delayed_work(devfreq_wq, &devfreq->work, | 397 | queue_delayed_work(devfreq_wq, &devfreq->work, |
| 395 | msecs_to_jiffies(devfreq->profile->polling_ms)); | 398 | msecs_to_jiffies(devfreq->profile->polling_ms)); |
| 396 | mutex_unlock(&devfreq->lock); | 399 | mutex_unlock(&devfreq->lock); |
| 400 | |||
| 401 | trace_devfreq_monitor(devfreq); | ||
| 397 | } | 402 | } |
| 398 | 403 | ||
| 399 | /** | 404 | /** |
| @@ -528,7 +533,7 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay) | |||
| 528 | mutex_lock(&devfreq->lock); | 533 | mutex_lock(&devfreq->lock); |
| 529 | if (!devfreq->stop_polling) | 534 | if (!devfreq->stop_polling) |
| 530 | queue_delayed_work(devfreq_wq, &devfreq->work, | 535 | queue_delayed_work(devfreq_wq, &devfreq->work, |
| 531 | msecs_to_jiffies(devfreq->profile->polling_ms)); | 536 | msecs_to_jiffies(devfreq->profile->polling_ms)); |
| 532 | } | 537 | } |
| 533 | out: | 538 | out: |
| 534 | mutex_unlock(&devfreq->lock); | 539 | mutex_unlock(&devfreq->lock); |
| @@ -537,7 +542,7 @@ EXPORT_SYMBOL(devfreq_interval_update); | |||
| 537 | 542 | ||
| 538 | /** | 543 | /** |
| 539 | * devfreq_notifier_call() - Notify that the device frequency requirements | 544 | * devfreq_notifier_call() - Notify that the device frequency requirements |
| 540 | * has been changed out of devfreq framework. | 545 | * has been changed out of devfreq framework. |
| 541 | * @nb: the notifier_block (supposed to be devfreq->nb) | 546 | * @nb: the notifier_block (supposed to be devfreq->nb) |
| 542 | * @type: not used | 547 | * @type: not used |
| 543 | * @devp: not used | 548 | * @devp: not used |
| @@ -651,7 +656,7 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
| 651 | mutex_unlock(&devfreq->lock); | 656 | mutex_unlock(&devfreq->lock); |
| 652 | err = set_freq_table(devfreq); | 657 | err = set_freq_table(devfreq); |
| 653 | if (err < 0) | 658 | if (err < 0) |
| 654 | goto err_out; | 659 | goto err_dev; |
| 655 | mutex_lock(&devfreq->lock); | 660 | mutex_lock(&devfreq->lock); |
| 656 | } | 661 | } |
| 657 | 662 | ||
| @@ -683,16 +688,27 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
| 683 | goto err_out; | 688 | goto err_out; |
| 684 | } | 689 | } |
| 685 | 690 | ||
| 686 | devfreq->trans_table = | 691 | devfreq->trans_table = devm_kzalloc(&devfreq->dev, |
| 687 | devm_kzalloc(&devfreq->dev, | 692 | array3_size(sizeof(unsigned int), |
| 688 | array3_size(sizeof(unsigned int), | 693 | devfreq->profile->max_state, |
| 689 | devfreq->profile->max_state, | 694 | devfreq->profile->max_state), |
| 690 | devfreq->profile->max_state), | 695 | GFP_KERNEL); |
| 691 | GFP_KERNEL); | 696 | if (!devfreq->trans_table) { |
| 697 | mutex_unlock(&devfreq->lock); | ||
| 698 | err = -ENOMEM; | ||
| 699 | goto err_devfreq; | ||
| 700 | } | ||
| 701 | |||
| 692 | devfreq->time_in_state = devm_kcalloc(&devfreq->dev, | 702 | devfreq->time_in_state = devm_kcalloc(&devfreq->dev, |
| 693 | devfreq->profile->max_state, | 703 | devfreq->profile->max_state, |
| 694 | sizeof(unsigned long), | 704 | sizeof(unsigned long), |
| 695 | GFP_KERNEL); | 705 | GFP_KERNEL); |
| 706 | if (!devfreq->time_in_state) { | ||
| 707 | mutex_unlock(&devfreq->lock); | ||
| 708 | err = -ENOMEM; | ||
| 709 | goto err_devfreq; | ||
| 710 | } | ||
| 711 | |||
| 696 | devfreq->last_stat_updated = jiffies; | 712 | devfreq->last_stat_updated = jiffies; |
| 697 | 713 | ||
| 698 | srcu_init_notifier_head(&devfreq->transition_notifier_list); | 714 | srcu_init_notifier_head(&devfreq->transition_notifier_list); |
| @@ -726,7 +742,7 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
| 726 | 742 | ||
| 727 | err_init: | 743 | err_init: |
| 728 | mutex_unlock(&devfreq_list_lock); | 744 | mutex_unlock(&devfreq_list_lock); |
| 729 | 745 | err_devfreq: | |
| 730 | devfreq_remove_device(devfreq); | 746 | devfreq_remove_device(devfreq); |
| 731 | devfreq = NULL; | 747 | devfreq = NULL; |
| 732 | err_dev: | 748 | err_dev: |
| @@ -1113,7 +1129,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, | |||
| 1113 | struct devfreq *df = to_devfreq(dev); | 1129 | struct devfreq *df = to_devfreq(dev); |
| 1114 | int ret; | 1130 | int ret; |
| 1115 | char str_governor[DEVFREQ_NAME_LEN + 1]; | 1131 | char str_governor[DEVFREQ_NAME_LEN + 1]; |
| 1116 | struct devfreq_governor *governor; | 1132 | const struct devfreq_governor *governor, *prev_governor; |
| 1117 | 1133 | ||
| 1118 | ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor); | 1134 | ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor); |
| 1119 | if (ret != 1) | 1135 | if (ret != 1) |
| @@ -1142,12 +1158,24 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, | |||
| 1142 | goto out; | 1158 | goto out; |
| 1143 | } | 1159 | } |
| 1144 | } | 1160 | } |
| 1161 | prev_governor = df->governor; | ||
| 1145 | df->governor = governor; | 1162 | df->governor = governor; |
| 1146 | strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN); | 1163 | strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN); |
| 1147 | ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); | 1164 | ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); |
| 1148 | if (ret) | 1165 | if (ret) { |
| 1149 | dev_warn(dev, "%s: Governor %s not started(%d)\n", | 1166 | dev_warn(dev, "%s: Governor %s not started(%d)\n", |
| 1150 | __func__, df->governor->name, ret); | 1167 | __func__, df->governor->name, ret); |
| 1168 | df->governor = prev_governor; | ||
| 1169 | strncpy(df->governor_name, prev_governor->name, | ||
| 1170 | DEVFREQ_NAME_LEN); | ||
| 1171 | ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); | ||
| 1172 | if (ret) { | ||
| 1173 | dev_err(dev, | ||
| 1174 | "%s: reverting to Governor %s failed (%d)\n", | ||
| 1175 | __func__, df->governor_name, ret); | ||
| 1176 | df->governor = NULL; | ||
| 1177 | } | ||
| 1178 | } | ||
| 1151 | out: | 1179 | out: |
| 1152 | mutex_unlock(&devfreq_list_lock); | 1180 | mutex_unlock(&devfreq_list_lock); |
| 1153 | 1181 | ||
| @@ -1172,7 +1200,7 @@ static ssize_t available_governors_show(struct device *d, | |||
| 1172 | */ | 1200 | */ |
| 1173 | if (df->governor->immutable) { | 1201 | if (df->governor->immutable) { |
| 1174 | count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, | 1202 | count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, |
| 1175 | "%s ", df->governor_name); | 1203 | "%s ", df->governor_name); |
| 1176 | /* | 1204 | /* |
| 1177 | * The devfreq device shows the registered governor except for | 1205 | * The devfreq device shows the registered governor except for |
| 1178 | * immutable governors such as passive governor . | 1206 | * immutable governors such as passive governor . |
| @@ -1485,8 +1513,8 @@ EXPORT_SYMBOL(devfreq_recommended_opp); | |||
| 1485 | 1513 | ||
| 1486 | /** | 1514 | /** |
| 1487 | * devfreq_register_opp_notifier() - Helper function to get devfreq notified | 1515 | * devfreq_register_opp_notifier() - Helper function to get devfreq notified |
| 1488 | * for any changes in the OPP availability | 1516 | * for any changes in the OPP availability |
| 1489 | * changes | 1517 | * changes |
| 1490 | * @dev: The devfreq user device. (parent of devfreq) | 1518 | * @dev: The devfreq user device. (parent of devfreq) |
| 1491 | * @devfreq: The devfreq object. | 1519 | * @devfreq: The devfreq object. |
| 1492 | */ | 1520 | */ |
| @@ -1498,8 +1526,8 @@ EXPORT_SYMBOL(devfreq_register_opp_notifier); | |||
| 1498 | 1526 | ||
| 1499 | /** | 1527 | /** |
| 1500 | * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq | 1528 | * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq |
| 1501 | * notified for any changes in the OPP | 1529 | * notified for any changes in the OPP |
| 1502 | * availability changes anymore. | 1530 | * availability changes anymore. |
| 1503 | * @dev: The devfreq user device. (parent of devfreq) | 1531 | * @dev: The devfreq user device. (parent of devfreq) |
| 1504 | * @devfreq: The devfreq object. | 1532 | * @devfreq: The devfreq object. |
| 1505 | * | 1533 | * |
| @@ -1518,8 +1546,8 @@ static void devm_devfreq_opp_release(struct device *dev, void *res) | |||
| 1518 | } | 1546 | } |
| 1519 | 1547 | ||
| 1520 | /** | 1548 | /** |
| 1521 | * devm_ devfreq_register_opp_notifier() | 1549 | * devm_devfreq_register_opp_notifier() - Resource-managed |
| 1522 | * - Resource-managed devfreq_register_opp_notifier() | 1550 | * devfreq_register_opp_notifier() |
| 1523 | * @dev: The devfreq user device. (parent of devfreq) | 1551 | * @dev: The devfreq user device. (parent of devfreq) |
| 1524 | * @devfreq: The devfreq object. | 1552 | * @devfreq: The devfreq object. |
| 1525 | */ | 1553 | */ |
| @@ -1547,8 +1575,8 @@ int devm_devfreq_register_opp_notifier(struct device *dev, | |||
| 1547 | EXPORT_SYMBOL(devm_devfreq_register_opp_notifier); | 1575 | EXPORT_SYMBOL(devm_devfreq_register_opp_notifier); |
| 1548 | 1576 | ||
| 1549 | /** | 1577 | /** |
| 1550 | * devm_devfreq_unregister_opp_notifier() | 1578 | * devm_devfreq_unregister_opp_notifier() - Resource-managed |
| 1551 | * - Resource-managed devfreq_unregister_opp_notifier() | 1579 | * devfreq_unregister_opp_notifier() |
| 1552 | * @dev: The devfreq user device. (parent of devfreq) | 1580 | * @dev: The devfreq user device. (parent of devfreq) |
| 1553 | * @devfreq: The devfreq object. | 1581 | * @devfreq: The devfreq object. |
| 1554 | */ | 1582 | */ |
| @@ -1567,8 +1595,8 @@ EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier); | |||
| 1567 | * @list: DEVFREQ_TRANSITION_NOTIFIER. | 1595 | * @list: DEVFREQ_TRANSITION_NOTIFIER. |
| 1568 | */ | 1596 | */ |
| 1569 | int devfreq_register_notifier(struct devfreq *devfreq, | 1597 | int devfreq_register_notifier(struct devfreq *devfreq, |
| 1570 | struct notifier_block *nb, | 1598 | struct notifier_block *nb, |
| 1571 | unsigned int list) | 1599 | unsigned int list) |
| 1572 | { | 1600 | { |
| 1573 | int ret = 0; | 1601 | int ret = 0; |
| 1574 | 1602 | ||
| @@ -1674,9 +1702,9 @@ EXPORT_SYMBOL(devm_devfreq_register_notifier); | |||
| 1674 | * @list: DEVFREQ_TRANSITION_NOTIFIER. | 1702 | * @list: DEVFREQ_TRANSITION_NOTIFIER. |
| 1675 | */ | 1703 | */ |
| 1676 | void devm_devfreq_unregister_notifier(struct device *dev, | 1704 | void devm_devfreq_unregister_notifier(struct device *dev, |
| 1677 | struct devfreq *devfreq, | 1705 | struct devfreq *devfreq, |
| 1678 | struct notifier_block *nb, | 1706 | struct notifier_block *nb, |
| 1679 | unsigned int list) | 1707 | unsigned int list) |
| 1680 | { | 1708 | { |
| 1681 | WARN_ON(devres_release(dev, devm_devfreq_notifier_release, | 1709 | WARN_ON(devres_release(dev, devm_devfreq_notifier_release, |
| 1682 | devm_devfreq_dev_match, devfreq)); | 1710 | devm_devfreq_dev_match, devfreq)); |
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c index c61de0bdf053..c2ea94957501 100644 --- a/drivers/devfreq/event/exynos-ppmu.c +++ b/drivers/devfreq/event/exynos-ppmu.c | |||
| @@ -529,7 +529,7 @@ static int of_get_devfreq_events(struct device_node *np, | |||
| 529 | if (!ppmu_events[i].name) | 529 | if (!ppmu_events[i].name) |
| 530 | continue; | 530 | continue; |
| 531 | 531 | ||
| 532 | if (!of_node_cmp(node->name, ppmu_events[i].name)) | 532 | if (of_node_name_eq(node, ppmu_events[i].name)) |
| 533 | break; | 533 | break; |
| 534 | } | 534 | } |
| 535 | 535 | ||
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index 22b113363ffc..a436ec4901bb 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
| 27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
| 28 | 28 | ||
| 29 | #include <soc/rockchip/rk3399_grf.h> | ||
| 30 | |||
| 29 | #define RK3399_DMC_NUM_CH 2 | 31 | #define RK3399_DMC_NUM_CH 2 |
| 30 | 32 | ||
| 31 | /* DDRMON_CTRL */ | 33 | /* DDRMON_CTRL */ |
| @@ -43,18 +45,6 @@ | |||
| 43 | #define DDRMON_CH1_COUNT_NUM 0x3c | 45 | #define DDRMON_CH1_COUNT_NUM 0x3c |
| 44 | #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 | 46 | #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 |
| 45 | 47 | ||
| 46 | /* pmu grf */ | ||
| 47 | #define PMUGRF_OS_REG2 0x308 | ||
| 48 | #define DDRTYPE_SHIFT 13 | ||
| 49 | #define DDRTYPE_MASK 7 | ||
| 50 | |||
| 51 | enum { | ||
| 52 | DDR3 = 3, | ||
| 53 | LPDDR3 = 6, | ||
| 54 | LPDDR4 = 7, | ||
| 55 | UNUSED = 0xFF | ||
| 56 | }; | ||
| 57 | |||
| 58 | struct dmc_usage { | 48 | struct dmc_usage { |
| 59 | u32 access; | 49 | u32 access; |
| 60 | u32 total; | 50 | u32 total; |
| @@ -83,16 +73,17 @@ static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev) | |||
| 83 | u32 ddr_type; | 73 | u32 ddr_type; |
| 84 | 74 | ||
| 85 | /* get ddr type */ | 75 | /* get ddr type */ |
| 86 | regmap_read(info->regmap_pmu, PMUGRF_OS_REG2, &val); | 76 | regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); |
| 87 | ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK; | 77 | ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & |
| 78 | RK3399_PMUGRF_DDRTYPE_MASK; | ||
| 88 | 79 | ||
| 89 | /* clear DDRMON_CTRL setting */ | 80 | /* clear DDRMON_CTRL setting */ |
| 90 | writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); | 81 | writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); |
| 91 | 82 | ||
| 92 | /* set ddr type to dfi */ | 83 | /* set ddr type to dfi */ |
| 93 | if (ddr_type == LPDDR3) | 84 | if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3) |
| 94 | writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); | 85 | writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); |
| 95 | else if (ddr_type == LPDDR4) | 86 | else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4) |
| 96 | writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); | 87 | writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); |
| 97 | 88 | ||
| 98 | /* enable count, use software mode */ | 89 | /* enable count, use software mode */ |
| @@ -211,7 +202,7 @@ static int rockchip_dfi_probe(struct platform_device *pdev) | |||
| 211 | if (IS_ERR(data->clk)) { | 202 | if (IS_ERR(data->clk)) { |
| 212 | dev_err(dev, "Cannot get the clk dmc_clk\n"); | 203 | dev_err(dev, "Cannot get the clk dmc_clk\n"); |
| 213 | return PTR_ERR(data->clk); | 204 | return PTR_ERR(data->clk); |
| 214 | }; | 205 | } |
| 215 | 206 | ||
| 216 | /* try to find the optional reference to the pmu syscon */ | 207 | /* try to find the optional reference to the pmu syscon */ |
| 217 | node = of_parse_phandle(np, "rockchip,pmu", 0); | 208 | node = of_parse_phandle(np, "rockchip,pmu", 0); |
diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c index c25658b26598..486cc5b422f1 100644 --- a/drivers/devfreq/exynos-bus.c +++ b/drivers/devfreq/exynos-bus.c | |||
| @@ -514,6 +514,13 @@ err: | |||
| 514 | return ret; | 514 | return ret; |
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | static void exynos_bus_shutdown(struct platform_device *pdev) | ||
| 518 | { | ||
| 519 | struct exynos_bus *bus = dev_get_drvdata(&pdev->dev); | ||
| 520 | |||
| 521 | devfreq_suspend_device(bus->devfreq); | ||
| 522 | } | ||
| 523 | |||
| 517 | #ifdef CONFIG_PM_SLEEP | 524 | #ifdef CONFIG_PM_SLEEP |
| 518 | static int exynos_bus_resume(struct device *dev) | 525 | static int exynos_bus_resume(struct device *dev) |
| 519 | { | 526 | { |
| @@ -556,6 +563,7 @@ MODULE_DEVICE_TABLE(of, exynos_bus_of_match); | |||
| 556 | 563 | ||
| 557 | static struct platform_driver exynos_bus_platdrv = { | 564 | static struct platform_driver exynos_bus_platdrv = { |
| 558 | .probe = exynos_bus_probe, | 565 | .probe = exynos_bus_probe, |
| 566 | .shutdown = exynos_bus_shutdown, | ||
| 559 | .driver = { | 567 | .driver = { |
| 560 | .name = "exynos-bus", | 568 | .name = "exynos-bus", |
| 561 | .pm = &exynos_bus_pm, | 569 | .pm = &exynos_bus_pm, |
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c index e795ad2b3f6b..567c034d0301 100644 --- a/drivers/devfreq/rk3399_dmc.c +++ b/drivers/devfreq/rk3399_dmc.c | |||
| @@ -18,14 +18,17 @@ | |||
| 18 | #include <linux/devfreq.h> | 18 | #include <linux/devfreq.h> |
| 19 | #include <linux/devfreq-event.h> | 19 | #include <linux/devfreq-event.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/mfd/syscon.h> | ||
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 24 | #include <linux/pm_opp.h> | 25 | #include <linux/pm_opp.h> |
| 26 | #include <linux/regmap.h> | ||
| 25 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
| 26 | #include <linux/rwsem.h> | 28 | #include <linux/rwsem.h> |
| 27 | #include <linux/suspend.h> | 29 | #include <linux/suspend.h> |
| 28 | 30 | ||
| 31 | #include <soc/rockchip/rk3399_grf.h> | ||
| 29 | #include <soc/rockchip/rockchip_sip.h> | 32 | #include <soc/rockchip/rockchip_sip.h> |
| 30 | 33 | ||
| 31 | struct dram_timing { | 34 | struct dram_timing { |
| @@ -69,8 +72,11 @@ struct rk3399_dmcfreq { | |||
| 69 | struct mutex lock; | 72 | struct mutex lock; |
| 70 | struct dram_timing timing; | 73 | struct dram_timing timing; |
| 71 | struct regulator *vdd_center; | 74 | struct regulator *vdd_center; |
| 75 | struct regmap *regmap_pmu; | ||
| 72 | unsigned long rate, target_rate; | 76 | unsigned long rate, target_rate; |
| 73 | unsigned long volt, target_volt; | 77 | unsigned long volt, target_volt; |
| 78 | unsigned int odt_dis_freq; | ||
| 79 | int odt_pd_arg0, odt_pd_arg1; | ||
| 74 | }; | 80 | }; |
| 75 | 81 | ||
| 76 | static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, | 82 | static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, |
| @@ -80,6 +86,8 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, | |||
| 80 | struct dev_pm_opp *opp; | 86 | struct dev_pm_opp *opp; |
| 81 | unsigned long old_clk_rate = dmcfreq->rate; | 87 | unsigned long old_clk_rate = dmcfreq->rate; |
| 82 | unsigned long target_volt, target_rate; | 88 | unsigned long target_volt, target_rate; |
| 89 | struct arm_smccc_res res; | ||
| 90 | bool odt_enable = false; | ||
| 83 | int err; | 91 | int err; |
| 84 | 92 | ||
| 85 | opp = devfreq_recommended_opp(dev, freq, flags); | 93 | opp = devfreq_recommended_opp(dev, freq, flags); |
| @@ -95,6 +103,19 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, | |||
| 95 | 103 | ||
| 96 | mutex_lock(&dmcfreq->lock); | 104 | mutex_lock(&dmcfreq->lock); |
| 97 | 105 | ||
| 106 | if (target_rate >= dmcfreq->odt_dis_freq) | ||
| 107 | odt_enable = true; | ||
| 108 | |||
| 109 | /* | ||
| 110 | * This makes a SMC call to the TF-A to set the DDR PD (power-down) | ||
| 111 | * timings and to enable or disable the ODT (on-die termination) | ||
| 112 | * resistors. | ||
| 113 | */ | ||
| 114 | arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, dmcfreq->odt_pd_arg0, | ||
| 115 | dmcfreq->odt_pd_arg1, | ||
| 116 | ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD, | ||
| 117 | odt_enable, 0, 0, 0, &res); | ||
| 118 | |||
| 98 | /* | 119 | /* |
| 99 | * If frequency scaling from low to high, adjust voltage first. | 120 | * If frequency scaling from low to high, adjust voltage first. |
| 100 | * If frequency scaling from high to low, adjust frequency first. | 121 | * If frequency scaling from high to low, adjust frequency first. |
| @@ -294,11 +315,13 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) | |||
| 294 | { | 315 | { |
| 295 | struct arm_smccc_res res; | 316 | struct arm_smccc_res res; |
| 296 | struct device *dev = &pdev->dev; | 317 | struct device *dev = &pdev->dev; |
| 297 | struct device_node *np = pdev->dev.of_node; | 318 | struct device_node *np = pdev->dev.of_node, *node; |
| 298 | struct rk3399_dmcfreq *data; | 319 | struct rk3399_dmcfreq *data; |
| 299 | int ret, index, size; | 320 | int ret, index, size; |
| 300 | uint32_t *timing; | 321 | uint32_t *timing; |
| 301 | struct dev_pm_opp *opp; | 322 | struct dev_pm_opp *opp; |
| 323 | u32 ddr_type; | ||
| 324 | u32 val; | ||
| 302 | 325 | ||
| 303 | data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL); | 326 | data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL); |
| 304 | if (!data) | 327 | if (!data) |
| @@ -322,7 +345,7 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) | |||
| 322 | 345 | ||
| 323 | dev_err(dev, "Cannot get the clk dmc_clk\n"); | 346 | dev_err(dev, "Cannot get the clk dmc_clk\n"); |
| 324 | return PTR_ERR(data->dmc_clk); | 347 | return PTR_ERR(data->dmc_clk); |
| 325 | }; | 348 | } |
| 326 | 349 | ||
| 327 | data->edev = devfreq_event_get_edev_by_phandle(dev, 0); | 350 | data->edev = devfreq_event_get_edev_by_phandle(dev, 0); |
| 328 | if (IS_ERR(data->edev)) | 351 | if (IS_ERR(data->edev)) |
| @@ -354,11 +377,57 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) | |||
| 354 | } | 377 | } |
| 355 | } | 378 | } |
| 356 | 379 | ||
| 380 | node = of_parse_phandle(np, "rockchip,pmu", 0); | ||
| 381 | if (node) { | ||
| 382 | data->regmap_pmu = syscon_node_to_regmap(node); | ||
| 383 | if (IS_ERR(data->regmap_pmu)) | ||
| 384 | return PTR_ERR(data->regmap_pmu); | ||
| 385 | } | ||
| 386 | |||
| 387 | regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); | ||
| 388 | ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & | ||
| 389 | RK3399_PMUGRF_DDRTYPE_MASK; | ||
| 390 | |||
| 391 | switch (ddr_type) { | ||
| 392 | case RK3399_PMUGRF_DDRTYPE_DDR3: | ||
| 393 | data->odt_dis_freq = data->timing.ddr3_odt_dis_freq; | ||
| 394 | break; | ||
| 395 | case RK3399_PMUGRF_DDRTYPE_LPDDR3: | ||
| 396 | data->odt_dis_freq = data->timing.lpddr3_odt_dis_freq; | ||
| 397 | break; | ||
| 398 | case RK3399_PMUGRF_DDRTYPE_LPDDR4: | ||
| 399 | data->odt_dis_freq = data->timing.lpddr4_odt_dis_freq; | ||
| 400 | break; | ||
| 401 | default: | ||
| 402 | return -EINVAL; | ||
| 403 | }; | ||
| 404 | |||
| 357 | arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0, | 405 | arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0, |
| 358 | ROCKCHIP_SIP_CONFIG_DRAM_INIT, | 406 | ROCKCHIP_SIP_CONFIG_DRAM_INIT, |
| 359 | 0, 0, 0, 0, &res); | 407 | 0, 0, 0, 0, &res); |
| 360 | 408 | ||
| 361 | /* | 409 | /* |
| 410 | * In TF-A there is a platform SIP call to set the PD (power-down) | ||
| 411 | * timings and to enable or disable the ODT (on-die termination). | ||
| 412 | * This call needs three arguments as follows: | ||
| 413 | * | ||
| 414 | * arg0: | ||
| 415 | * bit[0-7] : sr_idle | ||
| 416 | * bit[8-15] : sr_mc_gate_idle | ||
| 417 | * bit[16-31] : standby idle | ||
| 418 | * arg1: | ||
| 419 | * bit[0-11] : pd_idle | ||
| 420 | * bit[16-27] : srpd_lite_idle | ||
| 421 | * arg2: | ||
| 422 | * bit[0] : odt enable | ||
| 423 | */ | ||
| 424 | data->odt_pd_arg0 = (data->timing.sr_idle & 0xff) | | ||
| 425 | ((data->timing.sr_mc_gate_idle & 0xff) << 8) | | ||
| 426 | ((data->timing.standby_idle & 0xffff) << 16); | ||
| 427 | data->odt_pd_arg1 = (data->timing.pd_idle & 0xfff) | | ||
| 428 | ((data->timing.srpd_lite_idle & 0xfff) << 16); | ||
| 429 | |||
| 430 | /* | ||
| 362 | * We add a devfreq driver to our parent since it has a device tree node | 431 | * We add a devfreq driver to our parent since it has a device tree node |
| 363 | * with operating points. | 432 | * with operating points. |
| 364 | */ | 433 | */ |
diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index c59d2eee5d30..c89ba7b834ff 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c | |||
| @@ -573,10 +573,7 @@ static int tegra_governor_get_target(struct devfreq *devfreq, | |||
| 573 | static int tegra_governor_event_handler(struct devfreq *devfreq, | 573 | static int tegra_governor_event_handler(struct devfreq *devfreq, |
| 574 | unsigned int event, void *data) | 574 | unsigned int event, void *data) |
| 575 | { | 575 | { |
| 576 | struct tegra_devfreq *tegra; | 576 | struct tegra_devfreq *tegra = dev_get_drvdata(devfreq->dev.parent); |
| 577 | int ret = 0; | ||
| 578 | |||
| 579 | tegra = dev_get_drvdata(devfreq->dev.parent); | ||
| 580 | 577 | ||
| 581 | switch (event) { | 578 | switch (event) { |
| 582 | case DEVFREQ_GOV_START: | 579 | case DEVFREQ_GOV_START: |
| @@ -600,7 +597,7 @@ static int tegra_governor_event_handler(struct devfreq *devfreq, | |||
| 600 | break; | 597 | break; |
| 601 | } | 598 | } |
| 602 | 599 | ||
| 603 | return ret; | 600 | return 0; |
| 604 | } | 601 | } |
| 605 | 602 | ||
| 606 | static struct devfreq_governor tegra_devfreq_governor = { | 603 | static struct devfreq_governor tegra_devfreq_governor = { |
diff --git a/include/soc/rockchip/rk3399_grf.h b/include/soc/rockchip/rk3399_grf.h new file mode 100644 index 000000000000..3eebabcb2812 --- /dev/null +++ b/include/soc/rockchip/rk3399_grf.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
| 2 | /* | ||
| 3 | * Rockchip General Register Files definitions | ||
| 4 | * | ||
| 5 | * Copyright (c) 2018, Collabora Ltd. | ||
| 6 | * Author: Enric Balletbo i Serra <enric.balletbo@collabora.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef __SOC_RK3399_GRF_H | ||
| 10 | #define __SOC_RK3399_GRF_H | ||
| 11 | |||
| 12 | /* PMU GRF Registers */ | ||
| 13 | #define RK3399_PMUGRF_OS_REG2 0x308 | ||
| 14 | #define RK3399_PMUGRF_DDRTYPE_SHIFT 13 | ||
| 15 | #define RK3399_PMUGRF_DDRTYPE_MASK 7 | ||
| 16 | #define RK3399_PMUGRF_DDRTYPE_DDR3 3 | ||
| 17 | #define RK3399_PMUGRF_DDRTYPE_LPDDR2 5 | ||
| 18 | #define RK3399_PMUGRF_DDRTYPE_LPDDR3 6 | ||
| 19 | #define RK3399_PMUGRF_DDRTYPE_LPDDR4 7 | ||
| 20 | |||
| 21 | #endif | ||
diff --git a/include/soc/rockchip/rockchip_sip.h b/include/soc/rockchip/rockchip_sip.h index 7e28092c4d3d..ad9482c56797 100644 --- a/include/soc/rockchip/rockchip_sip.h +++ b/include/soc/rockchip/rockchip_sip.h | |||
| @@ -23,5 +23,6 @@ | |||
| 23 | #define ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE 0x05 | 23 | #define ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE 0x05 |
| 24 | #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 | 24 | #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 |
| 25 | #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 | 25 | #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 |
| 26 | #define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08 | ||
| 26 | 27 | ||
| 27 | #endif | 28 | #endif |
diff --git a/include/trace/events/devfreq.h b/include/trace/events/devfreq.h new file mode 100644 index 000000000000..cf5b8772175d --- /dev/null +++ b/include/trace/events/devfreq.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #undef TRACE_SYSTEM | ||
| 3 | #define TRACE_SYSTEM devfreq | ||
| 4 | |||
| 5 | #if !defined(_TRACE_DEVFREQ_H) || defined(TRACE_HEADER_MULTI_READ) | ||
| 6 | #define _TRACE_DEVFREQ_H | ||
| 7 | |||
| 8 | #include <linux/devfreq.h> | ||
| 9 | #include <linux/tracepoint.h> | ||
| 10 | |||
| 11 | TRACE_EVENT(devfreq_monitor, | ||
| 12 | TP_PROTO(struct devfreq *devfreq), | ||
| 13 | |||
| 14 | TP_ARGS(devfreq), | ||
| 15 | |||
| 16 | TP_STRUCT__entry( | ||
| 17 | __field(unsigned long, freq) | ||
| 18 | __field(unsigned long, busy_time) | ||
| 19 | __field(unsigned long, total_time) | ||
| 20 | __field(unsigned int, polling_ms) | ||
| 21 | __string(dev_name, dev_name(&devfreq->dev)) | ||
| 22 | ), | ||
| 23 | |||
| 24 | TP_fast_assign( | ||
| 25 | __entry->freq = devfreq->previous_freq; | ||
| 26 | __entry->busy_time = devfreq->last_status.busy_time; | ||
| 27 | __entry->total_time = devfreq->last_status.total_time; | ||
| 28 | __entry->polling_ms = devfreq->profile->polling_ms; | ||
| 29 | __assign_str(dev_name, dev_name(&devfreq->dev)); | ||
| 30 | ), | ||
| 31 | |||
| 32 | TP_printk("dev_name=%s freq=%lu polling_ms=%u load=%lu", | ||
| 33 | __get_str(dev_name), __entry->freq, __entry->polling_ms, | ||
| 34 | __entry->total_time == 0 ? 0 : | ||
| 35 | (100 * __entry->busy_time) / __entry->total_time) | ||
| 36 | ); | ||
| 37 | #endif /* _TRACE_DEVFREQ_H */ | ||
| 38 | |||
| 39 | /* This part must be outside protection */ | ||
| 40 | #include <trace/define_trace.h> | ||
