diff options
Diffstat (limited to 'drivers/pinctrl/mvebu/pinctrl-dove.c')
-rw-r--r-- | drivers/pinctrl/mvebu/pinctrl-dove.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c index da9ca26360fd..8d57d4bc1f0c 100644 --- a/drivers/pinctrl/mvebu/pinctrl-dove.c +++ b/drivers/pinctrl/mvebu/pinctrl-dove.c @@ -22,6 +22,11 @@ #include "pinctrl-mvebu.h" +/* Internal registers can be configured at any 1 MiB aligned address */ +#define INT_REGS_MASK ~(SZ_1M - 1) +#define MPP4_REGS_OFFS 0xd0440 +#define PMU_REGS_OFFS 0xd802c + #define DOVE_SB_REGS_VIRT_BASE IOMEM(0xfde00000) #define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0200) #define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10) @@ -52,6 +57,8 @@ #define CONFIG_PMU BIT(4) static void __iomem *mpp_base; +static void __iomem *mpp4_base; +static void __iomem *pmu_base; static int dove_mpp_ctrl_get(unsigned pid, unsigned long *config) { @@ -751,7 +758,8 @@ static struct of_device_id dove_pinctrl_of_match[] = { static int dove_pinctrl_probe(struct platform_device *pdev) { - struct resource *res; + struct resource *res, *mpp_res; + struct resource fb_res; const struct of_device_id *match = of_match_device(dove_pinctrl_of_match, &pdev->dev); pdev->dev.platform_data = (void *)match->data; @@ -767,11 +775,42 @@ static int dove_pinctrl_probe(struct platform_device *pdev) } clk_prepare_enable(clk); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mpp_base = devm_ioremap_resource(&pdev->dev, res); + mpp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mpp_base = devm_ioremap_resource(&pdev->dev, mpp_res); if (IS_ERR(mpp_base)) return PTR_ERR(mpp_base); + /* prepare fallback resource */ + memcpy(&fb_res, mpp_res, sizeof(struct resource)); + fb_res.start = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_warn(&pdev->dev, "falling back to hardcoded MPP4 resource\n"); + adjust_resource(&fb_res, + (mpp_res->start & INT_REGS_MASK) + MPP4_REGS_OFFS, 0x4); + res = &fb_res; + } + + mpp4_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mpp4_base)) + return PTR_ERR(mpp4_base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (!res) { + dev_warn(&pdev->dev, "falling back to hardcoded PMU resource\n"); + adjust_resource(&fb_res, + (mpp_res->start & INT_REGS_MASK) + PMU_REGS_OFFS, 0x8); + res = &fb_res; + } + + pmu_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pmu_base)) + return PTR_ERR(pmu_base); + + /* Warn on any missing DT resource */ + WARN(fb_res.start, FW_BUG "Missing pinctrl regs in DTB. Please update your firmware.\n"); + return mvebu_pinctrl_probe(pdev); } |