.. | .. |
---|
36 | 36 | #define VEPU2_REG_HW_ID_INDEX -1 /* INVALID */ |
---|
37 | 37 | #define VEPU2_REG_START_INDEX 0 |
---|
38 | 38 | #define VEPU2_REG_END_INDEX 183 |
---|
| 39 | +#define VEPU2_REG_OUT_INDEX (77) |
---|
| 40 | +#define VEPU2_REG_STRM_INDEX (53) |
---|
39 | 41 | |
---|
40 | 42 | #define VEPU2_REG_ENC_EN 0x19c |
---|
41 | 43 | #define VEPU2_REG_ENC_EN_INDEX (103) |
---|
.. | .. |
---|
97 | 99 | u32 width; |
---|
98 | 100 | u32 height; |
---|
99 | 101 | u32 pixels; |
---|
| 102 | + struct mpp_dma_buffer *bs_buf; |
---|
| 103 | + u32 offset_bs; |
---|
100 | 104 | }; |
---|
101 | 105 | |
---|
102 | 106 | struct vepu_session_priv { |
---|
.. | .. |
---|
121 | 125 | #endif |
---|
122 | 126 | struct reset_control *rst_a; |
---|
123 | 127 | struct reset_control *rst_h; |
---|
| 128 | + /* for ccu(central control unit) */ |
---|
| 129 | + struct vepu_ccu *ccu; |
---|
| 130 | + bool disable_work; |
---|
| 131 | +}; |
---|
| 132 | + |
---|
| 133 | +struct vepu_ccu { |
---|
| 134 | + u32 core_num; |
---|
| 135 | + /* lock for core attach */ |
---|
| 136 | + spinlock_t lock; |
---|
| 137 | + struct mpp_dev *main_core; |
---|
| 138 | + struct mpp_dev *cores[MPP_MAX_CORE_NUM]; |
---|
| 139 | + unsigned long core_idle; |
---|
124 | 140 | }; |
---|
125 | 141 | |
---|
126 | 142 | static struct mpp_hw_info vepu_v2_hw_info = { |
---|
.. | .. |
---|
167 | 183 | struct mpp_task_msgs *msgs) |
---|
168 | 184 | { |
---|
169 | 185 | int ret; |
---|
| 186 | + int fd_bs; |
---|
170 | 187 | int fmt = VEPU2_GET_FORMAT(task->reg[VEPU2_REG_ENC_EN_INDEX]); |
---|
| 188 | + |
---|
| 189 | + if (session->msg_flags & MPP_FLAGS_REG_NO_OFFSET) |
---|
| 190 | + fd_bs = task->reg[VEPU2_REG_OUT_INDEX]; |
---|
| 191 | + else |
---|
| 192 | + fd_bs = task->reg[VEPU2_REG_OUT_INDEX] & 0x3ff; |
---|
171 | 193 | |
---|
172 | 194 | ret = mpp_translate_reg_address(session, &task->mpp_task, |
---|
173 | 195 | fmt, task->reg, &task->off_inf); |
---|
.. | .. |
---|
176 | 198 | |
---|
177 | 199 | mpp_translate_reg_offset_info(&task->mpp_task, |
---|
178 | 200 | &task->off_inf, task->reg); |
---|
| 201 | + |
---|
| 202 | + if (fmt == VEPU2_FMT_JPEGE) { |
---|
| 203 | + struct mpp_dma_buffer *bs_buf = mpp_dma_find_buffer_fd(session->dma, fd_bs); |
---|
| 204 | + |
---|
| 205 | + task->offset_bs = mpp_query_reg_offset_info(&task->off_inf, VEPU2_REG_OUT_INDEX); |
---|
| 206 | + if (bs_buf && task->offset_bs > 0) |
---|
| 207 | + mpp_dma_buf_sync(bs_buf, 0, task->offset_bs, DMA_TO_DEVICE, false); |
---|
| 208 | + task->bs_buf = bs_buf; |
---|
| 209 | + } |
---|
179 | 210 | |
---|
180 | 211 | return 0; |
---|
181 | 212 | } |
---|
.. | .. |
---|
281 | 312 | return NULL; |
---|
282 | 313 | } |
---|
283 | 314 | |
---|
| 315 | +static void *vepu_prepare(struct mpp_dev *mpp, struct mpp_task *mpp_task) |
---|
| 316 | +{ |
---|
| 317 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 318 | + struct vepu_ccu *ccu = enc->ccu; |
---|
| 319 | + unsigned long core_idle; |
---|
| 320 | + unsigned long flags; |
---|
| 321 | + s32 core_id; |
---|
| 322 | + u32 i; |
---|
| 323 | + |
---|
| 324 | + spin_lock_irqsave(&ccu->lock, flags); |
---|
| 325 | + |
---|
| 326 | + core_idle = ccu->core_idle; |
---|
| 327 | + |
---|
| 328 | + for (i = 0; i < ccu->core_num; i++) { |
---|
| 329 | + struct mpp_dev *mpp = ccu->cores[i]; |
---|
| 330 | + |
---|
| 331 | + if (mpp && mpp->disable) |
---|
| 332 | + clear_bit(mpp->core_id, &core_idle); |
---|
| 333 | + } |
---|
| 334 | + |
---|
| 335 | + core_id = find_first_bit(&core_idle, ccu->core_num); |
---|
| 336 | + if (core_id >= ARRAY_SIZE(ccu->cores)) { |
---|
| 337 | + mpp_task = NULL; |
---|
| 338 | + mpp_dbg_core("core %d all busy %lx\n", core_id, ccu->core_idle); |
---|
| 339 | + goto done; |
---|
| 340 | + } |
---|
| 341 | + |
---|
| 342 | + core_id = array_index_nospec(core_id, MPP_MAX_CORE_NUM); |
---|
| 343 | + clear_bit(core_id, &ccu->core_idle); |
---|
| 344 | + mpp_task->mpp = ccu->cores[core_id]; |
---|
| 345 | + mpp_task->core_id = core_id; |
---|
| 346 | + |
---|
| 347 | + mpp_dbg_core("core cnt %d core %d set idle %lx -> %lx\n", |
---|
| 348 | + ccu->core_num, core_id, core_idle, ccu->core_idle); |
---|
| 349 | + |
---|
| 350 | +done: |
---|
| 351 | + spin_unlock_irqrestore(&ccu->lock, flags); |
---|
| 352 | + |
---|
| 353 | + return mpp_task; |
---|
| 354 | +} |
---|
| 355 | + |
---|
284 | 356 | static int vepu_run(struct mpp_dev *mpp, |
---|
285 | 357 | struct mpp_task *mpp_task) |
---|
286 | 358 | { |
---|
.. | .. |
---|
327 | 399 | return 0; |
---|
328 | 400 | } |
---|
329 | 401 | |
---|
| 402 | +static int vepu_px30_run(struct mpp_dev *mpp, |
---|
| 403 | + struct mpp_task *mpp_task) |
---|
| 404 | +{ |
---|
| 405 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
---|
| 406 | + return vepu_run(mpp, mpp_task); |
---|
| 407 | +} |
---|
| 408 | + |
---|
330 | 409 | static int vepu_irq(struct mpp_dev *mpp) |
---|
331 | 410 | { |
---|
332 | 411 | mpp->irq_status = mpp_read(mpp, VEPU2_REG_INT); |
---|
.. | .. |
---|
343 | 422 | u32 err_mask; |
---|
344 | 423 | struct vepu_task *task = NULL; |
---|
345 | 424 | struct mpp_task *mpp_task = mpp->cur_task; |
---|
| 425 | + unsigned long core_idle; |
---|
| 426 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 427 | + struct vepu_ccu *ccu = enc->ccu; |
---|
346 | 428 | |
---|
347 | 429 | /* FIXME use a spin lock here */ |
---|
348 | 430 | if (!mpp_task) { |
---|
.. | .. |
---|
364 | 446 | atomic_inc(&mpp->reset_request); |
---|
365 | 447 | |
---|
366 | 448 | mpp_task_finish(mpp_task->session, mpp_task); |
---|
| 449 | + /* the whole vepu has no ccu that manage multi core */ |
---|
| 450 | + if (ccu) { |
---|
| 451 | + core_idle = ccu->core_idle; |
---|
| 452 | + set_bit(mpp->core_id, &ccu->core_idle); |
---|
| 453 | + |
---|
| 454 | + mpp_dbg_core("core %d isr idle %lx -> %lx\n", mpp->core_id, core_idle, |
---|
| 455 | + ccu->core_idle); |
---|
| 456 | + } |
---|
367 | 457 | |
---|
368 | 458 | mpp_debug_leave(); |
---|
369 | 459 | |
---|
.. | .. |
---|
390 | 480 | /* revert hack for irq status */ |
---|
391 | 481 | task->reg[VEPU2_REG_INT_INDEX] = task->irq_status; |
---|
392 | 482 | |
---|
| 483 | + if (task->bs_buf) |
---|
| 484 | + mpp_dma_buf_sync(task->bs_buf, 0, |
---|
| 485 | + task->reg[VEPU2_REG_STRM_INDEX] / 8 + |
---|
| 486 | + task->offset_bs, |
---|
| 487 | + DMA_FROM_DEVICE, true); |
---|
393 | 488 | mpp_debug_leave(); |
---|
394 | 489 | |
---|
395 | 490 | return 0; |
---|
.. | .. |
---|
532 | 627 | } |
---|
533 | 628 | seq_puts(seq, "\n"); |
---|
534 | 629 | /* item data*/ |
---|
535 | | - seq_printf(seq, "|%8p|", session); |
---|
| 630 | + seq_printf(seq, "|%8d|", session->index); |
---|
536 | 631 | seq_printf(seq, "%8s|", mpp_device_name[session->device_type]); |
---|
537 | 632 | for (i = ENC_INFO_BASE; i < ENC_INFO_BUTT; i++) { |
---|
538 | 633 | u32 flag = priv->codec_info[i].flag; |
---|
.. | .. |
---|
565 | 660 | mutex_lock(&mpp->srv->session_lock); |
---|
566 | 661 | list_for_each_entry_safe(session, n, |
---|
567 | 662 | &mpp->srv->session_list, |
---|
568 | | - session_link) { |
---|
569 | | - if (session->device_type != MPP_DEVICE_VEPU2) |
---|
| 663 | + service_link) { |
---|
| 664 | + if (session->device_type != MPP_DEVICE_VEPU2 && |
---|
| 665 | + session->device_type != MPP_DEVICE_VEPU2_JPEG) |
---|
570 | 666 | continue; |
---|
571 | 667 | if (!session->priv) |
---|
572 | 668 | continue; |
---|
.. | .. |
---|
581 | 677 | static int vepu_procfs_init(struct mpp_dev *mpp) |
---|
582 | 678 | { |
---|
583 | 679 | struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 680 | + char name[32]; |
---|
584 | 681 | |
---|
585 | | - enc->procfs = proc_mkdir(mpp->dev->of_node->name, mpp->srv->procfs); |
---|
| 682 | + if (!mpp->dev || !mpp->dev->of_node || !mpp->dev->of_node->name || |
---|
| 683 | + !mpp->srv || !mpp->srv->procfs) |
---|
| 684 | + return -EINVAL; |
---|
| 685 | + if (enc->ccu) |
---|
| 686 | + snprintf(name, sizeof(name) - 1, "%s%d", |
---|
| 687 | + mpp->dev->of_node->name, mpp->core_id); |
---|
| 688 | + else |
---|
| 689 | + snprintf(name, sizeof(name) - 1, "%s", |
---|
| 690 | + mpp->dev->of_node->name); |
---|
| 691 | + |
---|
| 692 | + enc->procfs = proc_mkdir(name, mpp->srv->procfs); |
---|
586 | 693 | if (IS_ERR_OR_NULL(enc->procfs)) { |
---|
587 | 694 | mpp_err("failed on open procfs\n"); |
---|
588 | 695 | enc->procfs = NULL; |
---|
.. | .. |
---|
602 | 709 | |
---|
603 | 710 | return 0; |
---|
604 | 711 | } |
---|
| 712 | + |
---|
| 713 | +static int vepu_procfs_ccu_init(struct mpp_dev *mpp) |
---|
| 714 | +{ |
---|
| 715 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 716 | + |
---|
| 717 | + if (!enc->procfs) |
---|
| 718 | + goto done; |
---|
| 719 | + |
---|
| 720 | +done: |
---|
| 721 | + return 0; |
---|
| 722 | +} |
---|
605 | 723 | #else |
---|
606 | 724 | static inline int vepu_procfs_remove(struct mpp_dev *mpp) |
---|
607 | 725 | { |
---|
.. | .. |
---|
609 | 727 | } |
---|
610 | 728 | |
---|
611 | 729 | static inline int vepu_procfs_init(struct mpp_dev *mpp) |
---|
| 730 | +{ |
---|
| 731 | + return 0; |
---|
| 732 | +} |
---|
| 733 | + |
---|
| 734 | +static inline int vepu_procfs_ccu_init(struct mpp_dev *mpp) |
---|
612 | 735 | { |
---|
613 | 736 | return 0; |
---|
614 | 737 | } |
---|
.. | .. |
---|
735 | 858 | static int vepu_reset(struct mpp_dev *mpp) |
---|
736 | 859 | { |
---|
737 | 860 | struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 861 | + struct vepu_ccu *ccu = enc->ccu; |
---|
738 | 862 | |
---|
739 | 863 | mpp_write(mpp, VEPU2_REG_ENC_EN, 0); |
---|
740 | 864 | udelay(5); |
---|
.. | .. |
---|
749 | 873 | mpp_pmu_idle_request(mpp, false); |
---|
750 | 874 | } |
---|
751 | 875 | mpp_write(mpp, VEPU2_REG_INT, VEPU2_INT_CLEAR); |
---|
| 876 | + |
---|
| 877 | + if (ccu) { |
---|
| 878 | + set_bit(mpp->core_id, &ccu->core_idle); |
---|
| 879 | + mpp_dbg_core("core %d reset idle %lx\n", mpp->core_id, ccu->core_idle); |
---|
| 880 | + } |
---|
752 | 881 | |
---|
753 | 882 | return 0; |
---|
754 | 883 | } |
---|
.. | .. |
---|
787 | 916 | .dump_session = vepu_dump_session, |
---|
788 | 917 | }; |
---|
789 | 918 | |
---|
| 919 | +static struct mpp_dev_ops vepu_px30_dev_ops = { |
---|
| 920 | + .alloc_task = vepu_alloc_task, |
---|
| 921 | + .run = vepu_px30_run, |
---|
| 922 | + .irq = vepu_irq, |
---|
| 923 | + .isr = vepu_isr, |
---|
| 924 | + .finish = vepu_finish, |
---|
| 925 | + .result = vepu_result, |
---|
| 926 | + .free_task = vepu_free_task, |
---|
| 927 | + .ioctl = vepu_control, |
---|
| 928 | + .init_session = vepu_init_session, |
---|
| 929 | + .free_session = vepu_free_session, |
---|
| 930 | + .dump_session = vepu_dump_session, |
---|
| 931 | +}; |
---|
| 932 | + |
---|
| 933 | +static struct mpp_dev_ops vepu_ccu_dev_ops = { |
---|
| 934 | + .alloc_task = vepu_alloc_task, |
---|
| 935 | + .prepare = vepu_prepare, |
---|
| 936 | + .run = vepu_run, |
---|
| 937 | + .irq = vepu_irq, |
---|
| 938 | + .isr = vepu_isr, |
---|
| 939 | + .finish = vepu_finish, |
---|
| 940 | + .result = vepu_result, |
---|
| 941 | + .free_task = vepu_free_task, |
---|
| 942 | + .ioctl = vepu_control, |
---|
| 943 | + .init_session = vepu_init_session, |
---|
| 944 | + .free_session = vepu_free_session, |
---|
| 945 | + .dump_session = vepu_dump_session, |
---|
| 946 | +}; |
---|
| 947 | + |
---|
| 948 | + |
---|
790 | 949 | static const struct mpp_dev_var vepu_v2_data = { |
---|
791 | 950 | .device_type = MPP_DEVICE_VEPU2, |
---|
792 | 951 | .hw_info = &vepu_v2_hw_info, |
---|
.. | .. |
---|
800 | 959 | .hw_info = &vepu_v2_hw_info, |
---|
801 | 960 | .trans_info = trans_rk_vepu2, |
---|
802 | 961 | .hw_ops = &vepu_px30_hw_ops, |
---|
803 | | - .dev_ops = &vepu_v2_dev_ops, |
---|
| 962 | + .dev_ops = &vepu_px30_dev_ops, |
---|
| 963 | +}; |
---|
| 964 | + |
---|
| 965 | +static const struct mpp_dev_var vepu_ccu_data = { |
---|
| 966 | + .device_type = MPP_DEVICE_VEPU2_JPEG, |
---|
| 967 | + .hw_info = &vepu_v2_hw_info, |
---|
| 968 | + .trans_info = trans_rk_vepu2, |
---|
| 969 | + .hw_ops = &vepu_v2_hw_ops, |
---|
| 970 | + .dev_ops = &vepu_ccu_dev_ops, |
---|
804 | 971 | }; |
---|
805 | 972 | |
---|
806 | 973 | static const struct of_device_id mpp_vepu2_dt_match[] = { |
---|
.. | .. |
---|
814 | 981 | .data = &vepu_px30_data, |
---|
815 | 982 | }, |
---|
816 | 983 | #endif |
---|
| 984 | +#ifdef CONFIG_CPU_RK3588 |
---|
| 985 | + { |
---|
| 986 | + .compatible = "rockchip,vpu-jpege-core", |
---|
| 987 | + .data = &vepu_ccu_data, |
---|
| 988 | + }, |
---|
| 989 | + { |
---|
| 990 | + .compatible = "rockchip,vpu-jpege-ccu", |
---|
| 991 | + }, |
---|
| 992 | +#endif |
---|
817 | 993 | {}, |
---|
818 | 994 | }; |
---|
819 | 995 | |
---|
820 | | -static int vepu_probe(struct platform_device *pdev) |
---|
| 996 | +static int vepu_ccu_probe(struct platform_device *pdev) |
---|
| 997 | +{ |
---|
| 998 | + struct vepu_ccu *ccu; |
---|
| 999 | + struct device *dev = &pdev->dev; |
---|
| 1000 | + |
---|
| 1001 | + ccu = devm_kzalloc(dev, sizeof(*ccu), GFP_KERNEL); |
---|
| 1002 | + if (!ccu) |
---|
| 1003 | + return -ENOMEM; |
---|
| 1004 | + |
---|
| 1005 | + platform_set_drvdata(pdev, ccu); |
---|
| 1006 | + spin_lock_init(&ccu->lock); |
---|
| 1007 | + return 0; |
---|
| 1008 | +} |
---|
| 1009 | + |
---|
| 1010 | +static int vepu_attach_ccu(struct device *dev, struct vepu_dev *enc) |
---|
| 1011 | +{ |
---|
| 1012 | + struct device_node *np; |
---|
| 1013 | + struct platform_device *pdev; |
---|
| 1014 | + struct vepu_ccu *ccu; |
---|
| 1015 | + unsigned long flags; |
---|
| 1016 | + |
---|
| 1017 | + np = of_parse_phandle(dev->of_node, "rockchip,ccu", 0); |
---|
| 1018 | + if (!np || !of_device_is_available(np)) |
---|
| 1019 | + return -ENODEV; |
---|
| 1020 | + |
---|
| 1021 | + pdev = of_find_device_by_node(np); |
---|
| 1022 | + of_node_put(np); |
---|
| 1023 | + if (!pdev) |
---|
| 1024 | + return -ENODEV; |
---|
| 1025 | + |
---|
| 1026 | + ccu = platform_get_drvdata(pdev); |
---|
| 1027 | + if (!ccu) |
---|
| 1028 | + return -ENOMEM; |
---|
| 1029 | + |
---|
| 1030 | + spin_lock_irqsave(&ccu->lock, flags); |
---|
| 1031 | + ccu->core_num++; |
---|
| 1032 | + ccu->cores[enc->mpp.core_id] = &enc->mpp; |
---|
| 1033 | + set_bit(enc->mpp.core_id, &ccu->core_idle); |
---|
| 1034 | + spin_unlock_irqrestore(&ccu->lock, flags); |
---|
| 1035 | + |
---|
| 1036 | + /* attach the ccu-domain to current core */ |
---|
| 1037 | + if (!ccu->main_core) { |
---|
| 1038 | + /** |
---|
| 1039 | + * set the first device for the main-core, |
---|
| 1040 | + * then the domain of the main-core named ccu-domain |
---|
| 1041 | + */ |
---|
| 1042 | + ccu->main_core = &enc->mpp; |
---|
| 1043 | + } else { |
---|
| 1044 | + struct mpp_iommu_info *ccu_info, *cur_info; |
---|
| 1045 | + |
---|
| 1046 | + /* set the ccu domain for current device */ |
---|
| 1047 | + ccu_info = ccu->main_core->iommu_info; |
---|
| 1048 | + cur_info = enc->mpp.iommu_info; |
---|
| 1049 | + |
---|
| 1050 | + if (cur_info) |
---|
| 1051 | + cur_info->domain = ccu_info->domain; |
---|
| 1052 | + mpp_iommu_attach(cur_info); |
---|
| 1053 | + } |
---|
| 1054 | + enc->ccu = ccu; |
---|
| 1055 | + |
---|
| 1056 | + dev_info(dev, "attach ccu success\n"); |
---|
| 1057 | + return 0; |
---|
| 1058 | +} |
---|
| 1059 | + |
---|
| 1060 | +static int vepu_core_probe(struct platform_device *pdev) |
---|
821 | 1061 | { |
---|
822 | 1062 | struct device *dev = &pdev->dev; |
---|
823 | 1063 | struct vepu_dev *enc = NULL; |
---|
.. | .. |
---|
825 | 1065 | const struct of_device_id *match = NULL; |
---|
826 | 1066 | int ret = 0; |
---|
827 | 1067 | |
---|
828 | | - dev_info(dev, "probe device\n"); |
---|
829 | 1068 | enc = devm_kzalloc(dev, sizeof(struct vepu_dev), GFP_KERNEL); |
---|
830 | 1069 | if (!enc) |
---|
831 | 1070 | return -ENOMEM; |
---|
832 | 1071 | |
---|
833 | 1072 | mpp = &enc->mpp; |
---|
834 | | - platform_set_drvdata(pdev, enc); |
---|
| 1073 | + platform_set_drvdata(pdev, mpp); |
---|
835 | 1074 | |
---|
836 | 1075 | if (pdev->dev.of_node) { |
---|
837 | 1076 | match = of_match_node(mpp_vepu2_dt_match, pdev->dev.of_node); |
---|
838 | 1077 | if (match) |
---|
839 | 1078 | mpp->var = (struct mpp_dev_var *)match->data; |
---|
| 1079 | + |
---|
| 1080 | + mpp->core_id = of_alias_get_id(pdev->dev.of_node, "jpege"); |
---|
| 1081 | + } |
---|
| 1082 | + |
---|
| 1083 | + ret = mpp_dev_probe(mpp, pdev); |
---|
| 1084 | + if (ret) { |
---|
| 1085 | + dev_err(dev, "probe sub driver failed\n"); |
---|
| 1086 | + return -EINVAL; |
---|
| 1087 | + } |
---|
| 1088 | + /* current device attach to ccu */ |
---|
| 1089 | + ret = vepu_attach_ccu(dev, enc); |
---|
| 1090 | + if (ret) |
---|
| 1091 | + return ret; |
---|
| 1092 | + |
---|
| 1093 | + ret = devm_request_threaded_irq(dev, mpp->irq, |
---|
| 1094 | + mpp_dev_irq, |
---|
| 1095 | + mpp_dev_isr_sched, |
---|
| 1096 | + IRQF_SHARED, |
---|
| 1097 | + dev_name(dev), mpp); |
---|
| 1098 | + if (ret) { |
---|
| 1099 | + dev_err(dev, "register interrupter runtime failed\n"); |
---|
| 1100 | + return -EINVAL; |
---|
| 1101 | + } |
---|
| 1102 | + |
---|
| 1103 | + mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS; |
---|
| 1104 | + vepu_procfs_init(mpp); |
---|
| 1105 | + vepu_procfs_ccu_init(mpp); |
---|
| 1106 | + /* if current is main-core, register current device to mpp service */ |
---|
| 1107 | + if (mpp == enc->ccu->main_core) |
---|
| 1108 | + mpp_dev_register_srv(mpp, mpp->srv); |
---|
| 1109 | + |
---|
| 1110 | + return 0; |
---|
| 1111 | +} |
---|
| 1112 | + |
---|
| 1113 | +static int vepu_probe_default(struct platform_device *pdev) |
---|
| 1114 | +{ |
---|
| 1115 | + struct device *dev = &pdev->dev; |
---|
| 1116 | + struct vepu_dev *enc = NULL; |
---|
| 1117 | + struct mpp_dev *mpp = NULL; |
---|
| 1118 | + const struct of_device_id *match = NULL; |
---|
| 1119 | + int ret = 0; |
---|
| 1120 | + |
---|
| 1121 | + enc = devm_kzalloc(dev, sizeof(struct vepu_dev), GFP_KERNEL); |
---|
| 1122 | + if (!enc) |
---|
| 1123 | + return -ENOMEM; |
---|
| 1124 | + |
---|
| 1125 | + mpp = &enc->mpp; |
---|
| 1126 | + platform_set_drvdata(pdev, mpp); |
---|
| 1127 | + |
---|
| 1128 | + if (pdev->dev.of_node) { |
---|
| 1129 | + match = of_match_node(mpp_vepu2_dt_match, pdev->dev.of_node); |
---|
| 1130 | + if (match) |
---|
| 1131 | + mpp->var = (struct mpp_dev_var *)match->data; |
---|
| 1132 | + |
---|
| 1133 | + mpp->core_id = of_alias_get_id(pdev->dev.of_node, "vepu"); |
---|
840 | 1134 | } |
---|
841 | 1135 | |
---|
842 | 1136 | ret = mpp_dev_probe(mpp, pdev); |
---|
.. | .. |
---|
859 | 1153 | vepu_procfs_init(mpp); |
---|
860 | 1154 | /* register current device to mpp service */ |
---|
861 | 1155 | mpp_dev_register_srv(mpp, mpp->srv); |
---|
862 | | - dev_info(dev, "probing finish\n"); |
---|
863 | 1156 | |
---|
864 | 1157 | return 0; |
---|
| 1158 | +} |
---|
| 1159 | + |
---|
| 1160 | +static int vepu_probe(struct platform_device *pdev) |
---|
| 1161 | +{ |
---|
| 1162 | + int ret; |
---|
| 1163 | + struct device *dev = &pdev->dev; |
---|
| 1164 | + struct device_node *np = dev->of_node; |
---|
| 1165 | + |
---|
| 1166 | + dev_info(dev, "probing start\n"); |
---|
| 1167 | + |
---|
| 1168 | + if (strstr(np->name, "ccu")) |
---|
| 1169 | + ret = vepu_ccu_probe(pdev); |
---|
| 1170 | + else if (strstr(np->name, "core")) |
---|
| 1171 | + ret = vepu_core_probe(pdev); |
---|
| 1172 | + else |
---|
| 1173 | + ret = vepu_probe_default(pdev); |
---|
| 1174 | + |
---|
| 1175 | + dev_info(dev, "probing finish\n"); |
---|
| 1176 | + |
---|
| 1177 | + return ret; |
---|
865 | 1178 | } |
---|
866 | 1179 | |
---|
867 | 1180 | static int vepu_remove(struct platform_device *pdev) |
---|
868 | 1181 | { |
---|
869 | 1182 | struct device *dev = &pdev->dev; |
---|
870 | | - struct vepu_dev *enc = platform_get_drvdata(pdev); |
---|
| 1183 | + struct device_node *np = dev->of_node; |
---|
871 | 1184 | |
---|
872 | | - dev_info(dev, "remove device\n"); |
---|
873 | | - mpp_dev_remove(&enc->mpp); |
---|
874 | | - vepu_procfs_remove(&enc->mpp); |
---|
| 1185 | + if (strstr(np->name, "ccu")) { |
---|
| 1186 | + dev_info(dev, "remove ccu device\n"); |
---|
| 1187 | + } else if (strstr(np->name, "core")) { |
---|
| 1188 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1189 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 1190 | + |
---|
| 1191 | + dev_info(dev, "remove core\n"); |
---|
| 1192 | + if (enc->ccu) { |
---|
| 1193 | + s32 core_id = mpp->core_id; |
---|
| 1194 | + struct vepu_ccu *ccu = enc->ccu; |
---|
| 1195 | + unsigned long flags; |
---|
| 1196 | + |
---|
| 1197 | + spin_lock_irqsave(&ccu->lock, flags); |
---|
| 1198 | + ccu->core_num--; |
---|
| 1199 | + ccu->cores[core_id] = NULL; |
---|
| 1200 | + clear_bit(core_id, &ccu->core_idle); |
---|
| 1201 | + spin_unlock_irqrestore(&ccu->lock, flags); |
---|
| 1202 | + } |
---|
| 1203 | + mpp_dev_remove(&enc->mpp); |
---|
| 1204 | + vepu_procfs_remove(&enc->mpp); |
---|
| 1205 | + } else { |
---|
| 1206 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1207 | + |
---|
| 1208 | + dev_info(dev, "remove device\n"); |
---|
| 1209 | + mpp_dev_remove(mpp); |
---|
| 1210 | + vepu_procfs_remove(mpp); |
---|
| 1211 | + } |
---|
875 | 1212 | |
---|
876 | 1213 | return 0; |
---|
877 | 1214 | } |
---|
878 | 1215 | |
---|
879 | 1216 | static void vepu_shutdown(struct platform_device *pdev) |
---|
880 | 1217 | { |
---|
881 | | - int ret; |
---|
882 | | - int val; |
---|
883 | 1218 | struct device *dev = &pdev->dev; |
---|
884 | | - struct vepu_dev *enc = platform_get_drvdata(pdev); |
---|
885 | | - struct mpp_dev *mpp = &enc->mpp; |
---|
886 | 1219 | |
---|
887 | | - dev_info(dev, "shutdown device\n"); |
---|
888 | | - |
---|
889 | | - atomic_inc(&mpp->srv->shutdown_request); |
---|
890 | | - ret = readx_poll_timeout(atomic_read, |
---|
891 | | - &mpp->task_count, |
---|
892 | | - val, val == 0, 20000, 200000); |
---|
893 | | - if (ret == -ETIMEDOUT) |
---|
894 | | - dev_err(dev, "wait total running time out\n"); |
---|
| 1220 | + if (!strstr(dev_name(dev), "ccu")) |
---|
| 1221 | + mpp_dev_shutdown(pdev); |
---|
895 | 1222 | } |
---|
896 | 1223 | |
---|
897 | 1224 | struct platform_driver rockchip_vepu2_driver = { |
---|