Skip to content

Commit 7d3e4d8

Browse files
Kumaravel Thiagarajangregkh
authored andcommitted
misc: microchip: pci1xxxx: load gpio driver for the gpio controller auxiliary device enumerated by the auxiliary bus driver.
PIO function's auxiliary bus driver enumerates separate child devices for GPIO controller and OTP/EEPROM interface. This gpio driver implemented based on the gpio framework is loaded for the gpio auxiliary device. Signed-off-by: Kumaravel Thiagarajan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 393fc2f commit 7d3e4d8

File tree

3 files changed

+165
-1
lines changed

3 files changed

+165
-1
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13428,6 +13428,7 @@ L: [email protected]
1342813428
S: Supported
1342913429
F: drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c
1343013430
F: drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.h
13431+
F: drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c
1343113432

1343213433
MICROCHIP OTPC DRIVER
1343313434
M: Claudiu Beznea <[email protected]>

drivers/misc/mchp_pci1xxxx/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
obj-$(CONFIG_GP_PCI1XXXX) := mchp_pci1xxxx_gp.o
1+
obj-$(CONFIG_GP_PCI1XXXX) := mchp_pci1xxxx_gp.o mchp_pci1xxxx_gpio.o
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (C) 2022 Microchip Technology Inc.
3+
// pci1xxxx gpio driver
4+
5+
#include <linux/module.h>
6+
#include <linux/spinlock.h>
7+
#include <linux/gpio/driver.h>
8+
#include <linux/bio.h>
9+
#include <linux/spinlock.h>
10+
#include <linux/mutex.h>
11+
#include <linux/kthread.h>
12+
13+
#include "mchp_pci1xxxx_gp.h"
14+
15+
#define PCI1XXXX_NR_PINS 93
16+
#define PULLUP_OFFSET(x) ((((x) / 32) * 4) + 0x400 + 0x40)
17+
#define PULLDOWN_OFFSET(x) ((((x) / 32) * 4) + 0x400 + 0x50)
18+
#define OPENDRAIN_OFFSET(x) ((((x) / 32) * 4) + 0x400 + 0x60)
19+
#define DEBOUNCE_OFFSET(x) ((((x) / 32) * 4) + 0x400 + 0xE0)
20+
#define PIO_GLOBAL_CONFIG_OFFSET (0x400 + 0xF0)
21+
#define PIO_PCI_CTRL_REG_OFFSET (0x400 + 0xF4)
22+
#define INTR_MASK_OFFSET(x) ((((x) / 32) * 4) + 0x400 + 0x100)
23+
#define INTR_STATUS_OFFSET(x) (((x) * 4) + 0x400 + 0xD0)
24+
25+
struct pci1xxxx_gpio {
26+
struct auxiliary_device *aux_dev;
27+
void __iomem *reg_base;
28+
struct gpio_chip gpio;
29+
spinlock_t lock;
30+
int irq_base;
31+
};
32+
33+
static inline void pci1xxx_assign_bit(void __iomem *base_addr, unsigned int reg_offset,
34+
unsigned int bitpos, bool set)
35+
{
36+
u32 data;
37+
38+
data = readl(base_addr + reg_offset);
39+
if (set)
40+
data |= BIT(bitpos);
41+
else
42+
data &= ~BIT(bitpos);
43+
writel(data, base_addr + reg_offset);
44+
}
45+
46+
static int pci1xxxx_gpio_set_config(struct gpio_chip *gpio, unsigned int offset,
47+
unsigned long config)
48+
{
49+
struct pci1xxxx_gpio *priv = gpiochip_get_data(gpio);
50+
unsigned long flags;
51+
int ret = 0;
52+
53+
spin_lock_irqsave(&priv->lock, flags);
54+
switch (pinconf_to_config_param(config)) {
55+
case PIN_CONFIG_BIAS_PULL_UP:
56+
pci1xxx_assign_bit(priv->reg_base, PULLUP_OFFSET(offset), (offset % 32), true);
57+
break;
58+
case PIN_CONFIG_BIAS_PULL_DOWN:
59+
pci1xxx_assign_bit(priv->reg_base, PULLDOWN_OFFSET(offset), (offset % 32), true);
60+
break;
61+
case PIN_CONFIG_BIAS_DISABLE:
62+
pci1xxx_assign_bit(priv->reg_base, PULLUP_OFFSET(offset), (offset % 32), false);
63+
pci1xxx_assign_bit(priv->reg_base, PULLDOWN_OFFSET(offset), (offset % 32), false);
64+
break;
65+
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
66+
pci1xxx_assign_bit(priv->reg_base, OPENDRAIN_OFFSET(offset), (offset % 32), true);
67+
break;
68+
default:
69+
ret = -EOPNOTSUPP;
70+
break;
71+
}
72+
spin_unlock_irqrestore(&priv->lock, flags);
73+
74+
return ret;
75+
}
76+
77+
static int pci1xxxx_gpio_setup(struct pci1xxxx_gpio *priv, int irq)
78+
{
79+
struct gpio_chip *gchip = &priv->gpio;
80+
81+
gchip->label = dev_name(&priv->aux_dev->dev);
82+
gchip->parent = &priv->aux_dev->dev;
83+
gchip->owner = THIS_MODULE;
84+
gchip->set_config = pci1xxxx_gpio_set_config;
85+
gchip->dbg_show = NULL;
86+
gchip->base = -1;
87+
gchip->ngpio = PCI1XXXX_NR_PINS;
88+
gchip->can_sleep = false;
89+
90+
return 0;
91+
}
92+
93+
static int pci1xxxx_gpio_probe(struct auxiliary_device *aux_dev,
94+
const struct auxiliary_device_id *id)
95+
96+
{
97+
struct auxiliary_device_wrapper *aux_dev_wrapper;
98+
struct gp_aux_data_type *pdata;
99+
struct pci1xxxx_gpio *priv;
100+
int retval;
101+
102+
aux_dev_wrapper = (struct auxiliary_device_wrapper *)
103+
container_of(aux_dev, struct auxiliary_device_wrapper, aux_dev);
104+
105+
pdata = &aux_dev_wrapper->gp_aux_data;
106+
107+
if (!pdata)
108+
return -EINVAL;
109+
110+
priv = devm_kzalloc(&aux_dev->dev, sizeof(struct pci1xxxx_gpio), GFP_KERNEL);
111+
if (!priv)
112+
return -ENOMEM;
113+
114+
priv->aux_dev = aux_dev;
115+
116+
if (!devm_request_mem_region(&aux_dev->dev, pdata->region_start, 0x800, aux_dev->name))
117+
return -EBUSY;
118+
119+
priv->reg_base = devm_ioremap(&aux_dev->dev, pdata->region_start, 0x800);
120+
if (!priv->reg_base)
121+
return -ENOMEM;
122+
123+
writel(0x0264, (priv->reg_base + 0x400 + 0xF0));
124+
125+
retval = pci1xxxx_gpio_setup(priv, pdata->irq_num);
126+
127+
if (retval < 0)
128+
return retval;
129+
130+
dev_set_drvdata(&aux_dev->dev, priv);
131+
132+
return devm_gpiochip_add_data(&aux_dev->dev, &priv->gpio, priv);
133+
}
134+
135+
const struct auxiliary_device_id pci1xxxx_gpio_auxiliary_id_table[] = {
136+
{.name = "mchp_pci1xxxx_gp.gp_gpio"},
137+
{}
138+
};
139+
140+
static struct auxiliary_driver pci1xxxx_gpio_driver = {
141+
.driver = {
142+
.name = "PCI1xxxxGPIO",
143+
},
144+
.probe = pci1xxxx_gpio_probe,
145+
.id_table = pci1xxxx_gpio_auxiliary_id_table
146+
};
147+
148+
static int __init pci1xxxx_gpio_driver_init(void)
149+
{
150+
return auxiliary_driver_register(&pci1xxxx_gpio_driver);
151+
}
152+
153+
static void __exit pci1xxxx_gpio_driver_exit(void)
154+
{
155+
auxiliary_driver_unregister(&pci1xxxx_gpio_driver);
156+
}
157+
158+
module_init(pci1xxxx_gpio_driver_init);
159+
module_exit(pci1xxxx_gpio_driver_exit);
160+
161+
MODULE_DESCRIPTION("Microchip Technology Inc. PCI1xxxx GPIO controller");
162+
MODULE_AUTHOR("Kumaravel Thiagarajan <[email protected]>");
163+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)