lkml.org 
[lkml]   [2021]   [Dec]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v1 pinctrl-next 1/1] pinctrl: microchip-sgpio: add activity and blink functionality
    Date
    Add additional functions - two blink and two activity, for each SGPIO
    output.

    Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
    ---
    drivers/pinctrl/pinctrl-microchip-sgpio.c | 135 +++++++++++++++++++++-
    1 file changed, 130 insertions(+), 5 deletions(-)

    diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c
    index 8e081c90bdb2..e3230e5dedc0 100644
    --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c
    +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c
    @@ -51,6 +51,15 @@ enum {
    SGPIO_FLAGS_HAS_IRQ = BIT(0),
    };

    +enum {
    + FUNC_GPIO,
    + FUNC_BLINK0,
    + FUNC_BLINK1,
    + FUNC_ACTIVITY0,
    + FUNC_ACTIVITY1,
    + FUNC_MAX,
    +};
    +
    struct sgpio_properties {
    int arch;
    int flags;
    @@ -60,16 +69,22 @@ struct sgpio_properties {
    #define SGPIO_LUTON_AUTO_REPEAT BIT(5)
    #define SGPIO_LUTON_PORT_WIDTH GENMASK(3, 2)
    #define SGPIO_LUTON_CLK_FREQ GENMASK(11, 0)
    +#define SGPIO_LUTON_SIO_BMODE_0 GENMASK(21, 20)
    +#define SGPIO_LUTON_SIO_BMODE_1 GENMASK(19, 18)
    #define SGPIO_LUTON_BIT_SOURCE GENMASK(11, 0)

    #define SGPIO_OCELOT_AUTO_REPEAT BIT(10)
    #define SGPIO_OCELOT_PORT_WIDTH GENMASK(8, 7)
    #define SGPIO_OCELOT_CLK_FREQ GENMASK(19, 8)
    +#define SGPIO_OCELOT_SIO_BMODE_0 GENMASK(20, 19)
    +#define SGPIO_OCELOT_SIO_BMODE_1 GENMASK(22, 21)
    #define SGPIO_OCELOT_BIT_SOURCE GENMASK(23, 12)

    #define SGPIO_SPARX5_AUTO_REPEAT BIT(6)
    #define SGPIO_SPARX5_PORT_WIDTH GENMASK(4, 3)
    #define SGPIO_SPARX5_CLK_FREQ GENMASK(19, 8)
    +#define SGPIO_SPARX5_SIO_BMODE_0 GENMASK(16, 15)
    +#define SGPIO_SPARX5_SIO_BMODE_1 GENMASK(18, 17)
    #define SGPIO_SPARX5_BIT_SOURCE GENMASK(23, 12)

    #define SGPIO_MASTER_INTR_ENA BIT(0)
    @@ -98,22 +113,46 @@ static const struct sgpio_properties properties_sparx5 = {
    .regoff = { 0x00, 0x06, 0x26, 0x04, 0x05, 0x2a, 0x32, 0x3a, 0x3e, 0x42 },
    };

    -static const char * const functions[] = { "gpio" };
    +static const char * const function_names[] = {
    + [FUNC_GPIO] = "gpio",
    + [FUNC_BLINK0] = "blink0",
    + [FUNC_BLINK1] = "blink1",
    + [FUNC_ACTIVITY0] = "activity0",
    + [FUNC_ACTIVITY1] = "activity1",
    +};
    +
    +static const int function_values[] = {
    + [FUNC_GPIO] = 0,
    + [FUNC_BLINK0] = 2,
    + [FUNC_BLINK1] = 3,
    + [FUNC_ACTIVITY0] = 4,
    + [FUNC_ACTIVITY1] = 5,
    +};
    +
    +struct sgpio_pmx_func {
    + const char **groups;
    + unsigned int ngroups;
    +};

    struct sgpio_bank {
    struct sgpio_priv *priv;
    bool is_input;
    struct gpio_chip gpio;
    struct pinctrl_desc pctl_desc;
    + struct sgpio_pmx_func func[FUNC_MAX];
    + struct pinctrl_pin_desc *pins;
    };

    struct sgpio_priv {
    struct device *dev;
    struct sgpio_bank in;
    struct sgpio_bank out;
    + int ngpios;
    u32 bitcount;
    u32 ports;
    u32 clock;
    + u32 bmode0;
    + u32 bmode1;
    struct regmap *regs;
    const struct sgpio_properties *properties;
    };
    @@ -223,6 +262,32 @@ static inline void sgpio_configure_clock(struct sgpio_priv *priv, u32 clkfrq)
    sgpio_clrsetbits(priv, REG_SIO_CLOCK, 0, clr, set);
    }

    +static inline void sgpio_configure_blink_modes(struct sgpio_priv *priv)
    +{
    + u32 clr, set;
    +
    + switch (priv->properties->arch) {
    + case SGPIO_ARCH_LUTON:
    + clr = SGPIO_LUTON_SIO_BMODE_0 | SGPIO_LUTON_SIO_BMODE_1;
    + set = FIELD_PREP(SGPIO_LUTON_SIO_BMODE_0, priv->bmode0) |
    + FIELD_PREP(SGPIO_LUTON_SIO_BMODE_1, priv->bmode1);
    + break;
    + case SGPIO_ARCH_OCELOT:
    + clr = SGPIO_OCELOT_SIO_BMODE_0 | SGPIO_OCELOT_SIO_BMODE_1;
    + set = FIELD_PREP(SGPIO_OCELOT_SIO_BMODE_0, priv->bmode0) |
    + FIELD_PREP(SGPIO_OCELOT_SIO_BMODE_1, priv->bmode1);
    + break;
    + case SGPIO_ARCH_SPARX5:
    + clr = SGPIO_SPARX5_SIO_BMODE_0 | SGPIO_SPARX5_SIO_BMODE_1;
    + set = FIELD_PREP(SGPIO_SPARX5_SIO_BMODE_0, priv->bmode0) |
    + FIELD_PREP(SGPIO_SPARX5_SIO_BMODE_1, priv->bmode1);
    + break;
    + default:
    + return;
    + }
    + sgpio_clrsetbits(priv, REG_SIO_CONFIG, 0, clr, set);
    +}
    +
    static void sgpio_output_set(struct sgpio_priv *priv,
    struct sgpio_port_addr *addr,
    int value)
    @@ -352,13 +417,18 @@ static const struct pinconf_ops sgpio_confops = {

    static int sgpio_get_functions_count(struct pinctrl_dev *pctldev)
    {
    - return 1;
    + struct sgpio_bank *bank = pinctrl_dev_get_drvdata(pctldev);
    +
    + if (bank->is_input)
    + return 1;
    + else
    + return ARRAY_SIZE(function_names);
    }

    static const char *sgpio_get_function_name(struct pinctrl_dev *pctldev,
    unsigned int function)
    {
    - return functions[0];
    + return function_names[function];
    }

    static int sgpio_get_function_groups(struct pinctrl_dev *pctldev,
    @@ -366,8 +436,10 @@ static int sgpio_get_function_groups(struct pinctrl_dev *pctldev,
    const char *const **groups,
    unsigned *const num_groups)
    {
    - *groups = functions;
    - *num_groups = ARRAY_SIZE(functions);
    + struct sgpio_bank *bank = pinctrl_dev_get_drvdata(pctldev);
    +
    + *groups = bank->func[function].groups;
    + *num_groups = bank->func[function].ngroups;

    return 0;
    }
    @@ -375,6 +447,15 @@ static int sgpio_get_function_groups(struct pinctrl_dev *pctldev,
    static int sgpio_pinmux_set_mux(struct pinctrl_dev *pctldev,
    unsigned int selector, unsigned int group)
    {
    + struct sgpio_bank *bank = pinctrl_dev_get_drvdata(pctldev);
    + struct sgpio_priv *priv = bank->priv;
    + struct sgpio_port_addr addr;
    + int f;
    +
    + f = function_values[selector];
    + sgpio_pin_to_addr(priv, group, &addr);
    + sgpio_output_set(priv, &addr, f);
    +
    return 0;
    }

    @@ -693,6 +774,30 @@ static void sgpio_irq_handler(struct irq_desc *desc)
    }
    }

    +static int sgpio_create_group_func_map(struct device *dev,
    + struct sgpio_bank *bank)
    +{
    + struct sgpio_priv *priv = bank->priv;
    + int f, i;
    +
    + if (bank->is_input)
    + return 0;
    +
    + for (f = 0; f < FUNC_MAX; f++) {
    + bank->func[f].ngroups = priv->ngpios;
    + bank->func[f].groups = devm_kcalloc(dev, priv->ngpios,
    + sizeof(char *), GFP_KERNEL);
    +
    + if (!bank->func[f].groups)
    + return -ENOMEM;
    +
    + for (i = 0; i < priv->ngpios; i++)
    + bank->func[f].groups[i] = bank->pins[i].name;
    + }
    +
    + return 0;
    +}
    +
    static int microchip_sgpio_register_bank(struct device *dev,
    struct sgpio_priv *priv,
    struct fwnode_handle *fwnode,
    @@ -716,6 +821,7 @@ static int microchip_sgpio_register_bank(struct device *dev,
    ngpios = 64;
    }

    + priv->ngpios = ngpios;
    priv->bitcount = ngpios / SGPIO_BITS_PER_WORD;
    if (priv->bitcount > SGPIO_MAX_BITS) {
    dev_err(dev, "Bit width exceeds maximum (%d)\n",
    @@ -738,6 +844,7 @@ static int microchip_sgpio_register_bank(struct device *dev,

    pctl_desc->npins = ngpios;
    pctl_desc->pins = pins;
    + bank->pins = pins;

    for (i = 0; i < ngpios; i++) {
    struct sgpio_port_addr addr;
    @@ -753,6 +860,12 @@ static int microchip_sgpio_register_bank(struct device *dev,
    return -ENOMEM;
    }

    + ret = sgpio_create_group_func_map(dev, bank);
    + if (ret) {
    + dev_err(dev, "Unable to create group func map.\n");
    + return ret;
    + }
    +
    pctldev = devm_pinctrl_register(dev, pctl_desc, bank);
    if (IS_ERR(pctldev))
    return dev_err_probe(dev, PTR_ERR(pctldev), "Failed to register pinctrl\n");
    @@ -895,6 +1008,18 @@ static int microchip_sgpio_probe(struct platform_device *pdev)
    sgpio_writel(priv, 0, REG_PORT_CONFIG, port);
    sgpio_writel(priv, priv->ports, REG_PORT_ENABLE, 0);

    + /*
    + * The datasheet and register definitions contradict themselves, at
    + * least for the VSC7512. The Datasheet Revision 4.2 describes both
    + * default blink modes as 20 Hz, but the registers show the default
    + * blink mode 0 as 5 Hz. Two identical blink modes aren't very useful,
    + * so override BMODE_0 here to match the 5Hz "default" described in the
    + * register map.
    + */
    + if (priv->properties->arch == SGPIO_ARCH_OCELOT)
    + priv->bmode0 = 2;
    + sgpio_configure_blink_modes(priv);
    +
    return 0;
    }

    --
    2.25.1
    \
     
     \ /
      Last update: 2021-12-29 01:38    [W:3.669 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site