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
6 * Copyright (C) 2011, 2012 Cavium Inc.
9 #include <linux/platform_device.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/gpio.h>
15 #include <asm/octeon/octeon.h>
16 #include <asm/octeon/cvmx-gpio-defs.h>
22 * The address offset of the GPIO configuration register for a given
25 static unsigned int bit_cfg_reg(unsigned int offset
)
28 * The register stride is 8, with a discontinuity after the
34 return 8 * (offset
- 16) + 0x100;
38 struct gpio_chip chip
;
42 static int octeon_gpio_dir_in(struct gpio_chip
*chip
, unsigned offset
)
44 struct octeon_gpio
*gpio
= container_of(chip
, struct octeon_gpio
, chip
);
46 cvmx_write_csr(gpio
->register_base
+ bit_cfg_reg(offset
), 0);
50 static void octeon_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
52 struct octeon_gpio
*gpio
= container_of(chip
, struct octeon_gpio
, chip
);
53 u64 mask
= 1ull << offset
;
54 u64 reg
= gpio
->register_base
+ (value
? TX_SET
: TX_CLEAR
);
55 cvmx_write_csr(reg
, mask
);
58 static int octeon_gpio_dir_out(struct gpio_chip
*chip
, unsigned offset
,
61 struct octeon_gpio
*gpio
= container_of(chip
, struct octeon_gpio
, chip
);
62 union cvmx_gpio_bit_cfgx cfgx
;
64 octeon_gpio_set(chip
, offset
, value
);
69 cvmx_write_csr(gpio
->register_base
+ bit_cfg_reg(offset
), cfgx
.u64
);
73 static int octeon_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
75 struct octeon_gpio
*gpio
= container_of(chip
, struct octeon_gpio
, chip
);
76 u64 read_bits
= cvmx_read_csr(gpio
->register_base
+ RX_DAT
);
78 return ((1ull << offset
) & read_bits
) != 0;
81 static int octeon_gpio_probe(struct platform_device
*pdev
)
83 struct octeon_gpio
*gpio
;
84 struct gpio_chip
*chip
;
85 struct resource
*res_mem
;
88 gpio
= devm_kzalloc(&pdev
->dev
, sizeof(*gpio
), GFP_KERNEL
);
93 res_mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
94 if (res_mem
== NULL
) {
95 dev_err(&pdev
->dev
, "found no memory resource\n");
99 if (!devm_request_mem_region(&pdev
->dev
, res_mem
->start
,
100 resource_size(res_mem
),
102 dev_err(&pdev
->dev
, "request_mem_region failed\n");
106 gpio
->register_base
= (u64
)devm_ioremap(&pdev
->dev
, res_mem
->start
,
107 resource_size(res_mem
));
109 pdev
->dev
.platform_data
= chip
;
110 chip
->label
= "octeon-gpio";
111 chip
->dev
= &pdev
->dev
;
112 chip
->owner
= THIS_MODULE
;
114 chip
->can_sleep
= false;
116 chip
->direction_input
= octeon_gpio_dir_in
;
117 chip
->get
= octeon_gpio_get
;
118 chip
->direction_output
= octeon_gpio_dir_out
;
119 chip
->set
= octeon_gpio_set
;
120 err
= gpiochip_add(chip
);
124 dev_info(&pdev
->dev
, "OCTEON GPIO driver probed.\n");
129 static int octeon_gpio_remove(struct platform_device
*pdev
)
131 struct gpio_chip
*chip
= pdev
->dev
.platform_data
;
132 return gpiochip_remove(chip
);
135 static struct of_device_id octeon_gpio_match
[] = {
137 .compatible
= "cavium,octeon-3860-gpio",
141 MODULE_DEVICE_TABLE(of
, octeon_gpio_match
);
143 static struct platform_driver octeon_gpio_driver
= {
145 .name
= "octeon_gpio",
146 .owner
= THIS_MODULE
,
147 .of_match_table
= octeon_gpio_match
,
149 .probe
= octeon_gpio_probe
,
150 .remove
= octeon_gpio_remove
,
153 module_platform_driver(octeon_gpio_driver
);
155 MODULE_DESCRIPTION("Cavium Inc. OCTEON GPIO Driver");
156 MODULE_AUTHOR("David Daney");
157 MODULE_LICENSE("GPL");