Re: [PATCH 1/3] pinctrl: intel: Add support for variable size pad groups

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

 



On Mon, Jun 5, 2017 at 3:56 PM, Mika Westerberg
<mika.westerberg@xxxxxxxxxxxxxxx> wrote:
> The Intel GPIO hardware has a concept of pad groups, which means 1 to 32
> pads occupying their own GPI_IS, GPI_IE, PAD_OWN and so on registers. The
> existing hardware has the same amount of pads in each pad group (except the
> last one) so it is possible to use community->gpp_size to calculate start
> offset of each register.
>
> With the next generation SoCs the pad group size is not always the same
> anymore which means we cannot use community->gpp_size for register offset
> calculations directly.
>
> To support variable size pad groups we introduce struct intel_padgroup that
> can be filled in by the client drivers according the hardware pad group
> layout. The core driver will always use these when it performs calculations
> for pad register offsets. The core driver will automatically populate pad
> groups based on community->gpp_size if the driver does not provide any.
> This makes sure the existing drivers still work as expected.

> +static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
> +                                      struct intel_community *community)
> +{
> +       struct intel_padgroup *gpps;
> +       unsigned npins = community->npins;
> +       unsigned padown_num = 0;
> +       size_t ngpps, i;
> +
> +       if (community->gpps)
> +               ngpps = community->ngpps;
> +       else
> +               ngpps = DIV_ROUND_UP(community->npins, community->gpp_size);
> +
> +       gpps = devm_kcalloc(pctrl->dev, ngpps, sizeof(*gpps), GFP_KERNEL);
> +       if (!gpps)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < ngpps; i++) {
> +               if (community->gpps) {
> +                       gpps[i] = community->gpps[i];
> +               } else {
> +                       gpps[i].reg_num = i;
> +                       gpps[i].base = community->pin_base +
> +                                      i * community->gpp_size;
> +                       gpps[i].size = min(community->gpp_size, npins);
> +                       npins -= gpps[i].size;
> +               }
> +
> +               if (gpps[i].size > 32)
> +                       return -EINVAL;
> +
> +               gpps[i].padown_num = padown_num;
> +

> +               if (community->padown_fixed)
> +                       padown_num += ALIGN(DIV_ROUND_UP(gpps[i].size, 8), 4);
> +               else
> +                       padown_num += DIV_ROUND_UP(gpps[i].size, 8);
> +       }

It looks to me like you are trying to calculate 32-bit registers
needed for gpps of given size. Taking into account that each pad takes
4 bits you may rewrote entire conditional to be simple and clearer:

DIV_ROUND_UP(size, 32) * 4,

where 32 - is a _fixed_ length of the IO register and 4 is _fixed_
amount of bits per pad.

Please, check if it would work with all hardware we have.
Perhaps little comment also would be nice to have.

> +
> +       community->ngpps = ngpps;
> +       community->gpps = gpps;
> +
> +       return 0;
> +}



-- 
With Best Regards,
Andy Shevchenko
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux