summaryrefslogtreecommitdiff
path: root/drivers/tdm
diff options
context:
space:
mode:
authorSandeep Singh <Sandeep@freescale.com>2012-04-24 20:34:33 (GMT)
committerEmil Medve <Emilian.Medve@Freescale.com>2013-03-21 18:42:14 (GMT)
commit4abef5f73cb937f302b4f895845c8d9e28a7670d (patch)
treef205671497bdd04d006d20b2901fd0dc29a4da82 /drivers/tdm
parent5874ab40c5d7443554f339d8c9e6cce22f664283 (diff)
downloadlinux-fsl-qoriq-4abef5f73cb937f302b4f895845c8d9e28a7670d.tar.xz
Basic configuration module for Le88266 Zarlink SLIC
- Basic driver which does minimum intialization of the Le88266 SLIC device. - The code was originally borrowed from Zarlink driver implementation. - It is not full fledged SLIC driver code, it just does basic initialization which is required to setup a voice data path between channels. This is just enough to test and demonstrate TDM functionality on Freescale platforms using TDM Test Module. - For full fledged VoIP type of use case proper SLIC driver will be required which handles all the functionalities of the device. - Going forward this driver will be replaced by Opoen source Zarlink APIs. Signed-off-by: Sandeep Singh <Sandeep@freescale.com> Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com> (cherry picked from commit abd929c8081a0e474291d79adf837aaa3a61e6ca)
Diffstat (limited to 'drivers/tdm')
-rw-r--r--drivers/tdm/Kconfig1
-rw-r--r--drivers/tdm/Makefile2
-rw-r--r--drivers/tdm/line_ctrl/Kconfig12
-rw-r--r--drivers/tdm/line_ctrl/Makefile5
-rw-r--r--drivers/tdm/line_ctrl/slic_zarlink.c679
-rw-r--r--drivers/tdm/line_ctrl/slic_zarlink.h131
6 files changed, 829 insertions, 1 deletions
diff --git a/drivers/tdm/Kconfig b/drivers/tdm/Kconfig
index 120af1a..25fed1c 100644
--- a/drivers/tdm/Kconfig
+++ b/drivers/tdm/Kconfig
@@ -31,4 +31,5 @@ config TDM_TEST
a TDM Voice path between diff channels of a slic.
source drivers/tdm/device/Kconfig
+source drivers/tdm/line_ctrl/Kconfig
endif # TDM
diff --git a/drivers/tdm/Makefile b/drivers/tdm/Makefile
index d73fbbd..ea66fff 100644
--- a/drivers/tdm/Makefile
+++ b/drivers/tdm/Makefile
@@ -2,7 +2,7 @@
# Makefile for the TDM core.
#
-obj-$(CONFIG_TDM) += tdm-core.o device/
+obj-$(CONFIG_TDM) += tdm-core.o device/ line_ctrl/
obj-$(CONFIG_TDM_TEST) += test/
ifeq ($(CONFIG_TDM_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/tdm/line_ctrl/Kconfig b/drivers/tdm/line_ctrl/Kconfig
new file mode 100644
index 0000000..e7421b9
--- /dev/null
+++ b/drivers/tdm/line_ctrl/Kconfig
@@ -0,0 +1,12 @@
+#
+# TDM line control driver config file
+#
+
+menu "Line Control Devices"
+
+config SLIC_ZARLINK
+ tristate "Zarlink Slic intialization Module"
+ default n
+ ---help---
+ This module initialize and configure the zarlink slic
+endmenu
diff --git a/drivers/tdm/line_ctrl/Makefile b/drivers/tdm/line_ctrl/Makefile
new file mode 100644
index 0000000..91e8916
--- /dev/null
+++ b/drivers/tdm/line_ctrl/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the TDM line control drivers.
+#
+
+obj-y += slic_zarlink.o
diff --git a/drivers/tdm/line_ctrl/slic_zarlink.c b/drivers/tdm/line_ctrl/slic_zarlink.c
new file mode 100644
index 0000000..6aa562c0
--- /dev/null
+++ b/drivers/tdm/line_ctrl/slic_zarlink.c
@@ -0,0 +1,679 @@
+/*
+ * drivers/tdm/line_ctrl/slic_zarlink.c
+ *
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * SLIC Line Control Module for Zarlink SLICs.
+ * This is a slic control and initialization module.
+ *
+ * Author:Poonam Aggrwal<poonam.aggrwal@freescale.com>
+ * Hemant Agrawal <hemant@freescale.com>
+ * Rajesh Gumasta <rajesh.gumasta@freescale.com>
+ *
+ * Modified by Sandeep Kr Singh <sandeep@freescale.com>
+ * 1. Changed SPI cmnds to restrict transaction length to 1 byte.
+ * 2. Updated probe which now does not relies on modalias.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This driver was created solely by Freescale, without the assistance,
+ * support or intellectual property of Zarlink Semiconductor. No maintenance
+ * or support will be provided by Zarlink Semiconductor regarding this driver
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ /* Note that this is a complete rewrite of Poonam's slic code.
+ But we have used so much of her original code and ideas that it seems
+ only fair to recognize her as co-author -- Rajesh & Hemant */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/spi/spi.h>
+#include <linux/wait.h>
+#include <linux/param.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include "slic_zarlink.h"
+
+#define DRV_DESC "FREESCALE DEVELOPED ZARLINK SLIC DRIVER"
+#define DRV_NAME "legerity"
+
+#define MAX_NUM_OF_SLICS 10
+#define SLIC_TRANS_LEN 1
+
+#define TESTING_PRODUCT_CODE
+
+static struct spi_device *g_spi;
+struct spi_transfer t;
+
+struct slic_channel {
+ unsigned int ch1_rx_slot, ch1_tx_slot, ch2_rx_slot, ch2_tx_slot;
+};
+struct slic_channel slic_ch[MAX_NUM_OF_SLICS];
+static int num_slics;
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Poonam Aggrwal<poonam.aggrwal@freescale.com>");
+MODULE_DESCRIPTION(DRV_DESC);
+
+static void
+slic_cmd(struct spi_device *spi, unsigned char channel, unsigned char cmd,
+ unsigned char len, unsigned char *cmdData)
+{
+ unsigned char ecCmd = WRITE_CHANNEL_ENABLE;
+ unsigned char cmdLen;
+
+ /* Write EC command */
+ spi_write(spi, &ecCmd, SLIC_TRANS_LEN);
+
+ /* write EC value */
+ spi_write(spi, &channel, SLIC_TRANS_LEN);
+
+ /* write command */
+ spi_write(spi, &cmd, SLIC_TRANS_LEN);
+
+ /* If read command or write command */
+ if (cmd & 0x01) {
+ for (cmdLen = 0; cmdLen < len; cmdLen++)
+ spi_read(spi, &cmdData[cmdLen], SLIC_TRANS_LEN);
+ }
+ else {
+ for (cmdLen = 0; cmdLen < len; cmdLen++)
+ spi_write(spi, &cmdData[cmdLen], SLIC_TRANS_LEN);
+ }
+}
+
+static void get_slic_product_code(struct spi_device *spi)
+{
+ u8 tx = READ_PRODUCT_CODE;
+ u8 rx = 0x00;
+
+ spi_write(spi, &tx, SLIC_TRANS_LEN);
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: product code 1 read is %x\n", rx);
+
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: product code 2 read is %x\n", rx);
+
+ tx = WRITE_CHANNEL_ENABLE;
+ spi_write(spi, &tx, SLIC_TRANS_LEN);
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: config read is %x\n", rx);
+
+ tx = READ_DEVICE_CONFIGURATION;
+ spi_write(spi, &tx, SLIC_TRANS_LEN);
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: config read is %x\n", rx);
+
+ return;
+}
+
+static int slic_init_configure(unsigned char *device_handle,
+ struct spi_device *spi, int slic_id)
+{
+ char temp1 = 0;
+ char temp2[2];
+ char temp3[3];
+ unsigned char cad[4];
+ unsigned char len;
+ unsigned char channel_id;
+
+ temp3[0] = 0x04;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, HW_RESET, len, &temp3[0]);
+
+#ifdef TESTING_PRODUCT_CODE
+ get_slic_product_code(spi);
+#endif
+ temp3[0] = 0x82;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_DEVICE_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x7f;
+ temp3[1] = 0xff;
+ len = 0x02;
+ slic_cmd(spi, CHANNEL1, WRITE_INT_MASK, len, &temp3[0]);
+
+ temp3[0] = 0xff;
+ temp3[1] = 0xff;
+ len = 0x02;
+ slic_cmd(spi, CHANNEL1, WRITE_INT_MASK, len, &temp3[0]);
+
+ temp3[0] = 0x40;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_TXRXCLKSLOT_TXCLKEDGE, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ /* Put the Switching regulators in disabled mode */
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE_CFG, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_SYSTEM_STATE_CFG, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x2b;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x80;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_OPERATING_FUNCTION, len,
+ &temp3[0]);
+
+ temp3[0] = 0xe0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_OPERATING_CONDITIONS, len,
+ &temp3[0]);
+
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ /* Set Switching Paramenters as for Le88266
+ * 1. BSI[1:0] = 00b (sense pin VBL is SWVSY, VBH is SWVSZ)
+ * 2. SWFS[1:0] = 00b (setting frequency as 384kHz in high power mode)
+ * 3. SWYV[4:0] = 00101b (setting to -25V)
+ * 4. SWZV[4:0] = 00000b (setting to 0V)
+ */
+ temp3[0] = 0x00;
+ temp3[1] = 0x05;
+ temp3[2] = 0x00;
+ len = 0x03;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_PARAMS, len,
+ &temp3[0]);
+
+ /* Put the Switching regulators in
+ * 1. Regulator Y & Z in low power state
+ * 2. Over voltage protection enabled
+ */
+ temp3[0] = 0x15;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ /* Wait 20ms before switching from low power to high power */
+ mdelay(20);
+
+ temp3[0] = 0x9;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0xb;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0xb;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x2;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x2;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ /* Set Switching Paramenters as for Le88266
+ * 1. BSI[1:0] = 00b (sense pin VBL is SWVSY, VBH is SWVSZ)
+ * 2. SWFS[1:0] = 00b (setting frequency as 384kHz in high power mode)
+ * 3. SWYV[4:0] = 00101b (setting to -25V)
+ * 4. SWZV[4:0] = 00000b (setting to 0V)
+ */
+ temp3[0] = 0x00;
+ temp3[1] = 0x05;
+ temp3[2] = 0x00;
+ len = 0x03;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_PARAMS, len,
+ &temp3[0]);
+
+ /* Put the Switching regulators in
+ * 1. Regulator Y & Z in high power state
+ * 2. Over voltage protection enabled
+ */
+ temp3[0] = 0x1f;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ /* Setting the channel specific parameters */
+ for (channel_id = CHANNEL1; channel_id <= CHANNEL2; channel_id++) {
+
+ /* Set the IO direction to Output - to energise the fxo
+ * relay */
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_IO_DIRECTION, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_IO_DATA, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ len = sizeof(dataset_cadenceTimer) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_CADENCE_TIMER, len,
+ &dataset_cadenceTimer[0]);
+
+ temp3[0] = 0x2;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ temp3[1] = 0x2;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_DC_CALIBRATION, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE, len,
+ &temp3[0]);
+
+ len = sizeof(dataset_writeLoopParams) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id,
+ WRITE_LOOP_SUPERVISION_PARAMS, len,
+ &dataset_writeLoopParams[0]);
+
+ temp3[0] = 0x13;
+ temp3[1] = 0x8;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_DC_FEED_PARAMS, len,
+ &temp3[0]);
+
+ len = sizeof(dataset1_for_nooperation) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_NO_OPERATION, len,
+ &dataset1_for_nooperation[0]);
+
+ temp3[0] = 0x3f;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_FUNCTION,
+ len, &temp3[0]);
+
+ len = sizeof(dataset2_for_nooperation) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_NO_OPERATION, len,
+ &dataset2_for_nooperation[0]);
+
+ temp3[0] = 0x2;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ len = sizeof(dataset_internalCfgReg3) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_INTERNAL_CFG_REG3 ,
+ len, &dataset_internalCfgReg3[0]);
+
+ len = sizeof(dataset3_for_nooperation) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_NO_OPERATION, len,
+ &dataset3_for_nooperation[0]);
+
+ temp3[0] = 0xbf;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_FUNCTION,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x6;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0x6;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x16;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x16;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0x3f;
+ if (channel_id == CHANNEL1)
+ temp3[1] = 0xff;
+ else
+ temp3[1] = 0xbf;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_INT_MASK, len,
+ &temp3[0]);
+
+ temp3[0] = 0x16;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ temp3[1] = 0x2;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_DC_CALIBRATION, len,
+ &temp3[0]);
+
+ temp3[0] = 0x2b;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE, len,
+ &temp3[0]);
+
+ }
+ /* Reading the Device Configuration register */
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_DEVICE_CONFIGURATION, len,
+ &temp1);
+ printk(KERN_INFO "DEV reg is %x\n", temp1);
+
+ /* Enabling interrupt by writing into Device Configuration Register */
+ temp1 &= 0x7F;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_DEVICE_CFG, len, &temp1);
+
+ /* Reading the Device Configuration register */
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_DEVICE_CONFIGURATION, len,
+ &temp1);
+ printk(KERN_INFO "DEV reg after is %x\n", temp1);
+
+ /* Reading the Mask register */
+ len = 0x2;
+ slic_cmd(spi, CHANNEL1, READ_INT_MASK, len, &temp2[0]);
+ printk(KERN_INFO "Mask reg before setting is %x %x\n",
+ temp2[0], temp2[1]);
+
+ /* Writing into the mask register */
+ temp2[0] = 0xF6;
+ temp2[1] = 0xF6;
+ len = 0x2;
+ slic_cmd(spi, CHANNEL1, WRITE_INT_MASK, len, &temp2[0]);
+
+ /* Reading the Mask register */
+ len = 0x2;
+ slic_cmd(spi, CHANNEL1, READ_INT_MASK, len, &temp2[0]);
+ printk(KERN_INFO "Mask reg after setting is %x %x\n",
+ temp2[0], temp2[1]);
+
+ temp1 = slic_ch[slic_id].ch1_tx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, WRITE_TX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_TX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Tx Timeslot for CH1 is %x\n", temp1);
+
+ temp1 = slic_ch[slic_id].ch2_tx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, WRITE_TX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, READ_TX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Tx Timeslot for CH2 is %x\n", temp1);
+
+ temp1 = slic_ch[slic_id].ch1_rx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, WRITE_RX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_RX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Rx Timeslot for CH1 is %x\n", temp1);
+
+ temp1 = slic_ch[slic_id].ch2_rx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, WRITE_RX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, READ_RX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Rx Timeslot for CH2 is %x\n", temp1);
+
+ for (channel_id = CHANNEL1; channel_id <= CHANNEL2; channel_id++) {
+
+ temp1 &= 0xBF;
+ temp1 |= 0x80;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_FUNCTION,
+ len, &temp1);
+
+ len = 0x01;
+ slic_cmd(spi, channel_id, READ_OPERATING_FUNCTION,
+ len, &temp1);
+ printk(KERN_INFO "Operating Fun for channel %d is %x\n",
+ channel_id, temp1);
+
+ /* Install Timers */
+ len = 0x04;
+ slic_cmd(spi, channel_id, READ_CADENCE_TIMER, len,
+ &cad[0]);
+ printk(KERN_INFO "Cadence Timer Reg for CH%d before is %x %x"
+ "%x %x\n", channel_id, cad[0], cad[1], cad[2],
+ cad[3]);
+
+ len = sizeof(set_cadenceTimer) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_CADENCE_TIMER, len,
+ &set_cadenceTimer[0]);
+
+ len = 0x04;
+ slic_cmd(spi, channel_id, READ_CADENCE_TIMER , len,
+ &cad[0]);
+ printk(KERN_INFO "Cadence Timer Reg for CH%d after is %x %x"
+ "%x %x\n", channel_id, cad[0], cad[1], cad[2],
+ cad[3]);
+ temp1 = 0x20;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp1);
+
+ slic_cmd(spi, channel_id, READ_SYSTEM_STATE_CFG,
+ len, &temp1);
+ printk(KERN_INFO "Switching control for channel %d is %x\n",
+ channel_id, temp1);
+ }
+ return 0;
+}
+
+void configure_spi_pdata(struct spi_device *spi)
+{
+ struct slic_platform_data *spi_slic_pdata;
+ const u32 *iprop;
+ struct device_node *np = spi->dev.of_node;
+ static int num_slic;
+
+ spi_slic_pdata = kzalloc(sizeof(*spi_slic_pdata), GFP_KERNEL);
+ if (spi_slic_pdata == NULL)
+ return;
+
+ spi->dev.platform_data = spi_slic_pdata;
+
+ spi_slic_pdata->ch1_rx_slot = CH1_RX_SLOT_NUM + num_slic;
+ spi_slic_pdata->ch1_tx_slot = CH1_TX_SLOT_NUM + num_slic;
+ spi_slic_pdata->ch2_rx_slot = CH2_RX_SLOT_NUM + num_slic;
+ spi_slic_pdata->ch2_tx_slot = CH2_TX_SLOT_NUM + num_slic;
+ pr_info("SLIC config success\n");
+ num_slic = num_slic + SLIC_SLOT_OFFSET;
+
+}
+static int slic_remove(struct spi_device *spi)
+{
+
+ printk(KERN_INFO "SLIC module uninstalled\n");
+ return 0;
+}
+
+static int slic_probe(struct spi_device *spi)
+{
+ int ret = 0;
+ unsigned char *device_handle;
+ struct slic_platform_data *data;
+
+ printk(KERN_INFO "SLIC probed!\n");
+
+ g_spi = spi;
+ spi->bits_per_word = 8;
+
+ if (num_slics >= MAX_NUM_OF_SLICS) {
+ printk(KERN_ERR "Exceeded the max number of slics\n");
+ return ret;
+ }
+
+ /* Initialize the SLIC */
+ configure_spi_pdata(spi);
+ data = spi->dev.platform_data;
+ slic_ch[num_slics].ch1_tx_slot = data->ch1_tx_slot;
+ slic_ch[num_slics].ch1_rx_slot = data->ch1_rx_slot;
+ slic_ch[num_slics].ch2_tx_slot = data->ch2_tx_slot;
+ slic_ch[num_slics].ch2_rx_slot = data->ch2_rx_slot;
+
+ device_handle = 0x0;
+ ret = slic_init_configure(device_handle, spi, num_slics);
+ if (ret == 0) {
+ num_slics++;
+ printk(KERN_INFO "SLIC %d configuration success\n",
+ num_slics);
+ } else {
+ printk(KERN_ERR "%s slic configuration failed\n", __func__);
+ return ret;
+ }
+ return ret;
+}
+
+static const struct of_device_id slic_match[] = {
+ {
+ .compatible = "zarlink,le88266",
+ },
+ {},
+};
+
+static struct spi_driver slic_driver = {
+ .driver = {
+ .name = "legerity",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ .of_match_table = slic_match,
+ },
+ .probe = slic_probe,
+ .remove = slic_remove,
+
+};
+
+static int __init slic_init(void)
+{
+ int ret;
+ printk(KERN_INFO "SLIC: " DRV_DESC "\n");
+ printk(KERN_INFO "####################################################"
+ "\n# This driver was created solely by Freescale, #"
+ "\n# without the assistance, support or intellectual #"
+ "\n# property of Zarlink Semiconductor. No #"
+ "\n# maintenance or support will be provided by #"
+ "\n# Zarlink Semiconductor regarding this driver. #"
+ "\n####################################################"
+ "\n");
+
+ ret = spi_register_driver(&slic_driver);
+ if (ret != 0)
+ printk(KERN_ERR "%s spi_register_driver failed\n",
+ __func__);
+ return ret;
+}
+
+static void __exit slic_exit(void)
+{
+ spi_unregister_driver(&slic_driver);
+}
+
+module_init(slic_init);
+module_exit(slic_exit);
diff --git a/drivers/tdm/line_ctrl/slic_zarlink.h b/drivers/tdm/line_ctrl/slic_zarlink.h
new file mode 100644
index 0000000..1a44590
--- /dev/null
+++ b/drivers/tdm/line_ctrl/slic_zarlink.h
@@ -0,0 +1,131 @@
+/*
+ * drivers/tdm/line/slic_zarlink.h
+ *
+ * Copyright (C) 2009-2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This is the header file for the SLIC Driver Module
+ * drivers/tdm/line/slic_zarlink.c.
+ *
+ * Author: Rajesh Gumasta<rajesh.gumasta@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef SLIC_ZARLINK_H
+#define SLIC_ZARLINK_H
+
+struct slic_platform_data {
+ unsigned int ch1_rx_slot;
+ unsigned int ch1_tx_slot;
+ unsigned int ch2_rx_slot;
+ unsigned int ch2_tx_slot;
+};
+
+/* SLIC channel configuration */
+#define CH1_RX_SLOT_NUM 0
+#define CH1_TX_SLOT_NUM 0
+#define CH2_RX_SLOT_NUM 2
+#define CH2_TX_SLOT_NUM 2
+
+#define SLIC_SLOT_OFFSET 2
+
+/* commands to the SLIC */
+#define CHANNEL1 0x01
+#define CHANNEL2 0x02
+#define HW_RESET 0x04
+#define WRITE_NO_OPERATION 0x06
+#define WRITE_TX_TIME_SLOT 0x40
+#define READ_TX_TIME_SLOT 0x41
+#define WRITE_RX_TIME_SLOT 0x42
+#define READ_RX_TIME_SLOT 0x43
+#define WRITE_TXRXCLKSLOT_TXCLKEDGE 0x44
+#define WRITE_DEVICE_CFG 0x46
+#define READ_DEVICE_CONFIGURATION 0x47
+#define WRITE_CHANNEL_ENABLE 0X4A
+#define WRITE_IO_DATA 0x52
+#define WRITE_IO_DIRECTION 0x54
+#define WRITE_SYSTEM_STATE 0x56
+#define WRITE_OPERATING_FUNCTION 0x60
+#define READ_OPERATING_FUNCTION 0x61
+#define WRITE_SYSTEM_STATE_CFG 0x68
+#define READ_SYSTEM_STATE_CFG 0x69
+#define WRITE_INT_MASK 0x6C
+#define READ_INT_MASK 0x6D
+#define WRITE_OPERATING_CONDITIONS 0x70
+#define READ_PRODUCT_CODE 0X73
+#define WRITE_CONVERTER_CFG 0xA6
+#define WRITE_LOOP_SUPERVISION_PARAMS 0xC2
+#define WRITE_DC_FEED_PARAMS 0xC6
+#define WRITE_CADENCE_TIMER 0xE0
+#define READ_CADENCE_TIMER 0xE1
+#define WRITE_SWITCH_REGULATOR_PARAMS 0xE4
+#define WRITE_SWITCH_REGULATOR_CTRL 0xE6
+#define WRITE_INTERNAL_CFG_REG3 0xF2
+#define WRITE_DC_CALIBRATION 0xFC
+
+/* Dataset1 for no operation command */
+static unsigned char dataset1_for_nooperation[] = {
+ 0xca, 0xfa, 0x98, 0xca, 0xb9,
+ 0xa2, 0x4c, 0x2b, 0xa2, 0xa3,
+ 0xa2, 0xae, 0x2b, 0x9a, 0x23,
+ 0xca, 0x26, 0x9f, 0x1, 0x8a,
+ 0x1d, 0x1, 0x1, 0x11, 0x1,
+ 0x90, 0x1, 0x90, 0x1, 0x90,
+ 0x1, 0x90, 0x1, 0x90, 0x88,
+ 0xd8, 0x70, 0x7a, 0x87, 0x23,
+ 0x3f, 0x4a, 0x97, 0x5a, 0xa7,
+ 0x5a, 0xaf, 0x82, 0x22, 0xe0,
+ 0x80, 0x32, 0x10, 0x50, 0x10,
+ 0x86, 0xa2, 0x63, 0x23, 0xbb,
+ 0x2a, 0xa4, 0x29, 0x7d, 0x87,
+ 0x2a, 0xfa, 0x8f, 0x29, 0xf0,
+ 0x96, 0x2e, 0x1
+};
+
+/* Dataset2 for no operation command */
+static unsigned char dataset2_for_nooperation[] = {
+ 0xd2, 0x0, 0x0, 0x0, 0x0,
+ 0x36, 0x36, 0xb9, 0x0, 0x0,
+ 0x0, 0x0, 0x68, 0x0
+};
+
+/* Dataset3 for no operation command */
+static unsigned char dataset3_for_nooperation[] = {
+ 0xc2, 0x1b, 0x84, 0xb4, 0x5,
+ 0xc6, 0x8, 0x8
+};
+
+/* Dataset for internal configuration register 3 command */
+static unsigned char dataset_internalCfgReg3[] = {
+ 0x10, 0x1, 0x0, 0x0
+};
+
+/* Dataset for cadence timer command */
+static unsigned char dataset_cadenceTimer[] = {
+ 0x3f, 0xff, 0x0, 0x0
+};
+
+/* Dataset for Loop parameters command */
+static unsigned char dataset_writeLoopParams[] = {
+ 0x1b, 0x84, 0xb3, 0x5
+};
+
+/* Dataset1 for cadence timer command */
+static unsigned char set_cadenceTimer[] = {
+ 0x01, 0x90, 0x03, 0x20
+};
+
+#endif