Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * 74xx MMIO GPIO driver
0004  *
0005  *  Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
0006  */
0007 
0008 #include <linux/bits.h>
0009 #include <linux/err.h>
0010 #include <linux/gpio/driver.h>
0011 #include <linux/mod_devicetable.h>
0012 #include <linux/module.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/property.h>
0015 
0016 #define MMIO_74XX_DIR_IN    BIT(8)
0017 #define MMIO_74XX_DIR_OUT   BIT(9)
0018 #define MMIO_74XX_BIT_CNT(x)    ((x) & GENMASK(7, 0))
0019 
0020 struct mmio_74xx_gpio_priv {
0021     struct gpio_chip    gc;
0022     unsigned        flags;
0023 };
0024 
0025 static const struct of_device_id mmio_74xx_gpio_ids[] = {
0026     {
0027         .compatible = "ti,741g125",
0028         .data       = (const void *)(MMIO_74XX_DIR_IN | 1),
0029     },
0030     {
0031         .compatible = "ti,742g125",
0032         .data       = (const void *)(MMIO_74XX_DIR_IN | 2),
0033     },
0034     {
0035         .compatible = "ti,74125",
0036         .data       = (const void *)(MMIO_74XX_DIR_IN | 4),
0037     },
0038     {
0039         .compatible = "ti,74365",
0040         .data       = (const void *)(MMIO_74XX_DIR_IN | 6),
0041     },
0042     {
0043         .compatible = "ti,74244",
0044         .data       = (const void *)(MMIO_74XX_DIR_IN | 8),
0045     },
0046     {
0047         .compatible = "ti,741624",
0048         .data       = (const void *)(MMIO_74XX_DIR_IN | 16),
0049     },
0050     {
0051         .compatible = "ti,741g74",
0052         .data       = (const void *)(MMIO_74XX_DIR_OUT | 1),
0053     },
0054     {
0055         .compatible = "ti,7474",
0056         .data       = (const void *)(MMIO_74XX_DIR_OUT | 2),
0057     },
0058     {
0059         .compatible = "ti,74175",
0060         .data       = (const void *)(MMIO_74XX_DIR_OUT | 4),
0061     },
0062     {
0063         .compatible = "ti,74174",
0064         .data       = (const void *)(MMIO_74XX_DIR_OUT | 6),
0065     },
0066     {
0067         .compatible = "ti,74273",
0068         .data       = (const void *)(MMIO_74XX_DIR_OUT | 8),
0069     },
0070     {
0071         .compatible = "ti,7416374",
0072         .data       = (const void *)(MMIO_74XX_DIR_OUT | 16),
0073     },
0074     { }
0075 };
0076 MODULE_DEVICE_TABLE(of, mmio_74xx_gpio_ids);
0077 
0078 static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned offset)
0079 {
0080     struct mmio_74xx_gpio_priv *priv = gpiochip_get_data(gc);
0081 
0082     if (priv->flags & MMIO_74XX_DIR_OUT)
0083         return GPIO_LINE_DIRECTION_OUT;
0084 
0085     return  GPIO_LINE_DIRECTION_IN;
0086 }
0087 
0088 static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio)
0089 {
0090     struct mmio_74xx_gpio_priv *priv = gpiochip_get_data(gc);
0091 
0092     if (priv->flags & MMIO_74XX_DIR_IN)
0093         return 0;
0094 
0095     return -ENOTSUPP;
0096 }
0097 
0098 static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
0099 {
0100     struct mmio_74xx_gpio_priv *priv = gpiochip_get_data(gc);
0101 
0102     if (priv->flags & MMIO_74XX_DIR_OUT) {
0103         gc->set(gc, gpio, val);
0104         return 0;
0105     }
0106 
0107     return -ENOTSUPP;
0108 }
0109 
0110 static int mmio_74xx_gpio_probe(struct platform_device *pdev)
0111 {
0112     struct mmio_74xx_gpio_priv *priv;
0113     void __iomem *dat;
0114     int err;
0115 
0116     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0117     if (!priv)
0118         return -ENOMEM;
0119 
0120     priv->flags = (uintptr_t)device_get_match_data(&pdev->dev);
0121 
0122     dat = devm_platform_ioremap_resource(pdev, 0);
0123     if (IS_ERR(dat))
0124         return PTR_ERR(dat);
0125 
0126     err = bgpio_init(&priv->gc, &pdev->dev,
0127              DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
0128              dat, NULL, NULL, NULL, NULL, 0);
0129     if (err)
0130         return err;
0131 
0132     priv->gc.direction_input = mmio_74xx_dir_in;
0133     priv->gc.direction_output = mmio_74xx_dir_out;
0134     priv->gc.get_direction = mmio_74xx_get_direction;
0135     priv->gc.ngpio = MMIO_74XX_BIT_CNT(priv->flags);
0136     priv->gc.owner = THIS_MODULE;
0137 
0138     platform_set_drvdata(pdev, priv);
0139 
0140     return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
0141 }
0142 
0143 static struct platform_driver mmio_74xx_gpio_driver = {
0144     .driver = {
0145         .name       = "74xx-mmio-gpio",
0146         .of_match_table = mmio_74xx_gpio_ids,
0147     },
0148     .probe  = mmio_74xx_gpio_probe,
0149 };
0150 module_platform_driver(mmio_74xx_gpio_driver);
0151 
0152 MODULE_LICENSE("GPL");
0153 MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
0154 MODULE_DESCRIPTION("74xx MMIO GPIO driver");