2 * GPIO driver for Exar XR17V35X chip
4 * Copyright (C) 2015 Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 #include <linux/bitops.h>
11 #include <linux/device.h>
12 #include <linux/gpio/driver.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/platform_device.h>
19 #define EXAR_OFFSET_MPIOLVL_LO 0x90
20 #define EXAR_OFFSET_MPIOSEL_LO 0x93
21 #define EXAR_OFFSET_MPIOLVL_HI 0x96
22 #define EXAR_OFFSET_MPIOSEL_HI 0x99
24 #define DRIVER_NAME "gpio_exar"
26 static DEFINE_IDA(ida_index
);
28 struct exar_gpio_chip
{
29 struct gpio_chip gpio_chip
;
36 static void exar_update(struct gpio_chip
*chip
, unsigned int reg
, int val
,
39 struct exar_gpio_chip
*exar_gpio
= gpiochip_get_data(chip
);
42 mutex_lock(&exar_gpio
->lock
);
43 temp
= readb(exar_gpio
->regs
+ reg
);
47 writeb(temp
, exar_gpio
->regs
+ reg
);
48 mutex_unlock(&exar_gpio
->lock
);
51 static int exar_set_direction(struct gpio_chip
*chip
, int direction
,
54 unsigned int bank
= offset
/ 8;
57 addr
= bank
? EXAR_OFFSET_MPIOSEL_HI
: EXAR_OFFSET_MPIOSEL_LO
;
58 exar_update(chip
, addr
, direction
, offset
% 8);
62 static int exar_direction_output(struct gpio_chip
*chip
, unsigned int offset
,
65 return exar_set_direction(chip
, 0, offset
);
68 static int exar_direction_input(struct gpio_chip
*chip
, unsigned int offset
)
70 return exar_set_direction(chip
, 1, offset
);
73 static int exar_get(struct gpio_chip
*chip
, unsigned int reg
)
75 struct exar_gpio_chip
*exar_gpio
= gpiochip_get_data(chip
);
78 mutex_lock(&exar_gpio
->lock
);
79 value
= readb(exar_gpio
->regs
+ reg
);
80 mutex_unlock(&exar_gpio
->lock
);
85 static int exar_get_direction(struct gpio_chip
*chip
, unsigned int offset
)
87 unsigned int bank
= offset
/ 8;
91 addr
= bank
? EXAR_OFFSET_MPIOSEL_HI
: EXAR_OFFSET_MPIOSEL_LO
;
92 val
= exar_get(chip
, addr
) >> (offset
% 8);
97 static int exar_get_value(struct gpio_chip
*chip
, unsigned int offset
)
99 unsigned int bank
= offset
/ 8;
103 addr
= bank
? EXAR_OFFSET_MPIOLVL_LO
: EXAR_OFFSET_MPIOLVL_HI
;
104 val
= exar_get(chip
, addr
) >> (offset
% 8);
109 static void exar_set_value(struct gpio_chip
*chip
, unsigned int offset
,
112 unsigned int bank
= offset
/ 8;
115 addr
= bank
? EXAR_OFFSET_MPIOLVL_HI
: EXAR_OFFSET_MPIOLVL_LO
;
116 exar_update(chip
, addr
, value
, offset
% 8);
119 static int gpio_exar_probe(struct platform_device
*pdev
)
121 struct pci_dev
*pcidev
= platform_get_drvdata(pdev
);
122 struct exar_gpio_chip
*exar_gpio
;
126 if (pcidev
->vendor
!= PCI_VENDOR_ID_EXAR
)
130 * Map the pci device to get the register addresses.
131 * We will need to read and write those registers to control
133 * Using managed functions will save us from unmaping on exit.
134 * As the device is enabled using managed functions by the
135 * UART driver we can also use managed functions here.
137 p
= pcim_iomap(pcidev
, 0, 0);
141 exar_gpio
= devm_kzalloc(&pcidev
->dev
, sizeof(*exar_gpio
), GFP_KERNEL
);
145 mutex_init(&exar_gpio
->lock
);
147 index
= ida_simple_get(&ida_index
, 0, 0, GFP_KERNEL
);
149 sprintf(exar_gpio
->name
, "exar_gpio%d", index
);
150 exar_gpio
->gpio_chip
.label
= exar_gpio
->name
;
151 exar_gpio
->gpio_chip
.parent
= &pcidev
->dev
;
152 exar_gpio
->gpio_chip
.direction_output
= exar_direction_output
;
153 exar_gpio
->gpio_chip
.direction_input
= exar_direction_input
;
154 exar_gpio
->gpio_chip
.get_direction
= exar_get_direction
;
155 exar_gpio
->gpio_chip
.get
= exar_get_value
;
156 exar_gpio
->gpio_chip
.set
= exar_set_value
;
157 exar_gpio
->gpio_chip
.base
= -1;
158 exar_gpio
->gpio_chip
.ngpio
= 16;
160 exar_gpio
->index
= index
;
162 ret
= devm_gpiochip_add_data(&pcidev
->dev
,
163 &exar_gpio
->gpio_chip
, exar_gpio
);
167 platform_set_drvdata(pdev
, exar_gpio
);
172 ida_simple_remove(&ida_index
, index
);
173 mutex_destroy(&exar_gpio
->lock
);
177 static int gpio_exar_remove(struct platform_device
*pdev
)
179 struct exar_gpio_chip
*exar_gpio
= platform_get_drvdata(pdev
);
181 ida_simple_remove(&ida_index
, exar_gpio
->index
);
182 mutex_destroy(&exar_gpio
->lock
);
187 static struct platform_driver gpio_exar_driver
= {
188 .probe
= gpio_exar_probe
,
189 .remove
= gpio_exar_remove
,
195 module_platform_driver(gpio_exar_driver
);
197 MODULE_ALIAS("platform:" DRIVER_NAME
);
198 MODULE_DESCRIPTION("Exar GPIO driver");
199 MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
200 MODULE_LICENSE("GPL");