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) */ |
