|
|
@@ -0,0 +1,2998 @@
|
|
|
+/******************************************************************************
|
|
|
+
|
|
|
+ Copyright (c) 2009
|
|
|
+ Infineon Technologies AG
|
|
|
+ Am Campeon 1-12; 81726 Munich, Germany
|
|
|
+
|
|
|
+ For licensing information, see the file 'LICENSE' in the root folder of
|
|
|
+ this software module.
|
|
|
+
|
|
|
+******************************************************************************/
|
|
|
+
|
|
|
+/*!
|
|
|
+ \defgroup AMAZON_S_MEI Amazon-S MEI Driver Module
|
|
|
+ \brief Amazon-S MEI driver module
|
|
|
+ */
|
|
|
+
|
|
|
+/*!
|
|
|
+ \defgroup Internal Compile Parametere
|
|
|
+ \ingroup AMAZON_S_MEI
|
|
|
+ \brief exported functions for other driver use
|
|
|
+ */
|
|
|
+
|
|
|
+/*!
|
|
|
+ \file amazon_s_mei_bsp.c
|
|
|
+ \ingroup AMAZON_S_MEI
|
|
|
+ \brief Amazon-S MEI driver file
|
|
|
+ */
|
|
|
+
|
|
|
+#include <linux/kernel.h>
|
|
|
+#include <linux/module.h>
|
|
|
+#include <linux/version.h>
|
|
|
+#include <linux/utsrelease.h>
|
|
|
+#include <linux/types.h>
|
|
|
+#include <linux/fs.h>
|
|
|
+#include <linux/mm.h>
|
|
|
+#include <linux/errno.h>
|
|
|
+#include <linux/interrupt.h>
|
|
|
+#include <linux/netdevice.h>
|
|
|
+#include <linux/etherdevice.h>
|
|
|
+#include <linux/proc_fs.h>
|
|
|
+#include <linux/init.h>
|
|
|
+#include <linux/ioport.h>
|
|
|
+#include <linux/delay.h>
|
|
|
+#include <asm/uaccess.h>
|
|
|
+#include <asm/hardirq.h>
|
|
|
+#include <asm/ifx/ifx_regs.h>
|
|
|
+#include <asm/ifx/irq.h>
|
|
|
+#include <asm/ifx/ifx_gpio.h>
|
|
|
+//#include <asm/ifx/ifx_led.h>
|
|
|
+#include <asm/ifx/ifx_pmu.h>
|
|
|
+#include <asm/ifx/ifx_atm.h>
|
|
|
+#define IFX_MEI_BSP
|
|
|
+#include "ifxmips_mei_interface.h"
|
|
|
+
|
|
|
+#define IFXMIPS_RCU_RST IFX_RCU_RST_REQ
|
|
|
+#define IFXMIPS_RCU_RST_REQ_ARC_JTAG IFX_RCU_RST_REQ_ARC_JTAG
|
|
|
+#define IFXMIPS_RCU_RST_REQ_DFE IFX_RCU_RST_REQ_DFE
|
|
|
+#define IFXMIPS_RCU_RST_REQ_AFE IFX_RCU_RST_REQ_AFE
|
|
|
+#define IFXMIPS_FUSE_BASE_ADDR IFX_FUSE_BASE_ADDR
|
|
|
+#define IFXMIPS_ICU_IM0_IER IFX_ICU_IM0_IER
|
|
|
+#define IFXMIPS_ICU_IM2_IER IFX_ICU_IM2_IER
|
|
|
+#define IFXMIPS_MEI_INT IFX_MEI_INT
|
|
|
+#define IFXMIPS_MEI_DYING_GASP_INT IFX_MEI_DYING_GASP_INT
|
|
|
+#define IFXMIPS_MEI_BASE_ADDR IFX_MEI_SPACE_ACCESS
|
|
|
+#define IFXMIPS_PMU_PWDCR IFX_PMU_PWDCR
|
|
|
+#define IFXMIPS_MPS_CHIPID IFX_MPS_CHIPID
|
|
|
+
|
|
|
+#define ifxmips_port_reserve_pin ifx_gpio_pin_reserve
|
|
|
+#define ifxmips_port_set_dir_in ifx_gpio_dir_in_set
|
|
|
+#define ifxmips_port_clear_altsel0 ifx_gpio_altsel0_set
|
|
|
+#define ifxmips_port_clear_altsel1 ifx_gpio_altsel1_clear
|
|
|
+#define ifxmips_port_set_open_drain ifx_gpio_open_drain_clear
|
|
|
+#define ifxmips_port_free_pin ifx_gpio_pin_free
|
|
|
+#define ifxmips_mask_and_ack_irq bsp_mask_and_ack_irq
|
|
|
+#define IFXMIPS_MPS_CHIPID_VERSION_GET IFX_MCD_CHIPID_VERSION_GET
|
|
|
+#define ifxmips_r32(reg) __raw_readl(reg)
|
|
|
+#define ifxmips_w32(val, reg) __raw_writel(val, reg)
|
|
|
+#define ifxmips_w32_mask(clear, set, reg) ifxmips_w32((ifxmips_r32(reg) & ~clear) | set, reg)
|
|
|
+
|
|
|
+#define IFX_MEI_EMSG(fmt, args...) printk(KERN_ERR "[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
|
|
|
+#define IFX_MEI_DMSG(fmt, args...) printk(KERN_INFO "[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
|
|
|
+
|
|
|
+#ifdef CONFIG_IFXMIPS_MEI_FW_LOOPBACK
|
|
|
+//#define DFE_MEM_TEST
|
|
|
+//#define DFE_PING_TEST
|
|
|
+#define DFE_ATM_LOOPBACK
|
|
|
+
|
|
|
+#ifdef DFE_PING_TEST
|
|
|
+#include "dsp_xmem_arb_rand_em.h"
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef DFE_MEM_TEST
|
|
|
+#include "aai_mem_test.h"
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef DFE_ATM_LOOPBACK
|
|
|
+#include <asm/ifxmips/ifxmips_mei_fw_loopback.h>
|
|
|
+#endif
|
|
|
+
|
|
|
+void dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev);
|
|
|
+
|
|
|
+#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
|
|
|
+
|
|
|
+DSL_DEV_Version_t bsp_mei_version = {
|
|
|
+ major: 5,
|
|
|
+ minor: 0,
|
|
|
+ revision:0
|
|
|
+};
|
|
|
+DSL_DEV_HwVersion_t bsp_chip_info;
|
|
|
+
|
|
|
+#define IFX_MEI_DEVNAME "ifx_mei"
|
|
|
+#define BSP_MAX_DEVICES 1
|
|
|
+
|
|
|
+DSL_DEV_MeiError_t DSL_BSP_FWDownload (DSL_DEV_Device_t *, const char *, unsigned long, long *, long *);
|
|
|
+DSL_DEV_MeiError_t DSL_BSP_Showtime (DSL_DEV_Device_t *, DSL_uint32_t, DSL_uint32_t);
|
|
|
+DSL_DEV_MeiError_t DSL_BSP_AdslLedInit (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedType_t, DSL_DEV_LedHandler_t);
|
|
|
+//DSL_DEV_MeiError_t DSL_BSP_AdslLedSet (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedMode_t);
|
|
|
+DSL_DEV_MeiError_t DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t *, DSL_BSP_MemoryAccessType_t, DSL_uint32_t, DSL_uint32_t*, DSL_uint32_t);
|
|
|
+DSL_DEV_MeiError_t DSL_BSP_SendCMV (DSL_DEV_Device_t *, u16 *, int, u16 *);
|
|
|
+
|
|
|
+int DSL_BSP_KernelIoctls (DSL_DEV_Device_t *, unsigned int, unsigned long);
|
|
|
+
|
|
|
+static DSL_DEV_MeiError_t IFX_MEI_RunAdslModem (DSL_DEV_Device_t *);
|
|
|
+static DSL_DEV_MeiError_t IFX_MEI_CpuModeSet (DSL_DEV_Device_t *, DSL_DEV_CpuMode_t);
|
|
|
+static DSL_DEV_MeiError_t IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *);
|
|
|
+static DSL_DEV_MeiError_t IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *, int);
|
|
|
+static DSL_DEV_MeiError_t IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *, int);
|
|
|
+
|
|
|
+static int IFX_MEI_GetPage (DSL_DEV_Device_t *, u32, u32, u32, u32 *, u32 *);
|
|
|
+static int IFX_MEI_BarUpdate (DSL_DEV_Device_t *, int);
|
|
|
+
|
|
|
+static ssize_t IFX_MEI_Write (DSL_DRV_file_t *, const char *, size_t, loff_t *);
|
|
|
+static int IFX_MEI_UserIoctls (DSL_DRV_inode_t *, DSL_DRV_file_t *, unsigned int, unsigned long);
|
|
|
+static int IFX_MEI_Open (DSL_DRV_inode_t *, DSL_DRV_file_t *);
|
|
|
+static int IFX_MEI_Release (DSL_DRV_inode_t *, DSL_DRV_file_t *);
|
|
|
+
|
|
|
+void AMAZON_SE_MEI_ARC_MUX_Test(void);
|
|
|
+
|
|
|
+#ifdef CONFIG_PROC_FS
|
|
|
+static int IFX_MEI_ProcRead (struct file *, char *, size_t, loff_t *);
|
|
|
+static ssize_t IFX_MEI_ProcWrite (struct file *, const char *, size_t, loff_t *);
|
|
|
+
|
|
|
+#define PROC_ITEMS 11
|
|
|
+#define MEI_DIRNAME "ifxmips_mei"
|
|
|
+
|
|
|
+static struct proc_dir_entry *meidir;
|
|
|
+static struct file_operations IFX_MEI_ProcOperations = {
|
|
|
+ read:IFX_MEI_ProcRead,
|
|
|
+ write:IFX_MEI_ProcWrite,
|
|
|
+};
|
|
|
+static reg_entry_t regs[BSP_MAX_DEVICES][PROC_ITEMS]; //total items to be monitored by /proc/mei
|
|
|
+#define NUM_OF_REG_ENTRY (sizeof(regs[0])/sizeof(reg_entry_t))
|
|
|
+#endif //CONFIG_PROC_FS
|
|
|
+
|
|
|
+void IFX_MEI_ARC_MUX_Test(void);
|
|
|
+
|
|
|
+static int adsl_dummy_ledcallback(void);
|
|
|
+
|
|
|
+int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) = NULL;
|
|
|
+EXPORT_SYMBOL(ifx_mei_atm_showtime_enter);
|
|
|
+
|
|
|
+int (*ifx_mei_atm_showtime_exit)(void) = NULL;
|
|
|
+EXPORT_SYMBOL(ifx_mei_atm_showtime_exit);
|
|
|
+
|
|
|
+static int (*g_adsl_ledcallback)(void) = adsl_dummy_ledcallback;
|
|
|
+
|
|
|
+static unsigned int g_tx_link_rate[2] = {0};
|
|
|
+
|
|
|
+static void *g_xdata_addr = NULL;
|
|
|
+
|
|
|
+static u32 *mei_arc_swap_buff = NULL; // holding swap pages
|
|
|
+
|
|
|
+extern void ifxmips_mask_and_ack_irq(unsigned int irq_nr);
|
|
|
+#define MEI_MASK_AND_ACK_IRQ ifxmips_mask_and_ack_irq
|
|
|
+
|
|
|
+static int dev_major = 105;
|
|
|
+
|
|
|
+static struct file_operations bsp_mei_operations = {
|
|
|
+ owner:THIS_MODULE,
|
|
|
+ open:IFX_MEI_Open,
|
|
|
+ release:IFX_MEI_Release,
|
|
|
+ write:IFX_MEI_Write,
|
|
|
+ ioctl:IFX_MEI_UserIoctls,
|
|
|
+};
|
|
|
+
|
|
|
+static DSL_DEV_Device_t dsl_devices[BSP_MAX_DEVICES];
|
|
|
+
|
|
|
+static ifx_mei_device_private_t
|
|
|
+ sDanube_Mei_Private[BSP_MAX_DEVICES];
|
|
|
+
|
|
|
+static DSL_BSP_EventCallBack_t dsl_bsp_event_callback[DSL_BSP_CB_LAST + 1];
|
|
|
+
|
|
|
+/**
|
|
|
+ * Write a value to register
|
|
|
+ * This function writes a value to danube register
|
|
|
+ *
|
|
|
+ * \param ul_address The address to write
|
|
|
+ * \param ul_data The value to write
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+IFX_MEI_LongWordWrite (u32 ul_address, u32 ul_data)
|
|
|
+{
|
|
|
+ IFX_MEI_WRITE_REGISTER_L (ul_data, ul_address);
|
|
|
+ wmb();
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Write a value to register
|
|
|
+ * This function writes a value to danube register
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param ul_address The address to write
|
|
|
+ * \param ul_data The value to write
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+IFX_MEI_LongWordWriteOffset (DSL_DEV_Device_t * pDev, u32 ul_address,
|
|
|
+ u32 ul_data)
|
|
|
+{
|
|
|
+ IFX_MEI_WRITE_REGISTER_L (ul_data, pDev->base_address + ul_address);
|
|
|
+ wmb();
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Read the danube register
|
|
|
+ * This function read the value from danube register
|
|
|
+ *
|
|
|
+ * \param ul_address The address to write
|
|
|
+ * \param pul_data Pointer to the data
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+IFX_MEI_LongWordRead (u32 ul_address, u32 * pul_data)
|
|
|
+{
|
|
|
+ *pul_data = IFX_MEI_READ_REGISTER_L (ul_address);
|
|
|
+ rmb();
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Read the danube register
|
|
|
+ * This function read the value from danube register
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param ul_address The address to write
|
|
|
+ * \param pul_data Pointer to the data
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+IFX_MEI_LongWordReadOffset (DSL_DEV_Device_t * pDev, u32 ul_address,
|
|
|
+ u32 * pul_data)
|
|
|
+{
|
|
|
+ *pul_data = IFX_MEI_READ_REGISTER_L (pDev->base_address + ul_address);
|
|
|
+ rmb();
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Write several DWORD datas to ARC memory via ARC DMA interface
|
|
|
+ * This function writes several DWORD datas to ARC memory via DMA interface.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param destaddr The address to write
|
|
|
+ * \param databuff Pointer to the data buffer
|
|
|
+ * \param databuffsize Number of DWORDs to write
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_DMAWrite (DSL_DEV_Device_t * pDev, u32 destaddr,
|
|
|
+ u32 * databuff, u32 databuffsize)
|
|
|
+{
|
|
|
+ u32 *p = databuff;
|
|
|
+ u32 temp;
|
|
|
+
|
|
|
+ if (destaddr & 3)
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+
|
|
|
+ // Set the write transfer address
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, ME_DX_AD, destaddr);
|
|
|
+
|
|
|
+ // Write the data pushed across DMA
|
|
|
+ while (databuffsize--) {
|
|
|
+ temp = *p;
|
|
|
+ if (destaddr == MEI_TO_ARC_MAILBOX)
|
|
|
+ MEI_HALF_WORD_SWAP (temp);
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_DATA, temp);
|
|
|
+ p++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Read several DWORD datas from ARC memory via ARC DMA interface
|
|
|
+ * This function reads several DWORD datas from ARC memory via DMA interface.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param srcaddr The address to read
|
|
|
+ * \param databuff Pointer to the data buffer
|
|
|
+ * \param databuffsize Number of DWORDs to read
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_DMARead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff,
|
|
|
+ u32 databuffsize)
|
|
|
+{
|
|
|
+ u32 *p = databuff;
|
|
|
+ u32 temp;
|
|
|
+
|
|
|
+ if (srcaddr & 3)
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+
|
|
|
+ // Set the read transfer address
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_AD, srcaddr);
|
|
|
+
|
|
|
+ // Read the data popped across DMA
|
|
|
+ while (databuffsize--) {
|
|
|
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DX_DATA, &temp);
|
|
|
+ if (databuff == (u32 *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg) // swap half word
|
|
|
+ MEI_HALF_WORD_SWAP (temp);
|
|
|
+ *p = temp;
|
|
|
+ p++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Switch the ARC control mode
|
|
|
+ * This function switchs the ARC control mode to JTAG mode or MEI mode
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param mode The mode want to switch: JTAG_MASTER_MODE or MEI_MASTER_MODE.
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+IFX_MEI_ControlModeSet (DSL_DEV_Device_t * pDev, int mode)
|
|
|
+{
|
|
|
+ u32 temp = 0x0;
|
|
|
+
|
|
|
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_MASTER, &temp);
|
|
|
+ switch (mode) {
|
|
|
+ case JTAG_MASTER_MODE:
|
|
|
+ temp &= ~(HOST_MSTR);
|
|
|
+ break;
|
|
|
+ case MEI_MASTER_MODE:
|
|
|
+ temp |= (HOST_MSTR);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ IFX_MEI_EMSG ("IFX_MEI_ControlModeSet: unkonwn mode [%d]\n", mode);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_MASTER, temp);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Disable ARC to MEI interrupt
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+IFX_MEI_IRQDisable (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, 0x0);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Eable ARC to MEI interrupt
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+IFX_MEI_IRQEnable (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, MSGAV_EN);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Poll for transaction complete signal
|
|
|
+ * This function polls and waits for transaction complete signal.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static void
|
|
|
+meiPollForDbgDone (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ u32 query = 0;
|
|
|
+ int i = 0;
|
|
|
+
|
|
|
+ while (i < WHILE_DELAY) {
|
|
|
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ARC2ME_STAT, &query);
|
|
|
+ query &= (ARC_TO_MEI_DBG_DONE);
|
|
|
+ if (query)
|
|
|
+ break;
|
|
|
+ i++;
|
|
|
+ if (i == WHILE_DELAY) {
|
|
|
+ IFX_MEI_EMSG ("PollforDbg fail!\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_DBG_DONE); // to clear this interrupt
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ARC Debug Memory Access for a single DWORD reading.
|
|
|
+ * This function used for direct, address-based access to ARC memory.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param DEC_mode ARC memory space to used
|
|
|
+ * \param address Address to read
|
|
|
+ * \param data Pointer to data
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+_IFX_MEI_DBGLongWordRead (DSL_DEV_Device_t * pDev, u32 DEC_mode,
|
|
|
+ u32 address, u32 * data)
|
|
|
+{
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode);
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_RD_AD, address);
|
|
|
+ meiPollForDbgDone (pDev);
|
|
|
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_DATA, data);
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ARC Debug Memory Access for a single DWORD writing.
|
|
|
+ * This function used for direct, address-based access to ARC memory.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param DEC_mode ARC memory space to used
|
|
|
+ * \param address The address to write
|
|
|
+ * \param data The data to write
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+_IFX_MEI_DBGLongWordWrite (DSL_DEV_Device_t * pDev, u32 DEC_mode,
|
|
|
+ u32 address, u32 data)
|
|
|
+{
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode);
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_WR_AD, address);
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DATA, data);
|
|
|
+ meiPollForDbgDone (pDev);
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ARC Debug Memory Access for writing.
|
|
|
+ * This function used for direct, address-based access to ARC memory.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param destaddr The address to read
|
|
|
+ * \param databuffer Pointer to data
|
|
|
+ * \param databuffsize The number of DWORDs to read
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_DebugWrite (DSL_DEV_Device_t * pDev, u32 destaddr,
|
|
|
+ u32 * databuff, u32 databuffsize)
|
|
|
+{
|
|
|
+ u32 i;
|
|
|
+ u32 temp = 0x0;
|
|
|
+ u32 address = 0x0;
|
|
|
+ u32 *buffer = 0x0;
|
|
|
+
|
|
|
+ // Open the debug port before DMP memory write
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+
|
|
|
+ // For the requested length, write the address and write the data
|
|
|
+ address = destaddr;
|
|
|
+ buffer = databuff;
|
|
|
+ for (i = 0; i < databuffsize; i++) {
|
|
|
+ temp = *buffer;
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK, address, temp);
|
|
|
+ address += 4;
|
|
|
+ buffer++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Close the debug port after DMP memory write
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ARC Debug Memory Access for reading.
|
|
|
+ * This function used for direct, address-based access to ARC memory.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param srcaddr The address to read
|
|
|
+ * \param databuffer Pointer to data
|
|
|
+ * \param databuffsize The number of DWORDs to read
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_DebugRead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff, u32 databuffsize)
|
|
|
+{
|
|
|
+ u32 i;
|
|
|
+ u32 temp = 0x0;
|
|
|
+ u32 address = 0x0;
|
|
|
+ u32 *buffer = 0x0;
|
|
|
+
|
|
|
+ // Open the debug port before DMP memory read
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+
|
|
|
+ // For the requested length, write the address and read the data
|
|
|
+ address = srcaddr;
|
|
|
+ buffer = databuff;
|
|
|
+ for (i = 0; i < databuffsize; i++) {
|
|
|
+ _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK, address, &temp);
|
|
|
+ *buffer = temp;
|
|
|
+ address += 4;
|
|
|
+ buffer++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Close the debug port after DMP memory read
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Send a message to ARC MailBox.
|
|
|
+ * This function sends a message to ARC Mailbox via ARC DMA interface.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param msgsrcbuffer Pointer to message.
|
|
|
+ * \param msgsize The number of words to write.
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_MailboxWrite (DSL_DEV_Device_t * pDev, u16 * msgsrcbuffer,
|
|
|
+ u16 msgsize)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ u32 arc_mailbox_status = 0x0;
|
|
|
+ u32 temp = 0;
|
|
|
+ DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+
|
|
|
+ // Write to mailbox
|
|
|
+ meiMailboxError =
|
|
|
+ IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOX, (u32 *) msgsrcbuffer, msgsize / 2);
|
|
|
+ meiMailboxError =
|
|
|
+ IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOXR, (u32 *) (&temp), 1);
|
|
|
+
|
|
|
+ // Notify arc that mailbox write completed
|
|
|
+ DSL_DEV_PRIVATE(pDev)->cmv_waiting = 1;
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV);
|
|
|
+
|
|
|
+ i = 0;
|
|
|
+ while (i < WHILE_DELAY) { // wait for ARC to clear the bit
|
|
|
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ME2ARC_INT, &arc_mailbox_status);
|
|
|
+ if ((arc_mailbox_status & MEI_TO_ARC_MSGAV) != MEI_TO_ARC_MSGAV)
|
|
|
+ break;
|
|
|
+ i++;
|
|
|
+ if (i == WHILE_DELAY) {
|
|
|
+ IFX_MEI_EMSG (">>> Timeout waiting for ARC to clear MEI_TO_ARC_MSGAV!!!"
|
|
|
+ " MEI_TO_ARC message size = %d DWORDs <<<\n", msgsize/2);
|
|
|
+ meiMailboxError = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return meiMailboxError;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Read a message from ARC MailBox.
|
|
|
+ * This function reads a message from ARC Mailbox via ARC DMA interface.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param msgsrcbuffer Pointer to message.
|
|
|
+ * \param msgsize The number of words to read
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_MailboxRead (DSL_DEV_Device_t * pDev, u16 * msgdestbuffer,
|
|
|
+ u16 msgsize)
|
|
|
+{
|
|
|
+ DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ // Read from mailbox
|
|
|
+ meiMailboxError =
|
|
|
+ IFX_MEI_DMARead (pDev, ARC_TO_MEI_MAILBOX, (u32 *) msgdestbuffer, msgsize / 2);
|
|
|
+
|
|
|
+ // Notify arc that mailbox read completed
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
|
|
|
+
|
|
|
+ return meiMailboxError;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Download boot pages to ARC.
|
|
|
+ * This function downloads boot pages to ARC.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_DownloadBootPages (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ int boot_loop;
|
|
|
+ int page_size;
|
|
|
+ u32 dest_addr;
|
|
|
+
|
|
|
+ /*
|
|
|
+ ** DMA the boot code page(s)
|
|
|
+ */
|
|
|
+
|
|
|
+ for (boot_loop = 1;
|
|
|
+ boot_loop <
|
|
|
+ (DSL_DEV_PRIVATE(pDev)->img_hdr-> count); boot_loop++) {
|
|
|
+ if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].p_size) & BOOT_FLAG) {
|
|
|
+ page_size = IFX_MEI_GetPage (pDev, boot_loop,
|
|
|
+ GET_PROG, MAXSWAPSIZE,
|
|
|
+ mei_arc_swap_buff,
|
|
|
+ &dest_addr);
|
|
|
+ if (page_size > 0) {
|
|
|
+ IFX_MEI_DMAWrite (pDev, dest_addr,
|
|
|
+ mei_arc_swap_buff,
|
|
|
+ page_size);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].d_size) & BOOT_FLAG) {
|
|
|
+ page_size = IFX_MEI_GetPage (pDev, boot_loop,
|
|
|
+ GET_DATA, MAXSWAPSIZE,
|
|
|
+ mei_arc_swap_buff,
|
|
|
+ &dest_addr);
|
|
|
+ if (page_size > 0) {
|
|
|
+ IFX_MEI_DMAWrite (pDev, dest_addr,
|
|
|
+ mei_arc_swap_buff,
|
|
|
+ page_size);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Initial efuse rar.
|
|
|
+ **/
|
|
|
+static void
|
|
|
+IFX_MEI_FuseInit (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ u32 data = 0;
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE, &data, 1);
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, &data, 1);
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE, &data, 1);
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, &data, 1);
|
|
|
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE, &data, 1);
|
|
|
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, &data, 1);
|
|
|
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, &data, 1);
|
|
|
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, &data, 1);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * efuse rar program
|
|
|
+ **/
|
|
|
+static void
|
|
|
+IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ u32 reg_data, fuse_value;
|
|
|
+ int i = 0;
|
|
|
+
|
|
|
+ IFX_MEI_LongWordRead ((u32) IFXMIPS_RCU_RST, ®_data);
|
|
|
+ while ((reg_data & 0x10000000) == 0) {
|
|
|
+ IFX_MEI_LongWordRead ((u32) IFXMIPS_RCU_RST, ®_data);
|
|
|
+ i++;
|
|
|
+ /* 0x4000 translate to about 16 ms@111M, so should be enough */
|
|
|
+ if (i == 0x4000)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // STEP a: Prepare memory for external accesses
|
|
|
+ // Write fuse_en bit24
|
|
|
+ IFX_MEI_LongWordRead ((u32) IFXMIPS_RCU_RST, ®_data);
|
|
|
+ IFX_MEI_LongWordWrite ((u32) IFXMIPS_RCU_RST, reg_data | (1 << 24));
|
|
|
+
|
|
|
+ IFX_MEI_FuseInit (pDev);
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ IFX_MEI_LongWordRead ((u32) (IFXMIPS_FUSE_BASE_ADDR) + i * 4, &fuse_value);
|
|
|
+ switch (fuse_value & 0xF0000) {
|
|
|
+ case 0x80000:
|
|
|
+ reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
|
|
|
+ (RX_DILV_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, ®_data, 1);
|
|
|
+ break;
|
|
|
+ case 0x90000:
|
|
|
+ reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
|
|
|
+ (RX_DILV_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, ®_data, 1);
|
|
|
+ break;
|
|
|
+ case 0xA0000:
|
|
|
+ reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) |
|
|
|
+ (IRAM0_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE, ®_data, 1);
|
|
|
+ break;
|
|
|
+ case 0xB0000:
|
|
|
+ reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) |
|
|
|
+ (IRAM0_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, ®_data, 1);
|
|
|
+ break;
|
|
|
+ case 0xC0000:
|
|
|
+ reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) |
|
|
|
+ (IRAM1_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE, ®_data, 1);
|
|
|
+ break;
|
|
|
+ case 0xD0000:
|
|
|
+ reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) |
|
|
|
+ (IRAM1_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, ®_data, 1);
|
|
|
+ break;
|
|
|
+ case 0xE0000:
|
|
|
+ reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) |
|
|
|
+ (BRAM_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE, ®_data, 1);
|
|
|
+ break;
|
|
|
+ case 0xF0000:
|
|
|
+ reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) |
|
|
|
+ (BRAM_ADDR_BIT_MASK + 0x1));
|
|
|
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, ®_data, 1);
|
|
|
+ break;
|
|
|
+ default: // PPE efuse
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ IFX_MEI_LongWordRead ((u32) IFXMIPS_RCU_RST, ®_data);
|
|
|
+ IFX_MEI_LongWordWrite ((u32) IFXMIPS_RCU_RST, reg_data & ~(1 << 24));
|
|
|
+ IFX_MEI_LongWordRead ((u32) IFXMIPS_RCU_RST, ®_data);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Enable DFE Clock
|
|
|
+ * This function enables DFE Clock
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_EnableCLK (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ u32 arc_debug_data = 0;
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+ //enable ac_clk signal
|
|
|
+ _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK,
|
|
|
+ CRI_CCR0, &arc_debug_data);
|
|
|
+ arc_debug_data |= ACL_CLK_MODE_ENABLE;
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK,
|
|
|
+ CRI_CCR0, arc_debug_data);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Halt the ARC.
|
|
|
+ * This function halts the ARC.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_HaltArc (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ u32 arc_debug_data = 0x0;
|
|
|
+
|
|
|
+ // Switch arc control from JTAG mode to MEI mode
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+ _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK,
|
|
|
+ ARC_DEBUG, &arc_debug_data);
|
|
|
+ arc_debug_data |= ARC_DEBUG_HALT;
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
|
|
|
+ ARC_DEBUG, arc_debug_data);
|
|
|
+ // Switch arc control from MEI mode to JTAG mode
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+
|
|
|
+ MEI_WAIT (10);
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Run the ARC.
|
|
|
+ * This function runs the ARC.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_RunArc (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ u32 arc_debug_data = 0x0;
|
|
|
+
|
|
|
+ // Switch arc control from JTAG mode to MEI mode- write '1' to bit0
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+ _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK,
|
|
|
+ AUX_STATUS, &arc_debug_data);
|
|
|
+
|
|
|
+ // Write debug data reg with content ANDd with 0xFDFFFFFF (halt bit cleared)
|
|
|
+ arc_debug_data &= ~ARC_AUX_HALT;
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
|
|
|
+ AUX_STATUS, arc_debug_data);
|
|
|
+
|
|
|
+ // Switch arc control from MEI mode to JTAG mode- write '0' to bit0
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+ // Enable mask for arc codeswap interrupts
|
|
|
+ IFX_MEI_IRQEnable (pDev);
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Reset the ARC.
|
|
|
+ * This function resets the ARC.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_ResetARC (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ u32 arc_debug_data = 0;
|
|
|
+
|
|
|
+ IFX_MEI_HaltArc (pDev);
|
|
|
+
|
|
|
+ IFX_MEI_LongWordRead ((u32) IFXMIPS_RCU_RST, &arc_debug_data);
|
|
|
+ IFX_MEI_LongWordWrite ((u32) IFXMIPS_RCU_RST,
|
|
|
+ arc_debug_data | IFXMIPS_RCU_RST_REQ_DFE | IFXMIPS_RCU_RST_REQ_AFE);
|
|
|
+
|
|
|
+ // reset ARC
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, MEI_SOFT_RESET);
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, 0);
|
|
|
+
|
|
|
+ IFX_MEI_IRQDisable (pDev);
|
|
|
+
|
|
|
+ IFX_MEI_EnableCLK (pDev);
|
|
|
+
|
|
|
+#if 0
|
|
|
+ // reset part of PPE
|
|
|
+ *(unsigned long *) (BSP_PPE32_SRST) = 0xC30;
|
|
|
+ *(unsigned long *) (BSP_PPE32_SRST) = 0xFFF;
|
|
|
+#endif
|
|
|
+
|
|
|
+ DSL_DEV_PRIVATE(pDev)->modem_ready = 0;
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+DSL_DEV_MeiError_t
|
|
|
+DSL_BSP_Showtime (DSL_DEV_Device_t * dev, DSL_uint32_t rate_fast, DSL_uint32_t rate_intl)
|
|
|
+{
|
|
|
+ struct port_cell_info port_cell = {0};
|
|
|
+
|
|
|
+ IFX_MEI_EMSG ("Datarate US intl = %d, fast = %d\n", (int)rate_intl,
|
|
|
+ (int)rate_fast);
|
|
|
+
|
|
|
+ if ( rate_fast )
|
|
|
+ g_tx_link_rate[0] = rate_fast / (53 * 8);
|
|
|
+ if ( rate_intl )
|
|
|
+ g_tx_link_rate[1] = rate_intl / (53 * 8);
|
|
|
+
|
|
|
+ if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ) {
|
|
|
+ IFX_MEI_EMSG ("Got rate fail.\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( ifx_mei_atm_showtime_enter )
|
|
|
+ {
|
|
|
+ port_cell.port_num = 2;
|
|
|
+ port_cell.tx_link_rate[0] = g_tx_link_rate[0];
|
|
|
+ port_cell.tx_link_rate[1] = g_tx_link_rate[1];
|
|
|
+ ifx_mei_atm_showtime_enter(&port_cell, g_xdata_addr);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ IFX_MEI_EMSG("no hookup from ATM driver to set cell rate\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Reset/halt/run the DFE.
|
|
|
+ * This function provide operations to reset/halt/run the DFE.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param mode which operation want to do
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_CpuModeSet (DSL_DEV_Device_t *pDev,
|
|
|
+ DSL_DEV_CpuMode_t mode)
|
|
|
+{
|
|
|
+ DSL_DEV_MeiError_t err_ret = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ switch (mode) {
|
|
|
+ case DSL_CPU_HALT:
|
|
|
+ err_ret = IFX_MEI_HaltArc (pDev);
|
|
|
+ break;
|
|
|
+ case DSL_CPU_RUN:
|
|
|
+ err_ret = IFX_MEI_RunArc (pDev);
|
|
|
+ break;
|
|
|
+ case DSL_CPU_RESET:
|
|
|
+ err_ret = IFX_MEI_ResetARC (pDev);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return err_ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Accress DFE memory.
|
|
|
+ * This function provide a way to access DFE memory;
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param type read or write
|
|
|
+ * \param destaddr destination address
|
|
|
+ * \param databuff pointer to hold data
|
|
|
+ * \param databuffsize size want to read/write
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+DSL_DEV_MeiError_t
|
|
|
+DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t * pDev,
|
|
|
+ DSL_BSP_MemoryAccessType_t type,
|
|
|
+ DSL_uint32_t destaddr, DSL_uint32_t *databuff,
|
|
|
+ DSL_uint32_t databuffsize)
|
|
|
+{
|
|
|
+ DSL_DEV_MeiError_t meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ switch (type) {
|
|
|
+ case DSL_BSP_MEMORY_READ:
|
|
|
+ meierr = IFX_MEI_DebugRead (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize);
|
|
|
+ break;
|
|
|
+ case DSL_BSP_MEMORY_WRITE:
|
|
|
+ meierr = IFX_MEI_DebugWrite (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Download boot code to ARC.
|
|
|
+ * This function downloads boot code to ARC.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *pDev)
|
|
|
+{
|
|
|
+ IFX_MEI_IRQDisable (pDev);
|
|
|
+
|
|
|
+ IFX_MEI_EnableCLK (pDev);
|
|
|
+
|
|
|
+ IFX_MEI_FuseProg (pDev); //program fuse rar
|
|
|
+
|
|
|
+ IFX_MEI_DownloadBootPages (pDev);
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Enable Jtag debugger interface
|
|
|
+ * This function setups mips gpio to enable jtag debugger
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param enable enable or disable
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *dev, int enable)
|
|
|
+{
|
|
|
+ int meierr=0;
|
|
|
+ u32 reg_data;
|
|
|
+
|
|
|
+ switch (enable) {
|
|
|
+ case 1:
|
|
|
+ //reserve gpio 9, 10, 11, 14, 19 for ARC JTAG
|
|
|
+ ifxmips_port_reserve_pin (0, 9);
|
|
|
+ ifxmips_port_reserve_pin (0, 10);
|
|
|
+ ifxmips_port_reserve_pin (0, 11);
|
|
|
+ ifxmips_port_reserve_pin (0, 14);
|
|
|
+ ifxmips_port_reserve_pin (1, 3);
|
|
|
+
|
|
|
+ ifxmips_port_set_dir_in(0, 11);
|
|
|
+ ifxmips_port_clear_altsel0(0, 11);
|
|
|
+ ifxmips_port_clear_altsel1(0, 11);
|
|
|
+ ifxmips_port_set_open_drain(0, 11);
|
|
|
+ //enable ARC JTAG
|
|
|
+ IFX_MEI_LongWordRead ((u32) IFXMIPS_RCU_RST, ®_data);
|
|
|
+ IFX_MEI_LongWordWrite ((u32) IFXMIPS_RCU_RST, reg_data | IFXMIPS_RCU_RST_REQ_ARC_JTAG);
|
|
|
+ break;
|
|
|
+ case 0:
|
|
|
+ default:
|
|
|
+ //reserve gpio 9, 10, 11, 14, 19 for ARC JTAG
|
|
|
+ meierr = ifxmips_port_free_pin (0, 9);
|
|
|
+ if (meierr < 0) {
|
|
|
+ IFX_MEI_EMSG ("Reserve GPIO 9 Fail.\n");
|
|
|
+ goto jtag_end;
|
|
|
+ }
|
|
|
+ meierr = ifxmips_port_free_pin (0, 10);
|
|
|
+ if (meierr < 0) {
|
|
|
+ IFX_MEI_EMSG ("Reserve GPIO 10 Fail.\n");
|
|
|
+ goto jtag_end;
|
|
|
+ }
|
|
|
+ meierr = ifxmips_port_free_pin (0, 11);
|
|
|
+ if (meierr < 0) {
|
|
|
+ IFX_MEI_EMSG ("Reserve GPIO 11 Fail.\n");
|
|
|
+ goto jtag_end;
|
|
|
+ }
|
|
|
+ meierr = ifxmips_port_free_pin (0, 14);
|
|
|
+ if (meierr < 0) {
|
|
|
+ IFX_MEI_EMSG ("Reserve GPIO 14 Fail.\n");
|
|
|
+ goto jtag_end;
|
|
|
+ }
|
|
|
+ meierr = ifxmips_port_free_pin (1, 3);
|
|
|
+ if (meierr < 0) {
|
|
|
+ IFX_MEI_EMSG ("Reserve GPIO 19 Fail.\n");
|
|
|
+ goto jtag_end;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+jtag_end:
|
|
|
+ if (meierr)
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Enable DFE to MIPS interrupt
|
|
|
+ * This function enable DFE to MIPS interrupt
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param enable enable or disable
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *pDev, int enable)
|
|
|
+{
|
|
|
+ DSL_DEV_MeiError_t meierr;
|
|
|
+ switch (enable) {
|
|
|
+ case 0:
|
|
|
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ IFX_MEI_IRQDisable (pDev);
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ IFX_MEI_IRQEnable (pDev);
|
|
|
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+ return meierr;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Get the modem status
|
|
|
+ * This function return the modem status
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return 1: modem ready 0: not ready
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static int
|
|
|
+IFX_MEI_IsModemReady (DSL_DEV_Device_t * pDev)
|
|
|
+{
|
|
|
+ return DSL_DEV_PRIVATE(pDev)->modem_ready;
|
|
|
+}
|
|
|
+
|
|
|
+DSL_DEV_MeiError_t
|
|
|
+DSL_BSP_AdslLedInit (DSL_DEV_Device_t * dev,
|
|
|
+ DSL_DEV_LedId_t led_number,
|
|
|
+ DSL_DEV_LedType_t type,
|
|
|
+ DSL_DEV_LedHandler_t handler)
|
|
|
+{
|
|
|
+#if 0
|
|
|
+ struct led_config_param param;
|
|
|
+ if (led_number == DSL_LED_LINK_ID && type == DSL_LED_LINK_TYPE && handler == /*DSL_LED_HD_CPU*/DSL_LED_HD_FW) {
|
|
|
+ param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE;
|
|
|
+ param.led = 0x01;
|
|
|
+ param.source = 0x01;
|
|
|
+// bsp_led_config (¶m);
|
|
|
+
|
|
|
+ } else if (led_number == DSL_LED_DATA_ID && type == DSL_LED_DATA_TYPE && (handler == DSL_LED_HD_FW)) {
|
|
|
+ param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE;
|
|
|
+ param.led = 0x02;
|
|
|
+ param.source = 0x02;
|
|
|
+// bsp_led_config (¶m);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+};
|
|
|
+#if 0
|
|
|
+DSL_DEV_MeiError_t
|
|
|
+DSL_BSP_AdslLedSet (DSL_DEV_Device_t * dev, DSL_DEV_LedId_t led_number, DSL_DEV_LedMode_t mode)
|
|
|
+{
|
|
|
+ printk(KERN_INFO "[%s %d]: mode = %#x, led_number = %d\n", __func__, __LINE__, mode, led_number);
|
|
|
+ switch (mode) {
|
|
|
+ case DSL_LED_OFF:
|
|
|
+ switch (led_number) {
|
|
|
+ case DSL_LED_LINK_ID:
|
|
|
+#ifdef CONFIG_BSP_LED
|
|
|
+ bsp_led_set_blink (1, 0);
|
|
|
+ bsp_led_set_data (1, 0);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+ case DSL_LED_DATA_ID:
|
|
|
+#ifdef CONFIG_BSP_LED
|
|
|
+ bsp_led_set_blink (0, 0);
|
|
|
+ bsp_led_set_data (0, 0);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case DSL_LED_FLASH:
|
|
|
+ switch (led_number) {
|
|
|
+ case DSL_LED_LINK_ID:
|
|
|
+#ifdef CONFIG_BSP_LED
|
|
|
+ bsp_led_set_blink (1, 1); // data
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+ case DSL_LED_DATA_ID:
|
|
|
+#ifdef CONFIG_BSP_LED
|
|
|
+ bsp_led_set_blink (0, 1); // data
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case DSL_LED_ON:
|
|
|
+ switch (led_number) {
|
|
|
+ case DSL_LED_LINK_ID:
|
|
|
+#ifdef CONFIG_BSP_LED
|
|
|
+ bsp_led_set_blink (1, 0);
|
|
|
+ bsp_led_set_data (1, 1);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+ case DSL_LED_DATA_ID:
|
|
|
+#ifdef CONFIG_BSP_LED
|
|
|
+ bsp_led_set_blink (0, 0);
|
|
|
+ bsp_led_set_data (0, 1);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+};
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+/**
|
|
|
+* Compose a message.
|
|
|
+* This function compose a message from opcode, group, address, index, size, and data
|
|
|
+*
|
|
|
+* \param opcode The message opcode
|
|
|
+* \param group The message group number
|
|
|
+* \param address The message address.
|
|
|
+* \param index The message index.
|
|
|
+* \param size The number of words to read/write.
|
|
|
+* \param data The pointer to data.
|
|
|
+* \param CMVMSG The pointer to message buffer.
|
|
|
+* \ingroup Internal
|
|
|
+*/
|
|
|
+void
|
|
|
+makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, u16 * data, u16 *CMVMSG)
|
|
|
+{
|
|
|
+ memset (CMVMSG, 0, MSG_LENGTH * 2);
|
|
|
+ CMVMSG[0] = (opcode << 4) + (size & 0xf);
|
|
|
+ CMVMSG[1] = (((index == 0) ? 0 : 1) << 7) + (group & 0x7f);
|
|
|
+ CMVMSG[2] = address;
|
|
|
+ CMVMSG[3] = index;
|
|
|
+ if (opcode == H2D_CMV_WRITE)
|
|
|
+ memcpy (CMVMSG + 4, data, size * 2);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Send a message to ARC and read the response
|
|
|
+ * This function sends a message to arc, waits the response, and reads the responses.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param request Pointer to the request
|
|
|
+ * \param reply Wait reply or not.
|
|
|
+ * \param response Pointer to the response
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+DSL_DEV_MeiError_t
|
|
|
+DSL_BSP_SendCMV (DSL_DEV_Device_t * pDev, u16 * request, int reply, u16 * response) // write cmv to arc, if reply needed, wait for reply
|
|
|
+{
|
|
|
+ DSL_DEV_MeiError_t meierror;
|
|
|
+#if defined(BSP_PORT_RTEMS)
|
|
|
+ int delay_counter = 0;
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (MEI_MUTEX_LOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema))
|
|
|
+ return -ERESTARTSYS;
|
|
|
+
|
|
|
+ DSL_DEV_PRIVATE(pDev)->cmv_reply = reply;
|
|
|
+ memset (DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, 0,
|
|
|
+ sizeof (DSL_DEV_PRIVATE(pDev)->
|
|
|
+ CMV_RxMsg));
|
|
|
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
|
|
|
+
|
|
|
+ meierror = IFX_MEI_MailboxWrite (pDev, request, MSG_LENGTH);
|
|
|
+
|
|
|
+ if (meierror != DSL_DEV_MEI_ERR_SUCCESS) {
|
|
|
+ DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0;
|
|
|
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
|
|
|
+ IFX_MEI_EMSG ("MailboxWrite Fail!\n");
|
|
|
+ IFX_MEI_EMSG ("Resetting ARC...\n");
|
|
|
+ IFX_MEI_ResetARC(pDev);
|
|
|
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
|
|
|
+ return meierror;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ DSL_DEV_PRIVATE(pDev)->cmv_count++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)->cmv_reply ==
|
|
|
+ NO_REPLY) {
|
|
|
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+#if !defined(BSP_PORT_RTEMS)
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0)
|
|
|
+ MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav, CMV_TIMEOUT);
|
|
|
+#else
|
|
|
+ while (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0 && delay_counter < CMV_TIMEOUT / 5) {
|
|
|
+ MEI_WAIT (5);
|
|
|
+ delay_counter++;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0;
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0) { //CMV_timeout
|
|
|
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
|
|
|
+ IFX_MEI_EMSG ("\%s: DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT\n",
|
|
|
+ __FUNCTION__);
|
|
|
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
|
|
|
+ return DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
|
|
|
+ DSL_DEV_PRIVATE(pDev)->
|
|
|
+ reply_count++;
|
|
|
+ memcpy (response, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2);
|
|
|
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ }
|
|
|
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Reset the ARC, download boot codes, and run the ARC.
|
|
|
+ * This function resets the ARC, downloads boot codes to ARC, and runs the ARC.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
|
|
|
+{
|
|
|
+ int nSize = 0, idx = 0;
|
|
|
+ uint32_t im0_register, im2_register;
|
|
|
+// DSL_DEV_WinHost_Message_t m;
|
|
|
+
|
|
|
+ if (mei_arc_swap_buff == NULL) {
|
|
|
+ mei_arc_swap_buff =
|
|
|
+ (u32 *) kmalloc (MAXSWAPSIZE * 4, GFP_KERNEL);
|
|
|
+ if (mei_arc_swap_buff == NULL) {
|
|
|
+ IFX_MEI_EMSG (">>> malloc fail for codeswap buff!!! <<<\n");
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ }
|
|
|
+ printk("allocate %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff);
|
|
|
+ }
|
|
|
+
|
|
|
+ DSL_DEV_PRIVATE(pDev)->img_hdr =
|
|
|
+ (ARC_IMG_HDR *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[0].address;
|
|
|
+ if ((DSL_DEV_PRIVATE(pDev)->img_hdr->
|
|
|
+ count) * sizeof (ARC_SWP_PAGE_HDR) > SDRAM_SEGMENT_SIZE) {
|
|
|
+ IFX_MEI_EMSG ("firmware header size is bigger than 64K segment size\n");
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ }
|
|
|
+ // check image size
|
|
|
+ for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) {
|
|
|
+ nSize += DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].nCopy;
|
|
|
+ }
|
|
|
+ if (nSize !=
|
|
|
+ DSL_DEV_PRIVATE(pDev)->image_size) {
|
|
|
+ IFX_MEI_EMSG ("Firmware download is not completed. Please download firmware again!\n");
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ }
|
|
|
+ // TODO: check crc
|
|
|
+ ///
|
|
|
+
|
|
|
+ IFX_MEI_ResetARC (pDev);
|
|
|
+ IFX_MEI_HaltArc (pDev);
|
|
|
+ IFX_MEI_BarUpdate (pDev, DSL_DEV_PRIVATE(pDev)->nBar);
|
|
|
+
|
|
|
+ //IFX_MEI_DMSG("Starting to meiDownloadBootCode\n");
|
|
|
+
|
|
|
+ IFX_MEI_DownloadBootCode (pDev);
|
|
|
+
|
|
|
+ im0_register = (*IFXMIPS_ICU_IM0_IER) & (1 << 20);
|
|
|
+ im2_register = (*IFXMIPS_ICU_IM2_IER) & (1 << 20);
|
|
|
+ /* Turn off irq */
|
|
|
+ #ifdef CONFIG_IFXMIPS_AMAZON_SE
|
|
|
+ disable_irq (IFXMIPS_USB_OC_INT0);
|
|
|
+ disable_irq (IFXMIPS_USB_OC_INT2);
|
|
|
+ #elif defined(CONFIG_IFXMIPS_AR9)
|
|
|
+ disable_irq (IFXMIPS_USB_OC_INT0);
|
|
|
+ disable_irq (IFXMIPS_USB_OC_INT2);
|
|
|
+ #elif defined(CONFIG_IFXMIPS_DANUBE)
|
|
|
+ disable_irq (IFXMIPS_USB_OC_INT);
|
|
|
+ #endif
|
|
|
+ disable_irq (pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+
|
|
|
+ IFX_MEI_RunArc (pDev);
|
|
|
+
|
|
|
+ MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready, 1000);
|
|
|
+
|
|
|
+ #ifdef CONFIG_IFXMIPS_AMAZON_SE
|
|
|
+ MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
|
|
|
+ MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
|
|
|
+ #elif defined(CONFIG_IFXMIPS_AMAZON_S)
|
|
|
+ MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
|
|
|
+ MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
|
|
|
+ #elif defined(CONFIG_IFXMIPS_DANUBE)
|
|
|
+ MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT);
|
|
|
+ #endif
|
|
|
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+
|
|
|
+ /* Re-enable irq */
|
|
|
+ enable_irq(pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+ *IFXMIPS_ICU_IM0_IER |= im0_register;
|
|
|
+ *IFXMIPS_ICU_IM2_IER |= im2_register;
|
|
|
+
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)->modem_ready != 1) {
|
|
|
+ IFX_MEI_EMSG ("Modem failed to be ready!\n");
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ } else {
|
|
|
+ IFX_MEI_DMSG("Modem is ready.\n");
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Get the page's data pointer
|
|
|
+ * This function caculats the data address from the firmware header.
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param Page The page number.
|
|
|
+ * \param data Data page or program page.
|
|
|
+ * \param MaxSize The maximum size to read.
|
|
|
+ * \param Buffer Pointer to data.
|
|
|
+ * \param Dest Pointer to the destination address.
|
|
|
+ * \return The number of bytes to read.
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static int
|
|
|
+IFX_MEI_GetPage (DSL_DEV_Device_t * pDev, u32 Page, u32 data,
|
|
|
+ u32 MaxSize, u32 * Buffer, u32 * Dest)
|
|
|
+{
|
|
|
+ u32 size;
|
|
|
+ u32 i;
|
|
|
+ u32 *p;
|
|
|
+ u32 idx, offset, nBar = 0;
|
|
|
+
|
|
|
+ if (Page > DSL_DEV_PRIVATE(pDev)->img_hdr->count)
|
|
|
+ return -2;
|
|
|
+ /*
|
|
|
+ ** Get program or data size, depending on "data" flag
|
|
|
+ */
|
|
|
+ size = (data == GET_DATA) ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_size) :
|
|
|
+ (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_size);
|
|
|
+ size &= BOOT_FLAG_MASK; // Clear boot bit!
|
|
|
+ if (size > MaxSize)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if (size == 0)
|
|
|
+ return 0;
|
|
|
+ /*
|
|
|
+ ** Get program or data offset, depending on "data" flag
|
|
|
+ */
|
|
|
+ i = data ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_offset) :
|
|
|
+ (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_offset);
|
|
|
+
|
|
|
+ /*
|
|
|
+ ** Copy data/program to buffer
|
|
|
+ */
|
|
|
+
|
|
|
+ idx = i / SDRAM_SEGMENT_SIZE;
|
|
|
+ offset = i % SDRAM_SEGMENT_SIZE;
|
|
|
+ p = (u32 *) ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address + offset);
|
|
|
+
|
|
|
+ for (i = 0; i < size; i++) {
|
|
|
+ if (offset + i * 4 - (nBar * SDRAM_SEGMENT_SIZE) >= SDRAM_SEGMENT_SIZE) {
|
|
|
+ idx++;
|
|
|
+ nBar++;
|
|
|
+ p = (u32 *) ((u8 *) KSEG1ADDR ((u32)DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address));
|
|
|
+ }
|
|
|
+ Buffer[i] = *p++;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ ** Pass back data/program destination address
|
|
|
+ */
|
|
|
+ *Dest = data ? (DSL_DEV_PRIVATE(pDev)-> img_hdr->page[Page].d_dest) :
|
|
|
+ (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_dest);
|
|
|
+
|
|
|
+ return size;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Free the memory for ARC firmware
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param type Free all memory or free the unused memory after showtime
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+const char *free_str[4] = {"Invalid", "Free_Reload", "Free_Showtime", "Free_All"};
|
|
|
+static int
|
|
|
+IFX_MEI_DFEMemoryFree (DSL_DEV_Device_t * pDev, int type)
|
|
|
+{
|
|
|
+ int idx = 0;
|
|
|
+ smmu_mem_info_t *adsl_mem_info =
|
|
|
+ DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
|
|
|
+
|
|
|
+ for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) {
|
|
|
+ if (type == FREE_ALL ||adsl_mem_info[idx].type == type) {
|
|
|
+ if (adsl_mem_info[idx].size > 0) {
|
|
|
+ IFX_MEI_DMSG ("Freeing memory %p (%s)\n", adsl_mem_info[idx].org_address, free_str[adsl_mem_info[idx].type]);
|
|
|
+ if ( idx == XDATA_REGISTER ) {
|
|
|
+ g_xdata_addr = NULL;
|
|
|
+ if ( ifx_mei_atm_showtime_exit )
|
|
|
+ ifx_mei_atm_showtime_exit();
|
|
|
+ }
|
|
|
+ kfree (adsl_mem_info[idx].org_address);
|
|
|
+ adsl_mem_info[idx].org_address = 0;
|
|
|
+ adsl_mem_info[idx].address = 0;
|
|
|
+ adsl_mem_info[idx].size = 0;
|
|
|
+ adsl_mem_info[idx].type = 0;
|
|
|
+ adsl_mem_info[idx].nCopy = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(mei_arc_swap_buff != NULL){
|
|
|
+ printk("free %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff);
|
|
|
+ kfree(mei_arc_swap_buff);
|
|
|
+ mei_arc_swap_buff=NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+static int
|
|
|
+IFX_MEI_DFEMemoryAlloc (DSL_DEV_Device_t * pDev, long size)
|
|
|
+{
|
|
|
+ unsigned long mem_ptr;
|
|
|
+ char *org_mem_ptr = NULL;
|
|
|
+ int idx = 0;
|
|
|
+ long total_size = 0;
|
|
|
+ int err = 0;
|
|
|
+ smmu_mem_info_t *adsl_mem_info =
|
|
|
+ ((ifx_mei_device_private_t *) pDev->pPriv)->adsl_mem_info;
|
|
|
+// DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
|
|
|
+ int allocate_size = SDRAM_SEGMENT_SIZE;
|
|
|
+
|
|
|
+ printk(KERN_INFO "[%s %d]: image_size = %ld\n", __func__, __LINE__, size);
|
|
|
+ // Alloc Swap Pages
|
|
|
+ for (idx = 0; size > 0 && idx < MAX_BAR_REGISTERS; idx++) {
|
|
|
+ // skip bar15 for XDATA usage.
|
|
|
+#ifndef CONFIG_IFXMIPS_MEI_FW_LOOPBACK
|
|
|
+ if (idx == XDATA_REGISTER)
|
|
|
+ continue;
|
|
|
+#endif
|
|
|
+#if 0
|
|
|
+ if (size < SDRAM_SEGMENT_SIZE) {
|
|
|
+ allocate_size = size;
|
|
|
+ if (allocate_size < 1024)
|
|
|
+ allocate_size = 1024;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ if (idx == (MAX_BAR_REGISTERS - 1))
|
|
|
+ allocate_size = size;
|
|
|
+ else
|
|
|
+ allocate_size = SDRAM_SEGMENT_SIZE;
|
|
|
+ org_mem_ptr = kmalloc (allocate_size + 1024, GFP_KERNEL);
|
|
|
+ if (org_mem_ptr == NULL) {
|
|
|
+ IFX_MEI_EMSG ("%d: kmalloc %d bytes memory fail!\n", idx, allocate_size);
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto allocate_error;
|
|
|
+ }
|
|
|
+ mem_ptr = (unsigned long) (org_mem_ptr + 1023) & ~(1024 -1);
|
|
|
+ adsl_mem_info[idx].address = (char *) mem_ptr;
|
|
|
+ adsl_mem_info[idx].org_address = org_mem_ptr;
|
|
|
+ adsl_mem_info[idx].size = allocate_size;
|
|
|
+ size -= allocate_size;
|
|
|
+ total_size += allocate_size;
|
|
|
+ }
|
|
|
+ if (size > 0) {
|
|
|
+ IFX_MEI_EMSG ("Image size is too large!\n");
|
|
|
+ err = -EFBIG;
|
|
|
+ goto allocate_error;
|
|
|
+ }
|
|
|
+ err = idx;
|
|
|
+ return err;
|
|
|
+
|
|
|
+ allocate_error:
|
|
|
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Program the BAR registers
|
|
|
+ *
|
|
|
+ * \param pDev the device pointer
|
|
|
+ * \param nTotalBar The number of bar to program.
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static int
|
|
|
+IFX_MEI_BarUpdate (DSL_DEV_Device_t * pDev, int nTotalBar)
|
|
|
+{
|
|
|
+ int idx = 0;
|
|
|
+ smmu_mem_info_t *adsl_mem_info =
|
|
|
+ DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
|
|
|
+
|
|
|
+ for (idx = 0; idx < nTotalBar; idx++) {
|
|
|
+ //skip XDATA register
|
|
|
+ if (idx == XDATA_REGISTER)
|
|
|
+ continue;
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4,
|
|
|
+ (((uint32_t) adsl_mem_info[idx].address) & 0x0FFFFFFF));
|
|
|
+ }
|
|
|
+ for (idx = nTotalBar; idx < MAX_BAR_REGISTERS; idx++) {
|
|
|
+ if (idx == XDATA_REGISTER)
|
|
|
+ continue;
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4,
|
|
|
+ (((uint32_t)adsl_mem_info[nTotalBar - 1].address) & 0x0FFFFFFF));
|
|
|
+ /* These are for /proc/danube_mei/meminfo purpose */
|
|
|
+ adsl_mem_info[idx].address = adsl_mem_info[nTotalBar - 1].address;
|
|
|
+ adsl_mem_info[idx].org_address = adsl_mem_info[nTotalBar - 1].org_address;
|
|
|
+ adsl_mem_info[idx].size = 0; /* Prevent it from being freed */
|
|
|
+ }
|
|
|
+
|
|
|
+ g_xdata_addr = adsl_mem_info[XDATA_REGISTER].address;
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + XDATA_REGISTER * 4,
|
|
|
+ (((uint32_t) adsl_mem_info [XDATA_REGISTER].address) & 0x0FFFFFFF));
|
|
|
+ // update MEI_XDATA_BASE_SH
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH,
|
|
|
+ ((unsigned long)adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF);
|
|
|
+
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/* This copies the firmware from secondary storage to 64k memory segment in SDRAM */
|
|
|
+DSL_DEV_MeiError_t
|
|
|
+DSL_BSP_FWDownload (DSL_DEV_Device_t * pDev, const char *buf,
|
|
|
+ unsigned long size, long *loff, long *current_offset)
|
|
|
+{
|
|
|
+ ARC_IMG_HDR img_hdr_tmp;
|
|
|
+ smmu_mem_info_t *adsl_mem_info = DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
|
|
|
+
|
|
|
+ size_t nRead = 0, nCopy = 0;
|
|
|
+ char *mem_ptr;
|
|
|
+ ssize_t retval = -ENOMEM;
|
|
|
+ int idx = 0;
|
|
|
+
|
|
|
+ printk("\n%s\n", __func__);
|
|
|
+
|
|
|
+ if (*loff == 0) {
|
|
|
+ if (size < sizeof (img_hdr_tmp)) {
|
|
|
+ IFX_MEI_EMSG ("Firmware size is too small!\n");
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+ copy_from_user ((char *) &img_hdr_tmp, buf, sizeof (img_hdr_tmp));
|
|
|
+ // header of image_size and crc are not included.
|
|
|
+ DSL_DEV_PRIVATE(pDev)->image_size = le32_to_cpu (img_hdr_tmp.size) + 8;
|
|
|
+
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)->image_size > 1024 * 1024) {
|
|
|
+ IFX_MEI_EMSG ("Firmware size is too large!\n");
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+ // check if arc is halt
|
|
|
+ IFX_MEI_ResetARC (pDev);
|
|
|
+ IFX_MEI_HaltArc (pDev);
|
|
|
+
|
|
|
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL); //free all
|
|
|
+
|
|
|
+ retval = IFX_MEI_DFEMemoryAlloc (pDev, DSL_DEV_PRIVATE(pDev)->image_size);
|
|
|
+ if (retval < 0) {
|
|
|
+ IFX_MEI_EMSG ("Error: No memory space left.\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ for (idx = 0; idx < retval; idx++) {
|
|
|
+ //skip XDATA register
|
|
|
+ if (idx == XDATA_REGISTER)
|
|
|
+ continue;
|
|
|
+ if (idx * SDRAM_SEGMENT_SIZE < le32_to_cpu (img_hdr_tmp.page[0].p_offset))
|
|
|
+ adsl_mem_info[idx].type = FREE_RELOAD;
|
|
|
+ else
|
|
|
+ adsl_mem_info[idx].type = FREE_SHOWTIME;
|
|
|
+ }
|
|
|
+ DSL_DEV_PRIVATE(pDev)->nBar = retval;
|
|
|
+
|
|
|
+ DSL_DEV_PRIVATE(pDev)->img_hdr =
|
|
|
+ (ARC_IMG_HDR *) adsl_mem_info[0].address;
|
|
|
+
|
|
|
+ adsl_mem_info[XDATA_REGISTER].org_address = kmalloc (SDRAM_SEGMENT_SIZE + 1024, GFP_KERNEL);
|
|
|
+ adsl_mem_info[XDATA_REGISTER].address =
|
|
|
+ (char *) ((unsigned long) (adsl_mem_info[XDATA_REGISTER].org_address + 1023) & 0xFFFFFC00);
|
|
|
+
|
|
|
+ adsl_mem_info[XDATA_REGISTER].size = SDRAM_SEGMENT_SIZE;
|
|
|
+
|
|
|
+ if (adsl_mem_info[XDATA_REGISTER].address == NULL) {
|
|
|
+ IFX_MEI_EMSG ("kmalloc memory fail!\n");
|
|
|
+ retval = -ENOMEM;
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ adsl_mem_info[XDATA_REGISTER].type = FREE_RELOAD;
|
|
|
+ printk(KERN_INFO "[%s %d] -> IFX_MEI_BarUpdate()\n", __func__, __LINE__);
|
|
|
+ IFX_MEI_BarUpdate (pDev, (DSL_DEV_PRIVATE(pDev)->nBar));
|
|
|
+ }
|
|
|
+ else if (DSL_DEV_PRIVATE(pDev)-> image_size == 0) {
|
|
|
+ IFX_MEI_EMSG ("Error: Firmware size=0! \n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ nRead = 0;
|
|
|
+ while (nRead < size) {
|
|
|
+ long offset = ((long) (*loff) + nRead) % SDRAM_SEGMENT_SIZE;
|
|
|
+ idx = (((long) (*loff)) + nRead) / SDRAM_SEGMENT_SIZE;
|
|
|
+ mem_ptr = (char *) KSEG1ADDR ((unsigned long) (adsl_mem_info[idx].address) + offset);
|
|
|
+ if ((size - nRead + offset) > SDRAM_SEGMENT_SIZE)
|
|
|
+ nCopy = SDRAM_SEGMENT_SIZE - offset;
|
|
|
+ else
|
|
|
+ nCopy = size - nRead;
|
|
|
+ copy_from_user (mem_ptr, buf + nRead, nCopy);
|
|
|
+ for (offset = 0; offset < (nCopy / 4); offset++) {
|
|
|
+ ((unsigned long *) mem_ptr)[offset] = le32_to_cpu (((unsigned long *) mem_ptr)[offset]);
|
|
|
+ }
|
|
|
+ nRead += nCopy;
|
|
|
+ adsl_mem_info[idx].nCopy += nCopy;
|
|
|
+ }
|
|
|
+
|
|
|
+ *loff += size;
|
|
|
+ *current_offset = size;
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+error:
|
|
|
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+}
|
|
|
+/*
|
|
|
+ * Register a callback event.
|
|
|
+ * Return:
|
|
|
+ * -1 if the event already has a callback function registered.
|
|
|
+ * 0 success
|
|
|
+ */
|
|
|
+int DSL_BSP_EventCBRegister(DSL_BSP_EventCallBack_t *p)
|
|
|
+{
|
|
|
+ if (!p) {
|
|
|
+ IFX_MEI_EMSG("Invalid parameter!\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) {
|
|
|
+ IFX_MEI_EMSG("Invalid Event %d\n", p->event);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (dsl_bsp_event_callback[p->event].function) {
|
|
|
+ IFX_MEI_EMSG("Event %d already has a callback function registered!\n", p->event);
|
|
|
+ return -1;
|
|
|
+ } else {
|
|
|
+ dsl_bsp_event_callback[p->event].function = p->function;
|
|
|
+ dsl_bsp_event_callback[p->event].event = p->event;
|
|
|
+ dsl_bsp_event_callback[p->event].pData = p->pData;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+int DSL_BSP_EventCBUnregister(DSL_BSP_EventCallBack_t *p)
|
|
|
+{
|
|
|
+ if (!p) {
|
|
|
+ IFX_MEI_EMSG("Invalid parameter!\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) {
|
|
|
+ IFX_MEI_EMSG("Invalid Event %d\n", p->event);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (dsl_bsp_event_callback[p->event].function) {
|
|
|
+ IFX_MEI_EMSG("Unregistering Event %d...\n", p->event);
|
|
|
+ dsl_bsp_event_callback[p->event].function = NULL;
|
|
|
+ dsl_bsp_event_callback[p->event].pData = NULL;
|
|
|
+ } else {
|
|
|
+ IFX_MEI_EMSG("Event %d is not registered!\n", p->event);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * MEI Dying Gasp interrupt handler
|
|
|
+ *
|
|
|
+ * \param int1
|
|
|
+ * \param void0
|
|
|
+ * \param regs Pointer to the structure of danube mips registers
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static irqreturn_t IFX_MEI_Dying_Gasp_IrqHandle (int int1, void *void0)
|
|
|
+{
|
|
|
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
|
|
|
+ DSL_BSP_CB_Type_t event;
|
|
|
+
|
|
|
+ if (pDev == NULL)
|
|
|
+ IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n");
|
|
|
+
|
|
|
+#ifndef CONFIG_SMP
|
|
|
+ disable_irq (pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+#else
|
|
|
+ disable_irq_nosync(pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+#endif
|
|
|
+ event = DSL_BSP_CB_DYING_GASP;
|
|
|
+
|
|
|
+ if (dsl_bsp_event_callback[event].function)
|
|
|
+ (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
|
|
|
+
|
|
|
+#ifdef CONFIG_USE_EMULATOR
|
|
|
+ IFX_MEI_EMSG("Dying Gasp! Shutting Down... (Work around for Amazon-S Venus emulator)\n");
|
|
|
+#else
|
|
|
+ IFX_MEI_EMSG("Dying Gasp! Shutting Down...\n");
|
|
|
+// kill_proc (1, SIGINT, 1); /* Ask init to reboot us */
|
|
|
+#endif
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
+extern void ifx_usb_enable_afe_oc(void);
|
|
|
+
|
|
|
+/**
|
|
|
+ * MEI interrupt handler
|
|
|
+ *
|
|
|
+ * \param int1
|
|
|
+ * \param void0
|
|
|
+ * \param regs Pointer to the structure of danube mips registers
|
|
|
+ * \ingroup Internal
|
|
|
+ */
|
|
|
+static irqreturn_t IFX_MEI_IrqHandle (int int1, void *void0)
|
|
|
+{
|
|
|
+ u32 scratch;
|
|
|
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
|
|
|
+#if defined(CONFIG_IFXMIPS_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST)
|
|
|
+ dfe_loopback_irq_handler (pDev);
|
|
|
+ return IRQ_HANDLED;
|
|
|
+#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
|
|
|
+ DSL_BSP_CB_Type_t event;
|
|
|
+
|
|
|
+ if (pDev == NULL)
|
|
|
+ IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n");
|
|
|
+
|
|
|
+ IFX_MEI_DebugRead (pDev, ARC_MEI_MAILBOXR, &scratch, 1);
|
|
|
+ if (scratch & OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK) {
|
|
|
+ IFX_MEI_EMSG("Receive Code Swap Request interrupt!!!\n");
|
|
|
+ return IRQ_HANDLED;
|
|
|
+ }
|
|
|
+ else if (scratch & OMB_CLEAREOC_INTERRUPT_CODE) {
|
|
|
+ // clear eoc message interrupt
|
|
|
+ IFX_MEI_DMSG("OMB_CLEAREOC_INTERRUPT_CODE\n");
|
|
|
+ event = DSL_BSP_CB_CEOC_IRQ;
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
|
|
|
+ if (dsl_bsp_event_callback[event].function)
|
|
|
+ (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
|
|
|
+ } else if (scratch & OMB_REBOOT_INTERRUPT_CODE) {
|
|
|
+ // Reboot
|
|
|
+ IFX_MEI_DMSG("OMB_REBOOT_INTERRUPT_CODE\n");
|
|
|
+ event = DSL_BSP_CB_FIRMWARE_REBOOT;
|
|
|
+
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
|
|
|
+
|
|
|
+ if (dsl_bsp_event_callback[event].function)
|
|
|
+ (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
|
|
|
+ } else { // normal message
|
|
|
+ IFX_MEI_MailboxRead (pDev, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH);
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)-> cmv_waiting == 1) {
|
|
|
+ DSL_DEV_PRIVATE(pDev)-> arcmsgav = 1;
|
|
|
+ DSL_DEV_PRIVATE(pDev)-> cmv_waiting = 0;
|
|
|
+#if !defined(BSP_PORT_RTEMS)
|
|
|
+ MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ DSL_DEV_PRIVATE(pDev)-> modem_ready_cnt++;
|
|
|
+ memcpy ((char *) DSL_DEV_PRIVATE(pDev)->Recent_indicator,
|
|
|
+ (char *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2);
|
|
|
+ if (((DSL_DEV_PRIVATE(pDev)->CMV_RxMsg[0] & 0xff0) >> 4) == D2H_AUTONOMOUS_MODEM_READY_MSG) {
|
|
|
+ //check ARC ready message
|
|
|
+ IFX_MEI_DMSG ("Got MODEM_READY_MSG\n");
|
|
|
+ DSL_DEV_PRIVATE(pDev)->modem_ready = 1;
|
|
|
+ MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+DSL_BSP_ATMLedCBRegister (int (*ifx_adsl_ledcallback) (void))
|
|
|
+{
|
|
|
+ g_adsl_ledcallback = ifx_adsl_ledcallback;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+DSL_BSP_ATMLedCBUnregister (int (*ifx_adsl_ledcallback) (void))
|
|
|
+{
|
|
|
+ g_adsl_ledcallback = adsl_dummy_ledcallback;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#if 0
|
|
|
+int
|
|
|
+DSL_BSP_EventCBRegister (int (*ifx_adsl_callback)
|
|
|
+ (DSL_BSP_CB_Event_t * param))
|
|
|
+{
|
|
|
+ int error = 0;
|
|
|
+
|
|
|
+ if (DSL_EventCB == NULL) {
|
|
|
+ DSL_EventCB = ifx_adsl_callback;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ error = -EIO;
|
|
|
+ }
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+DSL_BSP_EventCBUnregister (int (*ifx_adsl_callback)
|
|
|
+ (DSL_BSP_CB_Event_t * param))
|
|
|
+{
|
|
|
+ int error = 0;
|
|
|
+
|
|
|
+ if (DSL_EventCB == ifx_adsl_callback) {
|
|
|
+ DSL_EventCB = NULL;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ error = -EIO;
|
|
|
+ }
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+DSL_BSP_GetEventCB (int (**ifx_adsl_callback)
|
|
|
+ (DSL_BSP_CB_Event_t * param))
|
|
|
+{
|
|
|
+ *ifx_adsl_callback = DSL_EventCB;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef CONFIG_IFXMIPS_MEI_FW_LOOPBACK
|
|
|
+#define mte_reg_base (0x4800*4+0x20000)
|
|
|
+
|
|
|
+/* Iridia Registers Address Constants */
|
|
|
+#define MTE_Reg(r) (int)(mte_reg_base + (r*4))
|
|
|
+
|
|
|
+#define IT_AMODE MTE_Reg(0x0004)
|
|
|
+
|
|
|
+#define TIMER_DELAY (1024)
|
|
|
+#define BC0_BYTES (32)
|
|
|
+#define BC1_BYTES (30)
|
|
|
+#define NUM_MB (12)
|
|
|
+#define TIMEOUT_VALUE 2000
|
|
|
+
|
|
|
+static void
|
|
|
+BFMWait (u32 cycle)
|
|
|
+{
|
|
|
+ u32 i;
|
|
|
+ for (i = 0; i < cycle; i++);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+WriteRegLong (u32 addr, u32 data)
|
|
|
+{
|
|
|
+ //*((volatile u32 *)(addr)) = data;
|
|
|
+ IFX_MEI_WRITE_REGISTER_L (data, addr);
|
|
|
+}
|
|
|
+
|
|
|
+static u32
|
|
|
+ReadRegLong (u32 addr)
|
|
|
+{
|
|
|
+ // u32 rd_val;
|
|
|
+ //rd_val = *((volatile u32 *)(addr));
|
|
|
+ // return rd_val;
|
|
|
+ return IFX_MEI_READ_REGISTER_L (addr);
|
|
|
+}
|
|
|
+
|
|
|
+/* This routine writes the mailbox with the data in an input array */
|
|
|
+static void
|
|
|
+WriteMbox (u32 * mboxarray, u32 size)
|
|
|
+{
|
|
|
+ IFX_MEI_DebugWrite (&dsl_devices[0], IMBOX_BASE, mboxarray, size);
|
|
|
+ printk ("write to %X\n", IMBOX_BASE);
|
|
|
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV);
|
|
|
+}
|
|
|
+
|
|
|
+/* This routine reads the output mailbox and places the results into an array */
|
|
|
+static void
|
|
|
+ReadMbox (u32 * mboxarray, u32 size)
|
|
|
+{
|
|
|
+ IFX_MEI_DebugRead (&dsl_devices[0], OMBOX_BASE, mboxarray, size);
|
|
|
+ printk ("read from %X\n", OMBOX_BASE);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+MEIWriteARCValue (u32 address, u32 value)
|
|
|
+{
|
|
|
+ u32 i, check = 0;
|
|
|
+
|
|
|
+ /* Write address register */
|
|
|
+ IFX_MEI_WRITE_REGISTER_L (address, ME_DBG_WR_AD + IFXMIPS_MEI_BASE_ADDR);
|
|
|
+
|
|
|
+ /* Write data register */
|
|
|
+ IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + IFXMIPS_MEI_BASE_ADDR);
|
|
|
+
|
|
|
+ /* wait until complete - timeout at 40 */
|
|
|
+ for (i = 0; i < 40; i++) {
|
|
|
+ check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + IFXMIPS_MEI_BASE_ADDR);
|
|
|
+
|
|
|
+ if ((check & ARC_TO_MEI_DBG_DONE))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* clear the flag */
|
|
|
+ IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + IFXMIPS_MEI_BASE_ADDR);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+arc_code_page_download (uint32_t arc_code_length, uint32_t * start_address)
|
|
|
+{
|
|
|
+ int count;
|
|
|
+
|
|
|
+ printk ("try to download pages,size=%d\n", arc_code_length);
|
|
|
+ IFX_MEI_ControlModeSet (&dsl_devices[0], MEI_MASTER_MODE);
|
|
|
+ IFX_MEI_HaltArc (&dsl_devices[0]);
|
|
|
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_AD, 0);
|
|
|
+ for (count = 0; count < arc_code_length; count++) {
|
|
|
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_DATA,
|
|
|
+ *(start_address + count));
|
|
|
+ }
|
|
|
+ IFX_MEI_ControlModeSet (&dsl_devices[0], JTAG_MASTER_MODE);
|
|
|
+}
|
|
|
+static int
|
|
|
+load_jump_table (unsigned long addr)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ uint32_t addr_le, addr_be;
|
|
|
+ uint32_t jump_table[32];
|
|
|
+
|
|
|
+ for (i = 0; i < 16; i++) {
|
|
|
+ addr_le = i * 8 + addr;
|
|
|
+ addr_be = ((addr_le >> 16) & 0xffff);
|
|
|
+ addr_be |= ((addr_le & 0xffff) << 16);
|
|
|
+ jump_table[i * 2 + 0] = 0x0f802020;
|
|
|
+ jump_table[i * 2 + 1] = addr_be;
|
|
|
+ //printk("jt %X %08X %08X\n",i,jump_table[i*2+0],jump_table[i*2+1]);
|
|
|
+ }
|
|
|
+ arc_code_page_download (32, &jump_table[0]);
|
|
|
+return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int got_int = 0;
|
|
|
+
|
|
|
+void
|
|
|
+dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev)
|
|
|
+{
|
|
|
+ uint32_t rd_mbox[10];
|
|
|
+
|
|
|
+ memset (&rd_mbox[0], 0, 10 * 4);
|
|
|
+ ReadMbox (&rd_mbox[0], 6);
|
|
|
+ if (rd_mbox[0] == 0x0) {
|
|
|
+ printk ("Get ARC_ACK\n");
|
|
|
+ got_int = 1;
|
|
|
+ }
|
|
|
+ else if (rd_mbox[0] == 0x5) {
|
|
|
+ printk ("Get ARC_BUSY\n");
|
|
|
+ got_int = 2;
|
|
|
+ }
|
|
|
+ else if (rd_mbox[0] == 0x3) {
|
|
|
+ printk ("Get ARC_EDONE\n");
|
|
|
+ if (rd_mbox[1] == 0x0) {
|
|
|
+ got_int = 3;
|
|
|
+ printk ("Get E_MEMTEST\n");
|
|
|
+ if (rd_mbox[2] != 0x1) {
|
|
|
+ got_int = 4;
|
|
|
+ printk ("Get Result %X\n", rd_mbox[2]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_STAT,
|
|
|
+ ARC_TO_MEI_DBG_DONE);
|
|
|
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]);
|
|
|
+ disable_irq (pDev->nIrq[IFX_DFEIR]);
|
|
|
+ //got_int = 1;
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+wait_mem_test_result (void)
|
|
|
+{
|
|
|
+ uint32_t mbox[5];
|
|
|
+ mbox[0] = 0;
|
|
|
+
|
|
|
+ printk ("Waiting Starting\n");
|
|
|
+ while (mbox[0] == 0) {
|
|
|
+ ReadMbox (&mbox[0], 5);
|
|
|
+ }
|
|
|
+ printk ("Try to get mem test result.\n");
|
|
|
+ ReadMbox (&mbox[0], 5);
|
|
|
+ if (mbox[0] == 0xA) {
|
|
|
+ printk ("Success.\n");
|
|
|
+ }
|
|
|
+ else if (mbox[0] == 0xA) {
|
|
|
+ printk ("Fail,address %X,except data %X,receive data %X\n",
|
|
|
+ mbox[1], mbox[2], mbox[3]);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ printk ("Fail\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+arc_ping_testing (DSL_DEV_Device_t *pDev)
|
|
|
+{
|
|
|
+#define MEI_PING 0x00000001
|
|
|
+ uint32_t wr_mbox[10], rd_mbox[10];
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < 10; i++) {
|
|
|
+ wr_mbox[i] = 0;
|
|
|
+ rd_mbox[i] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ printk ("send ping msg\n");
|
|
|
+ wr_mbox[0] = MEI_PING;
|
|
|
+ WriteMbox (&wr_mbox[0], 10);
|
|
|
+
|
|
|
+ while (got_int == 0) {
|
|
|
+ MEI_WAIT (100);
|
|
|
+ }
|
|
|
+
|
|
|
+ printk ("send start event\n");
|
|
|
+ got_int = 0;
|
|
|
+
|
|
|
+ wr_mbox[0] = 0x4;
|
|
|
+ wr_mbox[1] = 0;
|
|
|
+ wr_mbox[2] = 0;
|
|
|
+ wr_mbox[3] = (uint32_t) 0xf5acc307e;
|
|
|
+ wr_mbox[4] = 5;
|
|
|
+ wr_mbox[5] = 2;
|
|
|
+ wr_mbox[6] = 0x1c000;
|
|
|
+ wr_mbox[7] = 64;
|
|
|
+ wr_mbox[8] = 0;
|
|
|
+ wr_mbox[9] = 0;
|
|
|
+ WriteMbox (&wr_mbox[0], 10);
|
|
|
+ DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]);
|
|
|
+ //printk("IFX_MEI_MailboxWrite ret=%d\n",i);
|
|
|
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0],
|
|
|
+ (u32) ME_ME2ARC_INT,
|
|
|
+ MEI_TO_ARC_MSGAV);
|
|
|
+ printk ("sleeping\n");
|
|
|
+ while (1) {
|
|
|
+ if (got_int > 0) {
|
|
|
+
|
|
|
+ if (got_int > 3)
|
|
|
+ printk ("got_int >>>> 3\n");
|
|
|
+ else
|
|
|
+ printk ("got int = %d\n", got_int);
|
|
|
+ got_int = 0;
|
|
|
+ //schedule();
|
|
|
+ DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]);
|
|
|
+ }
|
|
|
+ //mbox_read(&rd_mbox[0],6);
|
|
|
+ MEI_WAIT (100);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static DSL_DEV_MeiError_t
|
|
|
+DFE_Loopback_Test (void)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+ u32 arc_debug_data = 0, temp;
|
|
|
+ DSL_DEV_Device_t *pDev = &dsl_devices[0];
|
|
|
+ uint32_t wr_mbox[10];
|
|
|
+
|
|
|
+ IFX_MEI_ResetARC (pDev);
|
|
|
+ // start the clock
|
|
|
+ arc_debug_data = ACL_CLK_MODE_ENABLE;
|
|
|
+ IFX_MEI_DebugWrite (pDev, CRI_CCR0, &arc_debug_data, 1);
|
|
|
+
|
|
|
+#if defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK)
|
|
|
+ // WriteARCreg(AUX_XMEM_LTEST,0);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+#define AUX_XMEM_LTEST 0x128
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XMEM_LTEST, 0);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+
|
|
|
+ // WriteARCreg(AUX_XDMA_GAP,0);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+#define AUX_XDMA_GAP 0x114
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XDMA_GAP, 0);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+ temp = 0;
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
|
|
|
+ (u32) ME_XDATA_BASE_SH + IFXMIPS_MEI_BASE_ADDR, temp);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+
|
|
|
+ i = IFX_MEI_DFEMemoryAlloc (pDev, SDRAM_SEGMENT_SIZE * 16);
|
|
|
+ if (i >= 0) {
|
|
|
+ int idx;
|
|
|
+
|
|
|
+ for (idx = 0; idx < i; idx++) {
|
|
|
+ DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].type = FREE_RELOAD;
|
|
|
+ IFX_MEI_WRITE_REGISTER_L ((((uint32_t) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address) & 0x0fffffff),
|
|
|
+ IFXMIPS_MEI_BASE_ADDR + ME_XMEM_BAR_BASE + idx * 4);
|
|
|
+ printk ("bar%d(%X)=%X\n", idx,
|
|
|
+ IFXMIPS_MEI_BASE_ADDR + ME_XMEM_BAR_BASE +
|
|
|
+ idx * 4, (((uint32_t)
|
|
|
+ ((ifx_mei_device_private_t *)
|
|
|
+ pDev->pPriv)->adsl_mem_info[idx].
|
|
|
+ address) & 0x0fffffff));
|
|
|
+ memset ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address, 0, SDRAM_SEGMENT_SIZE);
|
|
|
+ }
|
|
|
+
|
|
|
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH,
|
|
|
+ ((unsigned long) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ IFX_MEI_EMSG ("cannot load image: no memory\n");
|
|
|
+ return DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ }
|
|
|
+ //WriteARCreg(AUX_IC_CTRL,2);
|
|
|
+ printk(KERN_INFO "[%s %s %d]: Setting MEI_MASTER_MODE..\n", __FILE__, __func__, __LINE__);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
|
|
+#define AUX_IC_CTRL 0x11
|
|
|
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
|
|
|
+ AUX_IC_CTRL, 2);
|
|
|
+ printk(KERN_INFO "[%s %s %d]: Setting JTAG_MASTER_MODE..\n", __FILE__, __func__, __LINE__);
|
|
|
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
|
|
+
|
|
|
+ printk(KERN_INFO "[%s %s %d]: Halting ARC...\n", __FILE__, __func__, __LINE__);
|
|
|
+ IFX_MEI_HaltArc (&dsl_devices[0]);
|
|
|
+
|
|
|
+#ifdef DFE_PING_TEST
|
|
|
+
|
|
|
+ printk ("ping test image size=%d\n", sizeof (arc_ahb_access_code));
|
|
|
+ memcpy ((u8 *) (DSL_DEV_PRIVATE(pDev)->
|
|
|
+ adsl_mem_info[0].address + 0x1004),
|
|
|
+ &arc_ahb_access_code[0], sizeof (arc_ahb_access_code));
|
|
|
+ load_jump_table (0x80000 + 0x1004);
|
|
|
+
|
|
|
+#endif //DFE_PING_TEST
|
|
|
+
|
|
|
+ printk ("ARC ping test code download complete\n");
|
|
|
+#endif //defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK)
|
|
|
+#ifdef DFE_MEM_TEST
|
|
|
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_MASK, MSGAV_EN);
|
|
|
+
|
|
|
+ arc_code_page_download (1537, &code_array[0]);
|
|
|
+ printk ("ARC mem test code download complete\n");
|
|
|
+#endif //DFE_MEM_TEST
|
|
|
+#ifdef DFE_ATM_LOOPBACK
|
|
|
+ arc_debug_data = 0xf;
|
|
|
+ arc_code_page_download (sizeof(code_array) / sizeof(*code_array), &code_array[0]);
|
|
|
+ wr_mbox[0] = 0; //TIMER_DELAY - org: 1024
|
|
|
+ wr_mbox[1] = 0; //TXFB_START0
|
|
|
+ wr_mbox[2] = 0x7f; //TXFB_END0 - org: 49
|
|
|
+ wr_mbox[3] = 0x80; //TXFB_START1 - org: 80
|
|
|
+ wr_mbox[4] = 0xff; //TXFB_END1 - org: 109
|
|
|
+ wr_mbox[5] = 0x100; //RXFB_START0 - org: 0
|
|
|
+ wr_mbox[6] = 0x17f; //RXFB_END0 - org: 49
|
|
|
+ wr_mbox[7] = 0x180; //RXFB_START1 - org: 256
|
|
|
+ wr_mbox[8] = 0x1ff; //RXFB_END1 - org: 315
|
|
|
+ WriteMbox (&wr_mbox[0], 9);
|
|
|
+ // Start Iridia IT_AMODE (in dmp access) why is it required?
|
|
|
+ IFX_MEI_DebugWrite (&dsl_devices[0], 0x32010, &arc_debug_data, 1);
|
|
|
+#endif //DFE_ATM_LOOPBACK
|
|
|
+ IFX_MEI_IRQEnable (pDev);
|
|
|
+ printk(KERN_INFO "[%s %s %d]: run ARC...\n", __FILE__, __func__, __LINE__);
|
|
|
+ IFX_MEI_RunArc (&dsl_devices[0]);
|
|
|
+
|
|
|
+#ifdef DFE_PING_TEST
|
|
|
+ arc_ping_testing (pDev);
|
|
|
+#endif //DFE_PING_TEST
|
|
|
+#ifdef DFE_MEM_TEST
|
|
|
+ wait_mem_test_result ();
|
|
|
+#endif //DFE_MEM_TEST
|
|
|
+
|
|
|
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
|
|
|
+ return DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_InitDevNode (int num)
|
|
|
+{
|
|
|
+ if (num == 0) {
|
|
|
+ if ((dev_major = register_chrdev (dev_major, IFX_MEI_DEVNAME, &bsp_mei_operations)) < 0) {
|
|
|
+ IFX_MEI_EMSG ("register_chrdev(%d %s) failed!\n", dev_major, IFX_MEI_DEVNAME);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_CleanUpDevNode (int num)
|
|
|
+{
|
|
|
+ if (num == 0)
|
|
|
+ unregister_chrdev (dev_major, MEI_DIRNAME);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_InitDevice (int num)
|
|
|
+{
|
|
|
+ DSL_DEV_Device_t *pDev;
|
|
|
+ u32 temp;
|
|
|
+ pDev = &dsl_devices[num];
|
|
|
+ if (pDev == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+ pDev->pPriv = &sDanube_Mei_Private[num];
|
|
|
+ memset (pDev->pPriv, 0, sizeof (ifx_mei_device_private_t));
|
|
|
+
|
|
|
+ memset (&DSL_DEV_PRIVATE(pDev)->
|
|
|
+ adsl_mem_info[0], 0,
|
|
|
+ sizeof (smmu_mem_info_t) * MAX_BAR_REGISTERS);
|
|
|
+
|
|
|
+ if (num == 0) {
|
|
|
+ pDev->nIrq[IFX_DFEIR] = IFXMIPS_MEI_INT;
|
|
|
+ pDev->nIrq[IFX_DYING_GASP] = IFXMIPS_MEI_DYING_GASP_INT;
|
|
|
+ pDev->base_address = IFXMIPS_MEI_BASE_ADDR;
|
|
|
+
|
|
|
+ /* Power up MEI */
|
|
|
+#ifdef CONFIG_IFXMIPS_AMAZON_SE
|
|
|
+ *IFXMIPS_PMU_PWDCR &= ~(1 << 9); // enable dsl
|
|
|
+ *IFXMIPS_PMU_PWDCR &= ~(1 << 15); // enable AHB base
|
|
|
+#else
|
|
|
+ temp = ifxmips_r32(IFXMIPS_PMU_PWDCR);
|
|
|
+ temp &= 0xffff7dbe;
|
|
|
+ ifxmips_w32(temp, IFXMIPS_PMU_PWDCR);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ pDev->nInUse = 0;
|
|
|
+ DSL_DEV_PRIVATE(pDev)->modem_ready = 0;
|
|
|
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
|
|
|
+
|
|
|
+ MEI_INIT_WAKELIST ("arcq", DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav); // for ARCMSGAV
|
|
|
+ MEI_INIT_WAKELIST ("arcr", DSL_DEV_PRIVATE(pDev)->wait_queue_modemready); // for arc modem ready
|
|
|
+
|
|
|
+ MEI_MUTEX_INIT (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema, 1); // semaphore initialization, mutex
|
|
|
+#if 0
|
|
|
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]);
|
|
|
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+#endif
|
|
|
+ if (request_irq (pDev->nIrq[IFX_DFEIR], IFX_MEI_IrqHandle, 0, "DFEIR", pDev) != 0) {
|
|
|
+ IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DFEIR]);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (request_irq (pDev->nIrq[IFX_DYING_GASP], IFX_MEI_Dying_Gasp_IrqHandle, 0, "DYING_GASP", pDev) != 0) {
|
|
|
+ IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+// IFX_MEI_DMSG("Device %d initialized. IER %#x\n", num, bsp_get_irq_ier(pDev->nIrq[IFX_DYING_GASP]));
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_ExitDevice (int num)
|
|
|
+{
|
|
|
+ DSL_DEV_Device_t *pDev;
|
|
|
+ pDev = &dsl_devices[num];
|
|
|
+
|
|
|
+ if (pDev == NULL)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ disable_irq (pDev->nIrq[IFX_DFEIR]);
|
|
|
+ disable_irq (pDev->nIrq[IFX_DYING_GASP]);
|
|
|
+
|
|
|
+ free_irq(pDev->nIrq[IFX_DFEIR], pDev);
|
|
|
+ free_irq(pDev->nIrq[IFX_DYING_GASP], pDev);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static DSL_DEV_Device_t *
|
|
|
+IFX_BSP_HandleGet (int maj, int num)
|
|
|
+{
|
|
|
+ if (num > BSP_MAX_DEVICES)
|
|
|
+ return NULL;
|
|
|
+ return &dsl_devices[num];
|
|
|
+}
|
|
|
+
|
|
|
+DSL_DEV_Device_t *
|
|
|
+DSL_BSP_DriverHandleGet (int maj, int num)
|
|
|
+{
|
|
|
+ DSL_DEV_Device_t *pDev;
|
|
|
+
|
|
|
+ if (num > BSP_MAX_DEVICES)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ pDev = &dsl_devices[num];
|
|
|
+ if (!try_module_get(pDev->owner))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ pDev->nInUse++;
|
|
|
+ return pDev;
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+DSL_BSP_DriverHandleDelete (DSL_DEV_Device_t * nHandle)
|
|
|
+{
|
|
|
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) nHandle;
|
|
|
+ if (pDev->nInUse)
|
|
|
+ pDev->nInUse--;
|
|
|
+ module_put(pDev->owner);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_Open (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil)
|
|
|
+{
|
|
|
+ int maj = MAJOR (ino->i_rdev);
|
|
|
+ int num = MINOR (ino->i_rdev);
|
|
|
+
|
|
|
+ DSL_DEV_Device_t *pDev = NULL;
|
|
|
+ if ((pDev = DSL_BSP_DriverHandleGet (maj, num)) == NULL) {
|
|
|
+ IFX_MEI_EMSG("open(%d:%d) fail!\n", maj, num);
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ fil->private_data = pDev;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_Release (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil)
|
|
|
+{
|
|
|
+ //int maj = MAJOR(ino->i_rdev);
|
|
|
+ int num = MINOR (ino->i_rdev);
|
|
|
+ DSL_DEV_Device_t *pDev;
|
|
|
+
|
|
|
+ pDev = &dsl_devices[num];
|
|
|
+ if (pDev == NULL)
|
|
|
+ return -EIO;
|
|
|
+ DSL_BSP_DriverHandleDelete (pDev);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Callback function for linux userspace program writing
|
|
|
+ */
|
|
|
+static ssize_t
|
|
|
+IFX_MEI_Write (DSL_DRV_file_t * filp, const char *buf, size_t size, loff_t * loff)
|
|
|
+{
|
|
|
+ DSL_DEV_MeiError_t mei_error = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ long offset = 0;
|
|
|
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) filp->private_data;
|
|
|
+
|
|
|
+ if (pDev == NULL)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ mei_error =
|
|
|
+ DSL_BSP_FWDownload (pDev, buf, size, (long *) loff, &offset);
|
|
|
+
|
|
|
+ if (mei_error == DSL_DEV_MEI_ERR_FAILURE)
|
|
|
+ return -EIO;
|
|
|
+ return (ssize_t) offset;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Callback function for linux userspace program ioctling
|
|
|
+ */
|
|
|
+static int
|
|
|
+IFX_MEI_IoctlCopyFrom (int from_kernel, char *dest, char *from, int size)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!from_kernel)
|
|
|
+ ret = copy_from_user ((char *) dest, (char *) from, size);
|
|
|
+ else
|
|
|
+ ret = (int)memcpy ((char *) dest, (char *) from, size);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_IoctlCopyTo (int from_kernel, char *dest, char *from, int size)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!from_kernel)
|
|
|
+ ret = copy_to_user ((char *) dest, (char *) from, size);
|
|
|
+ else
|
|
|
+ ret = (int)memcpy ((char *) dest, (char *) from, size);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command, unsigned long lon)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+ int meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ u32 base_address = IFXMIPS_MEI_BASE_ADDR;
|
|
|
+ DSL_DEV_WinHost_Message_t winhost_msg, m;
|
|
|
+ DSL_DEV_MeiDebug_t debugrdwr;
|
|
|
+ DSL_DEV_MeiReg_t regrdwr;
|
|
|
+
|
|
|
+ switch (command) {
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_CMV_WINHOST:
|
|
|
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) winhost_msg.msg.TxMessage,
|
|
|
+ (char *) lon, MSG_LENGTH * 2);
|
|
|
+
|
|
|
+ if ((meierr = DSL_BSP_SendCMV (pDev, winhost_msg.msg.TxMessage, YES_REPLY,
|
|
|
+ winhost_msg.msg.RxMessage)) != DSL_DEV_MEI_ERR_SUCCESS) {
|
|
|
+ IFX_MEI_EMSG ("WINHOST CMV fail :TxMessage:%X %X %X %X, RxMessage:%X %X %X %X %X\n",
|
|
|
+ winhost_msg.msg.TxMessage[0], winhost_msg.msg.TxMessage[1], winhost_msg.msg.TxMessage[2], winhost_msg.msg.TxMessage[3],
|
|
|
+ winhost_msg.msg.RxMessage[0], winhost_msg.msg.RxMessage[1], winhost_msg.msg.RxMessage[2], winhost_msg.msg.RxMessage[3],
|
|
|
+ winhost_msg.msg.RxMessage[4]);
|
|
|
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
|
|
|
+ (char *) winhost_msg.msg.RxMessage,
|
|
|
+ MSG_LENGTH * 2);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_CMV_READ:
|
|
|
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (®rdwr),
|
|
|
+ (char *) lon, sizeof (DSL_DEV_MeiReg_t));
|
|
|
+
|
|
|
+ IFX_MEI_LongWordRead ((u32) regrdwr.iAddress,
|
|
|
+ (u32 *) & (regrdwr.iData));
|
|
|
+
|
|
|
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
|
|
|
+ (char *) (®rdwr),
|
|
|
+ sizeof (DSL_DEV_MeiReg_t));
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_CMV_WRITE:
|
|
|
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (®rdwr),
|
|
|
+ (char *) lon, sizeof (DSL_DEV_MeiReg_t));
|
|
|
+
|
|
|
+ IFX_MEI_LongWordWrite ((u32) regrdwr.iAddress,
|
|
|
+ regrdwr.iData);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_GET_BASE_ADDRESS:
|
|
|
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
|
|
|
+ (char *) (&base_address),
|
|
|
+ sizeof (base_address));
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_IS_MODEM_READY:
|
|
|
+ i = IFX_MEI_IsModemReady (pDev);
|
|
|
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
|
|
|
+ (char *) (&i), sizeof (int));
|
|
|
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ break;
|
|
|
+ case DSL_FIO_BSP_RESET:
|
|
|
+ case DSL_FIO_BSP_REBOOT:
|
|
|
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RESET);
|
|
|
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_HALT:
|
|
|
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_RUN:
|
|
|
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RUN);
|
|
|
+ break;
|
|
|
+ case DSL_FIO_BSP_BOOTDOWNLOAD:
|
|
|
+ meierr = IFX_MEI_DownloadBootCode (pDev);
|
|
|
+ break;
|
|
|
+ case DSL_FIO_BSP_JTAG_ENABLE:
|
|
|
+ meierr = IFX_MEI_ArcJtagEnable (pDev, 1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_REMOTE:
|
|
|
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&i),
|
|
|
+ (char *) lon, sizeof (int));
|
|
|
+
|
|
|
+ meierr = IFX_MEI_AdslMailboxIRQEnable (pDev, i);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_DSL_START:
|
|
|
+ printk("\n%s: DSL_FIO_BSP_DSL_START\n",__func__);
|
|
|
+ if ((meierr = IFX_MEI_RunAdslModem (pDev)) != DSL_DEV_MEI_ERR_SUCCESS) {
|
|
|
+ IFX_MEI_EMSG ("IFX_MEI_RunAdslModem() error...");
|
|
|
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_DEBUG_READ:
|
|
|
+ case DSL_FIO_BSP_DEBUG_WRITE:
|
|
|
+ IFX_MEI_IoctlCopyFrom (from_kernel,
|
|
|
+ (char *) (&debugrdwr),
|
|
|
+ (char *) lon,
|
|
|
+ sizeof (debugrdwr));
|
|
|
+
|
|
|
+ if (command == DSL_FIO_BSP_DEBUG_READ)
|
|
|
+ meierr = DSL_BSP_MemoryDebugAccess (pDev,
|
|
|
+ DSL_BSP_MEMORY_READ,
|
|
|
+ debugrdwr.
|
|
|
+ iAddress,
|
|
|
+ debugrdwr.
|
|
|
+ buffer,
|
|
|
+ debugrdwr.
|
|
|
+ iCount);
|
|
|
+ else
|
|
|
+ meierr = DSL_BSP_MemoryDebugAccess (pDev,
|
|
|
+ DSL_BSP_MEMORY_WRITE,
|
|
|
+ debugrdwr.
|
|
|
+ iAddress,
|
|
|
+ debugrdwr.
|
|
|
+ buffer,
|
|
|
+ debugrdwr.
|
|
|
+ iCount);
|
|
|
+
|
|
|
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&debugrdwr), sizeof (debugrdwr));
|
|
|
+ break;
|
|
|
+ case DSL_FIO_BSP_GET_VERSION:
|
|
|
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_mei_version), sizeof (DSL_DEV_Version_t));
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_GET_CHIP_INFO:
|
|
|
+ bsp_chip_info.major = 1;
|
|
|
+ bsp_chip_info.minor = IFXMIPS_MPS_CHIPID_VERSION_GET(*IFXMIPS_MPS_CHIPID);
|
|
|
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_chip_info), sizeof (DSL_DEV_HwVersion_t));
|
|
|
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DSL_FIO_BSP_FREE_RESOURCE:
|
|
|
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_STAT, 4, 0, 1, NULL, m.msg.TxMessage);
|
|
|
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) {
|
|
|
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ IFX_MEI_DMSG("RxMessage[4] = %#x\n", m.msg.RxMessage[4]);
|
|
|
+ if (!(m.msg.RxMessage[4] & DSL_DEV_STAT_CODESWAP_COMPLETE)) {
|
|
|
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
|
|
|
+ return -EAGAIN;
|
|
|
+ }
|
|
|
+ IFX_MEI_DMSG("Freeing all memories marked FREE_SHOWTIME\n");
|
|
|
+ IFX_MEI_DFEMemoryFree (pDev, FREE_SHOWTIME);
|
|
|
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
|
|
+ break;
|
|
|
+#ifdef CONFIG_IFXMIPS_AMAZON_SE
|
|
|
+ case DSL_FIO_ARC_MUX_TEST:
|
|
|
+ AMAZON_SE_MEI_ARC_MUX_Test();
|
|
|
+ break;
|
|
|
+#endif
|
|
|
+ default:
|
|
|
+// IFX_MEI_EMSG("Invalid IOCTL command: %d\n");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return meierr;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_IFXMIPS_AMAZON_SE
|
|
|
+void AMAZON_SE_MEI_ARC_MUX_Test(void)
|
|
|
+{
|
|
|
+ u32 *p, i;
|
|
|
+ *IFXMIPS_RCU_RST |= IFXMIPS_RCU_RST_REQ_MUX_ARC;
|
|
|
+
|
|
|
+ p = (u32*)(DFE_LDST_BASE_ADDR + IRAM0_BASE);
|
|
|
+ IFX_MEI_EMSG("Writing to IRAM0(%p)...\n", p);
|
|
|
+ for (i = 0; i < IRAM0_SIZE/sizeof(u32); i++, p++) {
|
|
|
+ *p = 0xdeadbeef;
|
|
|
+ if (*p != 0xdeadbeef)
|
|
|
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
|
|
|
+ }
|
|
|
+
|
|
|
+ p = (u32*)(DFE_LDST_BASE_ADDR + IRAM1_BASE);
|
|
|
+ IFX_MEI_EMSG("Writing to IRAM1(%p)...\n", p);
|
|
|
+ for (i = 0; i < IRAM1_SIZE/sizeof(u32); i++, p++) {
|
|
|
+ *p = 0xdeadbeef;
|
|
|
+ if (*p != 0xdeadbeef)
|
|
|
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
|
|
|
+ }
|
|
|
+
|
|
|
+ p = (u32*)(DFE_LDST_BASE_ADDR + BRAM_BASE);
|
|
|
+ IFX_MEI_EMSG("Writing to BRAM(%p)...\n", p);
|
|
|
+ for (i = 0; i < BRAM_SIZE/sizeof(u32); i++, p++) {
|
|
|
+ *p = 0xdeadbeef;
|
|
|
+ if (*p != 0xdeadbeef)
|
|
|
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
|
|
|
+ }
|
|
|
+
|
|
|
+ p = (u32*)(DFE_LDST_BASE_ADDR + XRAM_BASE);
|
|
|
+ IFX_MEI_EMSG("Writing to XRAM(%p)...\n", p);
|
|
|
+ for (i = 0; i < XRAM_SIZE/sizeof(u32); i++, p++) {
|
|
|
+ *p = 0xdeadbeef;
|
|
|
+ if (*p != 0xdeadbeef)
|
|
|
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
|
|
|
+ }
|
|
|
+
|
|
|
+ p = (u32*)(DFE_LDST_BASE_ADDR + YRAM_BASE);
|
|
|
+ IFX_MEI_EMSG("Writing to YRAM(%p)...\n", p);
|
|
|
+ for (i = 0; i < YRAM_SIZE/sizeof(u32); i++, p++) {
|
|
|
+ *p = 0xdeadbeef;
|
|
|
+ if (*p != 0xdeadbeef)
|
|
|
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
|
|
|
+ }
|
|
|
+
|
|
|
+ p = (u32*)(DFE_LDST_BASE_ADDR + EXT_MEM_BASE);
|
|
|
+ IFX_MEI_EMSG("Writing to EXT_MEM(%p)...\n", p);
|
|
|
+ for (i = 0; i < EXT_MEM_SIZE/sizeof(u32); i++, p++) {
|
|
|
+ *p = 0xdeadbeef;
|
|
|
+ if (*p != 0xdeadbeef)
|
|
|
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
|
|
|
+ }
|
|
|
+ *IFXMIPS_RCU_RST &= ~IFXMIPS_RCU_RST_REQ_MUX_ARC;
|
|
|
+}
|
|
|
+#endif
|
|
|
+int
|
|
|
+DSL_BSP_KernelIoctls (DSL_DEV_Device_t * pDev, unsigned int command,
|
|
|
+ unsigned long lon)
|
|
|
+{
|
|
|
+ int error = 0;
|
|
|
+
|
|
|
+ error = IFX_MEI_Ioctls (pDev, 1, command, lon);
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+IFX_MEI_UserIoctls (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil,
|
|
|
+ unsigned int command, unsigned long lon)
|
|
|
+{
|
|
|
+ int error = 0;
|
|
|
+ int maj = MAJOR (ino->i_rdev);
|
|
|
+ int num = MINOR (ino->i_rdev);
|
|
|
+ DSL_DEV_Device_t *pDev;
|
|
|
+
|
|
|
+ pDev = IFX_BSP_HandleGet (maj, num);
|
|
|
+ if (pDev == NULL)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ error = IFX_MEI_Ioctls (pDev, 0, command, lon);
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_PROC_FS
|
|
|
+/*
|
|
|
+ * Register a callback function for linux proc filesystem
|
|
|
+ */
|
|
|
+static int
|
|
|
+IFX_MEI_InitProcFS (int num)
|
|
|
+{
|
|
|
+ struct proc_dir_entry *entry;
|
|
|
+ int i ;
|
|
|
+ DSL_DEV_Device_t *pDev;
|
|
|
+ reg_entry_t regs_temp[PROC_ITEMS] = {
|
|
|
+ /* flag, name, description } */
|
|
|
+ {NULL, "arcmsgav", "arc to mei message ", 0},
|
|
|
+ {NULL, "cmv_reply", "cmv needs reply", 0},
|
|
|
+ {NULL, "cmv_waiting", "waiting for cmv reply from arc", 0},
|
|
|
+ {NULL, "modem_ready_cnt", "ARC to MEI indicator count", 0},
|
|
|
+ {NULL, "cmv_count", "MEI to ARC CMVs", 0},
|
|
|
+ {NULL, "reply_count", "ARC to MEI Reply", 0},
|
|
|
+ {NULL, "Recent_indicator", "most recent indicator", 0},
|
|
|
+ {NULL, "fw_version", "Firmware Version", 0},
|
|
|
+ {NULL, "fw_date", "Firmware Date", 0},
|
|
|
+ {NULL, "meminfo", "Memory Allocation Information", 0},
|
|
|
+ {NULL, "version", "MEI version information", 0},
|
|
|
+ };
|
|
|
+
|
|
|
+ pDev = &dsl_devices[num];
|
|
|
+ if (pDev == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ regs_temp[0].flag = &(DSL_DEV_PRIVATE(pDev)->arcmsgav);
|
|
|
+ regs_temp[1].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_reply);
|
|
|
+ regs_temp[2].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_waiting);
|
|
|
+ regs_temp[3].flag = &(DSL_DEV_PRIVATE(pDev)->modem_ready_cnt);
|
|
|
+ regs_temp[4].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_count);
|
|
|
+ regs_temp[5].flag = &(DSL_DEV_PRIVATE(pDev)->reply_count);
|
|
|
+ regs_temp[6].flag = (int *) &(DSL_DEV_PRIVATE(pDev)->Recent_indicator);
|
|
|
+
|
|
|
+ memcpy ((char *) regs[num], (char *) regs_temp, sizeof (regs_temp));
|
|
|
+ // procfs
|
|
|
+ meidir = proc_mkdir (MEI_DIRNAME, NULL);
|
|
|
+ if (meidir == NULL) {
|
|
|
+ IFX_MEI_EMSG ("Failed to create /proc/%s\n", MEI_DIRNAME);
|
|
|
+ return (-ENOMEM);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
|
|
|
+ entry = create_proc_entry (regs[num][i].name,
|
|
|
+ S_IWUSR | S_IRUSR | S_IRGRP |
|
|
|
+ S_IROTH, meidir);
|
|
|
+ if (entry) {
|
|
|
+ regs[num][i].low_ino = entry->low_ino;
|
|
|
+ entry->proc_fops = &IFX_MEI_ProcOperations;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ IFX_MEI_EMSG ("Failed to create /proc/%s/%s\n", MEI_DIRNAME, regs[num][i].name);
|
|
|
+ return (-ENOMEM);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Reading function for linux proc filesystem
|
|
|
+ */
|
|
|
+static int
|
|
|
+IFX_MEI_ProcRead (struct file *file, char *buf, size_t nbytes, loff_t * ppos)
|
|
|
+{
|
|
|
+ int i_ino = (file->f_dentry->d_inode)->i_ino;
|
|
|
+ char *p = buf;
|
|
|
+ int i;
|
|
|
+ int num;
|
|
|
+ reg_entry_t *entry = NULL;
|
|
|
+ DSL_DEV_Device_t *pDev = NULL;
|
|
|
+ DSL_DEV_WinHost_Message_t m;
|
|
|
+
|
|
|
+ for (num = 0; num < BSP_MAX_DEVICES; num++) {
|
|
|
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
|
|
|
+ if (regs[num][i].low_ino == (unsigned short)i_ino) {
|
|
|
+ entry = ®s[num][i];
|
|
|
+ pDev = &dsl_devices[num];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (entry == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+ else if (strcmp(entry->name, "meminfo") == 0) {
|
|
|
+ if (*ppos > 0) /* Assume reading completed in previous read */
|
|
|
+ return 0;
|
|
|
+ p += sprintf (p, "No Address Size\n");
|
|
|
+ for (i = 0; i < MAX_BAR_REGISTERS; i++) {
|
|
|
+ p += sprintf (p, "BAR[%02d] Addr:0x%08X Size:%lu\n",
|
|
|
+ i, (u32) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[i].address,
|
|
|
+ DSL_DEV_PRIVATE(pDev)-> adsl_mem_info[i].size);
|
|
|
+ //printk( "BAR[%02d] Addr:0x%08X Size:%d\n",i,adsl_mem_info[i].address,adsl_mem_info[i].size);
|
|
|
+ }
|
|
|
+ *ppos += (p - buf);
|
|
|
+ } else if (strcmp(entry->name, "fw_version") == 0) {
|
|
|
+ if (*ppos > 0) /* Assume reading completed in previous read */
|
|
|
+ return 0;
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1)
|
|
|
+ return -EAGAIN;
|
|
|
+ //major:bits 0-7
|
|
|
+ //minor:bits 8-15
|
|
|
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 0, 1, NULL, m.msg.TxMessage);
|
|
|
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
|
|
|
+ return -EIO;
|
|
|
+ p += sprintf(p, "FW Version: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF);
|
|
|
+ //sub_version:bits 4-7
|
|
|
+ //int_version:bits 0-3
|
|
|
+ //spl_appl:bits 8-13
|
|
|
+ //rel_state:bits 14-15
|
|
|
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 1, 1, NULL, m.msg.TxMessage);
|
|
|
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
|
|
|
+ return -EIO;
|
|
|
+ p += sprintf(p, "%d.%d.%d.%d\n",
|
|
|
+ (m.msg.RxMessage[4] >> 4) & 0xF, m.msg.RxMessage[4] & 0xF,
|
|
|
+ (m.msg.RxMessage[4] >> 14) & 3, (m.msg.RxMessage[4] >> 8) & 0x3F);
|
|
|
+ *ppos += (p - buf);
|
|
|
+ } else if (strcmp(entry->name, "fw_date") == 0) {
|
|
|
+ if (*ppos > 0) /* Assume reading completed in previous read */
|
|
|
+ return 0;
|
|
|
+ if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1)
|
|
|
+ return -EAGAIN;
|
|
|
+
|
|
|
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 0, 1, NULL, m.msg.TxMessage);
|
|
|
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
|
|
|
+ return -EIO;
|
|
|
+ /* Day/Month */
|
|
|
+ p += sprintf(p, "FW Date: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF);
|
|
|
+
|
|
|
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 2, 1, NULL, m.msg.TxMessage);
|
|
|
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
|
|
|
+ return -EIO;
|
|
|
+ /* Year */
|
|
|
+ p += sprintf(p, "%d ", m.msg.RxMessage[4]);
|
|
|
+
|
|
|
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 1, 1, NULL, m.msg.TxMessage);
|
|
|
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
|
|
|
+ return -EIO;
|
|
|
+ /* Hour:Minute */
|
|
|
+ p += sprintf(p, "%d:%d\n", (m.msg.RxMessage[4] >> 8) & 0xFF, m.msg.RxMessage[4] & 0xFF);
|
|
|
+
|
|
|
+ *ppos += (p - buf);
|
|
|
+ } else if (strcmp(entry->name, "version") == 0) {
|
|
|
+ if (*ppos > 0) /* Assume reading completed in previous read */
|
|
|
+ return 0;
|
|
|
+ p += sprintf (p, "IFX MEI V%ld.%ld.%ld\n", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision);
|
|
|
+
|
|
|
+ *ppos += (p - buf);
|
|
|
+ } else if (entry->flag != (int *) DSL_DEV_PRIVATE(pDev)->Recent_indicator) {
|
|
|
+ if (*ppos > 0) /* Assume reading completed in previous read */
|
|
|
+ return 0; // indicates end of file
|
|
|
+ p += sprintf (p, "0x%08X\n\n", *(entry->flag));
|
|
|
+ *ppos += (p - buf);
|
|
|
+ if ((p - buf) > nbytes) /* Assume output can be read at one time */
|
|
|
+ return -EINVAL;
|
|
|
+ } else {
|
|
|
+ if ((int) (*ppos) / ((int) 7) == 16)
|
|
|
+ return 0; // indicate end of the message
|
|
|
+ p += sprintf (p, "0x%04X\n\n", *(((u16 *) (entry->flag)) + (int) (*ppos) / ((int) 7)));
|
|
|
+ *ppos += (p - buf);
|
|
|
+ }
|
|
|
+ return p - buf;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Writing function for linux proc filesystem
|
|
|
+ */
|
|
|
+static ssize_t
|
|
|
+IFX_MEI_ProcWrite (struct file *file, const char *buffer, size_t count, loff_t * ppos)
|
|
|
+{
|
|
|
+ int i_ino = (file->f_dentry->d_inode)->i_ino;
|
|
|
+ reg_entry_t *current_reg = NULL;
|
|
|
+ int i = 0;
|
|
|
+ int num = 0;
|
|
|
+ unsigned long newRegValue = 0;
|
|
|
+ char *endp = NULL;
|
|
|
+ DSL_DEV_Device_t *pDev = NULL;
|
|
|
+
|
|
|
+ for (num = 0; num < BSP_MAX_DEVICES; num++) {
|
|
|
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
|
|
|
+ if (regs[num][i].low_ino == i_ino) {
|
|
|
+ current_reg = ®s[num][i];
|
|
|
+ pDev = &dsl_devices[num];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ((current_reg == NULL)
|
|
|
+ || (current_reg->flag ==
|
|
|
+ (int *) DSL_DEV_PRIVATE(pDev)->
|
|
|
+ Recent_indicator))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ newRegValue = simple_strtoul (buffer, &endp, 0);
|
|
|
+ *(current_reg->flag) = (int) newRegValue;
|
|
|
+ return (count + endp - buffer);
|
|
|
+}
|
|
|
+#endif //CONFIG_PROC_FS
|
|
|
+
|
|
|
+static int adsl_dummy_ledcallback(void)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int ifx_mei_atm_led_blink(void)
|
|
|
+{
|
|
|
+ return g_adsl_ledcallback();
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(ifx_mei_atm_led_blink);
|
|
|
+
|
|
|
+int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if ( is_showtime ) {
|
|
|
+ *is_showtime = g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ? 0 : 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( port_cell ) {
|
|
|
+ for ( i = 0; i < port_cell->port_num && i < 2; i++ )
|
|
|
+ port_cell->tx_link_rate[i] = g_tx_link_rate[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( xdata_addr ) {
|
|
|
+ if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 )
|
|
|
+ *xdata_addr = NULL;
|
|
|
+ else
|
|
|
+ *xdata_addr = g_xdata_addr;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(ifx_mei_atm_showtime_check);
|
|
|
+
|
|
|
+/*
|
|
|
+ * Writing function for linux proc filesystem
|
|
|
+ */
|
|
|
+int __init
|
|
|
+IFX_MEI_ModuleInit (void)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+
|
|
|
+ printk ("IFX MEI Version %ld.%02ld.%02ld", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision);
|
|
|
+
|
|
|
+ for (i = 0; i < BSP_MAX_DEVICES; i++) {
|
|
|
+ if (IFX_MEI_InitDevice (i) != 0) {
|
|
|
+ printk ("%s: Init device fail!\n", __FUNCTION__);
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ IFX_MEI_InitDevNode (i);
|
|
|
+#ifdef CONFIG_PROC_FS
|
|
|
+ IFX_MEI_InitProcFS (i);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ for (i = 0; i <= DSL_BSP_CB_LAST ; i++)
|
|
|
+ dsl_bsp_event_callback[i].function = NULL;
|
|
|
+
|
|
|
+#ifdef CONFIG_IFXMIPS_MEI_FW_LOOPBACK
|
|
|
+ printk(KERN_INFO "[%s %s %d]: Start loopback test...\n", __FILE__, __func__, __LINE__);
|
|
|
+ DFE_Loopback_Test ();
|
|
|
+#endif
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void __exit
|
|
|
+IFX_MEI_ModuleExit (void)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+ int num;
|
|
|
+
|
|
|
+ for (num = 0; num < BSP_MAX_DEVICES; num++) {
|
|
|
+ IFX_MEI_CleanUpDevNode (num);
|
|
|
+#ifdef CONFIG_PROC_FS
|
|
|
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
|
|
|
+ remove_proc_entry (regs[num][i].name, meidir);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
+ remove_proc_entry (MEI_DIRNAME, NULL);
|
|
|
+ for (i = 0; i < BSP_MAX_DEVICES; i++) {
|
|
|
+ for (i = 0; i < BSP_MAX_DEVICES; i++) {
|
|
|
+ IFX_MEI_ExitDevice (i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* export function for DSL Driver */
|
|
|
+
|
|
|
+/* The functions of MEI_DriverHandleGet and MEI_DriverHandleDelete are
|
|
|
+something like open/close in kernel space , where the open could be used
|
|
|
+to register a callback for autonomous messages and returns a mei driver context pointer (comparable to the file descriptor in user space)
|
|
|
+ The context will be required for the multi line chips future! */
|
|
|
+
|
|
|
+EXPORT_SYMBOL (DSL_BSP_DriverHandleGet);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_DriverHandleDelete);
|
|
|
+
|
|
|
+EXPORT_SYMBOL (DSL_BSP_ATMLedCBRegister);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_ATMLedCBUnregister);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_KernelIoctls);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_AdslLedInit);
|
|
|
+//EXPORT_SYMBOL (DSL_BSP_AdslLedSet);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_FWDownload);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_Showtime);
|
|
|
+
|
|
|
+EXPORT_SYMBOL (DSL_BSP_MemoryDebugAccess);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_SendCMV);
|
|
|
+
|
|
|
+// provide a register/unregister function for DSL driver to register a event callback function
|
|
|
+EXPORT_SYMBOL (DSL_BSP_EventCBRegister);
|
|
|
+EXPORT_SYMBOL (DSL_BSP_EventCBUnregister);
|
|
|
+
|
|
|
+module_init (IFX_MEI_ModuleInit);
|
|
|
+module_exit (IFX_MEI_ModuleExit);
|