brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · afb0e8a Raw
138 lines · c
1/*2 * This file is subject to the terms and conditions of the GNU General Public3 * License.  See the file "COPYING" in the main directory of this archive4 * 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 0x8019#define TX_SET 0x8820#define TX_CLEAR 0x9021/*22 * The address offset of the GPIO configuration register for a given23 * line.24 */25static unsigned int bit_cfg_reg(unsigned int offset)26{27	/*28	 * The register stride is 8, with a discontinuity after the29	 * first 16.30	 */31	if (offset < 16)32		return 8 * offset;33	else34		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");138