On Tue, 28 Jan 2025 at 20:48, Michal Wilczynski <m.wilczynski@xxxxxxxxxxx> wrote: > > The T-Head TH1520 SoC contains multiple power islands that can be > programmatically turned on and off using the AON (Always-On) protocol > and a hardware mailbox [1]. The relevant mailbox driver has already been > merged into the mainline kernel in commit 5d4d263e1c6b ("mailbox: > Introduce support for T-head TH1520 Mailbox driver"); > > Introduce a power-domain driver for the TH1520 SoC, which is using AON > firmware protocol to communicate with E902 core through the hardware > mailbox. This way it can send power on/off commands to the E902 core. > > The interaction with AUDIO power island e.g trying to turn it OFF proved > to crash the firmware running on the E902 core. Introduce the workaround > to disable interacting with the power island. > > Link: https://openbeagle.org/beaglev-ahead/beaglev-ahead/-/blob/main/docs/TH1520%20System%20User%20Manual.pdf [1] > > Signed-off-by: Michal Wilczynski <m.wilczynski@xxxxxxxxxxx> > --- [...] > + > +static int th1520_pd_probe(struct platform_device *pdev) > +{ > + struct generic_pm_domain **domains; > + struct genpd_onecell_data *pd_data; > + struct th1520_aon_chan *aon_chan; > + struct device *dev = &pdev->dev; > + int i; > + > + aon_chan = dev_get_drvdata(dev->parent); > + if (!aon_chan) { > + dev_err(dev, "Failed to get AON channel from parent\n"); > + return -EINVAL; > + } As pointed out on patch4. Rather than receiving the aon_chang from the parent device like this, it seems better to receive it from a call to a library function provided by the FW library. > + > + domains = devm_kcalloc(dev, ARRAY_SIZE(th1520_pd_ranges), > + sizeof(*domains), GFP_KERNEL); > + if (!domains) > + return -ENOMEM; > + > + pd_data = devm_kzalloc(dev, sizeof(*pd_data), GFP_KERNEL); > + if (!pd_data) > + return -ENOMEM; > + > + for (i = 0; i < ARRAY_SIZE(th1520_pd_ranges); i++) { > + struct th1520_power_domain *pd; > + > + if (th1520_pd_ranges[i].disabled) > + continue; > + > + pd = th1520_add_pm_domain(dev, &th1520_pd_ranges[i]); > + if (IS_ERR(pd)) > + return PTR_ERR(pd); > + > + pd->aon_chan = aon_chan; > + domains[i] = &pd->genpd; > + dev_dbg(dev, "added power domain %s\n", pd->genpd.name); > + } > + > + pd_data->domains = domains; > + pd_data->num_domains = ARRAY_SIZE(th1520_pd_ranges); > + pd_data->xlate = th1520_pd_xlate; > + > + /* > + * Initialize all power domains to off to ensure they start in a > + * low-power state. This allows device drivers to manage power > + * domains by turning them on or off as needed. > + */ > + th1520_pd_init_all_off(domains, dev); > + > + return of_genpd_add_provider_onecell(dev->parent->of_node, pd_data); > +} > + > +static struct platform_driver th1520_pd_driver = { > + .driver = { > + .name = "th1520-pd", > + }, > + .probe = th1520_pd_probe, > +}; > +module_platform_driver(th1520_pd_driver); There is no ->remove() callback. Either add one or make this a builtin_platform_driver() with "suppress_bind_attrs = true". > + > +MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@xxxxxxxxxxx>"); > +MODULE_DESCRIPTION("T-HEAD TH1520 SoC power domain controller"); > +MODULE_LICENSE("GPL"); > -- > 2.34.1 > Besides the minor thing above, this looks good to me! Kind regards Uffe