高通AR93XX QCA95XX系列CPU上调试32MB SPI Nor Flash

flash 专栏收录该内容
2 篇文章 0 订阅

项目需求,需要基于Openwrt BB1407在一款QCA9561上调试一块32MB的SPI Nor Flash芯片(mx25l2563xx)。一开始产品设计的时候,曾经论证过高通9xxx系列CPU能不能支持32MB Nor Flash的问题。那时想当然的认为,SPI Nor Flash不就是基于SPI总线访问的普通设备嘛,只要SPI总线正常,跟容量大小又有什么关系呢?当真正开始调的时候,才发现自己想的太简单了。

1. Flash地址模式问题

16MB以下的flash,在SPI总线上进行命令寻址操作的时候,地址参数共3个byte,即24-bit模式,而超过16M以后,地址参数就变成了4byte,即32-bit模式。超过16MB的SPI Nor Flash,一般都会有地址模式转换命令,比如mx25l2563xx,它的地址转换命令为:EN4B和EX4B,使得Flash可以在两个模式之间自由切换。地址模式除了关乎正确寻址之外,还会关系到重启是否正常。
SPI Nor Flash是不支持普通Nor Flash那样直接寻址读取数据的,要使CPU基于SPI Nor Flash正常启动,需要CPU在启动时能够自动从Flash芯片起始位置读取一定量的内容,方能保证系统可以正常启动。对此,一般CPU会要求SPI Nor Flash处于3byte模式(至少高通这几款是这样的)。
在基于Openwrt bb1407的版本中,Linux内核已经能够支持mx25l2563xx,驱动初始化时,会让Flash进入到4byte模式,当此时执行重启操作,系统将不会正常重启。解决这个问题通常有两种方法:

方法一

在linux的reboot过程中,会去调用Flash驱动的remove操作,所以对于重启不正常的问题,解决方法就是针对32M的Flash执行一个Reset或是EX4B命令,执行完毕后,系统就可以正常重启了。

/* drivers/mtd/devices/m25p80.c */
/* Reset opcodes */
#define OPCODE_RSTEN        0x66    /* Enable reset */
#define OPCODE_RESET        0x99    /* Reset device */

/*
 * Reset whole flash chip. Only be avaliable for chips size >= 32MiB
*/
static inline int flash_4byte_mode_reset(struct m25p *flash)
{
    struct spi_transfer t[2];
    struct spi_message m;
    char command[2];
    int ret;

    if (flash->addr_width != 4) 
        return 1;

    spi_message_init(&m);
    memset(t, 0, (sizeof t));

    t[0].tx_buf = &command[0];
    t[0].len = 1;
    t[0].cs_change = 1;
    spi_message_add_tail(&t[0], &m);

    t[1].tx_buf = &command[1];
    t[1].len = 1;
    t[1].cs_change = 1;
    spi_message_add_tail(&t[1], &m);

    command[0] = OPCODE_RSTEN;
    command[1] = OPCODE_RESET;

    mutex_lock(&flash->lock);

    ret = wait_till_ready(flash);
    if (ret) {
        mutex_unlock(&flash->lock);
        return 1;
    }

    spi_sync(flash->spi, &m);

    mutex_unlock(&flash->lock);

    return 0;
}

static int m25p_remove(struct spi_device *spi)
{
    struct m25p *flash = dev_get_drvdata(&spi->dev);
    int     status;

    /* Reset flash which is in 4-byte mode, since the system reset must run in 3byte mode */
    flash_4byte_mode_reset(flash);

    /* Clean up MTD stuff. */
    status = mtd_device_unregister(&flash->mtd);
    if (status == 0) {
        kfree(flash->command);
        kfree(flash);
    }
    return 0;
}

方法二

一般超过16MB的SPI Nor Flash都会有一些特殊的4byte模式操作命令,比如这款mx25l2563xx,通过查看其手册,可知以下命令:
4byte 命令
由上图可知,使用命令READ4B、PP4B、BE4B就可以对整个32MB的地址空间进行读写、擦除操作,而这个过程不需要对Flash执行地址模式切换操作,这样执行reboot的时候就跟原来一样,不会产生问题。其他厂商的Flash芯片都有类似命令,当然这个改动会稍微大一些,而且要随着Flash芯片的不同做不同的命令配置,维护起来感觉要麻烦一些。

2. 高通CPU对SPI Nor Flash特殊的读取优化

以前在调试mtk mt7620a和高通的ar934x系列uboot的时候曾经遇到过一个问题,就是mtk的机器在uboot里面进行SPI Nor Flash读写操作后,很容易产生丢内容的问题。跟踪了下,发现是因为一开始相关功能是在ar934x上面调试,然后功能比较通用,于是代码就直接移到mt7620a上来了。在ar934x上面,对SPI Nor Flash的读取访问,直接用了memcpy方式,高通的机器没有问题,但是同样的代码在mt7620a上就不对了。
按说SPI的访问,怎么能够用memcpy操作呢?在mt7620a上显然是这里出了问题,老老实实改回标准SPI读写方式,问题就解决了。那反过来,为何ar934x这样使用没有问题呢?由于该访问方式是直接照搬了高通提供的uboot原生代码,再加上事物繁忙,对于这点虽然有疑问,但一直没详加研究。-__-|| 一直到这次调试32MB的Flash才对这个问题有了更进一步的认识。

高通9xxx的地址空间
通常,访问SPI Nor Flash都是基于SPI总线接口,串行读取。但是高通的CPU对此做了一个硬件优化,可以将16MB及以下的Flash地址空间映射到一个内存空间直接访问(对于这些MIPS内核的高通CPU,该段空间属于kseg1区域),这样当要读取这些flash上的内容时,代码可以采用memcpy模式,很好的提升了读取速度。
对应代码为:

/* drivers/spi/spi-ath79.c */
static int ath79_spi_setup_transfer(struct spi_device *spi,
                    struct spi_transfer *t)
{
    struct ath79_spi *sp = ath79_spidev_to_sp(spi);
    struct ath79_spi_controller_data *cdata;
    int ret;

    ret = spi_bitbang_setup_transfer(spi, t);
    if (ret)
        return ret;

    cdata = spi->controller_data;
    /* 当is_flash置位时,采用memcpy方式,否则使用标准SPI方式 */
    if (cdata->is_flash)
        sp->bitbang.txrx_bufs = ath79_spi_txrx_bufs;
    else
        sp->bitbang.txrx_bufs = spi_bitbang_bufs;

    return ret;
}

一般在SPI Nor Flash驱动注册时,都会把这个is_flash置位。但是对于32MB Flash,一旦进入到这个4byte模式,这个硬件机制将不再有效,由于地址空间变了,读取都变得不正常,会导致启动内核失败。此时必须切回到标准的SPI操作,也就是将上述的is_flash清0,当然这会让读取速度慢很多。

/* arch/mips/ath79/dev-m25p80.c */
/* 针对32M flash,需要使用标准SPI 操作,不能使用AR 的memory copy */
void ath79_m25p80_use_raw_spi_txrx(void)
{
    ath79_spi0_cdata.is_flash = 0;
}
/* arch/mips/ath79/mach-xxx.c */

static void read_flash_id(void)
{
    u32 rd;

    ath_reg_wr_nf(ATH_SPI_FS, 1);
    ath_reg_wr_nf(ATH_SPI_WRITE, ATH_SPI_CS_DIS);
    ath_spi_bit_banger(ATH_SPI_CMD_RDID);
    ath_spi_delay_8();
    ath_spi_delay_8();
    ath_spi_delay_8();
    ath_spi_go();

    rd = ath_reg_rd(ATH_SPI_RD_STATUS);
    ath_reg_wr_nf(ATH_SPI_FS, 0);
    switch(rd){
        case 0xc22019:
            board_flash_4byte_mem_mode = 1;
            break;
        /* 其他大于16M 的SPI NOR FLASH */
        case xxxx:
        default:
            board_flash_4byte_mem_mode = 0;
            break;
    }

}

/* xx_setup */
static void xx_setup(void)
{
    ....
    read_flash_id();
    if(board_flash_4byte_mem_mode)
        ath79_m25p80_use_raw_spi_txrx();
    ...
}

假如仍然让Flash保持在3byte模式,则还是可以正常使用,但是只能正常使用前16MB的空间。

2.1 使用硬件优化方式与传统SPI方式的性能对比

通过对一颗16MB的Flash芯片,分别使用高通硬件优化方式和标准SPI读取方式,基于MTD命令读写命令,进行了简单的读写性能对比,结果如下:
memcpy模式,
读 15MB 9s 1.667MB/S
写 15MB 159s 0.094MB/S

SPI标准模式,
读15MB 18s 0.833MB/S
写 15MB 159s 0.094MB/S
由上可知,当使用SPI标准模式时,读取速度降了一半。

3. 无线驱动加载问题

高通的wifi驱动,一般需要有一个ART MTD分区,用来存放一些与wifi射频相关的参数,以供驱动启动时利用这些参数来做初始化配置。
通常这些无线参数都是在内核启动早期,通过memcpy的方式从SPI Nor Flash上面读取到特定的内存位置,现在变成32MB后,超过16MB的位置将无法继续使用这种方法访问。解决方法就是在这个位置判断Flash型号,如果Flash容量超过32MB,并且ART区还是在Flash的最后64KB,那么可以做个标记,等整个MTD起来后且在无线驱动加载之前,通过MTD的接口来进行参数区读取。
如果还是想用memcpy方式,可以考虑把ART区放在前面16MB,应该也是可以的,只是这样的话,改动牵扯面可能就比较大了,无线相关的参数校准、驱动加载都需要调整。

4. 后记

把上述几个问题都搞清楚后,在高通CPU上调试32MB Flash也就水到渠成,迎刃而解了。MT7620A并没有这样的硬件优化机制,所以在前面提到的uboot中使用高通的代码显然就会出错了(掉以轻心的ctrl+c ctrl+v害死人呀)。也难怪高通的片子要比MT7620A贵不少呢。
不过便宜有便宜的好处,至少在mt7620a上除了Flash地址模式这一共性问题需要注意外,其他方面都应该不用做大的修改了。

参考资料

https://forum.openwrt.org/viewtopic.php?id=45219
http://blog.csdn.net/manfeel/article/details/43530817

  • 2
    点赞
  • 0
    评论
  • 4
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

QCA8337N是一个高度集成的七端口千兆位以太网交换机,具有非阻塞交换机结构,一个具有2048个MAC地址的高性能查找单元,以及四个流量等级的QualityofS。服务(QoS)引擎QCA8337N交换机具有支持各种网络应用程序的灵活性。QCA8337N是为高端网关和xpon中的成本敏感的交换机应用而设计的。 QCA8337N集成了高速交换系统的所有功能,包括数据包缓冲区、PHY收发器、媒体访问控制器、地址管理和非阻塞交换结构。一个55 nm的CMOS器件。它符合10 BASE-Te和1000 BASE-T规范,包括mac控制、暂停帧和自动协商子部分,提供了与所有行业标准以太网、快速et兼容的功能。 QCA8337N器件包含5个全双工10BASE-Te/100BASE-Tx/1000BASE-T收发信机,10BASE-Te/100BASE-Tx可以在半双工运行,每一个都执行所有物理层Interfa。它们在第5类无屏蔽双绞线(UTP)电缆执行10BASE-Te以太网的所有物理层接口功能,在第5类UTP电缆执行快速/千兆以太网的所有物理层接口功能。 其余两个端口具有标准的GMII/RGMII/MII/SerDes接口,允许在PON/xDSL/电缆/Wi-Fi/光纤路由器中连接到主机CPU。在QCA8337N的媒体访问控制器也是。upport巨帧,通常用于与服务器的高性能连接,因为它们为更高的效率提供了较小的链路开销百分比。 spi或EEProm接口提供片内802.1pQoS和/或DiffServ/TOS的轻松编程。这允许将交换机流量指定为不同级别的优先级或服务-例如,语音IP电话应用程序的通信量,多媒体应用程序的视频通信量,或电子邮件应用程序的数据流量。 可以通过SPI端口设置多达4K的虚拟局域网(VLAN),以分离网络的不同用户或组。ACL特性可以减少基于第一层到第四层信息的VLAN/QoS/DSCP/正向映射和重映射的CPU工作量。PPPoE头加/移除可以提高视频质量和卸载CPU负载。绿色节电技术可以提高无链路或空闲状态下的能效 Qualcomm XSPantM QCA9563是一个高度集成和功能丰富的IEEE 802.11n 3x3 2.4 GHz系统芯片(SoC),适用于先进的WLAN平台。 它包括一个MIPS 74Kc处理器,一个SGMII接口和一个外部存储器接口,用于串行Flash,DDR 1或DDR 2,UART,PCIe,两个USB 2.0主机控制器,内置的MAC/PHY和GPO可用于LED控件或其他通用接口配置。 QCA9563支持高达216 Mbps的20 MHz和450 Mbps的40 MHz的802.11n操作和802.11b/g的数据速率。其他特性包括最大似然(ML)译码、低密度奇偶。 QCA9563支持从NOR闪存启动 Qualcomm Atheros QCA9882 是一种用于5GHz 802.11ac或2.4/5 GHz 802.11n WLAN应用的高度集成的无线局域网(WLAN)片系统(SoC)。QCA9882集成了板载CPU,用于WLAN物理层(PHY)和RF的低级设置,以便将主机处理器卸载到其他任务。支持两种空间的高性能2x2MIMO无线应用的流要求最高的健壮链路质量和最大的吞吐量和范围。QCA9882集成了多协议mac、phy、模拟数字/数字模拟转换器(ADC/DAC)、2x2mimo无线电收发器和pci Express接口,用于低功耗的cmos器件。 QCA9882实现了半双工OFDM、CCK和DSSS PHY,支持802.11ac 80MHz信道操作的867Mbps.它支持20MHz的802.11n和40MHz的300Mbps的802.11n,以及IEEE 802.11a/b/g数据速率。其他特性包括最大似然(ML)译码、低密度奇偶校验(Ldpc)、最大比合并(Mrc)、空时分组码(Stbc)。),以及片一次可编程(OTP)存储器,以消除外部闪存的需要,并进一步降低外部组件计数和BOM成本。QCA 9882支持802.11无线MA。C协议、802.11i安全、Rx/TX过滤、错误恢复和802.11e服务质量(QoS) QCA 9882支持多达两个同时的业务流,将两个TX和两个Rx链集成在一起,以实现高吞吐量和扩展覆盖。Tx链结合PHY同相(I)和正交(Q)sigNAL,将它们转换到所需的频率,并将RF信号驱动到多个天线。RX链使用集成的体系结构。该频率合成器支持1MHz步骤,以匹配IEEE 802.11a/b/g/n规范定义的频率。QCA9882支持使用PCIe接口与主机之间的帧数据传输。提供中断生成和报告、电源保存和状态报告。其他外部接口包
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值