cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpio-octeon.c (3281B)


      1/*
      2 * This file is subject to the terms and conditions of the GNU General Public
      3 * License.  See the file "COPYING" in the main directory of this archive
      4 * for more details.
      5 *
      6 * Copyright (C) 2011, 2012 Cavium Inc.
      7 */
      8
      9#include <linux/platform_device.h>
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/gpio/driver.h>
     13#include <linux/io.h>
     14
     15#include <asm/octeon/octeon.h>
     16#include <asm/octeon/cvmx-gpio-defs.h>
     17
     18#define RX_DAT 0x80
     19#define TX_SET 0x88
     20#define TX_CLEAR 0x90
     21/*
     22 * The address offset of the GPIO configuration register for a given
     23 * line.
     24 */
     25static unsigned int bit_cfg_reg(unsigned int offset)
     26{
     27	/*
     28	 * The register stride is 8, with a discontinuity after the
     29	 * first 16.
     30	 */
     31	if (offset < 16)
     32		return 8 * offset;
     33	else
     34		return 8 * (offset - 16) + 0x100;
     35}
     36
     37struct octeon_gpio {
     38	struct gpio_chip chip;
     39	u64 register_base;
     40};
     41
     42static int octeon_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
     43{
     44	struct octeon_gpio *gpio = gpiochip_get_data(chip);
     45
     46	cvmx_write_csr(gpio->register_base + bit_cfg_reg(offset), 0);
     47	return 0;
     48}
     49
     50static void octeon_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
     51{
     52	struct octeon_gpio *gpio = gpiochip_get_data(chip);
     53	u64 mask = 1ull << offset;
     54	u64 reg = gpio->register_base + (value ? TX_SET : TX_CLEAR);
     55	cvmx_write_csr(reg, mask);
     56}
     57
     58static int octeon_gpio_dir_out(struct gpio_chip *chip, unsigned offset,
     59			       int value)
     60{
     61	struct octeon_gpio *gpio = gpiochip_get_data(chip);
     62	union cvmx_gpio_bit_cfgx cfgx;
     63
     64	octeon_gpio_set(chip, offset, value);
     65
     66	cfgx.u64 = 0;
     67	cfgx.s.tx_oe = 1;
     68
     69	cvmx_write_csr(gpio->register_base + bit_cfg_reg(offset), cfgx.u64);
     70	return 0;
     71}
     72
     73static int octeon_gpio_get(struct gpio_chip *chip, unsigned offset)
     74{
     75	struct octeon_gpio *gpio = gpiochip_get_data(chip);
     76	u64 read_bits = cvmx_read_csr(gpio->register_base + RX_DAT);
     77
     78	return ((1ull << offset) & read_bits) != 0;
     79}
     80
     81static int octeon_gpio_probe(struct platform_device *pdev)
     82{
     83	struct octeon_gpio *gpio;
     84	struct gpio_chip *chip;
     85	void __iomem *reg_base;
     86	int err = 0;
     87
     88	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
     89	if (!gpio)
     90		return -ENOMEM;
     91	chip = &gpio->chip;
     92
     93	reg_base = devm_platform_ioremap_resource(pdev, 0);
     94	if (IS_ERR(reg_base))
     95		return PTR_ERR(reg_base);
     96
     97	gpio->register_base = (u64)reg_base;
     98	pdev->dev.platform_data = chip;
     99	chip->label = "octeon-gpio";
    100	chip->parent = &pdev->dev;
    101	chip->owner = THIS_MODULE;
    102	chip->base = 0;
    103	chip->can_sleep = false;
    104	chip->ngpio = 20;
    105	chip->direction_input = octeon_gpio_dir_in;
    106	chip->get = octeon_gpio_get;
    107	chip->direction_output = octeon_gpio_dir_out;
    108	chip->set = octeon_gpio_set;
    109	err = devm_gpiochip_add_data(&pdev->dev, chip, gpio);
    110	if (err)
    111		return err;
    112
    113	dev_info(&pdev->dev, "OCTEON GPIO driver probed.\n");
    114	return 0;
    115}
    116
    117static const struct of_device_id octeon_gpio_match[] = {
    118	{
    119		.compatible = "cavium,octeon-3860-gpio",
    120	},
    121	{},
    122};
    123MODULE_DEVICE_TABLE(of, octeon_gpio_match);
    124
    125static struct platform_driver octeon_gpio_driver = {
    126	.driver = {
    127		.name		= "octeon_gpio",
    128		.of_match_table = octeon_gpio_match,
    129	},
    130	.probe		= octeon_gpio_probe,
    131};
    132
    133module_platform_driver(octeon_gpio_driver);
    134
    135MODULE_DESCRIPTION("Cavium Inc. OCTEON GPIO Driver");
    136MODULE_AUTHOR("David Daney");
    137MODULE_LICENSE("GPL");