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