Root/package/ltq-dsl/src/lantiq_mei.c

1/******************************************************************************
2
3                               Copyright (c) 2009
4                            Infineon Technologies AG
5                     Am Campeon 1-12; 81726 Munich, Germany
6
7  For licensing information, see the file 'LICENSE' in the root folder of
8  this software module.
9
10******************************************************************************/
11
12/*!
13  \defgroup AMAZON_S_MEI Amazon-S MEI Driver Module
14  \brief Amazon-S MEI driver module
15 */
16
17/*!
18  \defgroup Internal Compile Parametere
19  \ingroup AMAZON_S_MEI
20  \brief exported functions for other driver use
21 */
22
23/*!
24  \file amazon_s_mei_bsp.c
25  \ingroup AMAZON_S_MEI
26  \brief Amazon-S MEI driver file
27 */
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/version.h>
32#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
33#include <linux/utsrelease.h>
34#else
35#include <generated/utsrelease.h>
36#endif
37#include <linux/types.h>
38#include <linux/fs.h>
39#include <linux/mm.h>
40#include <linux/errno.h>
41#include <linux/interrupt.h>
42#include <linux/netdevice.h>
43#include <linux/etherdevice.h>
44#include <linux/proc_fs.h>
45#include <linux/init.h>
46#include <linux/ioport.h>
47#include <linux/delay.h>
48#include <linux/device.h>
49#include <linux/sched.h>
50#include <asm/uaccess.h>
51#include <asm/hardirq.h>
52
53#include <lantiq_soc.h>
54#include "ifxmips_atm.h"
55#define IFX_MEI_BSP
56#include "ifxmips_mei_interface.h"
57
58/*#define LTQ_RCU_RST IFX_RCU_RST_REQ
59#define LTQ_RCU_RST_REQ_ARC_JTAG IFX_RCU_RST_REQ_ARC_JTAG
60#define LTQ_RCU_RST_REQ_DFE IFX_RCU_RST_REQ_DFE
61#define LTQ_RCU_RST_REQ_AFE IFX_RCU_RST_REQ_AFE
62#define IFXMIPS_FUSE_BASE_ADDR IFX_FUSE_BASE_ADDR
63#define IFXMIPS_ICU_IM0_IER IFX_ICU_IM0_IER
64#define IFXMIPS_ICU_IM2_IER IFX_ICU_IM2_IER
65#define LTQ_MEI_INT IFX_MEI_INT
66#define LTQ_MEI_DYING_GASP_INT IFX_MEI_DYING_GASP_INT
67#define LTQ_MEI_BASE_ADDR IFX_MEI_SPACE_ACCESS
68#define IFXMIPS_PMU_PWDCR IFX_PMU_PWDCR
69#define IFXMIPS_MPS_CHIPID IFX_MPS_CHIPID
70
71#define ifxmips_port_reserve_pin ifx_gpio_pin_reserve
72#define ifxmips_port_set_dir_in ifx_gpio_dir_in_set
73#define ifxmips_port_clear_altsel0 ifx_gpio_altsel0_set
74#define ifxmips_port_clear_altsel1 ifx_gpio_altsel1_clear
75#define ifxmips_port_set_open_drain ifx_gpio_open_drain_clear
76#define ifxmips_port_free_pin ifx_gpio_pin_free
77#define ifxmips_mask_and_ack_irq bsp_mask_and_ack_irq
78#define IFXMIPS_MPS_CHIPID_VERSION_GET IFX_MCD_CHIPID_VERSION_GET
79#define ltq_r32(reg) __raw_readl(reg)
80#define ltq_w32(val, reg) __raw_writel(val, reg)
81#define ltq_w32_mask(clear, set, reg) ltq_w32((ltq_r32(reg) & ~clear) | set, reg)
82*/
83
84#define LTQ_RCU_RST_REQ_DFE (1 << 7)
85#define LTQ_RCU_RST_REQ_AFE (1 << 11)
86
87#define LTQ_PMU_BASE (KSEG1 + LTQ_PMU_BASE_ADDR)
88#define LTQ_RCU_BASE (KSEG1 + LTQ_RCU_BASE_ADDR)
89#define LTQ_ICU_BASE (KSEG1 + LTQ_ICU_BASE_ADDR)
90
91#define LTQ_PMU_PWDCR ((u32 *)(LTQ_PMU_BASE + 0x001C))
92#define LTQ_PMU_PWDSR ((u32 *)(LTQ_PMU_BASE + 0x0020))
93#define LTQ_RCU_RST ((u32 *)(LTQ_RCU_BASE + 0x0010))
94#define LTQ_RCU_RST_ALL 0x40000000
95
96#define LTQ_ICU_IM0_ISR ((u32 *)(LTQ_ICU_BASE + 0x0000))
97#define LTQ_ICU_IM0_IER ((u32 *)(LTQ_ICU_BASE + 0x0008))
98#define LTQ_ICU_IM0_IOSR ((u32 *)(LTQ_ICU_BASE + 0x0010))
99#define LTQ_ICU_IM0_IRSR ((u32 *)(LTQ_ICU_BASE + 0x0018))
100#define LTQ_ICU_IM0_IMR ((u32 *)(LTQ_ICU_BASE + 0x0020))
101
102
103#define LTQ_ICU_IM1_ISR ((u32 *)(LTQ_ICU_BASE + 0x0028))
104#define LTQ_ICU_IM2_ISR ((u32 *)(LTQ_ICU_BASE + 0x0050))
105#define LTQ_ICU_IM3_ISR ((u32 *)(LTQ_ICU_BASE + 0x0078))
106#define LTQ_ICU_IM4_ISR ((u32 *)(LTQ_ICU_BASE + 0x00A0))
107
108#define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
109#define LTQ_ICU_IM2_IER (LTQ_ICU_IM0_IER + LTQ_ICU_OFFSET)
110
111#define IFX_MEI_EMSG(fmt, args...) pr_err("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
112#define IFX_MEI_DMSG(fmt, args...) pr_debug("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
113
114#define LTQ_FUSE_BASE (KSEG1 + 0x1F107354)
115
116#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
117//#define DFE_MEM_TEST
118//#define DFE_PING_TEST
119#define DFE_ATM_LOOPBACK
120
121
122#ifdef DFE_ATM_LOOPBACK
123#include <asm/ifxmips/ifxmips_mei_fw_loopback.h>
124#endif
125
126void dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev);
127
128#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
129
130DSL_DEV_Version_t bsp_mei_version = {
131    major: 5,
132    minor: 0,
133    revision:0
134};
135DSL_DEV_HwVersion_t bsp_chip_info;
136
137#define IFX_MEI_DEVNAME "ifx_mei"
138#define BSP_MAX_DEVICES 1
139
140DSL_DEV_MeiError_t DSL_BSP_FWDownload (DSL_DEV_Device_t *, const char *, unsigned long, long *, long *);
141DSL_DEV_MeiError_t DSL_BSP_Showtime (DSL_DEV_Device_t *, DSL_uint32_t, DSL_uint32_t);
142DSL_DEV_MeiError_t DSL_BSP_AdslLedInit (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedType_t, DSL_DEV_LedHandler_t);
143//DSL_DEV_MeiError_t DSL_BSP_AdslLedSet (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedMode_t);
144DSL_DEV_MeiError_t DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t *, DSL_BSP_MemoryAccessType_t, DSL_uint32_t, DSL_uint32_t*, DSL_uint32_t);
145DSL_DEV_MeiError_t DSL_BSP_SendCMV (DSL_DEV_Device_t *, u16 *, int, u16 *);
146
147int DSL_BSP_KernelIoctls (DSL_DEV_Device_t *, unsigned int, unsigned long);
148
149static DSL_DEV_MeiError_t IFX_MEI_RunAdslModem (DSL_DEV_Device_t *);
150static DSL_DEV_MeiError_t IFX_MEI_CpuModeSet (DSL_DEV_Device_t *, DSL_DEV_CpuMode_t);
151static DSL_DEV_MeiError_t IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *);
152static DSL_DEV_MeiError_t IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *, int);
153static DSL_DEV_MeiError_t IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *, int);
154
155static int IFX_MEI_GetPage (DSL_DEV_Device_t *, u32, u32, u32, u32 *, u32 *);
156static int IFX_MEI_BarUpdate (DSL_DEV_Device_t *, int);
157
158static ssize_t IFX_MEI_Write (DSL_DRV_file_t *, const char *, size_t, loff_t *);
159#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
160static int IFX_MEI_UserIoctls (DSL_DRV_inode_t *, DSL_DRV_file_t *, unsigned int, unsigned long);
161#else
162static int IFX_MEI_UserIoctls (DSL_DRV_file_t *, unsigned int, unsigned long);
163#endif
164static int IFX_MEI_Open (DSL_DRV_inode_t *, DSL_DRV_file_t *);
165static int IFX_MEI_Release (DSL_DRV_inode_t *, DSL_DRV_file_t *);
166
167void AMAZON_SE_MEI_ARC_MUX_Test(void);
168
169#ifdef CONFIG_PROC_FS
170static int IFX_MEI_ProcRead (struct file *, char *, size_t, loff_t *);
171static ssize_t IFX_MEI_ProcWrite (struct file *, const char *, size_t, loff_t *);
172
173#define PROC_ITEMS 11
174#define MEI_DIRNAME "ifxmips_mei"
175
176static struct proc_dir_entry *meidir;
177static struct file_operations IFX_MEI_ProcOperations = {
178      read:IFX_MEI_ProcRead,
179      write:IFX_MEI_ProcWrite,
180};
181static reg_entry_t regs[BSP_MAX_DEVICES][PROC_ITEMS]; //total items to be monitored by /proc/mei
182#define NUM_OF_REG_ENTRY (sizeof(regs[0])/sizeof(reg_entry_t))
183#endif //CONFIG_PROC_FS
184
185void IFX_MEI_ARC_MUX_Test(void);
186
187static int adsl_dummy_ledcallback(void);
188
189int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) = NULL;
190EXPORT_SYMBOL(ifx_mei_atm_showtime_enter);
191
192int (*ifx_mei_atm_showtime_exit)(void) = NULL;
193EXPORT_SYMBOL(ifx_mei_atm_showtime_exit);
194
195static int (*g_adsl_ledcallback)(void) = adsl_dummy_ledcallback;
196
197static unsigned int g_tx_link_rate[2] = {0};
198
199static void *g_xdata_addr = NULL;
200
201static u32 *mei_arc_swap_buff = NULL; // holding swap pages
202
203#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
204extern void ltq_mask_and_ack_irq(unsigned int irq_nr);
205#define MEI_MASK_AND_ACK_IRQ ltq_mask_and_ack_irq
206#else
207extern void ltq_mask_and_ack_irq(struct irq_data *d);
208static void inline MEI_MASK_AND_ACK_IRQ(int x)
209{
210    struct irq_data d;
211    d.irq = x;
212    ltq_mask_and_ack_irq(&d);
213}
214#endif
215#define MEI_MAJOR 105
216static int dev_major = MEI_MAJOR;
217
218static struct file_operations bsp_mei_operations = {
219      owner:THIS_MODULE,
220      open:IFX_MEI_Open,
221      release:IFX_MEI_Release,
222      write:IFX_MEI_Write,
223#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
224      ioctl:IFX_MEI_UserIoctls,
225#else
226      unlocked_ioctl:IFX_MEI_UserIoctls,
227#endif
228};
229
230static DSL_DEV_Device_t dsl_devices[BSP_MAX_DEVICES];
231
232static ifx_mei_device_private_t
233    sDanube_Mei_Private[BSP_MAX_DEVICES];
234
235static DSL_BSP_EventCallBack_t dsl_bsp_event_callback[DSL_BSP_CB_LAST + 1];
236
237/**
238 * Write a value to register
239 * This function writes a value to danube register
240 *
241 * \param ul_address The address to write
242 * \param ul_data The value to write
243 * \ingroup Internal
244 */
245static void
246IFX_MEI_LongWordWrite (u32 ul_address, u32 ul_data)
247{
248    IFX_MEI_WRITE_REGISTER_L (ul_data, ul_address);
249    wmb();
250    return;
251}
252
253/**
254 * Write a value to register
255 * This function writes a value to danube register
256 *
257 * \param pDev the device pointer
258 * \param ul_address The address to write
259 * \param ul_data The value to write
260 * \ingroup Internal
261 */
262static void
263IFX_MEI_LongWordWriteOffset (DSL_DEV_Device_t * pDev, u32 ul_address,
264                   u32 ul_data)
265{
266    IFX_MEI_WRITE_REGISTER_L (ul_data, pDev->base_address + ul_address);
267    wmb();
268    return;
269}
270
271/**
272 * Read the danube register
273 * This function read the value from danube register
274 *
275 * \param ul_address The address to write
276 * \param pul_data Pointer to the data
277 * \ingroup Internal
278 */
279static void
280IFX_MEI_LongWordRead (u32 ul_address, u32 * pul_data)
281{
282    *pul_data = IFX_MEI_READ_REGISTER_L (ul_address);
283    rmb();
284    return;
285}
286
287/**
288 * Read the danube register
289 * This function read the value from danube register
290 *
291 * \param pDev the device pointer
292 * \param ul_address The address to write
293 * \param pul_data Pointer to the data
294 * \ingroup Internal
295 */
296static void
297IFX_MEI_LongWordReadOffset (DSL_DEV_Device_t * pDev, u32 ul_address,
298                  u32 * pul_data)
299{
300    *pul_data = IFX_MEI_READ_REGISTER_L (pDev->base_address + ul_address);
301    rmb();
302    return;
303}
304
305/**
306 * Write several DWORD datas to ARC memory via ARC DMA interface
307 * This function writes several DWORD datas to ARC memory via DMA interface.
308 *
309 * \param pDev the device pointer
310 * \param destaddr The address to write
311 * \param databuff Pointer to the data buffer
312 * \param databuffsize Number of DWORDs to write
313 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
314 * \ingroup Internal
315 */
316static DSL_DEV_MeiError_t
317IFX_MEI_DMAWrite (DSL_DEV_Device_t * pDev, u32 destaddr,
318            u32 * databuff, u32 databuffsize)
319{
320    u32 *p = databuff;
321    u32 temp;
322
323    if (destaddr & 3)
324        return DSL_DEV_MEI_ERR_FAILURE;
325
326    // Set the write transfer address
327    IFX_MEI_LongWordWriteOffset (pDev, ME_DX_AD, destaddr);
328
329    // Write the data pushed across DMA
330    while (databuffsize--) {
331        temp = *p;
332        if (destaddr == MEI_TO_ARC_MAILBOX)
333            MEI_HALF_WORD_SWAP (temp);
334        IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_DATA, temp);
335        p++;
336    }
337
338    return DSL_DEV_MEI_ERR_SUCCESS;
339
340}
341
342/**
343 * Read several DWORD datas from ARC memory via ARC DMA interface
344 * This function reads several DWORD datas from ARC memory via DMA interface.
345 *
346 * \param pDev the device pointer
347 * \param srcaddr The address to read
348 * \param databuff Pointer to the data buffer
349 * \param databuffsize Number of DWORDs to read
350 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
351 * \ingroup Internal
352 */
353static DSL_DEV_MeiError_t
354IFX_MEI_DMARead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff,
355               u32 databuffsize)
356{
357    u32 *p = databuff;
358    u32 temp;
359
360    if (srcaddr & 3)
361        return DSL_DEV_MEI_ERR_FAILURE;
362
363    // Set the read transfer address
364    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_AD, srcaddr);
365
366    // Read the data popped across DMA
367    while (databuffsize--) {
368        IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DX_DATA, &temp);
369        if (databuff == (u32 *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg) // swap half word
370            MEI_HALF_WORD_SWAP (temp);
371        *p = temp;
372        p++;
373    }
374
375    return DSL_DEV_MEI_ERR_SUCCESS;
376
377}
378
379/**
380 * Switch the ARC control mode
381 * This function switchs the ARC control mode to JTAG mode or MEI mode
382 *
383 * \param pDev the device pointer
384 * \param mode The mode want to switch: JTAG_MASTER_MODE or MEI_MASTER_MODE.
385 * \ingroup Internal
386 */
387static void
388IFX_MEI_ControlModeSet (DSL_DEV_Device_t * pDev, int mode)
389{
390    u32 temp = 0x0;
391
392    IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_MASTER, &temp);
393    switch (mode) {
394    case JTAG_MASTER_MODE:
395        temp &= ~(HOST_MSTR);
396        break;
397    case MEI_MASTER_MODE:
398        temp |= (HOST_MSTR);
399        break;
400    default:
401        IFX_MEI_EMSG ("IFX_MEI_ControlModeSet: unkonwn mode [%d]\n", mode);
402        return;
403    }
404    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_MASTER, temp);
405}
406
407/**
408 * Disable ARC to MEI interrupt
409 *
410 * \param pDev the device pointer
411 * \ingroup Internal
412 */
413static void
414IFX_MEI_IRQDisable (DSL_DEV_Device_t * pDev)
415{
416    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, 0x0);
417}
418
419/**
420 * Eable ARC to MEI interrupt
421 *
422 * \param pDev the device pointer
423 * \ingroup Internal
424 */
425static void
426IFX_MEI_IRQEnable (DSL_DEV_Device_t * pDev)
427{
428    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, MSGAV_EN);
429}
430
431/**
432 * Poll for transaction complete signal
433 * This function polls and waits for transaction complete signal.
434 *
435 * \param pDev the device pointer
436 * \ingroup Internal
437 */
438static void
439meiPollForDbgDone (DSL_DEV_Device_t * pDev)
440{
441    u32 query = 0;
442    int i = 0;
443
444    while (i < WHILE_DELAY) {
445        IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ARC2ME_STAT, &query);
446        query &= (ARC_TO_MEI_DBG_DONE);
447        if (query)
448            break;
449        i++;
450        if (i == WHILE_DELAY) {
451            IFX_MEI_EMSG ("PollforDbg fail!\n");
452        }
453    }
454    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_DBG_DONE); // to clear this interrupt
455}
456
457/**
458 * ARC Debug Memory Access for a single DWORD reading.
459 * This function used for direct, address-based access to ARC memory.
460 *
461 * \param pDev the device pointer
462 * \param DEC_mode ARC memory space to used
463 * \param address Address to read
464 * \param data Pointer to data
465 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
466 * \ingroup Internal
467 */
468static DSL_DEV_MeiError_t
469_IFX_MEI_DBGLongWordRead (DSL_DEV_Device_t * pDev, u32 DEC_mode,
470                u32 address, u32 * data)
471{
472    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode);
473    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_RD_AD, address);
474    meiPollForDbgDone (pDev);
475    IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_DATA, data);
476    return DSL_DEV_MEI_ERR_SUCCESS;
477}
478
479/**
480 * ARC Debug Memory Access for a single DWORD writing.
481 * This function used for direct, address-based access to ARC memory.
482 *
483 * \param pDev the device pointer
484 * \param DEC_mode ARC memory space to used
485 * \param address The address to write
486 * \param data The data to write
487 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
488 * \ingroup Internal
489 */
490static DSL_DEV_MeiError_t
491_IFX_MEI_DBGLongWordWrite (DSL_DEV_Device_t * pDev, u32 DEC_mode,
492                 u32 address, u32 data)
493{
494    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode);
495    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_WR_AD, address);
496    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DATA, data);
497    meiPollForDbgDone (pDev);
498    return DSL_DEV_MEI_ERR_SUCCESS;
499}
500
501/**
502 * ARC Debug Memory Access for writing.
503 * This function used for direct, address-based access to ARC memory.
504 *
505 * \param pDev the device pointer
506 * \param destaddr The address to read
507 * \param databuffer Pointer to data
508 * \param databuffsize The number of DWORDs to read
509 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
510 * \ingroup Internal
511 */
512
513static DSL_DEV_MeiError_t
514IFX_MEI_DebugWrite (DSL_DEV_Device_t * pDev, u32 destaddr,
515              u32 * databuff, u32 databuffsize)
516{
517    u32 i;
518    u32 temp = 0x0;
519    u32 address = 0x0;
520    u32 *buffer = 0x0;
521
522    // Open the debug port before DMP memory write
523    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
524
525    // For the requested length, write the address and write the data
526    address = destaddr;
527    buffer = databuff;
528    for (i = 0; i < databuffsize; i++) {
529        temp = *buffer;
530        _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK, address, temp);
531        address += 4;
532        buffer++;
533    }
534
535    // Close the debug port after DMP memory write
536    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
537
538    return DSL_DEV_MEI_ERR_SUCCESS;
539}
540
541/**
542 * ARC Debug Memory Access for reading.
543 * This function used for direct, address-based access to ARC memory.
544 *
545 * \param pDev the device pointer
546 * \param srcaddr The address to read
547 * \param databuffer Pointer to data
548 * \param databuffsize The number of DWORDs to read
549 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
550 * \ingroup Internal
551 */
552static DSL_DEV_MeiError_t
553IFX_MEI_DebugRead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff, u32 databuffsize)
554{
555    u32 i;
556    u32 temp = 0x0;
557    u32 address = 0x0;
558    u32 *buffer = 0x0;
559
560    // Open the debug port before DMP memory read
561    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
562
563    // For the requested length, write the address and read the data
564    address = srcaddr;
565    buffer = databuff;
566    for (i = 0; i < databuffsize; i++) {
567        _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK, address, &temp);
568        *buffer = temp;
569        address += 4;
570        buffer++;
571    }
572
573    // Close the debug port after DMP memory read
574    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
575
576    return DSL_DEV_MEI_ERR_SUCCESS;
577}
578
579/**
580 * Send a message to ARC MailBox.
581 * This function sends a message to ARC Mailbox via ARC DMA interface.
582 *
583 * \param pDev the device pointer
584 * \param msgsrcbuffer Pointer to message.
585 * \param msgsize The number of words to write.
586 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
587 * \ingroup Internal
588 */
589static DSL_DEV_MeiError_t
590IFX_MEI_MailboxWrite (DSL_DEV_Device_t * pDev, u16 * msgsrcbuffer,
591                u16 msgsize)
592{
593    int i;
594    u32 arc_mailbox_status = 0x0;
595    u32 temp = 0;
596    DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS;
597
598    // Write to mailbox
599    meiMailboxError =
600        IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOX, (u32 *) msgsrcbuffer, msgsize / 2);
601    meiMailboxError =
602        IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOXR, (u32 *) (&temp), 1);
603
604    // Notify arc that mailbox write completed
605    DSL_DEV_PRIVATE(pDev)->cmv_waiting = 1;
606    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV);
607
608    i = 0;
609    while (i < WHILE_DELAY) { // wait for ARC to clear the bit
610        IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ME2ARC_INT, &arc_mailbox_status);
611        if ((arc_mailbox_status & MEI_TO_ARC_MSGAV) != MEI_TO_ARC_MSGAV)
612            break;
613        i++;
614        if (i == WHILE_DELAY) {
615            IFX_MEI_EMSG (">>> Timeout waiting for ARC to clear MEI_TO_ARC_MSGAV!!!"
616                  " MEI_TO_ARC message size = %d DWORDs <<<\n", msgsize/2);
617            meiMailboxError = DSL_DEV_MEI_ERR_FAILURE;
618        }
619    }
620
621    return meiMailboxError;
622}
623
624/**
625 * Read a message from ARC MailBox.
626 * This function reads a message from ARC Mailbox via ARC DMA interface.
627 *
628 * \param pDev the device pointer
629 * \param msgsrcbuffer Pointer to message.
630 * \param msgsize The number of words to read
631 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
632 * \ingroup Internal
633 */
634static DSL_DEV_MeiError_t
635IFX_MEI_MailboxRead (DSL_DEV_Device_t * pDev, u16 * msgdestbuffer,
636               u16 msgsize)
637{
638    DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS;
639    // Read from mailbox
640    meiMailboxError =
641        IFX_MEI_DMARead (pDev, ARC_TO_MEI_MAILBOX, (u32 *) msgdestbuffer, msgsize / 2);
642
643    // Notify arc that mailbox read completed
644    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
645
646    return meiMailboxError;
647}
648
649/**
650 * Download boot pages to ARC.
651 * This function downloads boot pages to ARC.
652 *
653 * \param pDev the device pointer
654 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
655 * \ingroup Internal
656 */
657static DSL_DEV_MeiError_t
658IFX_MEI_DownloadBootPages (DSL_DEV_Device_t * pDev)
659{
660    int boot_loop;
661    int page_size;
662    u32 dest_addr;
663
664    /*
665     ** DMA the boot code page(s)
666     */
667
668    for (boot_loop = 1;
669         boot_loop <
670         (DSL_DEV_PRIVATE(pDev)->img_hdr-> count); boot_loop++) {
671        if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].p_size) & BOOT_FLAG) {
672            page_size = IFX_MEI_GetPage (pDev, boot_loop,
673                               GET_PROG, MAXSWAPSIZE,
674                               mei_arc_swap_buff,
675                               &dest_addr);
676            if (page_size > 0) {
677                IFX_MEI_DMAWrite (pDev, dest_addr,
678                            mei_arc_swap_buff,
679                            page_size);
680            }
681        }
682        if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].d_size) & BOOT_FLAG) {
683            page_size = IFX_MEI_GetPage (pDev, boot_loop,
684                               GET_DATA, MAXSWAPSIZE,
685                               mei_arc_swap_buff,
686                               &dest_addr);
687            if (page_size > 0) {
688                IFX_MEI_DMAWrite (pDev, dest_addr,
689                            mei_arc_swap_buff,
690                            page_size);
691            }
692        }
693    }
694    return DSL_DEV_MEI_ERR_SUCCESS;
695}
696
697/**
698 * Initial efuse rar.
699 **/
700static void
701IFX_MEI_FuseInit (DSL_DEV_Device_t * pDev)
702{
703    u32 data = 0;
704    IFX_MEI_DMAWrite (pDev, IRAM0_BASE, &data, 1);
705    IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, &data, 1);
706    IFX_MEI_DMAWrite (pDev, IRAM1_BASE, &data, 1);
707    IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, &data, 1);
708    IFX_MEI_DMAWrite (pDev, BRAM_BASE, &data, 1);
709    IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, &data, 1);
710    IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, &data, 1);
711    IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, &data, 1);
712}
713
714/**
715 * efuse rar program
716 **/
717static void
718IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
719{
720    u32 reg_data, fuse_value;
721    int i = 0;
722
723    IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
724    while ((reg_data & 0x10000000) == 0) {
725        IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
726        i++;
727        /* 0x4000 translate to about 16 ms@111M, so should be enough */
728        if (i == 0x4000)
729            return;
730    }
731    // STEP a: Prepare memory for external accesses
732    // Write fuse_en bit24
733    IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
734    IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | (1 << 24));
735
736    IFX_MEI_FuseInit (pDev);
737    for (i = 0; i < 4; i++) {
738        IFX_MEI_LongWordRead ((u32) (LTQ_FUSE_BASE) + i * 4, &fuse_value);
739        switch (fuse_value & 0xF0000) {
740        case 0x80000:
741            reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
742                 (RX_DILV_ADDR_BIT_MASK + 0x1));
743            IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, &reg_data, 1);
744            break;
745        case 0x90000:
746            reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
747                 (RX_DILV_ADDR_BIT_MASK + 0x1));
748            IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, &reg_data, 1);
749            break;
750        case 0xA0000:
751            reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) |
752                 (IRAM0_ADDR_BIT_MASK + 0x1));
753            IFX_MEI_DMAWrite (pDev, IRAM0_BASE, &reg_data, 1);
754            break;
755        case 0xB0000:
756            reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) |
757                 (IRAM0_ADDR_BIT_MASK + 0x1));
758            IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, &reg_data, 1);
759            break;
760        case 0xC0000:
761            reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) |
762                 (IRAM1_ADDR_BIT_MASK + 0x1));
763            IFX_MEI_DMAWrite (pDev, IRAM1_BASE, &reg_data, 1);
764            break;
765        case 0xD0000:
766            reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) |
767                 (IRAM1_ADDR_BIT_MASK + 0x1));
768            IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, &reg_data, 1);
769            break;
770        case 0xE0000:
771            reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) |
772                 (BRAM_ADDR_BIT_MASK + 0x1));
773            IFX_MEI_DMAWrite (pDev, BRAM_BASE, &reg_data, 1);
774            break;
775        case 0xF0000:
776            reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) |
777                 (BRAM_ADDR_BIT_MASK + 0x1));
778            IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, &reg_data, 1);
779            break;
780        default: // PPE efuse
781            break;
782        }
783    }
784    IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
785    IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data & ~(1 << 24));
786    IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
787}
788
789/**
790 * Enable DFE Clock
791 * This function enables DFE Clock
792 *
793 * \param pDev the device pointer
794 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
795 * \ingroup Internal
796 */
797static DSL_DEV_MeiError_t
798IFX_MEI_EnableCLK (DSL_DEV_Device_t * pDev)
799{
800    u32 arc_debug_data = 0;
801    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
802    //enable ac_clk signal
803    _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK,
804                    CRI_CCR0, &arc_debug_data);
805    arc_debug_data |= ACL_CLK_MODE_ENABLE;
806    _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK,
807                     CRI_CCR0, arc_debug_data);
808    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
809    return DSL_DEV_MEI_ERR_SUCCESS;
810}
811
812/**
813 * Halt the ARC.
814 * This function halts the ARC.
815 *
816 * \param pDev the device pointer
817 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
818 * \ingroup Internal
819 */
820static DSL_DEV_MeiError_t
821IFX_MEI_HaltArc (DSL_DEV_Device_t * pDev)
822{
823    u32 arc_debug_data = 0x0;
824
825    // Switch arc control from JTAG mode to MEI mode
826    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
827    _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK,
828                    ARC_DEBUG, &arc_debug_data);
829    arc_debug_data |= ARC_DEBUG_HALT;
830    _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
831                     ARC_DEBUG, arc_debug_data);
832    // Switch arc control from MEI mode to JTAG mode
833    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
834
835    MEI_WAIT (10);
836
837    return DSL_DEV_MEI_ERR_SUCCESS;
838}
839
840/**
841 * Run the ARC.
842 * This function runs the ARC.
843 *
844 * \param pDev the device pointer
845 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
846 * \ingroup Internal
847 */
848static DSL_DEV_MeiError_t
849IFX_MEI_RunArc (DSL_DEV_Device_t * pDev)
850{
851    u32 arc_debug_data = 0x0;
852
853    // Switch arc control from JTAG mode to MEI mode- write '1' to bit0
854    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
855    _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK,
856                    AUX_STATUS, &arc_debug_data);
857
858    // Write debug data reg with content ANDd with 0xFDFFFFFF (halt bit cleared)
859    arc_debug_data &= ~ARC_AUX_HALT;
860    _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
861                     AUX_STATUS, arc_debug_data);
862
863    // Switch arc control from MEI mode to JTAG mode- write '0' to bit0
864    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
865    // Enable mask for arc codeswap interrupts
866    IFX_MEI_IRQEnable (pDev);
867
868    return DSL_DEV_MEI_ERR_SUCCESS;
869
870}
871
872/**
873 * Reset the ARC.
874 * This function resets the ARC.
875 *
876 * \param pDev the device pointer
877 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
878 * \ingroup Internal
879 */
880static DSL_DEV_MeiError_t
881IFX_MEI_ResetARC (DSL_DEV_Device_t * pDev)
882{
883    u32 arc_debug_data = 0;
884
885    IFX_MEI_HaltArc (pDev);
886
887    IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &arc_debug_data);
888    IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST,
889        arc_debug_data | LTQ_RCU_RST_REQ_DFE | LTQ_RCU_RST_REQ_AFE);
890
891    // reset ARC
892    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, MEI_SOFT_RESET);
893    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, 0);
894
895    IFX_MEI_IRQDisable (pDev);
896
897    IFX_MEI_EnableCLK (pDev);
898
899#if 0
900    // reset part of PPE
901    *(unsigned long *) (BSP_PPE32_SRST) = 0xC30;
902    *(unsigned long *) (BSP_PPE32_SRST) = 0xFFF;
903#endif
904
905    DSL_DEV_PRIVATE(pDev)->modem_ready = 0;
906
907    return DSL_DEV_MEI_ERR_SUCCESS;
908}
909
910DSL_DEV_MeiError_t
911DSL_BSP_Showtime (DSL_DEV_Device_t * dev, DSL_uint32_t rate_fast, DSL_uint32_t rate_intl)
912{
913    struct port_cell_info port_cell = {0};
914
915    IFX_MEI_EMSG ("Datarate US intl = %d, fast = %d\n", (int)rate_intl,
916                (int)rate_fast);
917
918    if ( rate_fast )
919        g_tx_link_rate[0] = rate_fast / (53 * 8);
920    if ( rate_intl )
921        g_tx_link_rate[1] = rate_intl / (53 * 8);
922
923    if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ) {
924        IFX_MEI_EMSG ("Got rate fail.\n");
925    }
926
927    if ( ifx_mei_atm_showtime_enter )
928    {
929        port_cell.port_num = 2;
930        port_cell.tx_link_rate[0] = g_tx_link_rate[0];
931        port_cell.tx_link_rate[1] = g_tx_link_rate[1];
932        ifx_mei_atm_showtime_enter(&port_cell, g_xdata_addr);
933    }
934    else
935    {
936        IFX_MEI_EMSG("no hookup from ATM driver to set cell rate\n");
937    }
938
939    return DSL_DEV_MEI_ERR_SUCCESS;
940};
941
942/**
943 * Reset/halt/run the DFE.
944 * This function provide operations to reset/halt/run the DFE.
945 *
946 * \param pDev the device pointer
947 * \param mode which operation want to do
948 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
949 * \ingroup Internal
950 */
951static DSL_DEV_MeiError_t
952IFX_MEI_CpuModeSet (DSL_DEV_Device_t *pDev,
953              DSL_DEV_CpuMode_t mode)
954{
955    DSL_DEV_MeiError_t err_ret = DSL_DEV_MEI_ERR_FAILURE;
956    switch (mode) {
957    case DSL_CPU_HALT:
958        err_ret = IFX_MEI_HaltArc (pDev);
959        break;
960    case DSL_CPU_RUN:
961        err_ret = IFX_MEI_RunArc (pDev);
962        break;
963    case DSL_CPU_RESET:
964        err_ret = IFX_MEI_ResetARC (pDev);
965        break;
966    default:
967        break;
968    }
969    return err_ret;
970}
971
972/**
973 * Accress DFE memory.
974 * This function provide a way to access DFE memory;
975 *
976 * \param pDev the device pointer
977 * \param type read or write
978 * \param destaddr destination address
979 * \param databuff pointer to hold data
980 * \param databuffsize size want to read/write
981 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
982 * \ingroup Internal
983 */
984DSL_DEV_MeiError_t
985DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t * pDev,
986                DSL_BSP_MemoryAccessType_t type,
987                DSL_uint32_t destaddr, DSL_uint32_t *databuff,
988                DSL_uint32_t databuffsize)
989{
990    DSL_DEV_MeiError_t meierr = DSL_DEV_MEI_ERR_SUCCESS;
991    switch (type) {
992    case DSL_BSP_MEMORY_READ:
993        meierr = IFX_MEI_DebugRead (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize);
994        break;
995    case DSL_BSP_MEMORY_WRITE:
996        meierr = IFX_MEI_DebugWrite (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize);
997        break;
998    }
999    return DSL_DEV_MEI_ERR_SUCCESS;
1000};
1001
1002/**
1003 * Download boot code to ARC.
1004 * This function downloads boot code to ARC.
1005 *
1006 * \param pDev the device pointer
1007 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
1008 * \ingroup Internal
1009 */
1010static DSL_DEV_MeiError_t
1011IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *pDev)
1012{
1013    IFX_MEI_IRQDisable (pDev);
1014
1015    IFX_MEI_EnableCLK (pDev);
1016
1017    IFX_MEI_FuseProg (pDev); //program fuse rar
1018
1019    IFX_MEI_DownloadBootPages (pDev);
1020
1021    return DSL_DEV_MEI_ERR_SUCCESS;
1022};
1023
1024/**
1025 * Enable Jtag debugger interface
1026 * This function setups mips gpio to enable jtag debugger
1027 *
1028 * \param pDev the device pointer
1029 * \param enable enable or disable
1030 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
1031 * \ingroup Internal
1032 */
1033static DSL_DEV_MeiError_t
1034IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *dev, int enable)
1035{
1036    /*
1037    int meierr=0;
1038    u32 reg_data;
1039    switch (enable) {
1040    case 1:
1041                //reserve gpio 9, 10, 11, 14, 19 for ARC JTAG
1042        ifxmips_port_reserve_pin (0, 9);
1043        ifxmips_port_reserve_pin (0, 10);
1044        ifxmips_port_reserve_pin (0, 11);
1045        ifxmips_port_reserve_pin (0, 14);
1046        ifxmips_port_reserve_pin (1, 3);
1047
1048        ifxmips_port_set_dir_in(0, 11);
1049        ifxmips_port_clear_altsel0(0, 11);
1050        ifxmips_port_clear_altsel1(0, 11);
1051        ifxmips_port_set_open_drain(0, 11);
1052        //enable ARC JTAG
1053        IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
1054        IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | LTQ_RCU_RST_REQ_ARC_JTAG);
1055        break;
1056    case 0:
1057    default:
1058        break;
1059    }
1060jtag_end:
1061    if (meierr)
1062        return DSL_DEV_MEI_ERR_FAILURE;
1063*/
1064
1065    return DSL_DEV_MEI_ERR_SUCCESS;
1066};
1067
1068/**
1069 * Enable DFE to MIPS interrupt
1070 * This function enable DFE to MIPS interrupt
1071 *
1072 * \param pDev the device pointer
1073 * \param enable enable or disable
1074 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
1075 * \ingroup Internal
1076 */
1077static DSL_DEV_MeiError_t
1078IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *pDev, int enable)
1079{
1080    DSL_DEV_MeiError_t meierr;
1081    switch (enable) {
1082    case 0:
1083        meierr = DSL_DEV_MEI_ERR_SUCCESS;
1084        IFX_MEI_IRQDisable (pDev);
1085        break;
1086    case 1:
1087        IFX_MEI_IRQEnable (pDev);
1088        meierr = DSL_DEV_MEI_ERR_SUCCESS;
1089        break;
1090    default:
1091        meierr = DSL_DEV_MEI_ERR_FAILURE;
1092        break;
1093
1094    }
1095    return meierr;
1096}
1097
1098/**
1099 * Get the modem status
1100 * This function return the modem status
1101 *
1102 * \param pDev the device pointer
1103 * \return 1: modem ready 0: not ready
1104 * \ingroup Internal
1105 */
1106static int
1107IFX_MEI_IsModemReady (DSL_DEV_Device_t * pDev)
1108{
1109    return DSL_DEV_PRIVATE(pDev)->modem_ready;
1110}
1111
1112DSL_DEV_MeiError_t
1113DSL_BSP_AdslLedInit (DSL_DEV_Device_t * dev,
1114              DSL_DEV_LedId_t led_number,
1115              DSL_DEV_LedType_t type,
1116              DSL_DEV_LedHandler_t handler)
1117{
1118#if 0
1119        struct led_config_param param;
1120        if (led_number == DSL_LED_LINK_ID && type == DSL_LED_LINK_TYPE && handler == /*DSL_LED_HD_CPU*/DSL_LED_HD_FW) {
1121                param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE;
1122                param.led = 0x01;
1123                param.source = 0x01;
1124// bsp_led_config (&param);
1125
1126        } else if (led_number == DSL_LED_DATA_ID && type == DSL_LED_DATA_TYPE && (handler == DSL_LED_HD_FW)) {
1127                param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE;
1128                param.led = 0x02;
1129                param.source = 0x02;
1130// bsp_led_config (&param);
1131        }
1132#endif
1133        return DSL_DEV_MEI_ERR_SUCCESS;
1134};
1135#if 0
1136DSL_DEV_MeiError_t
1137DSL_BSP_AdslLedSet (DSL_DEV_Device_t * dev, DSL_DEV_LedId_t led_number, DSL_DEV_LedMode_t mode)
1138{
1139    printk(KERN_INFO "[%s %d]: mode = %#x, led_number = %d\n", __func__, __LINE__, mode, led_number);
1140    switch (mode) {
1141    case DSL_LED_OFF:
1142        switch (led_number) {
1143        case DSL_LED_LINK_ID:
1144#ifdef CONFIG_BSP_LED
1145            bsp_led_set_blink (1, 0);
1146            bsp_led_set_data (1, 0);
1147#endif
1148            break;
1149        case DSL_LED_DATA_ID:
1150#ifdef CONFIG_BSP_LED
1151            bsp_led_set_blink (0, 0);
1152            bsp_led_set_data (0, 0);
1153#endif
1154            break;
1155        }
1156        break;
1157    case DSL_LED_FLASH:
1158        switch (led_number) {
1159        case DSL_LED_LINK_ID:
1160#ifdef CONFIG_BSP_LED
1161            bsp_led_set_blink (1, 1); // data
1162#endif
1163            break;
1164        case DSL_LED_DATA_ID:
1165#ifdef CONFIG_BSP_LED
1166            bsp_led_set_blink (0, 1); // data
1167#endif
1168            break;
1169        }
1170        break;
1171    case DSL_LED_ON:
1172        switch (led_number) {
1173        case DSL_LED_LINK_ID:
1174#ifdef CONFIG_BSP_LED
1175            bsp_led_set_blink (1, 0);
1176            bsp_led_set_data (1, 1);
1177#endif
1178            break;
1179        case DSL_LED_DATA_ID:
1180#ifdef CONFIG_BSP_LED
1181            bsp_led_set_blink (0, 0);
1182            bsp_led_set_data (0, 1);
1183#endif
1184            break;
1185        }
1186        break;
1187    }
1188    return DSL_DEV_MEI_ERR_SUCCESS;
1189};
1190
1191#endif
1192
1193/**
1194* Compose a message.
1195* This function compose a message from opcode, group, address, index, size, and data
1196*
1197* \param opcode The message opcode
1198* \param group The message group number
1199* \param address The message address.
1200* \param index The message index.
1201* \param size The number of words to read/write.
1202* \param data The pointer to data.
1203* \param CMVMSG The pointer to message buffer.
1204* \ingroup Internal
1205*/
1206void
1207makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, u16 * data, u16 *CMVMSG)
1208{
1209        memset (CMVMSG, 0, MSG_LENGTH * 2);
1210        CMVMSG[0] = (opcode << 4) + (size & 0xf);
1211        CMVMSG[1] = (((index == 0) ? 0 : 1) << 7) + (group & 0x7f);
1212        CMVMSG[2] = address;
1213        CMVMSG[3] = index;
1214        if (opcode == H2D_CMV_WRITE)
1215                memcpy (CMVMSG + 4, data, size * 2);
1216        return;
1217}
1218
1219/**
1220 * Send a message to ARC and read the response
1221 * This function sends a message to arc, waits the response, and reads the responses.
1222 *
1223 * \param pDev the device pointer
1224 * \param request Pointer to the request
1225 * \param reply Wait reply or not.
1226 * \param response Pointer to the response
1227 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
1228 * \ingroup Internal
1229 */
1230DSL_DEV_MeiError_t
1231DSL_BSP_SendCMV (DSL_DEV_Device_t * pDev, u16 * request, int reply, u16 * response) // write cmv to arc, if reply needed, wait for reply
1232{
1233    DSL_DEV_MeiError_t meierror;
1234#if defined(BSP_PORT_RTEMS)
1235    int delay_counter = 0;
1236#endif
1237
1238    if (MEI_MUTEX_LOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema))
1239        return -ERESTARTSYS;
1240
1241    DSL_DEV_PRIVATE(pDev)->cmv_reply = reply;
1242    memset (DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, 0,
1243        sizeof (DSL_DEV_PRIVATE(pDev)->
1244            CMV_RxMsg));
1245    DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
1246
1247    meierror = IFX_MEI_MailboxWrite (pDev, request, MSG_LENGTH);
1248
1249    if (meierror != DSL_DEV_MEI_ERR_SUCCESS) {
1250        DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0;
1251        DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
1252        IFX_MEI_EMSG ("MailboxWrite Fail!\n");
1253        IFX_MEI_EMSG ("Resetting ARC...\n");
1254        IFX_MEI_ResetARC(pDev);
1255        MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
1256        return meierror;
1257    }
1258    else {
1259        DSL_DEV_PRIVATE(pDev)->cmv_count++;
1260    }
1261
1262    if (DSL_DEV_PRIVATE(pDev)->cmv_reply ==
1263        NO_REPLY) {
1264        MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
1265        return DSL_DEV_MEI_ERR_SUCCESS;
1266    }
1267
1268#if !defined(BSP_PORT_RTEMS)
1269    if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0)
1270        MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav, CMV_TIMEOUT);
1271#else
1272    while (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0 && delay_counter < CMV_TIMEOUT / 5) {
1273        MEI_WAIT (5);
1274        delay_counter++;
1275    }
1276#endif
1277
1278    DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0;
1279    if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0) { //CMV_timeout
1280        DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
1281        IFX_MEI_EMSG ("\%s: DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT\n",
1282                    __FUNCTION__);
1283        MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
1284        return DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT;
1285    }
1286    else {
1287        DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
1288        DSL_DEV_PRIVATE(pDev)->
1289            reply_count++;
1290        memcpy (response, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2);
1291        MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
1292        return DSL_DEV_MEI_ERR_SUCCESS;
1293    }
1294    MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
1295    return DSL_DEV_MEI_ERR_SUCCESS;
1296}
1297
1298/**
1299 * Reset the ARC, download boot codes, and run the ARC.
1300 * This function resets the ARC, downloads boot codes to ARC, and runs the ARC.
1301 *
1302 * \param pDev the device pointer
1303 * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
1304 * \ingroup Internal
1305 */
1306static DSL_DEV_MeiError_t
1307IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
1308{
1309    int nSize = 0, idx = 0;
1310    uint32_t im0_register, im2_register;
1311// DSL_DEV_WinHost_Message_t m;
1312
1313    if (mei_arc_swap_buff == NULL) {
1314        mei_arc_swap_buff =
1315            (u32 *) kmalloc (MAXSWAPSIZE * 4, GFP_KERNEL);
1316        if (mei_arc_swap_buff == NULL) {
1317            IFX_MEI_EMSG (">>> malloc fail for codeswap buff!!! <<<\n");
1318            return DSL_DEV_MEI_ERR_FAILURE;
1319        }
1320                IFX_MEI_DMSG("allocate %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff);
1321    }
1322
1323    DSL_DEV_PRIVATE(pDev)->img_hdr =
1324        (ARC_IMG_HDR *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[0].address;
1325    if ((DSL_DEV_PRIVATE(pDev)->img_hdr->
1326         count) * sizeof (ARC_SWP_PAGE_HDR) > SDRAM_SEGMENT_SIZE) {
1327        IFX_MEI_EMSG ("firmware header size is bigger than 64K segment size\n");
1328        return DSL_DEV_MEI_ERR_FAILURE;
1329    }
1330    // check image size
1331    for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) {
1332        nSize += DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].nCopy;
1333    }
1334    if (nSize !=
1335        DSL_DEV_PRIVATE(pDev)->image_size) {
1336        IFX_MEI_EMSG ("Firmware download is not completed. Please download firmware again!\n");
1337        return DSL_DEV_MEI_ERR_FAILURE;
1338    }
1339    // TODO: check crc
1340    ///
1341
1342    IFX_MEI_ResetARC (pDev);
1343    IFX_MEI_HaltArc (pDev);
1344    IFX_MEI_BarUpdate (pDev, DSL_DEV_PRIVATE(pDev)->nBar);
1345
1346    //IFX_MEI_DMSG("Starting to meiDownloadBootCode\n");
1347
1348    IFX_MEI_DownloadBootCode (pDev);
1349
1350    im0_register = (*LTQ_ICU_IM0_IER) & (1 << 20);
1351    im2_register = (*LTQ_ICU_IM2_IER) & (1 << 20);
1352    /* Turn off irq */
1353    #ifdef CONFIG_SOC_AMAZON_SE
1354#define IFXMIPS_USB_OC_INT0 (INT_NUM_IM4_IRL0 + 23)
1355    disable_irq (IFXMIPS_USB_OC_INT0);
1356// disable_irq (IFXMIPS_USB_OC_INT2);
1357    #elif defined(CONFIG_SOC_AR9)
1358#define IFXMIPS_USB_OC_INT0 (INT_NUM_IM4_IRL1 + 28)
1359    disable_irq (IFXMIPS_USB_OC_INT0);
1360// disable_irq (IFXMIPS_USB_OC_INT2);
1361    #elif defined(CONFIG_SOC_XWAY)
1362    disable_irq (LTQ_USB_OC_INT);
1363    #else
1364    #error unkonwn arch
1365    #endif
1366    disable_irq (pDev->nIrq[IFX_DYING_GASP]);
1367
1368    IFX_MEI_RunArc (pDev);
1369
1370    MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready, 1000);
1371
1372    #ifdef CONFIG_SOC_AMAZON_SE
1373    MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
1374// MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
1375    #elif defined(CONFIG_SOC_AR9)
1376    MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
1377// MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
1378    #elif defined(CONFIG_SOC_XWAY)
1379    MEI_MASK_AND_ACK_IRQ (LTQ_USB_OC_INT);
1380    #else
1381    #error unkonwn arch
1382    #endif
1383    MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]);
1384
1385    /* Re-enable irq */
1386    enable_irq(pDev->nIrq[IFX_DYING_GASP]);
1387    *LTQ_ICU_IM0_IER |= im0_register;
1388    *LTQ_ICU_IM2_IER |= im2_register;
1389
1390    if (DSL_DEV_PRIVATE(pDev)->modem_ready != 1) {
1391        IFX_MEI_EMSG ("Modem failed to be ready!\n");
1392        return DSL_DEV_MEI_ERR_FAILURE;
1393    } else {
1394        IFX_MEI_DMSG("Modem is ready.\n");
1395        return DSL_DEV_MEI_ERR_SUCCESS;
1396    }
1397}
1398
1399/**
1400 * Get the page's data pointer
1401 * This function caculats the data address from the firmware header.
1402 *
1403 * \param pDev the device pointer
1404 * \param Page The page number.
1405 * \param data Data page or program page.
1406 * \param MaxSize The maximum size to read.
1407 * \param Buffer Pointer to data.
1408 * \param Dest Pointer to the destination address.
1409 * \return The number of bytes to read.
1410 * \ingroup Internal
1411 */
1412static int
1413IFX_MEI_GetPage (DSL_DEV_Device_t * pDev, u32 Page, u32 data,
1414               u32 MaxSize, u32 * Buffer, u32 * Dest)
1415{
1416    u32 size;
1417    u32 i;
1418    u32 *p;
1419    u32 idx, offset, nBar = 0;
1420
1421    if (Page > DSL_DEV_PRIVATE(pDev)->img_hdr->count)
1422        return -2;
1423    /*
1424     ** Get program or data size, depending on "data" flag
1425     */
1426    size = (data == GET_DATA) ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_size) :
1427                 (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_size);
1428    size &= BOOT_FLAG_MASK; // Clear boot bit!
1429    if (size > MaxSize)
1430        return -1;
1431
1432    if (size == 0)
1433        return 0;
1434    /*
1435     ** Get program or data offset, depending on "data" flag
1436     */
1437    i = data ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_offset) :
1438            (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_offset);
1439
1440    /*
1441     ** Copy data/program to buffer
1442     */
1443
1444    idx = i / SDRAM_SEGMENT_SIZE;
1445    offset = i % SDRAM_SEGMENT_SIZE;
1446    p = (u32 *) ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address + offset);
1447
1448    for (i = 0; i < size; i++) {
1449        if (offset + i * 4 - (nBar * SDRAM_SEGMENT_SIZE) >= SDRAM_SEGMENT_SIZE) {
1450            idx++;
1451            nBar++;
1452            p = (u32 *) ((u8 *) KSEG1ADDR ((u32)DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address));
1453        }
1454        Buffer[i] = *p++;
1455    }
1456
1457    /*
1458     ** Pass back data/program destination address
1459     */
1460    *Dest = data ? (DSL_DEV_PRIVATE(pDev)-> img_hdr->page[Page].d_dest) :
1461                (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_dest);
1462
1463    return size;
1464}
1465
1466/**
1467 * Free the memory for ARC firmware
1468 *
1469 * \param pDev the device pointer
1470 * \param type Free all memory or free the unused memory after showtime
1471 * \ingroup Internal
1472 */
1473const char *free_str[4] = {"Invalid", "Free_Reload", "Free_Showtime", "Free_All"};
1474static int
1475IFX_MEI_DFEMemoryFree (DSL_DEV_Device_t * pDev, int type)
1476{
1477        int idx = 0;
1478        smmu_mem_info_t *adsl_mem_info =
1479                DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
1480
1481        for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) {
1482                if (type == FREE_ALL ||adsl_mem_info[idx].type == type) {
1483                        if (adsl_mem_info[idx].size > 0) {
1484                                IFX_MEI_DMSG ("Freeing memory %p (%s)\n", adsl_mem_info[idx].org_address, free_str[adsl_mem_info[idx].type]);
1485                                if ( idx == XDATA_REGISTER ) {
1486                                    g_xdata_addr = NULL;
1487                                    if ( ifx_mei_atm_showtime_exit )
1488                                        ifx_mei_atm_showtime_exit();
1489                                }
1490                kfree (adsl_mem_info[idx].org_address);
1491                                adsl_mem_info[idx].org_address = 0;
1492                                adsl_mem_info[idx].address = 0;
1493                                adsl_mem_info[idx].size = 0;
1494                                adsl_mem_info[idx].type = 0;
1495                                adsl_mem_info[idx].nCopy = 0;
1496                        }
1497                }
1498        }
1499
1500    if(mei_arc_swap_buff != NULL){
1501                IFX_MEI_DMSG("free %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff);
1502        kfree(mei_arc_swap_buff);
1503        mei_arc_swap_buff=NULL;
1504    }
1505
1506        return 0;
1507}
1508static int
1509IFX_MEI_DFEMemoryAlloc (DSL_DEV_Device_t * pDev, long size)
1510{
1511    unsigned long mem_ptr;
1512    char *org_mem_ptr = NULL;
1513    int idx = 0;
1514    long total_size = 0;
1515    int err = 0;
1516    smmu_mem_info_t *adsl_mem_info =
1517        ((ifx_mei_device_private_t *) pDev->pPriv)->adsl_mem_info;
1518// DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
1519    int allocate_size = SDRAM_SEGMENT_SIZE;
1520
1521    IFX_MEI_DMSG("image_size = %ld\n", size);
1522    // Alloc Swap Pages
1523    for (idx = 0; size > 0 && idx < MAX_BAR_REGISTERS; idx++) {
1524        // skip bar15 for XDATA usage.
1525        if (idx == XDATA_REGISTER)
1526            continue;
1527#if 0
1528                if (size < SDRAM_SEGMENT_SIZE) {
1529                        allocate_size = size;
1530                        if (allocate_size < 1024)
1531                                allocate_size = 1024;
1532                }
1533#endif
1534                if (idx == (MAX_BAR_REGISTERS - 1))
1535                        allocate_size = size;
1536                else
1537                        allocate_size = SDRAM_SEGMENT_SIZE;
1538        org_mem_ptr = kmalloc (allocate_size + 1024, GFP_KERNEL);
1539        if (org_mem_ptr == NULL) {
1540                        IFX_MEI_EMSG ("%d: kmalloc %d bytes memory fail!\n", idx, allocate_size);
1541            err = -ENOMEM;
1542            goto allocate_error;
1543        }
1544                mem_ptr = (unsigned long) (org_mem_ptr + 1023) & ~(1024 -1);
1545                adsl_mem_info[idx].address = (char *) mem_ptr;
1546                adsl_mem_info[idx].org_address = org_mem_ptr;
1547                adsl_mem_info[idx].size = allocate_size;
1548                size -= allocate_size;
1549                total_size += allocate_size;
1550    }
1551    if (size > 0) {
1552        IFX_MEI_EMSG ("Image size is too large!\n");
1553        err = -EFBIG;
1554        goto allocate_error;
1555    }
1556    err = idx;
1557    return err;
1558
1559      allocate_error:
1560    IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
1561    return err;
1562}
1563
1564/**
1565 * Program the BAR registers
1566 *
1567 * \param pDev the device pointer
1568 * \param nTotalBar The number of bar to program.
1569 * \ingroup Internal
1570 */
1571static int
1572IFX_MEI_BarUpdate (DSL_DEV_Device_t * pDev, int nTotalBar)
1573{
1574    int idx = 0;
1575    smmu_mem_info_t *adsl_mem_info =
1576        DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
1577
1578    for (idx = 0; idx < nTotalBar; idx++) {
1579        //skip XDATA register
1580        if (idx == XDATA_REGISTER)
1581            continue;
1582        IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4,
1583            (((uint32_t) adsl_mem_info[idx].address) & 0x0FFFFFFF));
1584    }
1585    for (idx = nTotalBar; idx < MAX_BAR_REGISTERS; idx++) {
1586        if (idx == XDATA_REGISTER)
1587            continue;
1588        IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4,
1589             (((uint32_t)adsl_mem_info[nTotalBar - 1].address) & 0x0FFFFFFF));
1590        /* These are for /proc/danube_mei/meminfo purpose */
1591        adsl_mem_info[idx].address = adsl_mem_info[nTotalBar - 1].address;
1592        adsl_mem_info[idx].org_address = adsl_mem_info[nTotalBar - 1].org_address;
1593        adsl_mem_info[idx].size = 0; /* Prevent it from being freed */
1594    }
1595
1596    g_xdata_addr = adsl_mem_info[XDATA_REGISTER].address;
1597    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + XDATA_REGISTER * 4,
1598        (((uint32_t) adsl_mem_info [XDATA_REGISTER].address) & 0x0FFFFFFF));
1599    // update MEI_XDATA_BASE_SH
1600    IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH,
1601         ((unsigned long)adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF);
1602
1603    return DSL_DEV_MEI_ERR_SUCCESS;
1604}
1605
1606/* This copies the firmware from secondary storage to 64k memory segment in SDRAM */
1607DSL_DEV_MeiError_t
1608DSL_BSP_FWDownload (DSL_DEV_Device_t * pDev, const char *buf,
1609             unsigned long size, long *loff, long *current_offset)
1610{
1611    ARC_IMG_HDR img_hdr_tmp;
1612    smmu_mem_info_t *adsl_mem_info = DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
1613
1614    size_t nRead = 0, nCopy = 0;
1615    char *mem_ptr;
1616    ssize_t retval = -ENOMEM;
1617    int idx = 0;
1618
1619        IFX_MEI_DMSG("\n");
1620
1621    if (*loff == 0) {
1622        if (size < sizeof (img_hdr_tmp)) {
1623            IFX_MEI_EMSG ("Firmware size is too small!\n");
1624            return retval;
1625        }
1626        copy_from_user ((char *) &img_hdr_tmp, buf, sizeof (img_hdr_tmp));
1627        // header of image_size and crc are not included.
1628        DSL_DEV_PRIVATE(pDev)->image_size = le32_to_cpu (img_hdr_tmp.size) + 8;
1629
1630        if (DSL_DEV_PRIVATE(pDev)->image_size > 1024 * 1024) {
1631            IFX_MEI_EMSG ("Firmware size is too large!\n");
1632            return retval;
1633        }
1634        // check if arc is halt
1635        IFX_MEI_ResetARC (pDev);
1636        IFX_MEI_HaltArc (pDev);
1637
1638        IFX_MEI_DFEMemoryFree (pDev, FREE_ALL); //free all
1639
1640        retval = IFX_MEI_DFEMemoryAlloc (pDev, DSL_DEV_PRIVATE(pDev)->image_size);
1641        if (retval < 0) {
1642            IFX_MEI_EMSG ("Error: No memory space left.\n");
1643            goto error;
1644        }
1645        for (idx = 0; idx < retval; idx++) {
1646            //skip XDATA register
1647            if (idx == XDATA_REGISTER)
1648                continue;
1649            if (idx * SDRAM_SEGMENT_SIZE < le32_to_cpu (img_hdr_tmp.page[0].p_offset))
1650                adsl_mem_info[idx].type = FREE_RELOAD;
1651            else
1652                adsl_mem_info[idx].type = FREE_SHOWTIME;
1653        }
1654        DSL_DEV_PRIVATE(pDev)->nBar = retval;
1655
1656        DSL_DEV_PRIVATE(pDev)->img_hdr =
1657            (ARC_IMG_HDR *) adsl_mem_info[0].address;
1658
1659        adsl_mem_info[XDATA_REGISTER].org_address = kmalloc (SDRAM_SEGMENT_SIZE + 1024, GFP_KERNEL);
1660        adsl_mem_info[XDATA_REGISTER].address =
1661            (char *) ((unsigned long) (adsl_mem_info[XDATA_REGISTER].org_address + 1023) & 0xFFFFFC00);
1662
1663        adsl_mem_info[XDATA_REGISTER].size = SDRAM_SEGMENT_SIZE;
1664
1665        if (adsl_mem_info[XDATA_REGISTER].address == NULL) {
1666            IFX_MEI_EMSG ("kmalloc memory fail!\n");
1667            retval = -ENOMEM;
1668            goto error;
1669        }
1670        adsl_mem_info[XDATA_REGISTER].type = FREE_RELOAD;
1671        IFX_MEI_DMSG("-> IFX_MEI_BarUpdate()\n");
1672        IFX_MEI_BarUpdate (pDev, (DSL_DEV_PRIVATE(pDev)->nBar));
1673    }
1674    else if (DSL_DEV_PRIVATE(pDev)-> image_size == 0) {
1675        IFX_MEI_EMSG ("Error: Firmware size=0! \n");
1676        goto error;
1677    }
1678
1679    nRead = 0;
1680    while (nRead < size) {
1681        long offset = ((long) (*loff) + nRead) % SDRAM_SEGMENT_SIZE;
1682        idx = (((long) (*loff)) + nRead) / SDRAM_SEGMENT_SIZE;
1683        mem_ptr = (char *) KSEG1ADDR ((unsigned long) (adsl_mem_info[idx].address) + offset);
1684        if ((size - nRead + offset) > SDRAM_SEGMENT_SIZE)
1685            nCopy = SDRAM_SEGMENT_SIZE - offset;
1686        else
1687            nCopy = size - nRead;
1688        copy_from_user (mem_ptr, buf + nRead, nCopy);
1689        for (offset = 0; offset < (nCopy / 4); offset++) {
1690            ((unsigned long *) mem_ptr)[offset] = le32_to_cpu (((unsigned long *) mem_ptr)[offset]);
1691        }
1692        nRead += nCopy;
1693        adsl_mem_info[idx].nCopy += nCopy;
1694    }
1695
1696    *loff += size;
1697    *current_offset = size;
1698    return DSL_DEV_MEI_ERR_SUCCESS;
1699error:
1700    IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
1701    return DSL_DEV_MEI_ERR_FAILURE;
1702}
1703/*
1704 * Register a callback event.
1705 * Return:
1706 * -1 if the event already has a callback function registered.
1707 * 0 success
1708 */
1709int DSL_BSP_EventCBRegister(DSL_BSP_EventCallBack_t *p)
1710{
1711    if (!p) {
1712                IFX_MEI_EMSG("Invalid parameter!\n");
1713                return -EINVAL;
1714    }
1715        if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) {
1716                IFX_MEI_EMSG("Invalid Event %d\n", p->event);
1717                return -EINVAL;
1718        }
1719        if (dsl_bsp_event_callback[p->event].function) {
1720                IFX_MEI_EMSG("Event %d already has a callback function registered!\n", p->event);
1721                return -1;
1722        } else {
1723                dsl_bsp_event_callback[p->event].function = p->function;
1724                dsl_bsp_event_callback[p->event].event = p->event;
1725                dsl_bsp_event_callback[p->event].pData = p->pData;
1726        }
1727        return 0;
1728}
1729int DSL_BSP_EventCBUnregister(DSL_BSP_EventCallBack_t *p)
1730{
1731    if (!p) {
1732                IFX_MEI_EMSG("Invalid parameter!\n");
1733                return -EINVAL;
1734    }
1735        if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) {
1736                IFX_MEI_EMSG("Invalid Event %d\n", p->event);
1737                return -EINVAL;
1738        }
1739        if (dsl_bsp_event_callback[p->event].function) {
1740                IFX_MEI_EMSG("Unregistering Event %d...\n", p->event);
1741                dsl_bsp_event_callback[p->event].function = NULL;
1742                dsl_bsp_event_callback[p->event].pData = NULL;
1743        } else {
1744                IFX_MEI_EMSG("Event %d is not registered!\n", p->event);
1745                return -1;
1746        }
1747        return 0;
1748}
1749
1750/**
1751 * MEI Dying Gasp interrupt handler
1752 *
1753 * \param int1
1754 * \param void0
1755 * \param regs Pointer to the structure of danube mips registers
1756 * \ingroup Internal
1757 */
1758static irqreturn_t IFX_MEI_Dying_Gasp_IrqHandle (int int1, void *void0)
1759{
1760    DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
1761        DSL_BSP_CB_Type_t event;
1762
1763    if (pDev == NULL)
1764        IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n");
1765
1766#ifndef CONFIG_SMP
1767    disable_irq (pDev->nIrq[IFX_DYING_GASP]);
1768#else
1769    disable_irq_nosync(pDev->nIrq[IFX_DYING_GASP]);
1770#endif
1771    event = DSL_BSP_CB_DYING_GASP;
1772
1773    if (dsl_bsp_event_callback[event].function)
1774        (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
1775
1776#ifdef CONFIG_USE_EMULATOR
1777    IFX_MEI_EMSG("Dying Gasp! Shutting Down... (Work around for Amazon-S Venus emulator)\n");
1778#else
1779    IFX_MEI_EMSG("Dying Gasp! Shutting Down...\n");
1780// kill_proc (1, SIGINT, 1); /* Ask init to reboot us */
1781#endif
1782        return IRQ_HANDLED;
1783}
1784
1785extern void ifx_usb_enable_afe_oc(void);
1786
1787/**
1788 * MEI interrupt handler
1789 *
1790 * \param int1
1791 * \param void0
1792 * \param regs Pointer to the structure of danube mips registers
1793 * \ingroup Internal
1794 */
1795static irqreturn_t IFX_MEI_IrqHandle (int int1, void *void0)
1796{
1797    u32 scratch;
1798    DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
1799#if defined(CONFIG_LTQ_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST)
1800    dfe_loopback_irq_handler (pDev);
1801    return IRQ_HANDLED;
1802#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
1803        DSL_BSP_CB_Type_t event;
1804
1805    if (pDev == NULL)
1806        IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n");
1807
1808    IFX_MEI_DebugRead (pDev, ARC_MEI_MAILBOXR, &scratch, 1);
1809    if (scratch & OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK) {
1810        IFX_MEI_EMSG("Receive Code Swap Request interrupt!!!\n");
1811        return IRQ_HANDLED;
1812    }
1813    else if (scratch & OMB_CLEAREOC_INTERRUPT_CODE) {
1814        // clear eoc message interrupt
1815        IFX_MEI_DMSG("OMB_CLEAREOC_INTERRUPT_CODE\n");
1816                event = DSL_BSP_CB_CEOC_IRQ;
1817        IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
1818                if (dsl_bsp_event_callback[event].function)
1819            (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
1820        } else if (scratch & OMB_REBOOT_INTERRUPT_CODE) {
1821                // Reboot
1822                IFX_MEI_DMSG("OMB_REBOOT_INTERRUPT_CODE\n");
1823                event = DSL_BSP_CB_FIRMWARE_REBOOT;
1824
1825        IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
1826
1827                if (dsl_bsp_event_callback[event].function)
1828                        (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
1829        } else { // normal message
1830                IFX_MEI_MailboxRead (pDev, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH);
1831                if (DSL_DEV_PRIVATE(pDev)-> cmv_waiting == 1) {
1832                        DSL_DEV_PRIVATE(pDev)-> arcmsgav = 1;
1833                        DSL_DEV_PRIVATE(pDev)-> cmv_waiting = 0;
1834#if !defined(BSP_PORT_RTEMS)
1835                        MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav);
1836#endif
1837                }
1838        else {
1839            DSL_DEV_PRIVATE(pDev)-> modem_ready_cnt++;
1840            memcpy ((char *) DSL_DEV_PRIVATE(pDev)->Recent_indicator,
1841                (char *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2);
1842            if (((DSL_DEV_PRIVATE(pDev)->CMV_RxMsg[0] & 0xff0) >> 4) == D2H_AUTONOMOUS_MODEM_READY_MSG) {
1843                //check ARC ready message
1844                IFX_MEI_DMSG ("Got MODEM_READY_MSG\n");
1845                DSL_DEV_PRIVATE(pDev)->modem_ready = 1;
1846                MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready);
1847            }
1848        }
1849    }
1850
1851    return IRQ_HANDLED;
1852}
1853
1854int
1855DSL_BSP_ATMLedCBRegister (int (*ifx_adsl_ledcallback) (void))
1856{
1857    g_adsl_ledcallback = ifx_adsl_ledcallback;
1858    return 0;
1859}
1860
1861int
1862DSL_BSP_ATMLedCBUnregister (int (*ifx_adsl_ledcallback) (void))
1863{
1864    g_adsl_ledcallback = adsl_dummy_ledcallback;
1865    return 0;
1866}
1867
1868#if 0
1869int
1870DSL_BSP_EventCBRegister (int (*ifx_adsl_callback)
1871                    (DSL_BSP_CB_Event_t * param))
1872{
1873    int error = 0;
1874
1875    if (DSL_EventCB == NULL) {
1876        DSL_EventCB = ifx_adsl_callback;
1877    }
1878    else {
1879        error = -EIO;
1880    }
1881    return error;
1882}
1883
1884int
1885DSL_BSP_EventCBUnregister (int (*ifx_adsl_callback)
1886                  (DSL_BSP_CB_Event_t * param))
1887{
1888    int error = 0;
1889
1890    if (DSL_EventCB == ifx_adsl_callback) {
1891        DSL_EventCB = NULL;
1892    }
1893    else {
1894        error = -EIO;
1895    }
1896    return error;
1897}
1898
1899static int
1900DSL_BSP_GetEventCB (int (**ifx_adsl_callback)
1901               (DSL_BSP_CB_Event_t * param))
1902{
1903    *ifx_adsl_callback = DSL_EventCB;
1904    return 0;
1905}
1906#endif
1907
1908#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
1909#define mte_reg_base (0x4800*4+0x20000)
1910
1911/* Iridia Registers Address Constants */
1912#define MTE_Reg(r) (int)(mte_reg_base + (r*4))
1913
1914#define IT_AMODE MTE_Reg(0x0004)
1915
1916#define TIMER_DELAY (1024)
1917#define BC0_BYTES (32)
1918#define BC1_BYTES (30)
1919#define NUM_MB (12)
1920#define TIMEOUT_VALUE 2000
1921
1922static void
1923BFMWait (u32 cycle)
1924{
1925    u32 i;
1926    for (i = 0; i < cycle; i++);
1927}
1928
1929static void
1930WriteRegLong (u32 addr, u32 data)
1931{
1932    //*((volatile u32 *)(addr)) = data;
1933    IFX_MEI_WRITE_REGISTER_L (data, addr);
1934}
1935
1936static u32
1937ReadRegLong (u32 addr)
1938{
1939    // u32 rd_val;
1940    //rd_val = *((volatile u32 *)(addr));
1941    // return rd_val;
1942    return IFX_MEI_READ_REGISTER_L (addr);
1943}
1944
1945/* This routine writes the mailbox with the data in an input array */
1946static void
1947WriteMbox (u32 * mboxarray, u32 size)
1948{
1949    IFX_MEI_DebugWrite (&dsl_devices[0], IMBOX_BASE, mboxarray, size);
1950    IFX_MEI_DMSG("write to %X\n", IMBOX_BASE);
1951    IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV);
1952}
1953
1954/* This routine reads the output mailbox and places the results into an array */
1955static void
1956ReadMbox (u32 * mboxarray, u32 size)
1957{
1958    IFX_MEI_DebugRead (&dsl_devices[0], OMBOX_BASE, mboxarray, size);
1959    IFX_MEI_DMSG("read from %X\n", OMBOX_BASE);
1960}
1961
1962static void
1963MEIWriteARCValue (u32 address, u32 value)
1964{
1965    u32 i, check = 0;
1966
1967    /* Write address register */
1968    IFX_MEI_WRITE_REGISTER_L (address, ME_DBG_WR_AD + LTQ_MEI_BASE_ADDR);
1969
1970    /* Write data register */
1971    IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + LTQ_MEI_BASE_ADDR);
1972
1973    /* wait until complete - timeout at 40 */
1974    for (i = 0; i < 40; i++) {
1975        check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
1976
1977        if ((check & ARC_TO_MEI_DBG_DONE))
1978            break;
1979    }
1980    /* clear the flag */
1981    IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
1982}
1983
1984void
1985arc_code_page_download (uint32_t arc_code_length, uint32_t * start_address)
1986{
1987    int count;
1988
1989    IFX_MEI_DMSG("try to download pages,size=%d\n", arc_code_length);
1990    IFX_MEI_ControlModeSet (&dsl_devices[0], MEI_MASTER_MODE);
1991    IFX_MEI_HaltArc (&dsl_devices[0]);
1992    IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_AD, 0);
1993    for (count = 0; count < arc_code_length; count++) {
1994        IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_DATA,
1995                           *(start_address + count));
1996    }
1997    IFX_MEI_ControlModeSet (&dsl_devices[0], JTAG_MASTER_MODE);
1998}
1999static int
2000load_jump_table (unsigned long addr)
2001{
2002    int i;
2003    uint32_t addr_le, addr_be;
2004    uint32_t jump_table[32];
2005
2006    for (i = 0; i < 16; i++) {
2007        addr_le = i * 8 + addr;
2008        addr_be = ((addr_le >> 16) & 0xffff);
2009        addr_be |= ((addr_le & 0xffff) << 16);
2010        jump_table[i * 2 + 0] = 0x0f802020;
2011        jump_table[i * 2 + 1] = addr_be;
2012        //printk("jt %X %08X %08X\n",i,jump_table[i*2+0],jump_table[i*2+1]);
2013    }
2014    arc_code_page_download (32, &jump_table[0]);
2015return 0;
2016}
2017
2018int got_int = 0;
2019
2020void
2021dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev)
2022{
2023    uint32_t rd_mbox[10];
2024
2025    memset (&rd_mbox[0], 0, 10 * 4);
2026    ReadMbox (&rd_mbox[0], 6);
2027    if (rd_mbox[0] == 0x0) {
2028        FX_MEI_DMSG("Get ARC_ACK\n");
2029        got_int = 1;
2030    }
2031    else if (rd_mbox[0] == 0x5) {
2032        IFX_MEI_DMSG("Get ARC_BUSY\n");
2033        got_int = 2;
2034    }
2035    else if (rd_mbox[0] == 0x3) {
2036        IFX_MEI_DMSG("Get ARC_EDONE\n");
2037        if (rd_mbox[1] == 0x0) {
2038            got_int = 3;
2039            IFX_MEI_DMSG("Get E_MEMTEST\n");
2040            if (rd_mbox[2] != 0x1) {
2041                got_int = 4;
2042                IFX_MEI_DMSG("Get Result %X\n", rd_mbox[2]);
2043            }
2044        }
2045    }
2046    IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_STAT,
2047        ARC_TO_MEI_DBG_DONE);
2048    MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]);
2049    disable_irq (pDev->nIrq[IFX_DFEIR]);
2050    //got_int = 1;
2051    return;
2052}
2053
2054static void
2055wait_mem_test_result (void)
2056{
2057    uint32_t mbox[5];
2058    mbox[0] = 0;
2059
2060    IFX_MEI_DMSG("Waiting Starting\n");
2061    while (mbox[0] == 0) {
2062        ReadMbox (&mbox[0], 5);
2063    }
2064    IFX_MEI_DMSG("Try to get mem test result.\n");
2065    ReadMbox (&mbox[0], 5);
2066    if (mbox[0] == 0xA) {
2067        IFX_MEI_DMSG("Success.\n");
2068    }
2069    else if (mbox[0] == 0xA) {
2070        IFX_MEI_EMSG("Fail,address %X,except data %X,receive data %X\n",
2071            mbox[1], mbox[2], mbox[3]);
2072    }
2073    else {
2074        IFX_MEI_EMSG("Fail\n");
2075    }
2076}
2077
2078static int
2079arc_ping_testing (DSL_DEV_Device_t *pDev)
2080{
2081#define MEI_PING 0x00000001
2082    uint32_t wr_mbox[10], rd_mbox[10];
2083    int i;
2084
2085    for (i = 0; i < 10; i++) {
2086        wr_mbox[i] = 0;
2087        rd_mbox[i] = 0;
2088    }
2089
2090    FX_MEI_DMSG("send ping msg\n");
2091    wr_mbox[0] = MEI_PING;
2092    WriteMbox (&wr_mbox[0], 10);
2093
2094    while (got_int == 0) {
2095        MEI_WAIT (100);
2096    }
2097
2098    IFX_MEI_DMSG("send start event\n");
2099    got_int = 0;
2100
2101    wr_mbox[0] = 0x4;
2102    wr_mbox[1] = 0;
2103    wr_mbox[2] = 0;
2104    wr_mbox[3] = (uint32_t) 0xf5acc307e;
2105    wr_mbox[4] = 5;
2106    wr_mbox[5] = 2;
2107    wr_mbox[6] = 0x1c000;
2108    wr_mbox[7] = 64;
2109    wr_mbox[8] = 0;
2110    wr_mbox[9] = 0;
2111    WriteMbox (&wr_mbox[0], 10);
2112    DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]);
2113    //printk("IFX_MEI_MailboxWrite ret=%d\n",i);
2114    IFX_MEI_LongWordWriteOffset (&dsl_devices[0],
2115                       (u32) ME_ME2ARC_INT,
2116                       MEI_TO_ARC_MSGAV);
2117    IFX_MEI_DMSG("sleeping\n");
2118    while (1) {
2119        if (got_int > 0) {
2120
2121            if (got_int > 3)
2122                IFX_MEI_DMSG("got_int >>>> 3\n");
2123            else
2124                IFX_MEI_DMSG("got int = %d\n", got_int);
2125            got_int = 0;
2126            //schedule();
2127            DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]);
2128        }
2129        //mbox_read(&rd_mbox[0],6);
2130        MEI_WAIT (100);
2131    }
2132    return 0;
2133}
2134
2135static DSL_DEV_MeiError_t
2136DFE_Loopback_Test (void)
2137{
2138    int i = 0;
2139    u32 arc_debug_data = 0, temp;
2140    DSL_DEV_Device_t *pDev = &dsl_devices[0];
2141    uint32_t wr_mbox[10];
2142
2143    IFX_MEI_ResetARC (pDev);
2144    // start the clock
2145    arc_debug_data = ACL_CLK_MODE_ENABLE;
2146    IFX_MEI_DebugWrite (pDev, CRI_CCR0, &arc_debug_data, 1);
2147
2148#if defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK)
2149    // WriteARCreg(AUX_XMEM_LTEST,0);
2150    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
2151#define AUX_XMEM_LTEST 0x128
2152    _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XMEM_LTEST, 0);
2153    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
2154
2155    // WriteARCreg(AUX_XDMA_GAP,0);
2156    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
2157#define AUX_XDMA_GAP 0x114
2158    _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XDMA_GAP, 0);
2159    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
2160
2161    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
2162    temp = 0;
2163    _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
2164        (u32) ME_XDATA_BASE_SH + LTQ_MEI_BASE_ADDR, temp);
2165    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
2166
2167    i = IFX_MEI_DFEMemoryAlloc (pDev, SDRAM_SEGMENT_SIZE * 16);
2168    if (i >= 0) {
2169        int idx;
2170
2171        for (idx = 0; idx < i; idx++) {
2172            DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].type = FREE_RELOAD;
2173            IFX_MEI_WRITE_REGISTER_L ((((uint32_t) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address) & 0x0fffffff),
2174                            LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE + idx * 4);
2175            IFX_MEI_DMSG("bar%d(%X)=%X\n", idx,
2176                LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE +
2177                idx * 4, (((uint32_t)
2178                       ((ifx_mei_device_private_t *)
2179                        pDev->pPriv)->adsl_mem_info[idx].
2180                       address) & 0x0fffffff));
2181            memset ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address, 0, SDRAM_SEGMENT_SIZE);
2182        }
2183
2184        IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH,
2185                       ((unsigned long) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF);
2186    }
2187    else {
2188        IFX_MEI_EMSG ("cannot load image: no memory\n");
2189        return DSL_DEV_MEI_ERR_FAILURE;
2190    }
2191    //WriteARCreg(AUX_IC_CTRL,2);
2192    IFX_MEI_DMSG("Setting MEI_MASTER_MODE..\n");
2193    IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
2194#define AUX_IC_CTRL 0x11
2195    _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
2196                     AUX_IC_CTRL, 2);
2197    IFX_MEI_DMSG("Setting JTAG_MASTER_MODE..\n");
2198    IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
2199
2200    IFX_MEI_DMSG("Halting ARC...\n");
2201    IFX_MEI_HaltArc (&dsl_devices[0]);
2202
2203#ifdef DFE_PING_TEST
2204
2205    IFX_MEI_DMSG("ping test image size=%d\n", sizeof (arc_ahb_access_code));
2206    memcpy ((u8 *) (DSL_DEV_PRIVATE(pDev)->
2207            adsl_mem_info[0].address + 0x1004),
2208        &arc_ahb_access_code[0], sizeof (arc_ahb_access_code));
2209    load_jump_table (0x80000 + 0x1004);
2210
2211#endif //DFE_PING_TEST
2212
2213    IFX_MEI_DMSG("ARC ping test code download complete\n");
2214#endif //defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK)
2215#ifdef DFE_MEM_TEST
2216    IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_MASK, MSGAV_EN);
2217
2218    arc_code_page_download (1537, &code_array[0]);
2219    IFX_MEI_DMSG("ARC mem test code download complete\n");
2220#endif //DFE_MEM_TEST
2221#ifdef DFE_ATM_LOOPBACK
2222    arc_debug_data = 0xf;
2223    arc_code_page_download (sizeof(code_array) / sizeof(*code_array), &code_array[0]);
2224    wr_mbox[0] = 0; //TIMER_DELAY - org: 1024
2225    wr_mbox[1] = 0; //TXFB_START0
2226    wr_mbox[2] = 0x7f; //TXFB_END0 - org: 49
2227    wr_mbox[3] = 0x80; //TXFB_START1 - org: 80
2228    wr_mbox[4] = 0xff; //TXFB_END1 - org: 109
2229    wr_mbox[5] = 0x100; //RXFB_START0 - org: 0
2230    wr_mbox[6] = 0x17f; //RXFB_END0 - org: 49
2231    wr_mbox[7] = 0x180; //RXFB_START1 - org: 256
2232    wr_mbox[8] = 0x1ff; //RXFB_END1 - org: 315
2233    WriteMbox (&wr_mbox[0], 9);
2234    // Start Iridia IT_AMODE (in dmp access) why is it required?
2235    IFX_MEI_DebugWrite (&dsl_devices[0], 0x32010, &arc_debug_data, 1);
2236#endif //DFE_ATM_LOOPBACK
2237    IFX_MEI_IRQEnable (pDev);
2238    IFX_MEI_DMSG("run ARC...\n");
2239    IFX_MEI_RunArc (&dsl_devices[0]);
2240
2241#ifdef DFE_PING_TEST
2242    arc_ping_testing (pDev);
2243#endif //DFE_PING_TEST
2244#ifdef DFE_MEM_TEST
2245    wait_mem_test_result ();
2246#endif //DFE_MEM_TEST
2247
2248    IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
2249    return DSL_DEV_MEI_ERR_SUCCESS;
2250}
2251
2252#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
2253
2254static int
2255IFX_MEI_InitDevNode (int num)
2256{
2257    if (num == 0) {
2258        if ((dev_major = register_chrdev (dev_major, IFX_MEI_DEVNAME, &bsp_mei_operations)) < 0) {
2259            IFX_MEI_EMSG ("register_chrdev(%d %s) failed!\n", dev_major, IFX_MEI_DEVNAME);
2260            return -ENODEV;
2261        }
2262    }
2263    return 0;
2264}
2265
2266static int
2267IFX_MEI_CleanUpDevNode (int num)
2268{
2269    if (num == 0)
2270        unregister_chrdev (dev_major, MEI_DIRNAME);
2271    return 0;
2272}
2273
2274static int
2275IFX_MEI_InitDevice (int num)
2276{
2277    DSL_DEV_Device_t *pDev;
2278        u32 temp;
2279    pDev = &dsl_devices[num];
2280    if (pDev == NULL)
2281        return -ENOMEM;
2282    pDev->pPriv = &sDanube_Mei_Private[num];
2283    memset (pDev->pPriv, 0, sizeof (ifx_mei_device_private_t));
2284
2285    memset (&DSL_DEV_PRIVATE(pDev)->
2286        adsl_mem_info[0], 0,
2287        sizeof (smmu_mem_info_t) * MAX_BAR_REGISTERS);
2288
2289    if (num == 0) {
2290        pDev->nIrq[IFX_DFEIR] = LTQ_MEI_INT;
2291        pDev->nIrq[IFX_DYING_GASP] = LTQ_MEI_DYING_GASP_INT;
2292        pDev->base_address = KSEG1 + LTQ_MEI_BASE_ADDR;
2293
2294                /* Power up MEI */
2295#ifdef CONFIG_LANTIQ_AMAZON_SE
2296        *LTQ_PMU_PWDCR &= ~(1 << 9); // enable dsl
2297                *LTQ_PMU_PWDCR &= ~(1 << 15); // enable AHB base
2298#else
2299            temp = ltq_r32(LTQ_PMU_PWDCR);
2300            temp &= 0xffff7dbe;
2301            ltq_w32(temp, LTQ_PMU_PWDCR);
2302#endif
2303    }
2304    pDev->nInUse = 0;
2305    DSL_DEV_PRIVATE(pDev)->modem_ready = 0;
2306    DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
2307
2308    MEI_INIT_WAKELIST ("arcq", DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav); // for ARCMSGAV
2309    MEI_INIT_WAKELIST ("arcr", DSL_DEV_PRIVATE(pDev)->wait_queue_modemready); // for arc modem ready
2310
2311    MEI_MUTEX_INIT (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema, 1); // semaphore initialization, mutex
2312#if 0
2313    MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]);
2314    MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]);
2315#endif
2316    if (request_irq (pDev->nIrq[IFX_DFEIR], IFX_MEI_IrqHandle, 0, "DFEIR", pDev) != 0) {
2317        IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DFEIR]);
2318        return -1;
2319    }
2320    /*if (request_irq (pDev->nIrq[IFX_DYING_GASP], IFX_MEI_Dying_Gasp_IrqHandle, 0, "DYING_GASP", pDev) != 0) {
2321        IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DYING_GASP]);
2322        return -1;
2323    }*/
2324// IFX_MEI_DMSG("Device %d initialized. IER %#x\n", num, bsp_get_irq_ier(pDev->nIrq[IFX_DYING_GASP]));
2325    return 0;
2326}
2327
2328static int
2329IFX_MEI_ExitDevice (int num)
2330{
2331    DSL_DEV_Device_t *pDev;
2332    pDev = &dsl_devices[num];
2333
2334    if (pDev == NULL)
2335        return -EIO;
2336
2337    disable_irq (pDev->nIrq[IFX_DFEIR]);
2338    disable_irq (pDev->nIrq[IFX_DYING_GASP]);
2339
2340    free_irq(pDev->nIrq[IFX_DFEIR], pDev);
2341    free_irq(pDev->nIrq[IFX_DYING_GASP], pDev);
2342
2343    return 0;
2344}
2345
2346static DSL_DEV_Device_t *
2347IFX_BSP_HandleGet (int maj, int num)
2348{
2349    if (num > BSP_MAX_DEVICES)
2350        return NULL;
2351    return &dsl_devices[num];
2352}
2353
2354DSL_DEV_Device_t *
2355DSL_BSP_DriverHandleGet (int maj, int num)
2356{
2357    DSL_DEV_Device_t *pDev;
2358
2359    if (num > BSP_MAX_DEVICES)
2360        return NULL;
2361
2362    pDev = &dsl_devices[num];
2363    if (!try_module_get(pDev->owner))
2364        return NULL;
2365
2366    pDev->nInUse++;
2367    return pDev;
2368}
2369
2370int
2371DSL_BSP_DriverHandleDelete (DSL_DEV_Device_t * nHandle)
2372{
2373    DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) nHandle;
2374    if (pDev->nInUse)
2375        pDev->nInUse--;
2376        module_put(pDev->owner);
2377    return 0;
2378}
2379
2380static int
2381IFX_MEI_Open (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil)
2382{
2383    int maj = MAJOR (ino->i_rdev);
2384    int num = MINOR (ino->i_rdev);
2385
2386    DSL_DEV_Device_t *pDev = NULL;
2387    if ((pDev = DSL_BSP_DriverHandleGet (maj, num)) == NULL) {
2388        IFX_MEI_EMSG("open(%d:%d) fail!\n", maj, num);
2389        return -EIO;
2390    }
2391    fil->private_data = pDev;
2392    return 0;
2393}
2394
2395static int
2396IFX_MEI_Release (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil)
2397{
2398    //int maj = MAJOR(ino->i_rdev);
2399    int num = MINOR (ino->i_rdev);
2400    DSL_DEV_Device_t *pDev;
2401
2402    pDev = &dsl_devices[num];
2403    if (pDev == NULL)
2404        return -EIO;
2405    DSL_BSP_DriverHandleDelete (pDev);
2406    return 0;
2407}
2408
2409/**
2410 * Callback function for linux userspace program writing
2411 */
2412static ssize_t
2413IFX_MEI_Write (DSL_DRV_file_t * filp, const char *buf, size_t size, loff_t * loff)
2414{
2415    DSL_DEV_MeiError_t mei_error = DSL_DEV_MEI_ERR_FAILURE;
2416    long offset = 0;
2417    DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) filp->private_data;
2418
2419    if (pDev == NULL)
2420        return -EIO;
2421
2422    mei_error =
2423        DSL_BSP_FWDownload (pDev, buf, size, (long *) loff, &offset);
2424
2425    if (mei_error == DSL_DEV_MEI_ERR_FAILURE)
2426        return -EIO;
2427    return (ssize_t) offset;
2428}
2429
2430/**
2431 * Callback function for linux userspace program ioctling
2432 */
2433static int
2434IFX_MEI_IoctlCopyFrom (int from_kernel, char *dest, char *from, int size)
2435{
2436    int ret = 0;
2437
2438    if (!from_kernel)
2439        ret = copy_from_user ((char *) dest, (char *) from, size);
2440    else
2441        ret = (int)memcpy ((char *) dest, (char *) from, size);
2442    return ret;
2443}
2444
2445static int
2446IFX_MEI_IoctlCopyTo (int from_kernel, char *dest, char *from, int size)
2447{
2448    int ret = 0;
2449
2450    if (!from_kernel)
2451        ret = copy_to_user ((char *) dest, (char *) from, size);
2452    else
2453        ret = (int)memcpy ((char *) dest, (char *) from, size);
2454    return ret;
2455}
2456
2457static int
2458IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command, unsigned long lon)
2459{
2460    int i = 0;
2461    int meierr = DSL_DEV_MEI_ERR_SUCCESS;
2462    u32 base_address = LTQ_MEI_BASE_ADDR;
2463    DSL_DEV_WinHost_Message_t winhost_msg, m;
2464    DSL_DEV_MeiDebug_t debugrdwr;
2465    DSL_DEV_MeiReg_t regrdwr;
2466
2467    switch (command) {
2468
2469    case DSL_FIO_BSP_CMV_WINHOST:
2470        IFX_MEI_IoctlCopyFrom (from_kernel, (char *) winhost_msg.msg.TxMessage,
2471                         (char *) lon, MSG_LENGTH * 2);
2472
2473        if ((meierr = DSL_BSP_SendCMV (pDev, winhost_msg.msg.TxMessage, YES_REPLY,
2474                       winhost_msg.msg.RxMessage)) != DSL_DEV_MEI_ERR_SUCCESS) {
2475            IFX_MEI_EMSG ("WINHOST CMV fail :TxMessage:%X %X %X %X, RxMessage:%X %X %X %X %X\n",
2476                 winhost_msg.msg.TxMessage[0], winhost_msg.msg.TxMessage[1], winhost_msg.msg.TxMessage[2], winhost_msg.msg.TxMessage[3],
2477                 winhost_msg.msg.RxMessage[0], winhost_msg.msg.RxMessage[1], winhost_msg.msg.RxMessage[2], winhost_msg.msg.RxMessage[3],
2478                 winhost_msg.msg.RxMessage[4]);
2479            meierr = DSL_DEV_MEI_ERR_FAILURE;
2480        }
2481        else {
2482            IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
2483                           (char *) winhost_msg.msg.RxMessage,
2484                           MSG_LENGTH * 2);
2485        }
2486        break;
2487
2488    case DSL_FIO_BSP_CMV_READ:
2489        IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&regrdwr),
2490                         (char *) lon, sizeof (DSL_DEV_MeiReg_t));
2491
2492        IFX_MEI_LongWordRead ((u32) regrdwr.iAddress,
2493                        (u32 *) & (regrdwr.iData));
2494
2495        IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
2496                       (char *) (&regrdwr),
2497                       sizeof (DSL_DEV_MeiReg_t));
2498
2499        break;
2500
2501    case DSL_FIO_BSP_CMV_WRITE:
2502        IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&regrdwr),
2503                         (char *) lon, sizeof (DSL_DEV_MeiReg_t));
2504
2505        IFX_MEI_LongWordWrite ((u32) regrdwr.iAddress,
2506                         regrdwr.iData);
2507        break;
2508
2509    case DSL_FIO_BSP_GET_BASE_ADDRESS:
2510        IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
2511                       (char *) (&base_address),
2512                       sizeof (base_address));
2513        break;
2514
2515    case DSL_FIO_BSP_IS_MODEM_READY:
2516        i = IFX_MEI_IsModemReady (pDev);
2517        IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
2518                       (char *) (&i), sizeof (int));
2519        meierr = DSL_DEV_MEI_ERR_SUCCESS;
2520        break;
2521    case DSL_FIO_BSP_RESET:
2522    case DSL_FIO_BSP_REBOOT:
2523        meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RESET);
2524        meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT);
2525        break;
2526
2527    case DSL_FIO_BSP_HALT:
2528        meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT);
2529        break;
2530
2531    case DSL_FIO_BSP_RUN:
2532        meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RUN);
2533        break;
2534    case DSL_FIO_BSP_BOOTDOWNLOAD:
2535        meierr = IFX_MEI_DownloadBootCode (pDev);
2536        break;
2537    case DSL_FIO_BSP_JTAG_ENABLE:
2538        meierr = IFX_MEI_ArcJtagEnable (pDev, 1);
2539        break;
2540
2541    case DSL_FIO_BSP_REMOTE:
2542        IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&i),
2543                         (char *) lon, sizeof (int));
2544
2545        meierr = IFX_MEI_AdslMailboxIRQEnable (pDev, i);
2546        break;
2547
2548    case DSL_FIO_BSP_DSL_START:
2549        IFX_MEI_DMSG("DSL_FIO_BSP_DSL_START\n");
2550        if ((meierr = IFX_MEI_RunAdslModem (pDev)) != DSL_DEV_MEI_ERR_SUCCESS) {
2551            IFX_MEI_EMSG ("IFX_MEI_RunAdslModem() error...");
2552            meierr = DSL_DEV_MEI_ERR_FAILURE;
2553        }
2554        break;
2555
2556    case DSL_FIO_BSP_DEBUG_READ:
2557    case DSL_FIO_BSP_DEBUG_WRITE:
2558        IFX_MEI_IoctlCopyFrom (from_kernel,
2559                         (char *) (&debugrdwr),
2560                         (char *) lon,
2561                         sizeof (debugrdwr));
2562
2563        if (command == DSL_FIO_BSP_DEBUG_READ)
2564            meierr = DSL_BSP_MemoryDebugAccess (pDev,
2565                                 DSL_BSP_MEMORY_READ,
2566                                 debugrdwr.
2567                                 iAddress,
2568                                 debugrdwr.
2569                                 buffer,
2570                                 debugrdwr.
2571                                 iCount);
2572        else
2573            meierr = DSL_BSP_MemoryDebugAccess (pDev,
2574                                 DSL_BSP_MEMORY_WRITE,
2575                                 debugrdwr.
2576                                 iAddress,
2577                                 debugrdwr.
2578                                 buffer,
2579                                 debugrdwr.
2580                                 iCount);
2581
2582        IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&debugrdwr), sizeof (debugrdwr));
2583        break;
2584    case DSL_FIO_BSP_GET_VERSION:
2585        IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_mei_version), sizeof (DSL_DEV_Version_t));
2586        break;
2587
2588#define LTQ_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
2589    case DSL_FIO_BSP_GET_CHIP_INFO:
2590                bsp_chip_info.major = 1;
2591                bsp_chip_info.minor = LTQ_MPS_CHIPID_VERSION_GET(*LTQ_MPS_CHIPID);
2592                IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_chip_info), sizeof (DSL_DEV_HwVersion_t));
2593                meierr = DSL_DEV_MEI_ERR_SUCCESS;
2594        break;
2595
2596        case DSL_FIO_BSP_FREE_RESOURCE:
2597                makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_STAT, 4, 0, 1, NULL, m.msg.TxMessage);
2598                if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) {
2599                        meierr = DSL_DEV_MEI_ERR_FAILURE;
2600                        return -EIO;
2601                }
2602                IFX_MEI_DMSG("RxMessage[4] = %#x\n", m.msg.RxMessage[4]);
2603                if (!(m.msg.RxMessage[4] & DSL_DEV_STAT_CODESWAP_COMPLETE)) {
2604                        meierr = DSL_DEV_MEI_ERR_FAILURE;
2605                        return -EAGAIN;
2606                }
2607                IFX_MEI_DMSG("Freeing all memories marked FREE_SHOWTIME\n");
2608                IFX_MEI_DFEMemoryFree (pDev, FREE_SHOWTIME);
2609                meierr = DSL_DEV_MEI_ERR_SUCCESS;
2610        break;
2611#ifdef CONFIG_IFXMIPS_AMAZON_SE
2612    case DSL_FIO_ARC_MUX_TEST:
2613        AMAZON_SE_MEI_ARC_MUX_Test();
2614        break;
2615#endif
2616    default:
2617// IFX_MEI_EMSG("Invalid IOCTL command: %d\n");
2618        break;
2619    }
2620    return meierr;
2621}
2622
2623#ifdef CONFIG_IFXMIPS_AMAZON_SE
2624void AMAZON_SE_MEI_ARC_MUX_Test(void)
2625{
2626    u32 *p, i;
2627    *LTQ_RCU_RST |= LTQ_RCU_RST_REQ_MUX_ARC;
2628
2629    p = (u32*)(DFE_LDST_BASE_ADDR + IRAM0_BASE);
2630    IFX_MEI_EMSG("Writing to IRAM0(%p)...\n", p);
2631    for (i = 0; i < IRAM0_SIZE/sizeof(u32); i++, p++) {
2632        *p = 0xdeadbeef;
2633        if (*p != 0xdeadbeef)
2634            IFX_MEI_EMSG("%p: %#x\n", p, *p);
2635    }
2636
2637    p = (u32*)(DFE_LDST_BASE_ADDR + IRAM1_BASE);
2638    IFX_MEI_EMSG("Writing to IRAM1(%p)...\n", p);
2639    for (i = 0; i < IRAM1_SIZE/sizeof(u32); i++, p++) {
2640        *p = 0xdeadbeef;
2641        if (*p != 0xdeadbeef)
2642            IFX_MEI_EMSG("%p: %#x\n", p, *p);
2643    }
2644
2645    p = (u32*)(DFE_LDST_BASE_ADDR + BRAM_BASE);
2646    IFX_MEI_EMSG("Writing to BRAM(%p)...\n", p);
2647    for (i = 0; i < BRAM_SIZE/sizeof(u32); i++, p++) {
2648        *p = 0xdeadbeef;
2649        if (*p != 0xdeadbeef)
2650            IFX_MEI_EMSG("%p: %#x\n", p, *p);
2651    }
2652
2653    p = (u32*)(DFE_LDST_BASE_ADDR + XRAM_BASE);
2654    IFX_MEI_EMSG("Writing to XRAM(%p)...\n", p);
2655    for (i = 0; i < XRAM_SIZE/sizeof(u32); i++, p++) {
2656        *p = 0xdeadbeef;
2657        if (*p != 0xdeadbeef)
2658            IFX_MEI_EMSG("%p: %#x\n", p, *p);
2659    }
2660
2661    p = (u32*)(DFE_LDST_BASE_ADDR + YRAM_BASE);
2662    IFX_MEI_EMSG("Writing to YRAM(%p)...\n", p);
2663    for (i = 0; i < YRAM_SIZE/sizeof(u32); i++, p++) {
2664        *p = 0xdeadbeef;
2665        if (*p != 0xdeadbeef)
2666            IFX_MEI_EMSG("%p: %#x\n", p, *p);
2667    }
2668
2669    p = (u32*)(DFE_LDST_BASE_ADDR + EXT_MEM_BASE);
2670    IFX_MEI_EMSG("Writing to EXT_MEM(%p)...\n", p);
2671    for (i = 0; i < EXT_MEM_SIZE/sizeof(u32); i++, p++) {
2672        *p = 0xdeadbeef;
2673        if (*p != 0xdeadbeef)
2674            IFX_MEI_EMSG("%p: %#x\n", p, *p);
2675    }
2676    *LTQ_RCU_RST &= ~LTQ_RCU_RST_REQ_MUX_ARC;
2677}
2678#endif
2679int
2680DSL_BSP_KernelIoctls (DSL_DEV_Device_t * pDev, unsigned int command,
2681               unsigned long lon)
2682{
2683    int error = 0;
2684
2685    error = IFX_MEI_Ioctls (pDev, 1, command, lon);
2686    return error;
2687}
2688
2689#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
2690static int
2691IFX_MEI_UserIoctls (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil,
2692              unsigned int command, unsigned long lon)
2693#else
2694static int
2695IFX_MEI_UserIoctls (DSL_DRV_file_t * fil,
2696              unsigned int command, unsigned long lon)
2697#endif
2698{
2699    int error = 0;
2700#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
2701    int maj = MAJOR (ino->i_rdev);
2702    int num = MINOR (ino->i_rdev);
2703#endif
2704    DSL_DEV_Device_t *pDev;
2705
2706#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
2707    pDev = IFX_BSP_HandleGet (maj, num);
2708#else
2709    pDev = IFX_BSP_HandleGet (0, 0);
2710#endif
2711    if (pDev == NULL)
2712        return -EIO;
2713
2714    error = IFX_MEI_Ioctls (pDev, 0, command, lon);
2715    return error;
2716}
2717
2718#ifdef CONFIG_PROC_FS
2719/*
2720 * Register a callback function for linux proc filesystem
2721 */
2722static int
2723IFX_MEI_InitProcFS (int num)
2724{
2725    struct proc_dir_entry *entry;
2726    int i ;
2727    DSL_DEV_Device_t *pDev;
2728    reg_entry_t regs_temp[PROC_ITEMS] = {
2729        /* flag, name, description } */
2730        {NULL, "arcmsgav", "arc to mei message ", 0},
2731        {NULL, "cmv_reply", "cmv needs reply", 0},
2732        {NULL, "cmv_waiting", "waiting for cmv reply from arc", 0},
2733        {NULL, "modem_ready_cnt", "ARC to MEI indicator count", 0},
2734        {NULL, "cmv_count", "MEI to ARC CMVs", 0},
2735        {NULL, "reply_count", "ARC to MEI Reply", 0},
2736        {NULL, "Recent_indicator", "most recent indicator", 0},
2737        {NULL, "fw_version", "Firmware Version", 0},
2738        {NULL, "fw_date", "Firmware Date", 0},
2739        {NULL, "meminfo", "Memory Allocation Information", 0},
2740        {NULL, "version", "MEI version information", 0},
2741    };
2742
2743    pDev = &dsl_devices[num];
2744    if (pDev == NULL)
2745        return -ENOMEM;
2746
2747    regs_temp[0].flag = &(DSL_DEV_PRIVATE(pDev)->arcmsgav);
2748    regs_temp[1].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_reply);
2749    regs_temp[2].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_waiting);
2750    regs_temp[3].flag = &(DSL_DEV_PRIVATE(pDev)->modem_ready_cnt);
2751    regs_temp[4].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_count);
2752    regs_temp[5].flag = &(DSL_DEV_PRIVATE(pDev)->reply_count);
2753    regs_temp[6].flag = (int *) &(DSL_DEV_PRIVATE(pDev)->Recent_indicator);
2754
2755    memcpy ((char *) regs[num], (char *) regs_temp, sizeof (regs_temp));
2756    // procfs
2757    meidir = proc_mkdir (MEI_DIRNAME, NULL);
2758    if (meidir == NULL) {
2759        IFX_MEI_EMSG ("Failed to create /proc/%s\n", MEI_DIRNAME);
2760        return (-ENOMEM);
2761    }
2762
2763    for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
2764        entry = create_proc_entry (regs[num][i].name,
2765                       S_IWUSR | S_IRUSR | S_IRGRP |
2766                       S_IROTH, meidir);
2767        if (entry) {
2768            regs[num][i].low_ino = entry->low_ino;
2769            entry->proc_fops = &IFX_MEI_ProcOperations;
2770        }
2771        else {
2772            IFX_MEI_EMSG ("Failed to create /proc/%s/%s\n", MEI_DIRNAME, regs[num][i].name);
2773            return (-ENOMEM);
2774        }
2775    }
2776    return 0;
2777}
2778
2779/*
2780 * Reading function for linux proc filesystem
2781 */
2782static int
2783IFX_MEI_ProcRead (struct file *file, char *buf, size_t nbytes, loff_t * ppos)
2784{
2785    int i_ino = (file->f_dentry->d_inode)->i_ino;
2786    char *p = buf;
2787    int i;
2788    int num;
2789    reg_entry_t *entry = NULL;
2790    DSL_DEV_Device_t *pDev = NULL;
2791    DSL_DEV_WinHost_Message_t m;
2792
2793    for (num = 0; num < BSP_MAX_DEVICES; num++) {
2794        for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
2795            if (regs[num][i].low_ino == (unsigned short)i_ino) {
2796                entry = &regs[num][i];
2797                pDev = &dsl_devices[num];
2798                break;
2799            }
2800        }
2801    }
2802    if (entry == NULL)
2803        return -EINVAL;
2804    else if (strcmp(entry->name, "meminfo") == 0) {
2805        if (*ppos > 0) /* Assume reading completed in previous read */
2806            return 0;
2807        p += sprintf (p, "No Address Size\n");
2808        for (i = 0; i < MAX_BAR_REGISTERS; i++) {
2809            p += sprintf (p, "BAR[%02d] Addr:0x%08X Size:%lu\n",
2810                      i, (u32) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[i].address,
2811                      DSL_DEV_PRIVATE(pDev)-> adsl_mem_info[i].size);
2812            //printk( "BAR[%02d] Addr:0x%08X Size:%d\n",i,adsl_mem_info[i].address,adsl_mem_info[i].size);
2813        }
2814        *ppos += (p - buf);
2815    } else if (strcmp(entry->name, "fw_version") == 0) {
2816        if (*ppos > 0) /* Assume reading completed in previous read */
2817            return 0;
2818        if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1)
2819            return -EAGAIN;
2820                //major:bits 0-7
2821                //minor:bits 8-15
2822                makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 0, 1, NULL, m.msg.TxMessage);
2823        if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
2824            return -EIO;
2825        p += sprintf(p, "FW Version: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF);
2826                //sub_version:bits 4-7
2827                //int_version:bits 0-3
2828                //spl_appl:bits 8-13
2829                //rel_state:bits 14-15
2830                makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 1, 1, NULL, m.msg.TxMessage);
2831        if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
2832            return -EIO;
2833        p += sprintf(p, "%d.%d.%d.%d\n",
2834            (m.msg.RxMessage[4] >> 4) & 0xF, m.msg.RxMessage[4] & 0xF,
2835            (m.msg.RxMessage[4] >> 14) & 3, (m.msg.RxMessage[4] >> 8) & 0x3F);
2836                *ppos += (p - buf);
2837    } else if (strcmp(entry->name, "fw_date") == 0) {
2838        if (*ppos > 0) /* Assume reading completed in previous read */
2839            return 0;
2840        if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1)
2841            return -EAGAIN;
2842
2843                makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 0, 1, NULL, m.msg.TxMessage);
2844        if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
2845            return -EIO;
2846        /* Day/Month */
2847        p += sprintf(p, "FW Date: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF);
2848
2849                makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 2, 1, NULL, m.msg.TxMessage);
2850        if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
2851            return -EIO;
2852        /* Year */
2853        p += sprintf(p, "%d ", m.msg.RxMessage[4]);
2854
2855                makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 1, 1, NULL, m.msg.TxMessage);
2856        if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
2857            return -EIO;
2858        /* Hour:Minute */
2859        p += sprintf(p, "%d:%d\n", (m.msg.RxMessage[4] >> 8) & 0xFF, m.msg.RxMessage[4] & 0xFF);
2860
2861                *ppos += (p - buf);
2862    } else if (strcmp(entry->name, "version") == 0) {
2863        if (*ppos > 0) /* Assume reading completed in previous read */
2864            return 0;
2865        p += sprintf (p, "IFX MEI V%ld.%ld.%ld\n", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision);
2866
2867        *ppos += (p - buf);
2868    } else if (entry->flag != (int *) DSL_DEV_PRIVATE(pDev)->Recent_indicator) {
2869        if (*ppos > 0) /* Assume reading completed in previous read */
2870            return 0; // indicates end of file
2871        p += sprintf (p, "0x%08X\n\n", *(entry->flag));
2872        *ppos += (p - buf);
2873        if ((p - buf) > nbytes) /* Assume output can be read at one time */
2874            return -EINVAL;
2875    } else {
2876        if ((int) (*ppos) / ((int) 7) == 16)
2877            return 0; // indicate end of the message
2878        p += sprintf (p, "0x%04X\n\n", *(((u16 *) (entry->flag)) + (int) (*ppos) / ((int) 7)));
2879        *ppos += (p - buf);
2880    }
2881    return p - buf;
2882}
2883
2884/*
2885 * Writing function for linux proc filesystem
2886 */
2887static ssize_t
2888IFX_MEI_ProcWrite (struct file *file, const char *buffer, size_t count, loff_t * ppos)
2889{
2890    int i_ino = (file->f_dentry->d_inode)->i_ino;
2891    reg_entry_t *current_reg = NULL;
2892    int i = 0;
2893    int num = 0;
2894    unsigned long newRegValue = 0;
2895    char *endp = NULL;
2896    DSL_DEV_Device_t *pDev = NULL;
2897
2898    for (num = 0; num < BSP_MAX_DEVICES; num++) {
2899        for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
2900            if (regs[num][i].low_ino == i_ino) {
2901                current_reg = &regs[num][i];
2902                pDev = &dsl_devices[num];
2903                break;
2904            }
2905        }
2906    }
2907    if ((current_reg == NULL)
2908        || (current_reg->flag ==
2909        (int *) DSL_DEV_PRIVATE(pDev)->
2910        Recent_indicator))
2911        return -EINVAL;
2912
2913    newRegValue = simple_strtoul (buffer, &endp, 0);
2914    *(current_reg->flag) = (int) newRegValue;
2915    return (count + endp - buffer);
2916}
2917#endif //CONFIG_PROC_FS
2918
2919static int adsl_dummy_ledcallback(void)
2920{
2921    return 0;
2922}
2923
2924int ifx_mei_atm_led_blink(void)
2925{
2926    return g_adsl_ledcallback();
2927}
2928EXPORT_SYMBOL(ifx_mei_atm_led_blink);
2929
2930int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr)
2931{
2932    int i;
2933
2934    if ( is_showtime ) {
2935        *is_showtime = g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ? 0 : 1;
2936    }
2937
2938    if ( port_cell ) {
2939        for ( i = 0; i < port_cell->port_num && i < 2; i++ )
2940            port_cell->tx_link_rate[i] = g_tx_link_rate[i];
2941    }
2942
2943    if ( xdata_addr ) {
2944        if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 )
2945            *xdata_addr = NULL;
2946        else
2947            *xdata_addr = g_xdata_addr;
2948    }
2949
2950    return 0;
2951}
2952EXPORT_SYMBOL(ifx_mei_atm_showtime_check);
2953
2954/*
2955 * Writing function for linux proc filesystem
2956 */
2957int __init
2958IFX_MEI_ModuleInit (void)
2959{
2960    int i = 0;
2961    static struct class *dsl_class;
2962
2963    pr_info("IFX MEI Version %ld.%02ld.%02ld", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision);
2964
2965    for (i = 0; i < BSP_MAX_DEVICES; i++) {
2966        if (IFX_MEI_InitDevice (i) != 0) {
2967            IFX_MEI_EMSG("Init device fail!\n");
2968            return -EIO;
2969        }
2970        IFX_MEI_InitDevNode (i);
2971#ifdef CONFIG_PROC_FS
2972        IFX_MEI_InitProcFS (i);
2973#endif
2974    }
2975        for (i = 0; i <= DSL_BSP_CB_LAST ; i++)
2976        dsl_bsp_event_callback[i].function = NULL;
2977
2978#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
2979    IFX_MEI_DMSG("Start loopback test...\n");
2980    DFE_Loopback_Test ();
2981#endif
2982    dsl_class = class_create(THIS_MODULE, "ifx_mei");
2983    device_create(dsl_class, NULL, MKDEV(MEI_MAJOR, 0), NULL, "ifx_mei");
2984    return 0;
2985}
2986
2987void __exit
2988IFX_MEI_ModuleExit (void)
2989{
2990    int i = 0;
2991    int num;
2992
2993    for (num = 0; num < BSP_MAX_DEVICES; num++) {
2994        IFX_MEI_CleanUpDevNode (num);
2995#ifdef CONFIG_PROC_FS
2996        for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
2997            remove_proc_entry (regs[num][i].name, meidir);
2998        }
2999#endif
3000    }
3001
3002    remove_proc_entry (MEI_DIRNAME, NULL);
3003    for (i = 0; i < BSP_MAX_DEVICES; i++) {
3004        for (i = 0; i < BSP_MAX_DEVICES; i++) {
3005            IFX_MEI_ExitDevice (i);
3006        }
3007    }
3008}
3009
3010/* export function for DSL Driver */
3011
3012/* The functions of MEI_DriverHandleGet and MEI_DriverHandleDelete are
3013something like open/close in kernel space , where the open could be used
3014to register a callback for autonomous messages and returns a mei driver context pointer (comparable to the file descriptor in user space)
3015   The context will be required for the multi line chips future! */
3016
3017EXPORT_SYMBOL (DSL_BSP_DriverHandleGet);
3018EXPORT_SYMBOL (DSL_BSP_DriverHandleDelete);
3019
3020EXPORT_SYMBOL (DSL_BSP_ATMLedCBRegister);
3021EXPORT_SYMBOL (DSL_BSP_ATMLedCBUnregister);
3022EXPORT_SYMBOL (DSL_BSP_KernelIoctls);
3023EXPORT_SYMBOL (DSL_BSP_AdslLedInit);
3024//EXPORT_SYMBOL (DSL_BSP_AdslLedSet);
3025EXPORT_SYMBOL (DSL_BSP_FWDownload);
3026EXPORT_SYMBOL (DSL_BSP_Showtime);
3027
3028EXPORT_SYMBOL (DSL_BSP_MemoryDebugAccess);
3029EXPORT_SYMBOL (DSL_BSP_SendCMV);
3030
3031// provide a register/unregister function for DSL driver to register a event callback function
3032EXPORT_SYMBOL (DSL_BSP_EventCBRegister);
3033EXPORT_SYMBOL (DSL_BSP_EventCBUnregister);
3034
3035module_init (IFX_MEI_ModuleInit);
3036module_exit (IFX_MEI_ModuleExit);
3037
3038MODULE_LICENSE("Dual BSD/GPL");
3039

Archive Download this file



interactive