1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/pci.h>
23#include <linux/types.h>
24#include <linux/i2c.h>
25#include <linux/i2c-algo-bit.h>
26#include <linux/init.h>
27#include <linux/io.h>
28#include <asm/hydra.h>
29
30
31#define HYDRA_CPD_PD0 0x00000001
32#define HYDRA_CPD_PD1 0x00000002
33#define HYDRA_CPD_PD2 0x00000004
34#define HYDRA_CPD_PD3 0x00000008
35
36#define HYDRA_SCLK HYDRA_CPD_PD0
37#define HYDRA_SDAT HYDRA_CPD_PD1
38#define HYDRA_SCLK_OE 0x00000010
39#define HYDRA_SDAT_OE 0x00000020
40
41static inline void pdregw(void *data, u32 val)
42{
43 struct Hydra *hydra = (struct Hydra *)data;
44 writel(val, &hydra->CachePD);
45}
46
47static inline u32 pdregr(void *data)
48{
49 struct Hydra *hydra = (struct Hydra *)data;
50 return readl(&hydra->CachePD);
51}
52
53static void hydra_bit_setscl(void *data, int state)
54{
55 u32 val = pdregr(data);
56 if (state)
57 val &= ~HYDRA_SCLK_OE;
58 else {
59 val &= ~HYDRA_SCLK;
60 val |= HYDRA_SCLK_OE;
61 }
62 pdregw(data, val);
63}
64
65static void hydra_bit_setsda(void *data, int state)
66{
67 u32 val = pdregr(data);
68 if (state)
69 val &= ~HYDRA_SDAT_OE;
70 else {
71 val &= ~HYDRA_SDAT;
72 val |= HYDRA_SDAT_OE;
73 }
74 pdregw(data, val);
75}
76
77static int hydra_bit_getscl(void *data)
78{
79 return (pdregr(data) & HYDRA_SCLK) != 0;
80}
81
82static int hydra_bit_getsda(void *data)
83{
84 return (pdregr(data) & HYDRA_SDAT) != 0;
85}
86
87
88
89static struct i2c_algo_bit_data hydra_bit_data = {
90 .setsda = hydra_bit_setsda,
91 .setscl = hydra_bit_setscl,
92 .getsda = hydra_bit_getsda,
93 .getscl = hydra_bit_getscl,
94 .udelay = 5,
95 .timeout = HZ
96};
97
98static struct i2c_adapter hydra_adap = {
99 .owner = THIS_MODULE,
100 .name = "Hydra i2c",
101 .algo_data = &hydra_bit_data,
102};
103
104static const struct pci_device_id hydra_ids[] = {
105 { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) },
106 { 0, }
107};
108
109MODULE_DEVICE_TABLE (pci, hydra_ids);
110
111static int hydra_probe(struct pci_dev *dev,
112 const struct pci_device_id *id)
113{
114 unsigned long base = pci_resource_start(dev, 0);
115 int res;
116
117 if (!request_mem_region(base+offsetof(struct Hydra, CachePD), 4,
118 hydra_adap.name))
119 return -EBUSY;
120
121 hydra_bit_data.data = pci_ioremap_bar(dev, 0);
122 if (hydra_bit_data.data == NULL) {
123 release_mem_region(base+offsetof(struct Hydra, CachePD), 4);
124 return -ENODEV;
125 }
126
127 pdregw(hydra_bit_data.data, 0);
128 hydra_adap.dev.parent = &dev->dev;
129 res = i2c_bit_add_bus(&hydra_adap);
130 if (res < 0) {
131 iounmap(hydra_bit_data.data);
132 release_mem_region(base+offsetof(struct Hydra, CachePD), 4);
133 return res;
134 }
135 return 0;
136}
137
138static void hydra_remove(struct pci_dev *dev)
139{
140 pdregw(hydra_bit_data.data, 0);
141 i2c_del_adapter(&hydra_adap);
142 iounmap(hydra_bit_data.data);
143 release_mem_region(pci_resource_start(dev, 0)+
144 offsetof(struct Hydra, CachePD), 4);
145}
146
147
148static struct pci_driver hydra_driver = {
149 .name = "hydra_smbus",
150 .id_table = hydra_ids,
151 .probe = hydra_probe,
152 .remove = hydra_remove,
153};
154
155module_pci_driver(hydra_driver);
156
157MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
158MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O");
159MODULE_LICENSE("GPL");
160