// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2015 Freescale Semiconductor, Inc. All rights reserved.
 *
 * Authors:	Zhao Qiang <qiang.zhao@nxp.com>
 *
 * Description:
 * QE TDM API Set - TDM specific routines implementations.
 */
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <soc/fsl/qe/qe_tdm.h>

static int set_tdm_framer(const char *tdm_framer_type)
{
	if (strcmp(tdm_framer_type, "e1") == 0)
		return TDM_FRAMER_E1;
	else if (strcmp(tdm_framer_type, "t1") == 0)
		return TDM_FRAMER_T1;
	else
		return -EINVAL;
}

static void set_si_param(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info)
{
	struct si_mode_info *si_info = &ut_info->si_info;

	if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK) {
		si_info->simr_crt = 1;
		si_info->simr_rfsd = 0;
	}
}

int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
		     struct ucc_tdm_info *ut_info)
{
	const char *sprop;
	int ret = 0;
	u32 val;

	sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
	if (sprop) {
		ut_info->uf_info.rx_sync = qe_clock_source(sprop);
		if ((ut_info->uf_info.rx_sync < QE_CLK_NONE) ||
		    (ut_info->uf_info.rx_sync > QE_RSYNC_PIN)) {
			pr_err("QE-TDM: Invalid rx-sync-clock property\n");
			return -EINVAL;
		}
	} else {
		pr_err("QE-TDM: Invalid rx-sync-clock property\n");
		return -EINVAL;
	}

	sprop = of_get_property(np, "fsl,tx-sync-clock", NULL);
	if (sprop) {
		ut_info->uf_info.tx_sync = qe_clock_source(sprop);
		if ((ut_info->uf_info.tx_sync < QE_CLK_NONE) ||
		    (ut_info->uf_info.tx_sync > QE_TSYNC_PIN)) {
			pr_err("QE-TDM: Invalid tx-sync-clock property\n");
		return -EINVAL;
		}
	} else {
		pr_err("QE-TDM: Invalid tx-sync-clock property\n");
		return -EINVAL;
	}

	ret = of_property_read_u32_index(np, "fsl,tx-timeslot-mask", 0, &val);
	if (ret) {
		pr_err("QE-TDM: Invalid tx-timeslot-mask property\n");
		return -EINVAL;
	}
	utdm->tx_ts_mask = val;

	ret = of_property_read_u32_index(np, "fsl,rx-timeslot-mask", 0, &val);
	if (ret) {
		ret = -EINVAL;
		pr_err("QE-TDM: Invalid rx-timeslot-mask property\n");
		return ret;
	}
	utdm->rx_ts_mask = val;

	ret = of_property_read_u32_index(np, "fsl,tdm-id", 0, &val);
	if (ret) {
		ret = -EINVAL;
		pr_err("QE-TDM: No fsl,tdm-id property for this UCC\n");
		return ret;
	}
	utdm->tdm_port = val;
	ut_info->uf_info.tdm_num = utdm->tdm_port;

	if (of_property_read_bool(np, "fsl,tdm-internal-loopback"))
		utdm->tdm_mode = TDM_INTERNAL_LOOPBACK;
	else
		utdm->tdm_mode = TDM_NORMAL;

	sprop = of_get_property(np, "fsl,tdm-framer-type", NULL);
	if (!sprop) {
		ret = -EINVAL;
		pr_err("QE-TDM: No tdm-framer-type property for UCC\n");
		return ret;
	}
	ret = set_tdm_framer(sprop);
	if (ret < 0)
		return -EINVAL;
	utdm->tdm_framer_type = ret;

	ret = of_property_read_u32_index(np, "fsl,siram-entry-id", 0, &val);
	if (ret) {
		ret = -EINVAL;
		pr_err("QE-TDM: No siram entry id for UCC\n");
		return ret;
	}
	utdm->siram_entry_id = val;

	set_si_param(utdm, ut_info);
	return ret;
}
EXPORT_SYMBOL(ucc_of_parse_tdm);

void ucc_tdm_init(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info)
{
	struct si1 __iomem *si_regs;
	u16 __iomem *siram;
	u16 siram_entry_valid;
	u16 siram_entry_closed;
	u16 ucc_num;
	u8 csel;
	u16 sixmr;
	u16 tdm_port;
	u32 siram_entry_id;
	u32 mask;
	int i;

	si_regs = utdm->si_regs;
	siram = utdm->siram;
	ucc_num = ut_info->uf_info.ucc_num;
	tdm_port = utdm->tdm_port;
	siram_entry_id = utdm->siram_entry_id;

	if (utdm->tdm_framer_type == TDM_FRAMER_T1)
		utdm->num_of_ts = 24;
	if (utdm->tdm_framer_type == TDM_FRAMER_E1)
		utdm->num_of_ts = 32;

	/* set siram table */
	csel = (ucc_num < 4) ? ucc_num + 9 : ucc_num - 3;

	siram_entry_valid = SIR_CSEL(csel) | SIR_BYTE | SIR_CNT(0);
	siram_entry_closed = SIR_IDLE | SIR_BYTE | SIR_CNT(0);

	for (i = 0; i < utdm->num_of_ts; i++) {
		mask = 0x01 << i;

		if (utdm->tx_ts_mask & mask)
			iowrite16be(siram_entry_valid,
				    &siram[siram_entry_id * 32 + i]);
		else
			iowrite16be(siram_entry_closed,
				    &siram[siram_entry_id * 32 + i]);

		if (utdm->rx_ts_mask & mask)
			iowrite16be(siram_entry_valid,
				    &siram[siram_entry_id * 32 + 0x200 +  i]);
		else
			iowrite16be(siram_entry_closed,
				    &siram[siram_entry_id * 32 + 0x200 +  i]);
	}

	qe_setbits_be16(&siram[(siram_entry_id * 32) + (utdm->num_of_ts - 1)],
			SIR_LAST);
	qe_setbits_be16(&siram[(siram_entry_id * 32) + 0x200 + (utdm->num_of_ts - 1)],
			SIR_LAST);

	/* Set SIxMR register */
	sixmr = SIMR_SAD(siram_entry_id);

	sixmr &= ~SIMR_SDM_MASK;

	if (utdm->tdm_mode == TDM_INTERNAL_LOOPBACK)
		sixmr |= SIMR_SDM_INTERNAL_LOOPBACK;
	else
		sixmr |= SIMR_SDM_NORMAL;

	sixmr |= SIMR_RFSD(ut_info->si_info.simr_rfsd) |
			SIMR_TFSD(ut_info->si_info.simr_tfsd);

	if (ut_info->si_info.simr_crt)
		sixmr |= SIMR_CRT;
	if (ut_info->si_info.simr_sl)
		sixmr |= SIMR_SL;
	if (ut_info->si_info.simr_ce)
		sixmr |= SIMR_CE;
	if (ut_info->si_info.simr_fe)
		sixmr |= SIMR_FE;
	if (ut_info->si_info.simr_gm)
		sixmr |= SIMR_GM;

	switch (tdm_port) {
	case 0:
		iowrite16be(sixmr, &si_regs->sixmr1[0]);
		break;
	case 1:
		iowrite16be(sixmr, &si_regs->sixmr1[1]);
		break;
	case 2:
		iowrite16be(sixmr, &si_regs->sixmr1[2]);
		break;
	case 3:
		iowrite16be(sixmr, &si_regs->sixmr1[3]);
		break;
	default:
		pr_err("QE-TDM: can not find tdm sixmr reg\n");
		break;
	}
}
EXPORT_SYMBOL(ucc_tdm_init);
