sh-pfc: Compute pin ranges automatically
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Mon, 15 Jul 2013 16:38:30 +0000 (18:38 +0200)
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Mon, 29 Jul 2013 13:17:48 +0000 (15:17 +0200)
Remove the manually specified ranges from PFC SoC data and compute the
ranges automatically. This prevents ranges from being out-of-sync with
pins definitions.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
drivers/pinctrl/sh-pfc/core.c
drivers/pinctrl/sh-pfc/core.h
drivers/pinctrl/sh-pfc/gpio.c
drivers/pinctrl/sh-pfc/pfc-r8a73a4.c
drivers/pinctrl/sh-pfc/pfc-sh73a0.c
drivers/pinctrl/sh-pfc/pinctrl.c
drivers/pinctrl/sh-pfc/sh_pfc.h

index 96b02246796a9eafd54cb9d05d205d2b69793edb..cb47bcee0aab763c14b567f2cb735833c1104cdb 100644 (file)
@@ -82,17 +82,14 @@ int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin)
        unsigned int offset;
        unsigned int i;
 
-       if (pfc->info->ranges == NULL)
-               return pin;
-
-       for (i = 0, offset = 0; i < pfc->info->nr_ranges; ++i) {
-               const struct pinmux_range *range = &pfc->info->ranges[i];
+       for (i = 0, offset = 0; i < pfc->nr_ranges; ++i) {
+               const struct sh_pfc_pin_range *range = &pfc->ranges[i];
 
                if (pin <= range->end)
-                       return pin >= range->begin
-                            ? offset + pin - range->begin : -1;
+                       return pin >= range->start
+                            ? offset + pin - range->start : -1;
 
-               offset += range->end - range->begin + 1;
+               offset += range->end - range->start + 1;
        }
 
        return -EINVAL;
@@ -341,6 +338,59 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
        return 0;
 }
 
+static int sh_pfc_init_ranges(struct sh_pfc *pfc)
+{
+       struct sh_pfc_pin_range *range;
+       unsigned int nr_ranges;
+       unsigned int i;
+
+       if (pfc->info->pins[0].pin == (u16)-1) {
+               /* Pin number -1 denotes that the SoC doesn't report pin numbers
+                * in its pin arrays yet. Consider the pin numbers range as
+                * continuous and allocate a single range.
+                */
+               pfc->nr_ranges = 1;
+               pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges),
+                                          GFP_KERNEL);
+               if (pfc->ranges == NULL)
+                       return -ENOMEM;
+
+               pfc->ranges->start = 0;
+               pfc->ranges->end = pfc->info->nr_pins - 1;
+               pfc->nr_gpio_pins = pfc->info->nr_pins;
+
+               return 0;
+       }
+
+       /* Count, allocate and fill the ranges. */
+       for (i = 1, nr_ranges = 1; i < pfc->info->nr_pins; ++i) {
+               if (pfc->info->pins[i-1].pin != pfc->info->pins[i].pin - 1)
+                       nr_ranges++;
+       }
+
+       pfc->nr_ranges = nr_ranges;
+       pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges) * nr_ranges,
+                                  GFP_KERNEL);
+       if (pfc->ranges == NULL)
+               return -ENOMEM;
+
+       range = pfc->ranges;
+       range->start = pfc->info->pins[0].pin;
+
+       for (i = 1; i < pfc->info->nr_pins; ++i) {
+               if (pfc->info->pins[i-1].pin != pfc->info->pins[i].pin - 1) {
+                       range->end = pfc->info->pins[i-1].pin;
+                       range++;
+                       range->start = pfc->info->pins[i].pin;
+               }
+       }
+
+       range->end = pfc->info->pins[i-1].pin;
+       pfc->nr_gpio_pins = range->end + 1;
+
+       return 0;
+}
+
 #ifdef CONFIG_OF
 static const struct of_device_id sh_pfc_of_table[] = {
 #ifdef CONFIG_PINCTRL_PFC_R8A73A4
@@ -431,6 +481,10 @@ static int sh_pfc_probe(struct platform_device *pdev)
 
        pinctrl_provide_dummies();
 
+       ret = sh_pfc_init_ranges(pfc);
+       if (ret < 0)
+               return ret;
+
        /*
         * Initialize pinctrl bindings first
         */
index 93963a19b340a91effe858190a53a02c0c2d22da..a1b23762ac90691063d7aea5d14758c162bceaf5 100644 (file)
@@ -25,6 +25,11 @@ struct sh_pfc_window {
 struct sh_pfc_chip;
 struct sh_pfc_pinctrl;
 
+struct sh_pfc_pin_range {
+       u16 start;
+       u16 end;
+};
+
 struct sh_pfc {
        struct device *dev;
        const struct sh_pfc_soc_info *info;
@@ -34,6 +39,9 @@ struct sh_pfc {
        unsigned int num_windows;
        struct sh_pfc_window *window;
 
+       struct sh_pfc_pin_range *ranges;
+       unsigned int nr_ranges;
+
        unsigned int nr_gpio_pins;
 
        struct sh_pfc_chip *gpio;
index 7661be5054a00938fbcedc21a318184e484e2828..78fcb8029afdad2af6376cfa3354f56c7035600f 100644 (file)
@@ -334,10 +334,7 @@ sh_pfc_add_gpiochip(struct sh_pfc *pfc, int(*setup)(struct sh_pfc_chip *),
 
 int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
 {
-       const struct pinmux_range *ranges;
-       struct pinmux_range def_range;
        struct sh_pfc_chip *chip;
-       unsigned int nr_ranges;
        unsigned int i;
        int ret;
 
@@ -368,23 +365,13 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
        pfc->gpio = chip;
 
        /* Register the GPIO to pin mappings. */
-       if (pfc->info->ranges == NULL) {
-               def_range.begin = 0;
-               def_range.end = pfc->info->nr_pins - 1;
-               ranges = &def_range;
-               nr_ranges = 1;
-       } else {
-               ranges = pfc->info->ranges;
-               nr_ranges = pfc->info->nr_ranges;
-       }
-
-       for (i = 0; i < nr_ranges; ++i) {
-               const struct pinmux_range *range = &ranges[i];
+       for (i = 0; i < pfc->nr_ranges; ++i) {
+               const struct sh_pfc_pin_range *range = &pfc->ranges[i];
 
                ret = gpiochip_add_pin_range(&chip->gpio_chip,
                                             dev_name(pfc->dev),
-                                            range->begin, range->begin,
-                                            range->end - range->begin + 1);
+                                            range->start, range->start,
+                                            range->end - range->start + 1);
                if (ret < 0)
                        return ret;
        }
index 04ecb5e9e18ec12355afc162b159b6ffdb81113e..05d96ae36fca7c379be01e15887ae15cae2ba60b 100644 (file)
@@ -1398,20 +1398,6 @@ static struct sh_pfc_pin pinmux_pins[] = {
        R8A73A4_PIN_IO_PU_PD(328), R8A73A4_PIN_IO_PU_PD(329),
 };
 
-static const struct pinmux_range pinmux_ranges[] = {
-       {.begin = 0, .end = 30,},
-       {.begin = 32, .end = 40,},
-       {.begin = 64, .end = 85,},
-       {.begin = 96, .end = 126,},
-       {.begin = 128, .end = 134,},
-       {.begin = 160, .end = 178,},
-       {.begin = 192, .end = 222,},
-       {.begin = 224, .end = 250,},
-       {.begin = 256, .end = 283,},
-       {.begin = 288, .end = 308,},
-       {.begin = 320, .end = 329,},
-};
-
 /* - IRQC ------------------------------------------------------------------- */
 #define IRQC_PINS_MUX(pin, irq_mark)                           \
 static const unsigned int irqc_irq##irq_mark##_pins[] = {      \
@@ -2756,9 +2742,6 @@ const struct sh_pfc_soc_info r8a73a4_pinmux_info = {
        .pins = pinmux_pins,
        .nr_pins = ARRAY_SIZE(pinmux_pins),
 
-       .ranges = pinmux_ranges,
-       .nr_ranges = ARRAY_SIZE(pinmux_ranges),
-
        .groups = pinmux_groups,
        .nr_groups = ARRAY_SIZE(pinmux_groups),
        .functions = pinmux_functions,
index acf83921d75b141cf0063bb39896702a13405974..1f4dbe45737a86651329a20eff79708807a8b501 100644 (file)
@@ -1446,13 +1446,6 @@ static struct sh_pfc_pin pinmux_pins[] = {
        SH73A0_PIN_O(309),
 };
 
-static const struct pinmux_range pinmux_ranges[] = {
-       {.begin = 0, .end = 118,},
-       {.begin = 128, .end = 164,},
-       {.begin = 192, .end = 282,},
-       {.begin = 288, .end = 309,},
-};
-
 /* Pin numbers for pins without a corresponding GPIO port number are computed
  * from the row and column numbers with a 1000 offset to avoid collisions with
  * GPIO port numbers.
@@ -3894,8 +3887,6 @@ const struct sh_pfc_soc_info sh73a0_pinmux_info = {
 
        .pins = pinmux_pins,
        .nr_pins = ARRAY_SIZE(pinmux_pins),
-       .ranges = pinmux_ranges,
-       .nr_ranges = ARRAY_SIZE(pinmux_ranges),
        .groups = pinmux_groups,
        .nr_groups = ARRAY_SIZE(pinmux_groups),
        .functions = pinmux_functions,
index 314255d79bff820b20031a4f32b32ab31f532880..8649ec3910a3e1c8be863340468e94ada76954c5 100644 (file)
@@ -587,22 +587,9 @@ static const struct pinconf_ops sh_pfc_pinconf_ops = {
 /* PFC ranges -> pinctrl pin descs */
 static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
 {
-       const struct pinmux_range *ranges;
-       struct pinmux_range def_range;
-       unsigned int nr_ranges;
-       unsigned int nr_pins;
        unsigned int i;
 
-       if (pfc->info->ranges == NULL) {
-               def_range.begin = 0;
-               def_range.end = pfc->info->nr_pins - 1;
-               ranges = &def_range;
-               nr_ranges = 1;
-       } else {
-               ranges = pfc->info->ranges;
-               nr_ranges = pfc->info->nr_ranges;
-       }
-
+       /* Allocate and initialize the pins and configs arrays. */
        pmx->pins = devm_kzalloc(pfc->dev,
                                 sizeof(*pmx->pins) * pfc->info->nr_pins,
                                 GFP_KERNEL);
@@ -615,32 +602,24 @@ static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
        if (unlikely(!pmx->configs))
                return -ENOMEM;
 
-       for (i = 0, nr_pins = 0; i < nr_ranges; ++i) {
-               const struct pinmux_range *range = &ranges[i];
-               unsigned int number;
+       for (i = 0; i < pfc->info->nr_pins; ++i) {
+               const struct sh_pfc_pin *info = &pfc->info->pins[i];
+               struct sh_pfc_pin_config *cfg = &pmx->configs[i];
+               struct pinctrl_pin_desc *pin = &pmx->pins[i];
 
-               for (number = range->begin; number <= range->end;
-                    number++, nr_pins++) {
-                       struct sh_pfc_pin_config *cfg = &pmx->configs[nr_pins];
-                       struct pinctrl_pin_desc *pin = &pmx->pins[nr_pins];
-                       const struct sh_pfc_pin *info =
-                               &pfc->info->pins[nr_pins];
-
-                       pin->number = number;
-                       pin->name = info->name;
-                       cfg->type = PINMUX_TYPE_NONE;
-               }
+               /* If the pin number is equal to -1 all pins are considered */
+               pin->number = info->pin != (u16)-1 ? info->pin : i;
+               pin->name = info->name;
+               cfg->type = PINMUX_TYPE_NONE;
        }
 
-       pfc->nr_gpio_pins = ranges[nr_ranges-1].end + 1;
-
-       return nr_ranges;
+       return 0;
 }
 
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
 {
        struct sh_pfc_pinctrl *pmx;
-       int nr_ranges;
+       int ret;
 
        pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL);
        if (unlikely(!pmx))
@@ -649,9 +628,9 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
        pmx->pfc = pfc;
        pfc->pinctrl = pmx;
 
-       nr_ranges = sh_pfc_map_pins(pfc, pmx);
-       if (unlikely(nr_ranges < 0))
-               return nr_ranges;
+       ret = sh_pfc_map_pins(pfc, pmx);
+       if (ret < 0)
+               return ret;
 
        pmx->pctl_desc.name = DRV_NAME;
        pmx->pctl_desc.owner = THIS_MODULE;
index 839e69548a2cc0d52dc80a7acde92ae40a3d0e8e..2469b35cfda7f57d1e521aa8a98813cd7425280a 100644 (file)
@@ -125,8 +125,6 @@ struct sh_pfc_soc_info {
 
        const struct sh_pfc_pin *pins;
        unsigned int nr_pins;
-       const struct pinmux_range *ranges;
-       unsigned int nr_ranges;
        const struct sh_pfc_pin_group *groups;
        unsigned int nr_groups;
        const struct sh_pfc_function *functions;