lkml.org 
[lkml]   [2021]   [Nov]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH v4 net-next 13/23] pinctrl: ocelot: expose ocelot_pinctrl_core_probe interface
    Date
    This is step 2 to allow a custom regmap interface into the driver. This
    will allow regmaps that use other interfaces to fully utilize the pinctrl
    features.

    Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
    ---
    drivers/pinctrl/pinctrl-ocelot.c | 150 ++++++++++++++++++++-----------
    include/soc/mscc/ocelot.h | 18 ++++
    2 files changed, 118 insertions(+), 50 deletions(-)

    diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
    index b9acb80d6b3f..f8d2494b335c 100644
    --- a/drivers/pinctrl/pinctrl-ocelot.c
    +++ b/drivers/pinctrl/pinctrl-ocelot.c
    @@ -25,9 +25,6 @@
    #include "pinconf.h"
    #include "pinmux.h"

    -#define ocelot_clrsetbits(addr, clear, set) \
    - writel((readl(addr) & ~(clear)) | (set), (addr))
    -
    /* PINCONFIG bits (sparx5 only) */
    enum {
    PINCONF_BIAS,
    @@ -35,6 +32,9 @@ enum {
    PINCONF_DRIVE_STRENGTH,
    };

    +#define ocelot_pinctrl_determine_stride(desc) \
    + (1 + (desc->npins - 1) / 32)
    +
    #define BIAS_PD_BIT BIT(4)
    #define BIAS_PU_BIT BIT(3)
    #define BIAS_BITS (BIAS_PD_BIT|BIAS_PU_BIT)
    @@ -149,10 +149,13 @@ struct ocelot_pin_caps {

    struct ocelot_pinctrl {
    struct device *dev;
    + struct device_node *node;
    struct pinctrl_dev *pctl;
    struct gpio_chip gpio_chip;
    struct regmap *map;
    + u32 regmap_offset;
    struct regmap *pincfg;
    + u32 pincfg_offset;
    struct pinctrl_desc *desc;
    struct ocelot_pmx_func func[FUNC_MAX];
    u8 stride;
    @@ -714,7 +717,8 @@ static int ocelot_pin_function_idx(struct ocelot_pinctrl *info,
    return -1;
    }

    -#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->stride * ((p) / 32))))
    +#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + \
    + ((info)->stride * ((p) / 32))) + (info)->regmap_offset)

    static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
    unsigned int selector, unsigned int group)
    @@ -744,7 +748,8 @@ static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
    return 0;
    }

    -#define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32)))
    +#define REG(r, info, p) (((r) * (info)->stride + (4 * ((p) / 32))) + \
    + (info)->regmap_offset)

    static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev,
    struct pinctrl_gpio_range *range,
    @@ -766,10 +771,8 @@ static int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev,
    struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
    unsigned int p = offset % 32;

    - regmap_update_bits(info->map, REG_ALT(0, info, offset),
    - BIT(p), 0);
    - regmap_update_bits(info->map, REG_ALT(1, info, offset),
    - BIT(p), 0);
    + regmap_update_bits(info->map, REG_ALT(0, info, offset), BIT(p), 0);
    + regmap_update_bits(info->map, REG_ALT(1, info, offset), BIT(p), 0);

    return 0;
    }
    @@ -821,11 +824,11 @@ static int ocelot_hw_get_value(struct ocelot_pinctrl *info,
    if (info->pincfg) {
    u32 regcfg;

    - ret = regmap_read(info->pincfg, pin, &regcfg);
    + ret = regmap_read(info->pincfg, pin + info->pincfg_offset,
    + &regcfg);
    if (ret)
    return ret;

    - ret = 0;
    switch (reg) {
    case PINCONF_BIAS:
    *val = regcfg & BIAS_BITS;
    @@ -853,14 +856,14 @@ static int ocelot_pincfg_clrsetbits(struct ocelot_pinctrl *info, u32 regaddr,
    u32 val;
    int ret;

    - ret = regmap_read(info->pincfg, regaddr, &val);
    + ret = regmap_read(info->pincfg, regaddr + info->pincfg_offset, &val);
    if (ret)
    return ret;

    val &= ~clrbits;
    val |= setbits;

    - ret = regmap_write(info->pincfg, regaddr, val);
    + ret = regmap_write(info->pincfg, regaddr + info->pincfg_offset, val);

    return ret;
    }
    @@ -873,7 +876,6 @@ static int ocelot_hw_set_value(struct ocelot_pinctrl *info,
    int ret = -EOPNOTSUPP;

    if (info->pincfg) {
    -
    ret = 0;
    switch (reg) {
    case PINCONF_BIAS:
    @@ -1019,15 +1021,16 @@ static int ocelot_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
    if (arg)
    regmap_write(info->map,
    REG(OCELOT_GPIO_OUT_SET, info,
    - pin),
    + pin) + info->regmap_offset,
    BIT(p));
    else
    regmap_write(info->map,
    REG(OCELOT_GPIO_OUT_CLR, info,
    - pin),
    + pin) + info->regmap_offset,
    BIT(p));
    regmap_update_bits(info->map,
    - REG(OCELOT_GPIO_OE, info, pin),
    + REG(OCELOT_GPIO_OE, info, pin) +
    + info->regmap_offset,
    BIT(p),
    param == PIN_CONFIG_INPUT_ENABLE ?
    0 : BIT(p));
    @@ -1138,20 +1141,20 @@ static int ocelot_create_group_func_map(struct device *dev,
    return 0;
    }

    -static int ocelot_pinctrl_register(struct platform_device *pdev,
    +static int ocelot_pinctrl_register(struct device *dev,
    struct ocelot_pinctrl *info)
    {
    int ret;

    - ret = ocelot_create_group_func_map(&pdev->dev, info);
    + ret = ocelot_create_group_func_map(dev, info);
    if (ret) {
    - dev_err(&pdev->dev, "Unable to create group func map.\n");
    + dev_err(dev, "Unable to create group func map.\n");
    return ret;
    }

    - info->pctl = devm_pinctrl_register(&pdev->dev, info->desc, info);
    + info->pctl = devm_pinctrl_register(dev, info->desc, info);
    if (IS_ERR(info->pctl)) {
    - dev_err(&pdev->dev, "Failed to register pinctrl\n");
    + dev_err(dev, "Failed to register pinctrl\n");
    return PTR_ERR(info->pctl);
    }

    @@ -1320,7 +1323,7 @@ static void ocelot_irq_handler(struct irq_desc *desc)
    }
    }

    -static int ocelot_gpiochip_register(struct platform_device *pdev,
    +static int ocelot_gpiochip_register(struct device *dev,
    struct ocelot_pinctrl *info)
    {
    struct gpio_chip *gc;
    @@ -1331,7 +1334,7 @@ static int ocelot_gpiochip_register(struct platform_device *pdev,

    gc = &info->gpio_chip;
    gc->ngpio = info->desc->npins;
    - gc->parent = &pdev->dev;
    + gc->parent = dev;
    gc->base = -1;
    gc->of_node = info->dev->of_node;
    gc->label = "ocelot-gpio";
    @@ -1342,8 +1345,7 @@ static int ocelot_gpiochip_register(struct platform_device *pdev,
    girq->chip = &ocelot_irqchip;
    girq->parent_handler = ocelot_irq_handler;
    girq->num_parents = 1;
    - girq->parents = devm_kcalloc(&pdev->dev, 1,
    - sizeof(*girq->parents),
    + girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
    GFP_KERNEL);
    if (!girq->parents)
    return -ENOMEM;
    @@ -1352,7 +1354,7 @@ static int ocelot_gpiochip_register(struct platform_device *pdev,
    girq->handler = handle_edge_irq;
    }

    - return devm_gpiochip_add_data(&pdev->dev, gc, info);
    + return devm_gpiochip_add_data(dev, gc, info);
    }

    static const struct of_device_id ocelot_pinctrl_of_match[] = {
    @@ -1384,56 +1386,104 @@ static struct regmap *ocelot_pinctrl_create_pincfg(struct platform_device *pdev)
    return devm_regmap_init_mmio(&pdev->dev, base, &regmap_config);
    }

    +static struct pinctrl_desc
    +*ocelot_pinctrl_match_from_node(struct device_node *device_node)
    +{
    + const struct of_device_id *match;
    +
    + match = of_match_node(of_match_ptr(ocelot_pinctrl_of_match),
    + device_node);
    +
    + if (match)
    + return (struct pinctrl_desc *)match->data;
    +
    + return NULL;
    +}
    +
    +int ocelot_pinctrl_core_probe(struct device *dev,
    + struct pinctrl_desc *pinctrl_desc,
    + struct regmap *regmap_base, u32 regmap_offset,
    + struct regmap *pincfg_base, u32 pincfg_offset,
    + struct device_node *device_node)
    +{
    + struct ocelot_pinctrl *info;
    + int ret;
    +
    + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
    + if (!info)
    + return -ENOMEM;
    +
    + if (!pinctrl_desc)
    + pinctrl_desc = ocelot_pinctrl_match_from_node(device_node);
    + if (!pinctrl_desc) {
    + dev_err(dev, "Failed to find device match\n");
    + return -ENODEV;
    + }
    +
    + info->desc = pinctrl_desc;
    + info->stride = ocelot_pinctrl_determine_stride(info->desc);
    + info->dev = dev;
    + info->node = device_node;
    + info->map = regmap_base;
    + info->pincfg = pincfg_base;
    + info->regmap_offset = regmap_offset;
    + info->pincfg_offset = pincfg_offset;
    +
    + ret = ocelot_pinctrl_register(dev, info);
    + if (ret)
    + return ret;
    +
    + ret = ocelot_gpiochip_register(dev, info);
    + if (ret)
    + return ret;
    +
    + return 0;
    +}
    +EXPORT_SYMBOL(ocelot_pinctrl_core_probe);
    +
    static int ocelot_pinctrl_probe(struct platform_device *pdev)
    {
    + struct pinctrl_desc *pinctrl_desc;
    struct device *dev = &pdev->dev;
    - struct ocelot_pinctrl *info;
    + struct regmap *regmap;
    struct regmap *pincfg;
    void __iomem *base;
    - int ret;
    + int ret, stride;
    struct regmap_config regmap_config = {
    .reg_bits = 32,
    .val_bits = 32,
    .reg_stride = 4,
    };

    - info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
    - if (!info)
    - return -ENOMEM;
    -
    - info->desc = (struct pinctrl_desc *)device_get_match_data(dev);
    + pinctrl_desc = (struct pinctrl_desc *)device_get_match_data(dev);

    base = devm_ioremap_resource(dev,
    platform_get_resource(pdev, IORESOURCE_MEM, 0));
    if (IS_ERR(base))
    return PTR_ERR(base);

    - info->stride = 1 + (info->desc->npins - 1) / 32;
    + stride = ocelot_pinctrl_determine_stride(pinctrl_desc);

    - regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4;
    + regmap_config.max_register = OCELOT_GPIO_SD_MAP * stride + 15 * 4;

    - info->map = devm_regmap_init_mmio(dev, base, &regmap_config);
    - if (IS_ERR(info->map)) {
    + regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
    + if (IS_ERR(regmap)) {
    dev_err(dev, "Failed to create regmap\n");
    - return PTR_ERR(info->map);
    + return PTR_ERR(regmap);
    }
    - dev_set_drvdata(dev, info->map);
    - info->dev = dev;
    + dev_set_drvdata(dev, regmap);

    /* Pinconf registers */
    - if (info->desc->confops) {
    + if (pinctrl_desc->confops) {
    pincfg = ocelot_pinctrl_create_pincfg(pdev);
    - if (IS_ERR(pincfg))
    + if (IS_ERR(pincfg)) {
    dev_dbg(dev, "Failed to create pincfg regmap\n");
    - else
    - info->pincfg = pincfg;
    + pincfg = NULL;
    + }
    }

    - ret = ocelot_pinctrl_register(pdev, info);
    - if (ret)
    - return ret;
    -
    - ret = ocelot_gpiochip_register(pdev, info);
    + ret = ocelot_pinctrl_core_probe(dev, pinctrl_desc, regmap, 0, pincfg, 0,
    + dev->of_node);
    if (ret)
    return ret;

    diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
    index 9a4ded4bff04..14acfe82d0a4 100644
    --- a/include/soc/mscc/ocelot.h
    +++ b/include/soc/mscc/ocelot.h
    @@ -6,6 +6,7 @@
    #define _SOC_MSCC_OCELOT_H

    #include <linux/ptp_clock_kernel.h>
    +#include <linux/pinctrl/pinctrl.h>
    #include <linux/net_tstamp.h>
    #include <linux/if_vlan.h>
    #include <linux/regmap.h>
    @@ -912,4 +913,21 @@ ocelot_mrp_del_ring_role(struct ocelot *ocelot, int port,
    }
    #endif

    +#if IS_ENABLED(CONFIG_PINCTRL_OCELOT)
    +int ocelot_pinctrl_core_probe(struct device *dev,
    + struct pinctrl_desc *pinctrl_desc,
    + struct regmap *regmap_base, u32 regmap_offset,
    + struct regmap *pincfg_base, u32 pincfg_offset,
    + struct device_node *device_node);
    +#else
    +int ocelot_pinctrl_core_probe(struct device *dev,
    + struct pinctrl_desc *pinctrl_desc,
    + struct regmap *regmap_base, u32 regmap_offset,
    + struct regmap *pincfg_base, u32 pincfg_offset,
    + struct device_node *device_node)
    +{
    + return -EOPNOTSUPP;
    +}
    +#endif
    +
    #endif
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-11-16 07:28    [W:4.449 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site