Root/target/linux/mcs814x/files-3.3/drivers/gpio/gpio-mcs814x.c

1/*
2 * Moschip MCS814x GPIO support
3 *
4 * Copyright (C) 2012, Florian Fainelli <florian@openwrt.org>
5 *
6 * Licensed under the GPLv2
7 */
8
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/platform_device.h>
14#include <linux/gpio.h>
15#include <linux/io.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18
19struct mcs814x_gpio_chip {
20    void __iomem *regs;
21    struct gpio_chip chip;
22};
23
24#define GPIO_PIN 0x00
25#define GPIO_DIR 0x04
26
27#define to_mcs814x_gpio_chip(x) container_of(x, struct mcs814x_gpio_chip, chip)
28
29static int mcs814x_gpio_get(struct gpio_chip *chip, unsigned offset)
30{
31    struct mcs814x_gpio_chip *mcs814x = to_mcs814x_gpio_chip(chip);
32
33    return readl_relaxed(mcs814x->regs + GPIO_PIN) & (1 << offset);
34}
35
36static void mcs814x_gpio_set(struct gpio_chip *chip,
37                unsigned offset, int value)
38{
39    struct mcs814x_gpio_chip *mcs814x = to_mcs814x_gpio_chip(chip);
40    u32 mask;
41
42    mask = readl_relaxed(mcs814x->regs + GPIO_PIN);
43    if (value)
44        mask |= (1 << offset);
45    else
46        mask &= ~(1 << offset);
47    writel_relaxed(mask, mcs814x->regs + GPIO_PIN);
48}
49
50static int mcs814x_gpio_direction_output(struct gpio_chip *chip,
51                    unsigned offset, int value)
52{
53    struct mcs814x_gpio_chip *mcs814x = to_mcs814x_gpio_chip(chip);
54    u32 mask;
55
56    mask = readl_relaxed(mcs814x->regs + GPIO_DIR);
57    mask &= ~(1 << offset);
58    writel_relaxed(mask, mcs814x->regs + GPIO_DIR);
59
60    return 0;
61}
62
63static int mcs814x_gpio_direction_input(struct gpio_chip *chip,
64                    unsigned offset)
65{
66    struct mcs814x_gpio_chip *mcs814x = to_mcs814x_gpio_chip(chip);
67    u32 mask;
68
69    mask = readl_relaxed(mcs814x->regs + GPIO_DIR);
70    mask |= (1 << offset);
71    writel_relaxed(mask, mcs814x->regs + GPIO_DIR);
72
73    return 0;
74}
75
76static int __devinit mcs814x_gpio_probe(struct platform_device *pdev)
77{
78    struct resource *res;
79    struct mcs814x_gpio_chip *mcs814x_chip;
80    int ret;
81    const unsigned int *num_gpios;
82
83    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
84    if (!res)
85        return -ENODEV;
86
87    num_gpios = of_get_property(pdev->dev.of_node, "num-gpios", NULL);
88    if (!num_gpios)
89        dev_err(&pdev->dev, "FIXME: no num-gpios property\n");
90
91    mcs814x_chip = kzalloc(sizeof(*mcs814x_chip), GFP_KERNEL);
92    if (!mcs814x_chip)
93        return -ENOMEM;
94
95    mcs814x_chip->regs = devm_request_and_ioremap(&pdev->dev, res);
96    if (!mcs814x_chip->regs) {
97        ret = -ENOMEM;
98        goto out;
99    }
100
101    platform_set_drvdata(pdev, mcs814x_chip);
102
103#ifdef CONFIG_OF_GPIO
104    mcs814x_chip->chip.of_node = pdev->dev.of_node;
105#endif
106
107    mcs814x_chip->chip.label = pdev->name;
108    mcs814x_chip->chip.get = mcs814x_gpio_get;
109    mcs814x_chip->chip.set = mcs814x_gpio_set;
110    mcs814x_chip->chip.direction_input = mcs814x_gpio_direction_input;
111    mcs814x_chip->chip.direction_output = mcs814x_gpio_direction_output;
112    mcs814x_chip->chip.ngpio = be32_to_cpup(num_gpios);
113    /* we want dynamic base allocation */
114    mcs814x_chip->chip.base = -1;
115
116    ret = gpiochip_add(&mcs814x_chip->chip);
117    if (ret) {
118        dev_err(&pdev->dev, "failed to register gpiochip\n");
119        goto out;
120    }
121
122    return 0;
123
124out:
125    platform_set_drvdata(pdev, NULL);
126    kfree(mcs814x_chip);
127    return ret;
128}
129
130static struct of_device_id mcs814x_gpio_ids[] __devinitdata = {
131    { .compatible = "moschip,mcs814x-gpio" },
132    { /* sentinel */ },
133};
134
135static struct platform_driver mcs814x_gpio_driver = {
136    .driver = {
137        .name = "mcs814x-gpio",
138        .owner = THIS_MODULE,
139        .of_match_table = mcs814x_gpio_ids,
140    },
141    .probe = mcs814x_gpio_probe,
142};
143
144int __init mcs814x_gpio_init(void)
145{
146    return platform_driver_register(&mcs814x_gpio_driver);
147}
148postcore_initcall(mcs814x_gpio_init);
149

Archive Download this file



interactive