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