aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-09-23 00:44:06 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-23 01:17:35 -0400
commit0365ba7fb1fa94a41289d6a3d36b4d95960e56cc (patch)
tree1da4b5fb97266849d86a78010141e7345cc599aa
parent0f329075fb1dbd6845db03e9bb8252024fdbea1f (diff)
[PATCH] ppc64: SMU driver update & i2c support
The SMU is the "system controller" chip used by Apple recent G5 machines including the iMac G5. It drives things like fans, i2c busses, real time clock, etc... The current kernel contains a very crude driver that doesn't do much more than reading the real time clock synchronously. This is a completely rewritten driver that provides interrupt based command queuing, a userland interface, and an i2c/smbus driver for accessing the devices hanging off the SMU i2c busses like temperature sensors. This driver is a basic block for upcoming work on thermal control for those machines, among others. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ppc/platforms/pmac_setup.c10
-rw-r--r--arch/ppc/syslib/of_device.c6
-rw-r--r--arch/ppc64/kernel/of_device.c7
-rw-r--r--arch/ppc64/kernel/pmac_setup.c18
-rw-r--r--arch/ppc64/kernel/pmac_time.c4
-rw-r--r--drivers/i2c/busses/Kconfig12
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-pmac-smu.c316
-rw-r--r--drivers/macintosh/smu.c1030
-rw-r--r--drivers/macintosh/therm_adt746x.c2
-rw-r--r--drivers/macintosh/therm_pm72.c2
-rw-r--r--drivers/macintosh/therm_windtunnel.c2
-rw-r--r--include/asm-ppc/macio.h1
-rw-r--r--include/asm-ppc/of_device.h5
-rw-r--r--include/asm-ppc64/smu.h365
15 files changed, 1618 insertions, 163 deletions
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
index b392b9a15987..4c56a4734aec 100644
--- a/arch/ppc/platforms/pmac_setup.c
+++ b/arch/ppc/platforms/pmac_setup.c
@@ -719,7 +719,8 @@ pmac_declare_of_platform_devices(void)
719 if (np) { 719 if (np) {
720 for (np = np->child; np != NULL; np = np->sibling) 720 for (np = np->child; np != NULL; np = np->sibling)
721 if (strncmp(np->name, "i2c", 3) == 0) { 721 if (strncmp(np->name, "i2c", 3) == 0) {
722 of_platform_device_create(np, "uni-n-i2c"); 722 of_platform_device_create(np, "uni-n-i2c",
723 NULL);
723 break; 724 break;
724 } 725 }
725 } 726 }
@@ -727,17 +728,18 @@ pmac_declare_of_platform_devices(void)
727 if (np) { 728 if (np) {
728 for (np = np->child; np != NULL; np = np->sibling) 729 for (np = np->child; np != NULL; np = np->sibling)
729 if (strncmp(np->name, "i2c", 3) == 0) { 730 if (strncmp(np->name, "i2c", 3) == 0) {
730 of_platform_device_create(np, "u3-i2c"); 731 of_platform_device_create(np, "u3-i2c",
732 NULL);
731 break; 733 break;
732 } 734 }
733 } 735 }
734 736
735 np = find_devices("valkyrie"); 737 np = find_devices("valkyrie");
736 if (np) 738 if (np)
737 of_platform_device_create(np, "valkyrie"); 739 of_platform_device_create(np, "valkyrie", NULL);
738 np = find_devices("platinum"); 740 np = find_devices("platinum");
739 if (np) 741 if (np)
740 of_platform_device_create(np, "platinum"); 742 of_platform_device_create(np, "platinum", NULL);
741 743
742 return 0; 744 return 0;
743} 745}
diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c
index da8a0f2128dc..93c7231ea709 100644
--- a/arch/ppc/syslib/of_device.c
+++ b/arch/ppc/syslib/of_device.c
@@ -234,7 +234,9 @@ void of_device_unregister(struct of_device *ofdev)
234 device_unregister(&ofdev->dev); 234 device_unregister(&ofdev->dev);
235} 235}
236 236
237struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) 237struct of_device* of_platform_device_create(struct device_node *np,
238 const char *bus_id,
239 struct device *parent)
238{ 240{
239 struct of_device *dev; 241 struct of_device *dev;
240 u32 *reg; 242 u32 *reg;
@@ -247,7 +249,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
247 dev->node = of_node_get(np); 249 dev->node = of_node_get(np);
248 dev->dma_mask = 0xffffffffUL; 250 dev->dma_mask = 0xffffffffUL;
249 dev->dev.dma_mask = &dev->dma_mask; 251 dev->dev.dma_mask = &dev->dma_mask;
250 dev->dev.parent = NULL; 252 dev->dev.parent = parent;
251 dev->dev.bus = &of_platform_bus_type; 253 dev->dev.bus = &of_platform_bus_type;
252 dev->dev.release = of_release_dev; 254 dev->dev.release = of_release_dev;
253 255
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index da580812ddfe..9f200f0f2ad5 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -233,7 +233,9 @@ void of_device_unregister(struct of_device *ofdev)
233 device_unregister(&ofdev->dev); 233 device_unregister(&ofdev->dev);
234} 234}
235 235
236struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) 236struct of_device* of_platform_device_create(struct device_node *np,
237 const char *bus_id,
238 struct device *parent)
237{ 239{
238 struct of_device *dev; 240 struct of_device *dev;
239 241
@@ -245,7 +247,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
245 dev->node = np; 247 dev->node = np;
246 dev->dma_mask = 0xffffffffUL; 248 dev->dma_mask = 0xffffffffUL;
247 dev->dev.dma_mask = &dev->dma_mask; 249 dev->dev.dma_mask = &dev->dma_mask;
248 dev->dev.parent = NULL; 250 dev->dev.parent = parent;
249 dev->dev.bus = &of_platform_bus_type; 251 dev->dev.bus = &of_platform_bus_type;
250 dev->dev.release = of_release_dev; 252 dev->dev.release = of_release_dev;
251 253
@@ -259,6 +261,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
259 return dev; 261 return dev;
260} 262}
261 263
264
262EXPORT_SYMBOL(of_match_device); 265EXPORT_SYMBOL(of_match_device);
263EXPORT_SYMBOL(of_platform_bus_type); 266EXPORT_SYMBOL(of_platform_bus_type);
264EXPORT_SYMBOL(of_register_driver); 267EXPORT_SYMBOL(of_register_driver);
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index 325426c7bed0..25755252067a 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -434,15 +434,23 @@ static int pmac_check_legacy_ioport(unsigned int baseport)
434 434
435static int __init pmac_declare_of_platform_devices(void) 435static int __init pmac_declare_of_platform_devices(void)
436{ 436{
437 struct device_node *np; 437 struct device_node *np, *npp;
438 438
439 np = find_devices("u3"); 439 npp = of_find_node_by_name(NULL, "u3");
440 if (np) { 440 if (npp) {
441 for (np = np->child; np != NULL; np = np->sibling) 441 for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) {
442 if (strncmp(np->name, "i2c", 3) == 0) { 442 if (strncmp(np->name, "i2c", 3) == 0) {
443 of_platform_device_create(np, "u3-i2c"); 443 of_platform_device_create(np, "u3-i2c", NULL);
444 of_node_put(np);
444 break; 445 break;
445 } 446 }
447 }
448 of_node_put(npp);
449 }
450 npp = of_find_node_by_type(NULL, "smu");
451 if (npp) {
452 of_platform_device_create(npp, "smu", NULL);
453 of_node_put(npp);
446 } 454 }
447 455
448 return 0; 456 return 0;
diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c
index 3059edb09cc8..41bbb8c59697 100644
--- a/arch/ppc64/kernel/pmac_time.c
+++ b/arch/ppc64/kernel/pmac_time.c
@@ -84,7 +84,7 @@ void __pmac pmac_get_rtc_time(struct rtc_time *tm)
84 84
85#ifdef CONFIG_PMAC_SMU 85#ifdef CONFIG_PMAC_SMU
86 case SYS_CTRLER_SMU: 86 case SYS_CTRLER_SMU:
87 smu_get_rtc_time(tm); 87 smu_get_rtc_time(tm, 1);
88 break; 88 break;
89#endif /* CONFIG_PMAC_SMU */ 89#endif /* CONFIG_PMAC_SMU */
90 default: 90 default:
@@ -128,7 +128,7 @@ int __pmac pmac_set_rtc_time(struct rtc_time *tm)
128 128
129#ifdef CONFIG_PMAC_SMU 129#ifdef CONFIG_PMAC_SMU
130 case SYS_CTRLER_SMU: 130 case SYS_CTRLER_SMU:
131 return smu_set_rtc_time(tm); 131 return smu_set_rtc_time(tm, 1);
132#endif /* CONFIG_PMAC_SMU */ 132#endif /* CONFIG_PMAC_SMU */
133 default: 133 default:
134 return -ENODEV; 134 return -ENODEV;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8334496a7e0a..3badfec75b1c 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -245,6 +245,18 @@ config I2C_KEYWEST
245 This support is also available as a module. If so, the module 245 This support is also available as a module. If so, the module
246 will be called i2c-keywest. 246 will be called i2c-keywest.
247 247
248config I2C_PMAC_SMU
249 tristate "Powermac SMU I2C interface"
250 depends on I2C && PMAC_SMU
251 help
252 This supports the use of the I2C interface in the SMU
253 chip on recent Apple machines like the iMac G5. It is used
254 among others by the thermal control driver for those machines.
255 Say Y if you have such a machine.
256
257 This support is also available as a module. If so, the module
258 will be called i2c-pmac-smu.
259
248config I2C_MPC 260config I2C_MPC
249 tristate "MPC107/824x/85xx/52xx" 261 tristate "MPC107/824x/85xx/52xx"
250 depends on I2C && PPC32 262 depends on I2C && PPC32
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 980b3e983670..f1df00f66c6c 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_I2C_ITE) += i2c-ite.o
20obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o 20obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
21obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o 21obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
22obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o 22obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o
23obj-$(CONFIG_I2C_PMAC_SMU) += i2c-pmac-smu.o
23obj-$(CONFIG_I2C_MPC) += i2c-mpc.o 24obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
24obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o 25obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
25obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o 26obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
new file mode 100644
index 000000000000..8a9f5648a23d
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pmac-smu.c
@@ -0,0 +1,316 @@
1/*
2 i2c Support for Apple SMU Controller
3
4 Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
5 <benh@kernel.crashing.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21*/
22
23#include <linux/config.h>
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/types.h>
27#include <linux/i2c.h>
28#include <linux/init.h>
29#include <linux/completion.h>
30#include <linux/device.h>
31#include <asm/prom.h>
32#include <asm/of_device.h>
33#include <asm/smu.h>
34
35static int probe;
36
37MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
38MODULE_DESCRIPTION("I2C driver for Apple's SMU");
39MODULE_LICENSE("GPL");
40module_param(probe, bool, 0);
41
42
43/* Physical interface */
44struct smu_iface
45{
46 struct i2c_adapter adapter;
47 struct completion complete;
48 u32 busid;
49};
50
51static void smu_i2c_done(struct smu_i2c_cmd *cmd, void *misc)
52{
53 struct smu_iface *iface = misc;
54 complete(&iface->complete);
55}
56
57/*
58 * SMBUS-type transfer entrypoint
59 */
60static s32 smu_smbus_xfer( struct i2c_adapter* adap,
61 u16 addr,
62 unsigned short flags,
63 char read_write,
64 u8 command,
65 int size,
66 union i2c_smbus_data* data)
67{
68 struct smu_iface *iface = i2c_get_adapdata(adap);
69 struct smu_i2c_cmd cmd;
70 int rc = 0;
71 int read = (read_write == I2C_SMBUS_READ);
72
73 cmd.info.bus = iface->busid;
74 cmd.info.devaddr = (addr << 1) | (read ? 0x01 : 0x00);
75
76 /* Prepare datas & select mode */
77 switch (size) {
78 case I2C_SMBUS_QUICK:
79 cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
80 cmd.info.datalen = 0;
81 break;
82 case I2C_SMBUS_BYTE:
83 cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
84 cmd.info.datalen = 1;
85 if (!read)
86 cmd.info.data[0] = data->byte;
87 break;
88 case I2C_SMBUS_BYTE_DATA:
89 cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
90 cmd.info.datalen = 1;
91 cmd.info.sublen = 1;
92 cmd.info.subaddr[0] = command;
93 cmd.info.subaddr[1] = 0;
94 cmd.info.subaddr[2] = 0;
95 if (!read)
96 cmd.info.data[0] = data->byte;
97 break;
98 case I2C_SMBUS_WORD_DATA:
99 cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
100 cmd.info.datalen = 2;
101 cmd.info.sublen = 1;
102 cmd.info.subaddr[0] = command;
103 cmd.info.subaddr[1] = 0;
104 cmd.info.subaddr[2] = 0;
105 if (!read) {
106 cmd.info.data[0] = data->byte & 0xff;
107 cmd.info.data[1] = (data->byte >> 8) & 0xff;
108 }
109 break;
110 /* Note that these are broken vs. the expected smbus API where
111 * on reads, the lenght is actually returned from the function,
112 * but I think the current API makes no sense and I don't want
113 * any driver that I haven't verified for correctness to go
114 * anywhere near a pmac i2c bus anyway ...
115 */
116 case I2C_SMBUS_BLOCK_DATA:
117 cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
118 cmd.info.datalen = data->block[0] + 1;
119 if (cmd.info.datalen > 6)
120 return -EINVAL;
121 if (!read)
122 memcpy(cmd.info.data, data->block, cmd.info.datalen);
123 cmd.info.sublen = 1;
124 cmd.info.subaddr[0] = command;
125 cmd.info.subaddr[1] = 0;
126 cmd.info.subaddr[2] = 0;
127 break;
128 case I2C_SMBUS_I2C_BLOCK_DATA:
129 cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
130 cmd.info.datalen = data->block[0];
131 if (cmd.info.datalen > 7)
132 return -EINVAL;
133 if (!read)
134 memcpy(cmd.info.data, &data->block[1],
135 cmd.info.datalen);
136 cmd.info.sublen = 1;
137 cmd.info.subaddr[0] = command;
138 cmd.info.subaddr[1] = 0;
139 cmd.info.subaddr[2] = 0;
140 break;
141
142 default:
143 return -EINVAL;
144 }
145
146 /* Turn a standardsub read into a combined mode access */
147 if (read_write == I2C_SMBUS_READ &&
148 cmd.info.type == SMU_I2C_TRANSFER_STDSUB)
149 cmd.info.type = SMU_I2C_TRANSFER_COMBINED;
150
151 /* Finish filling command and submit it */
152 cmd.done = smu_i2c_done;
153 cmd.misc = iface;
154 rc = smu_queue_i2c(&cmd);
155 if (rc < 0)
156 return rc;
157 wait_for_completion(&iface->complete);
158 rc = cmd.status;
159
160 if (!read || rc < 0)
161 return rc;
162
163 switch (size) {
164 case I2C_SMBUS_BYTE:
165 case I2C_SMBUS_BYTE_DATA:
166 data->byte = cmd.info.data[0];
167 break;
168 case I2C_SMBUS_WORD_DATA:
169 data->word = ((u16)cmd.info.data[1]) << 8;
170 data->word |= cmd.info.data[0];
171 break;
172 /* Note that these are broken vs. the expected smbus API where
173 * on reads, the lenght is actually returned from the function,
174 * but I think the current API makes no sense and I don't want
175 * any driver that I haven't verified for correctness to go
176 * anywhere near a pmac i2c bus anyway ...
177 */
178 case I2C_SMBUS_BLOCK_DATA:
179 case I2C_SMBUS_I2C_BLOCK_DATA:
180 memcpy(&data->block[0], cmd.info.data, cmd.info.datalen);
181 break;
182 }
183
184 return rc;
185}
186
187static u32
188smu_smbus_func(struct i2c_adapter * adapter)
189{
190 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
191 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
192 I2C_FUNC_SMBUS_BLOCK_DATA;
193}
194
195/* For now, we only handle combined mode (smbus) */
196static struct i2c_algorithm smu_algorithm = {
197 .smbus_xfer = smu_smbus_xfer,
198 .functionality = smu_smbus_func,
199};
200
201static int create_iface(struct device_node *np, struct device *dev)
202{
203 struct smu_iface* iface;
204 u32 *reg, busid;
205 int rc;
206
207 reg = (u32 *)get_property(np, "reg", NULL);
208 if (reg == NULL) {
209 printk(KERN_ERR "i2c-pmac-smu: can't find bus number !\n");
210 return -ENXIO;
211 }
212 busid = *reg;
213
214 iface = kmalloc(sizeof(struct smu_iface), GFP_KERNEL);
215 if (iface == NULL) {
216 printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n");
217 return -ENOMEM;
218 }
219 memset(iface, 0, sizeof(struct smu_iface));
220 init_completion(&iface->complete);
221 iface->busid = busid;
222
223 dev_set_drvdata(dev, iface);
224
225 sprintf(iface->adapter.name, "smu-i2c-%02x", busid);
226 iface->adapter.algo = &smu_algorithm;
227 iface->adapter.algo_data = NULL;
228 iface->adapter.client_register = NULL;
229 iface->adapter.client_unregister = NULL;
230 i2c_set_adapdata(&iface->adapter, iface);
231 iface->adapter.dev.parent = dev;
232
233 rc = i2c_add_adapter(&iface->adapter);
234 if (rc) {
235 printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration "
236 "failed\n", iface->adapter.name);
237 i2c_set_adapdata(&iface->adapter, NULL);
238 }
239
240 if (probe) {
241 unsigned char addr;
242 printk("Probe: ");
243 for (addr = 0x00; addr <= 0x7f; addr++) {
244 if (i2c_smbus_xfer(&iface->adapter,addr,
245 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
246 printk("%02x ", addr);
247 }
248 printk("\n");
249 }
250
251 printk(KERN_INFO "SMU i2c bus %x registered\n", busid);
252
253 return 0;
254}
255
256static int dispose_iface(struct device *dev)
257{
258 struct smu_iface *iface = dev_get_drvdata(dev);
259 int rc;
260
261 rc = i2c_del_adapter(&iface->adapter);
262 i2c_set_adapdata(&iface->adapter, NULL);
263 /* We aren't that prepared to deal with this... */
264 if (rc)
265 printk("i2c-pmac-smu.c: Failed to remove bus %s !\n",
266 iface->adapter.name);
267 dev_set_drvdata(dev, NULL);
268 kfree(iface);
269
270 return 0;
271}
272
273
274static int create_iface_of_platform(struct of_device* dev,
275 const struct of_device_id *match)
276{
277 return create_iface(dev->node, &dev->dev);
278}
279
280
281static int dispose_iface_of_platform(struct of_device* dev)
282{
283 return dispose_iface(&dev->dev);
284}
285
286
287static struct of_device_id i2c_smu_match[] =
288{
289 {
290 .compatible = "smu-i2c",
291 },
292 {},
293};
294static struct of_platform_driver i2c_smu_of_platform_driver =
295{
296 .name = "i2c-smu",
297 .match_table = i2c_smu_match,
298 .probe = create_iface_of_platform,
299 .remove = dispose_iface_of_platform
300};
301
302
303static int __init i2c_pmac_smu_init(void)
304{
305 of_register_driver(&i2c_smu_of_platform_driver);
306 return 0;
307}
308
309
310static void __exit i2c_pmac_smu_cleanup(void)
311{
312 of_unregister_driver(&i2c_smu_of_platform_driver);
313}
314
315module_init(i2c_pmac_smu_init);
316module_exit(i2c_pmac_smu_cleanup);
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index fb535737d17d..a85ac18dd21d 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -8,21 +8,15 @@
8 */ 8 */
9 9
10/* 10/*
11 * For now, this driver includes:
12 * - RTC get & set
13 * - reboot & shutdown commands
14 * all synchronous with IRQ disabled (ugh)
15 *
16 * TODO: 11 * TODO:
17 * rework in a way the PMU driver works, that is asynchronous 12 * - maybe add timeout to commands ?
18 * with a queue of commands. I'll do that as soon as I have an 13 * - blocking version of time functions
19 * SMU based machine at hand. Some more cleanup is needed too, 14 * - polling version of i2c commands (including timer that works with
20 * like maybe fitting it into a platform device, etc... 15 * interrutps off)
21 * Also check what's up with cache coherency, and if we really 16 * - maybe avoid some data copies with i2c by directly using the smu cmd
22 * can't do better than flushing the cache, maybe build a table 17 * buffer and a lower level internal interface
23 * of command len/reply len like the PMU driver to only flush 18 * - understand SMU -> CPU events and implement reception of them via
24 * what is actually necessary. 19 * the userland interface
25 * --BenH.
26 */ 20 */
27 21
28#include <linux/config.h> 22#include <linux/config.h>
@@ -36,6 +30,11 @@
36#include <linux/jiffies.h> 30#include <linux/jiffies.h>
37#include <linux/interrupt.h> 31#include <linux/interrupt.h>
38#include <linux/rtc.h> 32#include <linux/rtc.h>
33#include <linux/completion.h>
34#include <linux/miscdevice.h>
35#include <linux/delay.h>
36#include <linux/sysdev.h>
37#include <linux/poll.h>
39 38
40#include <asm/byteorder.h> 39#include <asm/byteorder.h>
41#include <asm/io.h> 40#include <asm/io.h>
@@ -45,8 +44,13 @@
45#include <asm/smu.h> 44#include <asm/smu.h>
46#include <asm/sections.h> 45#include <asm/sections.h>
47#include <asm/abs_addr.h> 46#include <asm/abs_addr.h>
47#include <asm/uaccess.h>
48#include <asm/of_device.h>
49
50#define VERSION "0.6"
51#define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp."
48 52
49#define DEBUG_SMU 1 53#undef DEBUG_SMU
50 54
51#ifdef DEBUG_SMU 55#ifdef DEBUG_SMU
52#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) 56#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
@@ -57,20 +61,30 @@
57/* 61/*
58 * This is the command buffer passed to the SMU hardware 62 * This is the command buffer passed to the SMU hardware
59 */ 63 */
64#define SMU_MAX_DATA 254
65
60struct smu_cmd_buf { 66struct smu_cmd_buf {
61 u8 cmd; 67 u8 cmd;
62 u8 length; 68 u8 length;
63 u8 data[0x0FFE]; 69 u8 data[SMU_MAX_DATA];
64}; 70};
65 71
66struct smu_device { 72struct smu_device {
67 spinlock_t lock; 73 spinlock_t lock;
68 struct device_node *of_node; 74 struct device_node *of_node;
69 int db_ack; /* doorbell ack GPIO */ 75 struct of_device *of_dev;
70 int db_req; /* doorbell req GPIO */ 76 int doorbell; /* doorbell gpio */
71 u32 __iomem *db_buf; /* doorbell buffer */ 77 u32 __iomem *db_buf; /* doorbell buffer */
78 int db_irq;
79 int msg;
80 int msg_irq;
72 struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ 81 struct smu_cmd_buf *cmd_buf; /* command buffer virtual */
73 u32 cmd_buf_abs; /* command buffer absolute */ 82 u32 cmd_buf_abs; /* command buffer absolute */
83 struct list_head cmd_list;
84 struct smu_cmd *cmd_cur; /* pending command */
85 struct list_head cmd_i2c_list;
86 struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */
87 struct timer_list i2c_timer;
74}; 88};
75 89
76/* 90/*
@@ -79,113 +93,243 @@ struct smu_device {
79 */ 93 */
80static struct smu_device *smu; 94static struct smu_device *smu;
81 95
96
82/* 97/*
83 * SMU low level communication stuff 98 * SMU driver low level stuff
84 */ 99 */
85static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack)
86{
87 rmb();
88 return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0;
89}
90 100
91static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf) 101static void smu_start_cmd(void)
92{ 102{
93 return (~cmd_buf->cmd) & 0xff; 103 unsigned long faddr, fend;
94} 104 struct smu_cmd *cmd;
95 105
96static void smu_send_cmd(struct smu_device *dev) 106 if (list_empty(&smu->cmd_list))
97{ 107 return;
98 /* SMU command buf is currently cacheable, we need a physical 108
99 * address. This isn't exactly a DMA mapping here, I suspect 109 /* Fetch first command in queue */
110 cmd = list_entry(smu->cmd_list.next, struct smu_cmd, link);
111 smu->cmd_cur = cmd;
112 list_del(&cmd->link);
113
114 DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd,
115 cmd->data_len);
116 DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n",
117 ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1],
118 ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]);
119
120 /* Fill the SMU command buffer */
121 smu->cmd_buf->cmd = cmd->cmd;
122 smu->cmd_buf->length = cmd->data_len;
123 memcpy(smu->cmd_buf->data, cmd->data_buf, cmd->data_len);
124
125 /* Flush command and data to RAM */
126 faddr = (unsigned long)smu->cmd_buf;
127 fend = faddr + smu->cmd_buf->length + 2;
128 flush_inval_dcache_range(faddr, fend);
129
130 /* This isn't exactly a DMA mapping here, I suspect
100 * the SMU is actually communicating with us via i2c to the 131 * the SMU is actually communicating with us via i2c to the
101 * northbridge or the CPU to access RAM. 132 * northbridge or the CPU to access RAM.
102 */ 133 */
103 writel(dev->cmd_buf_abs, dev->db_buf); 134 writel(smu->cmd_buf_abs, smu->db_buf);
104 135
105 /* Ring the SMU doorbell */ 136 /* Ring the SMU doorbell */
106 pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4); 137 pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, smu->doorbell, 4);
107 pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4);
108} 138}
109 139
110static int smu_cmd_done(struct smu_device *dev) 140
141static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs)
111{ 142{
112 unsigned long wait = 0; 143 unsigned long flags;
113 int gpio; 144 struct smu_cmd *cmd;
145 void (*done)(struct smu_cmd *cmd, void *misc) = NULL;
146 void *misc = NULL;
147 u8 gpio;
148 int rc = 0;
114 149
115 /* Check the SMU doorbell */ 150 /* SMU completed the command, well, we hope, let's make sure
116 do { 151 * of it
117 gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, 152 */
118 NULL, dev->db_ack); 153 spin_lock_irqsave(&smu->lock, flags);
119 if ((gpio & 7) == 7)
120 return 0;
121 udelay(100);
122 } while(++wait < 10000);
123 154
124 printk(KERN_ERR "SMU timeout !\n"); 155 gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
125 return -ENXIO; 156 if ((gpio & 7) != 7)
157 return IRQ_HANDLED;
158
159 cmd = smu->cmd_cur;
160 smu->cmd_cur = NULL;
161 if (cmd == NULL)
162 goto bail;
163
164 if (rc == 0) {
165 unsigned long faddr;
166 int reply_len;
167 u8 ack;
168
169 /* CPU might have brought back the cache line, so we need
170 * to flush again before peeking at the SMU response. We
171 * flush the entire buffer for now as we haven't read the
172 * reply lenght (it's only 2 cache lines anyway)
173 */
174 faddr = (unsigned long)smu->cmd_buf;
175 flush_inval_dcache_range(faddr, faddr + 256);
176
177 /* Now check ack */
178 ack = (~cmd->cmd) & 0xff;
179 if (ack != smu->cmd_buf->cmd) {
180 DPRINTK("SMU: incorrect ack, want %x got %x\n",
181 ack, smu->cmd_buf->cmd);
182 rc = -EIO;
183 }
184 reply_len = rc == 0 ? smu->cmd_buf->length : 0;
185 DPRINTK("SMU: reply len: %d\n", reply_len);
186 if (reply_len > cmd->reply_len) {
187 printk(KERN_WARNING "SMU: reply buffer too small,"
188 "got %d bytes for a %d bytes buffer\n",
189 reply_len, cmd->reply_len);
190 reply_len = cmd->reply_len;
191 }
192 cmd->reply_len = reply_len;
193 if (cmd->reply_buf && reply_len)
194 memcpy(cmd->reply_buf, smu->cmd_buf->data, reply_len);
195 }
196
197 /* Now complete the command. Write status last in order as we lost
198 * ownership of the command structure as soon as it's no longer -1
199 */
200 done = cmd->done;
201 misc = cmd->misc;
202 mb();
203 cmd->status = rc;
204 bail:
205 /* Start next command if any */
206 smu_start_cmd();
207 spin_unlock_irqrestore(&smu->lock, flags);
208
209 /* Call command completion handler if any */
210 if (done)
211 done(cmd, misc);
212
213 /* It's an edge interrupt, nothing to do */
214 return IRQ_HANDLED;
126} 215}
127 216
128static int smu_do_cmd(struct smu_device *dev) 217
218static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs)
129{ 219{
130 int rc; 220 /* I don't quite know what to do with this one, we seem to never
131 u8 cmd_ack; 221 * receive it, so I suspect we have to arm it someway in the SMU
222 * to start getting events that way.
223 */
224
225 printk(KERN_INFO "SMU: message interrupt !\n");
132 226
133 DPRINTK("SMU do_cmd %02x len=%d %02x\n", 227 /* It's an edge interrupt, nothing to do */
134 dev->cmd_buf->cmd, dev->cmd_buf->length, 228 return IRQ_HANDLED;
135 dev->cmd_buf->data[0]); 229}
136 230
137 cmd_ack = smu_save_ack_cmd(dev->cmd_buf);
138 231
139 /* Clear cmd_buf cache lines */ 232/*
140 flush_inval_dcache_range((unsigned long)dev->cmd_buf, 233 * Queued command management.
141 ((unsigned long)dev->cmd_buf) + 234 *
142 sizeof(struct smu_cmd_buf)); 235 */
143 smu_send_cmd(dev);
144 rc = smu_cmd_done(dev);
145 if (rc == 0)
146 rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1;
147 236
148 DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n", 237int smu_queue_cmd(struct smu_cmd *cmd)
149 dev->cmd_buf->cmd, dev->cmd_buf->length, 238{
150 dev->cmd_buf->data[0], rc, cmd_ack); 239 unsigned long flags;
151 240
152 return rc; 241 if (smu == NULL)
242 return -ENODEV;
243 if (cmd->data_len > SMU_MAX_DATA ||
244 cmd->reply_len > SMU_MAX_DATA)
245 return -EINVAL;
246
247 cmd->status = 1;
248 spin_lock_irqsave(&smu->lock, flags);
249 list_add_tail(&cmd->link, &smu->cmd_list);
250 if (smu->cmd_cur == NULL)
251 smu_start_cmd();
252 spin_unlock_irqrestore(&smu->lock, flags);
253
254 return 0;
153} 255}
256EXPORT_SYMBOL(smu_queue_cmd);
154 257
155/* RTC low level commands */ 258
156static inline int bcd2hex (int n) 259int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
260 unsigned int data_len,
261 void (*done)(struct smu_cmd *cmd, void *misc),
262 void *misc, ...)
157{ 263{
158 return (((n & 0xf0) >> 4) * 10) + (n & 0xf); 264 struct smu_cmd *cmd = &scmd->cmd;
265 va_list list;
266 int i;
267
268 if (data_len > sizeof(scmd->buffer))
269 return -EINVAL;
270
271 memset(scmd, 0, sizeof(*scmd));
272 cmd->cmd = command;
273 cmd->data_len = data_len;
274 cmd->data_buf = scmd->buffer;
275 cmd->reply_len = sizeof(scmd->buffer);
276 cmd->reply_buf = scmd->buffer;
277 cmd->done = done;
278 cmd->misc = misc;
279
280 va_start(list, misc);
281 for (i = 0; i < data_len; ++i)
282 scmd->buffer[i] = (u8)va_arg(list, int);
283 va_end(list);
284
285 return smu_queue_cmd(cmd);
159} 286}
287EXPORT_SYMBOL(smu_queue_simple);
160 288
161static inline int hex2bcd (int n) 289
290void smu_poll(void)
162{ 291{
163 return ((n / 10) << 4) + (n % 10); 292 u8 gpio;
293
294 if (smu == NULL)
295 return;
296
297 gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
298 if ((gpio & 7) == 7)
299 smu_db_intr(smu->db_irq, smu, NULL);
164} 300}
301EXPORT_SYMBOL(smu_poll);
302
165 303
166#if 0 304void smu_done_complete(struct smu_cmd *cmd, void *misc)
167static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
168{ 305{
169 cmd_buf->cmd = 0x8e; 306 struct completion *comp = misc;
170 cmd_buf->length = 8; 307
171 cmd_buf->data[0] = 0x00; 308 complete(comp);
172 memset(cmd_buf->data + 1, 0, 7);
173} 309}
310EXPORT_SYMBOL(smu_done_complete);
311
174 312
175static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) 313void smu_spinwait_cmd(struct smu_cmd *cmd)
176{ 314{
177 cmd_buf->cmd = 0x8e; 315 while(cmd->status == 1)
178 cmd_buf->length = 1; 316 smu_poll();
179 cmd_buf->data[0] = 0x01; 317}
318EXPORT_SYMBOL(smu_spinwait_cmd);
319
320
321/* RTC low level commands */
322static inline int bcd2hex (int n)
323{
324 return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
180} 325}
181 326
182static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) 327
328static inline int hex2bcd (int n)
183{ 329{
184 cmd_buf->cmd = 0x8e; 330 return ((n / 10) << 4) + (n % 10);
185 cmd_buf->length = 1;
186 cmd_buf->data[0] = 0x02;
187} 331}
188#endif 332
189 333
190static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf, 334static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
191 struct rtc_time *time) 335 struct rtc_time *time)
@@ -202,100 +346,96 @@ static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
202 cmd_buf->data[7] = hex2bcd(time->tm_year - 100); 346 cmd_buf->data[7] = hex2bcd(time->tm_year - 100);
203} 347}
204 348
205static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf)
206{
207 cmd_buf->cmd = 0x8e;
208 cmd_buf->length = 1;
209 cmd_buf->data[0] = 0x81;
210}
211 349
212static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf, 350int smu_get_rtc_time(struct rtc_time *time, int spinwait)
213 struct rtc_time *time)
214{ 351{
215 time->tm_sec = bcd2hex(cmd_buf->data[0]); 352 struct smu_simple_cmd cmd;
216 time->tm_min = bcd2hex(cmd_buf->data[1]);
217 time->tm_hour = bcd2hex(cmd_buf->data[2]);
218 time->tm_wday = bcd2hex(cmd_buf->data[3]);
219 time->tm_mday = bcd2hex(cmd_buf->data[4]);
220 time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1;
221 time->tm_year = bcd2hex(cmd_buf->data[6]) + 100;
222}
223
224int smu_get_rtc_time(struct rtc_time *time)
225{
226 unsigned long flags;
227 int rc; 353 int rc;
228 354
229 if (smu == NULL) 355 if (smu == NULL)
230 return -ENODEV; 356 return -ENODEV;
231 357
232 memset(time, 0, sizeof(struct rtc_time)); 358 memset(time, 0, sizeof(struct rtc_time));
233 spin_lock_irqsave(&smu->lock, flags); 359 rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 1, NULL, NULL,
234 smu_fill_get_rtc_cmd(smu->cmd_buf); 360 SMU_CMD_RTC_GET_DATETIME);
235 rc = smu_do_cmd(smu); 361 if (rc)
236 if (rc == 0) 362 return rc;
237 smu_parse_get_rtc_reply(smu->cmd_buf, time); 363 smu_spinwait_simple(&cmd);
238 spin_unlock_irqrestore(&smu->lock, flags);
239 364
240 return rc; 365 time->tm_sec = bcd2hex(cmd.buffer[0]);
366 time->tm_min = bcd2hex(cmd.buffer[1]);
367 time->tm_hour = bcd2hex(cmd.buffer[2]);
368 time->tm_wday = bcd2hex(cmd.buffer[3]);
369 time->tm_mday = bcd2hex(cmd.buffer[4]);
370 time->tm_mon = bcd2hex(cmd.buffer[5]) - 1;
371 time->tm_year = bcd2hex(cmd.buffer[6]) + 100;
372
373 return 0;
241} 374}
242 375
243int smu_set_rtc_time(struct rtc_time *time) 376
377int smu_set_rtc_time(struct rtc_time *time, int spinwait)
244{ 378{
245 unsigned long flags; 379 struct smu_simple_cmd cmd;
246 int rc; 380 int rc;
247 381
248 if (smu == NULL) 382 if (smu == NULL)
249 return -ENODEV; 383 return -ENODEV;
250 384
251 spin_lock_irqsave(&smu->lock, flags); 385 rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 8, NULL, NULL,
252 smu_fill_set_rtc_cmd(smu->cmd_buf, time); 386 SMU_CMD_RTC_SET_DATETIME,
253 rc = smu_do_cmd(smu); 387 hex2bcd(time->tm_sec),
254 spin_unlock_irqrestore(&smu->lock, flags); 388 hex2bcd(time->tm_min),
389 hex2bcd(time->tm_hour),
390 time->tm_wday,
391 hex2bcd(time->tm_mday),
392 hex2bcd(time->tm_mon) + 1,
393 hex2bcd(time->tm_year - 100));
394 if (rc)
395 return rc;
396 smu_spinwait_simple(&cmd);
255 397
256 return rc; 398 return 0;
257} 399}
258 400
401
259void smu_shutdown(void) 402void smu_shutdown(void)
260{ 403{
261 const unsigned char *command = "SHUTDOWN"; 404 struct smu_simple_cmd cmd;
262 unsigned long flags;
263 405
264 if (smu == NULL) 406 if (smu == NULL)
265 return; 407 return;
266 408
267 spin_lock_irqsave(&smu->lock, flags); 409 if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 9, NULL, NULL,
268 smu->cmd_buf->cmd = 0xaa; 410 'S', 'H', 'U', 'T', 'D', 'O', 'W', 'N', 0))
269 smu->cmd_buf->length = strlen(command); 411 return;
270 strcpy(smu->cmd_buf->data, command); 412 smu_spinwait_simple(&cmd);
271 smu_do_cmd(smu);
272 for (;;) 413 for (;;)
273 ; 414 ;
274 spin_unlock_irqrestore(&smu->lock, flags);
275} 415}
276 416
417
277void smu_restart(void) 418void smu_restart(void)
278{ 419{
279 const unsigned char *command = "RESTART"; 420 struct smu_simple_cmd cmd;
280 unsigned long flags;
281 421
282 if (smu == NULL) 422 if (smu == NULL)
283 return; 423 return;
284 424
285 spin_lock_irqsave(&smu->lock, flags); 425 if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, NULL, NULL,
286 smu->cmd_buf->cmd = 0xaa; 426 'R', 'E', 'S', 'T', 'A', 'R', 'T', 0))
287 smu->cmd_buf->length = strlen(command); 427 return;
288 strcpy(smu->cmd_buf->data, command); 428 smu_spinwait_simple(&cmd);
289 smu_do_cmd(smu);
290 for (;;) 429 for (;;)
291 ; 430 ;
292 spin_unlock_irqrestore(&smu->lock, flags);
293} 431}
294 432
433
295int smu_present(void) 434int smu_present(void)
296{ 435{
297 return smu != NULL; 436 return smu != NULL;
298} 437}
438EXPORT_SYMBOL(smu_present);
299 439
300 440
301int smu_init (void) 441int smu_init (void)
@@ -307,6 +447,8 @@ int smu_init (void)
307 if (np == NULL) 447 if (np == NULL)
308 return -ENODEV; 448 return -ENODEV;
309 449
450 printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR);
451
310 if (smu_cmdbuf_abs == 0) { 452 if (smu_cmdbuf_abs == 0) {
311 printk(KERN_ERR "SMU: Command buffer not allocated !\n"); 453 printk(KERN_ERR "SMU: Command buffer not allocated !\n");
312 return -EINVAL; 454 return -EINVAL;
@@ -318,7 +460,13 @@ int smu_init (void)
318 memset(smu, 0, sizeof(*smu)); 460 memset(smu, 0, sizeof(*smu));
319 461
320 spin_lock_init(&smu->lock); 462 spin_lock_init(&smu->lock);
463 INIT_LIST_HEAD(&smu->cmd_list);
464 INIT_LIST_HEAD(&smu->cmd_i2c_list);
321 smu->of_node = np; 465 smu->of_node = np;
466 smu->db_irq = NO_IRQ;
467 smu->msg_irq = NO_IRQ;
468 init_timer(&smu->i2c_timer);
469
322 /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a 470 /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
323 * 32 bits value safely 471 * 32 bits value safely
324 */ 472 */
@@ -331,8 +479,8 @@ int smu_init (void)
331 goto fail; 479 goto fail;
332 } 480 }
333 data = (u32 *)get_property(np, "reg", NULL); 481 data = (u32 *)get_property(np, "reg", NULL);
334 of_node_put(np);
335 if (data == NULL) { 482 if (data == NULL) {
483 of_node_put(np);
336 printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); 484 printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
337 goto fail; 485 goto fail;
338 } 486 }
@@ -341,8 +489,31 @@ int smu_init (void)
341 * and ack. GPIOs are at 0x50, best would be to find that out 489 * and ack. GPIOs are at 0x50, best would be to find that out
342 * in the device-tree though. 490 * in the device-tree though.
343 */ 491 */
344 smu->db_req = 0x50 + *data; 492 smu->doorbell = *data;
345 smu->db_ack = 0x50 + *data; 493 if (smu->doorbell < 0x50)
494 smu->doorbell += 0x50;
495 if (np->n_intrs > 0)
496 smu->db_irq = np->intrs[0].line;
497
498 of_node_put(np);
499
500 /* Now look for the smu-interrupt GPIO */
501 do {
502 np = of_find_node_by_name(NULL, "smu-interrupt");
503 if (np == NULL)
504 break;
505 data = (u32 *)get_property(np, "reg", NULL);
506 if (data == NULL) {
507 of_node_put(np);
508 break;
509 }
510 smu->msg = *data;
511 if (smu->msg < 0x50)
512 smu->msg += 0x50;
513 if (np->n_intrs > 0)
514 smu->msg_irq = np->intrs[0].line;
515 of_node_put(np);
516 } while(0);
346 517
347 /* Doorbell buffer is currently hard-coded, I didn't find a proper 518 /* Doorbell buffer is currently hard-coded, I didn't find a proper
348 * device-tree entry giving the address. Best would probably to use 519 * device-tree entry giving the address. Best would probably to use
@@ -362,3 +533,584 @@ int smu_init (void)
362 return -ENXIO; 533 return -ENXIO;
363 534
364} 535}
536
537
538static int smu_late_init(void)
539{
540 if (!smu)
541 return 0;
542
543 /*
544 * Try to request the interrupts
545 */
546
547 if (smu->db_irq != NO_IRQ) {
548 if (request_irq(smu->db_irq, smu_db_intr,
549 SA_SHIRQ, "SMU doorbell", smu) < 0) {
550 printk(KERN_WARNING "SMU: can't "
551 "request interrupt %d\n",
552 smu->db_irq);
553 smu->db_irq = NO_IRQ;
554 }
555 }
556
557 if (smu->msg_irq != NO_IRQ) {
558 if (request_irq(smu->msg_irq, smu_msg_intr,
559 SA_SHIRQ, "SMU message", smu) < 0) {
560 printk(KERN_WARNING "SMU: can't "
561 "request interrupt %d\n",
562 smu->msg_irq);
563 smu->msg_irq = NO_IRQ;
564 }
565 }
566
567 return 0;
568}
569arch_initcall(smu_late_init);
570
571/*
572 * sysfs visibility
573 */
574
575static void smu_expose_childs(void *unused)
576{
577 struct device_node *np;
578
579 for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) {
580 if (device_is_compatible(np, "smu-i2c")) {
581 char name[32];
582 u32 *reg = (u32 *)get_property(np, "reg", NULL);
583
584 if (reg == NULL)
585 continue;
586 sprintf(name, "smu-i2c-%02x", *reg);
587 of_platform_device_create(np, name, &smu->of_dev->dev);
588 }
589 }
590
591}
592
593static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL);
594
595static int smu_platform_probe(struct of_device* dev,
596 const struct of_device_id *match)
597{
598 if (!smu)
599 return -ENODEV;
600 smu->of_dev = dev;
601
602 /*
603 * Ok, we are matched, now expose all i2c busses. We have to defer
604 * that unfortunately or it would deadlock inside the device model
605 */
606 schedule_work(&smu_expose_childs_work);
607
608 return 0;
609}
610
611static struct of_device_id smu_platform_match[] =
612{
613 {
614 .type = "smu",
615 },
616 {},
617};
618
619static struct of_platform_driver smu_of_platform_driver =
620{
621 .name = "smu",
622 .match_table = smu_platform_match,
623 .probe = smu_platform_probe,
624};
625
626static int __init smu_init_sysfs(void)
627{
628 int rc;
629
630 /*
631 * Due to sysfs bogosity, a sysdev is not a real device, so
632 * we should in fact create both if we want sysdev semantics
633 * for power management.
634 * For now, we don't power manage machines with an SMU chip,
635 * I'm a bit too far from figuring out how that works with those
636 * new chipsets, but that will come back and bite us
637 */
638 rc = of_register_driver(&smu_of_platform_driver);
639 return 0;
640}
641
642device_initcall(smu_init_sysfs);
643
644struct of_device *smu_get_ofdev(void)
645{
646 if (!smu)
647 return NULL;
648 return smu->of_dev;
649}
650
651EXPORT_SYMBOL_GPL(smu_get_ofdev);
652
653/*
654 * i2c interface
655 */
656
657static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail)
658{
659 void (*done)(struct smu_i2c_cmd *cmd, void *misc) = cmd->done;
660 void *misc = cmd->misc;
661 unsigned long flags;
662
663 /* Check for read case */
664 if (!fail && cmd->read) {
665 if (cmd->pdata[0] < 1)
666 fail = 1;
667 else
668 memcpy(cmd->info.data, &cmd->pdata[1],
669 cmd->info.datalen);
670 }
671
672 DPRINTK("SMU: completing, success: %d\n", !fail);
673
674 /* Update status and mark no pending i2c command with lock
675 * held so nobody comes in while we dequeue an eventual
676 * pending next i2c command
677 */
678 spin_lock_irqsave(&smu->lock, flags);
679 smu->cmd_i2c_cur = NULL;
680 wmb();
681 cmd->status = fail ? -EIO : 0;
682
683 /* Is there another i2c command waiting ? */
684 if (!list_empty(&smu->cmd_i2c_list)) {
685 struct smu_i2c_cmd *newcmd;
686
687 /* Fetch it, new current, remove from list */
688 newcmd = list_entry(smu->cmd_i2c_list.next,
689 struct smu_i2c_cmd, link);
690 smu->cmd_i2c_cur = newcmd;
691 list_del(&cmd->link);
692
693 /* Queue with low level smu */
694 list_add_tail(&cmd->scmd.link, &smu->cmd_list);
695 if (smu->cmd_cur == NULL)
696 smu_start_cmd();
697 }
698 spin_unlock_irqrestore(&smu->lock, flags);
699
700 /* Call command completion handler if any */
701 if (done)
702 done(cmd, misc);
703
704}
705
706
707static void smu_i2c_retry(unsigned long data)
708{
709 struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data;
710
711 DPRINTK("SMU: i2c failure, requeuing...\n");
712
713 /* requeue command simply by resetting reply_len */
714 cmd->pdata[0] = 0xff;
715 cmd->scmd.reply_len = 0x10;
716 smu_queue_cmd(&cmd->scmd);
717}
718
719
720static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
721{
722 struct smu_i2c_cmd *cmd = misc;
723 int fail = 0;
724
725 DPRINTK("SMU: i2c compl. stage=%d status=%x pdata[0]=%x rlen: %x\n",
726 cmd->stage, scmd->status, cmd->pdata[0], scmd->reply_len);
727
728 /* Check for possible status */
729 if (scmd->status < 0)
730 fail = 1;
731 else if (cmd->read) {
732 if (cmd->stage == 0)
733 fail = cmd->pdata[0] != 0;
734 else
735 fail = cmd->pdata[0] >= 0x80;
736 } else {
737 fail = cmd->pdata[0] != 0;
738 }
739
740 /* Handle failures by requeuing command, after 5ms interval
741 */
742 if (fail && --cmd->retries > 0) {
743 DPRINTK("SMU: i2c failure, starting timer...\n");
744 smu->i2c_timer.function = smu_i2c_retry;
745 smu->i2c_timer.data = (unsigned long)cmd;
746 smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5);
747 add_timer(&smu->i2c_timer);
748 return;
749 }
750
751 /* If failure or stage 1, command is complete */
752 if (fail || cmd->stage != 0) {
753 smu_i2c_complete_command(cmd, fail);
754 return;
755 }
756
757 DPRINTK("SMU: going to stage 1\n");
758
759 /* Ok, initial command complete, now poll status */
760 scmd->reply_buf = cmd->pdata;
761 scmd->reply_len = 0x10;
762 scmd->data_buf = cmd->pdata;
763 scmd->data_len = 1;
764 cmd->pdata[0] = 0;
765 cmd->stage = 1;
766 cmd->retries = 20;
767 smu_queue_cmd(scmd);
768}
769
770
771int smu_queue_i2c(struct smu_i2c_cmd *cmd)
772{
773 unsigned long flags;
774
775 if (smu == NULL)
776 return -ENODEV;
777
778 /* Fill most fields of scmd */
779 cmd->scmd.cmd = SMU_CMD_I2C_COMMAND;
780 cmd->scmd.done = smu_i2c_low_completion;
781 cmd->scmd.misc = cmd;
782 cmd->scmd.reply_buf = cmd->pdata;
783 cmd->scmd.reply_len = 0x10;
784 cmd->scmd.data_buf = (u8 *)(char *)&cmd->info;
785 cmd->scmd.status = 1;
786 cmd->stage = 0;
787 cmd->pdata[0] = 0xff;
788 cmd->retries = 20;
789 cmd->status = 1;
790
791 /* Check transfer type, sanitize some "info" fields
792 * based on transfer type and do more checking
793 */
794 cmd->info.caddr = cmd->info.devaddr;
795 cmd->read = cmd->info.devaddr & 0x01;
796 switch(cmd->info.type) {
797 case SMU_I2C_TRANSFER_SIMPLE:
798 memset(&cmd->info.sublen, 0, 4);
799 break;
800 case SMU_I2C_TRANSFER_COMBINED:
801 cmd->info.devaddr &= 0xfe;
802 case SMU_I2C_TRANSFER_STDSUB:
803 if (cmd->info.sublen > 3)
804 return -EINVAL;
805 break;
806 default:
807 return -EINVAL;
808 }
809
810 /* Finish setting up command based on transfer direction
811 */
812 if (cmd->read) {
813 if (cmd->info.datalen > SMU_I2C_READ_MAX)
814 return -EINVAL;
815 memset(cmd->info.data, 0xff, cmd->info.datalen);
816 cmd->scmd.data_len = 9;
817 } else {
818 if (cmd->info.datalen > SMU_I2C_WRITE_MAX)
819 return -EINVAL;
820 cmd->scmd.data_len = 9 + cmd->info.datalen;
821 }
822
823 DPRINTK("SMU: i2c enqueuing command\n");
824 DPRINTK("SMU: %s, len=%d bus=%x addr=%x sub0=%x type=%x\n",
825 cmd->read ? "read" : "write", cmd->info.datalen,
826 cmd->info.bus, cmd->info.caddr,
827 cmd->info.subaddr[0], cmd->info.type);
828
829
830 /* Enqueue command in i2c list, and if empty, enqueue also in
831 * main command list
832 */
833 spin_lock_irqsave(&smu->lock, flags);
834 if (smu->cmd_i2c_cur == NULL) {
835 smu->cmd_i2c_cur = cmd;
836 list_add_tail(&cmd->scmd.link, &smu->cmd_list);
837 if (smu->cmd_cur == NULL)
838 smu_start_cmd();
839 } else
840 list_add_tail(&cmd->link, &smu->cmd_i2c_list);
841 spin_unlock_irqrestore(&smu->lock, flags);
842
843 return 0;
844}
845
846
847
848/*
849 * Userland driver interface
850 */
851
852
853static LIST_HEAD(smu_clist);
854static DEFINE_SPINLOCK(smu_clist_lock);
855
856enum smu_file_mode {
857 smu_file_commands,
858 smu_file_events,
859 smu_file_closing
860};
861
862struct smu_private
863{
864 struct list_head list;
865 enum smu_file_mode mode;
866 int busy;
867 struct smu_cmd cmd;
868 spinlock_t lock;
869 wait_queue_head_t wait;
870 u8 buffer[SMU_MAX_DATA];
871};
872
873
874static int smu_open(struct inode *inode, struct file *file)
875{
876 struct smu_private *pp;
877 unsigned long flags;
878
879 pp = kmalloc(sizeof(struct smu_private), GFP_KERNEL);
880 if (pp == 0)
881 return -ENOMEM;
882 memset(pp, 0, sizeof(struct smu_private));
883 spin_lock_init(&pp->lock);
884 pp->mode = smu_file_commands;
885 init_waitqueue_head(&pp->wait);
886
887 spin_lock_irqsave(&smu_clist_lock, flags);
888 list_add(&pp->list, &smu_clist);
889 spin_unlock_irqrestore(&smu_clist_lock, flags);
890 file->private_data = pp;
891
892 return 0;
893}
894
895
896static void smu_user_cmd_done(struct smu_cmd *cmd, void *misc)
897{
898 struct smu_private *pp = misc;
899
900 wake_up_all(&pp->wait);
901}
902
903
904static ssize_t smu_write(struct file *file, const char __user *buf,
905 size_t count, loff_t *ppos)
906{
907 struct smu_private *pp = file->private_data;
908 unsigned long flags;
909 struct smu_user_cmd_hdr hdr;
910 int rc = 0;
911
912 if (pp->busy)
913 return -EBUSY;
914 else if (copy_from_user(&hdr, buf, sizeof(hdr)))
915 return -EFAULT;
916 else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) {
917 pp->mode = smu_file_events;
918 return 0;
919 } else if (hdr.cmdtype != SMU_CMDTYPE_SMU)
920 return -EINVAL;
921 else if (pp->mode != smu_file_commands)
922 return -EBADFD;
923 else if (hdr.data_len > SMU_MAX_DATA)
924 return -EINVAL;
925
926 spin_lock_irqsave(&pp->lock, flags);
927 if (pp->busy) {
928 spin_unlock_irqrestore(&pp->lock, flags);
929 return -EBUSY;
930 }
931 pp->busy = 1;
932 pp->cmd.status = 1;
933 spin_unlock_irqrestore(&pp->lock, flags);
934
935 if (copy_from_user(pp->buffer, buf + sizeof(hdr), hdr.data_len)) {
936 pp->busy = 0;
937 return -EFAULT;
938 }
939
940 pp->cmd.cmd = hdr.cmd;
941 pp->cmd.data_len = hdr.data_len;
942 pp->cmd.reply_len = SMU_MAX_DATA;
943 pp->cmd.data_buf = pp->buffer;
944 pp->cmd.reply_buf = pp->buffer;
945 pp->cmd.done = smu_user_cmd_done;
946 pp->cmd.misc = pp;
947 rc = smu_queue_cmd(&pp->cmd);
948 if (rc < 0)
949 return rc;
950 return count;
951}
952
953
954static ssize_t smu_read_command(struct file *file, struct smu_private *pp,
955 char __user *buf, size_t count)
956{
957 DECLARE_WAITQUEUE(wait, current);
958 struct smu_user_reply_hdr hdr;
959 unsigned long flags;
960 int size, rc = 0;
961
962 if (!pp->busy)
963 return 0;
964 if (count < sizeof(struct smu_user_reply_hdr))
965 return -EOVERFLOW;
966 spin_lock_irqsave(&pp->lock, flags);
967 if (pp->cmd.status == 1) {
968 if (file->f_flags & O_NONBLOCK)
969 return -EAGAIN;
970 add_wait_queue(&pp->wait, &wait);
971 for (;;) {
972 set_current_state(TASK_INTERRUPTIBLE);
973 rc = 0;
974 if (pp->cmd.status != 1)
975 break;
976 rc = -ERESTARTSYS;
977 if (signal_pending(current))
978 break;
979 spin_unlock_irqrestore(&pp->lock, flags);
980 schedule();
981 spin_lock_irqsave(&pp->lock, flags);
982 }
983 set_current_state(TASK_RUNNING);
984 remove_wait_queue(&pp->wait, &wait);
985 }
986 spin_unlock_irqrestore(&pp->lock, flags);
987 if (rc)
988 return rc;
989 if (pp->cmd.status != 0)
990 pp->cmd.reply_len = 0;
991 size = sizeof(hdr) + pp->cmd.reply_len;
992 if (count < size)
993 size = count;
994 rc = size;
995 hdr.status = pp->cmd.status;
996 hdr.reply_len = pp->cmd.reply_len;
997 if (copy_to_user(buf, &hdr, sizeof(hdr)))
998 return -EFAULT;
999 size -= sizeof(hdr);
1000 if (size && copy_to_user(buf + sizeof(hdr), pp->buffer, size))
1001 return -EFAULT;
1002 pp->busy = 0;
1003
1004 return rc;
1005}
1006
1007
1008static ssize_t smu_read_events(struct file *file, struct smu_private *pp,
1009 char __user *buf, size_t count)
1010{
1011 /* Not implemented */
1012 msleep_interruptible(1000);
1013 return 0;
1014}
1015
1016
1017static ssize_t smu_read(struct file *file, char __user *buf,
1018 size_t count, loff_t *ppos)
1019{
1020 struct smu_private *pp = file->private_data;
1021
1022 if (pp->mode == smu_file_commands)
1023 return smu_read_command(file, pp, buf, count);
1024 if (pp->mode == smu_file_events)
1025 return smu_read_events(file, pp, buf, count);
1026
1027 return -EBADFD;
1028}
1029
1030static unsigned int smu_fpoll(struct file *file, poll_table *wait)
1031{
1032 struct smu_private *pp = file->private_data;
1033 unsigned int mask = 0;
1034 unsigned long flags;
1035
1036 if (pp == 0)
1037 return 0;
1038
1039 if (pp->mode == smu_file_commands) {
1040 poll_wait(file, &pp->wait, wait);
1041
1042 spin_lock_irqsave(&pp->lock, flags);
1043 if (pp->busy && pp->cmd.status != 1)
1044 mask |= POLLIN;
1045 spin_unlock_irqrestore(&pp->lock, flags);
1046 } if (pp->mode == smu_file_events) {
1047 /* Not yet implemented */
1048 }
1049 return mask;
1050}
1051
1052static int smu_release(struct inode *inode, struct file *file)
1053{
1054 struct smu_private *pp = file->private_data;
1055 unsigned long flags;
1056 unsigned int busy;
1057
1058 if (pp == 0)
1059 return 0;
1060
1061 file->private_data = NULL;
1062
1063 /* Mark file as closing to avoid races with new request */
1064 spin_lock_irqsave(&pp->lock, flags);
1065 pp->mode = smu_file_closing;
1066 busy = pp->busy;
1067
1068 /* Wait for any pending request to complete */
1069 if (busy && pp->cmd.status == 1) {
1070 DECLARE_WAITQUEUE(wait, current);
1071
1072 add_wait_queue(&pp->wait, &wait);
1073 for (;;) {
1074 set_current_state(TASK_UNINTERRUPTIBLE);
1075 if (pp->cmd.status != 1)
1076 break;
1077 spin_lock_irqsave(&pp->lock, flags);
1078 schedule();
1079 spin_unlock_irqrestore(&pp->lock, flags);
1080 }
1081 set_current_state(TASK_RUNNING);
1082 remove_wait_queue(&pp->wait, &wait);
1083 }
1084 spin_unlock_irqrestore(&pp->lock, flags);
1085
1086 spin_lock_irqsave(&smu_clist_lock, flags);
1087 list_del(&pp->list);
1088 spin_unlock_irqrestore(&smu_clist_lock, flags);
1089 kfree(pp);
1090
1091 return 0;
1092}
1093
1094
1095static struct file_operations smu_device_fops __pmacdata = {
1096 .llseek = no_llseek,
1097 .read = smu_read,
1098 .write = smu_write,
1099 .poll = smu_fpoll,
1100 .open = smu_open,
1101 .release = smu_release,
1102};
1103
1104static struct miscdevice pmu_device __pmacdata = {
1105 MISC_DYNAMIC_MINOR, "smu", &smu_device_fops
1106};
1107
1108static int smu_device_init(void)
1109{
1110 if (!smu)
1111 return -ENODEV;
1112 if (misc_register(&pmu_device) < 0)
1113 printk(KERN_ERR "via-pmu: cannot register misc device.\n");
1114 return 0;
1115}
1116device_initcall(smu_device_init);
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index c9ca1118e449..f38696622eb4 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -599,7 +599,7 @@ thermostat_init(void)
599 sensor_location[2] = "?"; 599 sensor_location[2] = "?";
600 } 600 }
601 601
602 of_dev = of_platform_device_create(np, "temperatures"); 602 of_dev = of_platform_device_create(np, "temperatures", NULL);
603 603
604 if (of_dev == NULL) { 604 if (of_dev == NULL) {
605 printk(KERN_ERR "Can't register temperatures device !\n"); 605 printk(KERN_ERR "Can't register temperatures device !\n");
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 703e31973314..cc507ceef153 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -2051,7 +2051,7 @@ static int __init therm_pm72_init(void)
2051 return -ENODEV; 2051 return -ENODEV;
2052 } 2052 }
2053 } 2053 }
2054 of_dev = of_platform_device_create(np, "temperature"); 2054 of_dev = of_platform_device_create(np, "temperature", NULL);
2055 if (of_dev == NULL) { 2055 if (of_dev == NULL) {
2056 printk(KERN_ERR "Can't register FCU platform device !\n"); 2056 printk(KERN_ERR "Can't register FCU platform device !\n");
2057 return -ENODEV; 2057 return -ENODEV;
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index cbb72eb0426d..6aaa1df1a64e 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -504,7 +504,7 @@ g4fan_init( void )
504 } 504 }
505 if( !(np=of_find_node_by_name(NULL, "fan")) ) 505 if( !(np=of_find_node_by_name(NULL, "fan")) )
506 return -ENODEV; 506 return -ENODEV;
507 x.of_dev = of_platform_device_create( np, "temperature" ); 507 x.of_dev = of_platform_device_create(np, "temperature", NULL);
508 of_node_put( np ); 508 of_node_put( np );
509 509
510 if( !x.of_dev ) { 510 if( !x.of_dev ) {
diff --git a/include/asm-ppc/macio.h b/include/asm-ppc/macio.h
index a481b772d154..b553dd4b139e 100644
--- a/include/asm-ppc/macio.h
+++ b/include/asm-ppc/macio.h
@@ -1,7 +1,6 @@
1#ifndef __MACIO_ASIC_H__ 1#ifndef __MACIO_ASIC_H__
2#define __MACIO_ASIC_H__ 2#define __MACIO_ASIC_H__
3 3
4#include <linux/mod_devicetable.h>
5#include <asm/of_device.h> 4#include <asm/of_device.h>
6 5
7extern struct bus_type macio_bus_type; 6extern struct bus_type macio_bus_type;
diff --git a/include/asm-ppc/of_device.h b/include/asm-ppc/of_device.h
index 4b264cfd3998..575bce418f80 100644
--- a/include/asm-ppc/of_device.h
+++ b/include/asm-ppc/of_device.h
@@ -2,6 +2,7 @@
2#define __OF_DEVICE_H__ 2#define __OF_DEVICE_H__
3 3
4#include <linux/device.h> 4#include <linux/device.h>
5#include <linux/mod_devicetable.h>
5#include <asm/prom.h> 6#include <asm/prom.h>
6 7
7/* 8/*
@@ -55,7 +56,9 @@ extern int of_register_driver(struct of_platform_driver *drv);
55extern void of_unregister_driver(struct of_platform_driver *drv); 56extern void of_unregister_driver(struct of_platform_driver *drv);
56extern int of_device_register(struct of_device *ofdev); 57extern int of_device_register(struct of_device *ofdev);
57extern void of_device_unregister(struct of_device *ofdev); 58extern void of_device_unregister(struct of_device *ofdev);
58extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id); 59extern struct of_device *of_platform_device_create(struct device_node *np,
60 const char *bus_id,
61 struct device *parent);
59extern void of_release_dev(struct device *dev); 62extern void of_release_dev(struct device *dev);
60 63
61#endif /* __OF_DEVICE_H__ */ 64#endif /* __OF_DEVICE_H__ */
diff --git a/include/asm-ppc64/smu.h b/include/asm-ppc64/smu.h
index 10b4397af9aa..dee8eefe47bc 100644
--- a/include/asm-ppc64/smu.h
+++ b/include/asm-ppc64/smu.h
@@ -1,22 +1,379 @@
1#ifndef _SMU_H
2#define _SMU_H
3
1/* 4/*
2 * Definitions for talking to the SMU chip in newer G5 PowerMacs 5 * Definitions for talking to the SMU chip in newer G5 PowerMacs
3 */ 6 */
4 7
5#include <linux/config.h> 8#include <linux/config.h>
9#include <linux/list.h>
10
11/*
12 * Known SMU commands
13 *
14 * Most of what is below comes from looking at the Open Firmware driver,
15 * though this is still incomplete and could use better documentation here
16 * or there...
17 */
18
19
20/*
21 * Partition info commands
22 *
23 * I do not know what those are for at this point
24 */
25#define SMU_CMD_PARTITION_COMMAND 0x3e
26
27
28/*
29 * Fan control
30 *
31 * This is a "mux" for fan control commands, first byte is the
32 * "sub" command.
33 */
34#define SMU_CMD_FAN_COMMAND 0x4a
35
36
37/*
38 * Battery access
39 *
40 * Same command number as the PMU, could it be same syntax ?
41 */
42#define SMU_CMD_BATTERY_COMMAND 0x6f
43#define SMU_CMD_GET_BATTERY_INFO 0x00
44
45/*
46 * Real time clock control
47 *
48 * This is a "mux", first data byte contains the "sub" command.
49 * The "RTC" part of the SMU controls the date, time, powerup
50 * timer, but also a PRAM
51 *
52 * Dates are in BCD format on 7 bytes:
53 * [sec] [min] [hour] [weekday] [month day] [month] [year]
54 * with month being 1 based and year minus 100
55 */
56#define SMU_CMD_RTC_COMMAND 0x8e
57#define SMU_CMD_RTC_SET_PWRUP_TIMER 0x00 /* i: 7 bytes date */
58#define SMU_CMD_RTC_GET_PWRUP_TIMER 0x01 /* o: 7 bytes date */
59#define SMU_CMD_RTC_STOP_PWRUP_TIMER 0x02
60#define SMU_CMD_RTC_SET_PRAM_BYTE_ACC 0x20 /* i: 1 byte (address?) */
61#define SMU_CMD_RTC_SET_PRAM_AUTOINC 0x21 /* i: 1 byte (data?) */
62#define SMU_CMD_RTC_SET_PRAM_LO_BYTES 0x22 /* i: 10 bytes */
63#define SMU_CMD_RTC_SET_PRAM_HI_BYTES 0x23 /* i: 10 bytes */
64#define SMU_CMD_RTC_GET_PRAM_BYTE 0x28 /* i: 1 bytes (address?) */
65#define SMU_CMD_RTC_GET_PRAM_LO_BYTES 0x29 /* o: 10 bytes */
66#define SMU_CMD_RTC_GET_PRAM_HI_BYTES 0x2a /* o: 10 bytes */
67#define SMU_CMD_RTC_SET_DATETIME 0x80 /* i: 7 bytes date */
68#define SMU_CMD_RTC_GET_DATETIME 0x81 /* o: 7 bytes date */
69
70 /*
71 * i2c commands
72 *
73 * To issue an i2c command, first is to send a parameter block to the
74 * the SMU. This is a command of type 0x9a with 9 bytes of header
75 * eventually followed by data for a write:
76 *
77 * 0: bus number (from device-tree usually, SMU has lots of busses !)
78 * 1: transfer type/format (see below)
79 * 2: device address. For combined and combined4 type transfers, this
80 * is the "write" version of the address (bit 0x01 cleared)
81 * 3: subaddress length (0..3)
82 * 4: subaddress byte 0 (or only byte for subaddress length 1)
83 * 5: subaddress byte 1
84 * 6: subaddress byte 2
85 * 7: combined address (device address for combined mode data phase)
86 * 8: data length
87 *
88 * The transfer types are the same good old Apple ones it seems,
89 * that is:
90 * - 0x00: Simple transfer
91 * - 0x01: Subaddress transfer (addr write + data tx, no restart)
92 * - 0x02: Combined transfer (addr write + restart + data tx)
93 *
94 * This is then followed by actual data for a write.
95 *
96 * At this point, the OF driver seems to have a limitation on transfer
97 * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know
98 * wether this is just an OF limit due to some temporary buffer size
99 * or if this is an SMU imposed limit. This driver has the same limitation
100 * for now as I use a 0x10 bytes temporary buffer as well
101 *
102 * Once that is completed, a response is expected from the SMU. This is
103 * obtained via a command of type 0x9a with a length of 1 byte containing
104 * 0 as the data byte. OF also fills the rest of the data buffer with 0xff's
105 * though I can't tell yet if this is actually necessary. Once this command
106 * is complete, at this point, all I can tell is what OF does. OF tests
107 * byte 0 of the reply:
108 * - on read, 0xfe or 0xfc : bus is busy, wait (see below) or nak ?
109 * - on read, 0x00 or 0x01 : reply is in buffer (after the byte 0)
110 * - on write, < 0 -> failure (immediate exit)
111 * - else, OF just exists (without error, weird)
112 *
113 * So on read, there is this wait-for-busy thing when getting a 0xfc or
114 * 0xfe result. OF does a loop of up to 64 retries, waiting 20ms and
115 * doing the above again until either the retries expire or the result
116 * is no longer 0xfe or 0xfc
117 *
118 * The Darwin I2C driver is less subtle though. On any non-success status
119 * from the response command, it waits 5ms and tries again up to 20 times,
120 * it doesn't differenciate between fatal errors or "busy" status.
121 *
122 * This driver provides an asynchronous paramblock based i2c command
123 * interface to be used either directly by low level code or by a higher
124 * level driver interfacing to the linux i2c layer. The current
125 * implementation of this relies on working timers & timer interrupts
126 * though, so be careful of calling context for now. This may be "fixed"
127 * in the future by adding a polling facility.
128 */
129#define SMU_CMD_I2C_COMMAND 0x9a
130 /* transfer types */
131#define SMU_I2C_TRANSFER_SIMPLE 0x00
132#define SMU_I2C_TRANSFER_STDSUB 0x01
133#define SMU_I2C_TRANSFER_COMBINED 0x02
134
135/*
136 * Power supply control
137 *
138 * The "sub" command is an ASCII string in the data, the
139 * data lenght is that of the string.
140 *
141 * The VSLEW command can be used to get or set the voltage slewing.
142 * - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
143 * reply at data offset 6, 7 and 8.
144 * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is
145 * used to set the voltage slewing point. The SMU replies with "DONE"
146 * I yet have to figure out their exact meaning of those 3 bytes in
147 * both cases.
148 *
149 */
150#define SMU_CMD_POWER_COMMAND 0xaa
151#define SMU_CMD_POWER_RESTART "RESTART"
152#define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN"
153#define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW"
154
155/* Misc commands
156 *
157 * This command seem to be a grab bag of various things
158 */
159#define SMU_CMD_MISC_df_COMMAND 0xdf
160#define SMU_CMD_MISC_df_SET_DISPLAY_LIT 0x02 /* i: 1 byte */
161#define SMU_CMD_MISC_df_NMI_OPTION 0x04
162
163/*
164 * Version info commands
165 *
166 * I haven't quite tried to figure out how these work
167 */
168#define SMU_CMD_VERSION_COMMAND 0xea
169
170
171/*
172 * Misc commands
173 *
174 * This command seem to be a grab bag of various things
175 */
176#define SMU_CMD_MISC_ee_COMMAND 0xee
177#define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02
178#define SMU_CMD_MISC_ee_LEDS_CTRL 0x04 /* i: 00 (00,01) [00] */
179#define SMU_CMD_MISC_ee_GET_DATA 0x05 /* i: 00 , o: ?? */
180
181
182
183/*
184 * - Kernel side interface -
185 */
186
187#ifdef __KERNEL__
188
189/*
190 * Asynchronous SMU commands
191 *
192 * Fill up this structure and submit it via smu_queue_command(),
193 * and get notified by the optional done() callback, or because
194 * status becomes != 1
195 */
196
197struct smu_cmd;
198
199struct smu_cmd
200{
201 /* public */
202 u8 cmd; /* command */
203 int data_len; /* data len */
204 int reply_len; /* reply len */
205 void *data_buf; /* data buffer */
206 void *reply_buf; /* reply buffer */
207 int status; /* command status */
208 void (*done)(struct smu_cmd *cmd, void *misc);
209 void *misc;
210
211 /* private */
212 struct list_head link;
213};
214
215/*
216 * Queues an SMU command, all fields have to be initialized
217 */
218extern int smu_queue_cmd(struct smu_cmd *cmd);
219
220/*
221 * Simple command wrapper. This structure embeds a small buffer
222 * to ease sending simple SMU commands from the stack
223 */
224struct smu_simple_cmd
225{
226 struct smu_cmd cmd;
227 u8 buffer[16];
228};
229
230/*
231 * Queues a simple command. All fields will be initialized by that
232 * function
233 */
234extern int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
235 unsigned int data_len,
236 void (*done)(struct smu_cmd *cmd, void *misc),
237 void *misc,
238 ...);
239
240/*
241 * Completion helper. Pass it to smu_queue_simple or as 'done'
242 * member to smu_queue_cmd, it will call complete() on the struct
243 * completion passed in the "misc" argument
244 */
245extern void smu_done_complete(struct smu_cmd *cmd, void *misc);
6 246
7/* 247/*
8 * Basic routines for use by architecture. To be extended as 248 * Synchronous helpers. Will spin-wait for completion of a command
9 * we understand more of the chip 249 */
250extern void smu_spinwait_cmd(struct smu_cmd *cmd);
251
252static inline void smu_spinwait_simple(struct smu_simple_cmd *scmd)
253{
254 smu_spinwait_cmd(&scmd->cmd);
255}
256
257/*
258 * Poll routine to call if blocked with irqs off
259 */
260extern void smu_poll(void);
261
262
263/*
264 * Init routine, presence check....
10 */ 265 */
11extern int smu_init(void); 266extern int smu_init(void);
12extern int smu_present(void); 267extern int smu_present(void);
268struct of_device;
269extern struct of_device *smu_get_ofdev(void);
270
271
272/*
273 * Common command wrappers
274 */
13extern void smu_shutdown(void); 275extern void smu_shutdown(void);
14extern void smu_restart(void); 276extern void smu_restart(void);
15extern int smu_get_rtc_time(struct rtc_time *time); 277struct rtc_time;
16extern int smu_set_rtc_time(struct rtc_time *time); 278extern int smu_get_rtc_time(struct rtc_time *time, int spinwait);
279extern int smu_set_rtc_time(struct rtc_time *time, int spinwait);
17 280
18/* 281/*
19 * SMU command buffer absolute address, exported by pmac_setup, 282 * SMU command buffer absolute address, exported by pmac_setup,
20 * this is allocated very early during boot. 283 * this is allocated very early during boot.
21 */ 284 */
22extern unsigned long smu_cmdbuf_abs; 285extern unsigned long smu_cmdbuf_abs;
286
287
288/*
289 * Kenrel asynchronous i2c interface
290 */
291
292/* SMU i2c header, exactly matches i2c header on wire */
293struct smu_i2c_param
294{
295 u8 bus; /* SMU bus ID (from device tree) */
296 u8 type; /* i2c transfer type */
297 u8 devaddr; /* device address (includes direction) */
298 u8 sublen; /* subaddress length */
299 u8 subaddr[3]; /* subaddress */
300 u8 caddr; /* combined address, filled by SMU driver */
301 u8 datalen; /* length of transfer */
302 u8 data[7]; /* data */
303};
304
305#define SMU_I2C_READ_MAX 0x0d
306#define SMU_I2C_WRITE_MAX 0x05
307
308struct smu_i2c_cmd
309{
310 /* public */
311 struct smu_i2c_param info;
312 void (*done)(struct smu_i2c_cmd *cmd, void *misc);
313 void *misc;
314 int status; /* 1 = pending, 0 = ok, <0 = fail */
315
316 /* private */
317 struct smu_cmd scmd;
318 int read;
319 int stage;
320 int retries;
321 u8 pdata[0x10];
322 struct list_head link;
323};
324
325/*
326 * Call this to queue an i2c command to the SMU. You must fill info,
327 * including info.data for a write, done and misc.
328 * For now, no polling interface is provided so you have to use completion
329 * callback.
330 */
331extern int smu_queue_i2c(struct smu_i2c_cmd *cmd);
332
333
334#endif /* __KERNEL__ */
335
336/*
337 * - Userland interface -
338 */
339
340/*
341 * A given instance of the device can be configured for 2 different
342 * things at the moment:
343 *
344 * - sending SMU commands (default at open() time)
345 * - receiving SMU events (not yet implemented)
346 *
347 * Commands are written with write() of a command block. They can be
348 * "driver" commands (for example to switch to event reception mode)
349 * or real SMU commands. They are made of a header followed by command
350 * data if any.
351 *
352 * For SMU commands (not for driver commands), you can then read() back
353 * a reply. The reader will be blocked or not depending on how the device
354 * file is opened. poll() isn't implemented yet. The reply will consist
355 * of a header as well, followed by the reply data if any. You should
356 * always provide a buffer large enough for the maximum reply data, I
357 * recommand one page.
358 *
359 * It is illegal to send SMU commands through a file descriptor configured
360 * for events reception
361 *
362 */
363struct smu_user_cmd_hdr
364{
365 __u32 cmdtype;
366#define SMU_CMDTYPE_SMU 0 /* SMU command */
367#define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */
368
369 __u8 cmd; /* SMU command byte */
370 __u32 data_len; /* Lenght of data following */
371};
372
373struct smu_user_reply_hdr
374{
375 __u32 status; /* Command status */
376 __u32 reply_len; /* Lenght of data follwing */
377};
378
379#endif /* _SMU_H */