lkml.org 
[lkml]   [2022]   [Jul]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 3/3] mfd: atmel-flexcom: Add support for lan966x flexcom chip-select configuration
    Date
    LAN966x SoC have 5 flexcoms. Each flexcom has 2 chip-selects
    which are optional I/O lines. For each chip select of each
    flexcom there is a configuration register FLEXCOM_SHARED[0-4]:SS_MASK[0-1].
    The width of configuration register is 21 because there are
    21 shared pins on each of which the chip select can be mapped.
    Each bit of the register represents a different FLEXCOM_SHARED pin.

    Signed-off-by: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
    Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com>
    ---
    v5 -> v6:
    - No changes.

    v4 -> v5:
    - No changes.

    v3 -> v4:
    - Add condition for a flexcom whether to configure chip-select lines
    or not, based on "microchip,flx-shrd-pins" property existence because
    chip-select lines are optional.

    v2 -> v3:
    - used goto label for clk_disable in error cases.

    v1 -> v2:
    - use GENMASK for mask, macros for maximum allowed values.
    - use u32 values for flexcom chipselects instead of strings.
    - disable clock in case of errors.

    drivers/mfd/atmel-flexcom.c | 94 ++++++++++++++++++++++++++++++++++++-
    1 file changed, 93 insertions(+), 1 deletion(-)

    diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
    index 33caa4fba6af..430b6783b5a7 100644
    --- a/drivers/mfd/atmel-flexcom.c
    +++ b/drivers/mfd/atmel-flexcom.c
    @@ -28,15 +28,68 @@
    #define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) & \
    FLEX_MR_OPMODE_MASK)

    +/* LAN966x flexcom shared register offsets */
    +#define FLEX_SHRD_SS_MASK_0 0x0
    +#define FLEX_SHRD_SS_MASK_1 0x4
    +#define FLEX_SHRD_PIN_MAX 20
    +#define FLEX_CS_MAX 1
    +#define FLEX_SHRD_MASK GENMASK(20, 0)
    +
    +struct atmel_flex_caps {
    + bool has_flx_cs;
    +};
    +
    struct atmel_flexcom {
    void __iomem *base;
    + void __iomem *flexcom_shared_base;
    u32 opmode;
    struct clk *clk;
    };

    +static int atmel_flexcom_lan966x_cs_config(struct platform_device *pdev)
    +{
    + struct atmel_flexcom *ddata = dev_get_drvdata(&pdev->dev);
    + struct device_node *np = pdev->dev.of_node;
    + u32 flx_shrd_pins[2], flx_cs[2], val;
    + int err, i, count;
    +
    + count = of_property_count_u32_elems(np, "microchip,flx-shrd-pins");
    + if (count <= 0 || count > 2) {
    + dev_err(&pdev->dev, "Invalid %s property (%d)\n", "flx-shrd-pins",
    + count);
    + return -EINVAL;
    + }
    +
    + err = of_property_read_u32_array(np, "microchip,flx-shrd-pins", flx_shrd_pins, count);
    + if (err)
    + return err;
    +
    + err = of_property_read_u32_array(np, "microchip,flx-cs", flx_cs, count);
    + if (err)
    + return err;
    +
    + for (i = 0; i < count; i++) {
    + if (flx_shrd_pins[i] > FLEX_SHRD_PIN_MAX)
    + return -EINVAL;
    +
    + if (flx_cs[i] > FLEX_CS_MAX)
    + return -EINVAL;
    +
    + val = ~(1 << flx_shrd_pins[i]) & FLEX_SHRD_MASK;
    +
    + if (flx_cs[i] == 0)
    + writel(val, ddata->flexcom_shared_base + FLEX_SHRD_SS_MASK_0);
    + else
    + writel(val, ddata->flexcom_shared_base + FLEX_SHRD_SS_MASK_1);
    + }
    +
    + return 0;
    +}
    +
    static int atmel_flexcom_probe(struct platform_device *pdev)
    {
    struct device_node *np = pdev->dev.of_node;
    + const struct atmel_flex_caps *caps;
    struct resource *res;
    struct atmel_flexcom *ddata;
    int err;
    @@ -76,13 +129,52 @@ static int atmel_flexcom_probe(struct platform_device *pdev)
    */
    writel(FLEX_MR_OPMODE(ddata->opmode), ddata->base + FLEX_MR);

    + caps = of_device_get_match_data(&pdev->dev);
    + if (!caps) {
    + dev_err(&pdev->dev, "Could not retrieve flexcom caps\n");
    + err = -EINVAL;
    + goto clk_disable;
    + }
    +
    + if (caps->has_flx_cs && of_property_read_bool(np, "microchip,flx-shrd-pins")) {
    + ddata->flexcom_shared_base = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
    + if (IS_ERR(ddata->flexcom_shared_base)) {
    + err = dev_err_probe(&pdev->dev,
    + PTR_ERR(ddata->flexcom_shared_base),
    + "failed to get flexcom shared base address\n");
    + goto clk_disable;
    + }
    +
    + err = atmel_flexcom_lan966x_cs_config(pdev);
    + if (err)
    + goto clk_disable;
    + }
    +
    +clk_disable:
    clk_disable_unprepare(ddata->clk);
    + if (err)
    + return err;

    return devm_of_platform_populate(&pdev->dev);
    }

    +static const struct atmel_flex_caps atmel_flexcom_caps = {};
    +
    +static const struct atmel_flex_caps lan966x_flexcom_caps = {
    + .has_flx_cs = true,
    +};
    +
    static const struct of_device_id atmel_flexcom_of_match[] = {
    - { .compatible = "atmel,sama5d2-flexcom" },
    + {
    + .compatible = "atmel,sama5d2-flexcom",
    + .data = &atmel_flexcom_caps,
    + },
    +
    + {
    + .compatible = "microchip,lan966x-flexcom",
    + .data = &lan966x_flexcom_caps,
    + },
    +
    { /* sentinel */ }
    };
    MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match);
    --
    2.25.1
    \
     
     \ /
      Last update: 2022-07-05 09:00    [W:2.377 / U:0.912 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site