From patchwork Tue Mar 5 12:41:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sandeep@freescale.com X-Patchwork-Id: 2219151 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id B678D3FCF6 for ; Tue, 5 Mar 2013 12:45:36 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UCrCk-0002uJ-KP; Tue, 05 Mar 2013 12:42:50 +0000 Received: from va3ehsobe002.messaging.microsoft.com ([216.32.180.12] helo=va3outboundpool.messaging.microsoft.com) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UCrCE-0002o5-Fg for linux-arm-kernel@lists.infradead.org; Tue, 05 Mar 2013 12:42:35 +0000 Received: from mail22-va3-R.bigfish.com (10.7.14.252) by VA3EHSOBE010.bigfish.com (10.7.40.12) with Microsoft SMTP Server id 14.1.225.23; Tue, 5 Mar 2013 12:42:16 +0000 Received: from mail22-va3 (localhost [127.0.0.1]) by mail22-va3-R.bigfish.com (Postfix) with ESMTP id A93EE3A010C; Tue, 5 Mar 2013 12:42:16 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 3 X-BigFish: VS3(zzd799hc8kzz1f42h1ee6h1de0h1202h1e76h1d1ah1d2ahzz8275bhz2dh2a8h668h839he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1155h) Received: from mail22-va3 (localhost.localdomain [127.0.0.1]) by mail22-va3 (MessageSwitch) id 1362487333293280_12670; Tue, 5 Mar 2013 12:42:13 +0000 (UTC) Received: from VA3EHSMHS040.bigfish.com (unknown [10.7.14.239]) by mail22-va3.bigfish.com (Postfix) with ESMTP id 43AFEC004D; Tue, 5 Mar 2013 12:42:13 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS040.bigfish.com (10.7.99.50) with Microsoft SMTP Server (TLS) id 14.1.225.23; Tue, 5 Mar 2013 12:42:11 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-005.039d.mgd.msft.net (10.84.1.17) with Microsoft SMTP Server (TLS) id 14.2.328.11; Tue, 5 Mar 2013 12:42:10 +0000 Received: from nmglablinux22.zin33.ap.freescale.net (nmglablinux22.zin33.ap.freescale.net [10.232.20.244]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id r25CfqHj020636; Tue, 5 Mar 2013 05:42:08 -0700 From: Sandeep Singh To: Subject: [PATCH 4/4][v2] Basic configuration module for Le88266 Zarlink SLIC Date: Tue, 5 Mar 2013 18:11:37 +0530 Message-ID: <1362487297-19702-4-git-send-email-Sandeep@freescale.com> X-Mailer: git-send-email 1.7.6.GIT In-Reply-To: <1362487297-19702-1-git-send-email-Sandeep@freescale.com> References: <1362487297-19702-1-git-send-email-Sandeep@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130305_074218_672645_810AB873 X-CRM114-Status: GOOD ( 25.01 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [216.32.180.12 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Sandeep Singh , Poonam Aggrwal , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org - 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 Signed-off-by: Poonam Aggrwal --- drivers/tdm/Kconfig | 1 + drivers/tdm/Makefile | 2 +- drivers/tdm/line_ctrl/Kconfig | 12 + drivers/tdm/line_ctrl/Makefile | 5 + drivers/tdm/line_ctrl/slic_zarlink.c | 715 ++++++++++++++++++++++++++++++++++ drivers/tdm/line_ctrl/slic_zarlink.h | 131 +++++++ 6 files changed, 865 insertions(+), 1 deletions(-) create mode 100644 drivers/tdm/line_ctrl/Kconfig create mode 100644 drivers/tdm/line_ctrl/Makefile create mode 100644 drivers/tdm/line_ctrl/slic_zarlink.c create mode 100644 drivers/tdm/line_ctrl/slic_zarlink.h diff --git a/drivers/tdm/Kconfig b/drivers/tdm/Kconfig index f430adc..434ad6e 100644 --- a/drivers/tdm/Kconfig +++ b/drivers/tdm/Kconfig @@ -24,4 +24,5 @@ config TDM_DEBUG_CORE source drivers/tdm/test/Kconfig 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..579d2ab --- /dev/null +++ b/drivers/tdm/line_ctrl/slic_zarlink.c @@ -0,0 +1,715 @@ +/* + * 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 + * Hemant Agrawal + * Rajesh Gumasta + * + * Modified by Sandeep Kr Singh + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "slic_zarlink.h" +#include + +#define DRV_DESC "FREESCALE DEVELOPED ZARLINK SLIC DRIVER" +#define DRV_NAME "legerity" + +#define MAX_NUM_OF_SLICS 10 +#define SLIC_TRANS_LEN 1 +#define TDM_PHY_SLIC 1 +#define TDM_PHY_E1 2 +#define TDM_PHY_T1 3 + +#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"); +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(struct fsl_tdm_adapt_cfg *tdm_config) +{ + char temp1 = 0; + char temp2[2]; + char temp3[3]; + unsigned char cad[4]; + unsigned char len; + unsigned char channel_id; + struct spi_device *spi = g_spi; + int slic_id = num_slics; + + 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] = 0x80; + switch (tdm_config->tdm_tx_clk) { + case 2048000: + temp3[0] = temp3[0] | 0x02; + break; + default: + 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_id*4; + 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_id*4 + 2; + 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_id*4; + 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_id*4 + 2; + 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); + } + num_slics++; + return 0; +} + +void configure_spi_pdata(struct spi_device *spi) +{ + struct slic_platform_data *spi_slic_pdata; + 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; + struct slic_platform_data *data; + struct tdm_phy_priv *p_tdm_phy_priv; + struct device_node *np = spi->dev.of_node; + const phandle *phandle_prop; + g_spi = spi; + + printk(KERN_INFO "SLIC probed!\n"); + + p_tdm_phy_priv = kzalloc(sizeof(struct tdm_phy_priv), GFP_KERNEL); + if (!p_tdm_phy_priv) { + ret = -ENOMEM; + goto err_alloc; + } + + if (of_device_is_compatible(np, "tdm-phy-slic")) { + p_tdm_phy_priv->type = TDM_PHY_SLIC; + printk(KERN_INFO "TDM Phy type: SLIC\n"); + } else if (of_device_is_compatible(np, "tdm-phy-e1")) { + p_tdm_phy_priv->type = TDM_PHY_E1; + printk(KERN_INFO "TDM Phy type: E1\n"); + } else if (of_device_is_compatible(np, "tdm-phy-t1")) { + p_tdm_phy_priv->type = TDM_PHY_T1; + printk(KERN_INFO "TDM Phy type: T1\n"); + } else { + printk(KERN_ERR "TDM_PHY: Unknown device type\n"); + goto err_device_type; + } + + p_tdm_phy_priv->device = &spi->dev; + p_tdm_phy_priv->phy.np = np; + p_tdm_phy_priv->phy.configure_phy = slic_init_configure; + phandle_prop = of_get_property(np, "phandle", NULL); + if (!phandle_prop) + printk(KERN_ERR "Can't get phy handle\n"); + else { + p_tdm_phy_priv->phy.phandle_prop = (void *)phandle_prop; + add_tdm_phy(&p_tdm_phy_priv->phy); + } + 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; + +err_device_type: + kfree(p_tdm_phy_priv); +err_alloc: + 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 + * + * 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