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