xref: /OK3568_Linux_fs/kernel/drivers/media/pci/bt8xx/bttv-gpio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun     bttv-gpio.c  --  gpio sub drivers
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun     sysfs-based sub driver interface for bttv
7*4882a593Smuzhiyun     mainly intended for gpio access
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun     Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
11*4882a593Smuzhiyun 			   & Marcus Metzler (mocm@thp.uni-koeln.de)
12*4882a593Smuzhiyun     (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/init.h>
21*4882a593Smuzhiyun #include <linux/delay.h>
22*4882a593Smuzhiyun #include <linux/device.h>
23*4882a593Smuzhiyun #include <linux/slab.h>
24*4882a593Smuzhiyun #include <asm/io.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include "bttvp.h"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /* ----------------------------------------------------------------------- */
29*4882a593Smuzhiyun /* internal: the bttv "bus"                                                */
30*4882a593Smuzhiyun 
bttv_sub_bus_match(struct device * dev,struct device_driver * drv)31*4882a593Smuzhiyun static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
34*4882a593Smuzhiyun 	int len = strlen(sub->wanted);
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	if (0 == strncmp(dev_name(dev), sub->wanted, len))
37*4882a593Smuzhiyun 		return 1;
38*4882a593Smuzhiyun 	return 0;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
bttv_sub_probe(struct device * dev)41*4882a593Smuzhiyun static int bttv_sub_probe(struct device *dev)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
44*4882a593Smuzhiyun 	struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	return sub->probe ? sub->probe(sdev) : -ENODEV;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
bttv_sub_remove(struct device * dev)49*4882a593Smuzhiyun static int bttv_sub_remove(struct device *dev)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
52*4882a593Smuzhiyun 	struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	if (sub->remove)
55*4882a593Smuzhiyun 		sub->remove(sdev);
56*4882a593Smuzhiyun 	return 0;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun struct bus_type bttv_sub_bus_type = {
60*4882a593Smuzhiyun 	.name   = "bttv-sub",
61*4882a593Smuzhiyun 	.match  = &bttv_sub_bus_match,
62*4882a593Smuzhiyun 	.probe  = bttv_sub_probe,
63*4882a593Smuzhiyun 	.remove = bttv_sub_remove,
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun 
release_sub_device(struct device * dev)66*4882a593Smuzhiyun static void release_sub_device(struct device *dev)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
69*4882a593Smuzhiyun 	kfree(sub);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
bttv_sub_add_device(struct bttv_core * core,char * name)72*4882a593Smuzhiyun int bttv_sub_add_device(struct bttv_core *core, char *name)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	struct bttv_sub_device *sub;
75*4882a593Smuzhiyun 	int err;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	sub = kzalloc(sizeof(*sub),GFP_KERNEL);
78*4882a593Smuzhiyun 	if (NULL == sub)
79*4882a593Smuzhiyun 		return -ENOMEM;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	sub->core        = core;
82*4882a593Smuzhiyun 	sub->dev.parent  = &core->pci->dev;
83*4882a593Smuzhiyun 	sub->dev.bus     = &bttv_sub_bus_type;
84*4882a593Smuzhiyun 	sub->dev.release = release_sub_device;
85*4882a593Smuzhiyun 	dev_set_name(&sub->dev, "%s%d", name, core->nr);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	err = device_register(&sub->dev);
88*4882a593Smuzhiyun 	if (0 != err) {
89*4882a593Smuzhiyun 		put_device(&sub->dev);
90*4882a593Smuzhiyun 		return err;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 	pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
93*4882a593Smuzhiyun 	list_add_tail(&sub->list,&core->subs);
94*4882a593Smuzhiyun 	return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
bttv_sub_del_devices(struct bttv_core * core)97*4882a593Smuzhiyun int bttv_sub_del_devices(struct bttv_core *core)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	struct bttv_sub_device *sub, *save;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	list_for_each_entry_safe(sub, save, &core->subs, list) {
102*4882a593Smuzhiyun 		list_del(&sub->list);
103*4882a593Smuzhiyun 		device_unregister(&sub->dev);
104*4882a593Smuzhiyun 	}
105*4882a593Smuzhiyun 	return 0;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun /* ----------------------------------------------------------------------- */
109*4882a593Smuzhiyun /* external: sub-driver register/unregister                                */
110*4882a593Smuzhiyun 
bttv_sub_register(struct bttv_sub_driver * sub,char * wanted)111*4882a593Smuzhiyun int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	sub->drv.bus = &bttv_sub_bus_type;
114*4882a593Smuzhiyun 	snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted);
115*4882a593Smuzhiyun 	return driver_register(&sub->drv);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun EXPORT_SYMBOL(bttv_sub_register);
118*4882a593Smuzhiyun 
bttv_sub_unregister(struct bttv_sub_driver * sub)119*4882a593Smuzhiyun int bttv_sub_unregister(struct bttv_sub_driver *sub)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	driver_unregister(&sub->drv);
122*4882a593Smuzhiyun 	return 0;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun EXPORT_SYMBOL(bttv_sub_unregister);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /* ----------------------------------------------------------------------- */
127*4882a593Smuzhiyun /* external: gpio access functions                                         */
128*4882a593Smuzhiyun 
bttv_gpio_inout(struct bttv_core * core,u32 mask,u32 outbits)129*4882a593Smuzhiyun void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	struct bttv *btv = container_of(core, struct bttv, c);
132*4882a593Smuzhiyun 	unsigned long flags;
133*4882a593Smuzhiyun 	u32 data;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	spin_lock_irqsave(&btv->gpio_lock,flags);
136*4882a593Smuzhiyun 	data = btread(BT848_GPIO_OUT_EN);
137*4882a593Smuzhiyun 	data = data & ~mask;
138*4882a593Smuzhiyun 	data = data | (mask & outbits);
139*4882a593Smuzhiyun 	btwrite(data,BT848_GPIO_OUT_EN);
140*4882a593Smuzhiyun 	spin_unlock_irqrestore(&btv->gpio_lock,flags);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
bttv_gpio_read(struct bttv_core * core)143*4882a593Smuzhiyun u32 bttv_gpio_read(struct bttv_core *core)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct bttv *btv = container_of(core, struct bttv, c);
146*4882a593Smuzhiyun 	u32 value;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	value = btread(BT848_GPIO_DATA);
149*4882a593Smuzhiyun 	return value;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
bttv_gpio_write(struct bttv_core * core,u32 value)152*4882a593Smuzhiyun void bttv_gpio_write(struct bttv_core *core, u32 value)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	struct bttv *btv = container_of(core, struct bttv, c);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	btwrite(value,BT848_GPIO_DATA);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
bttv_gpio_bits(struct bttv_core * core,u32 mask,u32 bits)159*4882a593Smuzhiyun void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	struct bttv *btv = container_of(core, struct bttv, c);
162*4882a593Smuzhiyun 	unsigned long flags;
163*4882a593Smuzhiyun 	u32 data;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	spin_lock_irqsave(&btv->gpio_lock,flags);
166*4882a593Smuzhiyun 	data = btread(BT848_GPIO_DATA);
167*4882a593Smuzhiyun 	data = data & ~mask;
168*4882a593Smuzhiyun 	data = data | (mask & bits);
169*4882a593Smuzhiyun 	btwrite(data,BT848_GPIO_DATA);
170*4882a593Smuzhiyun 	spin_unlock_irqrestore(&btv->gpio_lock,flags);
171*4882a593Smuzhiyun }
172