diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/powermac/feature.c | 127 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/low_i2c.c | 853 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/setup.c | 23 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/smp.c | 75 |
4 files changed, 730 insertions, 348 deletions
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index d2915d64d45e..b271b11583ac 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -1677,124 +1677,6 @@ intrepid_shutdown(struct macio_chip *macio, int sleep_mode) | |||
1677 | } | 1677 | } |
1678 | 1678 | ||
1679 | 1679 | ||
1680 | void pmac_tweak_clock_spreading(int enable) | ||
1681 | { | ||
1682 | struct macio_chip *macio = &macio_chips[0]; | ||
1683 | |||
1684 | /* Hack for doing clock spreading on some machines PowerBooks and | ||
1685 | * iBooks. This implements the "platform-do-clockspreading" OF | ||
1686 | * property as decoded manually on various models. For safety, we also | ||
1687 | * check the product ID in the device-tree in cases we'll whack the i2c | ||
1688 | * chip to make reasonably sure we won't set wrong values in there | ||
1689 | * | ||
1690 | * Of course, ultimately, we have to implement a real parser for | ||
1691 | * the platform-do-* stuff... | ||
1692 | */ | ||
1693 | |||
1694 | if (macio->type == macio_intrepid) { | ||
1695 | struct device_node *clock = | ||
1696 | of_find_node_by_path("/uni-n@f8000000/hw-clock"); | ||
1697 | if (clock && get_property(clock, "platform-do-clockspreading", | ||
1698 | NULL)) { | ||
1699 | printk(KERN_INFO "%sabling clock spreading on Intrepid" | ||
1700 | " ASIC\n", enable ? "En" : "Dis"); | ||
1701 | if (enable) | ||
1702 | UN_OUT(UNI_N_CLOCK_SPREADING, 2); | ||
1703 | else | ||
1704 | UN_OUT(UNI_N_CLOCK_SPREADING, 0); | ||
1705 | mdelay(40); | ||
1706 | } | ||
1707 | of_node_put(clock); | ||
1708 | } | ||
1709 | |||
1710 | while (machine_is_compatible("PowerBook5,2") || | ||
1711 | machine_is_compatible("PowerBook5,3") || | ||
1712 | machine_is_compatible("PowerBook6,2") || | ||
1713 | machine_is_compatible("PowerBook6,3")) { | ||
1714 | struct device_node *ui2c = of_find_node_by_type(NULL, "i2c"); | ||
1715 | struct device_node *dt = of_find_node_by_name(NULL, "device-tree"); | ||
1716 | u8 buffer[9]; | ||
1717 | u32 *productID; | ||
1718 | int i, rc, changed = 0; | ||
1719 | |||
1720 | if (dt == NULL) | ||
1721 | break; | ||
1722 | productID = (u32 *)get_property(dt, "pid#", NULL); | ||
1723 | if (productID == NULL) | ||
1724 | break; | ||
1725 | while(ui2c) { | ||
1726 | struct device_node *p = of_get_parent(ui2c); | ||
1727 | if (p && !strcmp(p->name, "uni-n")) | ||
1728 | break; | ||
1729 | ui2c = of_find_node_by_type(ui2c, "i2c"); | ||
1730 | } | ||
1731 | if (ui2c == NULL) | ||
1732 | break; | ||
1733 | DBG("Trying to bump clock speed for PID: %08x...\n", *productID); | ||
1734 | rc = pmac_low_i2c_open(ui2c, 1); | ||
1735 | if (rc != 0) | ||
1736 | break; | ||
1737 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
1738 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
1739 | DBG("read result: %d,", rc); | ||
1740 | if (rc != 0) { | ||
1741 | pmac_low_i2c_close(ui2c); | ||
1742 | break; | ||
1743 | } | ||
1744 | for (i=0; i<9; i++) | ||
1745 | DBG(" %02x", buffer[i]); | ||
1746 | DBG("\n"); | ||
1747 | |||
1748 | switch(*productID) { | ||
1749 | case 0x1182: /* AlBook 12" rev 2 */ | ||
1750 | case 0x1183: /* iBook G4 12" */ | ||
1751 | buffer[0] = (buffer[0] & 0x8f) | 0x70; | ||
1752 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
1753 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
1754 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
1755 | buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba); | ||
1756 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
1757 | changed = 1; | ||
1758 | break; | ||
1759 | case 0x3142: /* AlBook 15" (ATI M10) */ | ||
1760 | case 0x3143: /* AlBook 17" (ATI M10) */ | ||
1761 | buffer[0] = (buffer[0] & 0xaf) | 0x50; | ||
1762 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
1763 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
1764 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
1765 | buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0); | ||
1766 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
1767 | changed = 1; | ||
1768 | break; | ||
1769 | default: | ||
1770 | DBG("i2c-hwclock: Machine model not handled\n"); | ||
1771 | break; | ||
1772 | } | ||
1773 | if (!changed) { | ||
1774 | pmac_low_i2c_close(ui2c); | ||
1775 | break; | ||
1776 | } | ||
1777 | printk(KERN_INFO "%sabling clock spreading on i2c clock chip\n", | ||
1778 | enable ? "En" : "Dis"); | ||
1779 | |||
1780 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub); | ||
1781 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9); | ||
1782 | DBG("write result: %d,", rc); | ||
1783 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
1784 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
1785 | DBG("read result: %d,", rc); | ||
1786 | if (rc != 0) { | ||
1787 | pmac_low_i2c_close(ui2c); | ||
1788 | break; | ||
1789 | } | ||
1790 | for (i=0; i<9; i++) | ||
1791 | DBG(" %02x", buffer[i]); | ||
1792 | pmac_low_i2c_close(ui2c); | ||
1793 | break; | ||
1794 | } | ||
1795 | } | ||
1796 | |||
1797 | |||
1798 | static int | 1680 | static int |
1799 | core99_sleep(void) | 1681 | core99_sleep(void) |
1800 | { | 1682 | { |
@@ -2980,12 +2862,6 @@ set_initial_features(void) | |||
2980 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | 2862 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); |
2981 | } | 2863 | } |
2982 | 2864 | ||
2983 | /* Some machine models need the clock chip to be properly setup for | ||
2984 | * clock spreading now. This should be a platform function but we | ||
2985 | * don't do these at the moment | ||
2986 | */ | ||
2987 | pmac_tweak_clock_spreading(1); | ||
2988 | |||
2989 | #endif /* CONFIG_POWER4 */ | 2865 | #endif /* CONFIG_POWER4 */ |
2990 | 2866 | ||
2991 | /* On all machines, switch modem & serial ports off */ | 2867 | /* On all machines, switch modem & serial ports off */ |
@@ -3013,9 +2889,6 @@ pmac_feature_init(void) | |||
3013 | return; | 2889 | return; |
3014 | } | 2890 | } |
3015 | 2891 | ||
3016 | /* Setup low-level i2c stuffs */ | ||
3017 | pmac_init_low_i2c(); | ||
3018 | |||
3019 | /* Probe machine type */ | 2892 | /* Probe machine type */ |
3020 | if (probe_motherboard()) | 2893 | if (probe_motherboard()) |
3021 | printk(KERN_WARNING "Unknown PowerMac !\n"); | 2894 | printk(KERN_WARNING "Unknown PowerMac !\n"); |
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 606e0ed13731..f31d6a678b9e 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c | |||
@@ -1,22 +1,34 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/platforms/pmac_low_i2c.c | 2 | * arch/powerpc/platforms/powermac/low_i2c.c |
3 | * | 3 | * |
4 | * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org) | 4 | * Copyright (C) 2003-2005 Ben. Herrenschmidt (benh@kernel.crashing.org) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | * | 10 | * |
11 | * This file contains some low-level i2c access routines that | 11 | * The linux i2c layer isn't completely suitable for our needs for various |
12 | * need to be used by various bits of the PowerMac platform code | 12 | * reasons ranging from too late initialisation to semantics not perfectly |
13 | * at times where the real asynchronous & interrupt driven driver | 13 | * matching some requirements of the apple platform functions etc... |
14 | * cannot be used. The API borrows some semantics from the darwin | 14 | * |
15 | * driver in order to ease the implementation of the platform | 15 | * This file thus provides a simple low level unified i2c interface for |
16 | * properties parser | 16 | * powermac that covers the various types of i2c busses used in Apple machines. |
17 | * For now, keywest, PMU and SMU, though we could add Cuda, or other bit | ||
18 | * banging busses found on older chipstes in earlier machines if we ever need | ||
19 | * one of them. | ||
20 | * | ||
21 | * The drivers in this file are synchronous/blocking. In addition, the | ||
22 | * keywest one is fairly slow due to the use of msleep instead of interrupts | ||
23 | * as the interrupt is currently used by i2c-keywest. In the long run, we | ||
24 | * might want to get rid of those high-level interfaces to linux i2c layer | ||
25 | * either completely (converting all drivers) or replacing them all with a | ||
26 | * single stub driver on top of this one. Once done, the interrupt will be | ||
27 | * available for our use. | ||
17 | */ | 28 | */ |
18 | 29 | ||
19 | #undef DEBUG | 30 | #undef DEBUG |
31 | #undef DEBUG_LOW | ||
20 | 32 | ||
21 | #include <linux/config.h> | 33 | #include <linux/config.h> |
22 | #include <linux/types.h> | 34 | #include <linux/types.h> |
@@ -25,15 +37,16 @@ | |||
25 | #include <linux/module.h> | 37 | #include <linux/module.h> |
26 | #include <linux/adb.h> | 38 | #include <linux/adb.h> |
27 | #include <linux/pmu.h> | 39 | #include <linux/pmu.h> |
40 | #include <linux/delay.h> | ||
41 | #include <linux/completion.h> | ||
28 | #include <asm/keylargo.h> | 42 | #include <asm/keylargo.h> |
29 | #include <asm/uninorth.h> | 43 | #include <asm/uninorth.h> |
30 | #include <asm/io.h> | 44 | #include <asm/io.h> |
31 | #include <asm/prom.h> | 45 | #include <asm/prom.h> |
32 | #include <asm/machdep.h> | 46 | #include <asm/machdep.h> |
47 | #include <asm/smu.h> | ||
33 | #include <asm/pmac_low_i2c.h> | 48 | #include <asm/pmac_low_i2c.h> |
34 | 49 | ||
35 | #define MAX_LOW_I2C_HOST 4 | ||
36 | |||
37 | #ifdef DEBUG | 50 | #ifdef DEBUG |
38 | #define DBG(x...) do {\ | 51 | #define DBG(x...) do {\ |
39 | printk(KERN_DEBUG "low_i2c:" x); \ | 52 | printk(KERN_DEBUG "low_i2c:" x); \ |
@@ -42,49 +55,54 @@ | |||
42 | #define DBG(x...) | 55 | #define DBG(x...) |
43 | #endif | 56 | #endif |
44 | 57 | ||
45 | struct low_i2c_host; | 58 | #ifdef DEBUG_LOW |
46 | 59 | #define DBG_LOW(x...) do {\ | |
47 | typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len); | 60 | printk(KERN_DEBUG "low_i2c:" x); \ |
48 | 61 | } while(0) | |
49 | struct low_i2c_host | 62 | #else |
50 | { | 63 | #define DBG_LOW(x...) |
51 | struct device_node *np; /* OF device node */ | 64 | #endif |
52 | struct semaphore mutex; /* Access mutex for use by i2c-keywest */ | ||
53 | low_i2c_func_t func; /* Access function */ | ||
54 | unsigned int is_open : 1; /* Poor man's access control */ | ||
55 | int mode; /* Current mode */ | ||
56 | int channel; /* Current channel */ | ||
57 | int num_channels; /* Number of channels */ | ||
58 | void __iomem *base; /* For keywest-i2c, base address */ | ||
59 | int bsteps; /* And register stepping */ | ||
60 | int speed; /* And speed */ | ||
61 | }; | ||
62 | |||
63 | static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST]; | ||
64 | 65 | ||
65 | /* No locking is necessary on allocation, we are running way before | 66 | /* |
66 | * anything can race with us | 67 | * A bus structure. Each bus in the system has such a structure associated. |
67 | */ | 68 | */ |
68 | static struct low_i2c_host *find_low_i2c_host(struct device_node *np) | 69 | struct pmac_i2c_bus |
69 | { | 70 | { |
70 | int i; | 71 | struct list_head link; |
72 | struct device_node *controller; | ||
73 | struct device_node *busnode; | ||
74 | int type; | ||
75 | int flags; | ||
76 | struct i2c_adapter *adapter; | ||
77 | void *hostdata; | ||
78 | int channel; /* some hosts have multiple */ | ||
79 | int mode; /* current mode */ | ||
80 | struct semaphore sem; | ||
81 | int opened; | ||
82 | int polled; /* open mode */ | ||
83 | |||
84 | /* ops */ | ||
85 | int (*open)(struct pmac_i2c_bus *bus); | ||
86 | void (*close)(struct pmac_i2c_bus *bus); | ||
87 | int (*xfer)(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, | ||
88 | u32 subaddr, u8 *data, int len); | ||
89 | }; | ||
71 | 90 | ||
72 | for (i = 0; i < MAX_LOW_I2C_HOST; i++) | 91 | static LIST_HEAD(pmac_i2c_busses); |
73 | if (low_i2c_hosts[i].np == np) | ||
74 | return &low_i2c_hosts[i]; | ||
75 | return NULL; | ||
76 | } | ||
77 | 92 | ||
78 | /* | 93 | /* |
79 | * | 94 | * Keywest implementation |
80 | * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's) | ||
81 | * | ||
82 | */ | 95 | */ |
83 | 96 | ||
84 | /* | 97 | struct pmac_i2c_host_kw |
85 | * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h, | 98 | { |
86 | * should be moved somewhere in include/asm-ppc/ | 99 | struct semaphore mutex; /* Access mutex for use by |
87 | */ | 100 | * i2c-keywest */ |
101 | void __iomem *base; /* register base address */ | ||
102 | int bsteps; /* register stepping */ | ||
103 | int speed; /* speed */ | ||
104 | }; | ||
105 | |||
88 | /* Register indices */ | 106 | /* Register indices */ |
89 | typedef enum { | 107 | typedef enum { |
90 | reg_mode = 0, | 108 | reg_mode = 0, |
@@ -153,52 +171,56 @@ static const char *__kw_state_names[] = { | |||
153 | "state_dead" | 171 | "state_dead" |
154 | }; | 172 | }; |
155 | 173 | ||
156 | static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) | 174 | static inline u8 __kw_read_reg(struct pmac_i2c_bus *bus, reg_t reg) |
157 | { | 175 | { |
176 | struct pmac_i2c_host_kw *host = bus->hostdata; | ||
158 | return readb(host->base + (((unsigned int)reg) << host->bsteps)); | 177 | return readb(host->base + (((unsigned int)reg) << host->bsteps)); |
159 | } | 178 | } |
160 | 179 | ||
161 | static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) | 180 | static inline void __kw_write_reg(struct pmac_i2c_bus *bus, reg_t reg, u8 val) |
162 | { | 181 | { |
182 | struct pmac_i2c_host_kw *host = bus->hostdata; | ||
163 | writeb(val, host->base + (((unsigned)reg) << host->bsteps)); | 183 | writeb(val, host->base + (((unsigned)reg) << host->bsteps)); |
164 | (void)__kw_read_reg(host, reg_subaddr); | 184 | (void)__kw_read_reg(bus, reg_subaddr); |
165 | } | 185 | } |
166 | 186 | ||
167 | #define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) | 187 | #define kw_write_reg(reg, val) __kw_write_reg(bus, reg, val) |
168 | #define kw_read_reg(reg) __kw_read_reg(host, reg) | 188 | #define kw_read_reg(reg) __kw_read_reg(bus, reg) |
169 | 189 | ||
170 | 190 | static u8 kw_i2c_wait_interrupt(struct pmac_i2c_bus* bus) | |
171 | /* Don't schedule, the g5 fan controller is too | ||
172 | * timing sensitive | ||
173 | */ | ||
174 | static u8 kw_wait_interrupt(struct low_i2c_host* host) | ||
175 | { | 191 | { |
176 | int i, j; | 192 | int i, j; |
177 | u8 isr; | 193 | u8 isr; |
178 | 194 | ||
179 | for (i = 0; i < 100000; i++) { | 195 | for (i = 0; i < 1000; i++) { |
180 | isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; | 196 | isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; |
181 | if (isr != 0) | 197 | if (isr != 0) |
182 | return isr; | 198 | return isr; |
183 | 199 | ||
184 | /* This code is used with the timebase frozen, we cannot rely | 200 | /* This code is used with the timebase frozen, we cannot rely |
185 | * on udelay ! For now, just use a bogus loop | 201 | * on udelay nor schedule when in polled mode ! |
202 | * For now, just use a bogus loop.... | ||
186 | */ | 203 | */ |
187 | for (j = 1; j < 10000; j++) | 204 | if (bus->polled) { |
188 | mb(); | 205 | for (j = 1; j < 1000000; j++) |
206 | mb(); | ||
207 | } else | ||
208 | msleep(1); | ||
189 | } | 209 | } |
190 | return isr; | 210 | return isr; |
191 | } | 211 | } |
192 | 212 | ||
193 | static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr) | 213 | static int kw_i2c_handle_interrupt(struct pmac_i2c_bus *bus, int state, int rw, |
214 | int *rc, u8 **data, int *len, u8 isr) | ||
194 | { | 215 | { |
195 | u8 ack; | 216 | u8 ack; |
196 | 217 | ||
197 | DBG("kw_handle_interrupt(%s, isr: %x)\n", __kw_state_names[state], isr); | 218 | DBG_LOW("kw_handle_interrupt(%s, isr: %x)\n", |
219 | __kw_state_names[state], isr); | ||
198 | 220 | ||
199 | if (isr == 0) { | 221 | if (isr == 0) { |
200 | if (state != state_stop) { | 222 | if (state != state_stop) { |
201 | DBG("KW: Timeout !\n"); | 223 | DBG_LOW("KW: Timeout !\n"); |
202 | *rc = -EIO; | 224 | *rc = -EIO; |
203 | goto stop; | 225 | goto stop; |
204 | } | 226 | } |
@@ -220,15 +242,16 @@ static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int | |||
220 | *rc = -EIO; | 242 | *rc = -EIO; |
221 | goto stop; | 243 | goto stop; |
222 | } | 244 | } |
223 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | 245 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { |
224 | *rc = -ENODEV; | 246 | *rc = -ENODEV; |
225 | DBG("KW: NAK on address\n"); | 247 | DBG_LOW("KW: NAK on address\n"); |
226 | return state_stop; | 248 | return state_stop; |
227 | } else { | 249 | } else { |
228 | if (rw) { | 250 | if (rw) { |
229 | state = state_read; | 251 | state = state_read; |
230 | if (*len > 1) | 252 | if (*len > 1) |
231 | kw_write_reg(reg_control, KW_I2C_CTL_AAK); | 253 | kw_write_reg(reg_control, |
254 | KW_I2C_CTL_AAK); | ||
232 | } else { | 255 | } else { |
233 | state = state_write; | 256 | state = state_write; |
234 | kw_write_reg(reg_data, **data); | 257 | kw_write_reg(reg_data, **data); |
@@ -250,7 +273,7 @@ static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int | |||
250 | } else if (state == state_write) { | 273 | } else if (state == state_write) { |
251 | ack = kw_read_reg(reg_status); | 274 | ack = kw_read_reg(reg_status); |
252 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | 275 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { |
253 | DBG("KW: nack on data write\n"); | 276 | DBG_LOW("KW: nack on data write\n"); |
254 | *rc = -EIO; | 277 | *rc = -EIO; |
255 | goto stop; | 278 | goto stop; |
256 | } else if (*len) { | 279 | } else if (*len) { |
@@ -291,35 +314,57 @@ static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int | |||
291 | return state_stop; | 314 | return state_stop; |
292 | } | 315 | } |
293 | 316 | ||
294 | static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len) | 317 | static int kw_i2c_open(struct pmac_i2c_bus *bus) |
295 | { | 318 | { |
319 | struct pmac_i2c_host_kw *host = bus->hostdata; | ||
320 | down(&host->mutex); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static void kw_i2c_close(struct pmac_i2c_bus *bus) | ||
325 | { | ||
326 | struct pmac_i2c_host_kw *host = bus->hostdata; | ||
327 | up(&host->mutex); | ||
328 | } | ||
329 | |||
330 | static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, | ||
331 | u32 subaddr, u8 *data, int len) | ||
332 | { | ||
333 | struct pmac_i2c_host_kw *host = bus->hostdata; | ||
296 | u8 mode_reg = host->speed; | 334 | u8 mode_reg = host->speed; |
297 | int state = state_addr; | 335 | int state = state_addr; |
298 | int rc = 0; | 336 | int rc = 0; |
299 | 337 | ||
300 | /* Setup mode & subaddress if any */ | 338 | /* Setup mode & subaddress if any */ |
301 | switch(host->mode) { | 339 | switch(bus->mode) { |
302 | case pmac_low_i2c_mode_dumb: | 340 | case pmac_i2c_mode_dumb: |
303 | printk(KERN_ERR "low_i2c: Dumb mode not supported !\n"); | ||
304 | return -EINVAL; | 341 | return -EINVAL; |
305 | case pmac_low_i2c_mode_std: | 342 | case pmac_i2c_mode_std: |
306 | mode_reg |= KW_I2C_MODE_STANDARD; | 343 | mode_reg |= KW_I2C_MODE_STANDARD; |
344 | if (subsize != 0) | ||
345 | return -EINVAL; | ||
307 | break; | 346 | break; |
308 | case pmac_low_i2c_mode_stdsub: | 347 | case pmac_i2c_mode_stdsub: |
309 | mode_reg |= KW_I2C_MODE_STANDARDSUB; | 348 | mode_reg |= KW_I2C_MODE_STANDARDSUB; |
349 | if (subsize != 1) | ||
350 | return -EINVAL; | ||
310 | break; | 351 | break; |
311 | case pmac_low_i2c_mode_combined: | 352 | case pmac_i2c_mode_combined: |
312 | mode_reg |= KW_I2C_MODE_COMBINED; | 353 | mode_reg |= KW_I2C_MODE_COMBINED; |
354 | if (subsize != 1) | ||
355 | return -EINVAL; | ||
313 | break; | 356 | break; |
314 | } | 357 | } |
315 | 358 | ||
316 | /* Setup channel & clear pending irqs */ | 359 | /* Setup channel & clear pending irqs */ |
317 | kw_write_reg(reg_isr, kw_read_reg(reg_isr)); | 360 | kw_write_reg(reg_isr, kw_read_reg(reg_isr)); |
318 | kw_write_reg(reg_mode, mode_reg | (host->channel << 4)); | 361 | kw_write_reg(reg_mode, mode_reg | (bus->channel << 4)); |
319 | kw_write_reg(reg_status, 0); | 362 | kw_write_reg(reg_status, 0); |
320 | 363 | ||
321 | /* Set up address and r/w bit */ | 364 | /* Set up address and r/w bit, strip possible stale bus number from |
322 | kw_write_reg(reg_addr, addr); | 365 | * address top bits |
366 | */ | ||
367 | kw_write_reg(reg_addr, addrdir & 0xff); | ||
323 | 368 | ||
324 | /* Set up the sub address */ | 369 | /* Set up the sub address */ |
325 | if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB | 370 | if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB |
@@ -330,27 +375,27 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, | |||
330 | kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); | 375 | kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); |
331 | kw_write_reg(reg_control, KW_I2C_CTL_XADDR); | 376 | kw_write_reg(reg_control, KW_I2C_CTL_XADDR); |
332 | 377 | ||
333 | /* State machine, to turn into an interrupt handler */ | 378 | /* State machine, to turn into an interrupt handler in the future */ |
334 | while(state != state_idle) { | 379 | while(state != state_idle) { |
335 | u8 isr = kw_wait_interrupt(host); | 380 | u8 isr = kw_i2c_wait_interrupt(bus); |
336 | state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr); | 381 | state = kw_i2c_handle_interrupt(bus, state, addrdir & 1, &rc, |
382 | &data, &len, isr); | ||
337 | } | 383 | } |
338 | 384 | ||
339 | return rc; | 385 | return rc; |
340 | } | 386 | } |
341 | 387 | ||
342 | static void keywest_low_i2c_add(struct device_node *np) | 388 | static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) |
343 | { | 389 | { |
344 | struct low_i2c_host *host = find_low_i2c_host(NULL); | 390 | struct pmac_i2c_host_kw *host; |
345 | u32 *psteps, *prate, *addrp, steps; | 391 | u32 *psteps, *prate, *addrp, steps; |
346 | struct device_node *parent; | ||
347 | 392 | ||
393 | host = kzalloc(sizeof(struct pmac_i2c_host_kw), GFP_KERNEL); | ||
348 | if (host == NULL) { | 394 | if (host == NULL) { |
349 | printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", | 395 | printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", |
350 | np->full_name); | 396 | np->full_name); |
351 | return; | 397 | return NULL; |
352 | } | 398 | } |
353 | memset(host, 0, sizeof(*host)); | ||
354 | 399 | ||
355 | /* Apple is kind enough to provide a valid AAPL,address property | 400 | /* Apple is kind enough to provide a valid AAPL,address property |
356 | * on all i2c keywest nodes so far ... we would have to fallback | 401 | * on all i2c keywest nodes so far ... we would have to fallback |
@@ -360,18 +405,14 @@ static void keywest_low_i2c_add(struct device_node *np) | |||
360 | if (addrp == NULL) { | 405 | if (addrp == NULL) { |
361 | printk(KERN_ERR "low_i2c: Can't find address for %s\n", | 406 | printk(KERN_ERR "low_i2c: Can't find address for %s\n", |
362 | np->full_name); | 407 | np->full_name); |
363 | return; | 408 | kfree(host); |
409 | return NULL; | ||
364 | } | 410 | } |
365 | init_MUTEX(&host->mutex); | 411 | init_MUTEX(&host->mutex); |
366 | host->np = of_node_get(np); | ||
367 | psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); | 412 | psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); |
368 | steps = psteps ? (*psteps) : 0x10; | 413 | steps = psteps ? (*psteps) : 0x10; |
369 | for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) | 414 | for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) |
370 | steps >>= 1; | 415 | steps >>= 1; |
371 | parent = of_get_parent(np); | ||
372 | host->num_channels = 1; | ||
373 | if (parent && parent->name[0] == 'u') | ||
374 | host->num_channels = 2; | ||
375 | /* Select interface rate */ | 416 | /* Select interface rate */ |
376 | host->speed = KW_I2C_MODE_25KHZ; | 417 | host->speed = KW_I2C_MODE_25KHZ; |
377 | prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); | 418 | prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); |
@@ -387,148 +428,620 @@ static void keywest_low_i2c_add(struct device_node *np) | |||
387 | break; | 428 | break; |
388 | } | 429 | } |
389 | 430 | ||
390 | printk(KERN_INFO "low_i2c: Bus %s found at 0x%08x, %d channels," | 431 | printk(KERN_INFO "KeyWest i2c @0x%08x %s\n", *addrp, np->full_name); |
391 | " speed = %d KHz\n", | ||
392 | np->full_name, *addrp, host->num_channels, prate ? *prate : 25); | ||
393 | |||
394 | host->mode = pmac_low_i2c_mode_std; | ||
395 | host->base = ioremap((*addrp), 0x1000); | 432 | host->base = ioremap((*addrp), 0x1000); |
396 | host->func = keywest_low_i2c_func; | 433 | |
434 | return host; | ||
397 | } | 435 | } |
398 | 436 | ||
437 | |||
438 | static void __init kw_i2c_add(struct pmac_i2c_host_kw *host, | ||
439 | struct device_node *controller, | ||
440 | struct device_node *busnode, | ||
441 | int channel) | ||
442 | { | ||
443 | struct pmac_i2c_bus *bus; | ||
444 | |||
445 | bus = kzalloc(sizeof(struct pmac_i2c_bus), GFP_KERNEL); | ||
446 | if (bus == NULL) | ||
447 | return; | ||
448 | |||
449 | bus->controller = of_node_get(controller); | ||
450 | bus->busnode = of_node_get(busnode); | ||
451 | bus->type = pmac_i2c_bus_keywest; | ||
452 | bus->hostdata = host; | ||
453 | bus->channel = channel; | ||
454 | bus->mode = pmac_i2c_mode_std; | ||
455 | bus->open = kw_i2c_open; | ||
456 | bus->close = kw_i2c_close; | ||
457 | bus->xfer = kw_i2c_xfer; | ||
458 | init_MUTEX(&bus->sem); | ||
459 | if (controller == busnode) | ||
460 | bus->flags = pmac_i2c_multibus; | ||
461 | list_add(&bus->link, &pmac_i2c_busses); | ||
462 | |||
463 | printk(KERN_INFO " channel %d bus %s\n", channel, | ||
464 | (controller == busnode) ? "<multibus>" : busnode->full_name); | ||
465 | } | ||
466 | |||
467 | static void __init kw_i2c_probe(void) | ||
468 | { | ||
469 | struct device_node *np, *child, *parent; | ||
470 | |||
471 | /* Probe keywest-i2c busses */ | ||
472 | for (np = NULL; | ||
473 | (np = of_find_compatible_node(np, "i2c","keywest-i2c")) != NULL;){ | ||
474 | struct pmac_i2c_host_kw *host; | ||
475 | int multibus, chans, i; | ||
476 | |||
477 | /* Found one, init a host structure */ | ||
478 | host = kw_i2c_host_init(np); | ||
479 | if (host == NULL) | ||
480 | continue; | ||
481 | |||
482 | /* Now check if we have a multibus setup (old style) or if we | ||
483 | * have proper bus nodes. Note that the "new" way (proper bus | ||
484 | * nodes) might cause us to not create some busses that are | ||
485 | * kept hidden in the device-tree. In the future, we might | ||
486 | * want to work around that by creating busses without a node | ||
487 | * but not for now | ||
488 | */ | ||
489 | child = of_get_next_child(np, NULL); | ||
490 | multibus = !child || strcmp(child->name, "i2c-bus"); | ||
491 | of_node_put(child); | ||
492 | |||
493 | /* For a multibus setup, we get the bus count based on the | ||
494 | * parent type | ||
495 | */ | ||
496 | if (multibus) { | ||
497 | parent = of_get_parent(np); | ||
498 | if (parent == NULL) | ||
499 | continue; | ||
500 | chans = parent->name[0] == 'u' ? 2 : 1; | ||
501 | for (i = 0; i < chans; i++) | ||
502 | kw_i2c_add(host, np, np, i); | ||
503 | } else { | ||
504 | for (child = NULL; | ||
505 | (child = of_get_next_child(np, child)) != NULL;) { | ||
506 | u32 *reg = | ||
507 | (u32 *)get_property(child, "reg", NULL); | ||
508 | if (reg == NULL) | ||
509 | continue; | ||
510 | kw_i2c_add(host, np, child, *reg); | ||
511 | } | ||
512 | } | ||
513 | } | ||
514 | } | ||
515 | |||
516 | |||
399 | /* | 517 | /* |
400 | * | 518 | * |
401 | * PMU implementation | 519 | * PMU implementation |
402 | * | 520 | * |
403 | */ | 521 | */ |
404 | 522 | ||
405 | |||
406 | #ifdef CONFIG_ADB_PMU | 523 | #ifdef CONFIG_ADB_PMU |
407 | 524 | ||
408 | static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len) | 525 | /* |
526 | * i2c command block to the PMU | ||
527 | */ | ||
528 | struct pmu_i2c_hdr { | ||
529 | u8 bus; | ||
530 | u8 mode; | ||
531 | u8 bus2; | ||
532 | u8 address; | ||
533 | u8 sub_addr; | ||
534 | u8 comb_addr; | ||
535 | u8 count; | ||
536 | u8 data[]; | ||
537 | }; | ||
538 | |||
539 | static void pmu_i2c_complete(struct adb_request *req) | ||
409 | { | 540 | { |
410 | // TODO | 541 | complete(req->arg); |
411 | return -ENODEV; | ||
412 | } | 542 | } |
413 | 543 | ||
414 | static void pmu_low_i2c_add(struct device_node *np) | 544 | static int pmu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, |
545 | u32 subaddr, u8 *data, int len) | ||
415 | { | 546 | { |
416 | struct low_i2c_host *host = find_low_i2c_host(NULL); | 547 | struct adb_request *req = bus->hostdata; |
548 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req->data[1]; | ||
549 | struct completion comp; | ||
550 | int read = addrdir & 1; | ||
551 | int retry; | ||
552 | int rc = 0; | ||
417 | 553 | ||
418 | if (host == NULL) { | 554 | /* For now, limit ourselves to 16 bytes transfers */ |
419 | printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", | 555 | if (len > 16) |
420 | np->full_name); | 556 | return -EINVAL; |
421 | return; | 557 | |
558 | init_completion(&comp); | ||
559 | |||
560 | for (retry = 0; retry < 16; retry++) { | ||
561 | memset(req, 0, sizeof(struct adb_request)); | ||
562 | hdr->bus = bus->channel; | ||
563 | hdr->count = len; | ||
564 | |||
565 | switch(bus->mode) { | ||
566 | case pmac_i2c_mode_std: | ||
567 | if (subsize != 0) | ||
568 | return -EINVAL; | ||
569 | hdr->address = addrdir; | ||
570 | hdr->mode = PMU_I2C_MODE_SIMPLE; | ||
571 | break; | ||
572 | case pmac_i2c_mode_stdsub: | ||
573 | case pmac_i2c_mode_combined: | ||
574 | if (subsize != 1) | ||
575 | return -EINVAL; | ||
576 | hdr->address = addrdir & 0xfe; | ||
577 | hdr->comb_addr = addrdir; | ||
578 | hdr->sub_addr = subaddr; | ||
579 | if (bus->mode == pmac_i2c_mode_stdsub) | ||
580 | hdr->mode = PMU_I2C_MODE_STDSUB; | ||
581 | else | ||
582 | hdr->mode = PMU_I2C_MODE_COMBINED; | ||
583 | break; | ||
584 | default: | ||
585 | return -EINVAL; | ||
586 | } | ||
587 | |||
588 | INIT_COMPLETION(comp); | ||
589 | req->data[0] = PMU_I2C_CMD; | ||
590 | req->reply[0] = 0xff; | ||
591 | req->nbytes = sizeof(struct pmu_i2c_hdr) + 1; | ||
592 | req->done = pmu_i2c_complete; | ||
593 | req->arg = ∁ | ||
594 | if (!read) { | ||
595 | memcpy(hdr->data, data, len); | ||
596 | req->nbytes += len; | ||
597 | } | ||
598 | rc = pmu_queue_request(req); | ||
599 | if (rc) | ||
600 | return rc; | ||
601 | wait_for_completion(&comp); | ||
602 | if (req->reply[0] == PMU_I2C_STATUS_OK) | ||
603 | break; | ||
604 | msleep(15); | ||
422 | } | 605 | } |
423 | memset(host, 0, sizeof(*host)); | 606 | if (req->reply[0] != PMU_I2C_STATUS_OK) |
607 | return -EIO; | ||
424 | 608 | ||
425 | init_MUTEX(&host->mutex); | 609 | for (retry = 0; retry < 16; retry++) { |
426 | host->np = of_node_get(np); | 610 | memset(req, 0, sizeof(struct adb_request)); |
427 | host->num_channels = 3; | 611 | |
428 | host->mode = pmac_low_i2c_mode_std; | 612 | /* I know that looks like a lot, slow as hell, but darwin |
429 | host->func = pmu_low_i2c_func; | 613 | * does it so let's be on the safe side for now |
614 | */ | ||
615 | msleep(15); | ||
616 | |||
617 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
618 | |||
619 | INIT_COMPLETION(comp); | ||
620 | req->data[0] = PMU_I2C_CMD; | ||
621 | req->reply[0] = 0xff; | ||
622 | req->nbytes = 2; | ||
623 | req->done = pmu_i2c_complete; | ||
624 | req->arg = ∁ | ||
625 | rc = pmu_queue_request(req); | ||
626 | if (rc) | ||
627 | return rc; | ||
628 | wait_for_completion(&comp); | ||
629 | |||
630 | if (req->reply[0] == PMU_I2C_STATUS_OK && !read) | ||
631 | return 0; | ||
632 | if (req->reply[0] == PMU_I2C_STATUS_DATAREAD && read) { | ||
633 | int rlen = req->reply_len - 1; | ||
634 | |||
635 | if (rlen != len) { | ||
636 | printk(KERN_WARNING "low_i2c: PMU returned %d" | ||
637 | " bytes, expected %d !\n", rlen, len); | ||
638 | return -EIO; | ||
639 | } | ||
640 | memcpy(data, &req->reply[1], len); | ||
641 | return 0; | ||
642 | } | ||
643 | } | ||
644 | return -EIO; | ||
645 | } | ||
646 | |||
647 | static void __init pmu_i2c_probe(void) | ||
648 | { | ||
649 | struct pmac_i2c_bus *bus; | ||
650 | struct device_node *busnode; | ||
651 | int channel, sz; | ||
652 | |||
653 | if (!pmu_present()) | ||
654 | return; | ||
655 | |||
656 | /* There might or might not be a "pmu-i2c" node, we use that | ||
657 | * or via-pmu itself, whatever we find. I haven't seen a machine | ||
658 | * with separate bus nodes, so we assume a multibus setup | ||
659 | */ | ||
660 | busnode = of_find_node_by_name(NULL, "pmu-i2c"); | ||
661 | if (busnode == NULL) | ||
662 | busnode = of_find_node_by_name(NULL, "via-pmu"); | ||
663 | if (busnode == NULL) | ||
664 | return; | ||
665 | |||
666 | printk(KERN_INFO "PMU i2c %s\n", busnode->full_name); | ||
667 | |||
668 | /* | ||
669 | * We add bus 1 and 2 only for now, bus 0 is "special" | ||
670 | */ | ||
671 | for (channel = 1; channel <= 2; channel++) { | ||
672 | sz = sizeof(struct pmac_i2c_bus) + sizeof(struct adb_request); | ||
673 | bus = kzalloc(sz, GFP_KERNEL); | ||
674 | if (bus == NULL) | ||
675 | return; | ||
676 | |||
677 | bus->controller = busnode; | ||
678 | bus->busnode = busnode; | ||
679 | bus->type = pmac_i2c_bus_pmu; | ||
680 | bus->channel = channel; | ||
681 | bus->mode = pmac_i2c_mode_std; | ||
682 | bus->hostdata = bus + 1; | ||
683 | bus->xfer = pmu_i2c_xfer; | ||
684 | init_MUTEX(&bus->sem); | ||
685 | bus->flags = pmac_i2c_multibus; | ||
686 | list_add(&bus->link, &pmac_i2c_busses); | ||
687 | |||
688 | printk(KERN_INFO " channel %d bus <multibus>\n", channel); | ||
689 | } | ||
430 | } | 690 | } |
431 | 691 | ||
432 | #endif /* CONFIG_ADB_PMU */ | 692 | #endif /* CONFIG_ADB_PMU */ |
433 | 693 | ||
434 | void __init pmac_init_low_i2c(void) | 694 | |
695 | /* | ||
696 | * | ||
697 | * SMU implementation | ||
698 | * | ||
699 | */ | ||
700 | |||
701 | #ifdef CONFIG_PMAC_SMU | ||
702 | |||
703 | static void smu_i2c_complete(struct smu_i2c_cmd *cmd, void *misc) | ||
435 | { | 704 | { |
436 | struct device_node *np; | 705 | complete(misc); |
706 | } | ||
437 | 707 | ||
438 | /* Probe keywest-i2c busses */ | 708 | static int smu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, |
439 | np = of_find_compatible_node(NULL, "i2c", "keywest-i2c"); | 709 | u32 subaddr, u8 *data, int len) |
440 | while(np) { | 710 | { |
441 | keywest_low_i2c_add(np); | 711 | struct smu_i2c_cmd *cmd = bus->hostdata; |
442 | np = of_find_compatible_node(np, "i2c", "keywest-i2c"); | 712 | struct completion comp; |
713 | int read = addrdir & 1; | ||
714 | int rc = 0; | ||
715 | |||
716 | memset(cmd, 0, sizeof(struct smu_i2c_cmd)); | ||
717 | cmd->info.bus = bus->channel; | ||
718 | cmd->info.devaddr = addrdir; | ||
719 | cmd->info.datalen = len; | ||
720 | |||
721 | switch(bus->mode) { | ||
722 | case pmac_i2c_mode_std: | ||
723 | if (subsize != 0) | ||
724 | return -EINVAL; | ||
725 | cmd->info.type = SMU_I2C_TRANSFER_SIMPLE; | ||
726 | break; | ||
727 | case pmac_i2c_mode_stdsub: | ||
728 | case pmac_i2c_mode_combined: | ||
729 | if (subsize > 3 || subsize < 1) | ||
730 | return -EINVAL; | ||
731 | cmd->info.sublen = subsize; | ||
732 | /* that's big-endian only but heh ! */ | ||
733 | memcpy(&cmd->info.subaddr, ((char *)&subaddr) + (4 - subsize), | ||
734 | subsize); | ||
735 | if (bus->mode == pmac_i2c_mode_stdsub) | ||
736 | cmd->info.type = SMU_I2C_TRANSFER_STDSUB; | ||
737 | else | ||
738 | cmd->info.type = SMU_I2C_TRANSFER_COMBINED; | ||
739 | break; | ||
740 | default: | ||
741 | return -EINVAL; | ||
443 | } | 742 | } |
743 | if (!read) | ||
744 | memcpy(cmd->info.data, data, len); | ||
745 | |||
746 | init_completion(&comp); | ||
747 | cmd->done = smu_i2c_complete; | ||
748 | cmd->misc = ∁ | ||
749 | rc = smu_queue_i2c(cmd); | ||
750 | if (rc < 0) | ||
751 | return rc; | ||
752 | wait_for_completion(&comp); | ||
753 | rc = cmd->status; | ||
754 | |||
755 | if (read) | ||
756 | memcpy(data, cmd->info.data, len); | ||
757 | return rc < 0 ? rc : 0; | ||
758 | } | ||
444 | 759 | ||
445 | #ifdef CONFIG_ADB_PMU | 760 | static void __init smu_i2c_probe(void) |
446 | /* Probe PMU busses */ | 761 | { |
447 | np = of_find_node_by_name(NULL, "via-pmu"); | 762 | struct device_node *controller, *busnode; |
448 | if (np) | 763 | struct pmac_i2c_bus *bus; |
449 | pmu_low_i2c_add(np); | 764 | u32 *reg; |
450 | #endif /* CONFIG_ADB_PMU */ | 765 | int sz; |
766 | |||
767 | if (!smu_present()) | ||
768 | return; | ||
769 | |||
770 | controller = of_find_node_by_name(NULL, "smu_i2c_control"); | ||
771 | if (controller == NULL) | ||
772 | controller = of_find_node_by_name(NULL, "smu"); | ||
773 | if (controller == NULL) | ||
774 | return; | ||
775 | |||
776 | printk(KERN_INFO "SMU i2c %s\n", controller->full_name); | ||
777 | |||
778 | /* Look for childs, note that they might not be of the right | ||
779 | * type as older device trees mix i2c busses and other thigns | ||
780 | * at the same level | ||
781 | */ | ||
782 | for (busnode = NULL; | ||
783 | (busnode = of_get_next_child(controller, busnode)) != NULL;) { | ||
784 | if (strcmp(busnode->type, "i2c") && | ||
785 | strcmp(busnode->type, "i2c-bus")) | ||
786 | continue; | ||
787 | reg = (u32 *)get_property(busnode, "reg", NULL); | ||
788 | if (reg == NULL) | ||
789 | continue; | ||
790 | |||
791 | sz = sizeof(struct pmac_i2c_bus) + sizeof(struct smu_i2c_cmd); | ||
792 | bus = kzalloc(sz, GFP_KERNEL); | ||
793 | if (bus == NULL) | ||
794 | return; | ||
795 | |||
796 | bus->controller = controller; | ||
797 | bus->busnode = of_node_get(busnode); | ||
798 | bus->type = pmac_i2c_bus_smu; | ||
799 | bus->channel = *reg; | ||
800 | bus->mode = pmac_i2c_mode_std; | ||
801 | bus->hostdata = bus + 1; | ||
802 | bus->xfer = smu_i2c_xfer; | ||
803 | init_MUTEX(&bus->sem); | ||
804 | bus->flags = 0; | ||
805 | list_add(&bus->link, &pmac_i2c_busses); | ||
806 | |||
807 | printk(KERN_INFO " channel %x bus %s\n", | ||
808 | bus->channel, busnode->full_name); | ||
809 | } | ||
810 | } | ||
811 | |||
812 | #endif /* CONFIG_PMAC_SMU */ | ||
813 | |||
814 | /* | ||
815 | * | ||
816 | * Core code | ||
817 | * | ||
818 | */ | ||
819 | |||
820 | |||
821 | struct pmac_i2c_bus *pmac_i2c_find_bus(struct device_node *node) | ||
822 | { | ||
823 | struct device_node *p = of_node_get(node); | ||
824 | struct device_node *prev = NULL; | ||
825 | struct pmac_i2c_bus *bus; | ||
826 | |||
827 | while(p) { | ||
828 | list_for_each_entry(bus, &pmac_i2c_busses, link) { | ||
829 | if (p == bus->busnode) { | ||
830 | if (prev && bus->flags & pmac_i2c_multibus) { | ||
831 | u32 *reg; | ||
832 | reg = (u32 *)get_property(prev, "reg", | ||
833 | NULL); | ||
834 | if (!reg) | ||
835 | continue; | ||
836 | if (((*reg) >> 8) != bus->channel) | ||
837 | continue; | ||
838 | } | ||
839 | of_node_put(p); | ||
840 | of_node_put(prev); | ||
841 | return bus; | ||
842 | } | ||
843 | } | ||
844 | of_node_put(prev); | ||
845 | prev = p; | ||
846 | p = of_get_parent(p); | ||
847 | } | ||
848 | return NULL; | ||
849 | } | ||
850 | EXPORT_SYMBOL_GPL(pmac_i2c_find_bus); | ||
851 | |||
852 | u8 pmac_i2c_get_dev_addr(struct device_node *device) | ||
853 | { | ||
854 | u32 *reg = (u32 *)get_property(device, "reg", NULL); | ||
855 | |||
856 | if (reg == NULL) | ||
857 | return 0; | ||
858 | |||
859 | return (*reg) & 0xff; | ||
860 | } | ||
861 | EXPORT_SYMBOL_GPL(pmac_i2c_get_dev_addr); | ||
862 | |||
863 | struct device_node *pmac_i2c_get_controller(struct pmac_i2c_bus *bus) | ||
864 | { | ||
865 | return bus->controller; | ||
866 | } | ||
867 | EXPORT_SYMBOL_GPL(pmac_i2c_get_controller); | ||
868 | |||
869 | struct device_node *pmac_i2c_get_bus_node(struct pmac_i2c_bus *bus) | ||
870 | { | ||
871 | return bus->busnode; | ||
872 | } | ||
873 | EXPORT_SYMBOL_GPL(pmac_i2c_get_bus_node); | ||
874 | |||
875 | int pmac_i2c_get_type(struct pmac_i2c_bus *bus) | ||
876 | { | ||
877 | return bus->type; | ||
878 | } | ||
879 | EXPORT_SYMBOL_GPL(pmac_i2c_get_type); | ||
880 | |||
881 | int pmac_i2c_get_flags(struct pmac_i2c_bus *bus) | ||
882 | { | ||
883 | return bus->flags; | ||
884 | } | ||
885 | EXPORT_SYMBOL_GPL(pmac_i2c_get_flags); | ||
451 | 886 | ||
452 | /* TODO: Add CUDA support as well */ | 887 | void pmac_i2c_attach_adapter(struct pmac_i2c_bus *bus, |
888 | struct i2c_adapter *adapter) | ||
889 | { | ||
890 | WARN_ON(bus->adapter != NULL); | ||
891 | bus->adapter = adapter; | ||
453 | } | 892 | } |
893 | EXPORT_SYMBOL_GPL(pmac_i2c_attach_adapter); | ||
894 | |||
895 | void pmac_i2c_detach_adapter(struct pmac_i2c_bus *bus, | ||
896 | struct i2c_adapter *adapter) | ||
897 | { | ||
898 | WARN_ON(bus->adapter != adapter); | ||
899 | bus->adapter = NULL; | ||
900 | } | ||
901 | EXPORT_SYMBOL_GPL(pmac_i2c_detach_adapter); | ||
902 | |||
903 | struct i2c_adapter *pmac_i2c_get_adapter(struct pmac_i2c_bus *bus) | ||
904 | { | ||
905 | return bus->adapter; | ||
906 | } | ||
907 | EXPORT_SYMBOL_GPL(pmac_i2c_get_adapter); | ||
908 | |||
909 | extern int pmac_i2c_match_adapter(struct device_node *dev, | ||
910 | struct i2c_adapter *adapter) | ||
911 | { | ||
912 | struct pmac_i2c_bus *bus = pmac_i2c_find_bus(dev); | ||
913 | |||
914 | if (bus == NULL) | ||
915 | return 0; | ||
916 | return (bus->adapter == adapter); | ||
917 | } | ||
918 | EXPORT_SYMBOL_GPL(pmac_i2c_match_adapter); | ||
454 | 919 | ||
455 | int pmac_low_i2c_lock(struct device_node *np) | 920 | int pmac_low_i2c_lock(struct device_node *np) |
456 | { | 921 | { |
457 | struct low_i2c_host *host = find_low_i2c_host(np); | 922 | struct pmac_i2c_bus *bus, *found = NULL; |
458 | 923 | ||
459 | if (!host) | 924 | list_for_each_entry(bus, &pmac_i2c_busses, link) { |
925 | if (np == bus->controller) { | ||
926 | found = bus; | ||
927 | break; | ||
928 | } | ||
929 | } | ||
930 | if (!found) | ||
460 | return -ENODEV; | 931 | return -ENODEV; |
461 | down(&host->mutex); | 932 | return pmac_i2c_open(bus, 0); |
462 | return 0; | ||
463 | } | 933 | } |
464 | EXPORT_SYMBOL(pmac_low_i2c_lock); | 934 | EXPORT_SYMBOL_GPL(pmac_low_i2c_lock); |
465 | 935 | ||
466 | int pmac_low_i2c_unlock(struct device_node *np) | 936 | int pmac_low_i2c_unlock(struct device_node *np) |
467 | { | 937 | { |
468 | struct low_i2c_host *host = find_low_i2c_host(np); | 938 | struct pmac_i2c_bus *bus, *found = NULL; |
469 | 939 | ||
470 | if (!host) | 940 | list_for_each_entry(bus, &pmac_i2c_busses, link) { |
941 | if (np == bus->controller) { | ||
942 | found = bus; | ||
943 | break; | ||
944 | } | ||
945 | } | ||
946 | if (!found) | ||
471 | return -ENODEV; | 947 | return -ENODEV; |
472 | up(&host->mutex); | 948 | pmac_i2c_close(bus); |
473 | return 0; | 949 | return 0; |
474 | } | 950 | } |
475 | EXPORT_SYMBOL(pmac_low_i2c_unlock); | 951 | EXPORT_SYMBOL_GPL(pmac_low_i2c_unlock); |
476 | 952 | ||
477 | 953 | ||
478 | int pmac_low_i2c_open(struct device_node *np, int channel) | 954 | int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled) |
479 | { | 955 | { |
480 | struct low_i2c_host *host = find_low_i2c_host(np); | 956 | int rc; |
957 | |||
958 | down(&bus->sem); | ||
959 | bus->polled = polled; | ||
960 | bus->opened = 1; | ||
961 | bus->mode = pmac_i2c_mode_std; | ||
962 | if (bus->open && (rc = bus->open(bus)) != 0) { | ||
963 | bus->opened = 0; | ||
964 | up(&bus->sem); | ||
965 | return rc; | ||
966 | } | ||
967 | return 0; | ||
968 | } | ||
969 | EXPORT_SYMBOL_GPL(pmac_i2c_open); | ||
481 | 970 | ||
482 | if (!host) | 971 | void pmac_i2c_close(struct pmac_i2c_bus *bus) |
483 | return -ENODEV; | 972 | { |
973 | WARN_ON(!bus->opened); | ||
974 | if (bus->close) | ||
975 | bus->close(bus); | ||
976 | bus->opened = 0; | ||
977 | up(&bus->sem); | ||
978 | } | ||
979 | EXPORT_SYMBOL_GPL(pmac_i2c_close); | ||
484 | 980 | ||
485 | if (channel >= host->num_channels) | 981 | int pmac_i2c_setmode(struct pmac_i2c_bus *bus, int mode) |
486 | return -EINVAL; | 982 | { |
983 | WARN_ON(!bus->opened); | ||
487 | 984 | ||
488 | down(&host->mutex); | 985 | /* Report me if you see the error below as there might be a new |
489 | host->is_open = 1; | 986 | * "combined4" mode that I need to implement for the SMU bus |
490 | host->channel = channel; | 987 | */ |
988 | if (mode < pmac_i2c_mode_dumb || mode > pmac_i2c_mode_combined) { | ||
989 | printk(KERN_ERR "low_i2c: Invalid mode %d requested on" | ||
990 | " bus %s !\n", mode, bus->busnode->full_name); | ||
991 | return -EINVAL; | ||
992 | } | ||
993 | bus->mode = mode; | ||
491 | 994 | ||
492 | return 0; | 995 | return 0; |
493 | } | 996 | } |
494 | EXPORT_SYMBOL(pmac_low_i2c_open); | 997 | EXPORT_SYMBOL_GPL(pmac_i2c_setmode); |
495 | 998 | ||
496 | int pmac_low_i2c_close(struct device_node *np) | 999 | int pmac_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, |
1000 | u32 subaddr, u8 *data, int len) | ||
497 | { | 1001 | { |
498 | struct low_i2c_host *host = find_low_i2c_host(np); | 1002 | int rc; |
499 | 1003 | ||
500 | if (!host) | 1004 | WARN_ON(!bus->opened); |
501 | return -ENODEV; | ||
502 | 1005 | ||
503 | host->is_open = 0; | 1006 | DBG("xfer() chan=%d, addrdir=0x%x, mode=%d, subsize=%d, subaddr=0x%x," |
504 | up(&host->mutex); | 1007 | " %d bytes, bus %s\n", bus->channel, addrdir, bus->mode, subsize, |
1008 | subaddr, len, bus->busnode->full_name); | ||
505 | 1009 | ||
506 | return 0; | 1010 | rc = bus->xfer(bus, addrdir, subsize, subaddr, data, len); |
1011 | |||
1012 | #ifdef DEBUG | ||
1013 | if (rc) | ||
1014 | DBG("xfer error %d\n", rc); | ||
1015 | #endif | ||
1016 | return rc; | ||
507 | } | 1017 | } |
508 | EXPORT_SYMBOL(pmac_low_i2c_close); | 1018 | EXPORT_SYMBOL_GPL(pmac_i2c_xfer); |
509 | 1019 | ||
510 | int pmac_low_i2c_setmode(struct device_node *np, int mode) | 1020 | /* |
1021 | * Initialize us: probe all i2c busses on the machine and instantiate | ||
1022 | * busses. | ||
1023 | */ | ||
1024 | /* This is non-static as it might be called early by smp code */ | ||
1025 | int __init pmac_i2c_init(void) | ||
511 | { | 1026 | { |
512 | struct low_i2c_host *host = find_low_i2c_host(np); | 1027 | static int i2c_inited; |
513 | 1028 | ||
514 | if (!host) | 1029 | if (i2c_inited) |
515 | return -ENODEV; | 1030 | return 0; |
516 | WARN_ON(!host->is_open); | 1031 | i2c_inited = 1; |
517 | host->mode = mode; | ||
518 | 1032 | ||
519 | return 0; | 1033 | /* Probe keywest-i2c busses */ |
520 | } | 1034 | kw_i2c_probe(); |
521 | EXPORT_SYMBOL(pmac_low_i2c_setmode); | ||
522 | 1035 | ||
523 | int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len) | 1036 | #ifdef CONFIG_ADB_PMU |
524 | { | 1037 | pmu_i2c_probe(); |
525 | struct low_i2c_host *host = find_low_i2c_host(np); | 1038 | #endif |
526 | 1039 | ||
527 | if (!host) | 1040 | #ifdef CONFIG_PMAC_SMU |
528 | return -ENODEV; | 1041 | smu_i2c_probe(); |
529 | WARN_ON(!host->is_open); | 1042 | #endif |
530 | 1043 | ||
531 | return host->func(host, addrdir, subaddr, data, len); | 1044 | return 0; |
532 | } | 1045 | } |
533 | EXPORT_SYMBOL(pmac_low_i2c_xfer); | 1046 | arch_initcall(pmac_i2c_init); |
534 | 1047 | ||
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index e5a5bdbdda7a..dc5cdc1484e8 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -652,27 +652,22 @@ static int __init pmac_declare_of_platform_devices(void) | |||
652 | { | 652 | { |
653 | struct device_node *np, *npp; | 653 | struct device_node *np, *npp; |
654 | 654 | ||
655 | np = find_devices("uni-n"); | 655 | np = of_find_node_by_name(NULL, "valkyrie"); |
656 | if (np) { | ||
657 | for (np = np->child; np != NULL; np = np->sibling) | ||
658 | if (strncmp(np->name, "i2c", 3) == 0) { | ||
659 | of_platform_device_create(np, "uni-n-i2c", | ||
660 | NULL); | ||
661 | break; | ||
662 | } | ||
663 | } | ||
664 | np = find_devices("valkyrie"); | ||
665 | if (np) | 656 | if (np) |
666 | of_platform_device_create(np, "valkyrie", NULL); | 657 | of_platform_device_create(np, "valkyrie", NULL); |
667 | np = find_devices("platinum"); | 658 | np = of_find_node_by_name(NULL, "platinum"); |
668 | if (np) | 659 | if (np) |
669 | of_platform_device_create(np, "platinum", NULL); | 660 | of_platform_device_create(np, "platinum", NULL); |
670 | 661 | npp = of_find_node_by_name(NULL, "uni-n"); | |
671 | npp = of_find_node_by_name(NULL, "u3"); | 662 | if (npp == NULL) |
663 | npp = of_find_node_by_name(NULL, "u3"); | ||
664 | if (npp == NULL) | ||
665 | npp = of_find_node_by_name(NULL, "u4"); | ||
672 | if (npp) { | 666 | if (npp) { |
673 | for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) { | 667 | for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) { |
674 | if (strncmp(np->name, "i2c", 3) == 0) { | 668 | if (strncmp(np->name, "i2c", 3) == 0) { |
675 | of_platform_device_create(np, "u3-i2c", NULL); | 669 | of_platform_device_create(np, "uni-n-i2c", |
670 | NULL); | ||
676 | of_node_put(np); | 671 | of_node_put(np); |
677 | break; | 672 | break; |
678 | } | 673 | } |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index df01bb8feb16..ab72ba86be1e 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -482,7 +482,7 @@ static void __devinit smp_core99_take_timebase(void) | |||
482 | /* | 482 | /* |
483 | * G5s enable/disable the timebase via an i2c-connected clock chip. | 483 | * G5s enable/disable the timebase via an i2c-connected clock chip. |
484 | */ | 484 | */ |
485 | static struct device_node *pmac_tb_clock_chip_host; | 485 | static struct pmac_i2c_bus *pmac_tb_clock_chip_host; |
486 | static u8 pmac_tb_pulsar_addr; | 486 | static u8 pmac_tb_pulsar_addr; |
487 | 487 | ||
488 | static void smp_core99_cypress_tb_freeze(int freeze) | 488 | static void smp_core99_cypress_tb_freeze(int freeze) |
@@ -493,20 +493,20 @@ static void smp_core99_cypress_tb_freeze(int freeze) | |||
493 | /* Strangely, the device-tree says address is 0xd2, but darwin | 493 | /* Strangely, the device-tree says address is 0xd2, but darwin |
494 | * accesses 0xd0 ... | 494 | * accesses 0xd0 ... |
495 | */ | 495 | */ |
496 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, | 496 | pmac_i2c_setmode(pmac_tb_clock_chip_host, |
497 | pmac_low_i2c_mode_combined); | 497 | pmac_i2c_mode_combined); |
498 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, | 498 | rc = pmac_i2c_xfer(pmac_tb_clock_chip_host, |
499 | 0xd0 | pmac_low_i2c_read, | 499 | 0xd0 | pmac_i2c_read, |
500 | 0x81, &data, 1); | 500 | 1, 0x81, &data, 1); |
501 | if (rc != 0) | 501 | if (rc != 0) |
502 | goto bail; | 502 | goto bail; |
503 | 503 | ||
504 | data = (data & 0xf3) | (freeze ? 0x00 : 0x0c); | 504 | data = (data & 0xf3) | (freeze ? 0x00 : 0x0c); |
505 | 505 | ||
506 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); | 506 | pmac_i2c_setmode(pmac_tb_clock_chip_host, pmac_i2c_mode_stdsub); |
507 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, | 507 | rc = pmac_i2c_xfer(pmac_tb_clock_chip_host, |
508 | 0xd0 | pmac_low_i2c_write, | 508 | 0xd0 | pmac_i2c_write, |
509 | 0x81, &data, 1); | 509 | 1, 0x81, &data, 1); |
510 | 510 | ||
511 | bail: | 511 | bail: |
512 | if (rc != 0) { | 512 | if (rc != 0) { |
@@ -522,20 +522,20 @@ static void smp_core99_pulsar_tb_freeze(int freeze) | |||
522 | u8 data; | 522 | u8 data; |
523 | int rc; | 523 | int rc; |
524 | 524 | ||
525 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, | 525 | pmac_i2c_setmode(pmac_tb_clock_chip_host, |
526 | pmac_low_i2c_mode_combined); | 526 | pmac_i2c_mode_combined); |
527 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, | 527 | rc = pmac_i2c_xfer(pmac_tb_clock_chip_host, |
528 | pmac_tb_pulsar_addr | pmac_low_i2c_read, | 528 | pmac_tb_pulsar_addr | pmac_i2c_read, |
529 | 0x2e, &data, 1); | 529 | 1, 0x2e, &data, 1); |
530 | if (rc != 0) | 530 | if (rc != 0) |
531 | goto bail; | 531 | goto bail; |
532 | 532 | ||
533 | data = (data & 0x88) | (freeze ? 0x11 : 0x22); | 533 | data = (data & 0x88) | (freeze ? 0x11 : 0x22); |
534 | 534 | ||
535 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); | 535 | pmac_i2c_setmode(pmac_tb_clock_chip_host, pmac_i2c_mode_stdsub); |
536 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, | 536 | rc = pmac_i2c_xfer(pmac_tb_clock_chip_host, |
537 | pmac_tb_pulsar_addr | pmac_low_i2c_write, | 537 | pmac_tb_pulsar_addr | pmac_i2c_write, |
538 | 0x2e, &data, 1); | 538 | 1, 0x2e, &data, 1); |
539 | bail: | 539 | bail: |
540 | if (rc != 0) { | 540 | if (rc != 0) { |
541 | printk(KERN_ERR "Pulsar Timebase %s rc: %d\n", | 541 | printk(KERN_ERR "Pulsar Timebase %s rc: %d\n", |
@@ -560,13 +560,15 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) | |||
560 | if (!ok) | 560 | if (!ok) |
561 | continue; | 561 | continue; |
562 | 562 | ||
563 | pmac_tb_clock_chip_host = pmac_i2c_find_bus(cc); | ||
564 | if (pmac_tb_clock_chip_host == NULL) | ||
565 | continue; | ||
563 | reg = (u32 *)get_property(cc, "reg", NULL); | 566 | reg = (u32 *)get_property(cc, "reg", NULL); |
564 | if (reg == NULL) | 567 | if (reg == NULL) |
565 | continue; | 568 | continue; |
566 | |||
567 | switch (*reg) { | 569 | switch (*reg) { |
568 | case 0xd2: | 570 | case 0xd2: |
569 | if (device_is_compatible(cc, "pulsar-legacy-slewing")) { | 571 | if (device_is_compatible(cc,"pulsar-legacy-slewing")) { |
570 | pmac_tb_freeze = smp_core99_pulsar_tb_freeze; | 572 | pmac_tb_freeze = smp_core99_pulsar_tb_freeze; |
571 | pmac_tb_pulsar_addr = 0xd2; | 573 | pmac_tb_pulsar_addr = 0xd2; |
572 | name = "Pulsar"; | 574 | name = "Pulsar"; |
@@ -585,30 +587,19 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) | |||
585 | break; | 587 | break; |
586 | } | 588 | } |
587 | if (pmac_tb_freeze != NULL) { | 589 | if (pmac_tb_freeze != NULL) { |
588 | struct device_node *p = of_get_parent(cc); | ||
589 | of_node_put(cc); | ||
590 | while(p && strcmp(p->type, "i2c")) { | ||
591 | cc = of_get_parent(p); | ||
592 | of_node_put(p); | ||
593 | p = cc; | ||
594 | } | ||
595 | if (p == NULL) | ||
596 | goto no_i2c_sync; | ||
597 | /* Open i2c bus for synchronous access */ | 590 | /* Open i2c bus for synchronous access */ |
598 | if (pmac_low_i2c_open(p, 0)) { | 591 | if (pmac_i2c_open(pmac_tb_clock_chip_host, 1)) { |
599 | printk(KERN_ERR "Failed top open i2c bus %s for clock" | 592 | printk(KERN_ERR "Failed top open i2c bus for clock" |
600 | " sync, fallback to software sync !\n", | 593 | " sync, fallback to software sync !\n"); |
601 | p->full_name); | ||
602 | of_node_put(p); | ||
603 | goto no_i2c_sync; | 594 | goto no_i2c_sync; |
604 | } | 595 | } |
605 | pmac_tb_clock_chip_host = p; | ||
606 | printk(KERN_INFO "Processor timebase sync using %s i2c clock\n", | 596 | printk(KERN_INFO "Processor timebase sync using %s i2c clock\n", |
607 | name); | 597 | name); |
608 | return; | 598 | return; |
609 | } | 599 | } |
610 | no_i2c_sync: | 600 | no_i2c_sync: |
611 | pmac_tb_freeze = NULL; | 601 | pmac_tb_freeze = NULL; |
602 | pmac_tb_clock_chip_host = NULL; | ||
612 | } | 603 | } |
613 | 604 | ||
614 | #endif /* CONFIG_PPC64 */ | 605 | #endif /* CONFIG_PPC64 */ |
@@ -752,8 +743,18 @@ static int __init smp_core99_probe(void) | |||
752 | if (ncpus <= 1) | 743 | if (ncpus <= 1) |
753 | return 1; | 744 | return 1; |
754 | 745 | ||
746 | /* We need to perform some early initialisations before we can start | ||
747 | * setting up SMP as we are running before initcalls | ||
748 | */ | ||
749 | pmac_i2c_init(); | ||
750 | |||
751 | /* Setup various bits like timebase sync method, ability to nap, ... */ | ||
755 | smp_core99_setup(ncpus); | 752 | smp_core99_setup(ncpus); |
753 | |||
754 | /* Install IPIs */ | ||
756 | mpic_request_ipis(); | 755 | mpic_request_ipis(); |
756 | |||
757 | /* Collect l2cr and l3cr values from CPU 0 */ | ||
757 | core99_init_caches(0); | 758 | core99_init_caches(0); |
758 | 759 | ||
759 | return ncpus; | 760 | return ncpus; |
@@ -817,7 +818,7 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr) | |||
817 | 818 | ||
818 | /* Close i2c bus if it was used for tb sync */ | 819 | /* Close i2c bus if it was used for tb sync */ |
819 | if (pmac_tb_clock_chip_host) { | 820 | if (pmac_tb_clock_chip_host) { |
820 | pmac_low_i2c_close(pmac_tb_clock_chip_host); | 821 | pmac_i2c_close(pmac_tb_clock_chip_host); |
821 | pmac_tb_clock_chip_host = NULL; | 822 | pmac_tb_clock_chip_host = NULL; |
822 | } | 823 | } |
823 | 824 | ||