diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/processor_idle.c | 10 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 15 | ||||
-rw-r--r-- | drivers/acpi/utilities/utobject.c | 2 | ||||
-rw-r--r-- | drivers/char/stallion.c | 7 | ||||
-rw-r--r-- | drivers/char/vt.c | 18 | ||||
-rw-r--r-- | drivers/hwmon/coretemp.c | 1 | ||||
-rw-r--r-- | drivers/macintosh/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mfd/sm501.c | 173 |
8 files changed, 191 insertions, 37 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index ee5759bef945..80ffc7829916 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -332,16 +332,18 @@ static void acpi_processor_idle(void) | |||
332 | int sleep_ticks = 0; | 332 | int sleep_ticks = 0; |
333 | u32 t1, t2 = 0; | 333 | u32 t1, t2 = 0; |
334 | 334 | ||
335 | pr = processors[smp_processor_id()]; | ||
336 | if (!pr) | ||
337 | return; | ||
338 | |||
339 | /* | 335 | /* |
340 | * Interrupts must be disabled during bus mastering calculations and | 336 | * Interrupts must be disabled during bus mastering calculations and |
341 | * for C2/C3 transitions. | 337 | * for C2/C3 transitions. |
342 | */ | 338 | */ |
343 | local_irq_disable(); | 339 | local_irq_disable(); |
344 | 340 | ||
341 | pr = processors[smp_processor_id()]; | ||
342 | if (!pr) { | ||
343 | local_irq_enable(); | ||
344 | return; | ||
345 | } | ||
346 | |||
345 | /* | 347 | /* |
346 | * Check whether we truly need to go idle, or should | 348 | * Check whether we truly need to go idle, or should |
347 | * reschedule: | 349 | * reschedule: |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 194ecfe8b360..88a6fc7fd271 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -828,6 +828,8 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) | |||
828 | { | 828 | { |
829 | struct acpi_thermal *tz = seq->private; | 829 | struct acpi_thermal *tz = seq->private; |
830 | struct acpi_device *device; | 830 | struct acpi_device *device; |
831 | acpi_status status; | ||
832 | |||
831 | int i = 0; | 833 | int i = 0; |
832 | int j = 0; | 834 | int j = 0; |
833 | 835 | ||
@@ -850,8 +852,10 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) | |||
850 | tz->trips.passive.tc1, tz->trips.passive.tc2, | 852 | tz->trips.passive.tc1, tz->trips.passive.tc2, |
851 | tz->trips.passive.tsp); | 853 | tz->trips.passive.tsp); |
852 | for (j = 0; j < tz->trips.passive.devices.count; j++) { | 854 | for (j = 0; j < tz->trips.passive.devices.count; j++) { |
853 | acpi_bus_get_device(tz->trips.passive.devices.handles[j], &device); | 855 | status = acpi_bus_get_device(tz->trips.passive.devices. |
854 | seq_printf(seq, "%4.4s ", acpi_device_bid(device)); | 856 | handles[j], &device); |
857 | seq_printf(seq, "%4.4s ", status ? "" : | ||
858 | acpi_device_bid(device)); | ||
855 | } | 859 | } |
856 | seq_puts(seq, "\n"); | 860 | seq_puts(seq, "\n"); |
857 | } | 861 | } |
@@ -863,8 +867,11 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) | |||
863 | i, | 867 | i, |
864 | KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); | 868 | KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); |
865 | for (j = 0; j < tz->trips.active[i].devices.count; j++){ | 869 | for (j = 0; j < tz->trips.active[i].devices.count; j++){ |
866 | acpi_bus_get_device(tz->trips.active[i].devices.handles[j], &device); | 870 | status = acpi_bus_get_device(tz->trips.active[i]. |
867 | seq_printf(seq, "%4.4s ", acpi_device_bid(device)); | 871 | devices.handles[j], |
872 | &device); | ||
873 | seq_printf(seq, "%4.4s ", status ? "" : | ||
874 | acpi_device_bid(device)); | ||
868 | } | 875 | } |
869 | seq_puts(seq, "\n"); | 876 | seq_puts(seq, "\n"); |
870 | } | 877 | } |
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index db0b9bac7945..76ee766c84f9 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c | |||
@@ -177,7 +177,7 @@ union acpi_operand_object *acpi_ut_create_package_object(u32 count) | |||
177 | package_elements = ACPI_ALLOCATE_ZEROED((acpi_size) | 177 | package_elements = ACPI_ALLOCATE_ZEROED((acpi_size) |
178 | (count + 1) * sizeof(void *)); | 178 | (count + 1) * sizeof(void *)); |
179 | if (!package_elements) { | 179 | if (!package_elements) { |
180 | ACPI_FREE(package_desc); | 180 | acpi_ut_remove_reference(package_desc); |
181 | return_PTR(NULL); | 181 | return_PTR(NULL); |
182 | } | 182 | } |
183 | 183 | ||
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 45bf2a262a85..8c73ccb8830f 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -4753,13 +4753,14 @@ static int __init stallion_module_init(void) | |||
4753 | brdp->ioaddr2 = conf.ioaddr2; | 4753 | brdp->ioaddr2 = conf.ioaddr2; |
4754 | brdp->irq = conf.irq; | 4754 | brdp->irq = conf.irq; |
4755 | brdp->irqtype = conf.irqtype; | 4755 | brdp->irqtype = conf.irqtype; |
4756 | if (stl_brdinit(brdp)) | 4756 | stl_brds[brdp->brdnr] = brdp; |
4757 | if (stl_brdinit(brdp)) { | ||
4758 | stl_brds[brdp->brdnr] = NULL; | ||
4757 | kfree(brdp); | 4759 | kfree(brdp); |
4758 | else { | 4760 | } else { |
4759 | for (j = 0; j < brdp->nrports; j++) | 4761 | for (j = 0; j < brdp->nrports; j++) |
4760 | tty_register_device(stl_serial, | 4762 | tty_register_device(stl_serial, |
4761 | brdp->brdnr * STL_MAXPORTS + j, NULL); | 4763 | brdp->brdnr * STL_MAXPORTS + j, NULL); |
4762 | stl_brds[brdp->brdnr] = brdp; | ||
4763 | stl_nrbrds = i + 1; | 4764 | stl_nrbrds = i + 1; |
4764 | } | 4765 | } |
4765 | } | 4766 | } |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index bbd9fc412877..6650ae1c088f 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -1956,7 +1956,7 @@ char con_buf[CON_BUF_SIZE]; | |||
1956 | DEFINE_MUTEX(con_buf_mtx); | 1956 | DEFINE_MUTEX(con_buf_mtx); |
1957 | 1957 | ||
1958 | /* is_double_width() is based on the wcwidth() implementation by | 1958 | /* is_double_width() is based on the wcwidth() implementation by |
1959 | * Markus Kuhn -- 2003-05-20 (Unicode 4.0) | 1959 | * Markus Kuhn -- 2007-05-26 (Unicode 5.0) |
1960 | * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c | 1960 | * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c |
1961 | */ | 1961 | */ |
1962 | struct interval { | 1962 | struct interval { |
@@ -1988,8 +1988,8 @@ static int is_double_width(uint32_t ucs) | |||
1988 | static const struct interval double_width[] = { | 1988 | static const struct interval double_width[] = { |
1989 | { 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E }, | 1989 | { 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E }, |
1990 | { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF }, | 1990 | { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF }, |
1991 | { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, { 0xFFE0, 0xFFE6 }, | 1991 | { 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, |
1992 | { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD } | 1992 | { 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD } |
1993 | }; | 1993 | }; |
1994 | return bisearch(ucs, double_width, | 1994 | return bisearch(ucs, double_width, |
1995 | sizeof(double_width) / sizeof(*double_width) - 1); | 1995 | sizeof(double_width) / sizeof(*double_width) - 1); |
@@ -2187,9 +2187,12 @@ rescan_last_byte: | |||
2187 | continue; /* nothing to display */ | 2187 | continue; /* nothing to display */ |
2188 | } | 2188 | } |
2189 | /* Glyph not found */ | 2189 | /* Glyph not found */ |
2190 | if (!(vc->vc_utf && !vc->vc_disp_ctrl) && !(c & ~charmask)) { | 2190 | if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { |
2191 | /* In legacy mode use the glyph we get by a 1:1 mapping. | 2191 | /* In legacy mode use the glyph we get by a 1:1 mapping. |
2192 | This would make absolutely no sense with Unicode in mind. */ | 2192 | This would make absolutely no sense with Unicode in mind, |
2193 | but do this for ASCII characters since a font may lack | ||
2194 | Unicode mapping info and we don't want to end up with | ||
2195 | having question marks only. */ | ||
2193 | tc = c; | 2196 | tc = c; |
2194 | } else { | 2197 | } else { |
2195 | /* Display U+FFFD. If it's not found, display an inverse question mark. */ | 2198 | /* Display U+FFFD. If it's not found, display an inverse question mark. */ |
@@ -2213,6 +2216,7 @@ rescan_last_byte: | |||
2213 | } else { | 2216 | } else { |
2214 | vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4); | 2217 | vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4); |
2215 | } | 2218 | } |
2219 | FLUSH | ||
2216 | } | 2220 | } |
2217 | 2221 | ||
2218 | while (1) { | 2222 | while (1) { |
@@ -2246,6 +2250,10 @@ rescan_last_byte: | |||
2246 | if (tc < 0) tc = ' '; | 2250 | if (tc < 0) tc = ' '; |
2247 | } | 2251 | } |
2248 | 2252 | ||
2253 | if (inverse) { | ||
2254 | FLUSH | ||
2255 | } | ||
2256 | |||
2249 | if (rescan) { | 2257 | if (rescan) { |
2250 | rescan = 0; | 2258 | rescan = 0; |
2251 | inverse = 0; | 2259 | inverse = 0; |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 0328382df8fa..6d54c8caed79 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -185,6 +185,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev) | |||
185 | /* check for microcode update */ | 185 | /* check for microcode update */ |
186 | rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx); | 186 | rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx); |
187 | if (edx < 0x39) { | 187 | if (edx < 0x39) { |
188 | err = -ENODEV; | ||
188 | dev_err(&pdev->dev, | 189 | dev_err(&pdev->dev, |
189 | "Errata AE18 not fixed, update BIOS or " | 190 | "Errata AE18 not fixed, update BIOS or " |
190 | "microcode of the CPU!\n"); | 191 | "microcode of the CPU!\n"); |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 0852d330c265..dbe96268866e 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | menuconfig MACINTOSH_DRIVERS | 2 | menuconfig MACINTOSH_DRIVERS |
3 | bool "Macintosh device drivers" | 3 | bool "Macintosh device drivers" |
4 | depends on PPC || MAC || X86 | 4 | depends on PPC || MAC || X86 |
5 | default y if MAC | 5 | default y if (PPC_PMAC || MAC) |
6 | 6 | ||
7 | if MACINTOSH_DRIVERS | 7 | if MACINTOSH_DRIVERS |
8 | 8 | ||
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index b0b4458ae90b..8135e4c3bf47 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
@@ -41,6 +41,9 @@ struct sm501_devdata { | |||
41 | struct resource *regs_claim; | 41 | struct resource *regs_claim; |
42 | struct sm501_platdata *platdata; | 42 | struct sm501_platdata *platdata; |
43 | 43 | ||
44 | unsigned int in_suspend; | ||
45 | unsigned long pm_misc; | ||
46 | |||
44 | int unit_power[20]; | 47 | int unit_power[20]; |
45 | unsigned int pdev_id; | 48 | unsigned int pdev_id; |
46 | unsigned int irq; | 49 | unsigned int irq; |
@@ -169,10 +172,41 @@ x "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n", | |||
169 | fmt_freq(decode_div(pll2, pm1, 8, 1<<12, 15, misc_div)), | 172 | fmt_freq(decode_div(pll2, pm1, 8, 1<<12, 15, misc_div)), |
170 | fmt_freq(decode_div(pll2, pm1, 0, 1<<4, 15, misc_div))); | 173 | fmt_freq(decode_div(pll2, pm1, 0, 1<<4, 15, misc_div))); |
171 | } | 174 | } |
172 | #else | 175 | |
173 | static void sm501_dump_clk(struct sm501_devdata *sm) | 176 | static void sm501_dump_regs(struct sm501_devdata *sm) |
174 | { | 177 | { |
178 | void __iomem *regs = sm->regs; | ||
179 | |||
180 | dev_info(sm->dev, "System Control %08x\n", | ||
181 | readl(regs + SM501_SYSTEM_CONTROL)); | ||
182 | dev_info(sm->dev, "Misc Control %08x\n", | ||
183 | readl(regs + SM501_MISC_CONTROL)); | ||
184 | dev_info(sm->dev, "GPIO Control Low %08x\n", | ||
185 | readl(regs + SM501_GPIO31_0_CONTROL)); | ||
186 | dev_info(sm->dev, "GPIO Control Hi %08x\n", | ||
187 | readl(regs + SM501_GPIO63_32_CONTROL)); | ||
188 | dev_info(sm->dev, "DRAM Control %08x\n", | ||
189 | readl(regs + SM501_DRAM_CONTROL)); | ||
190 | dev_info(sm->dev, "Arbitration Ctrl %08x\n", | ||
191 | readl(regs + SM501_ARBTRTN_CONTROL)); | ||
192 | dev_info(sm->dev, "Misc Timing %08x\n", | ||
193 | readl(regs + SM501_MISC_TIMING)); | ||
175 | } | 194 | } |
195 | |||
196 | static void sm501_dump_gate(struct sm501_devdata *sm) | ||
197 | { | ||
198 | dev_info(sm->dev, "CurrentGate %08x\n", | ||
199 | readl(sm->regs + SM501_CURRENT_GATE)); | ||
200 | dev_info(sm->dev, "CurrentClock %08x\n", | ||
201 | readl(sm->regs + SM501_CURRENT_CLOCK)); | ||
202 | dev_info(sm->dev, "PowerModeControl %08x\n", | ||
203 | readl(sm->regs + SM501_POWER_MODE_CONTROL)); | ||
204 | } | ||
205 | |||
206 | #else | ||
207 | static inline void sm501_dump_gate(struct sm501_devdata *sm) { } | ||
208 | static inline void sm501_dump_regs(struct sm501_devdata *sm) { } | ||
209 | static inline void sm501_dump_clk(struct sm501_devdata *sm) { } | ||
176 | #endif | 210 | #endif |
177 | 211 | ||
178 | /* sm501_sync_regs | 212 | /* sm501_sync_regs |
@@ -185,9 +219,21 @@ static void sm501_sync_regs(struct sm501_devdata *sm) | |||
185 | readl(sm->regs); | 219 | readl(sm->regs); |
186 | } | 220 | } |
187 | 221 | ||
222 | static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay) | ||
223 | { | ||
224 | /* during suspend/resume, we are currently not allowed to sleep, | ||
225 | * so change to using mdelay() instead of msleep() if we | ||
226 | * are in one of these paths */ | ||
227 | |||
228 | if (sm->in_suspend) | ||
229 | mdelay(delay); | ||
230 | else | ||
231 | msleep(delay); | ||
232 | } | ||
233 | |||
188 | /* sm501_misc_control | 234 | /* sm501_misc_control |
189 | * | 235 | * |
190 | * alters the misceleneous control parameters | 236 | * alters the miscellaneous control parameters |
191 | */ | 237 | */ |
192 | 238 | ||
193 | int sm501_misc_control(struct device *dev, | 239 | int sm501_misc_control(struct device *dev, |
@@ -368,7 +414,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to) | |||
368 | dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n", | 414 | dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n", |
369 | gate, clock, mode); | 415 | gate, clock, mode); |
370 | 416 | ||
371 | msleep(16); | 417 | sm501_mdelay(sm, 16); |
372 | 418 | ||
373 | already: | 419 | already: |
374 | mutex_unlock(&sm->clock_lock); | 420 | mutex_unlock(&sm->clock_lock); |
@@ -538,7 +584,7 @@ unsigned long sm501_set_clock(struct device *dev, | |||
538 | dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n", | 584 | dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n", |
539 | gate, clock, mode); | 585 | gate, clock, mode); |
540 | 586 | ||
541 | msleep(16); | 587 | sm501_mdelay(sm, 16); |
542 | mutex_unlock(&sm->clock_lock); | 588 | mutex_unlock(&sm->clock_lock); |
543 | 589 | ||
544 | sm501_dump_clk(sm); | 590 | sm501_dump_clk(sm); |
@@ -767,6 +813,9 @@ static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL); | |||
767 | /* sm501_init_reg | 813 | /* sm501_init_reg |
768 | * | 814 | * |
769 | * Helper function for the init code to setup a register | 815 | * Helper function for the init code to setup a register |
816 | * | ||
817 | * clear the bits which are set in r->mask, and then set | ||
818 | * the bits set in r->set. | ||
770 | */ | 819 | */ |
771 | 820 | ||
772 | static inline void sm501_init_reg(struct sm501_devdata *sm, | 821 | static inline void sm501_init_reg(struct sm501_devdata *sm, |
@@ -776,8 +825,8 @@ static inline void sm501_init_reg(struct sm501_devdata *sm, | |||
776 | unsigned long tmp; | 825 | unsigned long tmp; |
777 | 826 | ||
778 | tmp = readl(sm->regs + reg); | 827 | tmp = readl(sm->regs + reg); |
779 | tmp |= r->set; | ||
780 | tmp &= ~r->mask; | 828 | tmp &= ~r->mask; |
829 | tmp |= r->set; | ||
781 | writel(tmp, sm->regs + reg); | 830 | writel(tmp, sm->regs + reg); |
782 | } | 831 | } |
783 | 832 | ||
@@ -797,15 +846,33 @@ static void sm501_init_regs(struct sm501_devdata *sm, | |||
797 | sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low); | 846 | sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low); |
798 | sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high); | 847 | sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high); |
799 | 848 | ||
849 | if (init->m1xclk) { | ||
850 | dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk); | ||
851 | sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk); | ||
852 | } | ||
853 | |||
800 | if (init->mclk) { | 854 | if (init->mclk) { |
801 | dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk); | 855 | dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk); |
802 | sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk); | 856 | sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk); |
803 | } | 857 | } |
804 | 858 | ||
805 | if (init->m1xclk) { | 859 | } |
806 | dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk); | 860 | |
807 | sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk); | 861 | /* Check the PLL sources for the M1CLK and M1XCLK |
808 | } | 862 | * |
863 | * If the M1CLK and M1XCLKs are not sourced from the same PLL, then | ||
864 | * there is a risk (see errata AB-5) that the SM501 will cease proper | ||
865 | * function. If this happens, then it is likely the SM501 will | ||
866 | * hang the system. | ||
867 | */ | ||
868 | |||
869 | static int sm501_check_clocks(struct sm501_devdata *sm) | ||
870 | { | ||
871 | unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK); | ||
872 | unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC); | ||
873 | unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC); | ||
874 | |||
875 | return ((msrc == 0 && m1src != 0) || (msrc != 0 && m1src == 0)); | ||
809 | } | 876 | } |
810 | 877 | ||
811 | static unsigned int sm501_mem_local[] = { | 878 | static unsigned int sm501_mem_local[] = { |
@@ -826,6 +893,7 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
826 | { | 893 | { |
827 | resource_size_t mem_avail; | 894 | resource_size_t mem_avail; |
828 | unsigned long dramctrl; | 895 | unsigned long dramctrl; |
896 | unsigned long devid; | ||
829 | int ret; | 897 | int ret; |
830 | 898 | ||
831 | mutex_init(&sm->clock_lock); | 899 | mutex_init(&sm->clock_lock); |
@@ -833,17 +901,20 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
833 | 901 | ||
834 | INIT_LIST_HEAD(&sm->devices); | 902 | INIT_LIST_HEAD(&sm->devices); |
835 | 903 | ||
836 | dramctrl = readl(sm->regs + SM501_DRAM_CONTROL); | 904 | devid = readl(sm->regs + SM501_DEVICEID); |
905 | |||
906 | if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) { | ||
907 | dev_err(sm->dev, "incorrect device id %08lx\n", devid); | ||
908 | return -EINVAL; | ||
909 | } | ||
837 | 910 | ||
911 | dramctrl = readl(sm->regs + SM501_DRAM_CONTROL); | ||
838 | mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7]; | 912 | mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7]; |
839 | 913 | ||
840 | dev_info(sm->dev, "SM501 At %p: Version %08x, %ld Mb, IRQ %d\n", | 914 | dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n", |
841 | sm->regs, readl(sm->regs + SM501_DEVICEID), | 915 | sm->regs, devid, (unsigned long)mem_avail >> 20, sm->irq); |
842 | (unsigned long)mem_avail >> 20, sm->irq); | ||
843 | 916 | ||
844 | dev_info(sm->dev, "CurrentGate %08x\n", readl(sm->regs+0x38)); | 917 | sm501_dump_gate(sm); |
845 | dev_info(sm->dev, "CurrentClock %08x\n", readl(sm->regs+0x3c)); | ||
846 | dev_info(sm->dev, "PowerModeControl %08x\n", readl(sm->regs+0x54)); | ||
847 | 918 | ||
848 | ret = device_create_file(sm->dev, &dev_attr_dbg_regs); | 919 | ret = device_create_file(sm->dev, &dev_attr_dbg_regs); |
849 | if (ret) | 920 | if (ret) |
@@ -864,6 +935,13 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
864 | } | 935 | } |
865 | } | 936 | } |
866 | 937 | ||
938 | ret = sm501_check_clocks(sm); | ||
939 | if (ret) { | ||
940 | dev_err(sm->dev, "M1X and M clocks sourced from different " | ||
941 | "PLLs\n"); | ||
942 | return -EINVAL; | ||
943 | } | ||
944 | |||
867 | /* always create a framebuffer */ | 945 | /* always create a framebuffer */ |
868 | sm501_register_display(sm, &mem_avail); | 946 | sm501_register_display(sm, &mem_avail); |
869 | 947 | ||
@@ -933,6 +1011,57 @@ static int sm501_plat_probe(struct platform_device *dev) | |||
933 | 1011 | ||
934 | } | 1012 | } |
935 | 1013 | ||
1014 | #ifdef CONFIG_PM | ||
1015 | /* power management support */ | ||
1016 | |||
1017 | static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state) | ||
1018 | { | ||
1019 | struct sm501_devdata *sm = platform_get_drvdata(pdev); | ||
1020 | |||
1021 | sm->in_suspend = 1; | ||
1022 | sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL); | ||
1023 | |||
1024 | sm501_dump_regs(sm); | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int sm501_plat_resume(struct platform_device *pdev) | ||
1029 | { | ||
1030 | struct sm501_devdata *sm = platform_get_drvdata(pdev); | ||
1031 | |||
1032 | sm501_dump_regs(sm); | ||
1033 | sm501_dump_gate(sm); | ||
1034 | sm501_dump_clk(sm); | ||
1035 | |||
1036 | /* check to see if we are in the same state as when suspended */ | ||
1037 | |||
1038 | if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) { | ||
1039 | dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n"); | ||
1040 | writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL); | ||
1041 | |||
1042 | /* our suspend causes the controller state to change, | ||
1043 | * either by something attempting setup, power loss, | ||
1044 | * or an external reset event on power change */ | ||
1045 | |||
1046 | if (sm->platdata && sm->platdata->init) { | ||
1047 | sm501_init_regs(sm, sm->platdata->init); | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | /* dump our state from resume */ | ||
1052 | |||
1053 | sm501_dump_regs(sm); | ||
1054 | sm501_dump_clk(sm); | ||
1055 | |||
1056 | sm->in_suspend = 0; | ||
1057 | |||
1058 | return 0; | ||
1059 | } | ||
1060 | #else | ||
1061 | #define sm501_plat_suspend NULL | ||
1062 | #define sm501_plat_resume NULL | ||
1063 | #endif | ||
1064 | |||
936 | /* Initialisation data for PCI devices */ | 1065 | /* Initialisation data for PCI devices */ |
937 | 1066 | ||
938 | static struct sm501_initdata sm501_pci_initdata = { | 1067 | static struct sm501_initdata sm501_pci_initdata = { |
@@ -950,8 +1079,12 @@ static struct sm501_initdata sm501_pci_initdata = { | |||
950 | }, | 1079 | }, |
951 | 1080 | ||
952 | .devices = SM501_USE_ALL, | 1081 | .devices = SM501_USE_ALL, |
953 | .mclk = 100 * MHZ, | 1082 | |
954 | .m1xclk = 160 * MHZ, | 1083 | /* Errata AB-3 says that 72MHz is the fastest available |
1084 | * for 33MHZ PCI with proper bus-mastering operation */ | ||
1085 | |||
1086 | .mclk = 72 * MHZ, | ||
1087 | .m1xclk = 144 * MHZ, | ||
955 | }; | 1088 | }; |
956 | 1089 | ||
957 | static struct sm501_platdata_fbsub sm501_pdata_fbsub = { | 1090 | static struct sm501_platdata_fbsub sm501_pdata_fbsub = { |
@@ -1126,6 +1259,8 @@ static struct platform_driver sm501_plat_drv = { | |||
1126 | }, | 1259 | }, |
1127 | .probe = sm501_plat_probe, | 1260 | .probe = sm501_plat_probe, |
1128 | .remove = sm501_plat_remove, | 1261 | .remove = sm501_plat_remove, |
1262 | .suspend = sm501_plat_suspend, | ||
1263 | .resume = sm501_plat_resume, | ||
1129 | }; | 1264 | }; |
1130 | 1265 | ||
1131 | static int __init sm501_base_init(void) | 1266 | static int __init sm501_base_init(void) |