2 * Moschip MCS814x GPIO support
4 * Copyright (C) 2012, Florian Fainelli <florian@openwrt.org>
6 * Licensed under the GPLv2
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>
17 #include <linux/of_address.h>
19 struct mcs814x_gpio_chip
{
21 struct gpio_chip chip
;
27 #define to_mcs814x_gpio_chip(x) container_of(x, struct mcs814x_gpio_chip, chip)
29 static int mcs814x_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
31 struct mcs814x_gpio_chip
*mcs814x
= to_mcs814x_gpio_chip(chip
);
33 return readl_relaxed(mcs814x
->regs
+ GPIO_PIN
) & (1 << offset
);
36 static void mcs814x_gpio_set(struct gpio_chip
*chip
,
37 unsigned offset
, int value
)
39 struct mcs814x_gpio_chip
*mcs814x
= to_mcs814x_gpio_chip(chip
);
42 mask
= readl_relaxed(mcs814x
->regs
+ GPIO_PIN
);
44 mask
|= (1 << offset
);
46 mask
&= ~(1 << offset
);
47 writel_relaxed(mask
, mcs814x
->regs
+ GPIO_PIN
);
50 static int mcs814x_gpio_direction_output(struct gpio_chip
*chip
,
51 unsigned offset
, int value
)
53 struct mcs814x_gpio_chip
*mcs814x
= to_mcs814x_gpio_chip(chip
);
56 mask
= readl_relaxed(mcs814x
->regs
+ GPIO_DIR
);
57 mask
&= ~(1 << offset
);
58 writel_relaxed(mask
, mcs814x
->regs
+ GPIO_DIR
);
63 static int mcs814x_gpio_direction_input(struct gpio_chip
*chip
,
66 struct mcs814x_gpio_chip
*mcs814x
= to_mcs814x_gpio_chip(chip
);
69 mask
= readl_relaxed(mcs814x
->regs
+ GPIO_DIR
);
70 mask
|= (1 << offset
);
71 writel_relaxed(mask
, mcs814x
->regs
+ GPIO_DIR
);
76 static int mcs814x_gpio_probe(struct platform_device
*pdev
)
79 struct mcs814x_gpio_chip
*mcs814x_chip
;
81 const unsigned int *num_gpios
;
83 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
87 num_gpios
= of_get_property(pdev
->dev
.of_node
, "num-gpios", NULL
);
89 dev_err(&pdev
->dev
, "FIXME: no num-gpios property\n");
91 mcs814x_chip
= kzalloc(sizeof(*mcs814x_chip
), GFP_KERNEL
);
95 mcs814x_chip
->regs
= devm_request_and_ioremap(&pdev
->dev
, res
);
96 if (!mcs814x_chip
->regs
) {
101 platform_set_drvdata(pdev
, mcs814x_chip
);
103 #ifdef CONFIG_OF_GPIO
104 mcs814x_chip
->chip
.of_node
= pdev
->dev
.of_node
;
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;
116 ret
= gpiochip_add(&mcs814x_chip
->chip
);
118 dev_err(&pdev
->dev
, "failed to register gpiochip\n");
125 platform_set_drvdata(pdev
, NULL
);
130 static struct of_device_id mcs814x_gpio_ids
[] = {
131 { .compatible
= "moschip,mcs814x-gpio" },
135 static struct platform_driver mcs814x_gpio_driver
= {
137 .name
= "mcs814x-gpio",
138 .owner
= THIS_MODULE
,
139 .of_match_table
= mcs814x_gpio_ids
,
141 .probe
= mcs814x_gpio_probe
,
144 int __init
mcs814x_gpio_init(void)
146 return platform_driver_register(&mcs814x_gpio_driver
);
148 postcore_initcall(mcs814x_gpio_init
);