diff options
| -rw-r--r-- | drivers/platform/tegra/tegra-camera-rtcpu.c | 139 | ||||
| -rw-r--r-- | include/linux/platform/tegra/emc_bwmgr.h | 1 |
2 files changed, 117 insertions, 23 deletions
diff --git a/drivers/platform/tegra/tegra-camera-rtcpu.c b/drivers/platform/tegra/tegra-camera-rtcpu.c index 0e4fc172a..4b2900248 100644 --- a/drivers/platform/tegra/tegra-camera-rtcpu.c +++ b/drivers/platform/tegra/tegra-camera-rtcpu.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/of_irq.h> | 31 | #include <linux/of_irq.h> |
| 32 | #include <linux/of_platform.h> | 32 | #include <linux/of_platform.h> |
| 33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
| 34 | #include <linux/platform/tegra/emc_bwmgr.h> | ||
| 34 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
| 35 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
| 36 | #include <linux/seq_buf.h> | 37 | #include <linux/seq_buf.h> |
| @@ -201,6 +202,10 @@ struct tegra_cam_rtcpu { | |||
| 201 | } cmd; | 202 | } cmd; |
| 202 | u32 fw_version; | 203 | u32 fw_version; |
| 203 | u8 fw_hash[RTCPU_FW_HASH_SIZE]; | 204 | u8 fw_hash[RTCPU_FW_HASH_SIZE]; |
| 205 | struct { | ||
| 206 | u64 reset_complete; | ||
| 207 | u64 boot_handshake; | ||
| 208 | } stats; | ||
| 204 | union { | 209 | union { |
| 205 | void __iomem *regs[CAMRTC_NUM_REGS]; | 210 | void __iomem *regs[CAMRTC_NUM_REGS]; |
| 206 | struct { | 211 | struct { |
| @@ -221,7 +226,10 @@ struct tegra_cam_rtcpu { | |||
| 221 | }; | 226 | }; |
| 222 | const struct tegra_cam_rtcpu_pdata *pdata; | 227 | const struct tegra_cam_rtcpu_pdata *pdata; |
| 223 | struct camrtc_device_group *camera_devices; | 228 | struct camrtc_device_group *camera_devices; |
| 229 | struct tegra_bwmgr_client *bwmgr; | ||
| 224 | struct tegra_camrtc_mon *monitor; | 230 | struct tegra_camrtc_mon *monitor; |
| 231 | unsigned long full_bw; | ||
| 232 | u32 max_reboot_retry; | ||
| 225 | bool powered; | 233 | bool powered; |
| 226 | bool boot_sync_done; | 234 | bool boot_sync_done; |
| 227 | bool online; | 235 | bool online; |
| @@ -375,11 +383,64 @@ static void tegra_camrtc_assert_resets(struct device *dev) | |||
| 375 | static int tegra_camrtc_deassert_resets(struct device *dev) | 383 | static int tegra_camrtc_deassert_resets(struct device *dev) |
| 376 | { | 384 | { |
| 377 | struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev); | 385 | struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev); |
| 386 | int ret = 0; | ||
| 378 | 387 | ||
| 379 | if (rtcpu->pdata->deassert_resets) | 388 | if (rtcpu->pdata->deassert_resets) { |
| 380 | return rtcpu->pdata->deassert_resets(dev); | 389 | ret = rtcpu->pdata->deassert_resets(dev); |
| 390 | rtcpu->stats.reset_complete = ktime_get_ns(); | ||
| 391 | rtcpu->stats.boot_handshake = 0; | ||
| 392 | } | ||
| 381 | 393 | ||
| 382 | return 0; | 394 | return ret; |
| 395 | } | ||
| 396 | |||
| 397 | static void tegra_camrtc_init_bwmgr(struct device *dev) | ||
| 398 | { | ||
| 399 | struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev); | ||
| 400 | u32 bw; | ||
| 401 | |||
| 402 | if (of_property_read_u32(dev->of_node, NV(memory-bw), &bw) != 0) | ||
| 403 | return; | ||
| 404 | |||
| 405 | if (bw == 0xFFFFFFFFU) | ||
| 406 | rtcpu->full_bw = tegra_bwmgr_get_max_emc_rate(); | ||
| 407 | else | ||
| 408 | rtcpu->full_bw = tegra_bwmgr_round_rate(bw); | ||
| 409 | |||
| 410 | rtcpu->bwmgr = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_CAMRTC); | ||
| 411 | |||
| 412 | if (IS_ERR_OR_NULL(rtcpu->bwmgr)) { | ||
| 413 | dev_warn(dev, "no memory bw manager\n"); | ||
| 414 | rtcpu->bwmgr = NULL; | ||
| 415 | return; | ||
| 416 | } | ||
| 417 | |||
| 418 | dev_dbg(dev, "using emc rate %lu for power-on\n", rtcpu->full_bw); | ||
| 419 | } | ||
| 420 | |||
| 421 | static void tegra_camrtc_full_mem_bw(struct device *dev) | ||
| 422 | { | ||
| 423 | struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev); | ||
| 424 | |||
| 425 | if (rtcpu->bwmgr != NULL) { | ||
| 426 | int ret = tegra_bwmgr_set_emc(rtcpu->bwmgr, rtcpu->full_bw, | ||
| 427 | TEGRA_BWMGR_SET_EMC_FLOOR); | ||
| 428 | if (ret < 0) | ||
| 429 | dev_info(dev, "emc request rate %lu failed, %d\n", | ||
| 430 | rtcpu->full_bw, ret); | ||
| 431 | else | ||
| 432 | dev_dbg(dev, "requested emc rate %lu\n", | ||
| 433 | rtcpu->full_bw); | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | static void tegra_camrtc_slow_mem_bw(struct device *dev) | ||
| 438 | { | ||
| 439 | struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev); | ||
| 440 | |||
| 441 | if (rtcpu->bwmgr != NULL) | ||
| 442 | (void)tegra_bwmgr_set_emc(rtcpu->bwmgr, 0, | ||
| 443 | TEGRA_BWMGR_SET_EMC_FLOOR); | ||
| 383 | } | 444 | } |
| 384 | 445 | ||
| 385 | /* | 446 | /* |
| @@ -788,8 +849,10 @@ static int tegra_camrtc_poweron(struct device *dev, bool full_speed) | |||
| 788 | } | 849 | } |
| 789 | 850 | ||
| 790 | /* APE power domain may misbehave and try to resume while probing */ | 851 | /* APE power domain may misbehave and try to resume while probing */ |
| 791 | if (rtcpu->sm_pair == NULL) | 852 | if (rtcpu->sm_pair == NULL) { |
| 853 | dev_info(dev, "poweron while probing"); | ||
| 792 | return 0; | 854 | return 0; |
| 855 | } | ||
| 793 | 856 | ||
| 794 | /* Power on and let core run */ | 857 | /* Power on and let core run */ |
| 795 | ret = tegra_camrtc_enable_clks(dev); | 858 | ret = tegra_camrtc_enable_clks(dev); |
| @@ -846,6 +909,18 @@ static int tegra_camrtc_boot_sync(struct device *dev) | |||
| 846 | return -EIO; | 909 | return -EIO; |
| 847 | } | 910 | } |
| 848 | 911 | ||
| 912 | if (rtcpu->stats.boot_handshake == 0) { | ||
| 913 | u64 bt; | ||
| 914 | |||
| 915 | rtcpu->stats.boot_handshake = ktime_get_ns(); | ||
| 916 | |||
| 917 | bt = rtcpu->stats.boot_handshake - | ||
| 918 | rtcpu->stats.reset_complete + 500U; | ||
| 919 | |||
| 920 | dev_dbg(dev, "boot time %llu.%03u ms\n", bt / 1000000U, | ||
| 921 | (unsigned int)(bt % 10000000U) / 1000U); | ||
| 922 | } | ||
| 923 | |||
| 849 | command = RTCPU_COMMAND(FW_VERSION, RTCPU_DRIVER_SM5_VERSION); | 924 | command = RTCPU_COMMAND(FW_VERSION, RTCPU_DRIVER_SM5_VERSION); |
| 850 | ret = tegra_camrtc_command(dev, command, 0); | 925 | ret = tegra_camrtc_command(dev, command, 0); |
| 851 | if (ret < 0) | 926 | if (ret < 0) |
| @@ -866,7 +941,7 @@ static int tegra_camrtc_boot_sync(struct device *dev) | |||
| 866 | ret = tegra_rtcpu_trace_boot_sync(rtcpu->tracer); | 941 | ret = tegra_rtcpu_trace_boot_sync(rtcpu->tracer); |
| 867 | if (ret < 0) { | 942 | if (ret < 0) { |
| 868 | dev_err(dev, "trace boot sync failed: %d\n", ret); | 943 | dev_err(dev, "trace boot sync failed: %d\n", ret); |
| 869 | goto error; | 944 | return ret; |
| 870 | } | 945 | } |
| 871 | } | 946 | } |
| 872 | 947 | ||
| @@ -886,9 +961,6 @@ static int tegra_camrtc_boot_sync(struct device *dev) | |||
| 886 | } | 961 | } |
| 887 | 962 | ||
| 888 | return 0; | 963 | return 0; |
| 889 | |||
| 890 | error: | ||
| 891 | return ret; | ||
| 892 | } | 964 | } |
| 893 | 965 | ||
| 894 | /* | 966 | /* |
| @@ -896,17 +968,35 @@ error: | |||
| 896 | */ | 968 | */ |
| 897 | static int tegra_camrtc_boot(struct device *dev) | 969 | static int tegra_camrtc_boot(struct device *dev) |
| 898 | { | 970 | { |
| 971 | struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev); | ||
| 972 | int retry = 0, max_retries = rtcpu->max_reboot_retry; | ||
| 899 | int ret; | 973 | int ret; |
| 900 | 974 | ||
| 901 | ret = tegra_camrtc_poweron(dev, true); | 975 | ret = tegra_camrtc_poweron(dev, true); |
| 902 | if (ret) | 976 | if (ret) |
| 903 | return ret; | 977 | return ret; |
| 904 | 978 | ||
| 905 | ret = tegra_camrtc_boot_sync(dev); | 979 | tegra_camrtc_full_mem_bw(dev); |
| 980 | |||
| 981 | for (;;) { | ||
| 982 | ret = tegra_camrtc_boot_sync(dev); | ||
| 983 | if (ret == 0) | ||
| 984 | break; | ||
| 985 | if (retry++ == max_retries) | ||
| 986 | break; | ||
| 987 | dev_warn(dev, "%s full reset, retry %u/%u\n", | ||
| 988 | rtcpu->name, retry, max_retries); | ||
| 989 | tegra_camrtc_assert_resets(dev); | ||
| 990 | usleep_range(10, 30); | ||
| 991 | tegra_camrtc_deassert_resets(dev); | ||
| 992 | } | ||
| 993 | |||
| 906 | if (ret == 0) { | 994 | if (ret == 0) { |
| 907 | tegra_camrtc_set_online(dev, true); | 995 | tegra_camrtc_set_online(dev, true); |
| 908 | } | 996 | } |
| 909 | 997 | ||
| 998 | tegra_camrtc_slow_mem_bw(dev); | ||
| 999 | |||
| 910 | return 0; | 1000 | return 0; |
| 911 | } | 1001 | } |
| 912 | 1002 | ||
| @@ -1012,19 +1102,11 @@ static int tegra_cam_rtcpu_runtime_resume(struct device *dev) | |||
| 1012 | if (ret < 0) | 1102 | if (ret < 0) |
| 1013 | return ret; | 1103 | return ret; |
| 1014 | 1104 | ||
| 1015 | ret = tegra_camrtc_poweron(dev, true); | 1105 | ret = tegra_camrtc_boot(dev); |
| 1016 | if (ret) | ||
| 1017 | goto error; | ||
| 1018 | |||
| 1019 | ret = tegra_camrtc_boot_sync(dev); | ||
| 1020 | if (ret) | ||
| 1021 | goto error; | ||
| 1022 | 1106 | ||
| 1023 | tegra_camrtc_set_online(dev, true); | 1107 | if (ret < 0) |
| 1108 | camrtc_device_group_idle(rtcpu->camera_devices); | ||
| 1024 | 1109 | ||
| 1025 | return 0; | ||
| 1026 | error: | ||
| 1027 | camrtc_device_group_idle(rtcpu->camera_devices); | ||
| 1028 | return ret; | 1110 | return ret; |
| 1029 | } | 1111 | } |
| 1030 | 1112 | ||
| @@ -1120,10 +1202,14 @@ static int tegra_cam_rtcpu_remove(struct platform_device *pdev) | |||
| 1120 | } | 1202 | } |
| 1121 | 1203 | ||
| 1122 | tegra_rtcpu_trace_destroy(rtcpu->tracer); | 1204 | tegra_rtcpu_trace_destroy(rtcpu->tracer); |
| 1123 | if (rtcpu->coverage != NULL) | 1205 | rtcpu->tracer = NULL; |
| 1124 | tegra_rtcpu_coverage_destroy(rtcpu->coverage); | 1206 | tegra_rtcpu_coverage_destroy(rtcpu->coverage); |
| 1207 | rtcpu->coverage = NULL; | ||
| 1125 | 1208 | ||
| 1126 | tegra_camrtc_poweroff(&pdev->dev); | 1209 | tegra_camrtc_poweroff(&pdev->dev); |
| 1210 | if (rtcpu->bwmgr != NULL) | ||
| 1211 | tegra_bwmgr_unregister(rtcpu->bwmgr); | ||
| 1212 | rtcpu->bwmgr = NULL; | ||
| 1127 | tegra_pd_remove_device(&pdev->dev); | 1213 | tegra_pd_remove_device(&pdev->dev); |
| 1128 | tegra_cam_rtcpu_mon_destroy(rtcpu->monitor); | 1214 | tegra_cam_rtcpu_mon_destroy(rtcpu->monitor); |
| 1129 | tegra_ivc_bus_destroy(rtcpu->ivc); | 1215 | tegra_ivc_bus_destroy(rtcpu->ivc); |
| @@ -1170,6 +1256,10 @@ static int tegra_cam_rtcpu_probe(struct platform_device *pdev) | |||
| 1170 | if (ret) | 1256 | if (ret) |
| 1171 | goto fail; | 1257 | goto fail; |
| 1172 | 1258 | ||
| 1259 | rtcpu->max_reboot_retry = 2; | ||
| 1260 | (void)of_property_read_u32(dev->of_node, NV(max-reboot), | ||
| 1261 | &rtcpu->max_reboot_retry); | ||
| 1262 | |||
| 1173 | timeout = 2000; | 1263 | timeout = 2000; |
| 1174 | (void)of_property_read_u32(dev->of_node, NV(cmd-timeout), &timeout); | 1264 | (void)of_property_read_u32(dev->of_node, NV(cmd-timeout), &timeout); |
| 1175 | rtcpu->cmd.timeout = msecs_to_jiffies(timeout); | 1265 | rtcpu->cmd.timeout = msecs_to_jiffies(timeout); |
| @@ -1181,6 +1271,8 @@ static int tegra_cam_rtcpu_probe(struct platform_device *pdev) | |||
| 1181 | pm_runtime_set_autosuspend_delay(&pdev->dev, timeout); | 1271 | pm_runtime_set_autosuspend_delay(&pdev->dev, timeout); |
| 1182 | } | 1272 | } |
| 1183 | 1273 | ||
| 1274 | tegra_camrtc_init_bwmgr(dev); | ||
| 1275 | |||
| 1184 | dev->dma_parms = &rtcpu->dma_parms; | 1276 | dev->dma_parms = &rtcpu->dma_parms; |
| 1185 | dma_set_max_seg_size(dev, UINT_MAX); | 1277 | dma_set_max_seg_size(dev, UINT_MAX); |
| 1186 | 1278 | ||
| @@ -1193,7 +1285,8 @@ static int tegra_cam_rtcpu_probe(struct platform_device *pdev) | |||
| 1193 | goto fail; | 1285 | goto fail; |
| 1194 | 1286 | ||
| 1195 | /* Power on device */ | 1287 | /* Power on device */ |
| 1196 | if (pm_runtime_get_sync(dev) < 0) | 1288 | ret = pm_runtime_get_sync(dev); |
| 1289 | if (ret < 0) | ||
| 1197 | goto fail; | 1290 | goto fail; |
| 1198 | 1291 | ||
| 1199 | /* Clocks are on, resets are deasserted, we can touch the hardware */ | 1292 | /* Clocks are on, resets are deasserted, we can touch the hardware */ |
diff --git a/include/linux/platform/tegra/emc_bwmgr.h b/include/linux/platform/tegra/emc_bwmgr.h index 64d6f6f89..cbc79b03b 100644 --- a/include/linux/platform/tegra/emc_bwmgr.h +++ b/include/linux/platform/tegra/emc_bwmgr.h | |||
| @@ -50,6 +50,7 @@ enum tegra_bwmgr_client_id { | |||
| 50 | TEGRA_BWMGR_CLIENT_ISPB, | 50 | TEGRA_BWMGR_CLIENT_ISPB, |
| 51 | TEGRA_BWMGR_CLIENT_CAMERA, | 51 | TEGRA_BWMGR_CLIENT_CAMERA, |
| 52 | TEGRA_BWMGR_CLIENT_CAMERA_NON_ISO, | 52 | TEGRA_BWMGR_CLIENT_CAMERA_NON_ISO, |
| 53 | TEGRA_BWMGR_CLIENT_CAMRTC, | ||
| 53 | TEGRA_BWMGR_CLIENT_ISOMGR, | 54 | TEGRA_BWMGR_CLIENT_ISOMGR, |
| 54 | TEGRA_BWMGR_CLIENT_THERMAL_CAP, | 55 | TEGRA_BWMGR_CLIENT_THERMAL_CAP, |
| 55 | TEGRA_BWMGR_CLIENT_VIC, | 56 | TEGRA_BWMGR_CLIENT_VIC, |
