Message ID | 20191209195749.868-8-tiny.windzz@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [01/17] clk: sunxi: sunxi-ng: convert to devm_platform_ioremap_resource | expand |
On 09.12.2019 21:58, Yangtao Li wrote: > Use devm_platform_ioremap_resource() to simplify code. > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com> > --- > drivers/clk/imx/clk-imx8qxp-lpcg.c | 6 +----- > 1 file changed, 1 insertion(+), 5 deletions(-) > > diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c > index c0aff7ca6374..10ae712447c6 100644 > --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c > +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c > @@ -164,7 +164,6 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) > struct clk_hw_onecell_data *clk_data; > const struct imx8qxp_ss_lpcg *ss_lpcg; > const struct imx8qxp_lpcg_data *lpcg; > - struct resource *res; > struct clk_hw **clks; > void __iomem *base; > int i; > @@ -173,10 +172,7 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) > if (!ss_lpcg) > return -ENODEV; > > - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > - if (!res) > - return -EINVAL; > - base = devm_ioremap(dev, res->start, resource_size(res)); > + base = devm_platform_ioremap_resource(pdev, 0); > if (!base) > return -ENOMEM; This breaks imx8qxp-mek boot by causing most peripherals (like uart) to fail to probe. The old and new paths are not equivalent: devm_platform_ioremap_resource calls devm_ioremap_resource which differs from devm_ioremap by also calling devm_request_mem_region. This prevents other mappings in the area and imx8qxp-lpcg nodes map whole hardware "subsystems" and overlap most peripherals. For example: adma_lpcg: clock-controller@59000000 { compatible = "fsl,imx8qxp-lpcg-adma"; reg = <0x59000000 0x2000000>; #clock-cells = <1>; }; adma_lpuart0: serial@5a060000 { reg = <0x5a060000 0x1000>; ... }; I don't know if this issue affects any other platforms (imx8 lpcg bindings are unusual) but if you found this with an automated tool perhaps it should be adjusted? By my count it's the 4th time this incorrect cleanup was posted. Previously: https://lkml.org/lkml/2019/12/4/487 -- Regards, Leonard
On Mon, Dec 09, 2019 at 08:44:39PM +0000, Leonard Crestez wrote: > On 09.12.2019 21:58, Yangtao Li wrote: > > Use devm_platform_ioremap_resource() to simplify code. > > > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com> > > --- > > drivers/clk/imx/clk-imx8qxp-lpcg.c | 6 +----- > > 1 file changed, 1 insertion(+), 5 deletions(-) > > > > diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c > > index c0aff7ca6374..10ae712447c6 100644 > > --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c > > +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c > > @@ -164,7 +164,6 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) > > struct clk_hw_onecell_data *clk_data; > > const struct imx8qxp_ss_lpcg *ss_lpcg; > > const struct imx8qxp_lpcg_data *lpcg; > > - struct resource *res; > > struct clk_hw **clks; > > void __iomem *base; > > int i; > > @@ -173,10 +172,7 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) > > if (!ss_lpcg) > > return -ENODEV; > > > > - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > - if (!res) > > - return -EINVAL; > > - base = devm_ioremap(dev, res->start, resource_size(res)); > > + base = devm_platform_ioremap_resource(pdev, 0); > > if (!base) > > return -ENOMEM; > > This breaks imx8qxp-mek boot by causing most peripherals (like uart) to > fail to probe. > > The old and new paths are not equivalent: devm_platform_ioremap_resource > calls devm_ioremap_resource which differs from devm_ioremap by also > calling devm_request_mem_region. > > This prevents other mappings in the area and imx8qxp-lpcg nodes map > whole hardware "subsystems" and overlap most peripherals. For example: > > adma_lpcg: clock-controller@59000000 { > compatible = "fsl,imx8qxp-lpcg-adma"; > reg = <0x59000000 0x2000000>; > #clock-cells = <1>; > }; > > adma_lpuart0: serial@5a060000 { > reg = <0x5a060000 0x1000>; > ... > }; The whole point of doing a request_mem_region() is to avoid having multiple drivers trample on each others' mappings. What you do above doesn't look right. Why does that clock controller need access to 32 MiB of I/O memory space? That said, there are legitimate reasons for sharing mappings across drivers, so I agree that automated conversions like this should be done very carefully. The difficulty is that there are cases where drivers simply omitted that request_mem_region() by mistake and where the conversion can be correct (and in fact an improvement), but we can't make the assumption blindly. Thierry > I don't know if this issue affects any other platforms (imx8 lpcg > bindings are unusual) but if you found this with an automated tool > perhaps it should be adjusted? > > By my count it's the 4th time this incorrect cleanup was posted. > > Previously: https://lkml.org/lkml/2019/12/4/487 > > -- > Regards, > Leonard
Hi Thierry, Am 10.12.19 um 14:21 schrieb Thierry Reding: > On Mon, Dec 09, 2019 at 08:44:39PM +0000, Leonard Crestez wrote: >> On 09.12.2019 21:58, Yangtao Li wrote: >>> Use devm_platform_ioremap_resource() to simplify code. >>> >>> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com> >>> --- >>> drivers/clk/imx/clk-imx8qxp-lpcg.c | 6 +----- >>> 1 file changed, 1 insertion(+), 5 deletions(-) >>> >>> diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c >>> index c0aff7ca6374..10ae712447c6 100644 >>> --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c >>> +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c >>> @@ -164,7 +164,6 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) >>> struct clk_hw_onecell_data *clk_data; >>> const struct imx8qxp_ss_lpcg *ss_lpcg; >>> const struct imx8qxp_lpcg_data *lpcg; >>> - struct resource *res; >>> struct clk_hw **clks; >>> void __iomem *base; >>> int i; >>> @@ -173,10 +172,7 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) >>> if (!ss_lpcg) >>> return -ENODEV; >>> >>> - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >>> - if (!res) >>> - return -EINVAL; >>> - base = devm_ioremap(dev, res->start, resource_size(res)); >>> + base = devm_platform_ioremap_resource(pdev, 0); >>> if (!base) >>> return -ENOMEM; >> This breaks imx8qxp-mek boot by causing most peripherals (like uart) to >> fail to probe. >> >> The old and new paths are not equivalent: devm_platform_ioremap_resource >> calls devm_ioremap_resource which differs from devm_ioremap by also >> calling devm_request_mem_region. >> >> This prevents other mappings in the area and imx8qxp-lpcg nodes map >> whole hardware "subsystems" and overlap most peripherals. For example: >> >> adma_lpcg: clock-controller@59000000 { >> compatible = "fsl,imx8qxp-lpcg-adma"; >> reg = <0x59000000 0x2000000>; >> #clock-cells = <1>; >> }; >> >> adma_lpuart0: serial@5a060000 { >> reg = <0x5a060000 0x1000>; >> ... >> }; > The whole point of doing a request_mem_region() is to avoid having > multiple drivers trample on each others' mappings. What you do above > doesn't look right. Why does that clock controller need access to 32 > MiB of I/O memory space? I have similar cases with Realtek where registers are simply not grouped into convenient blocks but spread across large memory regions. Also, Fabien and I had a review discussion about the very same topic of suggesting these functions which implicitly do a request_mem_region(), so this might need some better documentation for raising awareness? For some cases I posted patches to convert those to syscon / simple-mfd, but clk in particular is a difficult one: clks still express their parents by names rather than pointers, and having clks spread across drivers has implications on needing to expose non-leaf clocks in the DT bindings, as well as needing to mess with __clk_get_name() for actually getting the name to use as parent when obtaining the clk from DT. Imagine a lonely clk gate register and the PLLs or other gates they are supplied from residing far away. It's really ugly either way... That said, the Actions Semi patch 16/17 that I'm CC'ed for looks okay. Regards, Andreas > > That said, there are legitimate reasons for sharing mappings across > drivers, so I agree that automated conversions like this should be done > very carefully. The difficulty is that there are cases where drivers > simply omitted that request_mem_region() by mistake and where the > conversion can be correct (and in fact an improvement), but we can't > make the assumption blindly. > > Thierry > >> I don't know if this issue affects any other platforms (imx8 lpcg >> bindings are unusual) but if you found this with an automated tool >> perhaps it should be adjusted? >> >> By my count it's the 4th time this incorrect cleanup was posted. >> >> Previously: https://lkml.org/lkml/2019/12/4/487 >> >> -- >> Regards, >> Leonard
On Tue, Dec 10, 2019 at 03:57:50PM +0100, Andreas Färber wrote: > For some cases I posted patches to convert those to syscon / simple-mfd, > but clk in particular is a difficult one: clks still express their > parents by names rather than pointers, It's no longer the case since 5.2. clk_init_data can now take either the parent name, a clk_hw, or one of the names in clock-names. maxime
On Tue, Dec 10, 2019 at 4:44 AM Leonard Crestez <leonard.crestez@nxp.com> wrote: > > On 09.12.2019 21:58, Yangtao Li wrote: > > Use devm_platform_ioremap_resource() to simplify code. > > > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com> > > --- > > drivers/clk/imx/clk-imx8qxp-lpcg.c | 6 +----- > > 1 file changed, 1 insertion(+), 5 deletions(-) > > > > diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c > > index c0aff7ca6374..10ae712447c6 100644 > > --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c > > +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c > > @@ -164,7 +164,6 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) > > struct clk_hw_onecell_data *clk_data; > > const struct imx8qxp_ss_lpcg *ss_lpcg; > > const struct imx8qxp_lpcg_data *lpcg; > > - struct resource *res; > > struct clk_hw **clks; > > void __iomem *base; > > int i; > > @@ -173,10 +172,7 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) > > if (!ss_lpcg) > > return -ENODEV; > > > > - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > - if (!res) > > - return -EINVAL; > > - base = devm_ioremap(dev, res->start, resource_size(res)); > > + base = devm_platform_ioremap_resource(pdev, 0); > > if (!base) > > return -ENOMEM; > > This breaks imx8qxp-mek boot by causing most peripherals (like uart) to > fail to probe. > > The old and new paths are not equivalent: devm_platform_ioremap_resource > calls devm_ioremap_resource which differs from devm_ioremap by also > calling devm_request_mem_region. > > This prevents other mappings in the area and imx8qxp-lpcg nodes map > whole hardware "subsystems" and overlap most peripherals. For example: > > adma_lpcg: clock-controller@59000000 { > compatible = "fsl,imx8qxp-lpcg-adma"; > reg = <0x59000000 0x2000000>; > #clock-cells = <1>; > }; It's a bit surprising that the clock driver does such a large mapping. So, it is best to check the dts reg configuration of the driver. Yours, Yangtao > > adma_lpuart0: serial@5a060000 { > reg = <0x5a060000 0x1000>; > ... > }; > > I don't know if this issue affects any other platforms (imx8 lpcg > bindings are unusual) but if you found this with an automated tool > perhaps it should be adjusted? > > By my count it's the 4th time this incorrect cleanup was posted. > > Previously: https://lkml.org/lkml/2019/12/4/487 > > -- > Regards, > Leonard
+ Dong On Tue, 10 Dec 2019, Thierry Reding wrote: > On Mon, Dec 09, 2019 at 08:44:39PM +0000, Leonard Crestez wrote: > > > This breaks imx8qxp-mek boot by causing most peripherals (like uart) to > > fail to probe. > > > > The old and new paths are not equivalent: devm_platform_ioremap_resource > > calls devm_ioremap_resource which differs from devm_ioremap by also > > calling devm_request_mem_region. > > > > This prevents other mappings in the area and imx8qxp-lpcg nodes map > > whole hardware "subsystems" and overlap most peripherals. For example: > > > > adma_lpcg: clock-controller@59000000 { > > compatible = "fsl,imx8qxp-lpcg-adma"; > > reg = <0x59000000 0x2000000>; > > #clock-cells = <1>; > > }; > > > > adma_lpuart0: serial@5a060000 { > > reg = <0x5a060000 0x1000>; > > ... > > }; > > The whole point of doing a request_mem_region() is to avoid having > multiple drivers trample on each others' mappings. What you do above > doesn't look right. Why does that clock controller need access to 32 > MiB of I/O memory space? Thierry's right; your DT data looks broken. Unfortunately the IMX8M TRM requires some sort of signup to download, so I can't easily read it, but based on files like this: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clk/imx/clk-imx8qxp-lpcg.h it looks like what should be in the DT instead is either a large set of smaller register ranges, or a set of separate DT nodes/drivers: one per peripheral LPCG instance. That should avoid the overlapping memory range issue. - Paul
On Tue, 10 Dec 2019, Andreas Färber wrote: > I have similar cases with Realtek where registers are simply not grouped > into convenient blocks but spread across large memory regions. At the hardware level, registers are grouped into IP blocks, to simply both design integration and address decoding. Not knowing which Realtek device you're referring to, most likely it's the same situation as with the IMX8M TRM, where the DT data doesn't match the underlying reality of the hardware. In those cases the best approach is usually to just fix the DT data. - Paul
On 11.12.2019 19:51, Paul Walmsley wrote: > On Tue, 10 Dec 2019, Thierry Reding wrote: >> On Mon, Dec 09, 2019 at 08:44:39PM +0000, Leonard Crestez wrote: >> >>> This breaks imx8qxp-mek boot by causing most peripherals (like uart) to >>> fail to probe. >>> >>> The old and new paths are not equivalent: devm_platform_ioremap_resource >>> calls devm_ioremap_resource which differs from devm_ioremap by also >>> calling devm_request_mem_region. >>> >>> This prevents other mappings in the area and imx8qxp-lpcg nodes map >>> whole hardware "subsystems" and overlap most peripherals. For example: >>> >>> adma_lpcg: clock-controller@59000000 { >>> compatible = "fsl,imx8qxp-lpcg-adma"; >>> reg = <0x59000000 0x2000000>; >>> #clock-cells = <1>; >>> }; >>> >>> adma_lpuart0: serial@5a060000 { >>> reg = <0x5a060000 0x1000>; >>> ... >>> }; >> >> The whole point of doing a request_mem_region() is to avoid having >> multiple drivers trample on each others' mappings. What you do above >> doesn't look right. Why does that clock controller need access to 32 >> MiB of I/O memory space? > > Thierry's right; your DT data looks broken. Unfortunately the IMX8M TRM > requires some sort of signup to download, so I can't easily read it, but > based on files like this: > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux.git%2Ftree%2Fdrivers%2Fclk%2Fimx%2Fclk-imx8qxp-lpcg.h&data=02%7C01%7Cleonard.crestez%40nxp.com%7Cf0e68024888e4aed777e08d77e62c5df%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C637116835018036168&sdata=z70QUYwknXfvc4zhyOrT7dcLPq5eryv4U7HoGMzI4ZE%3D&reserved=0 > > it looks like what should be in the DT instead is either a large set of > smaller register ranges, or a set of separate DT nodes/drivers: one per > peripheral LPCG instance. That should avoid the overlapping memory range > issue. Yes, current imx8 clock DT bindings are definitely odd. I only objected to the cleanup because it breaks boot. This series converts imx8 LPCG to use separate DT nodes for each peripheral LPCG instance and makes other improvements, it's just been stuck in review: https://patchwork.kernel.org/cover/11248249/ Having a large number of clock-providing DT nodes is also odd but it closely aligns with SOC hardware architecture. The clock gating bits were deliberately split into many 64k areas so that access can be controlled for each peripheral using very coarse-grained access control methods. For example hypervisors can control guest access on page boundaries but not to individual bits in a byte. This design makes it easy to securely grant control for a peripheral and all of its clock bits to an M4 core or virtualization guest without additional layers of software indirection. -- Regards, Leonard
Am 11.12.19 um 18:57 schrieb Paul Walmsley: > On Tue, 10 Dec 2019, Andreas Färber wrote: > >> I have similar cases with Realtek where registers are simply not grouped >> into convenient blocks but spread across large memory regions. > > At the hardware level, registers are grouped into IP blocks, to simply > both design integration and address decoding. Reality shows, not all vendors/chips always care about simplification. Blocks do have names, but they don't always group registers of the same kind, as Linux expects it - be it for historical backwards compatibility reasons or because Linux/Android wasn't their main use case in the past. Firmware developers won't care where their registers are located. > Not knowing which Realtek > device you're referring to, Arm based RTD1195 and RTD1295/RTD1395/RTD1619/RTD1319 SoC families, which I maintain. > most likely it's the same situation as with > the IMX8M TRM, where the DT data doesn't match the underlying reality of > the hardware. In those cases the best approach is usually to just fix the > DT data. No, you're not reading me. My DT data matches the hardware as far as I know it. You can be really happy that you can login to get NXP manuals; for other vendors, manuals simply don't exist and we have to deduce DT from register names/offsets ourselves. Reality is messy! Just please accept that hardware does not always allow for unique contiguous memory reservations, and we therefore cannot force these types of reservations onto everybody. There might be an opportunity for a new helper with even longer name that does the expected combination of actions. But is it worth it? People seem to have stopped giving motivations for their patches in commit message or cover letter, so it remains entirely unclear how else one might satisfy the submitter's goals while keeping your code working. (Also referring to unjustified style-only cleanups popping up lately.) "to simplify code" is not much to go on, it sounds like a style cleanup without any practical error avoidance benefits nor an API to be dropped. Note that I did not receive any cover letter accompanying this patch, but was CC'ed on plenty of other patches like this one that I'm not maintainer of, leading me to assume that none was sent. Alternatively one could do the reservations decoupled from DT inside the driver, but again not using this suggested helper. From what I read on other such patches, apparently some Coccinelle build target emits warnings when it matches some pattern for potential refactoring, which people then set out to resolve, without understanding the code they touch or being able to actually test it. That's probably the root cause that someone would need to tackle - whitelisting fully-intentional usages of certain APIs to protect against unwarranted refactorings, or otherwise making sure that people don't get inspired to in their best intentions break other people's code. I assume kbuild bot doesn't send out such cocci warnings to us maintainers for good reasons. A completely fragmented DT with either dozens of reg entries for single registers or distinct compatible strings for individual registers, to give them their own DT nodes, is not really handy, compared to one or two larger clk nodes that handle reg offsets under the hood, without impacting public DT bindings (e.g., bumping reg's maxItems, clk header). If you care about modeling this, you're welcome to participate in patch review @ DTML/LAKML/LRSML. So far there's largely been a yawning silence in response to my patches introducing syscon and simple-mfd as cleanups, before things get worse as we add to the DT. Following an unreviewed clk RFC of mine two years back, there's now been a clk patchset from Realtek that got a load of review comments from me, waiting for a v2. If you don't care, then please don't lecture us about how you think other people's hardware should ideally be like. That's not helpful. Regards, Andreas
On Wed, 11 Dec 2019, Andreas Färber wrote: > Blocks do have names, but they don't always group registers of the same > kind, as Linux expects it Linux does not expect that all of the registers in the same IP block are of the same kind. That's part of the reason why Linux frameworks exist. To consider clocks as the present example, you're welcome to register local IP block clock control registers in the local IP block driver via the clock framework. There's no need for a separate clock driver with an overlapping address range, or anything like that. This is nothing new with Realtek. IP blocks that contain many different kinds of registers have had Linux driver support without requiring overlapping register address ranges long before Realtek ARM SoCs appeared. > Just please accept that hardware does not always allow for unique > contiguous memory reservations Hardware designs do in fact mandate unique contiguous memory reservations, otherwise address decoding would be indeterministic. What they don't mandate is that all of the registers in that region be all of one kind. It's certainly possible to have an SoC with one giant IP block with all registers mixed together. Even in that case, it is still incorrect to have multiple DT entries with overlapping register address ranges. It sounds like you're thinking of the difficulties of figuring out how to structure the software driver support for those mixed IP block as a Linux driver: where it would fit in the tree, what frameworks it would need to register with, and who would maintain it. Those issues certainly merit careful thought and consideration. They aren't related to multiple overlapping address ranges. - Paul
Am 11.12.19 um 23:49 schrieb Paul Walmsley: > On Wed, 11 Dec 2019, Andreas Färber wrote: > >> Blocks do have names, but they don't always group registers of the same >> kind, as Linux expects it > > Linux does not expect that all of the registers in the same IP block are > of the same kind. That's part of the reason why Linux frameworks exist. > To consider clocks as the present example, you're welcome to register > local IP block clock control registers in the local IP block driver via > the clock framework. There's no need for a separate clock driver with an > overlapping address range, or anything like that. If I throw random code into drivers/mfd/ it will not get proper review. We rely on clk drivers going into drivers/clk/, even if I could theoretically register clks also from other parts of the code base - which will then require complex Kconfig dependencies or #ifdef'ery, not to mention the nightmares of collecting Acks and figuring out through whose tree which patches go. > > This is nothing new with Realtek. As this NXP patch proves. :) > IP blocks that contain many different > kinds of registers have had Linux driver support without requiring > overlapping register address ranges long before Realtek ARM SoCs > appeared. Hey, you're the one that's trying to pin this on Realtek, not me! STM32 RCC is another example I know, also Allwinner, etc. My point was precisely that this is - for good or bad - a rather common scenario that we need to deal with. >> Just please accept that hardware does not always allow for unique >> contiguous memory reservations > > Hardware designs do in fact mandate unique contiguous memory reservations, > otherwise address decoding would be indeterministic. Are you not understanding what I'm saying or intentionally gas-lighting? A contiguous memory _reservation_ is a range of memory like <0xdead0000 0x100> that the kernel (software!) blocks other drivers (software!) from reserving. This has _nothing_ to do with hardware address line decoding. It's still about devm_platform_ioremap_resource() and related APIs. Do a `cat /proc/iomem` to see, e.g., "98007800-9800781f : serial" reservation in successful case; as mentioned by Leonard, an unsuccessful reservation usually causes the driver to fail to probe and thus be unavailable. > What they don't > mandate is that all of the registers in that region be all of one kind. > It's certainly possible to have an SoC with one giant IP block with all > registers mixed together. Even in that case, it is still incorrect to > have multiple DT entries with overlapping register address ranges. Says who? Since when? Can we maybe agree that incorrect != invalid? > It sounds like you're thinking of the difficulties of figuring out how to > structure the software driver support for those mixed IP block as a Linux > driver: Yes, these are Linux kernel mailing lists and patches after all... I don't design hardware, that's why I said we need to live with the flawed reality of the actual hardware we get. > where it would fit in the tree, what frameworks it would need to > register with, and who would maintain it. Those issues certainly merit > careful thought and consideration. They aren't related to multiple > overlapping address ranges. Oh they are. Overlapping address ranges of DT nodes are a _result_ of unexpected hardware design involving blocks not clearly separated the same way as Linux subsystems (to distinguish from "frameworks") are. The DT should describe the hardware blocks as they were designed, but on the other hand, we need to describe it in a way that Linux drivers can actually bind against the relevant parts and that those drivers can operate efficiently. There is no ioremap-all-regs helper that I'm aware of, for instance, as that would result in __iomem base addresses to be stored per reg entry; compare that to just one for an overlapping range. Example: clk@f00 { reg = <0xf00 0x100>; } reset@f0f { reg = <0xf0c 0x4>; }; This should be a valid DT example today, as long as the clk driver doesn't mess with the reset register embedded within its range. In this case they can't both reserve their ranges as they would mutually cause each other to fail to probe, depending on probe order. As I wrote, turning this into clk@f00 { reg = <0xf00 0xc>, <0xf10 0xe0>; }; reset@f0f { reg = <0xf0c 0x4>; }; is helping no one and makes things much more complex, especially when the number of carve-outs grows or is not predetermined, as I noted about some of my cases. Thus I disagree with you about the overlapping ranges. DT needs to be designed forward-looking rather than just around the handful of registers we might read/write today, not just to relieve Rob from excessive reviews. My solution was to do syscon@f00 { reg = <0xf00 0x100>; ranges = ...; clk@0 { reg = <0x0 0x100>; }; reset@c { reg = <0xc 0x4>; }; }; https://patchwork.kernel.org/cover/11269453/ https://patchwork.kernel.org/cover/11269971/ (and more in my tree) which clearly models the blocks and shares a syscon for most children, other than pre-existing 8250 UART, I²C, etc. drivers using platform helpers such as the one discussed here. What we lose with syscon is reservations, i.e. /proc/iomem neither showing the full syscon nor the drivers using parts of it, unless we explicitly reserve the memory (syscon does the ioremap for us, so no need for this devm_platform_ioremap_resource helper there). Also please keep in mind that we actually want to get to the point where new systems are booting and usable. At least in the Arm world we do have hardware at plenty to boot Linux. Dying in DT-beauty then is counter-productive; we also need to come to timely compromises for not blocking other work. clk drivers don't need to be platform_drivers like here and thus can coexist easier with other drivers (e.g., syscon without child), but I clearly contradict the generality in which you appear to rule out overlapping memory ranges, be it for siblings or for parent/child. Hiding overlaps in an mfd driver does not strike me as better than openly declaring them - if the mfd components are not dynamic, then I understood simple-mfd were the way to go, which requires some reg(s), which then for convenience may overlap if there's no clear boundaries. Regards, Andreas
On Thu, Dec 12, 2019 at 06:38:31AM +0100, Andreas Färber wrote: > Am 11.12.19 um 23:49 schrieb Paul Walmsley: > > On Wed, 11 Dec 2019, Andreas Färber wrote: > > > >> Blocks do have names, but they don't always group registers of the same > >> kind, as Linux expects it > > > > Linux does not expect that all of the registers in the same IP block are > > of the same kind. That's part of the reason why Linux frameworks exist. > > To consider clocks as the present example, you're welcome to register > > local IP block clock control registers in the local IP block driver via > > the clock framework. There's no need for a separate clock driver with an > > overlapping address range, or anything like that. > > If I throw random code into drivers/mfd/ it will not get proper review. I don't think that's what Paul was suggesting. MFD is something that can help in these cases, but often isn't required. > We rely on clk drivers going into drivers/clk/, even if I could > theoretically register clks also from other parts of the code base - > which will then require complex Kconfig dependencies or #ifdef'ery, not > to mention the nightmares of collecting Acks and figuring out through > whose tree which patches go. That's a process issue and isn't actually that bad in my experience. > > This is nothing new with Realtek. > > As this NXP patch proves. :) > > > IP blocks that contain many different > > kinds of registers have had Linux driver support without requiring > > overlapping register address ranges long before Realtek ARM SoCs > > appeared. > > Hey, you're the one that's trying to pin this on Realtek, not me! > STM32 RCC is another example I know, also Allwinner, etc. My point was > precisely that this is - for good or bad - a rather common scenario that > we need to deal with. > > >> Just please accept that hardware does not always allow for unique > >> contiguous memory reservations > > > > Hardware designs do in fact mandate unique contiguous memory reservations, > > otherwise address decoding would be indeterministic. > > Are you not understanding what I'm saying or intentionally gas-lighting? > A contiguous memory _reservation_ is a range of memory like <0xdead0000 > 0x100> that the kernel (software!) blocks other drivers (software!) from > reserving. This has _nothing_ to do with hardware address line decoding. > It's still about devm_platform_ioremap_resource() and related APIs. Do a > `cat /proc/iomem` to see, e.g., "98007800-9800781f : serial" reservation > in successful case; as mentioned by Leonard, an unsuccessful reservation > usually causes the driver to fail to probe and thus be unavailable. I think what Paul is saying here is that even in hardware you do in fact have these contiguous address regions assigned for each block. This is just because you need to have an address decoder somewhere that forwards addresses from the CPU to the various IP blocks. These address decoders work on contiguous ranges, so by definitions registers within the same region go to the same IP block. > > What they don't > > mandate is that all of the registers in that region be all of one kind. > > It's certainly possible to have an SoC with one giant IP block with all > > registers mixed together. Even in that case, it is still incorrect to > > have multiple DT entries with overlapping register address ranges. > > Says who? Since when? Can we maybe agree that incorrect != invalid? We always represent each hardware blocks with one device tree node. Given the above, if you have multiple nodes with overlapping register ranges, you're describing one hardware block with multiple nodes and that's when these kinds of issues come up. > > It sounds like you're thinking of the difficulties of figuring out how to > > structure the software driver support for those mixed IP block as a Linux > > driver: > > Yes, these are Linux kernel mailing lists and patches after all... I > don't design hardware, that's why I said we need to live with the flawed > reality of the actual hardware we get. I don't think the hardware is necessarily flawed. It might not be structured in a way that reflects the Linux kernel's subsystem structure, but that's quite common. That's not a problem to solve at the device tree level. The device tree should describe the hardware. It's the job of device drivers to make the hardware available to the kernel and its subsystems. > > where it would fit in the tree, what frameworks it would need to > > register with, and who would maintain it. Those issues certainly merit > > careful thought and consideration. They aren't related to multiple > > overlapping address ranges. > > Oh they are. Overlapping address ranges of DT nodes are a _result_ of > unexpected hardware design involving blocks not clearly separated the > same way as Linux subsystems (to distinguish from "frameworks") are. > > The DT should describe the hardware blocks as they were designed, but on > the other hand, we need to describe it in a way that Linux drivers can > actually bind against the relevant parts and that those drivers can > operate efficiently. That's exactly where the misconception is. DT should not at all be concerned about the operating system's internal structuring. While I think the way that Linux is structure is great, not all operating systems may work the same way. Other operating systems may not have separate frameworks for clocks and resets. So if you start writing device trees with a specific operating system in mind, you're likely going to end up with one device tree per device per operating system. That's not what we want. One device tree per device, independent of the operating system, that's the goal. > There is no ioremap-all-regs helper that I'm aware > of, for instance, as that would result in __iomem base addresses to be > stored per reg entry; compare that to just one for an overlapping range. > > Example: > > clk@f00 { > reg = <0xf00 0x100>; > } > > reset@f0f { > reg = <0xf0c 0x4>; > }; > > This should be a valid DT example today, as long as the clk driver > doesn't mess with the reset register embedded within its range. In this > case they can't both reserve their ranges as they would mutually cause > each other to fail to probe, depending on probe order. It's certainly not invalid DT from a syntax point of view. But that doesn't necessarily mean that it's a correct description of the hardware. > > As I wrote, turning this into > > clk@f00 { > reg = <0xf00 0xc>, <0xf10 0xe0>; > }; > > reset@f0f { > reg = <0xf0c 0x4>; > }; > > is helping no one and makes things much more complex, especially when > the number of carve-outs grows or is not predetermined, as I noted about > some of my cases. Thus I disagree with you about the overlapping ranges. Again, you're trying to split the hardware up based on Linux' frameworks rather than by the actual hardware blocks. > DT needs to be designed forward-looking rather than just around the > handful of registers we might read/write today, not just to relieve Rob > from excessive reviews. > > My solution was to do > > syscon@f00 { > reg = <0xf00 0x100>; > ranges = ...; > > clk@0 { > reg = <0x0 0x100>; > }; > > reset@c { > reg = <0xc 0x4>; > }; > }; That's starting to look more like it. But still, why even bother with the separate clk and reset nodes? This block clearly provides both controls for clocks and controls for resets. The fact that Linux has two separate frameworks for these types of resources is secondary. The right thing to do here is to have one driver for the whole block and then register its device with both the clock and reset frameworks. That way you don't need two separate nodes. You only have these nodes so that you can get two separate devices that a clock driver and a reset driver can bind to, respectively. There's nothing in the frameworks that would prevent the same driver from registering to both frameworks. In other words, it's perfectly fine to have a single device/driver be a clock provider and reset provider at the same time. > https://patchwork.kernel.org/cover/11269453/ > https://patchwork.kernel.org/cover/11269971/ (and more in my tree) > > which clearly models the blocks and shares a syscon for most children, > other than pre-existing 8250 UART, I²C, etc. drivers using platform > helpers such as the one discussed here. > > What we lose with syscon is reservations, i.e. /proc/iomem neither > showing the full syscon nor the drivers using parts of it, unless we > explicitly reserve the memory (syscon does the ioremap for us, so no > need for this devm_platform_ioremap_resource helper there). > > Also please keep in mind that we actually want to get to the point where > new systems are booting and usable. At least in the Arm world we do have > hardware at plenty to boot Linux. Dying in DT-beauty then is > counter-productive; we also need to come to timely compromises for not > blocking other work. clk drivers don't need to be platform_drivers like > here and thus can coexist easier with other drivers (e.g., syscon > without child), but I clearly contradict the generality in which you > appear to rule out overlapping memory ranges, be it for siblings or for > parent/child. I think the common misconception that we need separate drivers for each framework is what's counter-productive. If the same device provides different types of resources, then we should just have one driver register with whatever the frameworks are that expose these resources. It becomes really quite simple once you shed that misconception. Thierry > Hiding overlaps in an mfd driver does not strike me as better than > openly declaring them - if the mfd components are not dynamic, then I > understood simple-mfd were the way to go, which requires some reg(s), > which then for convenience may overlap if there's no clear boundaries. > > Regards, > Andreas > > -- > SUSE Software Solutions Germany GmbH > Maxfeldstr. 5, 90409 Nürnberg, Germany > GF: Felix Imendörffer > HRB 36809 (AG Nürnberg)
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index c0aff7ca6374..10ae712447c6 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -164,7 +164,6 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) struct clk_hw_onecell_data *clk_data; const struct imx8qxp_ss_lpcg *ss_lpcg; const struct imx8qxp_lpcg_data *lpcg; - struct resource *res; struct clk_hw **clks; void __iomem *base; int i; @@ -173,10 +172,7 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) if (!ss_lpcg) return -ENODEV; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; - base = devm_ioremap(dev, res->start, resource_size(res)); + base = devm_platform_ioremap_resource(pdev, 0); if (!base) return -ENOMEM;
Use devm_platform_ioremap_resource() to simplify code. Signed-off-by: Yangtao Li <tiny.windzz@gmail.com> --- drivers/clk/imx/clk-imx8qxp-lpcg.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)