diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-09 13:03:44 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-09 13:03:44 -0500 |
commit | 6150c32589d1976ca8a5c987df951088c05a7542 (patch) | |
tree | 94073696576323ff966e365d8c47b8ecd8372f97 /drivers | |
parent | 44637a12f80b80157d9c1bc5b7d6ef09c9e05713 (diff) | |
parent | be42d5fa3772241b8ecebd443f1fb36247959c54 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
Diffstat (limited to 'drivers')
25 files changed, 824 insertions, 1911 deletions
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index af7cb2bfd670..01f042f6f1c4 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c | |||
@@ -1083,23 +1083,33 @@ static int swim3_add_device(struct device_node *swim) | |||
1083 | { | 1083 | { |
1084 | struct device_node *mediabay; | 1084 | struct device_node *mediabay; |
1085 | struct floppy_state *fs = &floppy_states[floppy_count]; | 1085 | struct floppy_state *fs = &floppy_states[floppy_count]; |
1086 | struct resource res_reg, res_dma; | ||
1086 | 1087 | ||
1087 | if (swim->n_addrs < 2) | 1088 | if (of_address_to_resource(swim, 0, &res_reg) || |
1088 | { | 1089 | of_address_to_resource(swim, 1, &res_dma)) { |
1089 | printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n", | 1090 | printk(KERN_ERR "swim3: Can't get addresses\n"); |
1090 | swim->n_addrs, swim->n_intrs); | ||
1091 | return -EINVAL; | 1091 | return -EINVAL; |
1092 | } | 1092 | } |
1093 | 1093 | if (request_mem_region(res_reg.start, res_reg.end - res_reg.start + 1, | |
1094 | if (swim->n_intrs < 2) | 1094 | " (reg)") == NULL) { |
1095 | { | 1095 | printk(KERN_ERR "swim3: Can't request register space\n"); |
1096 | printk(KERN_INFO "swim3: expecting 2 intrs (n_addrs:%d, n_intrs:%d)\n", | 1096 | return -EINVAL; |
1097 | swim->n_addrs, swim->n_intrs); | 1097 | } |
1098 | if (request_mem_region(res_dma.start, res_dma.end - res_dma.start + 1, | ||
1099 | " (dma)") == NULL) { | ||
1100 | release_mem_region(res_reg.start, | ||
1101 | res_reg.end - res_reg.start + 1); | ||
1102 | printk(KERN_ERR "swim3: Can't request DMA space\n"); | ||
1098 | return -EINVAL; | 1103 | return -EINVAL; |
1099 | } | 1104 | } |
1100 | 1105 | ||
1101 | if (!request_OF_resource(swim, 0, NULL)) { | 1106 | if (swim->n_intrs < 2) { |
1102 | printk(KERN_INFO "swim3: can't request IO resource !\n"); | 1107 | printk(KERN_INFO "swim3: expecting 2 intrs (n_intrs:%d)\n", |
1108 | swim->n_intrs); | ||
1109 | release_mem_region(res_reg.start, | ||
1110 | res_reg.end - res_reg.start + 1); | ||
1111 | release_mem_region(res_dma.start, | ||
1112 | res_dma.end - res_dma.start + 1); | ||
1103 | return -EINVAL; | 1113 | return -EINVAL; |
1104 | } | 1114 | } |
1105 | 1115 | ||
@@ -1110,10 +1120,8 @@ static int swim3_add_device(struct device_node *swim) | |||
1110 | memset(fs, 0, sizeof(*fs)); | 1120 | memset(fs, 0, sizeof(*fs)); |
1111 | spin_lock_init(&fs->lock); | 1121 | spin_lock_init(&fs->lock); |
1112 | fs->state = idle; | 1122 | fs->state = idle; |
1113 | fs->swim3 = (struct swim3 __iomem *) | 1123 | fs->swim3 = (struct swim3 __iomem *)ioremap(res_reg.start, 0x200); |
1114 | ioremap(swim->addrs[0].address, 0x200); | 1124 | fs->dma = (struct dbdma_regs __iomem *)ioremap(res_dma.start, 0x200); |
1115 | fs->dma = (struct dbdma_regs __iomem *) | ||
1116 | ioremap(swim->addrs[1].address, 0x200); | ||
1117 | fs->swim3_intr = swim->intrs[0].line; | 1125 | fs->swim3_intr = swim->intrs[0].line; |
1118 | fs->dma_intr = swim->intrs[1].line; | 1126 | fs->dma_intr = swim->intrs[1].line; |
1119 | fs->cur_cyl = -1; | 1127 | fs->cur_cyl = -1; |
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c index 56d62ba7c6ce..b2fc71e20850 100644 --- a/drivers/char/watchdog/mpc8xx_wdt.c +++ b/drivers/char/watchdog/mpc8xx_wdt.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/watchdog.h> | 18 | #include <linux/watchdog.h> |
19 | #include <asm/8xx_immap.h> | 19 | #include <asm/8xx_immap.h> |
20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
21 | #include <asm/io.h> | ||
21 | #include <syslib/m8xx_wdt.h> | 22 | #include <syslib/m8xx_wdt.h> |
22 | 23 | ||
23 | static unsigned long wdt_opened; | 24 | static unsigned long wdt_opened; |
@@ -25,18 +26,26 @@ static int wdt_status; | |||
25 | 26 | ||
26 | static void mpc8xx_wdt_handler_disable(void) | 27 | static void mpc8xx_wdt_handler_disable(void) |
27 | { | 28 | { |
28 | volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; | 29 | volatile uint __iomem *piscr; |
30 | piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr; | ||
29 | 31 | ||
30 | imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE); | 32 | if (!m8xx_has_internal_rtc) |
33 | m8xx_wdt_stop_timer(); | ||
34 | else | ||
35 | out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE)); | ||
31 | 36 | ||
32 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); | 37 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); |
33 | } | 38 | } |
34 | 39 | ||
35 | static void mpc8xx_wdt_handler_enable(void) | 40 | static void mpc8xx_wdt_handler_enable(void) |
36 | { | 41 | { |
37 | volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; | 42 | volatile uint __iomem *piscr; |
43 | piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr; | ||
38 | 44 | ||
39 | imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE; | 45 | if (!m8xx_has_internal_rtc) |
46 | m8xx_wdt_install_timer(); | ||
47 | else | ||
48 | out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE); | ||
40 | 49 | ||
41 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); | 50 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); |
42 | } | 51 | } |
@@ -68,9 +77,6 @@ static int mpc8xx_wdt_release(struct inode *inode, struct file *file) | |||
68 | static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len, | 77 | static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len, |
69 | loff_t * ppos) | 78 | loff_t * ppos) |
70 | { | 79 | { |
71 | if (ppos != &file->f_pos) | ||
72 | return -ESPIPE; | ||
73 | |||
74 | if (len) | 80 | if (len) |
75 | m8xx_wdt_reset(); | 81 | m8xx_wdt_reset(); |
76 | 82 | ||
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 4010fe92e72b..08d5b8fed2dc 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -236,27 +236,17 @@ config I2C_IXP2000 | |||
236 | This support is also available as a module. If so, the module | 236 | This support is also available as a module. If so, the module |
237 | will be called i2c-ixp2000. | 237 | will be called i2c-ixp2000. |
238 | 238 | ||
239 | config I2C_KEYWEST | 239 | config I2C_POWERMAC |
240 | tristate "Powermac Keywest I2C interface" | 240 | tristate "Powermac I2C interface" |
241 | depends on I2C && PPC_PMAC | 241 | depends on I2C && PPC_PMAC |
242 | default y | ||
242 | help | 243 | help |
243 | This supports the use of the I2C interface in the combo-I/O | 244 | This exposes the various PowerMac i2c interfaces to the linux i2c |
244 | chip on recent Apple machines. Say Y if you have such a machine. | 245 | layer and to userland. It is used by various drivers on the powemac |
245 | 246 | platform, thus should generally be enabled. | |
246 | This support is also available as a module. If so, the module | ||
247 | will be called i2c-keywest. | ||
248 | |||
249 | config I2C_PMAC_SMU | ||
250 | tristate "Powermac SMU I2C interface" | ||
251 | depends on I2C && PMAC_SMU | ||
252 | help | ||
253 | This supports the use of the I2C interface in the SMU | ||
254 | chip on recent Apple machines like the iMac G5. It is used | ||
255 | among others by the thermal control driver for those machines. | ||
256 | Say Y if you have such a machine. | ||
257 | 247 | ||
258 | This support is also available as a module. If so, the module | 248 | This support is also available as a module. If so, the module |
259 | will be called i2c-pmac-smu. | 249 | will be called i2c-powermac. |
260 | 250 | ||
261 | config I2C_MPC | 251 | config I2C_MPC |
262 | tristate "MPC107/824x/85xx/52xx" | 252 | tristate "MPC107/824x/85xx/52xx" |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index f1df00f66c6c..b44831dff683 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -19,8 +19,7 @@ obj-$(CONFIG_I2C_ISA) += i2c-isa.o | |||
19 | obj-$(CONFIG_I2C_ITE) += i2c-ite.o | 19 | obj-$(CONFIG_I2C_ITE) += i2c-ite.o |
20 | obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o | 20 | obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o |
21 | obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o | 21 | obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o |
22 | obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o | 22 | obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o |
23 | obj-$(CONFIG_I2C_PMAC_SMU) += i2c-pmac-smu.o | ||
24 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o | 23 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o |
25 | obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o | 24 | obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o |
26 | obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o | 25 | obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o |
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c deleted file mode 100644 index d61f748278fc..000000000000 --- a/drivers/i2c/busses/i2c-keywest.c +++ /dev/null | |||
@@ -1,751 +0,0 @@ | |||
1 | /* | ||
2 | i2c Support for Apple Keywest I2C Bus Controller | ||
3 | |||
4 | Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | |||
6 | Original work by | ||
7 | |||
8 | Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | |||
24 | Changes: | ||
25 | |||
26 | 2001/12/13 BenH New implementation | ||
27 | 2001/12/15 BenH Add support for "byte" and "quick" | ||
28 | transfers. Add i2c_xfer routine. | ||
29 | 2003/09/21 BenH Rework state machine with Paulus help | ||
30 | 2004/01/21 BenH Merge in Greg KH changes, polled mode is back | ||
31 | 2004/02/05 BenH Merge 64 bits fixes from the g5 ppc64 tree | ||
32 | |||
33 | My understanding of the various modes supported by keywest are: | ||
34 | |||
35 | - Dumb mode : not implemented, probably direct tweaking of lines | ||
36 | - Standard mode : simple i2c transaction of type | ||
37 | S Addr R/W A Data A Data ... T | ||
38 | - Standard sub mode : combined 8 bit subaddr write with data read | ||
39 | S Addr R/W A SubAddr A Data A Data ... T | ||
40 | - Combined mode : Subaddress and Data sequences appended with no stop | ||
41 | S Addr R/W A SubAddr S Addr R/W A Data A Data ... T | ||
42 | |||
43 | Currently, this driver uses only Standard mode for i2c xfer, and | ||
44 | smbus byte & quick transfers ; and uses StandardSub mode for | ||
45 | other smbus transfers instead of combined as we need that for the | ||
46 | sound driver to be happy | ||
47 | */ | ||
48 | |||
49 | #include <linux/module.h> | ||
50 | #include <linux/kernel.h> | ||
51 | #include <linux/ioport.h> | ||
52 | #include <linux/pci.h> | ||
53 | #include <linux/types.h> | ||
54 | #include <linux/delay.h> | ||
55 | #include <linux/i2c.h> | ||
56 | #include <linux/init.h> | ||
57 | #include <linux/mm.h> | ||
58 | #include <linux/timer.h> | ||
59 | #include <linux/spinlock.h> | ||
60 | #include <linux/completion.h> | ||
61 | #include <linux/interrupt.h> | ||
62 | |||
63 | #include <asm/io.h> | ||
64 | #include <asm/prom.h> | ||
65 | #include <asm/machdep.h> | ||
66 | #include <asm/pmac_feature.h> | ||
67 | #include <asm/pmac_low_i2c.h> | ||
68 | |||
69 | #include "i2c-keywest.h" | ||
70 | |||
71 | #undef POLLED_MODE | ||
72 | |||
73 | /* Some debug macros */ | ||
74 | #define WRONG_STATE(name) do {\ | ||
75 | pr_debug("KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ | ||
76 | name, __kw_state_names[iface->state], isr); \ | ||
77 | } while(0) | ||
78 | |||
79 | #ifdef DEBUG | ||
80 | static const char *__kw_state_names[] = { | ||
81 | "state_idle", | ||
82 | "state_addr", | ||
83 | "state_read", | ||
84 | "state_write", | ||
85 | "state_stop", | ||
86 | "state_dead" | ||
87 | }; | ||
88 | #endif /* DEBUG */ | ||
89 | |||
90 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
91 | MODULE_DESCRIPTION("I2C driver for Apple's Keywest"); | ||
92 | MODULE_LICENSE("GPL"); | ||
93 | |||
94 | #ifdef POLLED_MODE | ||
95 | /* Don't schedule, the g5 fan controller is too | ||
96 | * timing sensitive | ||
97 | */ | ||
98 | static u8 | ||
99 | wait_interrupt(struct keywest_iface* iface) | ||
100 | { | ||
101 | int i; | ||
102 | u8 isr; | ||
103 | |||
104 | for (i = 0; i < 200000; i++) { | ||
105 | isr = read_reg(reg_isr) & KW_I2C_IRQ_MASK; | ||
106 | if (isr != 0) | ||
107 | return isr; | ||
108 | udelay(10); | ||
109 | } | ||
110 | return isr; | ||
111 | } | ||
112 | #endif /* POLLED_MODE */ | ||
113 | |||
114 | static void | ||
115 | do_stop(struct keywest_iface* iface, int result) | ||
116 | { | ||
117 | write_reg(reg_control, KW_I2C_CTL_STOP); | ||
118 | iface->state = state_stop; | ||
119 | iface->result = result; | ||
120 | } | ||
121 | |||
122 | /* Main state machine for standard & standard sub mode */ | ||
123 | static void | ||
124 | handle_interrupt(struct keywest_iface *iface, u8 isr) | ||
125 | { | ||
126 | int ack; | ||
127 | |||
128 | if (isr == 0) { | ||
129 | if (iface->state != state_stop) { | ||
130 | pr_debug("KW: Timeout !\n"); | ||
131 | do_stop(iface, -EIO); | ||
132 | } | ||
133 | if (iface->state == state_stop) { | ||
134 | ack = read_reg(reg_status); | ||
135 | if (!(ack & KW_I2C_STAT_BUSY)) { | ||
136 | iface->state = state_idle; | ||
137 | write_reg(reg_ier, 0x00); | ||
138 | #ifndef POLLED_MODE | ||
139 | complete(&iface->complete); | ||
140 | #endif /* POLLED_MODE */ | ||
141 | } | ||
142 | } | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | if (isr & KW_I2C_IRQ_ADDR) { | ||
147 | ack = read_reg(reg_status); | ||
148 | if (iface->state != state_addr) { | ||
149 | write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
150 | WRONG_STATE("KW_I2C_IRQ_ADDR"); | ||
151 | do_stop(iface, -EIO); | ||
152 | return; | ||
153 | } | ||
154 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
155 | iface->state = state_stop; | ||
156 | iface->result = -ENODEV; | ||
157 | pr_debug("KW: NAK on address\n"); | ||
158 | } else { | ||
159 | /* Handle rw "quick" mode */ | ||
160 | if (iface->datalen == 0) { | ||
161 | do_stop(iface, 0); | ||
162 | } else if (iface->read_write == I2C_SMBUS_READ) { | ||
163 | iface->state = state_read; | ||
164 | if (iface->datalen > 1) | ||
165 | write_reg(reg_control, KW_I2C_CTL_AAK); | ||
166 | } else { | ||
167 | iface->state = state_write; | ||
168 | write_reg(reg_data, *(iface->data++)); | ||
169 | iface->datalen--; | ||
170 | } | ||
171 | } | ||
172 | write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
173 | } | ||
174 | |||
175 | if (isr & KW_I2C_IRQ_DATA) { | ||
176 | if (iface->state == state_read) { | ||
177 | *(iface->data++) = read_reg(reg_data); | ||
178 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
179 | iface->datalen--; | ||
180 | if (iface->datalen == 0) | ||
181 | iface->state = state_stop; | ||
182 | else if (iface->datalen == 1) | ||
183 | write_reg(reg_control, 0); | ||
184 | } else if (iface->state == state_write) { | ||
185 | /* Check ack status */ | ||
186 | ack = read_reg(reg_status); | ||
187 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
188 | pr_debug("KW: nack on data write (%x): %x\n", | ||
189 | iface->data[-1], ack); | ||
190 | do_stop(iface, -EIO); | ||
191 | } else if (iface->datalen) { | ||
192 | write_reg(reg_data, *(iface->data++)); | ||
193 | iface->datalen--; | ||
194 | } else { | ||
195 | write_reg(reg_control, KW_I2C_CTL_STOP); | ||
196 | iface->state = state_stop; | ||
197 | iface->result = 0; | ||
198 | } | ||
199 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
200 | } else { | ||
201 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
202 | WRONG_STATE("KW_I2C_IRQ_DATA"); | ||
203 | if (iface->state != state_stop) | ||
204 | do_stop(iface, -EIO); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | if (isr & KW_I2C_IRQ_STOP) { | ||
209 | write_reg(reg_isr, KW_I2C_IRQ_STOP); | ||
210 | if (iface->state != state_stop) { | ||
211 | WRONG_STATE("KW_I2C_IRQ_STOP"); | ||
212 | iface->result = -EIO; | ||
213 | } | ||
214 | iface->state = state_idle; | ||
215 | write_reg(reg_ier, 0x00); | ||
216 | #ifndef POLLED_MODE | ||
217 | complete(&iface->complete); | ||
218 | #endif /* POLLED_MODE */ | ||
219 | } | ||
220 | |||
221 | if (isr & KW_I2C_IRQ_START) | ||
222 | write_reg(reg_isr, KW_I2C_IRQ_START); | ||
223 | } | ||
224 | |||
225 | #ifndef POLLED_MODE | ||
226 | |||
227 | /* Interrupt handler */ | ||
228 | static irqreturn_t | ||
229 | keywest_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
230 | { | ||
231 | struct keywest_iface *iface = (struct keywest_iface *)dev_id; | ||
232 | unsigned long flags; | ||
233 | |||
234 | spin_lock_irqsave(&iface->lock, flags); | ||
235 | del_timer(&iface->timeout_timer); | ||
236 | handle_interrupt(iface, read_reg(reg_isr)); | ||
237 | if (iface->state != state_idle) { | ||
238 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
239 | add_timer(&iface->timeout_timer); | ||
240 | } | ||
241 | spin_unlock_irqrestore(&iface->lock, flags); | ||
242 | return IRQ_HANDLED; | ||
243 | } | ||
244 | |||
245 | static void | ||
246 | keywest_timeout(unsigned long data) | ||
247 | { | ||
248 | struct keywest_iface *iface = (struct keywest_iface *)data; | ||
249 | unsigned long flags; | ||
250 | |||
251 | pr_debug("timeout !\n"); | ||
252 | spin_lock_irqsave(&iface->lock, flags); | ||
253 | handle_interrupt(iface, read_reg(reg_isr)); | ||
254 | if (iface->state != state_idle) { | ||
255 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
256 | add_timer(&iface->timeout_timer); | ||
257 | } | ||
258 | spin_unlock_irqrestore(&iface->lock, flags); | ||
259 | } | ||
260 | |||
261 | #endif /* POLLED_MODE */ | ||
262 | |||
263 | /* | ||
264 | * SMBUS-type transfer entrypoint | ||
265 | */ | ||
266 | static s32 | ||
267 | keywest_smbus_xfer( struct i2c_adapter* adap, | ||
268 | u16 addr, | ||
269 | unsigned short flags, | ||
270 | char read_write, | ||
271 | u8 command, | ||
272 | int size, | ||
273 | union i2c_smbus_data* data) | ||
274 | { | ||
275 | struct keywest_chan* chan = i2c_get_adapdata(adap); | ||
276 | struct keywest_iface* iface = chan->iface; | ||
277 | int len; | ||
278 | u8* buffer; | ||
279 | u16 cur_word; | ||
280 | int rc = 0; | ||
281 | |||
282 | if (iface->state == state_dead) | ||
283 | return -ENXIO; | ||
284 | |||
285 | /* Prepare datas & select mode */ | ||
286 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
287 | switch (size) { | ||
288 | case I2C_SMBUS_QUICK: | ||
289 | len = 0; | ||
290 | buffer = NULL; | ||
291 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
292 | break; | ||
293 | case I2C_SMBUS_BYTE: | ||
294 | len = 1; | ||
295 | buffer = &data->byte; | ||
296 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
297 | break; | ||
298 | case I2C_SMBUS_BYTE_DATA: | ||
299 | len = 1; | ||
300 | buffer = &data->byte; | ||
301 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
302 | break; | ||
303 | case I2C_SMBUS_WORD_DATA: | ||
304 | len = 2; | ||
305 | cur_word = cpu_to_le16(data->word); | ||
306 | buffer = (u8 *)&cur_word; | ||
307 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
308 | break; | ||
309 | case I2C_SMBUS_BLOCK_DATA: | ||
310 | len = data->block[0]; | ||
311 | buffer = &data->block[1]; | ||
312 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
313 | break; | ||
314 | default: | ||
315 | return -1; | ||
316 | } | ||
317 | |||
318 | /* Turn a standardsub read into a combined mode access */ | ||
319 | if (read_write == I2C_SMBUS_READ | ||
320 | && (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB) { | ||
321 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
322 | iface->cur_mode |= KW_I2C_MODE_COMBINED; | ||
323 | } | ||
324 | |||
325 | /* Original driver had this limitation */ | ||
326 | if (len > 32) | ||
327 | len = 32; | ||
328 | |||
329 | if (pmac_low_i2c_lock(iface->node)) | ||
330 | return -ENXIO; | ||
331 | |||
332 | pr_debug("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n", | ||
333 | chan->chan_no, addr, len, read_write == I2C_SMBUS_READ); | ||
334 | |||
335 | iface->data = buffer; | ||
336 | iface->datalen = len; | ||
337 | iface->state = state_addr; | ||
338 | iface->result = 0; | ||
339 | iface->read_write = read_write; | ||
340 | |||
341 | /* Setup channel & clear pending irqs */ | ||
342 | write_reg(reg_isr, read_reg(reg_isr)); | ||
343 | write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); | ||
344 | write_reg(reg_status, 0); | ||
345 | |||
346 | /* Set up address and r/w bit */ | ||
347 | write_reg(reg_addr, | ||
348 | (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); | ||
349 | |||
350 | /* Set up the sub address */ | ||
351 | if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB | ||
352 | || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED) | ||
353 | write_reg(reg_subaddr, command); | ||
354 | |||
355 | #ifndef POLLED_MODE | ||
356 | /* Arm timeout */ | ||
357 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
358 | add_timer(&iface->timeout_timer); | ||
359 | #endif | ||
360 | |||
361 | /* Start sending address & enable interrupt*/ | ||
362 | write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
363 | write_reg(reg_ier, KW_I2C_IRQ_MASK); | ||
364 | |||
365 | #ifdef POLLED_MODE | ||
366 | pr_debug("using polled mode...\n"); | ||
367 | /* State machine, to turn into an interrupt handler */ | ||
368 | while(iface->state != state_idle) { | ||
369 | unsigned long flags; | ||
370 | |||
371 | u8 isr = wait_interrupt(iface); | ||
372 | spin_lock_irqsave(&iface->lock, flags); | ||
373 | handle_interrupt(iface, isr); | ||
374 | spin_unlock_irqrestore(&iface->lock, flags); | ||
375 | } | ||
376 | #else /* POLLED_MODE */ | ||
377 | pr_debug("using interrupt mode...\n"); | ||
378 | wait_for_completion(&iface->complete); | ||
379 | #endif /* POLLED_MODE */ | ||
380 | |||
381 | rc = iface->result; | ||
382 | pr_debug("transfer done, result: %d\n", rc); | ||
383 | |||
384 | if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ) | ||
385 | data->word = le16_to_cpu(cur_word); | ||
386 | |||
387 | /* Release sem */ | ||
388 | pmac_low_i2c_unlock(iface->node); | ||
389 | |||
390 | return rc; | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Generic i2c master transfer entrypoint | ||
395 | */ | ||
396 | static int | ||
397 | keywest_xfer( struct i2c_adapter *adap, | ||
398 | struct i2c_msg *msgs, | ||
399 | int num) | ||
400 | { | ||
401 | struct keywest_chan* chan = i2c_get_adapdata(adap); | ||
402 | struct keywest_iface* iface = chan->iface; | ||
403 | struct i2c_msg *pmsg; | ||
404 | int i, completed; | ||
405 | int rc = 0; | ||
406 | |||
407 | if (iface->state == state_dead) | ||
408 | return -ENXIO; | ||
409 | |||
410 | if (pmac_low_i2c_lock(iface->node)) | ||
411 | return -ENXIO; | ||
412 | |||
413 | /* Set adapter to standard mode */ | ||
414 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
415 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
416 | |||
417 | completed = 0; | ||
418 | for (i = 0; rc >= 0 && i < num;) { | ||
419 | u8 addr; | ||
420 | |||
421 | pmsg = &msgs[i++]; | ||
422 | addr = pmsg->addr; | ||
423 | if (pmsg->flags & I2C_M_TEN) { | ||
424 | printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n"); | ||
425 | rc = -EINVAL; | ||
426 | break; | ||
427 | } | ||
428 | pr_debug("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n", | ||
429 | chan->chan_no, | ||
430 | pmsg->flags & I2C_M_RD ? "read" : "write", | ||
431 | pmsg->len, addr, i, num); | ||
432 | |||
433 | /* Setup channel & clear pending irqs */ | ||
434 | write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); | ||
435 | write_reg(reg_isr, read_reg(reg_isr)); | ||
436 | write_reg(reg_status, 0); | ||
437 | |||
438 | iface->data = pmsg->buf; | ||
439 | iface->datalen = pmsg->len; | ||
440 | iface->state = state_addr; | ||
441 | iface->result = 0; | ||
442 | if (pmsg->flags & I2C_M_RD) | ||
443 | iface->read_write = I2C_SMBUS_READ; | ||
444 | else | ||
445 | iface->read_write = I2C_SMBUS_WRITE; | ||
446 | |||
447 | /* Set up address and r/w bit */ | ||
448 | if (pmsg->flags & I2C_M_REV_DIR_ADDR) | ||
449 | addr ^= 1; | ||
450 | write_reg(reg_addr, | ||
451 | (addr << 1) | | ||
452 | ((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); | ||
453 | |||
454 | #ifndef POLLED_MODE | ||
455 | /* Arm timeout */ | ||
456 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
457 | add_timer(&iface->timeout_timer); | ||
458 | #endif | ||
459 | |||
460 | /* Start sending address & enable interrupt*/ | ||
461 | write_reg(reg_ier, KW_I2C_IRQ_MASK); | ||
462 | write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
463 | |||
464 | #ifdef POLLED_MODE | ||
465 | pr_debug("using polled mode...\n"); | ||
466 | /* State machine, to turn into an interrupt handler */ | ||
467 | while(iface->state != state_idle) { | ||
468 | u8 isr = wait_interrupt(iface); | ||
469 | handle_interrupt(iface, isr); | ||
470 | } | ||
471 | #else /* POLLED_MODE */ | ||
472 | pr_debug("using interrupt mode...\n"); | ||
473 | wait_for_completion(&iface->complete); | ||
474 | #endif /* POLLED_MODE */ | ||
475 | |||
476 | rc = iface->result; | ||
477 | if (rc == 0) | ||
478 | completed++; | ||
479 | pr_debug("transfer done, result: %d\n", rc); | ||
480 | } | ||
481 | |||
482 | /* Release sem */ | ||
483 | pmac_low_i2c_unlock(iface->node); | ||
484 | |||
485 | return completed; | ||
486 | } | ||
487 | |||
488 | static u32 | ||
489 | keywest_func(struct i2c_adapter * adapter) | ||
490 | { | ||
491 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
492 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
493 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
494 | } | ||
495 | |||
496 | /* For now, we only handle combined mode (smbus) */ | ||
497 | static struct i2c_algorithm keywest_algorithm = { | ||
498 | .smbus_xfer = keywest_smbus_xfer, | ||
499 | .master_xfer = keywest_xfer, | ||
500 | .functionality = keywest_func, | ||
501 | }; | ||
502 | |||
503 | |||
504 | static int | ||
505 | create_iface(struct device_node *np, struct device *dev) | ||
506 | { | ||
507 | unsigned long steps; | ||
508 | unsigned bsteps, tsize, i, nchan, addroffset; | ||
509 | struct keywest_iface* iface; | ||
510 | u32 *psteps, *prate; | ||
511 | int rc; | ||
512 | |||
513 | if (np->n_intrs < 1 || np->n_addrs < 1) { | ||
514 | printk(KERN_ERR "%s: Missing interrupt or address !\n", | ||
515 | np->full_name); | ||
516 | return -ENODEV; | ||
517 | } | ||
518 | if (pmac_low_i2c_lock(np)) | ||
519 | return -ENODEV; | ||
520 | |||
521 | psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); | ||
522 | steps = psteps ? (*psteps) : 0x10; | ||
523 | |||
524 | /* Hrm... maybe we can be smarter here */ | ||
525 | for (bsteps = 0; (steps & 0x01) == 0; bsteps++) | ||
526 | steps >>= 1; | ||
527 | |||
528 | if (np->parent->name[0] == 'u') { | ||
529 | nchan = 2; | ||
530 | addroffset = 3; | ||
531 | } else { | ||
532 | addroffset = 0; | ||
533 | nchan = 1; | ||
534 | } | ||
535 | |||
536 | tsize = sizeof(struct keywest_iface) + | ||
537 | (sizeof(struct keywest_chan) + 4) * nchan; | ||
538 | iface = kzalloc(tsize, GFP_KERNEL); | ||
539 | if (iface == NULL) { | ||
540 | printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n"); | ||
541 | pmac_low_i2c_unlock(np); | ||
542 | return -ENOMEM; | ||
543 | } | ||
544 | spin_lock_init(&iface->lock); | ||
545 | init_completion(&iface->complete); | ||
546 | iface->node = of_node_get(np); | ||
547 | iface->bsteps = bsteps; | ||
548 | iface->chan_count = nchan; | ||
549 | iface->state = state_idle; | ||
550 | iface->irq = np->intrs[0].line; | ||
551 | iface->channels = (struct keywest_chan *) | ||
552 | (((unsigned long)(iface + 1) + 3UL) & ~3UL); | ||
553 | iface->base = ioremap(np->addrs[0].address + addroffset, | ||
554 | np->addrs[0].size); | ||
555 | if (!iface->base) { | ||
556 | printk(KERN_ERR "i2c-keywest: can't map inteface !\n"); | ||
557 | kfree(iface); | ||
558 | pmac_low_i2c_unlock(np); | ||
559 | return -ENOMEM; | ||
560 | } | ||
561 | |||
562 | #ifndef POLLED_MODE | ||
563 | init_timer(&iface->timeout_timer); | ||
564 | iface->timeout_timer.function = keywest_timeout; | ||
565 | iface->timeout_timer.data = (unsigned long)iface; | ||
566 | #endif | ||
567 | |||
568 | /* Select interface rate */ | ||
569 | iface->cur_mode = KW_I2C_MODE_100KHZ; | ||
570 | prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); | ||
571 | if (prate) switch(*prate) { | ||
572 | case 100: | ||
573 | iface->cur_mode = KW_I2C_MODE_100KHZ; | ||
574 | break; | ||
575 | case 50: | ||
576 | iface->cur_mode = KW_I2C_MODE_50KHZ; | ||
577 | break; | ||
578 | case 25: | ||
579 | iface->cur_mode = KW_I2C_MODE_25KHZ; | ||
580 | break; | ||
581 | default: | ||
582 | printk(KERN_WARNING "i2c-keywest: unknown rate %ldKhz, using 100KHz\n", | ||
583 | (long)*prate); | ||
584 | } | ||
585 | |||
586 | /* Select standard mode by default */ | ||
587 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
588 | |||
589 | /* Write mode */ | ||
590 | write_reg(reg_mode, iface->cur_mode); | ||
591 | |||
592 | /* Switch interrupts off & clear them*/ | ||
593 | write_reg(reg_ier, 0x00); | ||
594 | write_reg(reg_isr, KW_I2C_IRQ_MASK); | ||
595 | |||
596 | #ifndef POLLED_MODE | ||
597 | /* Request chip interrupt */ | ||
598 | rc = request_irq(iface->irq, keywest_irq, SA_INTERRUPT, "keywest i2c", iface); | ||
599 | if (rc) { | ||
600 | printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq); | ||
601 | iounmap(iface->base); | ||
602 | kfree(iface); | ||
603 | pmac_low_i2c_unlock(np); | ||
604 | return -ENODEV; | ||
605 | } | ||
606 | #endif /* POLLED_MODE */ | ||
607 | |||
608 | pmac_low_i2c_unlock(np); | ||
609 | dev_set_drvdata(dev, iface); | ||
610 | |||
611 | for (i=0; i<nchan; i++) { | ||
612 | struct keywest_chan* chan = &iface->channels[i]; | ||
613 | |||
614 | sprintf(chan->adapter.name, "%s %d", np->parent->name, i); | ||
615 | chan->iface = iface; | ||
616 | chan->chan_no = i; | ||
617 | chan->adapter.algo = &keywest_algorithm; | ||
618 | chan->adapter.algo_data = NULL; | ||
619 | chan->adapter.client_register = NULL; | ||
620 | chan->adapter.client_unregister = NULL; | ||
621 | i2c_set_adapdata(&chan->adapter, chan); | ||
622 | chan->adapter.dev.parent = dev; | ||
623 | |||
624 | rc = i2c_add_adapter(&chan->adapter); | ||
625 | if (rc) { | ||
626 | printk("i2c-keywest.c: Adapter %s registration failed\n", | ||
627 | chan->adapter.name); | ||
628 | i2c_set_adapdata(&chan->adapter, NULL); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n", | ||
633 | np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int | ||
639 | dispose_iface(struct device *dev) | ||
640 | { | ||
641 | struct keywest_iface *iface = dev_get_drvdata(dev); | ||
642 | int i, rc; | ||
643 | |||
644 | /* Make sure we stop all activity */ | ||
645 | if (pmac_low_i2c_lock(iface->node)) | ||
646 | return -ENODEV; | ||
647 | |||
648 | #ifndef POLLED_MODE | ||
649 | spin_lock_irq(&iface->lock); | ||
650 | while (iface->state != state_idle) { | ||
651 | spin_unlock_irq(&iface->lock); | ||
652 | msleep(100); | ||
653 | spin_lock_irq(&iface->lock); | ||
654 | } | ||
655 | #endif /* POLLED_MODE */ | ||
656 | iface->state = state_dead; | ||
657 | #ifndef POLLED_MODE | ||
658 | spin_unlock_irq(&iface->lock); | ||
659 | free_irq(iface->irq, iface); | ||
660 | #endif /* POLLED_MODE */ | ||
661 | |||
662 | pmac_low_i2c_unlock(iface->node); | ||
663 | |||
664 | /* Release all channels */ | ||
665 | for (i=0; i<iface->chan_count; i++) { | ||
666 | struct keywest_chan* chan = &iface->channels[i]; | ||
667 | if (i2c_get_adapdata(&chan->adapter) == NULL) | ||
668 | continue; | ||
669 | rc = i2c_del_adapter(&chan->adapter); | ||
670 | i2c_set_adapdata(&chan->adapter, NULL); | ||
671 | /* We aren't that prepared to deal with this... */ | ||
672 | if (rc) | ||
673 | printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); | ||
674 | } | ||
675 | iounmap(iface->base); | ||
676 | dev_set_drvdata(dev, NULL); | ||
677 | of_node_put(iface->node); | ||
678 | kfree(iface); | ||
679 | |||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static int | ||
684 | create_iface_macio(struct macio_dev* dev, const struct of_device_id *match) | ||
685 | { | ||
686 | return create_iface(dev->ofdev.node, &dev->ofdev.dev); | ||
687 | } | ||
688 | |||
689 | static int | ||
690 | dispose_iface_macio(struct macio_dev* dev) | ||
691 | { | ||
692 | return dispose_iface(&dev->ofdev.dev); | ||
693 | } | ||
694 | |||
695 | static int | ||
696 | create_iface_of_platform(struct of_device* dev, const struct of_device_id *match) | ||
697 | { | ||
698 | return create_iface(dev->node, &dev->dev); | ||
699 | } | ||
700 | |||
701 | static int | ||
702 | dispose_iface_of_platform(struct of_device* dev) | ||
703 | { | ||
704 | return dispose_iface(&dev->dev); | ||
705 | } | ||
706 | |||
707 | static struct of_device_id i2c_keywest_match[] = | ||
708 | { | ||
709 | { | ||
710 | .type = "i2c", | ||
711 | .compatible = "keywest" | ||
712 | }, | ||
713 | {}, | ||
714 | }; | ||
715 | |||
716 | static struct macio_driver i2c_keywest_macio_driver = | ||
717 | { | ||
718 | .owner = THIS_MODULE, | ||
719 | .name = "i2c-keywest", | ||
720 | .match_table = i2c_keywest_match, | ||
721 | .probe = create_iface_macio, | ||
722 | .remove = dispose_iface_macio | ||
723 | }; | ||
724 | |||
725 | static struct of_platform_driver i2c_keywest_of_platform_driver = | ||
726 | { | ||
727 | .owner = THIS_MODULE, | ||
728 | .name = "i2c-keywest", | ||
729 | .match_table = i2c_keywest_match, | ||
730 | .probe = create_iface_of_platform, | ||
731 | .remove = dispose_iface_of_platform | ||
732 | }; | ||
733 | |||
734 | static int __init | ||
735 | i2c_keywest_init(void) | ||
736 | { | ||
737 | of_register_driver(&i2c_keywest_of_platform_driver); | ||
738 | macio_register_driver(&i2c_keywest_macio_driver); | ||
739 | |||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | static void __exit | ||
744 | i2c_keywest_cleanup(void) | ||
745 | { | ||
746 | of_unregister_driver(&i2c_keywest_of_platform_driver); | ||
747 | macio_unregister_driver(&i2c_keywest_macio_driver); | ||
748 | } | ||
749 | |||
750 | module_init(i2c_keywest_init); | ||
751 | module_exit(i2c_keywest_cleanup); | ||
diff --git a/drivers/i2c/busses/i2c-keywest.h b/drivers/i2c/busses/i2c-keywest.h deleted file mode 100644 index c5022e1ca6ff..000000000000 --- a/drivers/i2c/busses/i2c-keywest.h +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | #ifndef __I2C_KEYWEST_H__ | ||
2 | #define __I2C_KEYWEST_H__ | ||
3 | |||
4 | /* The Tumbler audio equalizer can be really slow sometimes */ | ||
5 | #define POLL_TIMEOUT (2*HZ) | ||
6 | |||
7 | /* Register indices */ | ||
8 | typedef enum { | ||
9 | reg_mode = 0, | ||
10 | reg_control, | ||
11 | reg_status, | ||
12 | reg_isr, | ||
13 | reg_ier, | ||
14 | reg_addr, | ||
15 | reg_subaddr, | ||
16 | reg_data | ||
17 | } reg_t; | ||
18 | |||
19 | |||
20 | /* Mode register */ | ||
21 | #define KW_I2C_MODE_100KHZ 0x00 | ||
22 | #define KW_I2C_MODE_50KHZ 0x01 | ||
23 | #define KW_I2C_MODE_25KHZ 0x02 | ||
24 | #define KW_I2C_MODE_DUMB 0x00 | ||
25 | #define KW_I2C_MODE_STANDARD 0x04 | ||
26 | #define KW_I2C_MODE_STANDARDSUB 0x08 | ||
27 | #define KW_I2C_MODE_COMBINED 0x0C | ||
28 | #define KW_I2C_MODE_MODE_MASK 0x0C | ||
29 | #define KW_I2C_MODE_CHAN_MASK 0xF0 | ||
30 | |||
31 | /* Control register */ | ||
32 | #define KW_I2C_CTL_AAK 0x01 | ||
33 | #define KW_I2C_CTL_XADDR 0x02 | ||
34 | #define KW_I2C_CTL_STOP 0x04 | ||
35 | #define KW_I2C_CTL_START 0x08 | ||
36 | |||
37 | /* Status register */ | ||
38 | #define KW_I2C_STAT_BUSY 0x01 | ||
39 | #define KW_I2C_STAT_LAST_AAK 0x02 | ||
40 | #define KW_I2C_STAT_LAST_RW 0x04 | ||
41 | #define KW_I2C_STAT_SDA 0x08 | ||
42 | #define KW_I2C_STAT_SCL 0x10 | ||
43 | |||
44 | /* IER & ISR registers */ | ||
45 | #define KW_I2C_IRQ_DATA 0x01 | ||
46 | #define KW_I2C_IRQ_ADDR 0x02 | ||
47 | #define KW_I2C_IRQ_STOP 0x04 | ||
48 | #define KW_I2C_IRQ_START 0x08 | ||
49 | #define KW_I2C_IRQ_MASK 0x0F | ||
50 | |||
51 | /* Physical interface */ | ||
52 | struct keywest_iface | ||
53 | { | ||
54 | struct device_node *node; | ||
55 | void __iomem * base; | ||
56 | unsigned bsteps; | ||
57 | int irq; | ||
58 | spinlock_t lock; | ||
59 | struct keywest_chan *channels; | ||
60 | unsigned chan_count; | ||
61 | u8 cur_mode; | ||
62 | char read_write; | ||
63 | u8 *data; | ||
64 | unsigned datalen; | ||
65 | int state; | ||
66 | int result; | ||
67 | struct timer_list timeout_timer; | ||
68 | struct completion complete; | ||
69 | }; | ||
70 | |||
71 | enum { | ||
72 | state_idle, | ||
73 | state_addr, | ||
74 | state_read, | ||
75 | state_write, | ||
76 | state_stop, | ||
77 | state_dead | ||
78 | }; | ||
79 | |||
80 | /* Channel on an interface */ | ||
81 | struct keywest_chan | ||
82 | { | ||
83 | struct i2c_adapter adapter; | ||
84 | struct keywest_iface* iface; | ||
85 | unsigned chan_no; | ||
86 | }; | ||
87 | |||
88 | /* Register access */ | ||
89 | |||
90 | static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg) | ||
91 | { | ||
92 | return in_8(iface->base | ||
93 | + (((unsigned)reg) << iface->bsteps)); | ||
94 | } | ||
95 | |||
96 | static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val) | ||
97 | { | ||
98 | out_8(iface->base | ||
99 | + (((unsigned)reg) << iface->bsteps), val); | ||
100 | (void)__read_reg(iface, reg_subaddr); | ||
101 | } | ||
102 | |||
103 | #define write_reg(reg, val) __write_reg(iface, reg, val) | ||
104 | #define read_reg(reg) __read_reg(iface, reg) | ||
105 | |||
106 | |||
107 | |||
108 | #endif /* __I2C_KEYWEST_H__ */ | ||
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c deleted file mode 100644 index bfefe7f7a53d..000000000000 --- a/drivers/i2c/busses/i2c-pmac-smu.c +++ /dev/null | |||
@@ -1,315 +0,0 @@ | |||
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 | |||
35 | static int probe; | ||
36 | |||
37 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
38 | MODULE_DESCRIPTION("I2C driver for Apple's SMU"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | module_param(probe, bool, 0); | ||
41 | |||
42 | |||
43 | /* Physical interface */ | ||
44 | struct smu_iface | ||
45 | { | ||
46 | struct i2c_adapter adapter; | ||
47 | struct completion complete; | ||
48 | u32 busid; | ||
49 | }; | ||
50 | |||
51 | static 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 | */ | ||
60 | static 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 | |||
187 | static u32 | ||
188 | smu_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) */ | ||
196 | static struct i2c_algorithm smu_algorithm = { | ||
197 | .smbus_xfer = smu_smbus_xfer, | ||
198 | .functionality = smu_smbus_func, | ||
199 | }; | ||
200 | |||
201 | static 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 = kzalloc(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 | init_completion(&iface->complete); | ||
220 | iface->busid = busid; | ||
221 | |||
222 | dev_set_drvdata(dev, iface); | ||
223 | |||
224 | sprintf(iface->adapter.name, "smu-i2c-%02x", busid); | ||
225 | iface->adapter.algo = &smu_algorithm; | ||
226 | iface->adapter.algo_data = NULL; | ||
227 | iface->adapter.client_register = NULL; | ||
228 | iface->adapter.client_unregister = NULL; | ||
229 | i2c_set_adapdata(&iface->adapter, iface); | ||
230 | iface->adapter.dev.parent = dev; | ||
231 | |||
232 | rc = i2c_add_adapter(&iface->adapter); | ||
233 | if (rc) { | ||
234 | printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration " | ||
235 | "failed\n", iface->adapter.name); | ||
236 | i2c_set_adapdata(&iface->adapter, NULL); | ||
237 | } | ||
238 | |||
239 | if (probe) { | ||
240 | unsigned char addr; | ||
241 | printk("Probe: "); | ||
242 | for (addr = 0x00; addr <= 0x7f; addr++) { | ||
243 | if (i2c_smbus_xfer(&iface->adapter,addr, | ||
244 | 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) | ||
245 | printk("%02x ", addr); | ||
246 | } | ||
247 | printk("\n"); | ||
248 | } | ||
249 | |||
250 | printk(KERN_INFO "SMU i2c bus %x registered\n", busid); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int dispose_iface(struct device *dev) | ||
256 | { | ||
257 | struct smu_iface *iface = dev_get_drvdata(dev); | ||
258 | int rc; | ||
259 | |||
260 | rc = i2c_del_adapter(&iface->adapter); | ||
261 | i2c_set_adapdata(&iface->adapter, NULL); | ||
262 | /* We aren't that prepared to deal with this... */ | ||
263 | if (rc) | ||
264 | printk("i2c-pmac-smu.c: Failed to remove bus %s !\n", | ||
265 | iface->adapter.name); | ||
266 | dev_set_drvdata(dev, NULL); | ||
267 | kfree(iface); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | |||
273 | static int create_iface_of_platform(struct of_device* dev, | ||
274 | const struct of_device_id *match) | ||
275 | { | ||
276 | return create_iface(dev->node, &dev->dev); | ||
277 | } | ||
278 | |||
279 | |||
280 | static int dispose_iface_of_platform(struct of_device* dev) | ||
281 | { | ||
282 | return dispose_iface(&dev->dev); | ||
283 | } | ||
284 | |||
285 | |||
286 | static struct of_device_id i2c_smu_match[] = | ||
287 | { | ||
288 | { | ||
289 | .compatible = "smu-i2c", | ||
290 | }, | ||
291 | {}, | ||
292 | }; | ||
293 | static struct of_platform_driver i2c_smu_of_platform_driver = | ||
294 | { | ||
295 | .name = "i2c-smu", | ||
296 | .match_table = i2c_smu_match, | ||
297 | .probe = create_iface_of_platform, | ||
298 | .remove = dispose_iface_of_platform | ||
299 | }; | ||
300 | |||
301 | |||
302 | static int __init i2c_pmac_smu_init(void) | ||
303 | { | ||
304 | of_register_driver(&i2c_smu_of_platform_driver); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | |||
309 | static void __exit i2c_pmac_smu_cleanup(void) | ||
310 | { | ||
311 | of_unregister_driver(&i2c_smu_of_platform_driver); | ||
312 | } | ||
313 | |||
314 | module_init(i2c_pmac_smu_init); | ||
315 | module_exit(i2c_pmac_smu_cleanup); | ||
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c new file mode 100644 index 000000000000..df786eb55295 --- /dev/null +++ b/drivers/i2c/busses/i2c-powermac.c | |||
@@ -0,0 +1,290 @@ | |||
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 <linux/platform_device.h> | ||
32 | #include <asm/prom.h> | ||
33 | #include <asm/pmac_low_i2c.h> | ||
34 | |||
35 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
36 | MODULE_DESCRIPTION("I2C driver for Apple PowerMac"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | /* | ||
40 | * SMBUS-type transfer entrypoint | ||
41 | */ | ||
42 | static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, | ||
43 | u16 addr, | ||
44 | unsigned short flags, | ||
45 | char read_write, | ||
46 | u8 command, | ||
47 | int size, | ||
48 | union i2c_smbus_data* data) | ||
49 | { | ||
50 | struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); | ||
51 | int rc = 0; | ||
52 | int read = (read_write == I2C_SMBUS_READ); | ||
53 | int addrdir = (addr << 1) | read; | ||
54 | u8 local[2]; | ||
55 | |||
56 | rc = pmac_i2c_open(bus, 0); | ||
57 | if (rc) | ||
58 | return rc; | ||
59 | |||
60 | switch (size) { | ||
61 | case I2C_SMBUS_QUICK: | ||
62 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | ||
63 | if (rc) | ||
64 | goto bail; | ||
65 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0); | ||
66 | break; | ||
67 | case I2C_SMBUS_BYTE: | ||
68 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | ||
69 | if (rc) | ||
70 | goto bail; | ||
71 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1); | ||
72 | break; | ||
73 | case I2C_SMBUS_BYTE_DATA: | ||
74 | rc = pmac_i2c_setmode(bus, read ? | ||
75 | pmac_i2c_mode_combined : | ||
76 | pmac_i2c_mode_stdsub); | ||
77 | if (rc) | ||
78 | goto bail; | ||
79 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1); | ||
80 | break; | ||
81 | case I2C_SMBUS_WORD_DATA: | ||
82 | rc = pmac_i2c_setmode(bus, read ? | ||
83 | pmac_i2c_mode_combined : | ||
84 | pmac_i2c_mode_stdsub); | ||
85 | if (rc) | ||
86 | goto bail; | ||
87 | if (!read) { | ||
88 | local[0] = data->word & 0xff; | ||
89 | local[1] = (data->word >> 8) & 0xff; | ||
90 | } | ||
91 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2); | ||
92 | if (rc == 0 && read) { | ||
93 | data->word = ((u16)local[1]) << 8; | ||
94 | data->word |= local[0]; | ||
95 | } | ||
96 | break; | ||
97 | |||
98 | /* Note that these are broken vs. the expected smbus API where | ||
99 | * on reads, the lenght is actually returned from the function, | ||
100 | * but I think the current API makes no sense and I don't want | ||
101 | * any driver that I haven't verified for correctness to go | ||
102 | * anywhere near a pmac i2c bus anyway ... | ||
103 | * | ||
104 | * I'm also not completely sure what kind of phases to do between | ||
105 | * the actual command and the data (what I am _supposed_ to do that | ||
106 | * is). For now, I assume writes are a single stream and reads have | ||
107 | * a repeat start/addr phase (but not stop in between) | ||
108 | */ | ||
109 | case I2C_SMBUS_BLOCK_DATA: | ||
110 | rc = pmac_i2c_setmode(bus, read ? | ||
111 | pmac_i2c_mode_combined : | ||
112 | pmac_i2c_mode_stdsub); | ||
113 | if (rc) | ||
114 | goto bail; | ||
115 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block, | ||
116 | data->block[0] + 1); | ||
117 | |||
118 | break; | ||
119 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
120 | rc = pmac_i2c_setmode(bus, read ? | ||
121 | pmac_i2c_mode_combined : | ||
122 | pmac_i2c_mode_stdsub); | ||
123 | if (rc) | ||
124 | goto bail; | ||
125 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, | ||
126 | read ? data->block : &data->block[1], | ||
127 | data->block[0]); | ||
128 | break; | ||
129 | |||
130 | default: | ||
131 | rc = -EINVAL; | ||
132 | } | ||
133 | bail: | ||
134 | pmac_i2c_close(bus); | ||
135 | return rc; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Generic i2c master transfer entrypoint. This driver only support single | ||
140 | * messages (for "lame i2c" transfers). Anything else should use the smbus | ||
141 | * entry point | ||
142 | */ | ||
143 | static int i2c_powermac_master_xfer( struct i2c_adapter *adap, | ||
144 | struct i2c_msg *msgs, | ||
145 | int num) | ||
146 | { | ||
147 | struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); | ||
148 | int rc = 0; | ||
149 | int read; | ||
150 | int addrdir; | ||
151 | |||
152 | if (num != 1) | ||
153 | return -EINVAL; | ||
154 | if (msgs->flags & I2C_M_TEN) | ||
155 | return -EINVAL; | ||
156 | read = (msgs->flags & I2C_M_RD) != 0; | ||
157 | addrdir = (msgs->addr << 1) | read; | ||
158 | if (msgs->flags & I2C_M_REV_DIR_ADDR) | ||
159 | addrdir ^= 1; | ||
160 | |||
161 | rc = pmac_i2c_open(bus, 0); | ||
162 | if (rc) | ||
163 | return rc; | ||
164 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | ||
165 | if (rc) | ||
166 | goto bail; | ||
167 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); | ||
168 | bail: | ||
169 | pmac_i2c_close(bus); | ||
170 | return rc < 0 ? rc : msgs->len; | ||
171 | } | ||
172 | |||
173 | static u32 i2c_powermac_func(struct i2c_adapter * adapter) | ||
174 | { | ||
175 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
176 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
177 | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C; | ||
178 | } | ||
179 | |||
180 | /* For now, we only handle smbus */ | ||
181 | static struct i2c_algorithm i2c_powermac_algorithm = { | ||
182 | .smbus_xfer = i2c_powermac_smbus_xfer, | ||
183 | .master_xfer = i2c_powermac_master_xfer, | ||
184 | .functionality = i2c_powermac_func, | ||
185 | }; | ||
186 | |||
187 | |||
188 | static int i2c_powermac_remove(struct device *dev) | ||
189 | { | ||
190 | struct i2c_adapter *adapter = dev_get_drvdata(dev); | ||
191 | struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter); | ||
192 | int rc; | ||
193 | |||
194 | rc = i2c_del_adapter(adapter); | ||
195 | pmac_i2c_detach_adapter(bus, adapter); | ||
196 | i2c_set_adapdata(adapter, NULL); | ||
197 | /* We aren't that prepared to deal with this... */ | ||
198 | if (rc) | ||
199 | printk("i2c-powermac.c: Failed to remove bus %s !\n", | ||
200 | adapter->name); | ||
201 | dev_set_drvdata(dev, NULL); | ||
202 | kfree(adapter); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | |||
208 | static int i2c_powermac_probe(struct device *dev) | ||
209 | { | ||
210 | struct pmac_i2c_bus *bus = dev->platform_data; | ||
211 | struct device_node *parent = NULL; | ||
212 | struct i2c_adapter *adapter; | ||
213 | char name[32], *basename; | ||
214 | int rc; | ||
215 | |||
216 | if (bus == NULL) | ||
217 | return -EINVAL; | ||
218 | |||
219 | /* Ok, now we need to make up a name for the interface that will | ||
220 | * match what we used to do in the past, that is basically the | ||
221 | * controller's parent device node for keywest. PMU didn't have a | ||
222 | * naming convention and SMU has a different one | ||
223 | */ | ||
224 | switch(pmac_i2c_get_type(bus)) { | ||
225 | case pmac_i2c_bus_keywest: | ||
226 | parent = of_get_parent(pmac_i2c_get_controller(bus)); | ||
227 | if (parent == NULL) | ||
228 | return -EINVAL; | ||
229 | basename = parent->name; | ||
230 | break; | ||
231 | case pmac_i2c_bus_pmu: | ||
232 | basename = "pmu"; | ||
233 | break; | ||
234 | case pmac_i2c_bus_smu: | ||
235 | /* This is not what we used to do but I'm fixing drivers at | ||
236 | * the same time as this change | ||
237 | */ | ||
238 | basename = "smu"; | ||
239 | break; | ||
240 | default: | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus)); | ||
244 | of_node_put(parent); | ||
245 | |||
246 | adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); | ||
247 | if (adapter == NULL) { | ||
248 | printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n"); | ||
249 | return -ENOMEM; | ||
250 | } | ||
251 | dev_set_drvdata(dev, adapter); | ||
252 | strcpy(adapter->name, name); | ||
253 | adapter->algo = &i2c_powermac_algorithm; | ||
254 | i2c_set_adapdata(adapter, bus); | ||
255 | adapter->dev.parent = dev; | ||
256 | pmac_i2c_attach_adapter(bus, adapter); | ||
257 | rc = i2c_add_adapter(adapter); | ||
258 | if (rc) { | ||
259 | printk(KERN_ERR "i2c-powermac: Adapter %s registration " | ||
260 | "failed\n", name); | ||
261 | i2c_set_adapdata(adapter, NULL); | ||
262 | pmac_i2c_detach_adapter(bus, adapter); | ||
263 | } | ||
264 | |||
265 | printk(KERN_INFO "PowerMac i2c bus %s registered\n", name); | ||
266 | return rc; | ||
267 | } | ||
268 | |||
269 | |||
270 | static struct device_driver i2c_powermac_driver = { | ||
271 | .name = "i2c-powermac", | ||
272 | .bus = &platform_bus_type, | ||
273 | .probe = i2c_powermac_probe, | ||
274 | .remove = i2c_powermac_remove, | ||
275 | }; | ||
276 | |||
277 | static int __init i2c_powermac_init(void) | ||
278 | { | ||
279 | driver_register(&i2c_powermac_driver); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | static void __exit i2c_powermac_cleanup(void) | ||
285 | { | ||
286 | driver_unregister(&i2c_powermac_driver); | ||
287 | } | ||
288 | |||
289 | module_init(i2c_powermac_init); | ||
290 | module_exit(i2c_powermac_cleanup); | ||
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 16b28357885b..5013b1285e22 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c | |||
@@ -1271,7 +1271,7 @@ static int | |||
1271 | pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) | 1271 | pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) |
1272 | { | 1272 | { |
1273 | struct device_node *np = pmif->node; | 1273 | struct device_node *np = pmif->node; |
1274 | int *bidp, i; | 1274 | int *bidp; |
1275 | 1275 | ||
1276 | pmif->cable_80 = 0; | 1276 | pmif->cable_80 = 0; |
1277 | pmif->broken_dma = pmif->broken_dma_warn = 0; | 1277 | pmif->broken_dma = pmif->broken_dma_warn = 0; |
@@ -1430,7 +1430,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) | |||
1430 | pmif = &pmac_ide[i]; | 1430 | pmif = &pmac_ide[i]; |
1431 | hwif = &ide_hwifs[i]; | 1431 | hwif = &ide_hwifs[i]; |
1432 | 1432 | ||
1433 | if (mdev->ofdev.node->n_addrs == 0) { | 1433 | if (macio_resource_count(mdev) == 0) { |
1434 | printk(KERN_WARNING "ide%d: no address for %s\n", | 1434 | printk(KERN_WARNING "ide%d: no address for %s\n", |
1435 | i, mdev->ofdev.node->full_name); | 1435 | i, mdev->ofdev.node->full_name); |
1436 | return -ENXIO; | 1436 | return -ENXIO; |
@@ -1686,7 +1686,7 @@ pmac_ide_probe(void) | |||
1686 | #else | 1686 | #else |
1687 | macio_register_driver(&pmac_ide_macio_driver); | 1687 | macio_register_driver(&pmac_ide_macio_driver); |
1688 | pci_register_driver(&pmac_ide_pci_driver); | 1688 | pci_register_driver(&pmac_ide_pci_driver); |
1689 | #endif | 1689 | #endif |
1690 | } | 1690 | } |
1691 | 1691 | ||
1692 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 1692 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index a0ea44c3e8b1..7d4a0ac28c06 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -149,14 +149,14 @@ config MAC_EMUMOUSEBTN | |||
149 | 149 | ||
150 | config THERM_WINDTUNNEL | 150 | config THERM_WINDTUNNEL |
151 | tristate "Support for thermal management on Windtunnel G4s" | 151 | tristate "Support for thermal management on Windtunnel G4s" |
152 | depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 | 152 | depends on I2C && I2C_POWERMAC && PPC_PMAC && !PPC_PMAC64 |
153 | help | 153 | help |
154 | This driver provides some thermostat and fan control for the desktop | 154 | This driver provides some thermostat and fan control for the desktop |
155 | G4 "Windtunnel" | 155 | G4 "Windtunnel" |
156 | 156 | ||
157 | config THERM_ADT746X | 157 | config THERM_ADT746X |
158 | tristate "Support for thermal mgmnt on laptops with ADT 746x chipset" | 158 | tristate "Support for thermal mgmnt on laptops with ADT 746x chipset" |
159 | depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 | 159 | depends on I2C && I2C_POWERMAC && PPC_PMAC && !PPC_PMAC64 |
160 | help | 160 | help |
161 | This driver provides some thermostat and fan control for the | 161 | This driver provides some thermostat and fan control for the |
162 | iBook G4, and the ATI based aluminium PowerBooks, allowing slighlty | 162 | iBook G4, and the ATI based aluminium PowerBooks, allowing slighlty |
@@ -164,7 +164,7 @@ config THERM_ADT746X | |||
164 | 164 | ||
165 | config THERM_PM72 | 165 | config THERM_PM72 |
166 | tristate "Support for thermal management on PowerMac G5" | 166 | tristate "Support for thermal management on PowerMac G5" |
167 | depends on I2C && I2C_KEYWEST && PPC_PMAC64 | 167 | depends on I2C && I2C_POWERMAC && PPC_PMAC64 |
168 | help | 168 | help |
169 | This driver provides thermostat and fan control for the desktop | 169 | This driver provides thermostat and fan control for the desktop |
170 | G5 machines. | 170 | G5 machines. |
@@ -175,14 +175,14 @@ config WINDFARM | |||
175 | config WINDFARM_PM81 | 175 | config WINDFARM_PM81 |
176 | tristate "Support for thermal management on iMac G5" | 176 | tristate "Support for thermal management on iMac G5" |
177 | depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU | 177 | depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU |
178 | select I2C_PMAC_SMU | 178 | select I2C_POWERMAC |
179 | help | 179 | help |
180 | This driver provides thermal control for the iMacG5 | 180 | This driver provides thermal control for the iMacG5 |
181 | 181 | ||
182 | config WINDFARM_PM91 | 182 | config WINDFARM_PM91 |
183 | tristate "Support for thermal management on PowerMac9,1" | 183 | tristate "Support for thermal management on PowerMac9,1" |
184 | depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU | 184 | depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU |
185 | select I2C_PMAC_SMU | 185 | select I2C_POWERMAC |
186 | help | 186 | help |
187 | This driver provides thermal control for the PowerMac9,1 | 187 | This driver provides thermal control for the PowerMac9,1 |
188 | which is the recent (SMU based) single CPU desktop G5 | 188 | which is the recent (SMU based) single CPU desktop G5 |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 228e1852a836..2a545ceb523b 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -3,6 +3,13 @@ | |||
3 | * a MacIO ASIC. Interface to new driver model mostly | 3 | * a MacIO ASIC. Interface to new driver model mostly |
4 | * stolen from the PCI version. | 4 | * stolen from the PCI version. |
5 | * | 5 | * |
6 | * Copyright (C) 2005 Ben. Herrenschmidt (benh@kernel.crashing.org) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
6 | * TODO: | 13 | * TODO: |
7 | * | 14 | * |
8 | * - Don't probe below media bay by default, but instead provide | 15 | * - Don't probe below media bay by default, but instead provide |
@@ -218,12 +225,14 @@ postcore_initcall(macio_bus_driver_init); | |||
218 | 225 | ||
219 | 226 | ||
220 | /** | 227 | /** |
221 | * macio_release_dev - free a macio device structure when all users of it are finished. | 228 | * macio_release_dev - free a macio device structure when all users of it are |
229 | * finished. | ||
222 | * @dev: device that's been disconnected | 230 | * @dev: device that's been disconnected |
223 | * | 231 | * |
224 | * Will be called only by the device core when all users of this macio device are | 232 | * Will be called only by the device core when all users of this macio device |
225 | * done. This currently means never as we don't hot remove any macio device yet, | 233 | * are done. This currently means never as we don't hot remove any macio |
226 | * though that will happen with mediabay based devices in a later implementation. | 234 | * device yet, though that will happen with mediabay based devices in a later |
235 | * implementation. | ||
227 | */ | 236 | */ |
228 | static void macio_release_dev(struct device *dev) | 237 | static void macio_release_dev(struct device *dev) |
229 | { | 238 | { |
@@ -242,49 +251,114 @@ static void macio_release_dev(struct device *dev) | |||
242 | * If this routine returns non-null, then the resource is completely | 251 | * If this routine returns non-null, then the resource is completely |
243 | * skipped. | 252 | * skipped. |
244 | */ | 253 | */ |
245 | static int macio_resource_quirks(struct device_node *np, struct resource *res, int index) | 254 | static int macio_resource_quirks(struct device_node *np, struct resource *res, |
255 | int index) | ||
246 | { | 256 | { |
247 | if (res->flags & IORESOURCE_MEM) { | 257 | if (res->flags & IORESOURCE_MEM) { |
248 | /* Grand Central has too large resource 0 on some machines */ | 258 | /* Grand Central has too large resource 0 on some machines */ |
249 | if (index == 0 && !strcmp(np->name, "gc")) { | 259 | if (index == 0 && !strcmp(np->name, "gc")) |
250 | np->addrs[0].size = 0x20000; | ||
251 | res->end = res->start + 0x1ffff; | 260 | res->end = res->start + 0x1ffff; |
252 | } | 261 | |
253 | /* Airport has bogus resource 2 */ | 262 | /* Airport has bogus resource 2 */ |
254 | if (index >= 2 && !strcmp(np->name, "radio")) | 263 | if (index >= 2 && !strcmp(np->name, "radio")) |
255 | return 1; | 264 | return 1; |
265 | |||
266 | #ifndef CONFIG_PPC64 | ||
256 | /* DBDMAs may have bogus sizes */ | 267 | /* DBDMAs may have bogus sizes */ |
257 | if ((res->start & 0x0001f000) == 0x00008000) { | 268 | if ((res->start & 0x0001f000) == 0x00008000) |
258 | np->addrs[index].size = 0x100; | ||
259 | res->end = res->start + 0xff; | 269 | res->end = res->start + 0xff; |
260 | } | 270 | #endif /* CONFIG_PPC64 */ |
261 | /* ESCC parent eats child resources. We could have added a level of hierarchy, | 271 | |
262 | * but I don't really feel the need for it */ | 272 | /* ESCC parent eats child resources. We could have added a |
273 | * level of hierarchy, but I don't really feel the need | ||
274 | * for it | ||
275 | */ | ||
263 | if (!strcmp(np->name, "escc")) | 276 | if (!strcmp(np->name, "escc")) |
264 | return 1; | 277 | return 1; |
278 | |||
265 | /* ESCC has bogus resources >= 3 */ | 279 | /* ESCC has bogus resources >= 3 */ |
266 | if (index >= 3 && !(strcmp(np->name, "ch-a") && strcmp(np->name, "ch-b"))) | 280 | if (index >= 3 && !(strcmp(np->name, "ch-a") && |
281 | strcmp(np->name, "ch-b"))) | ||
267 | return 1; | 282 | return 1; |
283 | |||
268 | /* Media bay has too many resources, keep only first one */ | 284 | /* Media bay has too many resources, keep only first one */ |
269 | if (index > 0 && !strcmp(np->name, "media-bay")) | 285 | if (index > 0 && !strcmp(np->name, "media-bay")) |
270 | return 1; | 286 | return 1; |
287 | |||
271 | /* Some older IDE resources have bogus sizes */ | 288 | /* Some older IDE resources have bogus sizes */ |
272 | if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && | 289 | if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && |
273 | strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { | 290 | strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { |
274 | if (index == 0 && np->addrs[0].size > 0x1000) { | 291 | if (index == 0 && (res->end - res->start) > 0xfff) |
275 | np->addrs[0].size = 0x1000; | ||
276 | res->end = res->start + 0xfff; | 292 | res->end = res->start + 0xfff; |
277 | } | 293 | if (index == 1 && (res->end - res->start) > 0xff) |
278 | if (index == 1 && np->addrs[1].size > 0x100) { | ||
279 | np->addrs[1].size = 0x100; | ||
280 | res->end = res->start + 0xff; | 294 | res->end = res->start + 0xff; |
281 | } | ||
282 | } | 295 | } |
283 | } | 296 | } |
284 | return 0; | 297 | return 0; |
285 | } | 298 | } |
286 | 299 | ||
287 | 300 | ||
301 | static void macio_setup_interrupts(struct macio_dev *dev) | ||
302 | { | ||
303 | struct device_node *np = dev->ofdev.node; | ||
304 | int i,j; | ||
305 | |||
306 | /* For now, we use pre-parsed entries in the device-tree for | ||
307 | * interrupt routing and addresses, but we should change that | ||
308 | * to dynamically parsed entries and so get rid of most of the | ||
309 | * clutter in struct device_node | ||
310 | */ | ||
311 | for (i = j = 0; i < np->n_intrs; i++) { | ||
312 | struct resource *res = &dev->interrupt[j]; | ||
313 | |||
314 | if (j >= MACIO_DEV_COUNT_IRQS) | ||
315 | break; | ||
316 | res->start = np->intrs[i].line; | ||
317 | res->flags = IORESOURCE_IO; | ||
318 | if (np->intrs[j].sense) | ||
319 | res->flags |= IORESOURCE_IRQ_LOWLEVEL; | ||
320 | else | ||
321 | res->flags |= IORESOURCE_IRQ_HIGHEDGE; | ||
322 | res->name = dev->ofdev.dev.bus_id; | ||
323 | if (macio_resource_quirks(np, res, i)) | ||
324 | memset(res, 0, sizeof(struct resource)); | ||
325 | else | ||
326 | j++; | ||
327 | } | ||
328 | dev->n_interrupts = j; | ||
329 | } | ||
330 | |||
331 | static void macio_setup_resources(struct macio_dev *dev, | ||
332 | struct resource *parent_res) | ||
333 | { | ||
334 | struct device_node *np = dev->ofdev.node; | ||
335 | struct resource r; | ||
336 | int index; | ||
337 | |||
338 | for (index = 0; of_address_to_resource(np, index, &r) == 0; index++) { | ||
339 | struct resource *res = &dev->resource[index]; | ||
340 | if (index >= MACIO_DEV_COUNT_RESOURCES) | ||
341 | break; | ||
342 | *res = r; | ||
343 | res->name = dev->ofdev.dev.bus_id; | ||
344 | |||
345 | if (macio_resource_quirks(np, res, index)) { | ||
346 | memset(res, 0, sizeof(struct resource)); | ||
347 | continue; | ||
348 | } | ||
349 | /* Currently, we consider failure as harmless, this may | ||
350 | * change in the future, once I've found all the device | ||
351 | * tree bugs in older machines & worked around them | ||
352 | */ | ||
353 | if (insert_resource(parent_res, res)) { | ||
354 | printk(KERN_WARNING "Can't request resource " | ||
355 | "%d for MacIO device %s\n", | ||
356 | index, dev->ofdev.dev.bus_id); | ||
357 | } | ||
358 | } | ||
359 | dev->n_resources = index; | ||
360 | } | ||
361 | |||
288 | /** | 362 | /** |
289 | * macio_add_one_device - Add one device from OF node to the device tree | 363 | * macio_add_one_device - Add one device from OF node to the device tree |
290 | * @chip: pointer to the macio_chip holding the device | 364 | * @chip: pointer to the macio_chip holding the device |
@@ -294,12 +368,13 @@ static int macio_resource_quirks(struct device_node *np, struct resource *res, i | |||
294 | * When media-bay is changed to hotswap drivers, this function will | 368 | * When media-bay is changed to hotswap drivers, this function will |
295 | * be exposed to the bay driver some way... | 369 | * be exposed to the bay driver some way... |
296 | */ | 370 | */ |
297 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct device *parent, | 371 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip, |
298 | struct device_node *np, struct macio_dev *in_bay, | 372 | struct device *parent, |
373 | struct device_node *np, | ||
374 | struct macio_dev *in_bay, | ||
299 | struct resource *parent_res) | 375 | struct resource *parent_res) |
300 | { | 376 | { |
301 | struct macio_dev *dev; | 377 | struct macio_dev *dev; |
302 | int i, j; | ||
303 | u32 *reg; | 378 | u32 *reg; |
304 | 379 | ||
305 | if (np == NULL) | 380 | if (np == NULL) |
@@ -326,7 +401,8 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d | |||
326 | 401 | ||
327 | /* MacIO itself has a different reg, we use it's PCI base */ | 402 | /* MacIO itself has a different reg, we use it's PCI base */ |
328 | if (np == chip->of_node) { | 403 | if (np == chip->of_node) { |
329 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", chip->lbus.index, | 404 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", |
405 | chip->lbus.index, | ||
330 | #ifdef CONFIG_PCI | 406 | #ifdef CONFIG_PCI |
331 | pci_resource_start(chip->lbus.pdev, 0), | 407 | pci_resource_start(chip->lbus.pdev, 0), |
332 | #else | 408 | #else |
@@ -335,57 +411,16 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d | |||
335 | MAX_NODE_NAME_SIZE, np->name); | 411 | MAX_NODE_NAME_SIZE, np->name); |
336 | } else { | 412 | } else { |
337 | reg = (u32 *)get_property(np, "reg", NULL); | 413 | reg = (u32 *)get_property(np, "reg", NULL); |
338 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, | 414 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", |
415 | chip->lbus.index, | ||
339 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); | 416 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); |
340 | } | 417 | } |
341 | 418 | ||
342 | /* For now, we use pre-parsed entries in the device-tree for | 419 | /* Setup interrupts & resources */ |
343 | * interrupt routing and addresses, but we should change that | 420 | macio_setup_interrupts(dev); |
344 | * to dynamically parsed entries and so get rid of most of the | 421 | macio_setup_resources(dev, parent_res); |
345 | * clutter in struct device_node | ||
346 | */ | ||
347 | for (i = j = 0; i < np->n_intrs; i++) { | ||
348 | struct resource *res = &dev->interrupt[j]; | ||
349 | |||
350 | if (j >= MACIO_DEV_COUNT_IRQS) | ||
351 | break; | ||
352 | res->start = np->intrs[i].line; | ||
353 | res->flags = IORESOURCE_IO; | ||
354 | if (np->intrs[j].sense) | ||
355 | res->flags |= IORESOURCE_IRQ_LOWLEVEL; | ||
356 | else | ||
357 | res->flags |= IORESOURCE_IRQ_HIGHEDGE; | ||
358 | res->name = dev->ofdev.dev.bus_id; | ||
359 | if (macio_resource_quirks(np, res, i)) | ||
360 | memset(res, 0, sizeof(struct resource)); | ||
361 | else | ||
362 | j++; | ||
363 | } | ||
364 | dev->n_interrupts = j; | ||
365 | for (i = j = 0; i < np->n_addrs; i++) { | ||
366 | struct resource *res = &dev->resource[j]; | ||
367 | |||
368 | if (j >= MACIO_DEV_COUNT_RESOURCES) | ||
369 | break; | ||
370 | res->start = np->addrs[i].address; | ||
371 | res->end = np->addrs[i].address + np->addrs[i].size - 1; | ||
372 | res->flags = IORESOURCE_MEM; | ||
373 | res->name = dev->ofdev.dev.bus_id; | ||
374 | if (macio_resource_quirks(np, res, i)) | ||
375 | memset(res, 0, sizeof(struct resource)); | ||
376 | else { | ||
377 | j++; | ||
378 | /* Currently, we consider failure as harmless, this may | ||
379 | * change in the future, once I've found all the device | ||
380 | * tree bugs in older machines & worked around them | ||
381 | */ | ||
382 | if (insert_resource(parent_res, res)) | ||
383 | printk(KERN_WARNING "Can't request resource %d for MacIO" | ||
384 | " device %s\n", i, dev->ofdev.dev.bus_id); | ||
385 | } | ||
386 | } | ||
387 | dev->n_resources = j; | ||
388 | 422 | ||
423 | /* Register with core */ | ||
389 | if (of_device_register(&dev->ofdev) != 0) { | 424 | if (of_device_register(&dev->ofdev) != 0) { |
390 | printk(KERN_DEBUG"macio: device registration error for %s!\n", | 425 | printk(KERN_DEBUG"macio: device registration error for %s!\n", |
391 | dev->ofdev.dev.bus_id); | 426 | dev->ofdev.dev.bus_id); |
@@ -442,36 +477,42 @@ static void macio_pci_add_devices(struct macio_chip *chip) | |||
442 | 477 | ||
443 | /* First scan 1st level */ | 478 | /* First scan 1st level */ |
444 | for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { | 479 | for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { |
445 | if (!macio_skip_device(np)) { | 480 | if (macio_skip_device(np)) |
446 | of_node_get(np); | 481 | continue; |
447 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, root_res); | 482 | of_node_get(np); |
448 | if (mdev == NULL) | 483 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, |
449 | of_node_put(np); | 484 | root_res); |
450 | else if (strncmp(np->name, "media-bay", 9) == 0) | 485 | if (mdev == NULL) |
451 | mbdev = mdev; | 486 | of_node_put(np); |
452 | else if (strncmp(np->name, "escc", 4) == 0) | 487 | else if (strncmp(np->name, "media-bay", 9) == 0) |
453 | sdev = mdev; | 488 | mbdev = mdev; |
454 | } | 489 | else if (strncmp(np->name, "escc", 4) == 0) |
490 | sdev = mdev; | ||
455 | } | 491 | } |
456 | 492 | ||
457 | /* Add media bay devices if any */ | 493 | /* Add media bay devices if any */ |
458 | if (mbdev) | 494 | if (mbdev) |
459 | for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) != NULL;) | 495 | for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) |
460 | if (!macio_skip_device(np)) { | 496 | != NULL;) { |
461 | of_node_get(np); | 497 | if (macio_skip_device(np)) |
462 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, mbdev, | 498 | continue; |
463 | root_res) == NULL) | 499 | of_node_get(np); |
464 | of_node_put(np); | 500 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, |
465 | } | 501 | mbdev, root_res) == NULL) |
502 | of_node_put(np); | ||
503 | } | ||
504 | |||
466 | /* Add serial ports if any */ | 505 | /* Add serial ports if any */ |
467 | if (sdev) { | 506 | if (sdev) { |
468 | for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) != NULL;) | 507 | for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) |
469 | if (!macio_skip_device(np)) { | 508 | != NULL;) { |
470 | of_node_get(np); | 509 | if (macio_skip_device(np)) |
471 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np, NULL, | 510 | continue; |
472 | root_res) == NULL) | 511 | of_node_get(np); |
473 | of_node_put(np); | 512 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np, |
474 | } | 513 | NULL, root_res) == NULL) |
514 | of_node_put(np); | ||
515 | } | ||
475 | } | 516 | } |
476 | } | 517 | } |
477 | 518 | ||
@@ -519,7 +560,8 @@ void macio_unregister_driver(struct macio_driver *drv) | |||
519 | * Returns 0 on success, or %EBUSY on error. A warning | 560 | * Returns 0 on success, or %EBUSY on error. A warning |
520 | * message is also printed on failure. | 561 | * message is also printed on failure. |
521 | */ | 562 | */ |
522 | int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name) | 563 | int macio_request_resource(struct macio_dev *dev, int resource_no, |
564 | const char *name) | ||
523 | { | 565 | { |
524 | if (macio_resource_len(dev, resource_no) == 0) | 566 | if (macio_resource_len(dev, resource_no) == 0) |
525 | return 0; | 567 | return 0; |
@@ -606,20 +648,20 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
606 | if (ent->vendor != PCI_VENDOR_ID_APPLE) | 648 | if (ent->vendor != PCI_VENDOR_ID_APPLE) |
607 | return -ENODEV; | 649 | return -ENODEV; |
608 | 650 | ||
609 | /* Note regarding refcounting: We assume pci_device_to_OF_node() is ported | 651 | /* Note regarding refcounting: We assume pci_device_to_OF_node() is |
610 | * to new OF APIs and returns a node with refcount incremented. This isn't | 652 | * ported to new OF APIs and returns a node with refcount incremented. |
611 | * the case today, but on the other hand ppc32 doesn't do refcounting. This | ||
612 | * will have to be fixed when going to ppc64. --BenH. | ||
613 | */ | 653 | */ |
614 | np = pci_device_to_OF_node(pdev); | 654 | np = pci_device_to_OF_node(pdev); |
615 | if (np == NULL) | 655 | if (np == NULL) |
616 | return -ENODEV; | 656 | return -ENODEV; |
617 | 657 | ||
618 | /* This assumption is wrong, fix that here for now until I fix the arch */ | 658 | /* The above assumption is wrong !!! |
659 | * fix that here for now until I fix the arch code | ||
660 | */ | ||
619 | of_node_get(np); | 661 | of_node_get(np); |
620 | 662 | ||
621 | /* We also assume that pmac_feature will have done a get() on nodes stored | 663 | /* We also assume that pmac_feature will have done a get() on nodes |
622 | * in the macio chips array | 664 | * stored in the macio chips array |
623 | */ | 665 | */ |
624 | chip = macio_find(np, macio_unknown); | 666 | chip = macio_find(np, macio_unknown); |
625 | of_node_put(np); | 667 | of_node_put(np); |
@@ -639,9 +681,9 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
639 | 681 | ||
640 | /* | 682 | /* |
641 | * HACK ALERT: The WallStreet PowerBook and some OHare based machines | 683 | * HACK ALERT: The WallStreet PowerBook and some OHare based machines |
642 | * have 2 macio ASICs. I must probe the "main" one first or IDE ordering | 684 | * have 2 macio ASICs. I must probe the "main" one first or IDE |
643 | * will be incorrect. So I put on "hold" the second one since it seem to | 685 | * ordering will be incorrect. So I put on "hold" the second one since |
644 | * appear first on PCI | 686 | * it seem to appear first on PCI |
645 | */ | 687 | */ |
646 | if (chip->type == macio_gatwick || chip->type == macio_ohareII) | 688 | if (chip->type == macio_gatwick || chip->type == macio_ohareII) |
647 | if (macio_chips[0].lbus.pdev == NULL) { | 689 | if (macio_chips[0].lbus.pdev == NULL) { |
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index b856bb67169c..8dbf2852bae0 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c | |||
@@ -647,6 +647,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de | |||
647 | struct media_bay_info* bay; | 647 | struct media_bay_info* bay; |
648 | u32 __iomem *regbase; | 648 | u32 __iomem *regbase; |
649 | struct device_node *ofnode; | 649 | struct device_node *ofnode; |
650 | unsigned long base; | ||
650 | int i; | 651 | int i; |
651 | 652 | ||
652 | ofnode = mdev->ofdev.node; | 653 | ofnode = mdev->ofdev.node; |
@@ -656,10 +657,11 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de | |||
656 | if (macio_request_resources(mdev, "media-bay")) | 657 | if (macio_request_resources(mdev, "media-bay")) |
657 | return -EBUSY; | 658 | return -EBUSY; |
658 | /* Media bay registers are located at the beginning of the | 659 | /* Media bay registers are located at the beginning of the |
659 | * mac-io chip, we get the parent address for now (hrm...) | 660 | * mac-io chip, for now, we trick and align down the first |
661 | * resource passed in | ||
660 | */ | 662 | */ |
661 | regbase = (u32 __iomem *) | 663 | base = macio_resource_start(mdev, 0) & 0xffff0000u; |
662 | ioremap(ofnode->parent->addrs[0].address, 0x100); | 664 | regbase = (u32 __iomem *)ioremap(base, 0x100); |
663 | if (regbase == NULL) { | 665 | if (regbase == NULL) { |
664 | macio_release_resources(mdev); | 666 | macio_release_resources(mdev); |
665 | return -ENOMEM; | 667 | return -ENOMEM; |
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index e8378274d710..db2ae71d07ef 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c | |||
@@ -53,7 +53,7 @@ | |||
53 | #undef DEBUG_SMU | 53 | #undef DEBUG_SMU |
54 | 54 | ||
55 | #ifdef DEBUG_SMU | 55 | #ifdef DEBUG_SMU |
56 | #define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0) | 56 | #define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) |
57 | #else | 57 | #else |
58 | #define DPRINTK(fmt, args...) do { } while (0) | 58 | #define DPRINTK(fmt, args...) do { } while (0) |
59 | #endif | 59 | #endif |
@@ -94,6 +94,8 @@ struct smu_device { | |||
94 | static struct smu_device *smu; | 94 | static struct smu_device *smu; |
95 | static DECLARE_MUTEX(smu_part_access); | 95 | static DECLARE_MUTEX(smu_part_access); |
96 | 96 | ||
97 | static void smu_i2c_retry(unsigned long data); | ||
98 | |||
97 | /* | 99 | /* |
98 | * SMU driver low level stuff | 100 | * SMU driver low level stuff |
99 | */ | 101 | */ |
@@ -469,7 +471,6 @@ int __init smu_init (void) | |||
469 | smu->of_node = np; | 471 | smu->of_node = np; |
470 | smu->db_irq = NO_IRQ; | 472 | smu->db_irq = NO_IRQ; |
471 | smu->msg_irq = NO_IRQ; | 473 | smu->msg_irq = NO_IRQ; |
472 | init_timer(&smu->i2c_timer); | ||
473 | 474 | ||
474 | /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a | 475 | /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a |
475 | * 32 bits value safely | 476 | * 32 bits value safely |
@@ -544,6 +545,10 @@ static int smu_late_init(void) | |||
544 | if (!smu) | 545 | if (!smu) |
545 | return 0; | 546 | return 0; |
546 | 547 | ||
548 | init_timer(&smu->i2c_timer); | ||
549 | smu->i2c_timer.function = smu_i2c_retry; | ||
550 | smu->i2c_timer.data = (unsigned long)smu; | ||
551 | |||
547 | /* | 552 | /* |
548 | * Try to request the interrupts | 553 | * Try to request the interrupts |
549 | */ | 554 | */ |
@@ -570,7 +575,10 @@ static int smu_late_init(void) | |||
570 | 575 | ||
571 | return 0; | 576 | return 0; |
572 | } | 577 | } |
573 | arch_initcall(smu_late_init); | 578 | /* This has to be before arch_initcall as the low i2c stuff relies on the |
579 | * above having been done before we reach arch_initcalls | ||
580 | */ | ||
581 | core_initcall(smu_late_init); | ||
574 | 582 | ||
575 | /* | 583 | /* |
576 | * sysfs visibility | 584 | * sysfs visibility |
@@ -580,20 +588,10 @@ static void smu_expose_childs(void *unused) | |||
580 | { | 588 | { |
581 | struct device_node *np; | 589 | struct device_node *np; |
582 | 590 | ||
583 | for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) { | 591 | for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) |
584 | if (device_is_compatible(np, "smu-i2c")) { | ||
585 | char name[32]; | ||
586 | u32 *reg = (u32 *)get_property(np, "reg", NULL); | ||
587 | |||
588 | if (reg == NULL) | ||
589 | continue; | ||
590 | sprintf(name, "smu-i2c-%02x", *reg); | ||
591 | of_platform_device_create(np, name, &smu->of_dev->dev); | ||
592 | } | ||
593 | if (device_is_compatible(np, "smu-sensors")) | 592 | if (device_is_compatible(np, "smu-sensors")) |
594 | of_platform_device_create(np, "smu-sensors", &smu->of_dev->dev); | 593 | of_platform_device_create(np, "smu-sensors", |
595 | } | 594 | &smu->of_dev->dev); |
596 | |||
597 | } | 595 | } |
598 | 596 | ||
599 | static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL); | 597 | static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL); |
@@ -712,13 +710,13 @@ static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail) | |||
712 | 710 | ||
713 | static void smu_i2c_retry(unsigned long data) | 711 | static void smu_i2c_retry(unsigned long data) |
714 | { | 712 | { |
715 | struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data; | 713 | struct smu_i2c_cmd *cmd = smu->cmd_i2c_cur; |
716 | 714 | ||
717 | DPRINTK("SMU: i2c failure, requeuing...\n"); | 715 | DPRINTK("SMU: i2c failure, requeuing...\n"); |
718 | 716 | ||
719 | /* requeue command simply by resetting reply_len */ | 717 | /* requeue command simply by resetting reply_len */ |
720 | cmd->pdata[0] = 0xff; | 718 | cmd->pdata[0] = 0xff; |
721 | cmd->scmd.reply_len = 0x10; | 719 | cmd->scmd.reply_len = sizeof(cmd->pdata); |
722 | smu_queue_cmd(&cmd->scmd); | 720 | smu_queue_cmd(&cmd->scmd); |
723 | } | 721 | } |
724 | 722 | ||
@@ -747,10 +745,8 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) | |||
747 | */ | 745 | */ |
748 | if (fail && --cmd->retries > 0) { | 746 | if (fail && --cmd->retries > 0) { |
749 | DPRINTK("SMU: i2c failure, starting timer...\n"); | 747 | DPRINTK("SMU: i2c failure, starting timer...\n"); |
750 | smu->i2c_timer.function = smu_i2c_retry; | 748 | BUG_ON(cmd != smu->cmd_i2c_cur); |
751 | smu->i2c_timer.data = (unsigned long)cmd; | 749 | mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5)); |
752 | smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5); | ||
753 | add_timer(&smu->i2c_timer); | ||
754 | return; | 750 | return; |
755 | } | 751 | } |
756 | 752 | ||
@@ -764,7 +760,7 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) | |||
764 | 760 | ||
765 | /* Ok, initial command complete, now poll status */ | 761 | /* Ok, initial command complete, now poll status */ |
766 | scmd->reply_buf = cmd->pdata; | 762 | scmd->reply_buf = cmd->pdata; |
767 | scmd->reply_len = 0x10; | 763 | scmd->reply_len = sizeof(cmd->pdata); |
768 | scmd->data_buf = cmd->pdata; | 764 | scmd->data_buf = cmd->pdata; |
769 | scmd->data_len = 1; | 765 | scmd->data_len = 1; |
770 | cmd->pdata[0] = 0; | 766 | cmd->pdata[0] = 0; |
@@ -786,7 +782,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) | |||
786 | cmd->scmd.done = smu_i2c_low_completion; | 782 | cmd->scmd.done = smu_i2c_low_completion; |
787 | cmd->scmd.misc = cmd; | 783 | cmd->scmd.misc = cmd; |
788 | cmd->scmd.reply_buf = cmd->pdata; | 784 | cmd->scmd.reply_buf = cmd->pdata; |
789 | cmd->scmd.reply_len = 0x10; | 785 | cmd->scmd.reply_len = sizeof(cmd->pdata); |
790 | cmd->scmd.data_buf = (u8 *)(char *)&cmd->info; | 786 | cmd->scmd.data_buf = (u8 *)(char *)&cmd->info; |
791 | cmd->scmd.status = 1; | 787 | cmd->scmd.status = 1; |
792 | cmd->stage = 0; | 788 | cmd->stage = 0; |
@@ -909,10 +905,13 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) | |||
909 | struct property *prop; | 905 | struct property *prop; |
910 | 906 | ||
911 | /* First query the partition info */ | 907 | /* First query the partition info */ |
908 | DPRINTK("SMU: Query partition infos ... (irq=%d)\n", smu->db_irq); | ||
912 | smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2, | 909 | smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2, |
913 | smu_done_complete, &comp, | 910 | smu_done_complete, &comp, |
914 | SMU_CMD_PARTITION_LATEST, id); | 911 | SMU_CMD_PARTITION_LATEST, id); |
915 | wait_for_completion(&comp); | 912 | wait_for_completion(&comp); |
913 | DPRINTK("SMU: done, status: %d, reply_len: %d\n", | ||
914 | cmd.cmd.status, cmd.cmd.reply_len); | ||
916 | 915 | ||
917 | /* Partition doesn't exist (or other error) */ | 916 | /* Partition doesn't exist (or other error) */ |
918 | if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6) | 917 | if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6) |
@@ -975,6 +974,8 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, | |||
975 | 974 | ||
976 | sprintf(pname, "sdb-partition-%02x", id); | 975 | sprintf(pname, "sdb-partition-%02x", id); |
977 | 976 | ||
977 | DPRINTK("smu_get_sdb_partition(%02x)\n", id); | ||
978 | |||
978 | if (interruptible) { | 979 | if (interruptible) { |
979 | int rc; | 980 | int rc; |
980 | rc = down_interruptible(&smu_part_access); | 981 | rc = down_interruptible(&smu_part_access); |
@@ -986,6 +987,7 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, | |||
986 | part = (struct smu_sdbp_header *)get_property(smu->of_node, | 987 | part = (struct smu_sdbp_header *)get_property(smu->of_node, |
987 | pname, size); | 988 | pname, size); |
988 | if (part == NULL) { | 989 | if (part == NULL) { |
990 | DPRINTK("trying to extract from SMU ...\n"); | ||
989 | part = smu_create_sdb_partition(id); | 991 | part = smu_create_sdb_partition(id); |
990 | if (part != NULL && size) | 992 | if (part != NULL && size) |
991 | *size = part->len << 2; | 993 | *size = part->len << 2; |
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index d843a6c9c6df..2d9d79150403 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c | |||
@@ -127,39 +127,34 @@ struct adb_driver via_cuda_driver = { | |||
127 | #endif /* CONFIG_ADB */ | 127 | #endif /* CONFIG_ADB */ |
128 | 128 | ||
129 | #ifdef CONFIG_PPC | 129 | #ifdef CONFIG_PPC |
130 | int __init | 130 | int __init find_via_cuda(void) |
131 | find_via_cuda(void) | ||
132 | { | 131 | { |
133 | int err; | ||
134 | struct adb_request req; | 132 | struct adb_request req; |
133 | phys_addr_t taddr; | ||
134 | u32 *reg; | ||
135 | int err; | ||
135 | 136 | ||
136 | if (vias != 0) | 137 | if (vias != 0) |
137 | return 1; | 138 | return 1; |
138 | vias = find_devices("via-cuda"); | 139 | vias = of_find_node_by_name(NULL, "via-cuda"); |
139 | if (vias == 0) | 140 | if (vias == 0) |
140 | return 0; | 141 | return 0; |
141 | if (vias->next != 0) | ||
142 | printk(KERN_WARNING "Warning: only using 1st via-cuda\n"); | ||
143 | |||
144 | #if 0 | ||
145 | { int i; | ||
146 | |||
147 | printk("find_via_cuda: node = %p, addrs =", vias->node); | ||
148 | for (i = 0; i < vias->n_addrs; ++i) | ||
149 | printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size); | ||
150 | printk(", intrs ="); | ||
151 | for (i = 0; i < vias->n_intrs; ++i) | ||
152 | printk(" %x", vias->intrs[i].line); | ||
153 | printk("\n"); } | ||
154 | #endif | ||
155 | 142 | ||
156 | if (vias->n_addrs != 1 || vias->n_intrs != 1) { | 143 | reg = (u32 *)get_property(vias, "reg", NULL); |
157 | printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n", | 144 | if (reg == NULL) { |
158 | vias->n_addrs, vias->n_intrs); | 145 | printk(KERN_ERR "via-cuda: No \"reg\" property !\n"); |
159 | if (vias->n_addrs < 1 || vias->n_intrs < 1) | 146 | goto fail; |
160 | return 0; | 147 | } |
148 | taddr = of_translate_address(vias, reg); | ||
149 | if (taddr == 0) { | ||
150 | printk(KERN_ERR "via-cuda: Can't translate address !\n"); | ||
151 | goto fail; | ||
152 | } | ||
153 | via = ioremap(taddr, 0x2000); | ||
154 | if (via == NULL) { | ||
155 | printk(KERN_ERR "via-cuda: Can't map address !\n"); | ||
156 | goto fail; | ||
161 | } | 157 | } |
162 | via = ioremap(vias->addrs->address, 0x2000); | ||
163 | 158 | ||
164 | cuda_state = idle; | 159 | cuda_state = idle; |
165 | sys_ctrler = SYS_CTRLER_CUDA; | 160 | sys_ctrler = SYS_CTRLER_CUDA; |
@@ -185,6 +180,11 @@ find_via_cuda(void) | |||
185 | cuda_poll(); | 180 | cuda_poll(); |
186 | 181 | ||
187 | return 1; | 182 | return 1; |
183 | |||
184 | fail: | ||
185 | of_node_put(vias); | ||
186 | vias = NULL; | ||
187 | return 0; | ||
188 | } | 188 | } |
189 | #endif /* CONFIG_PPC */ | 189 | #endif /* CONFIG_PPC */ |
190 | 190 | ||
@@ -193,10 +193,6 @@ static int __init via_cuda_start(void) | |||
193 | if (via == NULL) | 193 | if (via == NULL) |
194 | return -ENODEV; | 194 | return -ENODEV; |
195 | 195 | ||
196 | #ifdef CONFIG_PPC | ||
197 | request_OF_resource(vias, 0, NULL); | ||
198 | #endif | ||
199 | |||
200 | if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { | 196 | if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { |
201 | printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); | 197 | printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); |
202 | return -EAGAIN; | 198 | return -EAGAIN; |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 564043508569..6eb93e45fcd3 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -55,6 +55,8 @@ | |||
55 | #include <asm/sections.h> | 55 | #include <asm/sections.h> |
56 | #include <asm/irq.h> | 56 | #include <asm/irq.h> |
57 | #include <asm/pmac_feature.h> | 57 | #include <asm/pmac_feature.h> |
58 | #include <asm/pmac_pfunc.h> | ||
59 | #include <asm/pmac_low_i2c.h> | ||
58 | #include <asm/uaccess.h> | 60 | #include <asm/uaccess.h> |
59 | #include <asm/mmu_context.h> | 61 | #include <asm/mmu_context.h> |
60 | #include <asm/cputable.h> | 62 | #include <asm/cputable.h> |
@@ -147,6 +149,7 @@ static struct device_node *vias; | |||
147 | static int pmu_kind = PMU_UNKNOWN; | 149 | static int pmu_kind = PMU_UNKNOWN; |
148 | static int pmu_fully_inited = 0; | 150 | static int pmu_fully_inited = 0; |
149 | static int pmu_has_adb; | 151 | static int pmu_has_adb; |
152 | static struct device_node *gpio_node; | ||
150 | static unsigned char __iomem *gpio_reg = NULL; | 153 | static unsigned char __iomem *gpio_reg = NULL; |
151 | static int gpio_irq = -1; | 154 | static int gpio_irq = -1; |
152 | static int gpio_irq_enabled = -1; | 155 | static int gpio_irq_enabled = -1; |
@@ -157,8 +160,8 @@ static int pmu_version; | |||
157 | static int drop_interrupts; | 160 | static int drop_interrupts; |
158 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) | 161 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) |
159 | static int option_lid_wakeup = 1; | 162 | static int option_lid_wakeup = 1; |
160 | static int sleep_in_progress; | ||
161 | #endif /* CONFIG_PM && CONFIG_PPC32 */ | 163 | #endif /* CONFIG_PM && CONFIG_PPC32 */ |
164 | static int sleep_in_progress; | ||
162 | static unsigned long async_req_locks; | 165 | static unsigned long async_req_locks; |
163 | static unsigned int pmu_irq_stats[11]; | 166 | static unsigned int pmu_irq_stats[11]; |
164 | 167 | ||
@@ -196,7 +199,6 @@ static int pmu_adb_reset_bus(void); | |||
196 | #endif /* CONFIG_ADB */ | 199 | #endif /* CONFIG_ADB */ |
197 | 200 | ||
198 | static int init_pmu(void); | 201 | static int init_pmu(void); |
199 | static int pmu_queue_request(struct adb_request *req); | ||
200 | static void pmu_start(void); | 202 | static void pmu_start(void); |
201 | static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs); | 203 | static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs); |
202 | static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs); | 204 | static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs); |
@@ -295,22 +297,26 @@ static struct backlight_controller pmu_backlight_controller = { | |||
295 | }; | 297 | }; |
296 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 298 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
297 | 299 | ||
298 | int | 300 | int __init find_via_pmu(void) |
299 | find_via_pmu(void) | ||
300 | { | 301 | { |
302 | u64 taddr; | ||
303 | u32 *reg; | ||
304 | |||
301 | if (via != 0) | 305 | if (via != 0) |
302 | return 1; | 306 | return 1; |
303 | vias = find_devices("via-pmu"); | 307 | vias = of_find_node_by_name(NULL, "via-pmu"); |
304 | if (vias == 0) | 308 | if (vias == NULL) |
305 | return 0; | 309 | return 0; |
306 | if (vias->next != 0) | ||
307 | printk(KERN_WARNING "Warning: only using 1st via-pmu\n"); | ||
308 | 310 | ||
309 | if (vias->n_addrs < 1 || vias->n_intrs < 1) { | 311 | reg = (u32 *)get_property(vias, "reg", NULL); |
310 | printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n", | 312 | if (reg == NULL) { |
311 | vias->n_addrs, vias->n_intrs); | 313 | printk(KERN_ERR "via-pmu: No \"reg\" property !\n"); |
312 | if (vias->n_addrs < 1 || vias->n_intrs < 1) | 314 | goto fail; |
313 | return 0; | 315 | } |
316 | taddr = of_translate_address(vias, reg); | ||
317 | if (taddr == OF_BAD_ADDR) { | ||
318 | printk(KERN_ERR "via-pmu: Can't translate address !\n"); | ||
319 | goto fail; | ||
314 | } | 320 | } |
315 | 321 | ||
316 | spin_lock_init(&pmu_lock); | 322 | spin_lock_init(&pmu_lock); |
@@ -331,7 +337,8 @@ find_via_pmu(void) | |||
331 | pmu_kind = PMU_HEATHROW_BASED; | 337 | pmu_kind = PMU_HEATHROW_BASED; |
332 | else if (device_is_compatible(vias->parent, "Keylargo") | 338 | else if (device_is_compatible(vias->parent, "Keylargo") |
333 | || device_is_compatible(vias->parent, "K2-Keylargo")) { | 339 | || device_is_compatible(vias->parent, "K2-Keylargo")) { |
334 | struct device_node *gpio, *gpiop; | 340 | struct device_node *gpiop; |
341 | u64 gaddr = OF_BAD_ADDR; | ||
335 | 342 | ||
336 | pmu_kind = PMU_KEYLARGO_BASED; | 343 | pmu_kind = PMU_KEYLARGO_BASED; |
337 | pmu_has_adb = (find_type_devices("adb") != NULL); | 344 | pmu_has_adb = (find_type_devices("adb") != NULL); |
@@ -341,19 +348,24 @@ find_via_pmu(void) | |||
341 | PMU_INT_TICK | | 348 | PMU_INT_TICK | |
342 | PMU_INT_ENVIRONMENT; | 349 | PMU_INT_ENVIRONMENT; |
343 | 350 | ||
344 | gpiop = find_devices("gpio"); | 351 | gpiop = of_find_node_by_name(NULL, "gpio"); |
345 | if (gpiop && gpiop->n_addrs) { | 352 | if (gpiop) { |
346 | gpio_reg = ioremap(gpiop->addrs->address, 0x10); | 353 | reg = (u32 *)get_property(gpiop, "reg", NULL); |
347 | gpio = find_devices("extint-gpio1"); | 354 | if (reg) |
348 | if (gpio == NULL) | 355 | gaddr = of_translate_address(gpiop, reg); |
349 | gpio = find_devices("pmu-interrupt"); | 356 | if (gaddr != OF_BAD_ADDR) |
350 | if (gpio && gpio->parent == gpiop && gpio->n_intrs) | 357 | gpio_reg = ioremap(gaddr, 0x10); |
351 | gpio_irq = gpio->intrs[0].line; | ||
352 | } | 358 | } |
359 | if (gpio_reg == NULL) | ||
360 | printk(KERN_ERR "via-pmu: Can't find GPIO reg !\n"); | ||
353 | } else | 361 | } else |
354 | pmu_kind = PMU_UNKNOWN; | 362 | pmu_kind = PMU_UNKNOWN; |
355 | 363 | ||
356 | via = ioremap(vias->addrs->address, 0x2000); | 364 | via = ioremap(taddr, 0x2000); |
365 | if (via == NULL) { | ||
366 | printk(KERN_ERR "via-pmu: Can't map address !\n"); | ||
367 | goto fail; | ||
368 | } | ||
357 | 369 | ||
358 | out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ | 370 | out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ |
359 | out_8(&via[IFR], 0x7f); /* clear IFR */ | 371 | out_8(&via[IFR], 0x7f); /* clear IFR */ |
@@ -365,23 +377,25 @@ find_via_pmu(void) | |||
365 | return 0; | 377 | return 0; |
366 | } | 378 | } |
367 | 379 | ||
368 | printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n", | 380 | printk(KERN_INFO "PMU driver v%d initialized for %s, firmware: %02x\n", |
369 | PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version); | 381 | PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version); |
370 | 382 | ||
371 | sys_ctrler = SYS_CTRLER_PMU; | 383 | sys_ctrler = SYS_CTRLER_PMU; |
372 | 384 | ||
373 | return 1; | 385 | return 1; |
386 | fail: | ||
387 | of_node_put(vias); | ||
388 | vias = NULL; | ||
389 | return 0; | ||
374 | } | 390 | } |
375 | 391 | ||
376 | #ifdef CONFIG_ADB | 392 | #ifdef CONFIG_ADB |
377 | static int | 393 | static int pmu_probe(void) |
378 | pmu_probe(void) | ||
379 | { | 394 | { |
380 | return vias == NULL? -ENODEV: 0; | 395 | return vias == NULL? -ENODEV: 0; |
381 | } | 396 | } |
382 | 397 | ||
383 | static int __init | 398 | static int __init pmu_init(void) |
384 | pmu_init(void) | ||
385 | { | 399 | { |
386 | if (vias == NULL) | 400 | if (vias == NULL) |
387 | return -ENODEV; | 401 | return -ENODEV; |
@@ -405,7 +419,7 @@ static int __init via_pmu_start(void) | |||
405 | bright_req_2.complete = 1; | 419 | bright_req_2.complete = 1; |
406 | batt_req.complete = 1; | 420 | batt_req.complete = 1; |
407 | 421 | ||
408 | #if defined(CONFIG_PPC32) && !defined(CONFIG_PPC_MERGE) | 422 | #ifndef CONFIG_PPC_MERGE |
409 | if (pmu_kind == PMU_KEYLARGO_BASED) | 423 | if (pmu_kind == PMU_KEYLARGO_BASED) |
410 | openpic_set_irq_priority(vias->intrs[0].line, | 424 | openpic_set_irq_priority(vias->intrs[0].line, |
411 | OPENPIC_PRIORITY_DEFAULT + 1); | 425 | OPENPIC_PRIORITY_DEFAULT + 1); |
@@ -418,10 +432,22 @@ static int __init via_pmu_start(void) | |||
418 | return -EAGAIN; | 432 | return -EAGAIN; |
419 | } | 433 | } |
420 | 434 | ||
421 | if (pmu_kind == PMU_KEYLARGO_BASED && gpio_irq != -1) { | 435 | if (pmu_kind == PMU_KEYLARGO_BASED) { |
422 | if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0)) | 436 | gpio_node = of_find_node_by_name(NULL, "extint-gpio1"); |
423 | printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n", gpio_irq); | 437 | if (gpio_node == NULL) |
424 | gpio_irq_enabled = 1; | 438 | gpio_node = of_find_node_by_name(NULL, |
439 | "pmu-interrupt"); | ||
440 | if (gpio_node && gpio_node->n_intrs > 0) | ||
441 | gpio_irq = gpio_node->intrs[0].line; | ||
442 | |||
443 | if (gpio_irq != -1) { | ||
444 | if (request_irq(gpio_irq, gpio1_interrupt, 0, | ||
445 | "GPIO1 ADB", (void *)0)) | ||
446 | printk(KERN_ERR "pmu: can't get irq %d" | ||
447 | " (GPIO1)\n", gpio_irq); | ||
448 | else | ||
449 | gpio_irq_enabled = 1; | ||
450 | } | ||
425 | } | 451 | } |
426 | 452 | ||
427 | /* Enable interrupts */ | 453 | /* Enable interrupts */ |
@@ -454,9 +480,6 @@ static int __init via_pmu_dev_init(void) | |||
454 | if (vias == NULL) | 480 | if (vias == NULL) |
455 | return -ENODEV; | 481 | return -ENODEV; |
456 | 482 | ||
457 | #ifndef CONFIG_PPC64 | ||
458 | request_OF_resource(vias, 0, NULL); | ||
459 | #endif | ||
460 | #ifdef CONFIG_PMAC_BACKLIGHT | 483 | #ifdef CONFIG_PMAC_BACKLIGHT |
461 | /* Enable backlight */ | 484 | /* Enable backlight */ |
462 | register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); | 485 | register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); |
@@ -1371,7 +1394,6 @@ next: | |||
1371 | } | 1394 | } |
1372 | pmu_done(req); | 1395 | pmu_done(req); |
1373 | } else { | 1396 | } else { |
1374 | #if defined(CONFIG_XMON) && !defined(CONFIG_PPC64) | ||
1375 | if (len == 4 && data[1] == 0x2c) { | 1397 | if (len == 4 && data[1] == 0x2c) { |
1376 | extern int xmon_wants_key, xmon_adb_keycode; | 1398 | extern int xmon_wants_key, xmon_adb_keycode; |
1377 | if (xmon_wants_key) { | 1399 | if (xmon_wants_key) { |
@@ -1379,7 +1401,6 @@ next: | |||
1379 | return; | 1401 | return; |
1380 | } | 1402 | } |
1381 | } | 1403 | } |
1382 | #endif /* defined(CONFIG_XMON) && !defined(CONFIG_PPC64) */ | ||
1383 | #ifdef CONFIG_ADB | 1404 | #ifdef CONFIG_ADB |
1384 | /* | 1405 | /* |
1385 | * XXX On the [23]400 the PMU gives us an up | 1406 | * XXX On the [23]400 the PMU gives us an up |
@@ -1782,258 +1803,6 @@ pmu_present(void) | |||
1782 | return via != 0; | 1803 | return via != 0; |
1783 | } | 1804 | } |
1784 | 1805 | ||
1785 | struct pmu_i2c_hdr { | ||
1786 | u8 bus; | ||
1787 | u8 mode; | ||
1788 | u8 bus2; | ||
1789 | u8 address; | ||
1790 | u8 sub_addr; | ||
1791 | u8 comb_addr; | ||
1792 | u8 count; | ||
1793 | }; | ||
1794 | |||
1795 | int | ||
1796 | pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len) | ||
1797 | { | ||
1798 | struct adb_request req; | ||
1799 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1800 | int retry; | ||
1801 | int rc; | ||
1802 | |||
1803 | for (retry=0; retry<16; retry++) { | ||
1804 | memset(&req, 0, sizeof(req)); | ||
1805 | |||
1806 | hdr->bus = bus; | ||
1807 | hdr->address = addr & 0xfe; | ||
1808 | hdr->mode = PMU_I2C_MODE_COMBINED; | ||
1809 | hdr->bus2 = 0; | ||
1810 | hdr->sub_addr = subaddr; | ||
1811 | hdr->comb_addr = addr | 1; | ||
1812 | hdr->count = len; | ||
1813 | |||
1814 | req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; | ||
1815 | req.reply_expected = 0; | ||
1816 | req.reply_len = 0; | ||
1817 | req.data[0] = PMU_I2C_CMD; | ||
1818 | req.reply[0] = 0xff; | ||
1819 | rc = pmu_queue_request(&req); | ||
1820 | if (rc) | ||
1821 | return rc; | ||
1822 | while(!req.complete) | ||
1823 | pmu_poll(); | ||
1824 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1825 | break; | ||
1826 | mdelay(15); | ||
1827 | } | ||
1828 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1829 | return -1; | ||
1830 | |||
1831 | for (retry=0; retry<16; retry++) { | ||
1832 | memset(&req, 0, sizeof(req)); | ||
1833 | |||
1834 | mdelay(15); | ||
1835 | |||
1836 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1837 | req.reply[0] = 0xff; | ||
1838 | |||
1839 | req.nbytes = 2; | ||
1840 | req.reply_expected = 0; | ||
1841 | req.reply_len = 0; | ||
1842 | req.data[0] = PMU_I2C_CMD; | ||
1843 | rc = pmu_queue_request(&req); | ||
1844 | if (rc) | ||
1845 | return rc; | ||
1846 | while(!req.complete) | ||
1847 | pmu_poll(); | ||
1848 | if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { | ||
1849 | memcpy(data, &req.reply[1], req.reply_len - 1); | ||
1850 | return req.reply_len - 1; | ||
1851 | } | ||
1852 | } | ||
1853 | return -1; | ||
1854 | } | ||
1855 | |||
1856 | int | ||
1857 | pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len) | ||
1858 | { | ||
1859 | struct adb_request req; | ||
1860 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1861 | int retry; | ||
1862 | int rc; | ||
1863 | |||
1864 | for (retry=0; retry<16; retry++) { | ||
1865 | memset(&req, 0, sizeof(req)); | ||
1866 | |||
1867 | hdr->bus = bus; | ||
1868 | hdr->address = addr & 0xfe; | ||
1869 | hdr->mode = PMU_I2C_MODE_STDSUB; | ||
1870 | hdr->bus2 = 0; | ||
1871 | hdr->sub_addr = subaddr; | ||
1872 | hdr->comb_addr = addr & 0xfe; | ||
1873 | hdr->count = len; | ||
1874 | |||
1875 | req.data[0] = PMU_I2C_CMD; | ||
1876 | memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); | ||
1877 | req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; | ||
1878 | req.reply_expected = 0; | ||
1879 | req.reply_len = 0; | ||
1880 | req.reply[0] = 0xff; | ||
1881 | rc = pmu_queue_request(&req); | ||
1882 | if (rc) | ||
1883 | return rc; | ||
1884 | while(!req.complete) | ||
1885 | pmu_poll(); | ||
1886 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1887 | break; | ||
1888 | mdelay(15); | ||
1889 | } | ||
1890 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1891 | return -1; | ||
1892 | |||
1893 | for (retry=0; retry<16; retry++) { | ||
1894 | memset(&req, 0, sizeof(req)); | ||
1895 | |||
1896 | mdelay(15); | ||
1897 | |||
1898 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1899 | req.reply[0] = 0xff; | ||
1900 | |||
1901 | req.nbytes = 2; | ||
1902 | req.reply_expected = 0; | ||
1903 | req.reply_len = 0; | ||
1904 | req.data[0] = PMU_I2C_CMD; | ||
1905 | rc = pmu_queue_request(&req); | ||
1906 | if (rc) | ||
1907 | return rc; | ||
1908 | while(!req.complete) | ||
1909 | pmu_poll(); | ||
1910 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1911 | return len; | ||
1912 | } | ||
1913 | return -1; | ||
1914 | } | ||
1915 | |||
1916 | int | ||
1917 | pmu_i2c_simple_read(int bus, int addr, u8* data, int len) | ||
1918 | { | ||
1919 | struct adb_request req; | ||
1920 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1921 | int retry; | ||
1922 | int rc; | ||
1923 | |||
1924 | for (retry=0; retry<16; retry++) { | ||
1925 | memset(&req, 0, sizeof(req)); | ||
1926 | |||
1927 | hdr->bus = bus; | ||
1928 | hdr->address = addr | 1; | ||
1929 | hdr->mode = PMU_I2C_MODE_SIMPLE; | ||
1930 | hdr->bus2 = 0; | ||
1931 | hdr->sub_addr = 0; | ||
1932 | hdr->comb_addr = 0; | ||
1933 | hdr->count = len; | ||
1934 | |||
1935 | req.data[0] = PMU_I2C_CMD; | ||
1936 | req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; | ||
1937 | req.reply_expected = 0; | ||
1938 | req.reply_len = 0; | ||
1939 | req.reply[0] = 0xff; | ||
1940 | rc = pmu_queue_request(&req); | ||
1941 | if (rc) | ||
1942 | return rc; | ||
1943 | while(!req.complete) | ||
1944 | pmu_poll(); | ||
1945 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1946 | break; | ||
1947 | mdelay(15); | ||
1948 | } | ||
1949 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1950 | return -1; | ||
1951 | |||
1952 | for (retry=0; retry<16; retry++) { | ||
1953 | memset(&req, 0, sizeof(req)); | ||
1954 | |||
1955 | mdelay(15); | ||
1956 | |||
1957 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1958 | req.reply[0] = 0xff; | ||
1959 | |||
1960 | req.nbytes = 2; | ||
1961 | req.reply_expected = 0; | ||
1962 | req.reply_len = 0; | ||
1963 | req.data[0] = PMU_I2C_CMD; | ||
1964 | rc = pmu_queue_request(&req); | ||
1965 | if (rc) | ||
1966 | return rc; | ||
1967 | while(!req.complete) | ||
1968 | pmu_poll(); | ||
1969 | if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { | ||
1970 | memcpy(data, &req.reply[1], req.reply_len - 1); | ||
1971 | return req.reply_len - 1; | ||
1972 | } | ||
1973 | } | ||
1974 | return -1; | ||
1975 | } | ||
1976 | |||
1977 | int | ||
1978 | pmu_i2c_simple_write(int bus, int addr, u8* data, int len) | ||
1979 | { | ||
1980 | struct adb_request req; | ||
1981 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1982 | int retry; | ||
1983 | int rc; | ||
1984 | |||
1985 | for (retry=0; retry<16; retry++) { | ||
1986 | memset(&req, 0, sizeof(req)); | ||
1987 | |||
1988 | hdr->bus = bus; | ||
1989 | hdr->address = addr & 0xfe; | ||
1990 | hdr->mode = PMU_I2C_MODE_SIMPLE; | ||
1991 | hdr->bus2 = 0; | ||
1992 | hdr->sub_addr = 0; | ||
1993 | hdr->comb_addr = 0; | ||
1994 | hdr->count = len; | ||
1995 | |||
1996 | req.data[0] = PMU_I2C_CMD; | ||
1997 | memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); | ||
1998 | req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; | ||
1999 | req.reply_expected = 0; | ||
2000 | req.reply_len = 0; | ||
2001 | req.reply[0] = 0xff; | ||
2002 | rc = pmu_queue_request(&req); | ||
2003 | if (rc) | ||
2004 | return rc; | ||
2005 | while(!req.complete) | ||
2006 | pmu_poll(); | ||
2007 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
2008 | break; | ||
2009 | mdelay(15); | ||
2010 | } | ||
2011 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
2012 | return -1; | ||
2013 | |||
2014 | for (retry=0; retry<16; retry++) { | ||
2015 | memset(&req, 0, sizeof(req)); | ||
2016 | |||
2017 | mdelay(15); | ||
2018 | |||
2019 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
2020 | req.reply[0] = 0xff; | ||
2021 | |||
2022 | req.nbytes = 2; | ||
2023 | req.reply_expected = 0; | ||
2024 | req.reply_len = 0; | ||
2025 | req.data[0] = PMU_I2C_CMD; | ||
2026 | rc = pmu_queue_request(&req); | ||
2027 | if (rc) | ||
2028 | return rc; | ||
2029 | while(!req.complete) | ||
2030 | pmu_poll(); | ||
2031 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
2032 | return len; | ||
2033 | } | ||
2034 | return -1; | ||
2035 | } | ||
2036 | |||
2037 | #ifdef CONFIG_PM | 1806 | #ifdef CONFIG_PM |
2038 | 1807 | ||
2039 | static LIST_HEAD(sleep_notifiers); | 1808 | static LIST_HEAD(sleep_notifiers); |
@@ -2338,8 +2107,9 @@ pmac_suspend_devices(void) | |||
2338 | return -EBUSY; | 2107 | return -EBUSY; |
2339 | } | 2108 | } |
2340 | 2109 | ||
2341 | /* Disable clock spreading on some machines */ | 2110 | /* Call platform functions marked "on sleep" */ |
2342 | pmac_tweak_clock_spreading(0); | 2111 | pmac_pfunc_i2c_suspend(); |
2112 | pmac_pfunc_base_suspend(); | ||
2343 | 2113 | ||
2344 | /* Stop preemption */ | 2114 | /* Stop preemption */ |
2345 | preempt_disable(); | 2115 | preempt_disable(); |
@@ -2411,8 +2181,9 @@ pmac_wakeup_devices(void) | |||
2411 | mdelay(10); | 2181 | mdelay(10); |
2412 | preempt_enable(); | 2182 | preempt_enable(); |
2413 | 2183 | ||
2414 | /* Re-enable clock spreading on some machines */ | 2184 | /* Call platform functions marked "on wake" */ |
2415 | pmac_tweak_clock_spreading(1); | 2185 | pmac_pfunc_base_resume(); |
2186 | pmac_pfunc_i2c_resume(); | ||
2416 | 2187 | ||
2417 | /* Resume devices */ | 2188 | /* Resume devices */ |
2418 | device_resume(); | 2189 | device_resume(); |
@@ -3130,16 +2901,13 @@ static int __init init_pmu_sysfs(void) | |||
3130 | subsys_initcall(init_pmu_sysfs); | 2901 | subsys_initcall(init_pmu_sysfs); |
3131 | 2902 | ||
3132 | EXPORT_SYMBOL(pmu_request); | 2903 | EXPORT_SYMBOL(pmu_request); |
2904 | EXPORT_SYMBOL(pmu_queue_request); | ||
3133 | EXPORT_SYMBOL(pmu_poll); | 2905 | EXPORT_SYMBOL(pmu_poll); |
3134 | EXPORT_SYMBOL(pmu_poll_adb); | 2906 | EXPORT_SYMBOL(pmu_poll_adb); |
3135 | EXPORT_SYMBOL(pmu_wait_complete); | 2907 | EXPORT_SYMBOL(pmu_wait_complete); |
3136 | EXPORT_SYMBOL(pmu_suspend); | 2908 | EXPORT_SYMBOL(pmu_suspend); |
3137 | EXPORT_SYMBOL(pmu_resume); | 2909 | EXPORT_SYMBOL(pmu_resume); |
3138 | EXPORT_SYMBOL(pmu_unlock); | 2910 | EXPORT_SYMBOL(pmu_unlock); |
3139 | EXPORT_SYMBOL(pmu_i2c_combined_read); | ||
3140 | EXPORT_SYMBOL(pmu_i2c_stdsub_write); | ||
3141 | EXPORT_SYMBOL(pmu_i2c_simple_read); | ||
3142 | EXPORT_SYMBOL(pmu_i2c_simple_write); | ||
3143 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) | 2911 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) |
3144 | EXPORT_SYMBOL(pmu_enable_irled); | 2912 | EXPORT_SYMBOL(pmu_enable_irled); |
3145 | EXPORT_SYMBOL(pmu_battery_count); | 2913 | EXPORT_SYMBOL(pmu_battery_count); |
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 57460e46c89f..906d3ecae6e6 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/io.h> | 21 | #include <asm/io.h> |
22 | #include <asm/system.h> | 22 | #include <asm/system.h> |
23 | #include <asm/sections.h> | 23 | #include <asm/sections.h> |
24 | #include <asm/pmac_low_i2c.h> | ||
24 | 25 | ||
25 | #include "windfarm.h" | 26 | #include "windfarm.h" |
26 | 27 | ||
@@ -157,53 +158,21 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, | |||
157 | 158 | ||
158 | static int wf_lm75_attach(struct i2c_adapter *adapter) | 159 | static int wf_lm75_attach(struct i2c_adapter *adapter) |
159 | { | 160 | { |
160 | u8 bus_id; | 161 | struct device_node *busnode, *dev; |
161 | struct device_node *smu, *bus, *dev; | 162 | struct pmac_i2c_bus *bus; |
162 | |||
163 | /* We currently only deal with LM75's hanging off the SMU | ||
164 | * i2c busses. If we extend that driver to other/older | ||
165 | * machines, we should split this function into SMU-i2c, | ||
166 | * keywest-i2c, PMU-i2c, ... | ||
167 | */ | ||
168 | 163 | ||
169 | DBG("wf_lm75: adapter %s detected\n", adapter->name); | 164 | DBG("wf_lm75: adapter %s detected\n", adapter->name); |
170 | 165 | ||
171 | if (strncmp(adapter->name, "smu-i2c-", 8) != 0) | 166 | bus = pmac_i2c_adapter_to_bus(adapter); |
172 | return 0; | 167 | if (bus == NULL) |
173 | smu = of_find_node_by_type(NULL, "smu"); | 168 | return -ENODEV; |
174 | if (smu == NULL) | 169 | busnode = pmac_i2c_get_bus_node(bus); |
175 | return 0; | ||
176 | |||
177 | /* Look for the bus in the device-tree */ | ||
178 | bus_id = (u8)simple_strtoul(adapter->name + 8, NULL, 16); | ||
179 | |||
180 | DBG("wf_lm75: bus ID is %x\n", bus_id); | ||
181 | |||
182 | /* Look for sensors subdir */ | ||
183 | for (bus = NULL; | ||
184 | (bus = of_get_next_child(smu, bus)) != NULL;) { | ||
185 | u32 *reg; | ||
186 | |||
187 | if (strcmp(bus->name, "i2c")) | ||
188 | continue; | ||
189 | reg = (u32 *)get_property(bus, "reg", NULL); | ||
190 | if (reg == NULL) | ||
191 | continue; | ||
192 | if (bus_id == *reg) | ||
193 | break; | ||
194 | } | ||
195 | of_node_put(smu); | ||
196 | if (bus == NULL) { | ||
197 | printk(KERN_WARNING "windfarm: SMU i2c bus 0x%x not found" | ||
198 | " in device-tree !\n", bus_id); | ||
199 | return 0; | ||
200 | } | ||
201 | 170 | ||
202 | DBG("wf_lm75: bus found, looking for device...\n"); | 171 | DBG("wf_lm75: bus found, looking for device...\n"); |
203 | 172 | ||
204 | /* Now look for lm75(s) in there */ | 173 | /* Now look for lm75(s) in there */ |
205 | for (dev = NULL; | 174 | for (dev = NULL; |
206 | (dev = of_get_next_child(bus, dev)) != NULL;) { | 175 | (dev = of_get_next_child(busnode, dev)) != NULL;) { |
207 | const char *loc = | 176 | const char *loc = |
208 | get_property(dev, "hwsensor-location", NULL); | 177 | get_property(dev, "hwsensor-location", NULL); |
209 | u32 *reg = (u32 *)get_property(dev, "reg", NULL); | 178 | u32 *reg = (u32 *)get_property(dev, "reg", NULL); |
@@ -217,9 +186,6 @@ static int wf_lm75_attach(struct i2c_adapter *adapter) | |||
217 | else if (device_is_compatible(dev, "ds1775")) | 186 | else if (device_is_compatible(dev, "ds1775")) |
218 | wf_lm75_create(adapter, *reg, 1, loc); | 187 | wf_lm75_create(adapter, *reg, 1, loc); |
219 | } | 188 | } |
220 | |||
221 | of_node_put(bus); | ||
222 | |||
223 | return 0; | 189 | return 0; |
224 | } | 190 | } |
225 | 191 | ||
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 932dcf0366eb..311a4122bd70 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c | |||
@@ -432,11 +432,12 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat | |||
432 | struct Scsi_Host *host; | 432 | struct Scsi_Host *host; |
433 | void *dma_cmd_space; | 433 | void *dma_cmd_space; |
434 | unsigned char *clkprop; | 434 | unsigned char *clkprop; |
435 | int proplen; | 435 | int proplen, rc = -ENODEV; |
436 | 436 | ||
437 | if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) { | 437 | if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) { |
438 | printk(KERN_ERR "mac53c94: expected 2 addrs and intrs (got %d/%d)\n", | 438 | printk(KERN_ERR "mac53c94: expected 2 addrs and intrs" |
439 | node->n_addrs, node->n_intrs); | 439 | " (got %d/%d)\n", |
440 | macio_resource_count(mdev), macio_irq_count(mdev)); | ||
440 | return -ENODEV; | 441 | return -ENODEV; |
441 | } | 442 | } |
442 | 443 | ||
@@ -448,6 +449,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat | |||
448 | host = scsi_host_alloc(&mac53c94_template, sizeof(struct fsc_state)); | 449 | host = scsi_host_alloc(&mac53c94_template, sizeof(struct fsc_state)); |
449 | if (host == NULL) { | 450 | if (host == NULL) { |
450 | printk(KERN_ERR "mac53c94: couldn't register host"); | 451 | printk(KERN_ERR "mac53c94: couldn't register host"); |
452 | rc = -ENOMEM; | ||
451 | goto out_release; | 453 | goto out_release; |
452 | } | 454 | } |
453 | 455 | ||
@@ -486,6 +488,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat | |||
486 | if (dma_cmd_space == 0) { | 488 | if (dma_cmd_space == 0) { |
487 | printk(KERN_ERR "mac53c94: couldn't allocate dma " | 489 | printk(KERN_ERR "mac53c94: couldn't allocate dma " |
488 | "command space for %s\n", node->full_name); | 490 | "command space for %s\n", node->full_name); |
491 | rc = -ENOMEM; | ||
489 | goto out_free; | 492 | goto out_free; |
490 | } | 493 | } |
491 | state->dma_cmds = (struct dbdma_cmd *)DBDMA_ALIGN(dma_cmd_space); | 494 | state->dma_cmds = (struct dbdma_cmd *)DBDMA_ALIGN(dma_cmd_space); |
@@ -495,18 +498,21 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat | |||
495 | 498 | ||
496 | mac53c94_init(state); | 499 | mac53c94_init(state); |
497 | 500 | ||
498 | if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94", state)) { | 501 | if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94",state)) { |
499 | printk(KERN_ERR "mac53C94: can't get irq %d for %s\n", | 502 | printk(KERN_ERR "mac53C94: can't get irq %d for %s\n", |
500 | state->intr, node->full_name); | 503 | state->intr, node->full_name); |
501 | goto out_free_dma; | 504 | goto out_free_dma; |
502 | } | 505 | } |
503 | 506 | ||
504 | /* XXX FIXME: handle failure */ | 507 | rc = scsi_add_host(host, &mdev->ofdev.dev); |
505 | scsi_add_host(host, &mdev->ofdev.dev); | 508 | if (rc != 0) |
506 | scsi_scan_host(host); | 509 | goto out_release_irq; |
507 | 510 | ||
511 | scsi_scan_host(host); | ||
508 | return 0; | 512 | return 0; |
509 | 513 | ||
514 | out_release_irq: | ||
515 | free_irq(state->intr, state); | ||
510 | out_free_dma: | 516 | out_free_dma: |
511 | kfree(state->dma_cmd_space); | 517 | kfree(state->dma_cmd_space); |
512 | out_free: | 518 | out_free: |
@@ -518,7 +524,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat | |||
518 | out_release: | 524 | out_release: |
519 | macio_release_resources(mdev); | 525 | macio_release_resources(mdev); |
520 | 526 | ||
521 | return -ENODEV; | 527 | return rc; |
522 | } | 528 | } |
523 | 529 | ||
524 | static int mac53c94_remove(struct macio_dev *mdev) | 530 | static int mac53c94_remove(struct macio_dev *mdev) |
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index bdccf73cf9fe..d6d2125f9044 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c | |||
@@ -1869,7 +1869,8 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match) | |||
1869 | 1869 | ||
1870 | if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) { | 1870 | if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) { |
1871 | printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs" | 1871 | printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs" |
1872 | " (got %d,%d)\n", mesh->n_addrs, mesh->n_intrs); | 1872 | " (got %d,%d)\n", macio_resource_count(mdev), |
1873 | macio_irq_count(mdev)); | ||
1873 | return -ENODEV; | 1874 | return -ENODEV; |
1874 | } | 1875 | } |
1875 | 1876 | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 987d22b53c22..16af5626c243 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -608,7 +608,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
608 | 608 | ||
609 | p = cpm2cpu_addr(bdp->cbd_bufaddr); | 609 | p = cpm2cpu_addr(bdp->cbd_bufaddr); |
610 | 610 | ||
611 | *p++ = xmit->buf[xmit->tail]; | 611 | *p++ = port->x_char; |
612 | bdp->cbd_datlen = 1; | 612 | bdp->cbd_datlen = 1; |
613 | bdp->cbd_sc |= BD_SC_READY; | 613 | bdp->cbd_sc |= BD_SC_READY; |
614 | /* Get next BD. */ | 614 | /* Get next BD. */ |
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 5ddd8ab1f108..ea24129eb6b9 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c | |||
@@ -1431,11 +1431,14 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) | |||
1431 | char name[1]; | 1431 | char name[1]; |
1432 | } *slots; | 1432 | } *slots; |
1433 | int len; | 1433 | int len; |
1434 | struct resource r_ports, r_rxdma, r_txdma; | ||
1434 | 1435 | ||
1435 | /* | 1436 | /* |
1436 | * Request & map chip registers | 1437 | * Request & map chip registers |
1437 | */ | 1438 | */ |
1438 | uap->port.mapbase = np->addrs[0].address; | 1439 | if (of_address_to_resource(np, 0, &r_ports)) |
1440 | return -ENODEV; | ||
1441 | uap->port.mapbase = r_ports.start; | ||
1439 | uap->port.membase = ioremap(uap->port.mapbase, 0x1000); | 1442 | uap->port.membase = ioremap(uap->port.mapbase, 0x1000); |
1440 | 1443 | ||
1441 | uap->control_reg = uap->port.membase; | 1444 | uap->control_reg = uap->port.membase; |
@@ -1445,16 +1448,20 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) | |||
1445 | * Request & map DBDMA registers | 1448 | * Request & map DBDMA registers |
1446 | */ | 1449 | */ |
1447 | #ifdef HAS_DBDMA | 1450 | #ifdef HAS_DBDMA |
1448 | if (np->n_addrs >= 3 && np->n_intrs >= 3) | 1451 | if (of_address_to_resource(np, 1, &r_txdma) == 0 && |
1452 | of_address_to_resource(np, 2, &r_rxdma) == 0) | ||
1449 | uap->flags |= PMACZILOG_FLAG_HAS_DMA; | 1453 | uap->flags |= PMACZILOG_FLAG_HAS_DMA; |
1454 | #else | ||
1455 | memset(&r_txdma, 0, sizeof(struct resource)); | ||
1456 | memset(&r_rxdma, 0, sizeof(struct resource)); | ||
1450 | #endif | 1457 | #endif |
1451 | if (ZS_HAS_DMA(uap)) { | 1458 | if (ZS_HAS_DMA(uap)) { |
1452 | uap->tx_dma_regs = ioremap(np->addrs[np->n_addrs - 2].address, 0x1000); | 1459 | uap->tx_dma_regs = ioremap(r_txdma.start, 0x100); |
1453 | if (uap->tx_dma_regs == NULL) { | 1460 | if (uap->tx_dma_regs == NULL) { |
1454 | uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; | 1461 | uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; |
1455 | goto no_dma; | 1462 | goto no_dma; |
1456 | } | 1463 | } |
1457 | uap->rx_dma_regs = ioremap(np->addrs[np->n_addrs - 1].address, 0x1000); | 1464 | uap->rx_dma_regs = ioremap(r_rxdma.start, 0x100); |
1458 | if (uap->rx_dma_regs == NULL) { | 1465 | if (uap->rx_dma_regs == NULL) { |
1459 | iounmap(uap->tx_dma_regs); | 1466 | iounmap(uap->tx_dma_regs); |
1460 | uap->tx_dma_regs = NULL; | 1467 | uap->tx_dma_regs = NULL; |
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 403d17377f8d..03798e9c882d 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c | |||
@@ -133,12 +133,6 @@ static int controlfb_mmap(struct fb_info *info, struct file *file, | |||
133 | static int controlfb_set_par (struct fb_info *info); | 133 | static int controlfb_set_par (struct fb_info *info); |
134 | static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); | 134 | static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); |
135 | 135 | ||
136 | /* | ||
137 | * inititialization | ||
138 | */ | ||
139 | int control_init(void); | ||
140 | void control_setup(char *); | ||
141 | |||
142 | /******************** Prototypes for internal functions **********************/ | 136 | /******************** Prototypes for internal functions **********************/ |
143 | 137 | ||
144 | static void set_control_clock(unsigned char *params); | 138 | static void set_control_clock(unsigned char *params); |
@@ -550,9 +544,46 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro | |||
550 | 544 | ||
551 | 545 | ||
552 | /* | 546 | /* |
553 | * Called from fbmem.c for probing & initializing | 547 | * Parse user speficied options (`video=controlfb:') |
554 | */ | 548 | */ |
555 | int __init control_init(void) | 549 | static void __init control_setup(char *options) |
550 | { | ||
551 | char *this_opt; | ||
552 | |||
553 | if (!options || !*options) | ||
554 | return; | ||
555 | |||
556 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
557 | if (!strncmp(this_opt, "vmode:", 6)) { | ||
558 | int vmode = simple_strtoul(this_opt+6, NULL, 0); | ||
559 | if (vmode > 0 && vmode <= VMODE_MAX && | ||
560 | control_mac_modes[vmode - 1].m[1] >= 0) | ||
561 | default_vmode = vmode; | ||
562 | } else if (!strncmp(this_opt, "cmode:", 6)) { | ||
563 | int depth = simple_strtoul(this_opt+6, NULL, 0); | ||
564 | switch (depth) { | ||
565 | case CMODE_8: | ||
566 | case CMODE_16: | ||
567 | case CMODE_32: | ||
568 | default_cmode = depth; | ||
569 | break; | ||
570 | case 8: | ||
571 | default_cmode = CMODE_8; | ||
572 | break; | ||
573 | case 15: | ||
574 | case 16: | ||
575 | default_cmode = CMODE_16; | ||
576 | break; | ||
577 | case 24: | ||
578 | case 32: | ||
579 | default_cmode = CMODE_32; | ||
580 | break; | ||
581 | } | ||
582 | } | ||
583 | } | ||
584 | } | ||
585 | |||
586 | static int __init control_init(void) | ||
556 | { | 587 | { |
557 | struct device_node *dp; | 588 | struct device_node *dp; |
558 | char *option = NULL; | 589 | char *option = NULL; |
@@ -651,15 +682,16 @@ static void __init find_vram_size(struct fb_info_control *p) | |||
651 | static int __init control_of_init(struct device_node *dp) | 682 | static int __init control_of_init(struct device_node *dp) |
652 | { | 683 | { |
653 | struct fb_info_control *p; | 684 | struct fb_info_control *p; |
654 | unsigned long addr; | 685 | struct resource fb_res, reg_res; |
655 | int i; | ||
656 | 686 | ||
657 | if (control_fb) { | 687 | if (control_fb) { |
658 | printk(KERN_ERR "controlfb: only one control is supported\n"); | 688 | printk(KERN_ERR "controlfb: only one control is supported\n"); |
659 | return -ENXIO; | 689 | return -ENXIO; |
660 | } | 690 | } |
661 | if(dp->n_addrs != 2) { | 691 | |
662 | printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs); | 692 | if (of_pci_address_to_resource(dp, 2, &fb_res) || |
693 | of_pci_address_to_resource(dp, 1, ®_res)) { | ||
694 | printk(KERN_ERR "can't get 2 addresses for control\n"); | ||
663 | return -ENXIO; | 695 | return -ENXIO; |
664 | } | 696 | } |
665 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 697 | p = kmalloc(sizeof(*p), GFP_KERNEL); |
@@ -669,18 +701,12 @@ static int __init control_of_init(struct device_node *dp) | |||
669 | memset(p, 0, sizeof(*p)); | 701 | memset(p, 0, sizeof(*p)); |
670 | 702 | ||
671 | /* Map in frame buffer and registers */ | 703 | /* Map in frame buffer and registers */ |
672 | for (i = 0; i < dp->n_addrs; ++i) { | 704 | p->fb_orig_base = fb_res.start; |
673 | addr = dp->addrs[i].address; | 705 | p->fb_orig_size = fb_res.end - fb_res.start + 1; |
674 | if (dp->addrs[i].size >= 0x800000) { | 706 | /* use the big-endian aperture (??) */ |
675 | p->fb_orig_base = addr; | 707 | p->frame_buffer_phys = fb_res.start + 0x800000; |
676 | p->fb_orig_size = dp->addrs[i].size; | 708 | p->control_regs_phys = reg_res.start; |
677 | /* use the big-endian aperture (??) */ | 709 | p->control_regs_size = reg_res.end - reg_res.start + 1; |
678 | p->frame_buffer_phys = addr + 0x800000; | ||
679 | } else { | ||
680 | p->control_regs_phys = addr; | ||
681 | p->control_regs_size = dp->addrs[i].size; | ||
682 | } | ||
683 | } | ||
684 | 710 | ||
685 | if (!p->fb_orig_base || | 711 | if (!p->fb_orig_base || |
686 | !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) { | 712 | !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) { |
@@ -1059,43 +1085,3 @@ static void control_cleanup(void) | |||
1059 | } | 1085 | } |
1060 | 1086 | ||
1061 | 1087 | ||
1062 | /* | ||
1063 | * Parse user speficied options (`video=controlfb:') | ||
1064 | */ | ||
1065 | void __init control_setup(char *options) | ||
1066 | { | ||
1067 | char *this_opt; | ||
1068 | |||
1069 | if (!options || !*options) | ||
1070 | return; | ||
1071 | |||
1072 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
1073 | if (!strncmp(this_opt, "vmode:", 6)) { | ||
1074 | int vmode = simple_strtoul(this_opt+6, NULL, 0); | ||
1075 | if (vmode > 0 && vmode <= VMODE_MAX && | ||
1076 | control_mac_modes[vmode - 1].m[1] >= 0) | ||
1077 | default_vmode = vmode; | ||
1078 | } else if (!strncmp(this_opt, "cmode:", 6)) { | ||
1079 | int depth = simple_strtoul(this_opt+6, NULL, 0); | ||
1080 | switch (depth) { | ||
1081 | case CMODE_8: | ||
1082 | case CMODE_16: | ||
1083 | case CMODE_32: | ||
1084 | default_cmode = depth; | ||
1085 | break; | ||
1086 | case 8: | ||
1087 | default_cmode = CMODE_8; | ||
1088 | break; | ||
1089 | case 15: | ||
1090 | case 16: | ||
1091 | default_cmode = CMODE_16; | ||
1092 | break; | ||
1093 | case 24: | ||
1094 | case 32: | ||
1095 | default_cmode = CMODE_32; | ||
1096 | break; | ||
1097 | } | ||
1098 | } | ||
1099 | } | ||
1100 | } | ||
1101 | |||
diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 00d87f5bb7be..ad1434e3f227 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c | |||
@@ -223,6 +223,7 @@ static int offb_blank(int blank, struct fb_info *info) | |||
223 | int __init offb_init(void) | 223 | int __init offb_init(void) |
224 | { | 224 | { |
225 | struct device_node *dp = NULL, *boot_disp = NULL; | 225 | struct device_node *dp = NULL, *boot_disp = NULL; |
226 | |||
226 | #if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) | 227 | #if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) |
227 | struct device_node *macos_display = NULL; | 228 | struct device_node *macos_display = NULL; |
228 | #endif | 229 | #endif |
@@ -234,60 +235,54 @@ int __init offb_init(void) | |||
234 | if (boot_infos != 0) { | 235 | if (boot_infos != 0) { |
235 | unsigned long addr = | 236 | unsigned long addr = |
236 | (unsigned long) boot_infos->dispDeviceBase; | 237 | (unsigned long) boot_infos->dispDeviceBase; |
238 | u32 *addrp; | ||
239 | u64 daddr, dsize; | ||
240 | unsigned int flags; | ||
241 | |||
237 | /* find the device node corresponding to the macos display */ | 242 | /* find the device node corresponding to the macos display */ |
238 | while ((dp = of_find_node_by_type(dp, "display"))) { | 243 | while ((dp = of_find_node_by_type(dp, "display"))) { |
239 | int i; | 244 | int i; |
240 | /* | ||
241 | * Grrr... It looks like the MacOS ATI driver | ||
242 | * munges the assigned-addresses property (but | ||
243 | * the AAPL,address value is OK). | ||
244 | */ | ||
245 | if (strncmp(dp->name, "ATY,", 4) == 0 | ||
246 | && dp->n_addrs == 1) { | ||
247 | unsigned int *ap = | ||
248 | (unsigned int *) get_property(dp, | ||
249 | "AAPL,address", | ||
250 | NULL); | ||
251 | if (ap != NULL) { | ||
252 | dp->addrs[0].address = *ap; | ||
253 | dp->addrs[0].size = 0x01000000; | ||
254 | } | ||
255 | } | ||
256 | 245 | ||
257 | /* | 246 | /* |
258 | * The LTPro on the Lombard powerbook has no addresses | 247 | * Look for an AAPL,address property first. |
259 | * on the display nodes, they are on their parent. | ||
260 | */ | 248 | */ |
261 | if (dp->n_addrs == 0 | 249 | unsigned int na; |
262 | && device_is_compatible(dp, "ATY,264LTPro")) { | 250 | unsigned int *ap = |
263 | int na; | 251 | (unsigned int *)get_property(dp, "AAPL,address", |
264 | unsigned int *ap = (unsigned int *) | 252 | &na); |
265 | get_property(dp, "AAPL,address", &na); | 253 | if (ap != 0) { |
266 | if (ap != 0) | 254 | for (na /= sizeof(unsigned int); na > 0; |
267 | for (na /= sizeof(unsigned int); | 255 | --na, ++ap) |
268 | na > 0; --na, ++ap) | 256 | if (*ap <= addr && |
269 | if (*ap <= addr | 257 | addr < *ap + 0x1000000) { |
270 | && addr < | 258 | macos_display = dp; |
271 | *ap + 0x1000000) | 259 | goto foundit; |
272 | goto foundit; | 260 | } |
273 | } | 261 | } |
274 | 262 | ||
275 | /* | 263 | /* |
276 | * See if the display address is in one of the address | 264 | * See if the display address is in one of the address |
277 | * ranges for this display. | 265 | * ranges for this display. |
278 | */ | 266 | */ |
279 | for (i = 0; i < dp->n_addrs; ++i) { | 267 | i = 0; |
280 | if (dp->addrs[i].address <= addr | 268 | for (;;) { |
281 | && addr < | 269 | addrp = of_get_address(dp, i++, &dsize, &flags); |
282 | dp->addrs[i].address + | 270 | if (addrp == NULL) |
283 | dp->addrs[i].size) | ||
284 | break; | 271 | break; |
272 | if (!(flags & IORESOURCE_MEM)) | ||
273 | continue; | ||
274 | daddr = of_translate_address(dp, addrp); | ||
275 | if (daddr == OF_BAD_ADDR) | ||
276 | continue; | ||
277 | if (daddr <= addr && addr < (daddr + dsize)) { | ||
278 | macos_display = dp; | ||
279 | goto foundit; | ||
280 | } | ||
285 | } | 281 | } |
286 | if (i < dp->n_addrs) { | 282 | foundit: |
287 | foundit: | 283 | if (macos_display) { |
288 | printk(KERN_INFO "MacOS display is %s\n", | 284 | printk(KERN_INFO "MacOS display is %s\n", |
289 | dp->full_name); | 285 | dp->full_name); |
290 | macos_display = dp; | ||
291 | break; | 286 | break; |
292 | } | 287 | } |
293 | } | 288 | } |
@@ -326,8 +321,10 @@ static void __init offb_init_nodriver(struct device_node *dp) | |||
326 | int *pp, i; | 321 | int *pp, i; |
327 | unsigned int len; | 322 | unsigned int len; |
328 | int width = 640, height = 480, depth = 8, pitch; | 323 | int width = 640, height = 480, depth = 8, pitch; |
329 | unsigned int rsize, *up; | 324 | unsigned int flags, rsize, *up; |
330 | unsigned long address = 0; | 325 | u64 address = OF_BAD_ADDR; |
326 | u32 *addrp; | ||
327 | u64 asize; | ||
331 | 328 | ||
332 | if ((pp = (int *) get_property(dp, "depth", &len)) != NULL | 329 | if ((pp = (int *) get_property(dp, "depth", &len)) != NULL |
333 | && len == sizeof(int)) | 330 | && len == sizeof(int)) |
@@ -363,7 +360,7 @@ static void __init offb_init_nodriver(struct device_node *dp) | |||
363 | break; | 360 | break; |
364 | } | 361 | } |
365 | if (pdev) { | 362 | if (pdev) { |
366 | for (i = 0; i < 6 && address == 0; i++) { | 363 | for (i = 0; i < 6 && address == OF_BAD_ADDR; i++) { |
367 | if ((pci_resource_flags(pdev, i) & | 364 | if ((pci_resource_flags(pdev, i) & |
368 | IORESOURCE_MEM) && | 365 | IORESOURCE_MEM) && |
369 | (pci_resource_len(pdev, i) >= rsize)) | 366 | (pci_resource_len(pdev, i) >= rsize)) |
@@ -374,27 +371,33 @@ static void __init offb_init_nodriver(struct device_node *dp) | |||
374 | } | 371 | } |
375 | #endif /* CONFIG_PCI */ | 372 | #endif /* CONFIG_PCI */ |
376 | 373 | ||
377 | if (address == 0 && | 374 | /* This one is dodgy, we may drop it ... */ |
378 | (up = (unsigned *) get_property(dp, "address", &len)) != NULL && | 375 | if (address == OF_BAD_ADDR && |
379 | len == sizeof(unsigned)) | 376 | (up = (unsigned *) get_property(dp, "address", &len)) != NULL && |
380 | address = (u_long) * up; | 377 | len == sizeof(unsigned int)) |
381 | if (address == 0) { | 378 | address = (u64) * up; |
382 | for (i = 0; i < dp->n_addrs; ++i) | 379 | |
383 | if (dp->addrs[i].size >= | 380 | if (address == OF_BAD_ADDR) { |
384 | pitch * height * depth / 8) | 381 | for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) |
385 | break; | 382 | != NULL; i++) { |
386 | if (i >= dp->n_addrs) { | 383 | if (!(flags & IORESOURCE_MEM)) |
384 | continue; | ||
385 | if (asize >= pitch * height * depth / 8) | ||
386 | break; | ||
387 | } | ||
388 | if (addrp == NULL) { | ||
387 | printk(KERN_ERR | 389 | printk(KERN_ERR |
388 | "no framebuffer address found for %s\n", | 390 | "no framebuffer address found for %s\n", |
389 | dp->full_name); | 391 | dp->full_name); |
390 | return; | 392 | return; |
391 | } | 393 | } |
392 | 394 | address = of_translate_address(dp, addrp); | |
393 | address = (u_long) dp->addrs[i].address; | 395 | if (address == OF_BAD_ADDR) { |
394 | 396 | printk(KERN_ERR | |
395 | #ifdef CONFIG_PPC64 | 397 | "can't translate framebuffer address for %s\n", |
396 | address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset; | 398 | dp->full_name); |
397 | #endif | 399 | return; |
400 | } | ||
398 | 401 | ||
399 | /* kludge for valkyrie */ | 402 | /* kludge for valkyrie */ |
400 | if (strcmp(dp->name, "valkyrie") == 0) | 403 | if (strcmp(dp->name, "valkyrie") == 0) |
@@ -459,7 +462,9 @@ static void __init offb_init_fb(const char *name, const char *full_name, | |||
459 | 462 | ||
460 | par->cmap_type = cmap_unknown; | 463 | par->cmap_type = cmap_unknown; |
461 | if (depth == 8) { | 464 | if (depth == 8) { |
462 | /* XXX kludge for ati */ | 465 | |
466 | /* Palette hacks disabled for now */ | ||
467 | #if 0 | ||
463 | if (dp && !strncmp(name, "ATY,Rage128", 11)) { | 468 | if (dp && !strncmp(name, "ATY,Rage128", 11)) { |
464 | unsigned long regbase = dp->addrs[2].address; | 469 | unsigned long regbase = dp->addrs[2].address; |
465 | par->cmap_adr = ioremap(regbase, 0x1FFF); | 470 | par->cmap_adr = ioremap(regbase, 0x1FFF); |
@@ -490,6 +495,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, | |||
490 | par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); | 495 | par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); |
491 | par->cmap_type = cmap_gxt2000; | 496 | par->cmap_type = cmap_gxt2000; |
492 | } | 497 | } |
498 | #endif | ||
493 | fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR | 499 | fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR |
494 | : FB_VISUAL_STATIC_PSEUDOCOLOR; | 500 | : FB_VISUAL_STATIC_PSEUDOCOLOR; |
495 | } else | 501 | } else |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index ca4082ae5a18..335e37465559 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -69,6 +69,8 @@ struct fb_info_platinum { | |||
69 | unsigned long total_vram; | 69 | unsigned long total_vram; |
70 | int clktype; | 70 | int clktype; |
71 | int dactype; | 71 | int dactype; |
72 | |||
73 | struct resource rsrc_fb, rsrc_reg; | ||
72 | }; | 74 | }; |
73 | 75 | ||
74 | /* | 76 | /* |
@@ -97,9 +99,6 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, | |||
97 | * Interface used by the world | 99 | * Interface used by the world |
98 | */ | 100 | */ |
99 | 101 | ||
100 | int platinumfb_init(void); | ||
101 | int platinumfb_setup(char*); | ||
102 | |||
103 | static struct fb_ops platinumfb_ops = { | 102 | static struct fb_ops platinumfb_ops = { |
104 | .owner = THIS_MODULE, | 103 | .owner = THIS_MODULE, |
105 | .fb_check_var = platinumfb_check_var, | 104 | .fb_check_var = platinumfb_check_var, |
@@ -138,13 +137,15 @@ static int platinumfb_set_par (struct fb_info *info) | |||
138 | 137 | ||
139 | init = platinum_reg_init[pinfo->vmode-1]; | 138 | init = platinum_reg_init[pinfo->vmode-1]; |
140 | 139 | ||
141 | if (pinfo->vmode == 13 && pinfo->cmode > 0) | 140 | if ((pinfo->vmode == VMODE_832_624_75) && (pinfo->cmode > CMODE_8)) |
142 | offset = 0x10; | 141 | offset = 0x10; |
142 | |||
143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; | 143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; |
144 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; | 144 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; |
145 | info->fix.visual = (pinfo->cmode == CMODE_8) ? | 145 | info->fix.visual = (pinfo->cmode == CMODE_8) ? |
146 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | 146 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; |
147 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) + offset; | 147 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) |
148 | + offset; | ||
148 | printk("line_length: %x\n", info->fix.line_length); | 149 | printk("line_length: %x\n", info->fix.line_length); |
149 | return 0; | 150 | return 0; |
150 | } | 151 | } |
@@ -221,7 +222,9 @@ static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
221 | static inline int platinum_vram_reqd(int video_mode, int color_mode) | 222 | static inline int platinum_vram_reqd(int video_mode, int color_mode) |
222 | { | 223 | { |
223 | return vmode_attrs[video_mode-1].vres * | 224 | return vmode_attrs[video_mode-1].vres * |
224 | (vmode_attrs[video_mode-1].hres * (1<<color_mode) + 0x20) +0x1000; | 225 | (vmode_attrs[video_mode-1].hres * (1<<color_mode) + |
226 | ((video_mode == VMODE_832_624_75) && | ||
227 | (color_mode > CMODE_8)) ? 0x10 : 0x20) + 0x1000; | ||
225 | } | 228 | } |
226 | 229 | ||
227 | #define STORE_D2(a, d) { \ | 230 | #define STORE_D2(a, d) { \ |
@@ -481,7 +484,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, | |||
481 | /* | 484 | /* |
482 | * Parse user speficied options (`video=platinumfb:') | 485 | * Parse user speficied options (`video=platinumfb:') |
483 | */ | 486 | */ |
484 | int __init platinumfb_setup(char *options) | 487 | static int __init platinumfb_setup(char *options) |
485 | { | 488 | { |
486 | char *this_opt; | 489 | char *this_opt; |
487 | 490 | ||
@@ -522,19 +525,15 @@ int __init platinumfb_setup(char *options) | |||
522 | #define invalidate_cache(addr) | 525 | #define invalidate_cache(addr) |
523 | #endif | 526 | #endif |
524 | 527 | ||
525 | static int __devinit platinumfb_probe(struct of_device* odev, const struct of_device_id *match) | 528 | static int __devinit platinumfb_probe(struct of_device* odev, |
529 | const struct of_device_id *match) | ||
526 | { | 530 | { |
527 | struct device_node *dp = odev->node; | 531 | struct device_node *dp = odev->node; |
528 | struct fb_info *info; | 532 | struct fb_info *info; |
529 | struct fb_info_platinum *pinfo; | 533 | struct fb_info_platinum *pinfo; |
530 | unsigned long addr, size; | ||
531 | volatile __u8 *fbuffer; | 534 | volatile __u8 *fbuffer; |
532 | int i, bank0, bank1, bank2, bank3, rc; | 535 | int bank0, bank1, bank2, bank3, rc; |
533 | 536 | ||
534 | if (dp->n_addrs != 2) { | ||
535 | printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs); | ||
536 | return -ENXIO; | ||
537 | } | ||
538 | printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n"); | 537 | printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n"); |
539 | 538 | ||
540 | info = framebuffer_alloc(sizeof(*pinfo), &odev->dev); | 539 | info = framebuffer_alloc(sizeof(*pinfo), &odev->dev); |
@@ -542,26 +541,39 @@ static int __devinit platinumfb_probe(struct of_device* odev, const struct of_de | |||
542 | return -ENOMEM; | 541 | return -ENOMEM; |
543 | pinfo = info->par; | 542 | pinfo = info->par; |
544 | 543 | ||
545 | /* Map in frame buffer and registers */ | 544 | if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) || |
546 | for (i = 0; i < dp->n_addrs; ++i) { | 545 | of_address_to_resource(dp, 1, &pinfo->rsrc_fb)) { |
547 | addr = dp->addrs[i].address; | 546 | printk(KERN_ERR "platinumfb: Can't get resources\n"); |
548 | size = dp->addrs[i].size; | 547 | framebuffer_release(info); |
549 | /* Let's assume we can request either all or nothing */ | 548 | return -ENXIO; |
550 | if (!request_mem_region(addr, size, "platinumfb")) { | ||
551 | framebuffer_release(info); | ||
552 | return -ENXIO; | ||
553 | } | ||
554 | if (size >= 0x400000) { | ||
555 | /* frame buffer - map only 4MB */ | ||
556 | pinfo->frame_buffer_phys = addr; | ||
557 | pinfo->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU); | ||
558 | pinfo->base_frame_buffer = pinfo->frame_buffer; | ||
559 | } else { | ||
560 | /* registers */ | ||
561 | pinfo->platinum_regs_phys = addr; | ||
562 | pinfo->platinum_regs = ioremap(addr, size); | ||
563 | } | ||
564 | } | 549 | } |
550 | if (!request_mem_region(pinfo->rsrc_reg.start, | ||
551 | pinfo->rsrc_reg.start - | ||
552 | pinfo->rsrc_reg.end + 1, | ||
553 | "platinumfb registers")) { | ||
554 | framebuffer_release(info); | ||
555 | return -ENXIO; | ||
556 | } | ||
557 | if (!request_mem_region(pinfo->rsrc_fb.start, | ||
558 | pinfo->rsrc_fb.start | ||
559 | - pinfo->rsrc_fb.end + 1, | ||
560 | "platinumfb framebuffer")) { | ||
561 | release_mem_region(pinfo->rsrc_reg.start, | ||
562 | pinfo->rsrc_reg.end - | ||
563 | pinfo->rsrc_reg.start + 1); | ||
564 | framebuffer_release(info); | ||
565 | return -ENXIO; | ||
566 | } | ||
567 | |||
568 | /* frame buffer - map only 4MB */ | ||
569 | pinfo->frame_buffer_phys = pinfo->rsrc_fb.start; | ||
570 | pinfo->frame_buffer = __ioremap(pinfo->rsrc_fb.start, 0x400000, | ||
571 | _PAGE_WRITETHRU); | ||
572 | pinfo->base_frame_buffer = pinfo->frame_buffer; | ||
573 | |||
574 | /* registers */ | ||
575 | pinfo->platinum_regs_phys = pinfo->rsrc_reg.start; | ||
576 | pinfo->platinum_regs = ioremap(pinfo->rsrc_reg.start, 0x1000); | ||
565 | 577 | ||
566 | pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ | 578 | pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ |
567 | request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap"); | 579 | request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap"); |
@@ -624,18 +636,16 @@ static int __devexit platinumfb_remove(struct of_device* odev) | |||
624 | { | 636 | { |
625 | struct fb_info *info = dev_get_drvdata(&odev->dev); | 637 | struct fb_info *info = dev_get_drvdata(&odev->dev); |
626 | struct fb_info_platinum *pinfo = info->par; | 638 | struct fb_info_platinum *pinfo = info->par; |
627 | struct device_node *dp = odev->node; | ||
628 | unsigned long addr, size; | ||
629 | int i; | ||
630 | 639 | ||
631 | unregister_framebuffer (info); | 640 | unregister_framebuffer (info); |
632 | 641 | ||
633 | /* Unmap frame buffer and registers */ | 642 | /* Unmap frame buffer and registers */ |
634 | for (i = 0; i < dp->n_addrs; ++i) { | 643 | release_mem_region(pinfo->rsrc_fb.start, |
635 | addr = dp->addrs[i].address; | 644 | pinfo->rsrc_fb.end - |
636 | size = dp->addrs[i].size; | 645 | pinfo->rsrc_fb.start + 1); |
637 | release_mem_region(addr, size); | 646 | release_mem_region(pinfo->rsrc_reg.start, |
638 | } | 647 | pinfo->rsrc_reg.end - |
648 | pinfo->rsrc_reg.start + 1); | ||
639 | iounmap(pinfo->frame_buffer); | 649 | iounmap(pinfo->frame_buffer); |
640 | iounmap(pinfo->platinum_regs); | 650 | iounmap(pinfo->platinum_regs); |
641 | release_mem_region(pinfo->cmap_regs_phys, 0x1000); | 651 | release_mem_region(pinfo->cmap_regs_phys, 0x1000); |
@@ -662,7 +672,7 @@ static struct of_platform_driver platinum_driver = | |||
662 | .remove = platinumfb_remove, | 672 | .remove = platinumfb_remove, |
663 | }; | 673 | }; |
664 | 674 | ||
665 | int __init platinumfb_init(void) | 675 | static int __init platinumfb_init(void) |
666 | { | 676 | { |
667 | #ifndef MODULE | 677 | #ifndef MODULE |
668 | char *option = NULL; | 678 | char *option = NULL; |
@@ -676,7 +686,7 @@ int __init platinumfb_init(void) | |||
676 | return 0; | 686 | return 0; |
677 | } | 687 | } |
678 | 688 | ||
679 | void __exit platinumfb_exit(void) | 689 | static void __exit platinumfb_exit(void) |
680 | { | 690 | { |
681 | of_unregister_driver(&platinum_driver); | 691 | of_unregister_driver(&platinum_driver); |
682 | } | 692 | } |
diff --git a/drivers/video/platinumfb.h b/drivers/video/platinumfb.h index 2834fc1c344b..f6bd77cafd17 100644 --- a/drivers/video/platinumfb.h +++ b/drivers/video/platinumfb.h | |||
@@ -158,7 +158,9 @@ static struct platinum_regvals platinum_reg_init_14 = { | |||
158 | /* 832x624, 75Hz (13) */ | 158 | /* 832x624, 75Hz (13) */ |
159 | static struct platinum_regvals platinum_reg_init_13 = { | 159 | static struct platinum_regvals platinum_reg_init_13 = { |
160 | 0x70, | 160 | 0x70, |
161 | { 864, 1680, 3360 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB */ | 161 | { 864, 1680, 3344 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB, |
162 | * and we use 3344 instead of 3360 to fit in 2Mb | ||
163 | */ | ||
162 | { 0xff0, 4, 0, 0, 0, 0, 0x299, 0, | 164 | { 0xff0, 4, 0, 0, 0, 0, 0x299, 0, |
163 | 0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37, | 165 | 0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37, |
164 | 0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52, | 166 | 0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52, |
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index ce97ec8eae97..2bdeb4baa952 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
@@ -342,19 +342,19 @@ int __init valkyriefb_init(void) | |||
342 | #else /* ppc (!CONFIG_MAC) */ | 342 | #else /* ppc (!CONFIG_MAC) */ |
343 | { | 343 | { |
344 | struct device_node *dp; | 344 | struct device_node *dp; |
345 | struct resource r; | ||
345 | 346 | ||
346 | dp = find_devices("valkyrie"); | 347 | dp = of_find_node_by_name(NULL, "valkyrie"); |
347 | if (dp == 0) | 348 | if (dp == 0) |
348 | return 0; | 349 | return 0; |
349 | 350 | ||
350 | if (dp->n_addrs != 1) { | 351 | if (of_address_to_resource(dp, 0, &r)) { |
351 | printk(KERN_ERR "expecting 1 address for valkyrie (got %d)\n", | 352 | printk(KERN_ERR "can't find address for valkyrie\n"); |
352 | dp->n_addrs); | ||
353 | return 0; | 353 | return 0; |
354 | } | 354 | } |
355 | 355 | ||
356 | frame_buffer_phys = dp->addrs[0].address; | 356 | frame_buffer_phys = r.start; |
357 | cmap_regs_phys = dp->addrs[0].address+0x304000; | 357 | cmap_regs_phys = r.start + 0x304000; |
358 | flags = _PAGE_WRITETHRU; | 358 | flags = _PAGE_WRITETHRU; |
359 | } | 359 | } |
360 | #endif /* ppc (!CONFIG_MAC) */ | 360 | #endif /* ppc (!CONFIG_MAC) */ |