blob: 64b3b48f1765afb2205edb996c72df2c30163f82 [file] [log] [blame]
/*
* Legerity driver for Mindspeed Comcerto.
*
* Copyright (C) 2008 Mindspeed Technologies, Inc.
* All rights reserved
*/
#include "gpio.h"
#include <mach/comcerto_spi.h>
#include "legerity.h"
#include "legerity_event_hdlr.h"
#define __raw_readl(addr) (*(volatile unsigned int *)(addr))
#define __raw_writel(b,addr) ((*(volatile unsigned int *)(addr)) = (b))
#define GFP_KERNEL 0
#define DEVICE_SPI "legerity0"
struct legerity_data *legerity;
struct legerity_slic_desc *slic1, *slic;
struct spi_adapter comcerto_spi_adapter;
int legerity_init(void);
/* define the module options for slic types */
static int slic_type = 14;
static int flash_time = 500;
/*
* legerity_run_tick - performs the API-II tick
*/
void legerity_run_tick (struct legerity_slic_desc * slic)
{
bool event;
VpApiTick(&slic->context, &event);
if (event) {
/* read out and handle the events */
VpEventType pEvent;
while (VpGetEvent(&slic->context, &pEvent)) legerity_event_handler(pEvent);
}
return;
}
/*
* initialize_slic - initializes a specific slic device
*/
static int initialize_slic (struct legerity_slic_desc *slic)
{
int i, res;
if ((res = VpMakeDeviceObject(slic->deviceType, slic->id, &slic->context, slic->object)) != VP_STATUS_SUCCESS) {
printf ("Failed to make legerity device %d object (%d)\n", slic->id, res);
return -1;
} else {
printf ("VpMakeDeviceObjectsucess to make legerity device %d object (%d)\n", slic->id, res);
}
for (i = 0; i < slic->slicMaxLines; i++) {
res = VpMakeLineObject(slic->termType, i, &slic->line_list[i].context, slic->line_list[i].object, &slic->context);
if (res != VP_STATUS_SUCCESS) {
printf ("Failed to make legerity device %d line %d object (%d)\n", slic->id, i, res);
return -1;
} else {
printf ("sucess to make legerity device %d line %d object (%d)\n", slic->id, i, res);
}
}
slic->num_rings=0;
res= VpInitDevice(&slic->context, DEV_PROFILE_LE88264_ABS_ZSI,
AC_PROFILE_LE88264_ABS_ZSI, DC_PROFILE_LE88264_ABS_ZSI,
RING_PROFILE_LE88264_ABS_ZSI, VP_PTABLE_NULL, VP_PTABLE_NULL);
if (res != VP_STATUS_SUCCESS) {
printf("FXS slicId %i VpInitDevice call failed condition:%d\n", slic->id, res);
return -1;
} else {
printf("FXS slicId %i VpInitDevice success \n", slic->id);
}
return 0;
}
/*
* fill_slic_params - initializes the legerity driver
*/
static void fill_slic_params(struct legerity_slic_desc *slic, int cs_no)
{
int i;
unsigned long nDelay1, nDelay2;
uint32 spiClk_kHz = LEGERITY_SPI_SC_RATE / 1000;
uint32 pClk_kHz = 4096;
/* initialize structure */
slic->id = cs_no;
slic->type = slic_type;
slic->deviceType = VP_DEV_880_SERIES;
slic->slicMaxLines = SLIC_MAX_LINES_LE88264_ABS_ZSI;
slic->termType = VP_TERM_FXS_GENERIC;
slic->object = (void *) MALLOC(sizeof (Vp880DeviceObjectType));
slic->line_list = (struct legerity_slic_line_desc *) MALLOC
(sizeof(struct legerity_slic_line_desc) * slic->slicMaxLines);
for (i=0; i < slic->slicMaxLines; i++)
slic->line_list[i].object = (void *) MALLOC(sizeof (Vp880LineObjectType));
/* determine slic profiles */
slic->deviceProfile = DEV_PROFILE_LE88264_ABS_ZSI;
slic->deviceProfileLt = NULL;
slic->acProfile = AC_PROFILE_LE88264_ABS_ZSI;
slic->dcProfile = DC_PROFILE_LE88264_ABS_ZSI;
slic->ringProfile = RING_PROFILE_LE88264_ABS_ZSI;
slic->ringCadence = RING_CAD_LE88264_ABS_ZSI;
/*
* ZSI devices have a special chip select off time requirement
* that is based on the SPI clock and the PCM clock.
*/
/* make sure we dont divide by 0 */
spiClk_kHz = (spiClk_kHz < 0) ? 1 : spiClk_kHz;
pClk_kHz = (pClk_kHz < 0) ? 1 : pClk_kHz;
nDelay1 = 2500 + (8000000 / pClk_kHz) - (7000000 / spiClk_kHz);
nDelay2 = (11000000/pClk_kHz) + 122;
/* cant delay by a negative value */
nDelay1 = (nDelay1 < 0) ? 0 : nDelay1;
nDelay2 = (nDelay2 < 0) ? 0 : nDelay2;
return;
}
/*
* detect_slic - tries to detect and initialize slics
*/
static int detect_slic(struct spi_adapter *adapter, int cs_no)
{
struct device_d *client = get_device_by_name(DEVICE_SPI);
int i;
/* initialize the slic structure */
legerity->slic_list = (void *) MALLOC(sizeof (struct legerity_slic_desc));
slic = legerity->slic_list;
slic->spi_client = client;
fill_slic_params(slic, cs_no);
/* initialize the slic itself */
if (!initialize_slic (slic))
printk ("Detected slic type %d\n", slic->type);
else
goto err0;
slic1 = slic;
printf("-----------------------------------------------------\n");
printf("Do On/Off Hook operations on the attached POTS phone:\n");
printf("Press <Control + c> to quit.\n");
while(1)
{
if (ctrlc())
{
printf("Exiting from POTS testing\n");
break;
}
legerity_run_tick(slic);
}
printf("-----------------------------------------------------\n");
return 0;
err0:
for (i=0; i<slic->slicMaxLines; i++)
FREE(slic->line_list[i].object);
FREE(slic->line_list);
FREE(slic->object);
FREE(slic);
legerity->slic_list = NULL;
return -1;
}
/*
* legerity_attach_adapter - initializes the legerity driver
*/
int legerity_attach_adapter(struct spi_adapter *adapter)
{
legerity->tdm_coding = 1;
legerity->flash_time= flash_time;
if(detect_slic(adapter, 3))
return -1;
legerity->running_timer = 1;
return 0;
}
/**
* legerity_init -
*/
static int is_legerity_init = 0;
int legerity_init(void)
{
if(is_legerity_init)
{
printf("SLIC already initialized\n");
printf("-----------------------------------------------------\n");
printf("Do On/Off Hook operations on the attached POTS phone:\n");
printf("Press <Control + c> to quit.\n");
while(1)
{
if (ctrlc())
{
printf("Exiting from POTS testing\n");
break;
}
legerity_run_tick(slic1);
}
printf("-----------------------------------------------------\n");
return 0;
}
is_legerity_init = 1;
printf("Initializing SLIC...\n");
/* allocate legerity_data structure */
legerity = (void *) MALLOC(sizeof (struct legerity_data));
if (legerity == NULL)
{
printf ("Unable to allocate memory for legerity driver\n");
return -1;
}
memset(legerity, 0, sizeof(struct legerity_data));
if(legerity_attach_adapter(&comcerto_spi_adapter))
return -1;
return 0;
}