Lines Matching +full:serial +full:- +full:clk +full:- +full:low
1 // SPDX-License-Identifier: GPL-2.0
11 #include <dt-bindings/soc/cpm1-fsl,tsa.h>
12 #include <dt-bindings/soc/qe-fsl,tsa.h>
14 #include <linux/clk.h>
51 * - CPM1: 32bit register split in 2*16bit (16bit TDM)
52 * - QE: 4x16bit registers, one per TDM
140 struct clk *l1rclk_clk;
141 struct clk *l1rsync_clk;
142 struct clk *l1tclk_clk;
143 struct clk *l1tsync_clk;
182 /* The serials table is indexed by the serial id */ in tsa_serial_get_tsa()
183 return container_of(tsa_serial, struct tsa, serials[tsa_serial->id]); in tsa_serial_get_tsa()
229 return tsa->version == TSA_QE; in tsa_is_qe()
238 switch (tsa_serial->id) { in tsa_qe_serial_get_num()
248 dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id); in tsa_qe_serial_get_num()
249 return -EINVAL; in tsa_qe_serial_get_num()
257 * There is no need to get the serial num out of the TSA driver in the in tsa_serial_get_num()
259 * Further more, in CPM, we can have 2 types of serial SCCs and FCCs. in tsa_serial_get_num()
263 return tsa_is_qe(tsa) ? tsa_qe_serial_get_num(tsa_serial) : -EOPNOTSUPP; in tsa_serial_get_num()
274 switch (tsa_serial->id) { in tsa_cpm1_serial_connect()
288 dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id); in tsa_cpm1_serial_connect()
289 return -EINVAL; in tsa_cpm1_serial_connect()
292 spin_lock_irqsave(&tsa->lock, flags); in tsa_cpm1_serial_connect()
293 tsa_clrsetbits32(tsa->si_regs + TSA_CPM1_SICR, clear, in tsa_cpm1_serial_connect()
295 spin_unlock_irqrestore(&tsa->lock, flags); in tsa_cpm1_serial_connect()
311 spin_lock_irqsave(&tsa->lock, flags); in tsa_qe_serial_connect()
313 spin_unlock_irqrestore(&tsa->lock, flags); in tsa_qe_serial_connect()
315 dev_err(tsa->dev, "Connect serial id %u to TSA failed (%d)\n", in tsa_qe_serial_connect()
316 tsa_serial->id, ret); in tsa_qe_serial_connect()
344 memcpy(info, &tsa_serial->info, sizeof(*info)); in tsa_serial_get_info()
355 quarter = tsa->si_ram_sz / 4; in tsa_cpm1_init_entries_area()
356 half = tsa->si_ram_sz / 2; in tsa_cpm1_init_entries_area()
362 area->entries_start = tsa->si_ram; in tsa_cpm1_init_entries_area()
363 area->entries_next = area->entries_start + half; in tsa_cpm1_init_entries_area()
364 area->last_entry = NULL; in tsa_cpm1_init_entries_area()
367 area->entries_start = tsa->si_ram + half; in tsa_cpm1_init_entries_area()
368 area->entries_next = area->entries_start + half; in tsa_cpm1_init_entries_area()
369 area->last_entry = NULL; in tsa_cpm1_init_entries_area()
376 area->entries_start = tsa->si_ram; in tsa_cpm1_init_entries_area()
377 area->entries_next = area->entries_start + quarter; in tsa_cpm1_init_entries_area()
378 area->last_entry = NULL; in tsa_cpm1_init_entries_area()
381 area->entries_start = tsa->si_ram + (2 * quarter); in tsa_cpm1_init_entries_area()
382 area->entries_next = area->entries_start + quarter; in tsa_cpm1_init_entries_area()
383 area->last_entry = NULL; in tsa_cpm1_init_entries_area()
388 area->entries_start = tsa->si_ram + quarter; in tsa_cpm1_init_entries_area()
389 area->entries_next = area->entries_start + quarter; in tsa_cpm1_init_entries_area()
390 area->last_entry = NULL; in tsa_cpm1_init_entries_area()
393 area->entries_start = tsa->si_ram + (3 * quarter); in tsa_cpm1_init_entries_area()
394 area->entries_next = area->entries_start + quarter; in tsa_cpm1_init_entries_area()
395 area->last_entry = NULL; in tsa_cpm1_init_entries_area()
407 eighth = tsa->si_ram_sz / 8; in tsa_qe_init_entries_area()
408 half = tsa->si_ram_sz / 2; in tsa_qe_init_entries_area()
416 area->entries_start = tsa->si_ram + half + (eighth * tdm_id); in tsa_qe_init_entries_area()
417 area->entries_next = area->entries_start + eighth; in tsa_qe_init_entries_area()
418 area->last_entry = NULL; in tsa_qe_init_entries_area()
421 area->entries_start = tsa->si_ram + (eighth * tdm_id); in tsa_qe_init_entries_area()
422 area->entries_next = area->entries_start + eighth; in tsa_qe_init_entries_area()
423 area->last_entry = NULL; in tsa_qe_init_entries_area()
496 addr = area->last_entry ? area->last_entry + 4 : area->entries_start; in tsa_cpm1_add_entry()
499 if ((addr + (nb * 4)) > area->entries_next) { in tsa_cpm1_add_entry()
500 dev_err(tsa->dev, "si ram area full\n"); in tsa_cpm1_add_entry()
501 return -ENOSPC; in tsa_cpm1_add_entry()
504 if (area->last_entry) { in tsa_cpm1_add_entry()
506 tsa_clrbits32(area->last_entry, TSA_CPM1_SIRAM_ENTRY_LAST); in tsa_cpm1_add_entry()
518 area->last_entry = addr; in tsa_cpm1_add_entry()
520 val |= TSA_CPM1_SIRAM_ENTRY_CNT(cnt - 1); in tsa_cpm1_add_entry()
524 left -= cnt; in tsa_cpm1_add_entry()
553 addr = area->last_entry ? area->last_entry + 2 : area->entries_start; in tsa_qe_add_entry()
556 if ((addr + (nb * 2)) > area->entries_next) { in tsa_qe_add_entry()
557 dev_err(tsa->dev, "si ram area full\n"); in tsa_qe_add_entry()
558 return -ENOSPC; in tsa_qe_add_entry()
561 if (area->last_entry) { in tsa_qe_add_entry()
563 tsa_clrbits16(area->last_entry, TSA_QE_SIRAM_ENTRY_LAST); in tsa_qe_add_entry()
575 area->last_entry = addr; in tsa_qe_add_entry()
577 val |= TSA_QE_SIRAM_ENTRY_CNT(cnt - 1); in tsa_qe_add_entry()
581 left -= cnt; in tsa_qe_add_entry()
609 route_name = is_rx ? "fsl,rx-ts-routes" : "fsl,tx-ts-routes"; in tsa_of_parse_tdm_route()
613 dev_err(tsa->dev, "%pOF: failed to read %s\n", tdm_np, route_name); in tsa_of_parse_tdm_route()
617 dev_err(tsa->dev, "%pOF: wrong %s format\n", tdm_np, route_name); in tsa_of_parse_tdm_route()
618 return -EINVAL; in tsa_of_parse_tdm_route()
627 if (serial_id >= ARRAY_SIZE(tsa->serials)) { in tsa_of_parse_tdm_route()
628 dev_err(tsa->dev, "%pOF: invalid serial id (%u)\n", in tsa_of_parse_tdm_route()
630 return -EINVAL; in tsa_of_parse_tdm_route()
635 dev_err(tsa->dev, "%pOF: unsupported serial id (%u)\n", in tsa_of_parse_tdm_route()
637 return -EINVAL; in tsa_of_parse_tdm_route()
640 dev_dbg(tsa->dev, "tdm_id=%u, %s ts %u..%u -> %s\n", in tsa_of_parse_tdm_route()
641 tdm_id, route_name, ts, ts + count - 1, serial_name); in tsa_of_parse_tdm_route()
648 serial_info = &tsa->serials[serial_id].info; in tsa_of_parse_tdm_route()
649 tdm = &tsa->tdm[tdm_id]; in tsa_of_parse_tdm_route()
651 serial_info->rx_fs_rate = clk_get_rate(tdm->l1rsync_clk); in tsa_of_parse_tdm_route()
652 serial_info->rx_bit_rate = clk_get_rate(tdm->l1rclk_clk); in tsa_of_parse_tdm_route()
653 serial_info->nb_rx_ts += count; in tsa_of_parse_tdm_route()
655 serial_info->tx_fs_rate = tdm->l1tsync_clk ? in tsa_of_parse_tdm_route()
656 clk_get_rate(tdm->l1tsync_clk) : in tsa_of_parse_tdm_route()
657 clk_get_rate(tdm->l1rsync_clk); in tsa_of_parse_tdm_route()
658 serial_info->tx_bit_rate = tdm->l1tclk_clk ? in tsa_of_parse_tdm_route()
659 clk_get_rate(tdm->l1tclk_clk) : in tsa_of_parse_tdm_route()
660 clk_get_rate(tdm->l1rclk_clk); in tsa_of_parse_tdm_route()
661 serial_info->nb_tx_ts += count; in tsa_of_parse_tdm_route()
684 struct clk *clk; in tsa_of_parse_tdms() local
689 tsa->tdms = 0; in tsa_of_parse_tdms()
690 for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) in tsa_of_parse_tdms()
691 tsa->tdm[i].is_enable = false; in tsa_of_parse_tdms()
696 dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); in tsa_of_parse_tdms()
701 tsa->tdms |= BIT(TSA_TDMA); in tsa_of_parse_tdms()
704 tsa->tdms |= BIT(TSA_TDMB); in tsa_of_parse_tdms()
709 tsa->tdms |= BIT(TSA_TDMC); in tsa_of_parse_tdms()
714 tsa->tdms |= BIT(TSA_TDMD); in tsa_of_parse_tdms()
718 dev_err(tsa->dev, "%pOF: Invalid tdm_id (%u)\n", tdm_np, in tsa_of_parse_tdms()
720 return -EINVAL; in tsa_of_parse_tdms()
727 dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np); in tsa_of_parse_tdms()
731 tdm = &tsa->tdm[tdm_id]; in tsa_of_parse_tdms()
732 tdm->simode_tdm = TSA_SIMODE_TDM_SDM_NORM; in tsa_of_parse_tdms()
735 ret = of_property_read_u32(tdm_np, "fsl,rx-frame-sync-delay-bits", in tsa_of_parse_tdms()
737 if (ret && ret != -EINVAL) { in tsa_of_parse_tdms()
738 dev_err(tsa->dev, in tsa_of_parse_tdms()
739 "%pOF: failed to read fsl,rx-frame-sync-delay-bits\n", in tsa_of_parse_tdms()
744 dev_err(tsa->dev, in tsa_of_parse_tdms()
745 "%pOF: Invalid fsl,rx-frame-sync-delay-bits (%u)\n", in tsa_of_parse_tdms()
747 return -EINVAL; in tsa_of_parse_tdms()
749 tdm->simode_tdm |= TSA_SIMODE_TDM_RFSD(val); in tsa_of_parse_tdms()
752 ret = of_property_read_u32(tdm_np, "fsl,tx-frame-sync-delay-bits", in tsa_of_parse_tdms()
754 if (ret && ret != -EINVAL) { in tsa_of_parse_tdms()
755 dev_err(tsa->dev, in tsa_of_parse_tdms()
756 "%pOF: failed to read fsl,tx-frame-sync-delay-bits\n", in tsa_of_parse_tdms()
761 dev_err(tsa->dev, in tsa_of_parse_tdms()
762 "%pOF: Invalid fsl,tx-frame-sync-delay-bits (%u)\n", in tsa_of_parse_tdms()
764 return -EINVAL; in tsa_of_parse_tdms()
766 tdm->simode_tdm |= TSA_SIMODE_TDM_TFSD(val); in tsa_of_parse_tdms()
768 if (of_property_read_bool(tdm_np, "fsl,common-rxtx-pins")) in tsa_of_parse_tdms()
769 tdm->simode_tdm |= TSA_SIMODE_TDM_CRT; in tsa_of_parse_tdms()
771 if (of_property_read_bool(tdm_np, "fsl,clock-falling-edge")) in tsa_of_parse_tdms()
772 tdm->simode_tdm |= TSA_SIMODE_TDM_CE; in tsa_of_parse_tdms()
774 if (of_property_read_bool(tdm_np, "fsl,fsync-rising-edge")) in tsa_of_parse_tdms()
775 tdm->simode_tdm |= TSA_SIMODE_TDM_FE; in tsa_of_parse_tdms()
778 of_property_read_bool(tdm_np, "fsl,fsync-active-low")) in tsa_of_parse_tdms()
779 tdm->simode_tdm |= TSA_QE_SIMODE_TDM_SL; in tsa_of_parse_tdms()
781 if (of_property_read_bool(tdm_np, "fsl,double-speed-clock")) in tsa_of_parse_tdms()
782 tdm->simode_tdm |= TSA_SIMODE_TDM_DSC; in tsa_of_parse_tdms()
784 clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rsync" : "l1rsync"); in tsa_of_parse_tdms()
785 if (IS_ERR(clk)) { in tsa_of_parse_tdms()
786 ret = PTR_ERR(clk); in tsa_of_parse_tdms()
789 ret = clk_prepare_enable(clk); in tsa_of_parse_tdms()
791 clk_put(clk); in tsa_of_parse_tdms()
794 tdm->l1rsync_clk = clk; in tsa_of_parse_tdms()
796 clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rclk" : "l1rclk"); in tsa_of_parse_tdms()
797 if (IS_ERR(clk)) { in tsa_of_parse_tdms()
798 ret = PTR_ERR(clk); in tsa_of_parse_tdms()
801 ret = clk_prepare_enable(clk); in tsa_of_parse_tdms()
803 clk_put(clk); in tsa_of_parse_tdms()
806 tdm->l1rclk_clk = clk; in tsa_of_parse_tdms()
808 if (!(tdm->simode_tdm & TSA_SIMODE_TDM_CRT)) { in tsa_of_parse_tdms()
809 clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tsync" : "l1tsync"); in tsa_of_parse_tdms()
810 if (IS_ERR(clk)) { in tsa_of_parse_tdms()
811 ret = PTR_ERR(clk); in tsa_of_parse_tdms()
814 ret = clk_prepare_enable(clk); in tsa_of_parse_tdms()
816 clk_put(clk); in tsa_of_parse_tdms()
819 tdm->l1tsync_clk = clk; in tsa_of_parse_tdms()
821 clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tclk" : "l1tclk"); in tsa_of_parse_tdms()
822 if (IS_ERR(clk)) { in tsa_of_parse_tdms()
823 ret = PTR_ERR(clk); in tsa_of_parse_tdms()
826 ret = clk_prepare_enable(clk); in tsa_of_parse_tdms()
828 clk_put(clk); in tsa_of_parse_tdms()
831 tdm->l1tclk_clk = clk; in tsa_of_parse_tdms()
839 * We assign entries equally -> 128 Rx/Tx entries per in tsa_of_parse_tdms()
842 tdm->simode_tdm |= TSA_QE_SIMODE_TDM_SAD(4 * tdm_id); in tsa_of_parse_tdms()
845 ret = tsa_of_parse_tdm_rx_route(tsa, tdm_np, tsa->tdms, tdm_id); in tsa_of_parse_tdms()
849 ret = tsa_of_parse_tdm_tx_route(tsa, tdm_np, tsa->tdms, tdm_id); in tsa_of_parse_tdms()
853 tdm->is_enable = true; in tsa_of_parse_tdms()
858 for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) { in tsa_of_parse_tdms()
859 if (tsa->tdm[i].l1rsync_clk) { in tsa_of_parse_tdms()
860 clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); in tsa_of_parse_tdms()
861 clk_put(tsa->tdm[i].l1rsync_clk); in tsa_of_parse_tdms()
863 if (tsa->tdm[i].l1rclk_clk) { in tsa_of_parse_tdms()
864 clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); in tsa_of_parse_tdms()
865 clk_put(tsa->tdm[i].l1rclk_clk); in tsa_of_parse_tdms()
867 if (tsa->tdm[i].l1tsync_clk) { in tsa_of_parse_tdms()
868 clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); in tsa_of_parse_tdms()
869 clk_put(tsa->tdm[i].l1rsync_clk); in tsa_of_parse_tdms()
871 if (tsa->tdm[i].l1tclk_clk) { in tsa_of_parse_tdms()
872 clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); in tsa_of_parse_tdms()
873 clk_put(tsa->tdm[i].l1rclk_clk); in tsa_of_parse_tdms()
885 for (i = 0; i < tsa->si_ram_sz; i += 2) in tsa_init_si_ram()
886 tsa_write16(tsa->si_ram + i, TSA_QE_SIRAM_ENTRY_LAST); in tsa_init_si_ram()
888 for (i = 0; i < tsa->si_ram_sz; i += 4) in tsa_init_si_ram()
889 tsa_write32(tsa->si_ram + i, TSA_CPM1_SIRAM_ENTRY_LAST); in tsa_init_si_ram()
899 if (tsa->tdm[0].is_enable) in tsa_cpm1_setup()
900 val |= TSA_CPM1_SIMODE_TDMA(tsa->tdm[0].simode_tdm); in tsa_cpm1_setup()
901 if (tsa->tdm[1].is_enable) in tsa_cpm1_setup()
902 val |= TSA_CPM1_SIMODE_TDMB(tsa->tdm[1].simode_tdm); in tsa_cpm1_setup()
904 tsa_clrsetbits32(tsa->si_regs + TSA_CPM1_SIMODE, in tsa_cpm1_setup()
910 val = (tsa->tdms == BIT(TSA_TDMA)) ? in tsa_cpm1_setup()
912 if (tsa->tdms & BIT(TSA_TDMA)) in tsa_cpm1_setup()
914 if (tsa->tdms & BIT(TSA_TDMB)) in tsa_cpm1_setup()
916 tsa_write8(tsa->si_regs + TSA_CPM1_SIGMR, val); in tsa_cpm1_setup()
927 for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) { in tsa_qe_setup()
928 if (!tsa->tdm[i].is_enable) in tsa_qe_setup()
949 return -EINVAL; in tsa_qe_setup()
953 tsa_write16(tsa->si_regs + sixmr, tsa->tdm[i].simode_tdm); in tsa_qe_setup()
957 tsa_write8(tsa->si_regs + TSA_QE_SIGLMRH, siglmrh); in tsa_qe_setup()
969 struct device_node *np = pdev->dev.of_node; in tsa_probe()
975 tsa = devm_kzalloc(&pdev->dev, sizeof(*tsa), GFP_KERNEL); in tsa_probe()
977 return -ENOMEM; in tsa_probe()
979 tsa->dev = &pdev->dev; in tsa_probe()
980 tsa->version = (enum tsa_version)(uintptr_t)of_device_get_match_data(&pdev->dev); in tsa_probe()
981 switch (tsa->version) { in tsa_probe()
983 dev_info(tsa->dev, "CPM1 version\n"); in tsa_probe()
986 dev_info(tsa->dev, "QE version\n"); in tsa_probe()
989 dev_err(tsa->dev, "Unknown version (%d)\n", tsa->version); in tsa_probe()
990 return -EINVAL; in tsa_probe()
993 for (i = 0; i < ARRAY_SIZE(tsa->serials); i++) in tsa_probe()
994 tsa->serials[i].id = i; in tsa_probe()
996 spin_lock_init(&tsa->lock); in tsa_probe()
998 tsa->si_regs = devm_platform_ioremap_resource_byname(pdev, "si_regs"); in tsa_probe()
999 if (IS_ERR(tsa->si_regs)) in tsa_probe()
1000 return PTR_ERR(tsa->si_regs); in tsa_probe()
1004 dev_err(tsa->dev, "si_ram resource missing\n"); in tsa_probe()
1005 return -EINVAL; in tsa_probe()
1007 tsa->si_ram_sz = resource_size(res); in tsa_probe()
1008 tsa->si_ram = devm_ioremap_resource(&pdev->dev, res); in tsa_probe()
1009 if (IS_ERR(tsa->si_ram)) in tsa_probe()
1010 return PTR_ERR(tsa->si_ram); in tsa_probe()
1032 for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) { in tsa_remove()
1033 if (tsa->tdm[i].l1rsync_clk) { in tsa_remove()
1034 clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); in tsa_remove()
1035 clk_put(tsa->tdm[i].l1rsync_clk); in tsa_remove()
1037 if (tsa->tdm[i].l1rclk_clk) { in tsa_remove()
1038 clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); in tsa_remove()
1039 clk_put(tsa->tdm[i].l1rclk_clk); in tsa_remove()
1041 if (tsa->tdm[i].l1tsync_clk) { in tsa_remove()
1042 clk_disable_unprepare(tsa->tdm[i].l1rsync_clk); in tsa_remove()
1043 clk_put(tsa->tdm[i].l1rsync_clk); in tsa_remove()
1045 if (tsa->tdm[i].l1tclk_clk) { in tsa_remove()
1046 clk_disable_unprepare(tsa->tdm[i].l1rclk_clk); in tsa_remove()
1047 clk_put(tsa->tdm[i].l1rclk_clk); in tsa_remove()
1054 { .compatible = "fsl,cpm1-tsa", .data = (void *)TSA_CPM1 },
1057 { .compatible = "fsl,qe-tsa", .data = (void *)TSA_QE },
1065 .name = "fsl-tsa",
1088 return ERR_PTR(-EINVAL); in tsa_serial_get_byphandle()
1094 return ERR_PTR(-ENODEV); in tsa_serial_get_byphandle()
1099 return ERR_PTR(-EPROBE_DEFER); in tsa_serial_get_byphandle()
1104 return ERR_PTR(-EINVAL); in tsa_serial_get_byphandle()
1107 if (out_args.args[0] >= ARRAY_SIZE(tsa->serials)) { in tsa_serial_get_byphandle()
1109 return ERR_PTR(-EINVAL); in tsa_serial_get_byphandle()
1112 tsa_serial = &tsa->serials[out_args.args[0]]; in tsa_serial_get_byphandle()
1115 * Be sure that the serial id matches the phandle arg. in tsa_serial_get_byphandle()
1116 * The tsa_serials table is indexed by serial ids. The serial id is set in tsa_serial_get_byphandle()
1119 if (WARN_ON(tsa_serial->id != out_args.args[0])) { in tsa_serial_get_byphandle()
1121 return ERR_PTR(-EINVAL); in tsa_serial_get_byphandle()
1132 put_device(tsa->dev); in tsa_serial_put()
1152 return ERR_PTR(-ENOMEM); in devm_tsa_serial_get_byphandle()