基于MT7688 原厂SDK 使用SPI控制器驱动TFT屏幕ILI9225驱动器(spi接口)

以下是我的一个利用SPI控制器操作屏的一个操作实例 包含一个bpeer_tft.c 和一个bpeer_tft.h

这是我基于flash驱动剥离出来的spi控制器驱动

好的话,顶起来~~~~~~~~~~~~~~~~~~~

下面是代码:

bpeer_tft.c

1 /*
  2  * MTD SPI driver for ST M25Pxx flash chips
  3  *
  4  * Author: Mike Lavender, [email protected]
  5  *
  6  * Copyright (c) 2005, Intec Automation Inc.
  7  *
  8  * Some parts are based on lart.c by Abraham Van Der Merwe
  9  *
 10  * Cleaned up and generalized based on mtd_dataflash.c
 11  *
 12  * This code is free software; you can redistribute it and/or modify
 13  * it under the terms of the GNU General Public License version 2 as
 14  * published by the Free Software Foundation.
 15  *
 16  */
 17
 18 #include <linux/init.h>
 19 #include <linux/module.h>
 20 #include <linux/device.h>
 21 #include <linux/interrupt.h>
 22 #include <linux/interrupt.h>
 23 #include <linux/mtd/mtd.h>
 24 #include <linux/mtd/map.h>
 25 #include <linux/mtd/gen_probe.h>
 26 #include <linux/mtd/partitions.h>
 27 #include <linux/semaphore.h>
 28 #include <linux/slab.h>
 29 #include <linux/delay.h>
 30 #include <linux/spi/spi.h>
 31 #include <linux/spi/flash.h>
 32 #include <linux/version.h>
 33 #include <linux/time.h>
 34 #if defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628)
 35 #else
 36 #include "ralink_spi.h"
 37 #endif
 38 #include <linux/fcntl.h> /* O_ACCMODE */
 39 #include <linux/types.h> /* size_t */
 40 #include <linux/proc_fs.h>
 41
 42
 43
 44
 45 #include "bpeer_tft.h"
 46
 47
 48
 49
 50
 51
 52
 53
 54
55
 56 //#define SPI_DEBUG
 57 #if !defined (SPI_DEBUG)
 58 #define ra_inl(addr)  (*(volatile unsigned int *)(addr))
 59 #define ra_outl(addr, value)  (*(volatile unsigned int *)(addr) = (value))
 60 #define ra_dbg(args...) do {} while(0)
 61 /*#define ra_dbg(args...) do { printk(args); } while(0)*/
 62
 63 #else
 64 #define ra_dbg(args...) do { printk(args); } while(0)
 65 #define _ra_inl(addr)  (*(volatile unsigned int *)(addr))
 66 #define _ra_outl(addr, value)  (*(volatile unsigned int *)(addr) = (value))
 67
 68 u32 ra_inl(u32 addr)
 69 {
 70         u32 retval = _ra_inl(addr);
 71         printk("%s(%x) => %x \n", __func__, addr, retval);
 72
 73         return retval;
 74 }
 75
 76 u32 ra_outl(u32 addr, u32 val)
 77 {
 78         _ra_outl(addr, val);
 79
 80         printk("%s(%x, %x) \n", __func__, addr, val);
 81
 82         return val;
 83 }
 84
 85 #endif // SPI_DEBUG //
 86
 87 #define ra_aor(addr, a_mask, o_value)  ra_outl(addr, (ra_inl(addr) & (a_mask)) | (o_value))
 88 #define ra_and(addr, a_mask)  ra_aor(addr, a_mask, 0)
 89 #define ra_or(addr, o_value)  ra_aor(addr, -1, o_value)
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100 #define SPI_MAX_DEV 2
101
102 static struct base_spi spi_pre[SPI_MAX_DEV];
103 static struct tft_config_type tft_config[2];
104
105
106
107
108 static int spidrv_major = 111;
109 int eye_l_minor =  0;
110 int eye_r_minor =  1;
111
112
113
114 static struct tft_reg_info tft_reg_data [] = {
115         /* init tft reg  */
116         { "rest",               0, 0},
117         { "reg",0x10, 0x0000 }, // Set SAP,DSTB,STB
118         { "reg", 0x11, 0x0000 }, // Set APON,PON,AON,VCI1EN,VC
119         { "reg", 0x12, 0x0000 }, // Set BT,DC1,DC2,DC3
120         { "reg", 0x13, 0x0000 }, // Set GVDD
121         { "reg", 0x14, 0x0000 }, // Set VCOMH/VCOML voltage
122         { "msleep",             40, 0},  //mdelay( 40 }, // Delay 20
123
124                 // Please follow this power on sequence
125         { "reg", 0x11, 0x0018 }, // Set APON,PON,AON,VCI1EN,VC
126         { "reg", 0x12, 0x1121 }, // Set BT,DC1,DC2,DC3
127         { "reg", 0x13, 0x0063 }, // Set GVDD
128         { "reg", 0x14, 0x3961 }, // Set VCOMH/VCOML voltage
129         { "reg", 0x10, 0x0800 }, // Set SAP,DSTB,STB
130         { "msleep",             10, 0},  //mdelay( 10 }, // Delay 10 ms
131         { "reg", 0x11, 0x1038 }, // Set APON,PON,AON,VCI1EN,VC
132         { "msleep",             30, 0}, //mdelay( 30 }, // Delay 30 ms
133         { "reg", 0x02, 0x0100 }, // set 1 line inversion
134
135         #if USE_HORIZONTAL//
136                 //R01H:SM=0,GS=0,SS=0 (for details,See the datasheet of ILI9225)
137         { "reg", 0x01, 0x001C }, // set the display line number and display direction
138         //R03H:BGR=1,ID0=1,ID1=1,AM=1 (for details,See the datasheet of ILI9225)
139         { "reg", 0x03, 0x1038 }, // set GRAM write direction .
140         #else
141                 //R01H:SM=0,GS=0,SS=1 (for details,See the datasheet of ILI9225)
142         { "reg", 0x01, 0x011C }, // set the display line number and display direction
143                 //R03H:BGR=1,ID0=1,ID1=1,AM=0 (for details,See the datasheet of ILI9225)
144         { "reg", 0x03, 0x1030 }, // set GRAM write direction.
145 //      { "reg", 0x03, 0x1020 }, // set GRAM write direction.
146         #endif
147         { "reg", 0x07, 0x0000 }, // Display off
148         { "reg", 0x08, 0x0808 },
149         { "reg", 0x0B, 0x1100 },
150         { "reg", 0x0C, 0x0000 },
151         { "reg", 0x0F, 0x0501 }, // Set Osc
152         { "reg", 0x15, 0x0020 }, // Set VCI recycling
153         { "reg", 0x20, 0x0000 }, // RAM Address
154         { "reg", 0x21, 0x0000 }, // RAM Address
155
156         //------------------------ Set GRAM area --------------------------------//
157         { "reg", 0x30, 0x0000 },
158         { "reg", 0x31, 0x00DB },
159         { "reg", 0x32, 0x0000 },
160         { "reg", 0x33, 0x0000 },
161         { "reg", 0x34, 0x00DB },
162         { "reg", 0x35, 0x0000 },
163         { "reg", 0x36, 0x00AF },
164         { "reg", 0x37, 0x0000 },
165         { "reg", 0x38, 0x00DB },
166         { "reg", 0x39, 0x0000 },
167
168
169         // ---------- Adjust the Gamma 2.2 Curve -------------------//
170         { "reg", 0x50, 0x0603},
171         { "reg", 0x51, 0x080D},
172         { "reg", 0x52, 0x0D0C},
173         { "reg", 0x53, 0x0205},
174         { "reg", 0x54, 0x040A},
175         { "reg", 0x55, 0x0703},
176         { "reg", 0x56, 0x0300},
177         { "reg", 0x57, 0x0400},
178         { "reg", 0x58, 0x0B00},
179         { "reg", 0x59, 0x0017},
180
181         { "reg", 0x0F, 0x0701}, // Vertical RAM Address Position
182         { "reg", 0x07, 0x0012}, // Vertical RAM Address Position
183         { "msleep", 50, 0}, //mdelay( 50 }, // Delay 50 ms
184         { "reg", 0x07, 0x1017}, // Vertical RAM Address Position
185
186 };
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201 /*-------------------------GPIO base ----------------------------------------------------------------------*/
202
203
204 #define GPIO_OUT_H 1
#define GPIO_OUT_L 0
206
207 static int base_gpio_set(int gpio,int value)
208 {
209         unsigned int tmp;
210         if (gpio <= 31) {
211                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR));
212                 tmp |= 1 << gpio;
213                 *(volatile u32 *)(RALINK_REG_PIODIR) = tmp;
214
215                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA));
216                 tmp &= ~(1 << gpio);
217                 tmp |= value << gpio;
218                 *(volatile u32 *)(RALINK_REG_PIODATA) = cpu_to_le32(tmp);
219 //              *(volatile u32 *)(RALINK_REG_PIOSET) = cpu_to_le32(tmp);
220         } else if (gpio <= 63) {
221                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR + 0x04));
222                 tmp |= 1 << (gpio - 32);
223                 *(volatile u32 *)(RALINK_REG_PIODIR + 0x04) = tmp;
224
225                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA + 0x04));
226                 tmp &= ~(1 << (gpio - 32));
227                 tmp |= value << (gpio - 32);
228                 *(volatile u32 *)(RALINK_REG_PIODATA + 0x04) = tmp;
229         } else {
230                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR + 0x08));
231                 tmp |= 1 << (gpio - 64);
232                 *(volatile u32 *)(RALINK_REG_PIODIR + 0x08) = tmp;
233
234                 tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA + 0x08));
235                 tmp &= ~(1 << (gpio - 64));
236                 tmp |= value << (gpio - 64);
237                 *(volatile u32 *)(RALINK_REG_PIODATA + 0x08) = tmp;
238         }
239
240 //      *(volatile u32 *)(RALINK_REG_PIOSET) = cpu_to_le32(arg);
241 }
242
243
244
245 static int  base_gpio_init(void)
246 {
247         unsigned int i;
248         u32 gpiomode;
249
250         //config these pins to gpio mode
251         gpiomode = le32_to_cpu(*(volatile u32 *)(RALINK_REG_GPIOMODE));
252         gpiomode &= ~(3<<6);//0xc00;  //clear bit[11:10] 00:SD_mode
253         gpiomode |= (1<<6);//0xc00;  //clear bit[11:10] 00:SD_mode
254         gpiomode &= ~(3<<4);
255
256 //      *(volatile u32 *)(RALINK_REG_AGPIOCFG) = cpu_to_le32(le32_to_cpu(*(volatile u32 *)(RALINK_REG_AGPIOCFG)) | 0x1e0000 );  //set bit[20:17] 1111:Digital_mode
257 //      gpiomode &= ~0xc00;  //clear bit[11:10] 00:SD_mode
258 //      gpiomode &= ~0x03000000;  //clear bit[25:24] 00:UART1_mode
259 //      gpiomode &= ~0x0300;  //clear bit[9:8] 00:UART0_mode
260         *(volatile u32 *)(RALINK_REG_GPIOMODE) = cpu_to_le32(gpiomode);
261         printk("RALINK_REG_GPIOMODE %08x !\n",le32_to_cpu(*(volatile u32 *)(RALINK_REG_GPIOMODE)));
262
263         printk("base_gpio_init initialized\n");
264
265         base_gpio_set(TFT_GPIO_RS,1);
266         base_gpio_set(TFT_GPIO_LED,0);
267         return 0;
268 }
269
270
271
272
273
274 /*-------------------------SPI base ----------------------------------------------------------------------*/
275
276
277 #if 0
278 void usleep(unsigned int usecs)
279 {
280         unsigned long timeout = usecs_to_jiffies(usecs);
281
282         while (timeout)
283                 timeout = schedule_timeout_interruptible(timeout);
284 }
285 #endif
286
287 static int base_spi_busy_wait(void)
288 {
289         int n = 100000;
290         do {
291                 if ((ra_inl(SPI_REG_CTL) & SPI_CTL_BUSY) == 0)
292                         return 0;
293                 udelay(1);
294         } while (--n > 0);
295
296         printk("%s: fail \n", __func__);
297         return -1;
298 }
299
300 static inline u32 base_spi_read( u32 reg)
301 {
302         u32 val;
303         val = ra_inl(reg);
304 //      printk("mt7621_spi_read reg %08x val %08x \n",reg,val);
305         return val;
306 }
307
308 static inline void base_spi_write( u32 reg, u32 val)
309 {
310 //      printk("mt7621_spi_write reg %08x val %08x \n",reg,val);
311         ra_outl(reg,val);
312 }
313
314 static void base_spi_reset(int duplex) // 0 half duplex ; 1 full duplex
315 {
316         u32 master = base_spi_read(SPI_REG_MASTER);
317
318         master |= 7 << 29;
319         master |= 1 << 2;
320         if (duplex)
321                 master |= 1 << 10;
322         else
323                 master &= ~(1 << 10);
324         base_spi_write(SPI_REG_MASTER, master);
325 }
326
327 static void base_spi_set_cs(struct base_spi *spi, int enable)
328 {
329         int cs = spi->chip_select;
330         u32 polar = 0;
331         base_spi_reset(0);
332         if(cs > 1)
333                 base_gpio_set(cs,GPIO_OUT_H);
334         if (enable){
335                 if(cs > 1)
336                         base_gpio_set(cs,GPIO_OUT_L);
337                 else
338                         polar = BIT(cs);
339                 }
340         base_spi_write(SPI_REG_CS_POLAR, polar);
341 }
342
343 static int base_spi_prepare(struct base_spi* spi)
344 {
345         u32 rate;
346         u32 reg;
347
348 //      printk("speed:%u\n", spi->speed);
349
350         rate = DIV_ROUND_UP(spi->sys_freq,spi->speed);
351 //      printk( "rate-1:%u\n", rate);
352
353         if (rate > 4097)
354                 return -EINVAL;
355
356         if (rate < 2)
357                 rate = 2;
358
359         reg = base_spi_read(SPI_REG_MASTER);
360         reg &= ~(0xfff << 16);
361         reg |= (rate - 2) << 16;
362
363         reg &= ~SPI_REG_LSB_FIRST;
364         if (spi->mode & SPI_LSB_FIRST)
365                 reg |= SPI_REG_LSB_FIRST;
366
367         reg &= ~(SPI_REG_CPHA | SPI_REG_CPOL);
368         switch(spi->mode & (SPI_CPOL | SPI_CPHA)) {
369                 case SPI_MODE_0:
370                         break;
371                 case SPI_MODE_1:
372                         reg |= SPI_REG_CPHA;
373                         break;
374                 case SPI_MODE_2:
375                         reg |= SPI_REG_CPOL;
376                         break;
377                 case SPI_MODE_3:
378                         reg |= SPI_REG_CPOL | SPI_REG_CPHA;
379                         break;
380         }
381         base_spi_write(SPI_REG_MASTER, reg);
382
383         return 0;
384 }
385
386
387 static int base_spi_transfer_half_duplex(struct base_spi *m)
388 {
389         unsigned long flags;
390         int status = 0;
391         int i, len = 0;
392         int rx_len = 0;
393         u32 data[9] = { 0 };
394         u32 val;
395         spin_lock_irqsave(&m->lock, flags);
396         base_spi_busy_wait();
397
398         u8 *buf = m->tx_buf;
399         for (i = 0; i < m->tx_len; i++, len++)
400                 data[len / 4] |= buf[i] << (8 * (len & 3));
401         if (WARN_ON(rx_len > 32)) {
402                 status = -EIO;
403                 goto msg_done;
404         }
405
406         if (base_spi_prepare(m)) {
407                 status = -EIO;
408                 goto msg_done;
409         }
410
411         data[0] = swab32(data[0]);
412         if (len < 4)
413                 data[0] >>= (4 - len) * 8;
414
415         for (i = 0; i < len; i += 4)
416                 base_spi_write(SPI_REG_OPCODE + i, data[i / 4]);
417
418         val = (min_t(int, len, 4) * 8) << 24;
419         if (len > 4)
420                 val |= (len - 4) * 8;
421         val |= (rx_len * 8) << 12;
422         base_spi_write(SPI_REG_MOREBUF, val);
423
424         base_spi_set_cs(m, 1);
425
426         val = base_spi_read(SPI_REG_CTL);
427         val |= SPI_CTL_START;
428         base_spi_write(SPI_REG_CTL, val);
429
430         base_spi_busy_wait();
431
432         base_spi_set_cs(m, 0);
433
434         for (i = 0; i < rx_len; i += 4)
435                 data[i / 4] = base_spi_read(SPI_REG_DATA0 + i);
436
437         len = 0;
438         buf = m->rx_buf;
439         for (i = 0; i < m->rx_len; i++, len++)
440                 buf[i] = data[len / 4] >> (8 * (len & 3));
441
442 msg_done:
443         spin_unlock_irqrestore(&m->lock, flags);
444 //      m->status = status;
445 //      spi_finalize_current_message(master);
446
447         return status;
448 }
449
450
451 /*-------------------------TFT ----------------------------------------------------------------------*/
452
453
454
455 static int tft_write_index(struct base_spi* spi, char reg)
456 {
457         int retval;
458         base_gpio_set(TFT_GPIO_RS,0);
459         spi->tx_buf[0] = reg;
460         spi->tx_len = 1;
461         retval = base_spi_transfer_half_duplex(spi);
462         if (retval != 0) {
463                 printk("%s: ret: %x\n", __func__, retval);
464         }
465         return retval;
466 }
467
468 static int tft_write_data(struct base_spi* spi, unsigned char* data,int length)
469 {
470         int retval;
471         int i = 0;
472         int j = 0;
473         int n = 0;
474         base_gpio_set(TFT_GPIO_RS,1);
475         int step = 4;
476         unsigned char* buf;
477
478         while((length - j) > 0){
479 //              printk("%s: ret: %d  j %d\n", __func__, length,j);
480                 buf =  data + j;
481                 n = length - j;
482                 if(n >= step)
483                         n = step;
484                 for(i = 0; i < n; i++){
485                         spi->tx_buf[i] = buf[n - i -1];
486                 }
487                 spi->tx_len = n;
488 //              printk("data: %02x %02x %02x %02x \n", spi->tx_buf[0],spi->tx_buf[1],spi->tx_buf[2],spi->tx_buf[3]);
489                 retval = base_spi_transfer_half_duplex(spi);
490                 j += n;
491                 }
492
493         return retval;
494 }
495 static int write_data(struct base_spi* spi, unsigned char* data,int length)
496 {
497         int retval;
498         int i = 0;
499         int j = 0;
500         int n = 0;
501         base_gpio_set(TFT_GPIO_RS,1);
502         int step = 32;
503         unsigned char* buf;
504
505         while((length - j) > 0){
506 //              printk("%s: ret: %d  j %d\n", __func__, length,j);
507                 buf =  data + j;
508                 n = length - j;
509                 if(n >= step)
510                         n = step;
511                 for(i = 0; i < n; i++){
512                         spi->tx_buf[i] = buf[i];
513                 }
514                 spi->tx_len = n;
515 //              printk("data: %02x %02x %02x %02x \n", spi->tx_buf[0],spi->tx_buf[1],spi->tx_buf[2],spi->tx_buf[3]);
516                 retval = base_spi_transfer_half_duplex(spi);
517                 j += n;
518                 }
519
520
521         return retval;
522
523 }
524
525
526 static int tft_write_reg(struct base_spi* spi, char reg, char* data, int length)
527 {
528         int retval;
529         tft_write_index( spi,reg);
530         tft_write_data( spi, data,length);
531
532         return retval;
533 }
534
535
536
537
538
539 static void
540 Lcd_SetRegion( struct base_spi* spi, unsigned char xStar, unsigned char yStar, unsigned char xEnd, unsigned char yEnd )
541 {
542         char buf = 0;
543         int err;
544         #if   USE_HORIZONTAL
545                 tft_write_reg( spi, 0x38, &xEnd  ,2);
546                 tft_write_reg( spi, 0x39, &xStar ,2);
547                 tft_write_reg( spi, 0x36, &yEnd  ,2);
548                 tft_write_reg( spi, 0x37, &yStar ,2);
549                 tft_write_reg( spi, 0x21, &xStar ,2);
550                 tft_write_reg( spi, 0x20, &yStar ,2);
551         #else
552 //              tft_write_reg( spi, 0x36, &xEnd, 2);
553 //              tft_write_reg( spi, 0x37, &xStar, 2);
554 //              tft_write_reg( spi, 0x38, &yEnd,  2);
555 //              tft_write_reg( spi, 0x39, &yStar, 2);
556 ///             tft_write_reg( spi, 0x20, &xStar, 2);
557 //              tft_write_reg( spi, 0x21, &yStar, 2);
558
559                 tft_write_reg( spi, 0x36, &yEnd, 2);
560                 tft_write_reg( spi, 0x37, &yStar, 2);
561                 tft_write_reg( spi, 0x38, &xEnd,  2);
562                 tft_write_reg( spi, 0x39, &xStar, 2);
563                 tft_write_reg( spi, 0x20, &xStar, 2);
564                 tft_write_reg( spi, 0x21, &yStar, 2);
565
566
567         #endif
568         tft_write_index( spi, 0x22);
569
570 }
571
572
573 static void Lcd_Clear( struct base_spi* spi, unsigned short Color)
574 {
575         unsigned int i,m;
576         Lcd_SetRegion( spi, 0, 0, X_MAX_PIXEL-1, Y_MAX_PIXEL-1 );
577         for( i =0; i < X_MAX_PIXEL; i++ )
578                 for( m = 0; m < Y_MAX_PIXEL ; m++ ){
579                         tft_write_data( spi, &Color,2);
580                 }
581 }
582 static void Lcd_Clear1( struct base_spi* spi, unsigned short Color)
583 {
584         unsigned int i,m;
585 //      Lcd_SetRegion( spi, 0, 0, X_MAX_PIXEL-1, Y_MAX_PIXEL-1 );
586         Lcd_SetRegion( spi, 0, 0, X_MAX_PIXEL-1, Y_MAX_PIXEL-1 );
587 //      for( i =0; i < X_MAX_PIXEL; i++ )
588         for( i =0; i < 1; i++ )
589                 for( m = 0; m < 10 ; m++ ){
590                         tft_write_data( spi, &Color,2);
591                 }
592 }
593
594
595
596
597
598
599 static ssize_t tft_write(struct file *file, const char __user *buf,
600                                                 size_t count, loff_t *ppos)
601 {
602         struct timeval  tval1, tval2, tval3, tval4, tval5, tval6, tval7;
603 //      do_gettimeofday( &tval1 );
604         struct tft_config_type* ptrtft_config;
605         unsigned long flags;
606         unsigned char* data;//[200*250*2];
607         int minor ; // = iminor(inode);
608 //      Lcd_SetRegion( spi, X_MAX_PIXEL-1, Y_MAX_PIXEL-1, 0, 0 );
609         data = kzalloc(200*250*2, GFP_KERNEL);
610 //      printk("tft_write: %d %x\n",data,data);
611 //      do_gettimeofday( &tval2 );
612
613
614         ptrtft_config = file->private_data;
615 //      spin_lock_irq( &ptrtft_config->spi->lock );
616         Lcd_SetRegion( ptrtft_config->spi, 0, 0, X_MAX_PIXEL-1, Y_MAX_PIXEL-1 );
617 //      Lcd_SetRegion( ptrtft_config->spi, Y_MAX_PIXEL-1, X_MAX_PIXEL, 0, 0 );
618 //      do_gettimeofday( &tval3 );
619
620 //      Lcd_SetRegion( ptrtft_config->spi, X_MAX_PIXEL-1, Y_MAX_PIXEL-1, 0, 0 );
621         copy_from_user( data, buf, count );
622 //      do_gettimeofday( &tval4 );
623
624         count = write_data(ptrtft_config->spi, data, count);
625 //      do_gettimeofday( &tval5 );
626         kfree(data);
627 //      do_gettimeofday( &tval6 );
628         data = NULL;
629 //      spin_unlock_irq( &ptrtft_config->spi->lock );
630         base_gpio_set(TFT_GPIO_LED,1);
631 //      do_gettimeofday( &tval7 );
632 //      do_gettimeofday( &tval2 );
633 //      printk("---------syscall_write_time= time2 - time1----------\n");
634 //      printk("timeval2->tv_sec - timeval1->tv_sec=%ld\n",tval2.tv_sec - tval1.tv_sec);
635 //      printk("timeval2->tv_usec - timeval2->tv_usec=%ld\n",tval2.tv_usec - tval1.tv_usec);
636 /*
637         printk("\n");
638         printk("-------kzalloc_time = time2 - time1-----------------\n");
639         printk("timeval2->tv_sec - timeval1->tv_sec=%ld\n",tval2.tv_sec - tval1.tv_sec);
640         printk("timeval2->tv_usec - timeval2->tv_usec=%ld\n",tval2.tv_usec - tval1.tv_usec);
641         printk("---------Lcd_SetRgion_time = time3 - time2------------\n");
642         printk("timeval3->tv_sec - timeval2->tv_sec=%ld\n",tval3.tv_sec - tval2.tv_sec);
643         printk("timeval3->tv_usec - timeval2->tv_usec=%ld\n",tval3.tv_usec - tval2.tv_usec);
644         printk("--------------copy_from_user_time = time4 -time3-----------\n");
645         printk("timeval4->tv_sec - timeval3->tv_sec=%ld\n",tval4.tv_sec - tval3.tv_sec);
646         printk("timeval4->tv_usec - timeval3->tv_usec=%ld\n",tval4.tv_usec - tval3.tv_usec);
647         printk("--------------write_data_time = time5 - time4--------------\n");
648         printk("timeval5->tv_sec - timeval4->tv_sec=%ld\n",tval5.tv_sec - tval4.tv_sec);
649         printk("timeval5->tv_usec - timeval4->tv_usec=%ld\n",tval5.tv_usec - tval4.tv_usec);
650         printk("--------------kfree()_time = time6 - time5------------------\n");
651         printk("timeval6->tv_sec - timeval5->tv_sec=%ld\n",tval6.tv_sec - tval5.tv_sec);
652         printk("timeval6->tv_usec - timeval5->tv_usec=%ld\n",tval6.tv_usec - tval5.tv_usec);
653         printk("--------------gpio_set_time = time7 - time6------------------\n");
654         printk("timeval7->tv_sec - timeval6->tv_sec=%ld\n",tval7.tv_sec - tval6.tv_sec);
655         printk("timeval7->tv_usec - timeval6->tv_usec=%ld\n",tval7.tv_usec - tval6.tv_usec);
656         printk("---------------All End---------------------\n");
657         printk("\n");
658 */
659         return count;
660 }
661
662
663 long tft_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
664 {
665         int i ;
666         char* data;
667         void __user *argp = (void __user *)arg;
668         int __user *p = argp;
669         struct tft_config_type* ptrtft_config;
670         unsigned long flags;
671         struct base_spi* spi;
672         ptrtft_config = filp->private_data;
673         spi = ptrtft_config->spi;
674         switch (cmd) {
675         case TFT_RESET:
676
677                 break;
678         case TFT_SET_REG:
679
680                 break;
681         case TFT_GET_REG:
682                 copy_to_user(argp, data, sizeof(data)) ? -EFAULT : 0;
683
684
685                 break;
686         case TFT_DEBUG:
687                 break;
688         default :
689                 printk("TFT_ioctl: command format error\n");
690         }
691
692         return 0;
693 }
694
695
696
697 int reset = 0;
698 static int tft_param_init(struct tft_config_type* ptrtft_config)
699 {
700         struct tft_reg_info *info;
701         int i = 0;
702         int err;
703         u16 buff = 0x4255;
704
705
706 //      tft_write_reg( ptrtft_config->spi, 0x38, &buff  ,2);
707
708 #if 1
709         for (i = 0; i < ARRAY_SIZE(tft_reg_data); i++) {
710                 info = &tft_reg_data[i];
711 //              printk("tft_param_init tft_reg_data %d %s %x %x\n",i, info->name,info->reg,info->val);
712                 if(strcmp(info->name,"reg")==0) {
713                         err = tft_write_reg(ptrtft_config->spi,info->reg,&info->val,2);
714                         if(err < 0){
715                                 printk("init tft Successful!\n");
716                                 return err;
717                                 }
718                         }
719                 if(strcmp(info->name,"msleep")==0) {
720                         mdelay(info->reg);
721                         }
722                 if(strcmp(info->name,"rest")==0) {
723                         if(reset == 0){
724                                 base_gpio_set(TFT_GPIO_RESET,0);
725                                 mdelay(100);
726                                 base_gpio_set(TFT_GPIO_RESET,1);
727                                 mdelay(50);
728                                 reset = 1;
729                                 }
730                         }
731                 }
732 #endif
733         printk("init tft Successful!\n");
734         return 0;
735 }
736
737
738
739
740
741
742
743 int tft_open(struct inode *inode, struct file *filp)
744 {
745         struct base_spi* spi_init;
746         int chip_select = 0;
747         int minor = iminor(inode);
748         if(minor == eye_l_minor){
749                 chip_select = TFT_EYEL_CS;
750                 printk("tft_open eye lift  minor %d !\n", minor);
751                 }
752         if(minor == eye_r_minor){
753                 chip_select = TFT_EYER_CS;
754                 printk("tft_open eye right   minor %d ! \n", minor);
755                 }
756
757         if ((minor != eye_l_minor)&&(minor != eye_r_minor)){
758                 printk("minor is error minor %d ! \n", minor);
759                 return -ENODEV;
760                 }
761         printk("%s was called\n",__func__);
762
763         tft_config[minor].spi = &spi_pre[minor];
764         spi_init = tft_config[minor].spi;
765 //      spi_init->start = kmalloc(200*250*2, GFP_KERNEL);
766 //      if( !spi_init->start)
767 //      {
768 //              printk(" kmalloc is failed was open()");
769 //              return -ENOMEM;
770 //      }
771
772         spi_init->chip_select = chip_select;
773         spi_init->mode = SPI_MODE_3;
774         spi_init->speed = 50000000;
775         spi_init->sys_freq = 575000000;
776         spin_lock_init(&spi_init->lock);
777         tft_param_init(&tft_config[minor]);
778
779         filp->private_data = &tft_config[minor];
780         printk("%s was End\n",__func__);
781
782         base_gpio_set(TFT_GPIO_LED,1);
783 //      mdelay(3000);
784
785 //      Lcd_Clear(spi_init, 0x001f);
786 //      mdelay(3000);
787 //      Lcd_Clear(spi_init, 0x07e0);
788 //      mdelay(3000);
789 //      Lcd_Clear(spi_init, 0xf800);
790         Lcd_Clear(spi_init, 0x0);
791 //      Lcd_Clear1(spi_init, 0xf800);
792 //      base_gpio_set(TFT_GPIO_LED,1);
793 //      try_module_get(THIS_MODULE);
794 //      if (filp->f_flags & O_NONBLOCK) {
795 //              printk("filep->f_flags O_NONBLOCK set\n");
796 //              return -EAGAIN;
797 //      }
798         return 0;
799 }
800
801
802 static int tft_release(struct inode *inode, struct file *filp)
803 {
804         /************Liuchen modfiy here***************/
805         struct tft_config_type* tmp = filp->private_data;
806         spin_lock_irq( &tmp->spi->lock );
807         kfree( tmp->spi->start);
808         spin_unlock_irq( &tmp->spi->lock );
809         /*************END******************************/
810         printk("tft_release 1  !\n");
811
812         filp->private_data=NULL;
813
814         return 0;
815 }
816
817
818 static const struct file_operations tft_fops = {
819         .owner          = THIS_MODULE,
820         .open           = tft_open,
821         .write          = tft_write,
822         .release        = tft_release,
823         .unlocked_ioctl = tft_ioctl,
824 };
825
826
827
828 struct class *my_class;
829 static int __init tft_init(void)
830 {
831
832         int result=0, i = 0;
833 /*
834         struct base_spi *dev;
835         struct tft_config_type *tmp;
836         for( i =0; i < SPI_MAX_DEV; i++)
837         {
838                 dev = (struct base_spi*)kzalloc(sizeof(*dev), GFP_KERNEL);
839                 if(!dev){
840                         return -ENOMEM;
841                 }
842                 dev->start = kzalloc(200*250*2, GFP_KERNEL);
843                 if( !dev->start ){
844                         return -ENOMEM;
845                 }
846
847                 tmp = (struct tft_config_type*)kzalloc(sizeof(*tmp), GFP_KERNEL);
848                 if(!tmp){
849                         return -ENOMEM;
850                 }
851                 spi_pre[i] = dev;
852                 tft_config[i] = spi_pre[i];
853         }
854 */
855         result = register_chrdev(spidrv_major, "TFT", &tft_fops);
856         printk("creat %s major %d  %d!\n","TFT",spidrv_major,result);
857         if (result < 0) {
858                 printk(KERN_WARNING "i2s: can't get major %d\n",spidrv_major);
859                 return result;
860         }
861
862         my_class=class_create(THIS_MODULE, "TFT");
863         if (IS_ERR(my_class))
864                 return -EFAULT;
865         device_create(my_class, NULL, MKDEV(spidrv_major, eye_l_minor), NULL,TFT_LIFT_DEVNAME);
866         device_create(my_class, NULL, MKDEV(spidrv_major, eye_r_minor), NULL,TFT_RIGHT_DEVNAME);
867
868
869
870         if (spidrv_major == 0) {
871                 spidrv_major = result; /* dynamic */
872         }
873         base_gpio_init();
874
875
876
877 #if 0
878         u32 gpiomode;
879         //config these pins to gpio mode
880         gpiomode = le32_to_cpu(*(volatile u32 *)(RALINK_REG_GPIOMODE));
881         printk("RALINK_REG_GPIOMODE %08x !\n",gpiomode);
882
883         base_gpio_set(11,1);
884         mdelay(100);
885         base_gpio_set(11,0);
886         mdelay(100);
887         base_gpio_set(11,1);
888         mdelay(100);
889
890
891         struct base_spi* spi_init;
892
893         spi_init = &spi_pre[0];
894         spi_init->chip_select = 1;
895         spi_init->mode = SPI_MODE_3 ;
896         spi_init->speed = 40000000;
897         spi_init->sys_freq = 575000000;
898
899
900         spi_init->tx_buf[0] = 0xa5;
901         spi_init->tx_buf[1] = 0x8b;
902         spi_init->tx_len = 2;
903
904         base_spi_transfer_half_duplex(spi_init);
905 #endif
906         printk("insmod tft driver end !\n");
907
908         return 0;
909 }
910 /*
911 static void dev_release(void)
912 {
913         int i;
914         for(i = 0; i < 2; i++)
915         {
916                 if(spi_pre[i]){
917                         kfree()
918                 }
919
920         }
921 }
922 */
923 static void __exit tft_exit(void)
924 {
925 //              dev_t devno = MKDEV (hello_major, hello_minor);
926         printk("rmmod tft driver!\n");
927         device_destroy(my_class, MKDEV(spidrv_major, eye_l_minor));                //delete device node under /dev
928         device_destroy(my_class, MKDEV(spidrv_major, eye_r_minor));                //delete device node under /dev
929         class_destroy(my_class);                                                           //delete class created by us
930         unregister_chrdev(spidrv_major, "TFT");
931         printk("rmmod tft driver!\n");
932 }
933
934
935 module_init(tft_init);
936 module_exit(tft_exit);

下面是bpeer_tft.h文件1 #ifndef __TFT__

2 #define __TFT__

3 #include <asm/mach-ralink/rt_mmap.h>

4

5 #define TFT_EYE_VERSION         "1.0"

6 #define TFT_LIFT_DEVNAME        "eye_L"

7 #define TFT_RIGHT_DEVNAME       "eye_R"

8

9

10

11 #define TFT_IOCTL_BASE  ‘M‘

12

13 struct tft_reg_info {

14         char*   name;

15         u8              reg;

16         u16             val;

17 };

18

19 #define TFT_RESET               _IOR(TFT_IOCTL_BASE, 0, int)

20 #define TFT_SET_REG             _IOR(TFT_IOCTL_BASE, 1, struct tft_reg_info)

21 #define TFT_GET_REG             _IOR(TFT_IOCTL_BASE, 2, struct tft_reg_info)

22 #define TFT_DEBUG               _IOR(TFT_IOCTL_BASE, 3, int)

23

24 #define TFT_GPIO_RESET          3

25 #define TFT_GPIO_RS             2

26 #define TFT_GPIO_LED            0

27 #define TFT_EYER_CS             11

28 #define TFT_EYEL_CS             1

29

30

31

32 //define GPIO39         RS      pin

33 //define GPIO40         REST    pin

34 //define GPIO41         LED     pin

35 #define GPIO39          39

36 #define GPIO40          40

37 #define GPIO41          41

38 #define LED_ON          1

39 #define DEV_NAME                "bptft"

40 #define BUF_SIZE                80000

41 #define DEV_NUM                 2

42 #define SYS_CTRL                0XB0000000

43 #define GPIOMODE2_BASE          (SYS_CTRL + 0x64)  //configure to gpio mode

44 #define GPIOMODE2_CTRL_BASE     (SYS_CTRL + 0x604) //configure to output mode

45 #define GPIOMODE2_DATA_BASE     (SYS_CTRL + 0x624) //configure register up or down

46

47 #define LCD_X_SIZE      176

48 #define LCD_Y_SIZE      220

49 #define USE_HORIZONTAL  0

50

51 #ifdef USE_HORIZONTAL //使用横屏

52 #define X_MAX_PIXEL     LCD_Y_SIZE

53 #define Y_MAX_PIXEL     LCD_X_SIZE

54 #else//使用竖屏

55 #define X_MAX_PIXEL     LCD_X_SIZE

56 #define Y_MAX_PIXEL     LCD_Y_SIZE

57 #endif

58

59

60

61

62

63

64 /*    ------------------------------------spi----------------------------------------------------      */

65 #define SPI_REG_CTL             (RALINK_SPI_BASE + 0x00)

66

67 #define SPI_REG_CTL             (RALINK_SPI_BASE + 0x00)

68 #define SPI_REG_OPCODE          (RALINK_SPI_BASE + 0x04)

69 #define SPI_REG_DATA0           (RALINK_SPI_BASE + 0x08)

70 #define SPI_REG_DATA(x)         (SPI_REG_DATA0 + (x * 4))

71 #define SPI_REG_MASTER          (RALINK_SPI_BASE + 0x28)

72 #define SPI_REG_MOREBUF         (RALINK_SPI_BASE + 0x2c)

73 #define SPI_REG_Q_CTL           (RALINK_SPI_BASE + 0x30)

74 #define SPI_REG_CS_POLAR        (RALINK_SPI_BASE + 0x38)

75 #define SPI_REG_SPACE_CR        (RALINK_SPI_BASE + 0x3c)

76

77 #define SPI_CTL_START           0x00000100

78 #define SPI_CTL_BUSY            0x00010000

79 #define SPI_CTL_TXCNT_MASK      0x0000000f

80 #define SPI_CTL_RXCNT_MASK      0x000000f0

81 #define SPI_CTL_TX_RX_CNT_MASK  0x000000ff

82 #define SPI_CTL_SIZE_MASK       0x00180000

83 #define SPI_CTL_ADDREXT_MASK    0xff000000

84

85 #define SPI_MBCTL_TXCNT_MASK            0x000001ff

86 #define SPI_MBCTL_RXCNT_MASK            0x001ff000

87 #define SPI_MBCTL_TX_RX_CNT_MASK        (SPI_MBCTL_TXCNT_MASK | SPI_MBCTL_RXCNT_MASK)

88 #define SPI_MBCTL_CMD_MASK              0x3f000000

89

90 #define SPI_CTL_CLK_SEL_MASK    0x03000000

91 #define SPI_OPCODE_MASK         0x000000ff

92

93 #define SPI_STATUS_WIP          STM_STATUS_WIP

94

95 #define SPI_REG_CPHA            BIT(5)

96 #define SPI_REG_CPOL            BIT(4)

97 #define SPI_REG_LSB_FIRST       BIT(3)

98 #define SPI_REG_MODE_BITS       (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH)

99

100 #define SPI_CPHA                0x01

101 #define SPI_CPOL                0x02

102

103 #define SPI_MODE_0              (0|0)

104 #define SPI_MODE_1              (0|SPI_CPHA)

105 #define SPI_MODE_2              (SPI_CPOL|0)

106 #define SPI_MODE_3              (SPI_CPOL|SPI_CPHA)

107

108 #define SPI_CS_HIGH             0x04

109 #define SPI_LSB_FIRST           0x08

110 #define SPI_3WIRE               0x10

111 #define SPI_LOOP                0x20

112 #define SPI_NO_CS               0x40

113 #define SPI_READY               0x80

114

115

116

117 struct base_spi {

118         struct clk              *clk;

119         spinlock_t              lock;

120         unsigned int    speed;

121         unsigned int    sys_freq;

122         unsigned char           *start;

123         u32                     max_speed_hz;

124         u8                      chip_select;

125         u8                      mode;

126         u8                      tx_buf[36];

127         u8                      tx_len;

128         u8                      rx_buf[36];

129         u8                      rx_len;

130 };

131

132

133

134 struct tft_config_type {

135         struct base_spi* spi;

136

137 };

138

139

140 /* ------------------------------GPIO---------------------------------------------- */

141 #include <asm/rt2880/rt_mmap.h>

142

143 #define RALINK_SYSCTL_ADDR              RALINK_SYSCTL_BASE      // system control

144 #define RALINK_REG_GPIOMODE             (RALINK_SYSCTL_ADDR + 0x60)

145

146 #define RALINK_IRQ_ADDR                 RALINK_INTCL_BASE

147 #define RALINK_PRGIO_ADDR               RALINK_PIO_BASE // Programmable I/O

148

149 #define RALINK_REG_INTENA               (RALINK_IRQ_ADDR   + 0x80)

150 #define RALINK_REG_INTDIS               (RALINK_IRQ_ADDR   + 0x78)

151

152 #define RALINK_REG_PIOINT               (RALINK_PRGIO_ADDR + 0x90)

153 #define RALINK_REG_PIOEDGE              (RALINK_PRGIO_ADDR + 0xA0)

154 #define RALINK_REG_PIORENA              (RALINK_PRGIO_ADDR + 0x50)

155 #define RALINK_REG_PIOFENA              (RALINK_PRGIO_ADDR + 0x60)

156 #define RALINK_REG_PIODATA              (RALINK_PRGIO_ADDR + 0x20)

157 #define RALINK_REG_PIODIR               (RALINK_PRGIO_ADDR + 0x00)

158 #define RALINK_REG_PIOSET               (RALINK_PRGIO_ADDR + 0x30)

159 #define RALINK_REG_PIORESET             (RALINK_PRGIO_ADDR + 0x40)

160

161

162 #endif

如有疑问,请指出,多多交流

时间: 2024-09-29 15:28:28

基于MT7688 原厂SDK 使用SPI控制器驱动TFT屏幕ILI9225驱动器(spi接口)的相关文章

Linux SPI总线和设备驱动架构之三:SPI控制器驱动

通过第一篇文章,我们已经知道,整个SPI驱动架构可以分为协议驱动.通用接口层和控制器驱动三大部分.其中,控制器驱动负责最底层的数据收发工作,为了完成数据的收发工作,控制器驱动需要完成以下这些功能:1.    申请必要的硬件资源,例如中断,DMA通道,DMA内存缓冲区等等:2.    配置SPI控制器的工作模式和参数,使之可以和相应的设备进行正确的数据交换工作: 3.    向通用接口层提供接口,使得上层的协议驱动可以通过通用接口层访问控制器驱动: 4.    配合通用接口层,完成数据消息队列的排

Linux SPI总线和设备驱动架构之二:SPI通用接口层

通过上一篇文章的介绍,我们知道,SPI通用接口层用于把具体SPI设备的协议驱动和SPI控制器驱动联接在一起,通用接口层除了为协议驱动和控制器驱动提供一系列的标准接口API,同时还为这些接口API定义了相应的数据结构,这些数据结构一部分是SPI设备.SPI协议驱动和SPI控制器的数据抽象,一部分是为了协助数据传输而定义的数据结构.另外,通用接口层还负责SPI系统与Linux设备模型相关的初始化工作.本章的我们就通过这些数据结构和API的讨论来对整个通用接口层进行深入的了解. /**********

3.0.35 SPI主机控制器驱动和外设驱动

SPI(同步外设接口)是由motorola开发的全双工同步串行总线,其接口由MISO(串行数据输入),MOSI(串行数据输出),SCK(串行移位时钟) SS(从使能信号)4种信号构成.SS决定了惟一的与主设备通信的从设备,主设备通过产生移位时钟来发起通信. 在3.0.35 内核中,用spi_master 结构体来描述一个spi 主机控制器驱动,如下定义(include/linux/spi/spi.h): /** * struct spi_master - interface to SPI mas

Nexus 5 LG&quot;hammerhead&quot;刷机(刷原厂系统镜像)

Nexus 5到手是4.x的系统,系统通知有升级到5.0的包,就直接在后台下载安装了.平面的风格相当喜欢,但是系统占内存貌似比4.x要多,chrome也时常卡顿.然而最无法忍受的是——我用的AnyConnect的客户端只支持到4.x.有一款Openconnect的第三方客户端可以用,但是经常断线,而且这两天貌似全部停止服务,除了连接不上,豌豆荚和play市场也都无法下载.AnyConnect连接不上,系统自带的vpn居然也不行,因此只能刷机. ——现已刷回4.4,对5.x的界面非常不舍.希望下半

超级懒汉编写的基于.NET的微信SDK

一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发"框架",但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的xml消息在组装成实体类,所以会比较臃肿,现在都提倡轻量级,所以有什么办法可以避免大量实体类的存在呢. 当然,还有包装的比较繁杂,看完官方API后,再看"框架",让人感觉一头雾水,不够清晰.明了. 二.我的实现思路 我的微信SDK(不敢自称框架),最重要的实现2个目标: 1.轻量级,就是要摒弃实体类,尽量少的申明

[转贴]超级懒汉编写的基于.NET的微信SDK

一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发"框架",但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的xml消息在组装成实体类,所以会比较臃肿,现在都提倡轻量级,所以有什么办法可以避免大量实体类的存在呢. 当然,还有包装的比较繁杂,看完官方API后,再看"框架",让人感觉一头雾水,不够清晰.明了. 二.我的实现思路 我的微信SDK(不敢自称框架),最重要的实现2个目标: 1.轻量级,就是要摒弃实体类,尽量少的申明

TL-MR11U v2 openwrt 刷回原厂固件经验心得

第一次写博文,大家多多捧场哈. 小白刷openwrt 后,以无线AP模式工作,因为特殊情况,必须要用无线路由模式,而自己又不会玩iptables,故只能只能刷回原厂固件!下面就是实操了: 准备工作:下载并安装WinSCP和PuTTY. mr11u 长按reset键,恢复原厂设置. 本机网线直连路由器,telnet 192.168.1.1 passwd 123456,成功后关闭telnet 把准备好的固件,改名为1.bin,用WinSCP登录192.168.1.1 ,用户名/密码:root/123

广州14款奔驰S320S400原厂改装记忆座椅,桃木方向盘,电动..

广州14款奔驰S320S400原厂改装舒适进入,记忆座椅.桃木方向盘,电动尾门作业  产品名称:广州14款奔驰S320S400原厂舒适进入,记忆座椅.桃木方向盘,电动尾门作业  适合车型:奔驰S320S400一.以前奔驰车代表优雅,到现在的奔驰S还是存在.开宝马,做奔驰.但是现在的奔驰也一部分已经没有优雅了.考虑了很久,最后还是提了奔驰14款S320简配版.诶,票子不多啊,要是多的话,直接迈巴赫了.那个才是真真的舒适.提车回来,使用了一段时间,现在说说感受.车子最满意的就是开和坐都能感受奔驰S是

R6300V2 从 DD-WRT 回刷恢复 官方原厂固件 &nbsp; DD-WRT to R6300V2

DD-WRT 用着不方便需回刷 R6300V2原厂固件.在DD-WRT的升级界面中直接选择R6300V2的官方固件.chk升级两秒钟后页面自动跳转显示无法访问.无法完成刷机. 解决办法是DD-WRT选择恢复默认设置后然后升级即可. 附件 R6300v2   官方固件下载    http://support.netgear.cn/doucument/More.asp?id=2226   固件有历史依赖性请参看官方固件版本说明中的依赖关系本文中使用的是 R6300v2_V1.0.0.8_1.0.4P