Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2011, 2012 Cavium Inc.
0007  */
0008 
0009 #include <linux/platform_device.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/gpio/driver.h>
0013 #include <linux/io.h>
0014 
0015 #include <asm/octeon/octeon.h>
0016 #include <asm/octeon/cvmx-gpio-defs.h>
0017 
0018 #define RX_DAT 0x80
0019 #define TX_SET 0x88
0020 #define TX_CLEAR 0x90
0021 /*
0022  * The address offset of the GPIO configuration register for a given
0023  * line.
0024  */
0025 static unsigned int bit_cfg_reg(unsigned int offset)
0026 {
0027     /*
0028      * The register stride is 8, with a discontinuity after the
0029      * first 16.
0030      */
0031     if (offset < 16)
0032         return 8 * offset;
0033     else
0034         return 8 * (offset - 16) + 0x100;
0035 }
0036 
0037 struct octeon_gpio {
0038     struct gpio_chip chip;
0039     u64 register_base;
0040 };
0041 
0042 static int octeon_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
0043 {
0044     struct octeon_gpio *gpio = gpiochip_get_data(chip);
0045 
0046     cvmx_write_csr(gpio->register_base + bit_cfg_reg(offset), 0);
0047     return 0;
0048 }
0049 
0050 static void octeon_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
0051 {
0052     struct octeon_gpio *gpio = gpiochip_get_data(chip);
0053     u64 mask = 1ull << offset;
0054     u64 reg = gpio->register_base + (value ? TX_SET : TX_CLEAR);
0055     cvmx_write_csr(reg, mask);
0056 }
0057 
0058 static int octeon_gpio_dir_out(struct gpio_chip *chip, unsigned offset,
0059                    int value)
0060 {
0061     struct octeon_gpio *gpio = gpiochip_get_data(chip);
0062     union cvmx_gpio_bit_cfgx cfgx;
0063 
0064     octeon_gpio_set(chip, offset, value);
0065 
0066     cfgx.u64 = 0;
0067     cfgx.s.tx_oe = 1;
0068 
0069     cvmx_write_csr(gpio->register_base + bit_cfg_reg(offset), cfgx.u64);
0070     return 0;
0071 }
0072 
0073 static int octeon_gpio_get(struct gpio_chip *chip, unsigned offset)
0074 {
0075     struct octeon_gpio *gpio = gpiochip_get_data(chip);
0076     u64 read_bits = cvmx_read_csr(gpio->register_base + RX_DAT);
0077 
0078     return ((1ull << offset) & read_bits) != 0;
0079 }
0080 
0081 static int octeon_gpio_probe(struct platform_device *pdev)
0082 {
0083     struct octeon_gpio *gpio;
0084     struct gpio_chip *chip;
0085     void __iomem *reg_base;
0086     int err = 0;
0087 
0088     gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
0089     if (!gpio)
0090         return -ENOMEM;
0091     chip = &gpio->chip;
0092 
0093     reg_base = devm_platform_ioremap_resource(pdev, 0);
0094     if (IS_ERR(reg_base))
0095         return PTR_ERR(reg_base);
0096 
0097     gpio->register_base = (u64)reg_base;
0098     pdev->dev.platform_data = chip;
0099     chip->label = "octeon-gpio";
0100     chip->parent = &pdev->dev;
0101     chip->owner = THIS_MODULE;
0102     chip->base = 0;
0103     chip->can_sleep = false;
0104     chip->ngpio = 20;
0105     chip->direction_input = octeon_gpio_dir_in;
0106     chip->get = octeon_gpio_get;
0107     chip->direction_output = octeon_gpio_dir_out;
0108     chip->set = octeon_gpio_set;
0109     err = devm_gpiochip_add_data(&pdev->dev, chip, gpio);
0110     if (err)
0111         return err;
0112 
0113     dev_info(&pdev->dev, "OCTEON GPIO driver probed.\n");
0114     return 0;
0115 }
0116 
0117 static const struct of_device_id octeon_gpio_match[] = {
0118     {
0119         .compatible = "cavium,octeon-3860-gpio",
0120     },
0121     {},
0122 };
0123 MODULE_DEVICE_TABLE(of, octeon_gpio_match);
0124 
0125 static struct platform_driver octeon_gpio_driver = {
0126     .driver = {
0127         .name       = "octeon_gpio",
0128         .of_match_table = octeon_gpio_match,
0129     },
0130     .probe      = octeon_gpio_probe,
0131 };
0132 
0133 module_platform_driver(octeon_gpio_driver);
0134 
0135 MODULE_DESCRIPTION("Cavium Inc. OCTEON GPIO Driver");
0136 MODULE_AUTHOR("David Daney");
0137 MODULE_LICENSE("GPL");