Message ID | 20220406052459.10438-2-amhetre@nvidia.com |
---|---|
State | Changes Requested |
Headers | show |
Series | memory: tegra: Add MC channels and error logging | expand |
06.04.2022 08:24, Ashish Mhetre пишет: > + num_dt_channels = of_property_count_elems_of_size(pdev->dev.of_node, "reg", > + reg_cells * sizeof(u32)); > + /* > + * On tegra186 onwards, memory controller support multiple channels. > + * Apart from regular memory controller channels, there is one broadcast > + * channel and one for stream-id registers. > + */ > + if (num_dt_channels < mc->soc->num_channels + 2) { > + dev_warn(&pdev->dev, "MC channels are missing, please update memory controller DT node with MC channels\n"); > + return 0; > + } > + > + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "mc-broadcast"); > + if (IS_ERR(mc->bcast_ch_regs)) > + return PTR_ERR(mc->bcast_ch_regs); Looks to me that you don't need to use of_property_count_elems_of_size() and could only check the "mc-broadcast" presence to decide whether this is an older DT. mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "broadcast"); if (IS_ERR(mc->bcast_ch_regs)) { dev_warn(&pdev->dev, "Broadcast channel is missing, please update your device-tree\n"); return PTR_ERR(mc->bcast_ch_regs); }
06.04.2022 08:24, Ashish Mhetre пишет: > diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h > index 1066b1194a5a..c3c121fbfbb7 100644 > --- a/include/soc/tegra/mc.h > +++ b/include/soc/tegra/mc.h > @@ -13,6 +13,9 @@ > #include <linux/irq.h> > #include <linux/reset-controller.h> > #include <linux/types.h> > +#include <linux/platform_device.h> > + > +#define MC_MAX_CHANNELS 16 > > struct clk; > struct device; > @@ -181,6 +184,7 @@ struct tegra_mc_ops { > int (*resume)(struct tegra_mc *mc); > irqreturn_t (*handle_irq)(int irq, void *data); > int (*probe_device)(struct tegra_mc *mc, struct device *dev); > + int (*map_regs)(struct tegra_mc *mc, struct platform_device *pdev); Use to_platform_device(mc->dev) instead of passing the pdev argument.
06.04.2022 08:24, Ashish Mhetre пишет: > diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h > index 1066b1194a5a..c3c121fbfbb7 100644 > --- a/include/soc/tegra/mc.h > +++ b/include/soc/tegra/mc.h > @@ -13,6 +13,9 @@ > #include <linux/irq.h> > #include <linux/reset-controller.h> > #include <linux/types.h> > +#include <linux/platform_device.h> > + > +#define MC_MAX_CHANNELS 16 > > struct clk; > struct device; > @@ -181,6 +184,7 @@ struct tegra_mc_ops { > int (*resume)(struct tegra_mc *mc); > irqreturn_t (*handle_irq)(int irq, void *data); > int (*probe_device)(struct tegra_mc *mc, struct device *dev); > + int (*map_regs)(struct tegra_mc *mc, struct platform_device *pdev); > }; > > struct tegra_mc_soc { > @@ -194,6 +198,7 @@ struct tegra_mc_soc { > unsigned int atom_size; > > u8 client_id_mask; > + u8 num_channels; > > const struct tegra_smmu_soc *smmu; > > @@ -212,6 +217,8 @@ struct tegra_mc { > struct tegra_smmu *smmu; > struct gart_device *gart; > void __iomem *regs; > + void __iomem *bcast_ch_regs; > + void __iomem *ch_regs[MC_MAX_CHANNELS]; Why not to allocate ch_regs at runtime?
On 4/10/2022 7:48 PM, Dmitry Osipenko wrote: > External email: Use caution opening links or attachments > > > 06.04.2022 08:24, Ashish Mhetre пишет: >> + num_dt_channels = of_property_count_elems_of_size(pdev->dev.of_node, "reg", >> + reg_cells * sizeof(u32)); >> + /* >> + * On tegra186 onwards, memory controller support multiple channels. >> + * Apart from regular memory controller channels, there is one broadcast >> + * channel and one for stream-id registers. >> + */ >> + if (num_dt_channels < mc->soc->num_channels + 2) { >> + dev_warn(&pdev->dev, "MC channels are missing, please update memory controller DT node with MC channels\n"); >> + return 0; >> + } >> + >> + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "mc-broadcast"); >> + if (IS_ERR(mc->bcast_ch_regs)) >> + return PTR_ERR(mc->bcast_ch_regs); > > Looks to me that you don't need to use of_property_count_elems_of_size() > and could only check the "mc-broadcast" presence to decide whether this > is an older DT. > Now that we are using reg-names in new DT, yes it'd be fine to just check mc-broadcast to decide it's a new or old DT. > mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, > "broadcast"); > if (IS_ERR(mc->bcast_ch_regs)) { > dev_warn(&pdev->dev, "Broadcast channel is missing, please update your > device-tree\n"); > return PTR_ERR(mc->bcast_ch_regs); > } return 0; to avoid DT ABI break, right?
On 4/10/2022 8:31 PM, Dmitry Osipenko wrote: > External email: Use caution opening links or attachments > > > 06.04.2022 08:24, Ashish Mhetre пишет: >> diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h >> index 1066b1194a5a..c3c121fbfbb7 100644 >> --- a/include/soc/tegra/mc.h >> +++ b/include/soc/tegra/mc.h >> @@ -13,6 +13,9 @@ >> #include <linux/irq.h> >> #include <linux/reset-controller.h> >> #include <linux/types.h> >> +#include <linux/platform_device.h> >> + >> +#define MC_MAX_CHANNELS 16 >> >> struct clk; >> struct device; >> @@ -181,6 +184,7 @@ struct tegra_mc_ops { >> int (*resume)(struct tegra_mc *mc); >> irqreturn_t (*handle_irq)(int irq, void *data); >> int (*probe_device)(struct tegra_mc *mc, struct device *dev); >> + int (*map_regs)(struct tegra_mc *mc, struct platform_device *pdev); > > Use to_platform_device(mc->dev) instead of passing the pdev argument. Okay, I'll update in v7.
On 4/10/2022 8:34 PM, Dmitry Osipenko wrote: > External email: Use caution opening links or attachments > > > 06.04.2022 08:24, Ashish Mhetre пишет: >> diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h >> index 1066b1194a5a..c3c121fbfbb7 100644 >> --- a/include/soc/tegra/mc.h >> +++ b/include/soc/tegra/mc.h >> @@ -13,6 +13,9 @@ >> #include <linux/irq.h> >> #include <linux/reset-controller.h> >> #include <linux/types.h> >> +#include <linux/platform_device.h> >> + >> +#define MC_MAX_CHANNELS 16 >> >> struct clk; >> struct device; >> @@ -181,6 +184,7 @@ struct tegra_mc_ops { >> int (*resume)(struct tegra_mc *mc); >> irqreturn_t (*handle_irq)(int irq, void *data); >> int (*probe_device)(struct tegra_mc *mc, struct device *dev); >> + int (*map_regs)(struct tegra_mc *mc, struct platform_device *pdev); >> }; >> >> struct tegra_mc_soc { >> @@ -194,6 +198,7 @@ struct tegra_mc_soc { >> unsigned int atom_size; >> >> u8 client_id_mask; >> + u8 num_channels; >> >> const struct tegra_smmu_soc *smmu; >> >> @@ -212,6 +217,8 @@ struct tegra_mc { >> struct tegra_smmu *smmu; >> struct gart_device *gart; >> void __iomem *regs; >> + void __iomem *bcast_ch_regs; >> + void __iomem *ch_regs[MC_MAX_CHANNELS]; > > Why not to allocate ch_regs at runtime? Yes, we can do that. I'll make necessary changes in v7.
On 4/11/22 09:05, Ashish Mhetre wrote: > > > On 4/10/2022 7:48 PM, Dmitry Osipenko wrote: >> External email: Use caution opening links or attachments >> >> >> 06.04.2022 08:24, Ashish Mhetre пишет: >>> + num_dt_channels = >>> of_property_count_elems_of_size(pdev->dev.of_node, "reg", >>> + reg_cells * >>> sizeof(u32)); >>> + /* >>> + * On tegra186 onwards, memory controller support multiple >>> channels. >>> + * Apart from regular memory controller channels, there is one >>> broadcast >>> + * channel and one for stream-id registers. >>> + */ >>> + if (num_dt_channels < mc->soc->num_channels + 2) { >>> + dev_warn(&pdev->dev, "MC channels are missing, please >>> update memory controller DT node with MC channels\n"); >>> + return 0; >>> + } >>> + >>> + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>> "mc-broadcast"); >>> + if (IS_ERR(mc->bcast_ch_regs)) >>> + return PTR_ERR(mc->bcast_ch_regs); >> >> Looks to me that you don't need to use of_property_count_elems_of_size() >> and could only check the "mc-broadcast" presence to decide whether this >> is an older DT. >> > Now that we are using reg-names in new DT, yes it'd be fine to just > check mc-broadcast to decide it's a new or old DT. > >> mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >> "broadcast"); >> if (IS_ERR(mc->bcast_ch_regs)) { >> dev_warn(&pdev->dev, "Broadcast channel is missing, please >> update your >> device-tree\n"); >> return PTR_ERR(mc->bcast_ch_regs); >> } > > return 0; > > to avoid DT ABI break, right? Yes, it should be "return 0".
On 4/11/2022 12:03 PM, Dmitry Osipenko wrote: > External email: Use caution opening links or attachments > > > On 4/11/22 09:05, Ashish Mhetre wrote: >> >> >> On 4/10/2022 7:48 PM, Dmitry Osipenko wrote: >>> External email: Use caution opening links or attachments >>> >>> >>> 06.04.2022 08:24, Ashish Mhetre пишет: >>>> + num_dt_channels = >>>> of_property_count_elems_of_size(pdev->dev.of_node, "reg", >>>> + reg_cells * >>>> sizeof(u32)); >>>> + /* >>>> + * On tegra186 onwards, memory controller support multiple >>>> channels. >>>> + * Apart from regular memory controller channels, there is one >>>> broadcast >>>> + * channel and one for stream-id registers. >>>> + */ >>>> + if (num_dt_channels < mc->soc->num_channels + 2) { >>>> + dev_warn(&pdev->dev, "MC channels are missing, please >>>> update memory controller DT node with MC channels\n"); >>>> + return 0; >>>> + } >>>> + >>>> + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>>> "mc-broadcast"); >>>> + if (IS_ERR(mc->bcast_ch_regs)) >>>> + return PTR_ERR(mc->bcast_ch_regs); >>> >>> Looks to me that you don't need to use of_property_count_elems_of_size() >>> and could only check the "mc-broadcast" presence to decide whether this >>> is an older DT. >>> >> Now that we are using reg-names in new DT, yes it'd be fine to just >> check mc-broadcast to decide it's a new or old DT. >> >>> mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>> "broadcast"); >>> if (IS_ERR(mc->bcast_ch_regs)) { >>> dev_warn(&pdev->dev, "Broadcast channel is missing, please >>> update your >>> device-tree\n"); >>> return PTR_ERR(mc->bcast_ch_regs); >>> } >> >> return 0; >> >> to avoid DT ABI break, right? > > Yes, it should be "return 0". But if we "return 0" from here, then what about the case when ioremap() actually fails with new DT i.e. when broadcast reg is present in DT? In that case error should be returned and probe should be failed, right?
On 4/11/22 10:28, Ashish Mhetre wrote: > > > On 4/11/2022 12:03 PM, Dmitry Osipenko wrote: >> External email: Use caution opening links or attachments >> >> >> On 4/11/22 09:05, Ashish Mhetre wrote: >>> >>> >>> On 4/10/2022 7:48 PM, Dmitry Osipenko wrote: >>>> External email: Use caution opening links or attachments >>>> >>>> >>>> 06.04.2022 08:24, Ashish Mhetre пишет: >>>>> + num_dt_channels = >>>>> of_property_count_elems_of_size(pdev->dev.of_node, "reg", >>>>> + reg_cells * >>>>> sizeof(u32)); >>>>> + /* >>>>> + * On tegra186 onwards, memory controller support multiple >>>>> channels. >>>>> + * Apart from regular memory controller channels, there is one >>>>> broadcast >>>>> + * channel and one for stream-id registers. >>>>> + */ >>>>> + if (num_dt_channels < mc->soc->num_channels + 2) { >>>>> + dev_warn(&pdev->dev, "MC channels are missing, please >>>>> update memory controller DT node with MC channels\n"); >>>>> + return 0; >>>>> + } >>>>> + >>>>> + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>>>> "mc-broadcast"); >>>>> + if (IS_ERR(mc->bcast_ch_regs)) >>>>> + return PTR_ERR(mc->bcast_ch_regs); >>>> >>>> Looks to me that you don't need to use >>>> of_property_count_elems_of_size() >>>> and could only check the "mc-broadcast" presence to decide whether this >>>> is an older DT. >>>> >>> Now that we are using reg-names in new DT, yes it'd be fine to just >>> check mc-broadcast to decide it's a new or old DT. >>> >>>> mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>>> "broadcast"); >>>> if (IS_ERR(mc->bcast_ch_regs)) { >>>> dev_warn(&pdev->dev, "Broadcast channel is missing, please >>>> update your >>>> device-tree\n"); >>>> return PTR_ERR(mc->bcast_ch_regs); >>>> } >>> >>> return 0; >>> >>> to avoid DT ABI break, right? >> >> Yes, it should be "return 0". > > But if we "return 0" from here, then what about the case when ioremap() > actually fails with new DT i.e. when broadcast reg is present in DT? > In that case error should be returned and probe should be failed, right? You should check for the -ENOENT.
On 4/11/2022 1:05 PM, Dmitry Osipenko wrote: > External email: Use caution opening links or attachments > > > On 4/11/22 10:28, Ashish Mhetre wrote: >> >> >> On 4/11/2022 12:03 PM, Dmitry Osipenko wrote: >>> External email: Use caution opening links or attachments >>> >>> >>> On 4/11/22 09:05, Ashish Mhetre wrote: >>>> >>>> >>>> On 4/10/2022 7:48 PM, Dmitry Osipenko wrote: >>>>> External email: Use caution opening links or attachments >>>>> >>>>> >>>>> 06.04.2022 08:24, Ashish Mhetre пишет: >>>>>> + num_dt_channels = >>>>>> of_property_count_elems_of_size(pdev->dev.of_node, "reg", >>>>>> + reg_cells * >>>>>> sizeof(u32)); >>>>>> + /* >>>>>> + * On tegra186 onwards, memory controller support multiple >>>>>> channels. >>>>>> + * Apart from regular memory controller channels, there is one >>>>>> broadcast >>>>>> + * channel and one for stream-id registers. >>>>>> + */ >>>>>> + if (num_dt_channels < mc->soc->num_channels + 2) { >>>>>> + dev_warn(&pdev->dev, "MC channels are missing, please >>>>>> update memory controller DT node with MC channels\n"); >>>>>> + return 0; >>>>>> + } >>>>>> + >>>>>> + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>>>>> "mc-broadcast"); >>>>>> + if (IS_ERR(mc->bcast_ch_regs)) >>>>>> + return PTR_ERR(mc->bcast_ch_regs); >>>>> >>>>> Looks to me that you don't need to use >>>>> of_property_count_elems_of_size() >>>>> and could only check the "mc-broadcast" presence to decide whether this >>>>> is an older DT. >>>>> >>>> Now that we are using reg-names in new DT, yes it'd be fine to just >>>> check mc-broadcast to decide it's a new or old DT. >>>> >>>>> mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>>>> "broadcast"); >>>>> if (IS_ERR(mc->bcast_ch_regs)) { >>>>> dev_warn(&pdev->dev, "Broadcast channel is missing, please >>>>> update your >>>>> device-tree\n"); >>>>> return PTR_ERR(mc->bcast_ch_regs); >>>>> } >>>> >>>> return 0; >>>> >>>> to avoid DT ABI break, right? >>> >>> Yes, it should be "return 0". >> >> But if we "return 0" from here, then what about the case when ioremap() >> actually fails with new DT i.e. when broadcast reg is present in DT? >> In that case error should be returned and probe should be failed, right? > > You should check for the -ENOENT. I checked __devm_ioremap_resource(), it returns -EINVAL if given resource is not present. So should we check for -EINVAL instead?
On 4/11/22 12:18, Ashish Mhetre wrote: > > > On 4/11/2022 1:05 PM, Dmitry Osipenko wrote: >> External email: Use caution opening links or attachments >> >> >> On 4/11/22 10:28, Ashish Mhetre wrote: >>> >>> >>> On 4/11/2022 12:03 PM, Dmitry Osipenko wrote: >>>> External email: Use caution opening links or attachments >>>> >>>> >>>> On 4/11/22 09:05, Ashish Mhetre wrote: >>>>> >>>>> >>>>> On 4/10/2022 7:48 PM, Dmitry Osipenko wrote: >>>>>> External email: Use caution opening links or attachments >>>>>> >>>>>> >>>>>> 06.04.2022 08:24, Ashish Mhetre пишет: >>>>>>> + num_dt_channels = >>>>>>> of_property_count_elems_of_size(pdev->dev.of_node, "reg", >>>>>>> + reg_cells * >>>>>>> sizeof(u32)); >>>>>>> + /* >>>>>>> + * On tegra186 onwards, memory controller support multiple >>>>>>> channels. >>>>>>> + * Apart from regular memory controller channels, there is one >>>>>>> broadcast >>>>>>> + * channel and one for stream-id registers. >>>>>>> + */ >>>>>>> + if (num_dt_channels < mc->soc->num_channels + 2) { >>>>>>> + dev_warn(&pdev->dev, "MC channels are missing, please >>>>>>> update memory controller DT node with MC channels\n"); >>>>>>> + return 0; >>>>>>> + } >>>>>>> + >>>>>>> + mc->bcast_ch_regs = >>>>>>> devm_platform_ioremap_resource_byname(pdev, >>>>>>> "mc-broadcast"); >>>>>>> + if (IS_ERR(mc->bcast_ch_regs)) >>>>>>> + return PTR_ERR(mc->bcast_ch_regs); >>>>>> >>>>>> Looks to me that you don't need to use >>>>>> of_property_count_elems_of_size() >>>>>> and could only check the "mc-broadcast" presence to decide whether >>>>>> this >>>>>> is an older DT. >>>>>> >>>>> Now that we are using reg-names in new DT, yes it'd be fine to just >>>>> check mc-broadcast to decide it's a new or old DT. >>>>> >>>>>> mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, >>>>>> "broadcast"); >>>>>> if (IS_ERR(mc->bcast_ch_regs)) { >>>>>> dev_warn(&pdev->dev, "Broadcast channel is missing, please >>>>>> update your >>>>>> device-tree\n"); >>>>>> return PTR_ERR(mc->bcast_ch_regs); >>>>>> } >>>>> >>>>> return 0; >>>>> >>>>> to avoid DT ABI break, right? >>>> >>>> Yes, it should be "return 0". >>> >>> But if we "return 0" from here, then what about the case when ioremap() >>> actually fails with new DT i.e. when broadcast reg is present in DT? >>> In that case error should be returned and probe should be failed, right? >> >> You should check for the -ENOENT. > > I checked __devm_ioremap_resource(), it returns -EINVAL if given > resource is not present. So should we check for -EINVAL instead? Yes
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index bf3abb6d8354..3cda1d9ad32a 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -749,6 +749,12 @@ static int tegra_mc_probe(struct platform_device *pdev) if (IS_ERR(mc->regs)) return PTR_ERR(mc->regs); + if (mc->soc->ops && mc->soc->ops->map_regs) { + err = mc->soc->ops->map_regs(mc, pdev); + if (err < 0) + return err; + } + mc->debugfs.root = debugfs_create_dir("mc", NULL); if (mc->soc->ops && mc->soc->ops->probe) { diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c index 3d153881abc1..2ca8ce349188 100644 --- a/drivers/memory/tegra/tegra186.c +++ b/drivers/memory/tegra/tegra186.c @@ -139,11 +139,64 @@ static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev) return 0; } +static int tegra186_mc_map_regs(struct tegra_mc *mc, + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.parent->of_node; + int num_dt_channels, reg_cells = 0; + int i, ret; + u32 val; + + ret = of_property_read_u32(np, "#address-cells", &val); + if (ret) { + dev_err(&pdev->dev, "missing #address-cells property\n"); + return ret; + } + + reg_cells = val; + + ret = of_property_read_u32(np, "#size-cells", &val); + if (ret) { + dev_err(&pdev->dev, "missing #size-cells property\n"); + return ret; + } + + reg_cells += val; + + num_dt_channels = of_property_count_elems_of_size(pdev->dev.of_node, "reg", + reg_cells * sizeof(u32)); + /* + * On tegra186 onwards, memory controller support multiple channels. + * Apart from regular memory controller channels, there is one broadcast + * channel and one for stream-id registers. + */ + if (num_dt_channels < mc->soc->num_channels + 2) { + dev_warn(&pdev->dev, "MC channels are missing, please update memory controller DT node with MC channels\n"); + return 0; + } + + mc->bcast_ch_regs = devm_platform_ioremap_resource_byname(pdev, "mc-broadcast"); + if (IS_ERR(mc->bcast_ch_regs)) + return PTR_ERR(mc->bcast_ch_regs); + + for (i = 0; i < mc->soc->num_channels; i++) { + char name[4]; + + sprintf(name, "mc%u", i); + mc->ch_regs[i] = devm_platform_ioremap_resource_byname(pdev, name); + if (IS_ERR(mc->ch_regs[i])) + return PTR_ERR(mc->ch_regs[i]); + } + + return 0; +} + const struct tegra_mc_ops tegra186_mc_ops = { .probe = tegra186_mc_probe, .remove = tegra186_mc_remove, .resume = tegra186_mc_resume, .probe_device = tegra186_mc_probe_device, + .map_regs = tegra186_mc_map_regs, }; #if defined(CONFIG_ARCH_TEGRA_186_SOC) @@ -875,6 +928,7 @@ const struct tegra_mc_soc tegra186_mc_soc = { .num_clients = ARRAY_SIZE(tegra186_mc_clients), .clients = tegra186_mc_clients, .num_address_bits = 40, + .num_channels = 4, .ops = &tegra186_mc_ops, }; #endif diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c index cab998b8bd5c..94001174deaf 100644 --- a/drivers/memory/tegra/tegra194.c +++ b/drivers/memory/tegra/tegra194.c @@ -1347,5 +1347,6 @@ const struct tegra_mc_soc tegra194_mc_soc = { .num_clients = ARRAY_SIZE(tegra194_mc_clients), .clients = tegra194_mc_clients, .num_address_bits = 40, + .num_channels = 16, .ops = &tegra186_mc_ops, }; diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c index e22824a79f45..6335a132be2d 100644 --- a/drivers/memory/tegra/tegra234.c +++ b/drivers/memory/tegra/tegra234.c @@ -97,5 +97,6 @@ const struct tegra_mc_soc tegra234_mc_soc = { .num_clients = ARRAY_SIZE(tegra234_mc_clients), .clients = tegra234_mc_clients, .num_address_bits = 40, + .num_channels = 16, .ops = &tegra186_mc_ops, }; diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 1066b1194a5a..c3c121fbfbb7 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -13,6 +13,9 @@ #include <linux/irq.h> #include <linux/reset-controller.h> #include <linux/types.h> +#include <linux/platform_device.h> + +#define MC_MAX_CHANNELS 16 struct clk; struct device; @@ -181,6 +184,7 @@ struct tegra_mc_ops { int (*resume)(struct tegra_mc *mc); irqreturn_t (*handle_irq)(int irq, void *data); int (*probe_device)(struct tegra_mc *mc, struct device *dev); + int (*map_regs)(struct tegra_mc *mc, struct platform_device *pdev); }; struct tegra_mc_soc { @@ -194,6 +198,7 @@ struct tegra_mc_soc { unsigned int atom_size; u8 client_id_mask; + u8 num_channels; const struct tegra_smmu_soc *smmu; @@ -212,6 +217,8 @@ struct tegra_mc { struct tegra_smmu *smmu; struct gart_device *gart; void __iomem *regs; + void __iomem *bcast_ch_regs; + void __iomem *ch_regs[MC_MAX_CHANNELS]; struct clk *clk; int irq;
From tegra186 onwards, memory controller support multiple channels. Add support for mapping address spaces of these channels. Make sure that number of channels are as expected on each SOC. During error interrupts from memory controller, appropriate registers from these channels need to be accessed for logging error info. Signed-off-by: Ashish Mhetre <amhetre@nvidia.com> --- drivers/memory/tegra/mc.c | 6 ++++ drivers/memory/tegra/tegra186.c | 54 +++++++++++++++++++++++++++++++++ drivers/memory/tegra/tegra194.c | 1 + drivers/memory/tegra/tegra234.c | 1 + include/soc/tegra/mc.h | 7 +++++ 5 files changed, 69 insertions(+)