[RFC] Baikal-T1 SoC System Controller DT nodes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello folks,

I've been addressed with a several questions from Rob, Arnd, Andy and Stephen
in replies to he i2c, clock, ehb (errors handler block) and syscon patchsets sent
by me in the framework of the Baikal-T1 SoC support integration into the kernel
[1 - 4]. Seeing the questions have similar nature it would be better to settle the
issues all at once, provide fixes for all of them and proceed with the
rest of review.

In general the questions are related with syscon, clocks, i2c0 and ehb DT nodes
residence. Some of them concern the memory mapped registers alignment
(clock/i2c0), some of them are of whether the corresponding device drivers
belong to the soc-subsystem (ehb) or whether some device nodes should be
sub-nodes of the syscon or of anything else like root node. Anyway as I see it
the answers to all the questions are hidden in a way the Baikal-T1 System
Controller is structured. That's why I'll start from describing it first.
Then I'll provide the System Controller DT nodes structure currently implemented
for Baikal-T1 SoC and explain why we chose to develop it in favor of any other.
Finally I'll offer you an alternative structure, which we also had in mind,
but didn't implement it for reasons also given in the text below.

In accordance with Baikal-T1 SoC documentations there is a System Control
Module (we also call it System Controller), which contains two big subsystems:
Clocks Control Unit (CCU) and Boot Controller. But the System Controller
functionality isn't limited with just clocks control and boot procedure
execution. There are settings, which aren't directly connected with those
sub-blocks, but is still exposed through the System Controller registers space
just because, well, because either the system designers wanted them to be
exposed from there or they didn't find any better way to map them. We don't
know for sure. We just know the mapping as it is and can't do anything to
change it. So here is the System Controller structure implemented in the
Baikal-T1 SoC:

System Control Module
|
+--> Clock Control Unit + System-specific settings: 0x1F04D000 @ 4KB
|    |
|    +-> PLLs                   0x1F04D000 - 0x1F04D027
|    |
|    +-> System Devices Clocks: 0x1F04D028 - 0x1F04D02F (clock dividers)
|    |   (DDR clock gate + L2 WS/Data/Tag stall cycles configs)
|    +-> AXI-bus Clocks:        0x1F04D030 - 0x1F04D05F (clock dividers)
|    |
|    +-> System Devices Clocks: 0x1F04D060 - 0x1F04D09F (clock dividers)
|    |
|    +-> I2C0 Indirect Access:  0x1F04D100 - 0x1F04D10F (+ IRQ)
|    |   (Just three Command/Read/Write registers to access the DW APB I2C controller registers space)
|    +-> AXI-bus EHB Error Addr:0x1F04D110 - 0x1F04D117 (+ IRQ)
|    |
|    +-> CPU Debug register:    0x1F04D118 - 0x1F04D11B
|    |   (provide the CPU reset flag for 'syscon-reboot' driver)
|    +-> PCIe control block:    0x1F04D140 - 0x1F04D14F
|    |   (PCIe internal Clocks, Reset, PMU, LTSSM and custom settings)
|    +-> System Devices Clocks: 0x1F04D150 - 0x1F04D153 (clock divider)
|    |   (Just watchdog clock divider)
|    +-> Reset safe register:   0x1F04D154 - 0x1F04D157
|        (register preserved during a soft/watchdog resets for
|         'syscon-reboot-mode' driver)
|
+--> Boot Controller: 0x1F040000 @ 4KB, 0x1BFC0000 @ 4KB, 0x1C000000 @ 16MB,
|    |                0x1FC00000 @ 4MB
|    |
|    +-> Boot Controller settings:               0x1F040000 - 0x1F0400FF
|    |
|    +-> Synopsis DesignWare APB SSI controller: 0x1F040100 - 0x1F040FFF
|    |   (with very limited resources though: nor IRQ, no DMA, just 8 bytes FIFO)
|    +-> Physically mapped Internal ROM:         0x1BFC0000 - 0x1BFCFFFF
|    |
|    +-> Physically mapped SPI-flash ROM:        0x1C000000 - 0x1CFFFFFF
|    |   (This region access is multiplexed with DW APB SSI controller registers)
|    +-> Physically mapped Boot ROM:             0x1FC00000 - 0x1FFFFFFF
|        (mirror of either Internal or SPI-flash ROMs depending on the boot
|         mode)

There is also an APB EHB (APB bus Errors Handler Block), but according to the
Baikal-T1 documentation, it isn't part of the System Control Module (though as
for me it was a tech-writers mistake to represent it as a separate block).

+--> APB bus errors handler: 0x1F059000 @ 4KB, 0x1D000000 @ 32.25MB
     |
     +-> APB bus EHB registers: 0x1F059000 - 0x1F059FFF (+ IRQ)
     |   (Error address, type and timeout settings)
     +-> Unmapped space for errors injection: 0x1D000000 - 0x1F03FFFF


It's a mystery to me why the SoC designers couldn't create a different registers
space for CCU (PLLs and Clock dividers) and for the custom system settings. But
we have to deal with what we currently have, since it can't be changed. So
as you can see the Boot Controller and Clock Control Unit (CCU) registers space
are separated from each other, and CCU registers (PLLs, AXI-bus and System
Devices Clock dividers) can be unpinned from the custom system settings. In
addition the Boot Controller and CCU sub-blocks registers don't have
intersecting parts, which makes the syscon interface using regmaps with
spin-lock synch-primitive redundant for simultaneous accesses of the registers
of different groups. So I've decided to just redistribute the registers
resources between the corresponding DT nodes not necessarily being sub-nodes of
the System Controller node (I suppose most of your questions were raised due to
this decision). This made the nodes being unrelated to each other, but the nodes
MMIO resources turned to be size-unaligned. Here is a DT nodes structure we've
currently implemented in the framework of Baikal-T1 SoC support in the kernel.

/* System Controller DT Nodes I */
root {
    reboot {
        compatible = "syscon-reboot";
        regmap = <&cpu_ctl>;
    };

    reboot-mode {
        compatible = "syscon-reboot-mode";
        regmap = <&wdt_rcr>;
    };

    apb {
        compatible = "simple-bus";

        ccu_pll {
            compatible = "be,bt1-ccu-pll"; /* PLLs */
        };
        ccu_axi {
            compatible = "be,bt1-ccu-axi"; /* AXI-bus Clock */
            clocks = <&ccu_pll X>, <&ccu_pll Y>, ...;
        };
        ccu_sys {
            compatible = "be,bt1-ccu-sys"; /* System Devices Clock */
            clocks = <&ccu_pll X>, <&ccu_pll Y>, ...;
        };

        syscon {
            compatible = "simple-mfd";

            l2_ctl {
                compatible = "be,bt1-l2-ctl", "syscon";
            };

            ddr_ctl {
                compatible = "be,bt1-ddr-ctl", "syscon";
            };

            axi_ehb {
                compatible = "be,bt1-axi-ehb";
            };

            cpu_ctl {
                compatible = "be,bt1-cpu-ctl", "syscon";
            };

            pcie_ctl {
                compatible = "be,bt1-pcie-ctl", "syscon";
            };

            wdt_rcr {
                compatible = "be,bt1-wdt-rcr", "syscon";
            };
        };

        i2c0 {
            compatible = "be,bt1-i2c"; /* DW APB i2c with indirect registers access */
        };

        boot {
            compatible = "be,bt1-boot-ctl";

            int_rom {
                compatible = "be,bt1-int-rom", "mtd-rom";
            };

            spi_rom {
                compatible = "be,bt1-ssi-rom", "mtd-rom";
            };

            spi0 {
                compatible = "be,bt1-boot-ssi";
            };

            boot_rom {
                compatible = "be,bt1-boot-rom", "mtd-rom";
            };
        };

        apb_ehb {
            compatible = "be,bt1-apb-ehb";
        };
    };
};

The corresponding dts-file hasn't been submitted so far. So if you don't like
the structure we've chosen to define the System Controller parts, please justify
why it isn't right and if it's possible point me out at some place of the kernel
documentation so to refer to in future developments. We don't refuse to change it,
I'd just like to know what's wrong with it and how to bypass the same problem in
future.

On the other hand as an alternative, which you'd possibly like much more, if we
got used to the fact that syscon-interface converts the registers resource to
the spin-lock secured regmap object and in order to retain the system controller
structure, the next System Controller DT nodes tree could be implemented:

/* System Controller DT Nodes II */
root {
    axi {
        compatible = "be,bt1-axi", "simple-bus";
        syscon = <&syscon>;
        interrupts = <...>;
    };

    apb {
        compatible = "be,bt1-apb", "simple-bus";
        reg = <X>, <Y>;
        interrupts = <...>;

        syscon {
            compatible = "be,bt1-sys-con", "syscon", "simple-mfd";

            ccu_pll {
                compatible = "be,bt1-ccu-pll";
            };

            ccu_axi {
                compatible = "be,bt1-ccu-axi";
            };

            ccu_sys {
                compatible = "be,bt1-ccu-sys";
            };

            l2_ctl {
                compatible = "be,bt1-l2-ctl";
            };

            i2c0 {
                compatible = "be,bt1-sys-i2c";
            };

            reboot {
                compatible = "syscon-reboot";
            };

            reboot-mode {
                compatible = "syscon-reboot-mode";
            };

            boot {
                compatible = "be,bt1-boot-ctl";

                int_rom {
                    compatible = "be,bt1-int-rom", "mtd-rom";
                };

                spi_rom {
                    compatible = "be,bt1-ssi-rom", "mtd-rom";
                };

                spi0 {
                    compatible = "be,bt1-boot-ssi";
                };

                boot_rom {
                    compatible = "be,bt1-boot-rom", "mtd-rom";
                };
            };
        };
    };
};

I suppose you'd like it better than "DT Nodes I", since in accordance with
Arnd Bergmann suggestion [1] the APB/AXI EHB would be moved to the drivers/bus
subsystem. In the framework of the "be,bt1-sys-con" MFD driver I would have
to implement an extra regmap to provide the indirectly accessible i2c0
registers, which would satisfy the Andy Shevchenko comment [2] regarding our
DW APB i2c patchset. I wouldn't need to have the "syscon-reboot-mode"
patchset in order to be able to declare the reboot-mode node in any place of
the DTS tree, which Rob Herring already nacked [3], but didn't explain why.
Finally I wouldn't have the unaligned registers space defined for Clock Control
Unit nodes, but would use the syscon-regmap to access them from the system
clock drivers. This would fix the issue raised by Stephen Boyd [4] in the
framework of the Baikal-T1 CCU drivers patchset.

So if you like the "DT Nodes II" structure better than the version I or have
any idea of how to improve it could you tell us in reply to this email while
it's still possible to change the System Controller nodes structure at this
point since we are at v1-v2 stages in each patchset and non of the drivers
have been fully accepted so far.

[1] soc: Add Baikal-T1 SoC APB/AXI EHB and L2-cache drivers
    https://lkml.org/lkml/2020/3/6/669
[2] i2c: designware: Add Baikal-T1 SoC DW I2C specifics support 
    https://lkml.org/lkml/2020/3/6/542
[3] dt-bindings: power: reset: Add regmap support to the SYSCON reboot-mode bindings
    https://lkml.org/lkml/2020/3/12/1010
[4] dt-bindings: clk: Add Baikal-T1 System Devices CCU bindings
    https://lkml.org/lkml/2020/3/9/1249

Regards,
-Sergey



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux