[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHp75Vc_Qa8gs6V4ZxrrxYVM1iX8pO+xvED=C0ywen8hhFJTPw@mail.gmail.com>
Date: Mon, 5 Jun 2017 18:11:06 +0300
From: Andy Shevchenko <andy.shevchenko@...il.com>
To: Mika Westerberg <mika.westerberg@...ux.intel.com>
Cc: Linus Walleij <linus.walleij@...aro.org>,
Heikki Krogerus <heikki.krogerus@...ux.intel.com>,
"linux-gpio@...r.kernel.org" <linux-gpio@...r.kernel.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH 1/3] pinctrl: intel: Add support for variable size pad groups
On Mon, Jun 5, 2017 at 3:56 PM, Mika Westerberg
<mika.westerberg@...ux.intel.com> 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
Powered by blists - more mailing lists