watchdog module_amba_driver

 

[root@centos7 linux-5.14]# ls /dev/watchdog
/dev/watchdog

 

[root@centos7 opensbi]#  ls  /sys/bus/amba/
devices  drivers  drivers_autoprobe  drivers_probe  uevent
[root@centos7 opensbi]#  ls  /sys/bus/amba/devices/
[root@centos7 opensbi]# 

 

 

[root@centos7 opensbi]#  ls  /sys/bus/amba/devices/
[root@centos7 opensbi]#  ls  /sys/bus/amba/
devices  drivers  drivers_autoprobe  drivers_probe  uevent
[root@centos7 opensbi]#  ls  /sys/bus/amba/devices/
[root@centos7 opensbi]#  ls  /sys/bus/amba/devices/
[root@centos7 opensbi]#  ls  /sys/bus/amba/
devices  drivers  drivers_autoprobe  drivers_probe  uevent
[root@centos7 opensbi]#  ls  /sys/bus/amba/drivers
clcd-pl11x  kmi-pl050  pl061_gpio  rtc-pl031  uart-pl011
[root@centos7 opensbi]# 

 

 

 

/*
 * module_amba_driver() - Helper macro for drivers that don't do anything
 * special in module init/exit.  This eliminates a lot of boilerplate.  Each
 * module may only use this macro once, and calling it replaces module_init()
 * and module_exit()
 */
#define module_amba_driver(__amba_drv) \
        module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)

 

#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
        return __register(&(__driver) , ##__VA_ARGS__); \
} 

 ARM_AMBA

 

drivers/amba/Kconfig:2:config ARM_AMBA

root@ubuntu:~/linux_arm64/linux-5.14# grep ARM64  .config
CONFIG_ARM64=y

 

root@ubuntu:~/linux_arm64/linux-5.14# grep ARM_AMBA  .config
CONFIG_ARM_AMBA=y

 

drivers/amba/Makefile:2:obj-$(CONFIG_ARM_AMBA)          += bus.o
include/linux/amba/bus.h:108:#ifdef CONFIG_ARM_AMBA

 

drivers/amba/bus.c

 

EXPORT_SYMBOL(amba_driver_register);
EXPORT_SYMBOL(amba_driver_unregister);
EXPORT_SYMBOL(amba_device_register);
EXPORT_SYMBOL(amba_device_unregister);
EXPORT_SYMBOL(amba_find_device);
EXPORT_SYMBOL(amba_request_regions);
EXPORT_SYMBOL(amba_release_regions);

 


 

 

 

 

 

 

 

 

root@ubuntu:~/linux_arm64/linux-5.14# grep ARM_SP805_WATCHDOG .config
CONFIG_ARM_SP805_WATCHDOG=m
root@ubuntu:~/linux_arm64/linux-5.14# lscpu
Architecture:        aarch64
Byte Order:          Little Endian
CPU(s):              64
On-line CPU(s) list: 0-63
Thread(s) per core:  1
Core(s) per socket:  32
Socket(s):           2
NUMA node(s):        4
Vendor ID:           ARM
Model:               2
Model name:          Cortex-A72
Stepping:            r0p2
BogoMIPS:            100.00
L1d cache:           32K
L1i cache:           48K
L2 cache:            1024K
L3 cache:            16384K
NUMA node0 CPU(s):   0-15
NUMA node1 CPU(s):   16-31
NUMA node2 CPU(s):   32-47
NUMA node3 CPU(s):   48-63
Flags:               fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
root@ubuntu:~/linux_arm64/linux-5.14# 

 

 

CONFIG_ARM_AMBA

drivers/of/platform.c:28://#ifdef CONFIG_ARM_AMBA
drivers/of/platform.c:218://#ifdef CONFIG_ARM_AMBA
drivers/of/platform.c:573://#ifdef CONFIG_ARM_AMBA
drivers/iommu/amd/iommu.c:1795:#ifdef CONFIG_ARM_AMBA
drivers/iommu/arm/arm-smmu/arm-smmu.c:2030:#ifdef CONFIG_ARM_AMBA
drivers/iommu/arm/arm-smmu/arm-smmu.c:2058:#ifdef CONFIG_ARM_AMBA
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c:3718:#ifdef CONFIG_ARM_AMBA
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c:3734:#ifdef CONFIG_ARM_AMBA
drivers/iommu/virtio-iommu.c:1088:#ifdef CONFIG_ARM_AMBA
drivers/xen/arm-device.c:146:#ifdef CONFIG_ARM_AMBA
drivers/gpu/drm/pl111/pl111_drv.c:441:#ifdef CONFIG_ARM_AMBA
drivers/acpi/internal.h:29:#ifdef CONFIG_ARM_AMBA
include/linux/amba/bus.h:108://#ifdef CONFIG_ARM_AMBA

 

riscv SP805

# ALPHA Architecture

# ARM Architecture

config ARM_SP805_WATCHDOG
        tristate "ARM SP805 Watchdog"
        depends on (ARM || ARM64 || COMPILE_TEST) && ARM_AMBA
        select WATCHDOG_CORE
        help
          ARM Primecell SP805 Watchdog timer. This will reboot your system when
          the timeout is reached.

 

 

 

 

 

[root@centos7 linux-5.14]# grep SP805  .config
CONFIG_ARM_SP805_WATCHDOG=y
[root@centos7 linux-5.14]# 

 

[root@centos7 linux-5.14]# make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-   -j128
  SYNC    include/config/auto.conf.cmd
  CALL    scripts/atomic/check-atomics.sh
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CC      drivers/watchdog/watchdog_core.o
  CC      drivers/watchdog/watchdog_dev.o
  CC      drivers/watchdog/sp805_wdt.o
  UPD     kernel/config_data
  GZIP    kernel/config_data.gz
  CC      kernel/configs.o
  AR      kernel/built-in.a
  AR      drivers/watchdog/built-in.a
  AR      drivers/built-in.a
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  AR      init/built-in.a
  LD      vmlinux.o
  MODPOST vmlinux.symvers
  MODINFO modules.builtin.modinfo
  GEN     modules.builtin
  LD      .tmp_vmlinux.kallsyms1
  KSYMS   .tmp_vmlinux.kallsyms1.S
  AS      .tmp_vmlinux.kallsyms1.S
  LD      .tmp_vmlinux.kallsyms2
  KSYMS   .tmp_vmlinux.kallsyms2.S
  AS      .tmp_vmlinux.kallsyms2.S
  LD      vmlinux
  SYSMAP  System.map
  MODPOST modules-only.symvers
  OBJCOPY arch/riscv/boot/Image
  GEN     Module.symvers
  GZIP    arch/riscv/boot/Image.gz
  Kernel: arch/riscv/boot/Image.gz is ready
[root@centos7 linux-5.14]# cat System.map | grep amba_driver_registe
[root@centos7 linux-5.14]# cat System.map | grep 

 

竟然没有

[root@centos7 linux-5.14]# cat System.map | grep sp805_wdt_probe
[root@centos7 linux-5.14]# cat System.map | grep sp805_wdt_resume
[root@centos7 linux-5.14]# 

 

clean 下重新编译

[root@centos7 linux-5.14]# cat System.map | grep sp805_wdt_probe
[root@centos7 linux-5.14]# cat System.map | grep sp805
ffffffff8061c276 t sp805_wdt_driver_init
ffffffff8062ae7e t sp805_wdt_driver_exit
ffffffff8080f5f8 d __initcall__kmod_sp805_wdt__324_358_sp805_wdt_driver_init6
[root@centos7 linux-5.14]# cat System.map | grep amba_driver_
[root@centos7 linux-5.14]# 

 

但是还是没有amba_driver_

 

原来是.config 和 driver/xx/Kconfig   driver/xx/Makefile 中的config_XXX不一致

 

 

 

 

 

[root@centos7 linux-5.14]# make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j128 
  CALL    scripts/atomic/check-atomics.sh
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CC      drivers/amba/bus.o
drivers/amba/bus.c:343:5: error: redefinition of 'amba_driver_register'
  343 | int amba_driver_register(struct amba_driver *drv)
      |     ^~~~~~~~~~~~~~~~~~~~
In file included from drivers/amba/bus.c:16:
./include/linux/amba/bus.h:112:19: note: previous definition of 'amba_driver_register' with type 'int(struct amba_driver *)'
  112 | static inline int amba_driver_register(struct amba_driver *drv)
      |                   ^~~~~~~~~~~~~~~~~~~~
drivers/amba/bus.c:361:6: error: redefinition of 'amba_driver_unregister'
  361 | void amba_driver_unregister(struct amba_driver *drv)
      |      ^~~~~~~~~~~~~~~~~~~~~~
In file included from drivers/amba/bus.c:16:
./include/linux/amba/bus.h:116:20: note: previous definition of 'amba_driver_unregister' with type 'void(struct amba_driver *)'
  116 | static inline void amba_driver_unregister(struct amba_driver *drv)
      |                    ^~~~~~~~~~~~~~~~~~~~~~
make[2]: *** [scripts/Makefile.build:271: drivers/amba/bus.o] Error 1
make[1]: *** [scripts/Makefile.build:514: drivers/amba] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1851: drivers] Error 2
[root@centos7 linux-5.14]# find ./ -name amba
./include/linux/amba
./drivers/amba
[root@centos7 linux-5.14]# vim 

 

 

 

更改 vim include/linux/amba/bus.h +116

 

 

[root@centos7 linux-5.14]# make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j128 
  CALL    scripts/atomic/check-atomics.sh
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CC      drivers/amba/bus.o
  CC      drivers/of/platform.o
  AR      drivers/of/built-in.a
  AR      drivers/amba/built-in.a
  AR      drivers/built-in.a
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  AR      init/built-in.a
  LD      vmlinux.o
  MODPOST vmlinux.symvers
  MODINFO modules.builtin.modinfo
  GEN     modules.builtin
  LD      .tmp_vmlinux.kallsyms1
  KSYMS   .tmp_vmlinux.kallsyms1.S
  AS      .tmp_vmlinux.kallsyms1.S
  LD      .tmp_vmlinux.kallsyms2
  KSYMS   .tmp_vmlinux.kallsyms2.S
  AS      .tmp_vmlinux.kallsyms2.S
  LD      vmlinux
  SYSMAP  System.map
  MODPOST modules-only.symvers
  OBJCOPY arch/riscv/boot/Image
  GEN     Module.symvers
  GZIP    arch/riscv/boot/Image.gz
  Kernel: arch/riscv/boot/Image.gz is ready

 

[root@centos7 linux-5.14]# cat System.map | grep amba_driver_
ffffffff804f0d12 T amba_driver_register
ffffffff804f0d38 T amba_driver_unregister
ffffffff80f77568 r __ksymtab_amba_driver_register
ffffffff80f77580 r __ksymtab_amba_driver_unregister
ffffffff80faf548 r __kstrtabns_amba_driver_register
ffffffff80faf548 r __kstrtabns_amba_driver_unregister
ffffffff80fb98fd r __kstrtab_amba_driver_register
ffffffff80fb9912 r __kstrtab_amba_driver_unregister
[root@centos7 linux-5.14]# 

 

 

[root@centos7 linux-5.14]# cat System.map  | grep sp805_
ffffffff804ba33e t sp805_wdt_remove
ffffffff804fa280 t sp805_wdt_probe
ffffffff8061c276 t sp805_wdt_driver_init
ffffffff8062aeb6 t sp805_wdt_driver_exit
ffffffff8080f600 d __initcall__kmod_sp805_wdt__324_359_sp805_wdt_driver_init6
ffffffff80e8f4c0 d sp805_wdt_ids
ffffffff80e8f4e0 d sp805_wdt_dev_pm_ops
ffffffff812b1280 d sp805_wdt_driver

 

login[98]: root login on 'console'
#
# ls /sys/bus/amba/
devices drivers_autoprobe uevent
drivers drivers_probe
#
# ls /sys/bus/amba/devices/
#
# ls /sys/bus/amba/devices/
#
# ls /sys/bus/amba/devices/drivers
ls: /sys/bus/amba/devices/drivers: No such file or directory
#
# ls /sys/bus/amba/
devices drivers_autoprobe uevent
drivers drivers_probe
#
# ls /sys/bus/amba/drivers
sp805-wdt
#
# ls /sys/bus/amba/drivers/sp805-wdt/
bind uevent unbind
#
# ls /sys/bus/amba/devices/
#
# ls /dev/watchdog
ls: /dev/watchdog: No such file or directory
#
#

 

amba_device_create

 customize_machine

  ->of_platform_populate

    ->of_platform_bus_create

      ->of_amba_device_create

        ->of_amba_device_create
-> ……
->
call_driver_probe
-->amba_probe -->pcdrv->probe(pcdev, id) -->sp805_wdt_probe

 sp805-wdt: probe of 20030000.watchdog failed with error -2

static int call_driver_probe(struct device *dev, struct device_driver *drv)
{
        int ret = 0;

        if (dev->bus->probe)
                ret = dev->bus->probe(dev);
        else if (drv->probe)
                ret = drv->probe(dev);

        switch (ret) {
        case 0:
                break;
        case -EPROBE_DEFER:
                /* Driver requested deferred probing */
                dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
                break;
        case -ENODEV:
        case -ENXIO:
                pr_debug("%s: probe of %s rejects match %d\n",
                         drv->name, dev_name(dev), ret);
                break;
        default:
                /* driver matched but the probe failed */
                pr_warn("%s: probe of %s failed with error %d\n",
                        drv->name, dev_name(dev), ret);
                break;
        }

        return ret;
}

 

 amba_probe(struct device *dev) -->amba_get_enable_pclk-->clk_get 

调用clk_get失败了

drivers/clk/clkdev.c

struct clk *clk_get(struct device *dev, const char *con_id)
{
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct clk_hw *hw;

        if (dev && dev->of_node) {
                hw = of_clk_get_hw(dev->of_node, 0, con_id);
                if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER)
                        return clk_hw_create_clk(dev, hw, dev_id, con_id);
        }

        return __clk_get_sys(dev, dev_id, con_id);
}

 

 struct device_node *of_node; /* associated device tree node */

 

[    0.933175] OF: amba: of_address_to_resource() failed (-22) for /soc/timer@0

 

static struct amba_device *of_amba_device_create(struct device_node *node,
                                                 const char *bus_id,
                                                 void *platform_data,
                                                 struct device *parent)
{
        struct amba_device *dev;
        const void *prop;
        int i, ret;

        pr_err("Creating amba device %pOF\n", node);
        //pr_debug("Creating amba device %pOF\n", node);

        if (!of_device_is_available(node) ||
            of_node_test_and_set_flag(node, OF_POPULATED))
                return NULL;

        dev = amba_device_alloc(NULL, 0, 0);
        if (!dev)
                goto err_clear_flag;

        /* AMBA devices only support a single DMA mask */
        dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        dev->dev.dma_mask = &dev->dev.coherent_dma_mask;

        /* setup generic device info */
        dev->dev.of_node = of_node_get(node);
        dev->dev.fwnode = &node->fwnode;
        dev->dev.parent = parent ? : &platform_bus;
        dev->dev.platform_data = platform_data;
        if (bus_id)
                dev_set_name(&dev->dev, "%s", bus_id);
        else
                of_device_make_bus_id(&dev->dev);

        /* Allow the HW Peripheral ID to be overridden */
        prop = of_get_property(node, "arm,primecell-periphid", NULL);
        if (prop)
                dev->periphid = of_read_ulong(prop, 1);

        /* Decode the IRQs and address ranges */
        for (i = 0; i < AMBA_NR_IRQS; i++)
                dev->irq[i] = irq_of_parse_and_map(node, i);

        ret = of_address_to_resource(node, 0, &dev->res);
        if (ret) {
                pr_err("amba: of_address_to_resource() failed (%d) for %pOF\n",
                       ret, node);
                goto err_free;
        }

        ret = amba_device_add(dev, &iomem_resource);
        if (ret) {
                pr_err("amba_device_add() failed (%d) for %pOF\n",
                       ret, node);
                goto err_free;
        }

        return dev;

err_free:
        amba_device_put(dev);
err_clear_flag:
        of_node_clear_flag(node, OF_POPULATED);
        return NULL;
}

 

 

 

static int __of_address_to_resource(struct device_node *dev, int index, int bar_no,
                struct resource *r)
{
        u64 taddr;
        const __be32    *addrp;
        u64             size;
        unsigned int    flags;
        const char      *name = NULL;

        addrp = __of_get_address(dev, index, bar_no, &size, &flags);
        pr_err("tracing %s __of_get_address  %d" ,dev->full_name, addrp == NULL);
        if (addrp == NULL)
                return -EINVAL;

        /* Get optional "reg-names" property to add a name to a resource */
        if (index >= 0)
                of_property_read_string_index(dev, "reg-names", index, &name);

        if (flags & IORESOURCE_MEM)
                taddr = of_translate_address(dev, addrp);
        else if (flags & IORESOURCE_IO)
                taddr = of_translate_ioport(dev, addrp, size);
        else
                return -EINVAL;

        if (taddr == OF_BAD_ADDR)
                return -EINVAL;
        memset(r, 0, sizeof(struct resource));

        if (of_mmio_is_nonposted(dev))
                flags |= IORESOURCE_MEM_NONPOSTED;

        r->start = taddr;
        r->end = taddr + size - 1;
        r->flags = flags;
        r->name = name ? name : dev->full_name;

        return 0;
}



/**
 * of_address_to_resource - Translate device tree address and return as resource
 * @dev:        Caller's Device Node
 * @index:      Index into the array
 * @r:          Pointer to resource array
 *
 * Note that if your address is a PIO address, the conversion will fail if
 * the physical address can't be internally converted to an IO token with
 * pci_address_to_pio(), that is because it's either called too early or it
 * can't be matched to any host bridge IO space
 */
int of_address_to_resource(struct device_node *dev, int index,
                           struct resource *r)
{
        return __of_address_to_resource(dev, index, -1, r);
}
0x4306_0000c
EXPORT_SYMBOL_GPL(of_address_to_resource);

/**
 * of_iomap - Maps the memory mapped IO for a given device_node
 * @np:         the device whose io range will be mapped
 * @index:      index of the io range
 *
 * Returns a pointer to the mapped memory
 */
void __iomem *of_iomap(struct device_node *np, int index)
{
        struct resource res;

        if (of_address_to_resource(np, index, &res))
                return NULL;

        if (res.flags & IORESOURCE_MEM_NONPOSTED)
                return ioremap_np(res.start, resource_size(&res));
        else
                return ioremap(res.start, resource_size(&res));
}
EXPORT_SYMBOL(of_iomap);

 

 

 

[    1.337101] OF:   __of_get_address parent == NULL ? 0 
[    1.337450] OF:   __of_get_address prop == NULL? 0
[    1.343550] OF:   __of_get_address psize 2, onesize 4
[    1.349286] OF:     __of_get_address addrp == NULL ?  1

跟踪_of_get_address发现psize 小于onesize

 

const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no,
                               u64 *size, unsigned int *flags)
{
        const __be32 *prop;
        unsigned int psize;
        struct device_node *parent;
        struct of_bus *bus;
        int onesize, i, na, ns;

        /* Get parent & match bus type */
        parent = of_get_parent(dev);
        pr_err("%s parent == NULL ? %d ",__func__, parent == NULL);
        if (parent == NULL)
                return NULL;
        bus = of_match_bus(parent);
        if (strcmp(bus->name, "pci") && (bar_no >= 0)) {
                of_node_put(parent);
                return NULL;
        }
        bus->count_cells(dev, &na, &ns);
        of_node_put(parent);
        if (!OF_CHECK_ADDR_COUNT(na))
                return NULL;

        /* Get "reg" or "assigned-addresses" property */

       pr_err(" %s prop == NULL? %d",__func__, prop == NULL);
        if (prop == NULL)
                return NULL;
        psize /= 4;

        onesize = na + ns;
        pr_err(" %s psize %x, onesize %x",__func__, psize, onesize);
        for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) {
                u32 val = be32_to_cpu(prop[0]);
                /* PCI bus matches on BAR number instead of index */
                if (((bar_no >= 0) && ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0))) ||
                    ((index >= 0) && (i == index))) {
                        if (size)
                                *size = of_read_number(prop + na, ns);
                        if (flags)
                                *flags = bus->get_flags(prop);
                        return prop;
                }
        }
        return NULL;
}

 

soc: soc {
#address-cells = <2>;
#size-cells = <2>;

  timer0: timer0 {
                        compatible = "arm,sp804", "arm,primecell";
                        reg = <  0x200A0000  0x1000>;
                        interrupt-parent = <&plic0>;
                        interrupts = <33>, <34>, <35>, <36>;
                        clocks = <&timclk1 &timclk2>;
                        clock-names = "timer1", "timer2";
                };

原来是timer0继承了

#address-cells = <2>;
#size-cells = <2>;

改成如下,问题解决

     timer0: timer0 {
                        compatible = "arm,sp804", "arm,primecell";
                        reg = < 0x0 0x200A0000 0x0  0x1000>;
                        interrupt-parent = <&plic0>;
                        interrupts = <33>, <34>, <35>, <36>;
                        clocks = <&timclk1 &timclk2>;
                        clock-names = "timer1", "timer2";
                };

 

ARM amba总线驱动

posted on 2021-11-01 15:23  tycoon3  阅读(274)  评论(0编辑  收藏  举报

导航