[PATCH v8 3/3] pinctrl: nuvoton: Add ma35d1 pinctrl and GPIO driver

Jacky Huang ychuang570808 at gmail.com
Wed May 8 02:38:35 PDT 2024


Dear Christophe,

Thanks for the review.


On 2024/5/8 下午 04:38, Christophe JAILLET wrote:
> Le 08/05/2024 à 08:51, Jacky Huang a écrit :
>> From: Jacky Huang <ychuang3 at nuvoton.com>
>>
>> Add common pinctrl and GPIO driver for Nuvoton MA35 series SoC, and
>> add support for ma35d1 pinctrl.
>>
>> Signed-off-by: Jacky Huang <ychuang3 at nuvoton.com>
>> ---
>
> ...
>
>> +static int ma35_gpiolib_register(struct platform_device *pdev, 
>> struct ma35_pinctrl *npctl)
>> +{
>> +    struct ma35_pin_ctrl *ctrl = npctl->ctrl;
>> +    struct ma35_pin_bank *bank = ctrl->pin_banks;
>> +    int ret;
>> +    int i;
>> +
>> +    for (i = 0; i < ctrl->nr_banks; i++, bank++) {
>> +        if (!bank->valid) {
>> +            dev_warn(&pdev->dev, "%pfw: bank is not valid\n", 
>> bank->fwnode);
>> +            continue;
>> +        }
>> +        bank->irqtype = 0;
>> +        bank->irqinten = 0;
>> +        bank->chip.label = bank->name;
>> +        bank->chip.of_gpio_n_cells = 2;
>> +        bank->chip.parent = &pdev->dev;
>> +        bank->chip.request = ma35_gpio_core_to_request;
>> +        bank->chip.direction_input = ma35_gpio_core_direction_in;
>> +        bank->chip.direction_output = ma35_gpio_core_direction_out;
>> +        bank->chip.get = ma35_gpio_core_get;
>> +        bank->chip.set = ma35_gpio_core_set;
>> +        bank->chip.base = -1;
>> +        bank->chip.ngpio = bank->nr_pins;
>> +        bank->chip.can_sleep = false;
>> +
>> +        if (bank->irq > 0) {
>> +            struct gpio_irq_chip *girq;
>> +
>> +            girq = &bank->chip.irq;
>> +            gpio_irq_chip_set_chip(girq, &ma35_gpio_irqchip);
>> +            girq->parent_handler = ma35_irq_demux_intgroup;
>> +            girq->num_parents = 1;
>> +
>> +            girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
>> +                             sizeof(*girq->parents), GFP_KERNEL);
>> +            if (!girq->parents) {
>> +                ret = -ENOMEM;
>> +                goto fail;
>> +            }
>> +
>> +            girq->parents[0] = bank->irq;
>> +            girq->default_type = IRQ_TYPE_NONE;
>> +            girq->handler = handle_bad_irq;
>> +        }
>> +
>> +        ret = devm_gpiochip_add_data(&pdev->dev, &bank->chip, bank);
>> +        if (ret) {
>> +            dev_err(&pdev->dev, "failed to register gpio_chip %s, 
>> error code: %d\n",
>> +                bank->chip.label, ret);
>> +            goto fail;
>> +        }
>> +    }
>> +    return 0;
>> +
>> +fail:
>> +    while (i--) {
>> +        bank--;
>> +        if (!bank->valid)
>> +            continue;
>> +        gpiochip_remove(&bank->chip);
>> +    }
>
> I don't think this is correct. This is to undo the 
> devm_gpiochip_add_data(), right?
> Because of the devm_, no need to explicityl call gpiochip_remove()
>
> (more over, it should have been --i and not i-- in the while)
>

Yes, I will just drop the whole "fail:" case and  make it return from 
"goto fail" with the error code.

>> +    return ret;
>> +}
>
> ...
>
>> +static int ma35_pinconf_set_drive_strength(struct ma35_pinctrl 
>> *npctl, unsigned int pin,
>> +                       int strength)
>> +{
>> +    unsigned int port, group_num;
>> +    void __iomem *base;
>> +    int i, ds_val = -1;
>> +    u32 regval;
>> +
>> +    if (ma35_pinconf_get_power_source(npctl, pin) == MVOLT_1800) {
>> +        for (i = 0; i < ARRAY_SIZE(ds_1800mv_tbl); i++) {
>> +            if (ds_1800mv_tbl[i] == strength) {
>> +                ds_val = i;
>> +                break;
>> +            }
>> +        }
>> +    } else {
>> +        for (i = 0; i < ARRAY_SIZE(ds_3300mv_tbl); i++) {
>> +            if (ds_3300mv_tbl[i] == strength) {
>> +                ds_val = i;
>> +                continue;
>
> break; ?

I will fix it.

>
>> +            }
>> +        }
>> +    }
>> +    if (ds_val == -1)
>> +        return -EINVAL;
>> +
>> +    ma35_gpio_cla_port(pin, &group_num, &port);
>> +    base = npctl->ctrl->pin_banks[group_num].reg_base;
>> +
>> +    regval = readl(base + MA35_GP_DS_REG(port));
>> +    regval &= ~MA35_GP_DS_MASK(port);
>> +    regval |= field_prep(MA35_GP_DS_MASK(port), ds_val);
>> +
>> +    writel(regval, base + MA35_GP_DS_REG(port));
>> +
>> +    return 0;
>> +}
>
> ...
>
>> +static int ma35_pinctrl_probe_dt(struct platform_device *pdev, 
>> struct ma35_pinctrl *npctl)
>> +{
>> +    struct fwnode_handle *child;
>> +    u32 idx = 0;
>> +    int ret;
>> +
>> +    device_for_each_child_node(&pdev->dev, child) {
>> +        if (fwnode_property_present(child, "gpio-controller"))
>> +            continue;
>> +        npctl->nfunctions++;
>> +        npctl->ngroups += of_get_child_count(to_of_node(child));
>> +    }
>> +
>> +    if (!npctl->nfunctions)
>> +        return -EINVAL;
>> +
>> +    npctl->functions = devm_kcalloc(&pdev->dev, npctl->nfunctions,
>> +                    sizeof(*npctl->functions), GFP_KERNEL);
>> +    if (!npctl->functions)
>> +        return -ENOMEM;
>> +
>> +    npctl->groups = devm_kcalloc(&pdev->dev, npctl->ngroups,
>> +                     sizeof(*npctl->groups), GFP_KERNEL);
>> +    if (!npctl->groups)
>> +        return -ENOMEM;
>> +
>> +    device_for_each_child_node(&pdev->dev, child) {
>> +        if (fwnode_property_present(child, "gpio-controller"))
>> +            continue;
>> +
>> +        ret = ma35_pinctrl_parse_functions(to_of_node(child), npctl, 
>> idx++);
>> +        if (ret) {
>> +            dev_err(&pdev->dev, "failed to parse function\n");
>
> Missing fwnode_handle_put(child); ?
> (or a scoped version of device_for_each_child_node() if it exists)
>

Yes, I will add fwnode_handle_put(child) here.

>> +            return ret;
>> +        }
>> +    }
>> +    return 0;
>> +
>
> ...
>
> CJ

Best Regards,
Jacky Huang




More information about the linux-arm-kernel mailing list