当前位置:首页 > 技术 > LINUX > 正文内容

【转】小白自制Linux开发板 七. USB驱动配置

Watrt2个月前 (01-06)LINUX1170

F1c100s芯片支持USB的OTG模式,也就是可以通过更改UsbId拉低或拉高方式定义当前的开发板可以作为host还是device。

  • usbid 拉高时,开发板作为外设方式。

  • usbid 拉低时,开发板作为主机方式。

当然除了使用硬件方式,还可以通过Linux系统直接更改当前USB的模式。

1. 原理图

在F1c100s中PE2引脚是作为usbid功能来使用,因为为了使用Sunxi-tool 所以我在画原理图的时候默认将PE2做了上拉处理。

 这个芯片只有一个usb引脚

 为了可以引出更多的usb外设,所以这里使用了FE8.1这个USB Hub芯片,这个芯片最多可以引出4个Usb接口。具体原理图如下:

 2. 设备树与驱动代码配置

硬件处理完成,接下来就是软件部分修改了,打开Linux5.7.1内核源码

2.1 首先修改设备树文件arch/arm/boot/dts/suniv-f1c100s.dtsi文件

在soc节点下增加

usb_otg: usb@1c13000 {
    compatible = "allwinner,suniv-musb";
    reg = <0x01c13000 0x0400>;
    clocks = <&ccu CLK_BUS_OTG>;
    resets = <&ccu RST_BUS_OTG>;
    interrupts = <26>;
    interrupt-names = "mc";
    phys = <&usbphy 0>;
    phy-names = "usb";
    extcon = <&usbphy 0>;
    allwinner,sram = <&otg_sram 1>;
    status = "disabled";
};
usbphy: phy@1c13400 {
    compatible = "allwinner,suniv-usb-phy";
    reg = <0x01c13400 0x10>;
    reg-names = "phy_ctrl";
    clocks = <&ccu CLK_USB_PHY0>;
    clock-names = "usb0_phy";
    resets = <&ccu RST_USB_PHY0>;
    reset-names = "usb0_reset";
    #phy-cells = <1>;
    status = "disabled";
};

2.2 修改arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts文件

在文件里面添加

&otg_sram {
        status = "okay";
};&usb_otg {
        dr_mode = "host"; /* 三个可选项: otg / host / peripheral  我在这里指定为host模式*/
        status = "okay";
};&usbphy {
        usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>; /* PE2 */
        status = "okay";
};

2.3 修改drivers/phy/allwinner/phy-sun4i-usb.c文件

因为我们在设备树中定义的驱动是suniv-usb-phy,所以我们需要添加这部分代码。

enum sun4i_usb_phy_type {
    suniv_phy,  //新增枚举值    sun4i_a10_phy,
    sun6i_a31_phy,
    sun8i_a33_phy,
    sun8i_a83t_phy,
    sun8i_h3_phy,
    sun8i_r40_phy,
    sun8i_v3s_phy,
    sun50i_a64_phy,
    sun50i_h6_phy,
};
//新增以下结构static const struct sun4i_usb_phy_cfg suniv_cfg = {
    .num_phys = 1,
    .type = suniv_phy,
    .disc_thresh = 3,
    .phyctl_offset = REG_PHYCTL_A10,
    .dedicated_clocks = true,
};
static const struct of_device_id sun4i_usb_phy_of_match[] = {
    { .compatible = "allwinner,suniv-usb-phy", .data = &suniv_cfg }, //新增配置项
    { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
    { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
    { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg },
    { .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
    { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
    { .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
    { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = &sun8i_a83t_cfg },
    { .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
    { .compatible = "allwinner,sun8i-r40-usb-phy", .data = &sun8i_r40_cfg },
    { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
    { .compatible = "allwinner,sun50i-a64-usb-phy",
      .data = &sun50i_a64_cfg},
    { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
    { },
};

2.4 修改drivers/usb/musb/sunxi.c文件

这里主要处理设备树中定义的驱动suniv-musb

static int sunxi_musb_probe(struct platform_device *pdev)
{    struct musb_hdrc_platform_data    pdata;    struct platform_device_info    pinfo;    struct sunxi_glue        *glue;    struct device_node        *np = pdev->dev.of_node;    int ret;    if (!np) {
        dev_err(&pdev->dev, "Error no device tree node found\n");        return -EINVAL;
    }
    glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);    if (!glue)        return -ENOMEM;
    memset(&pdata, 0, sizeof(pdata));    switch (usb_get_dr_mode(&pdev->dev)) {#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST    case USB_DR_MODE_HOST:
        pdata.mode = MUSB_HOST;
        glue->phy_mode = PHY_MODE_USB_HOST;        break;#endif#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET    case USB_DR_MODE_PERIPHERAL:
        pdata.mode = MUSB_PERIPHERAL;
        glue->phy_mode = PHY_MODE_USB_DEVICE;        break;#endif#ifdef CONFIG_USB_MUSB_DUAL_ROLE    case USB_DR_MODE_OTG:
        pdata.mode = MUSB_OTG;
        glue->phy_mode = PHY_MODE_USB_OTG;        break;#endif
    default:
        dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n");        return -EINVAL;
    }
    pdata.platform_ops    = &sunxi_musb_ops;    if (!of_device_is_compatible(np, "allwinner,sun8i-h3-musb"))
        pdata.config = &sunxi_musb_hdrc_config;    else
        pdata.config = &sunxi_musb_hdrc_config_h3;
    glue->dev = &pdev->dev;
    INIT_WORK(&glue->work, sunxi_musb_work);
    glue->host_nb.notifier_call = sunxi_musb_host_notifier;    if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb")||
        of_device_is_compatible(np, "allwinner,suniv-musb")){ //新增判断项代码
        set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
    }    if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
        set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);    if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") ||
        of_device_is_compatible(np, "allwinner,sun8i-h3-musb") ||
        of_device_is_compatible(np, "allwinner,suniv-musb")) {  //新增判断项代码
        set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
        set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
    }
    glue->clk = devm_clk_get(&pdev->dev, NULL);    if (IS_ERR(glue->clk)) {
        dev_err(&pdev->dev, "Error getting clock: %ld\n",
            PTR_ERR(glue->clk));        return PTR_ERR(glue->clk);
    }    if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
        glue->rst = devm_reset_control_get(&pdev->dev, NULL);        if (IS_ERR(glue->rst)) {            if (PTR_ERR(glue->rst) == -EPROBE_DEFER)                return -EPROBE_DEFER;
            dev_err(&pdev->dev, "Error getting reset %ld\n",
                PTR_ERR(glue->rst));            return PTR_ERR(glue->rst);
        }
    }
    …………
static const struct of_device_id sunxi_musb_match[] = {
    { .compatible = "allwinner,suniv-musb", }, //新增代码
    { .compatible = "allwinner,sun4i-a10-musb", },
    { .compatible = "allwinner,sun6i-a31-musb", },
    { .compatible = "allwinner,sun8i-a33-musb", },
    { .compatible = "allwinner,sun8i-h3-musb", },
    {}
};

2.5 通过menuconfig配置usb相关的选项

进入:Device Drivers - USB support

 进行配置,当然可以根据自己实际情况进行开启与配置。

接下载编译Linux编译内核和设备树,就可以得到内核文件和设备树文件了。

3. 测试USB键盘

这里我默认设置开发板为host模式,然后我要通过usb连接键盘进行输入操作:

[   31.653231] cfg80211: failed to load regulatory.db
[   31.696053] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[   31.707915] VFS: Mounted root (ext4 filesystem) on device 179:2.
[   31.726584] devtmpfs: mounted
[   31.736031] Freeing unused kernel memory: 1024K
[   31.746083] Run /sbin/init as init process
[   32.023410] usb 1-1: new high-speed USB device number 2 using musb-hdrc
[   32.215728] hub 1-1:1.0: USB hub found
[   32.221496] hub 1-1:1.0: 4 ports detected

 启动日志中我们可以看到usb已经被检测到,并且检测到4个端口,但是我们只用到两个。

插入键盘。

拔出键盘。

 键盘操作开发板:

 如果想要进一步了解usb相关的操作,可以借助usbutils相关组件。

首先安装usbutils组件

apt-get install usbutils

安装完成后执行:

lsusb

就可以查看相关usb设备信息了。

4 通过LINUX方式更改USB属性

首先更改设备树,改为otg模式

&usb_otg {
        dr_mode = "otg"; /* 三个可选项: otg / host / peripheral */
        status = "okay";
};

进入Linux系统,执行,usb将会被设置成为host模式

echo host > /sys/devices/platform/soc/1c13000.usb/musb-hdrc.1.auto/mode

运行结果如下,此时可以插入键盘,就可以使用键盘操作Linux了。

# echo host > /sys/devices/platform/soc/1c13000.usb/musb-hdrc.1.auto/mode
# [117.758152] phy phy-1c13400.phy.0: Changing dr_mode to 1[  118.414817] usb 1-1: new high-speed USB device number 3 using musb-hdrc
[  118.598193] usb-storage 1-1:1.0: USB Mass Storage device detected
[  118.611789] scsi host0: usb-storage 1-1:1.0[  119.686198] scsi 0:0:0:0: Direct-Access     Mass     Storage Device   1.00 PQ: 0 ANSI: 0 CCS
[  119.703976] sd 0:0:0:0: [sda] 3842048 512-byte logical blocks: (1.97 GB/1.83 GiB)
[  119.725260] sd 0:0:0:0: Attached scsi generic sg0 type 0[  119.739844] sd 0:0:0:0: [sda] Write Protect is off
[  119.771819] sd 0:0:0:0: [sda] No Caching mode page found
[  119.777288] sd 0:0:0:0: [sda] Assuming drive cache: write through
[  119.801571]  sda: sda1 sda2 sda3
[  119.817224] sd 0:0:0:0: [sda] Attached SCSI removable disk

如果执行如下命令,则进入设备模式

#
##切换到device模式:
# echo peripheral > /sys/devices/platform/soc/1c13000.usb/musb-hdrc.1.auto/mode
[  123.880272] phy phy-1c13400.phy.0: Changing dr_mode to 2# [  123.890905] usb 1-1: USB disconnect, device number 3

 后记

在论坛中用有测试表明,在这个方案配置完USB后,可能无法同时运行两个控制设备,墨云没做相关测试,如果有相关需求的还请注意核实。谢谢

分享给朋友:

相关文章

Linux 压缩解压命令备忘

Linux 压缩解压命令备忘

01-.tar格式解包:[*******]$ tar xvf FileName.tar 打包:[*******]$ tar cvf FileName.tar DirName(注:tar是打包,不是压缩!) 02-.gz格式 解压1:[*******]$ gunzip FileName.gz 解压2:[*******]$ gzip -d FileName.gz 压 缩:[*******]$ gzip...

制作荔枝派Zero开发板(全志V3s) TF/SD卡启动盘

制作荔枝派Zero开发板(全志V3s) TF/SD卡启动盘

0. 前言近几天买了一块荔枝派0开发板,以及官方配的480×272的屏幕。让我记录一下入坑与采坑过程。1. u-boot的编译git clone https://github.com/Lichee-Pi/u-boot -b v3s-current cd u-boot make ARCH=arm LicheePi_Zero_480x272LCD_defconfig make ARCH=arm CROSS...

Deepin Linux修复grub引导

Deepin Linux修复grub引导

环境说明:一直使用的是Win7+Deepin 15.5。后来全新安装了Win 10,需要修复grub第一步:在Windows操作系统下使用深度官方的U盘启动制作器 制作U盘第二步:开机U盘启动进入Deepin linux安装界面,待进入到安装界面选择语言时,按住Crtl+Alt+F2/F1进入Linux tty终端。并执行以下命令完成修复sudo fdisk -l/*根据查询结果确定deepin 的/目录和/boot目录所在的分区编号*/sudo mount&nbs...

buildroot编译中的问题

buildroot编译中的问题

在编译中遇到flex 报错。一直过不了。后来发现安装flex bison两个包后解决sudo apt-get install flex bison...

荔枝派Nano 全流程指南

荔枝派Nano 全流程指南

u-boot 初体验安装交叉编译链首先需要安装交叉编译链:# 此处为获取7.2.1版本,您可获取其他版本或者通过链接直接下载 wget http://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/arm-linux-gnueabi/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz tar -vxJf gcc-li...

利用BusyBox ~私人定制 My LINUX~

利用BusyBox ~私人定制 My LINUX~

前言  我在今天在这里跟大家详细地探讨一下Linux系统的定制过程和实现例如、用户能够远程登录;和Nginx能够稳定地运行在我们私人定制的LINUX系统上、一步一步从头开始定制属于我们自己的系统。正文   首先我们先来简单的介绍一下我们这里定制属于自己的Linux系统的基本元素.   一个定制的linux内核+一个定制的busybox就可以定制一个小型的Linux操作系统了,安装Dropbear和Nginx,Linux的组成 部分包括内核空间和用户空间、而...

 Debian 9.9 (stretch) 文件系统制作

Debian 9.9 (stretch) 文件系统制作

0. 准备工作:sudo apt install qemu-user-static -y sudo apt install debootstrap -y mkdir rootfs1. debootstrapdebootstrap --foreign --verbose --arch=armhf  stretch rootfs http...

控制台终端输出颜色

控制台终端输出颜色

在使用putty、secureCRT、XShell等终端仿真器连接linux系统时,ls、vim等工具的输出都含有各种颜色,这些颜色的输出大大地增强了文本的可读性。一、终端文本颜色输出的一般示例在bash中,通常我们可以使用echo命令加-e选项输出各种颜色的文本,例如:echo -e "\033[31mRed Text\033[0m" echo -e "\033[32mGreen Text\033[0m...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。