Commit c95d1e53ed89b75a4d7b68d1cbae4607b1479243
Committed by
Linus Torvalds
1 parent
f3a57a60d3
Exists in
master
and in
7 other branches
cs5535: drop the Geode-specific MFGPT/GPIO code
With generic modular drivers handling all of this stuff, the geode-specific code can go away. The cs5535-gpio, cs5535-mfgpt, and cs5535-clockevt drivers now handle this. Signed-off-by: Andres Salomon <dilinger@collabora.co.uk> Cc: Jordan Crouse <jordan@cosmicpenguin.net> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: john stultz <johnstul@us.ibm.com> Cc: Chris Ball <cjb@laptop.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 7 changed files with 2 additions and 714 deletions Side-by-side Diff
arch/x86/Kconfig
... | ... | @@ -2012,16 +2012,6 @@ |
2012 | 2012 | processor goes idle (as is done by the scheduler). The |
2013 | 2013 | other workaround is idle=poll boot option. |
2014 | 2014 | |
2015 | -config GEODE_MFGPT_TIMER | |
2016 | - def_bool y | |
2017 | - prompt "Geode Multi-Function General Purpose Timer (MFGPT) events" | |
2018 | - depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS | |
2019 | - ---help--- | |
2020 | - This driver provides a clock event source based on the MFGPT | |
2021 | - timer(s) in the CS5535 and CS5536 companion chip for the geode. | |
2022 | - MFGPTs have a better resolution and max interval than the | |
2023 | - generic PIT, and are suitable for use as high-res timers. | |
2024 | - | |
2025 | 2015 | config OLPC |
2026 | 2016 | bool "One Laptop Per Child support" |
2027 | 2017 | select GPIOLIB |
arch/x86/include/asm/geode.h
... | ... | @@ -14,98 +14,6 @@ |
14 | 14 | #include <linux/io.h> |
15 | 15 | #include <linux/cs5535.h> |
16 | 16 | |
17 | -/* Generic southbridge functions */ | |
18 | - | |
19 | -#define GEODE_DEV_PMS 0 | |
20 | -#define GEODE_DEV_ACPI 1 | |
21 | -#define GEODE_DEV_GPIO 2 | |
22 | -#define GEODE_DEV_MFGPT 3 | |
23 | - | |
24 | -extern int geode_get_dev_base(unsigned int dev); | |
25 | - | |
26 | -/* Useful macros */ | |
27 | -#define geode_pms_base() geode_get_dev_base(GEODE_DEV_PMS) | |
28 | -#define geode_acpi_base() geode_get_dev_base(GEODE_DEV_ACPI) | |
29 | -#define geode_gpio_base() geode_get_dev_base(GEODE_DEV_GPIO) | |
30 | -#define geode_mfgpt_base() geode_get_dev_base(GEODE_DEV_MFGPT) | |
31 | - | |
32 | -/* MSRS */ | |
33 | - | |
34 | -#define MSR_LBAR_SMB 0x5140000B | |
35 | -#define MSR_LBAR_GPIO 0x5140000C | |
36 | -#define MSR_LBAR_MFGPT 0x5140000D | |
37 | -#define MSR_LBAR_ACPI 0x5140000E | |
38 | -#define MSR_LBAR_PMS 0x5140000F | |
39 | - | |
40 | -/* Resource Sizes */ | |
41 | - | |
42 | -#define LBAR_GPIO_SIZE 0xFF | |
43 | -#define LBAR_MFGPT_SIZE 0x40 | |
44 | -#define LBAR_ACPI_SIZE 0x40 | |
45 | -#define LBAR_PMS_SIZE 0x80 | |
46 | - | |
47 | -/* ACPI registers (PMS block) */ | |
48 | - | |
49 | -/* | |
50 | - * PM1_EN is only valid when VSA is enabled for 16 bit reads. | |
51 | - * When VSA is not enabled, *always* read both PM1_STS and PM1_EN | |
52 | - * with a 32 bit read at offset 0x0 | |
53 | - */ | |
54 | - | |
55 | -#define PM1_STS 0x00 | |
56 | -#define PM1_EN 0x02 | |
57 | -#define PM1_CNT 0x08 | |
58 | -#define PM2_CNT 0x0C | |
59 | -#define PM_TMR 0x10 | |
60 | -#define PM_GPE0_STS 0x18 | |
61 | -#define PM_GPE0_EN 0x1C | |
62 | - | |
63 | -/* PMC registers (PMS block) */ | |
64 | - | |
65 | -#define PM_SSD 0x00 | |
66 | -#define PM_SCXA 0x04 | |
67 | -#define PM_SCYA 0x08 | |
68 | -#define PM_OUT_SLPCTL 0x0C | |
69 | -#define PM_SCLK 0x10 | |
70 | -#define PM_SED 0x1 | |
71 | -#define PM_SCXD 0x18 | |
72 | -#define PM_SCYD 0x1C | |
73 | -#define PM_IN_SLPCTL 0x20 | |
74 | -#define PM_WKD 0x30 | |
75 | -#define PM_WKXD 0x34 | |
76 | -#define PM_RD 0x38 | |
77 | -#define PM_WKXA 0x3C | |
78 | -#define PM_FSD 0x40 | |
79 | -#define PM_TSD 0x44 | |
80 | -#define PM_PSD 0x48 | |
81 | -#define PM_NWKD 0x4C | |
82 | -#define PM_AWKD 0x50 | |
83 | -#define PM_SSC 0x54 | |
84 | - | |
85 | -static inline u32 geode_gpio(unsigned int nr) | |
86 | -{ | |
87 | - BUG_ON(nr > 28); | |
88 | - return 1 << nr; | |
89 | -} | |
90 | - | |
91 | -extern void geode_gpio_set(u32, unsigned int); | |
92 | -extern void geode_gpio_clear(u32, unsigned int); | |
93 | -extern int geode_gpio_isset(u32, unsigned int); | |
94 | -extern void geode_gpio_setup_event(unsigned int, int, int); | |
95 | -extern void geode_gpio_set_irq(unsigned int, unsigned int); | |
96 | - | |
97 | -static inline void geode_gpio_event_irq(unsigned int gpio, int pair) | |
98 | -{ | |
99 | - geode_gpio_setup_event(gpio, pair, 0); | |
100 | -} | |
101 | - | |
102 | -static inline void geode_gpio_event_pme(unsigned int gpio, int pair) | |
103 | -{ | |
104 | - geode_gpio_setup_event(gpio, pair, 1); | |
105 | -} | |
106 | - | |
107 | -/* Specific geode tests */ | |
108 | - | |
109 | 17 | static inline int is_geode_gx(void) |
110 | 18 | { |
111 | 19 | return ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC) && |
... | ... | @@ -124,31 +32,6 @@ |
124 | 32 | { |
125 | 33 | return (is_geode_gx() || is_geode_lx()); |
126 | 34 | } |
127 | - | |
128 | -static inline void geode_mfgpt_write(int timer, u16 reg, u16 value) | |
129 | -{ | |
130 | - u32 base = geode_get_dev_base(GEODE_DEV_MFGPT); | |
131 | - outw(value, base + reg + (timer * 8)); | |
132 | -} | |
133 | - | |
134 | -static inline u16 geode_mfgpt_read(int timer, u16 reg) | |
135 | -{ | |
136 | - u32 base = geode_get_dev_base(GEODE_DEV_MFGPT); | |
137 | - return inw(base + reg + (timer * 8)); | |
138 | -} | |
139 | - | |
140 | -extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable); | |
141 | -extern int geode_mfgpt_set_irq(int timer, int cmp, int *irq, int enable); | |
142 | -extern int geode_mfgpt_alloc_timer(int timer, int domain); | |
143 | - | |
144 | -#define geode_mfgpt_setup_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 1) | |
145 | -#define geode_mfgpt_release_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 0) | |
146 | - | |
147 | -#ifdef CONFIG_GEODE_MFGPT_TIMER | |
148 | -extern int __init mfgpt_timer_setup(void); | |
149 | -#else | |
150 | -static inline int mfgpt_timer_setup(void) { return 0; } | |
151 | -#endif | |
152 | 35 | |
153 | 36 | #endif /* _ASM_X86_GEODE_H */ |
arch/x86/kernel/Makefile
arch/x86/kernel/geode_32.c
1 | -/* | |
2 | - * AMD Geode southbridge support code | |
3 | - * Copyright (C) 2006, Advanced Micro Devices, Inc. | |
4 | - * Copyright (C) 2007, Andres Salomon <dilinger@debian.org> | |
5 | - * | |
6 | - * This program is free software; you can redistribute it and/or | |
7 | - * modify it under the terms of version 2 of the GNU General Public License | |
8 | - * as published by the Free Software Foundation. | |
9 | - */ | |
10 | - | |
11 | -#include <linux/kernel.h> | |
12 | -#include <linux/module.h> | |
13 | -#include <linux/ioport.h> | |
14 | -#include <linux/io.h> | |
15 | -#include <asm/msr.h> | |
16 | -#include <asm/geode.h> | |
17 | - | |
18 | -static struct { | |
19 | - char *name; | |
20 | - u32 msr; | |
21 | - int size; | |
22 | - u32 base; | |
23 | -} lbars[] = { | |
24 | - { "geode-pms", MSR_LBAR_PMS, LBAR_PMS_SIZE, 0 }, | |
25 | - { "geode-acpi", MSR_LBAR_ACPI, LBAR_ACPI_SIZE, 0 }, | |
26 | - { "geode-gpio", MSR_LBAR_GPIO, LBAR_GPIO_SIZE, 0 }, | |
27 | - { "geode-mfgpt", MSR_LBAR_MFGPT, LBAR_MFGPT_SIZE, 0 } | |
28 | -}; | |
29 | - | |
30 | -static void __init init_lbars(void) | |
31 | -{ | |
32 | - u32 lo, hi; | |
33 | - int i; | |
34 | - | |
35 | - for (i = 0; i < ARRAY_SIZE(lbars); i++) { | |
36 | - rdmsr(lbars[i].msr, lo, hi); | |
37 | - if (hi & 0x01) | |
38 | - lbars[i].base = lo & 0x0000ffff; | |
39 | - | |
40 | - if (lbars[i].base == 0) | |
41 | - printk(KERN_ERR "geode: Couldn't initialize '%s'\n", | |
42 | - lbars[i].name); | |
43 | - } | |
44 | -} | |
45 | - | |
46 | -int geode_get_dev_base(unsigned int dev) | |
47 | -{ | |
48 | - BUG_ON(dev >= ARRAY_SIZE(lbars)); | |
49 | - return lbars[dev].base; | |
50 | -} | |
51 | -EXPORT_SYMBOL_GPL(geode_get_dev_base); | |
52 | - | |
53 | -/* === GPIO API === */ | |
54 | - | |
55 | -void geode_gpio_set(u32 gpio, unsigned int reg) | |
56 | -{ | |
57 | - u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | |
58 | - | |
59 | - if (!base) | |
60 | - return; | |
61 | - | |
62 | - /* low bank register */ | |
63 | - if (gpio & 0xFFFF) | |
64 | - outl(gpio & 0xFFFF, base + reg); | |
65 | - /* high bank register */ | |
66 | - gpio >>= 16; | |
67 | - if (gpio) | |
68 | - outl(gpio, base + 0x80 + reg); | |
69 | -} | |
70 | -EXPORT_SYMBOL_GPL(geode_gpio_set); | |
71 | - | |
72 | -void geode_gpio_clear(u32 gpio, unsigned int reg) | |
73 | -{ | |
74 | - u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | |
75 | - | |
76 | - if (!base) | |
77 | - return; | |
78 | - | |
79 | - /* low bank register */ | |
80 | - if (gpio & 0xFFFF) | |
81 | - outl((gpio & 0xFFFF) << 16, base + reg); | |
82 | - /* high bank register */ | |
83 | - gpio &= (0xFFFF << 16); | |
84 | - if (gpio) | |
85 | - outl(gpio, base + 0x80 + reg); | |
86 | -} | |
87 | -EXPORT_SYMBOL_GPL(geode_gpio_clear); | |
88 | - | |
89 | -int geode_gpio_isset(u32 gpio, unsigned int reg) | |
90 | -{ | |
91 | - u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | |
92 | - u32 val; | |
93 | - | |
94 | - if (!base) | |
95 | - return 0; | |
96 | - | |
97 | - /* low bank register */ | |
98 | - if (gpio & 0xFFFF) { | |
99 | - val = inl(base + reg) & (gpio & 0xFFFF); | |
100 | - if ((gpio & 0xFFFF) == val) | |
101 | - return 1; | |
102 | - } | |
103 | - /* high bank register */ | |
104 | - gpio >>= 16; | |
105 | - if (gpio) { | |
106 | - val = inl(base + 0x80 + reg) & gpio; | |
107 | - if (gpio == val) | |
108 | - return 1; | |
109 | - } | |
110 | - return 0; | |
111 | -} | |
112 | -EXPORT_SYMBOL_GPL(geode_gpio_isset); | |
113 | - | |
114 | -void geode_gpio_set_irq(unsigned int group, unsigned int irq) | |
115 | -{ | |
116 | - u32 lo, hi; | |
117 | - | |
118 | - if (group > 7 || irq > 15) | |
119 | - return; | |
120 | - | |
121 | - rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi); | |
122 | - | |
123 | - lo &= ~(0xF << (group * 4)); | |
124 | - lo |= (irq & 0xF) << (group * 4); | |
125 | - | |
126 | - wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi); | |
127 | -} | |
128 | -EXPORT_SYMBOL_GPL(geode_gpio_set_irq); | |
129 | - | |
130 | -void geode_gpio_setup_event(unsigned int gpio, int pair, int pme) | |
131 | -{ | |
132 | - u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | |
133 | - u32 offset, shift, val; | |
134 | - | |
135 | - if (gpio >= 24) | |
136 | - offset = GPIO_MAP_W; | |
137 | - else if (gpio >= 16) | |
138 | - offset = GPIO_MAP_Z; | |
139 | - else if (gpio >= 8) | |
140 | - offset = GPIO_MAP_Y; | |
141 | - else | |
142 | - offset = GPIO_MAP_X; | |
143 | - | |
144 | - shift = (gpio % 8) * 4; | |
145 | - | |
146 | - val = inl(base + offset); | |
147 | - | |
148 | - /* Clear whatever was there before */ | |
149 | - val &= ~(0xF << shift); | |
150 | - | |
151 | - /* And set the new value */ | |
152 | - | |
153 | - val |= ((pair & 7) << shift); | |
154 | - | |
155 | - /* Set the PME bit if this is a PME event */ | |
156 | - | |
157 | - if (pme) | |
158 | - val |= (1 << (shift + 3)); | |
159 | - | |
160 | - outl(val, base + offset); | |
161 | -} | |
162 | -EXPORT_SYMBOL_GPL(geode_gpio_setup_event); | |
163 | - | |
164 | -static int __init geode_southbridge_init(void) | |
165 | -{ | |
166 | - if (!is_geode()) | |
167 | - return -ENODEV; | |
168 | - | |
169 | - init_lbars(); | |
170 | - (void) mfgpt_timer_setup(); | |
171 | - return 0; | |
172 | -} | |
173 | - | |
174 | -postcore_initcall(geode_southbridge_init); |
arch/x86/kernel/mfgpt_32.c
1 | -/* | |
2 | - * Driver/API for AMD Geode Multi-Function General Purpose Timers (MFGPT) | |
3 | - * | |
4 | - * Copyright (C) 2006, Advanced Micro Devices, Inc. | |
5 | - * Copyright (C) 2007, Andres Salomon <dilinger@debian.org> | |
6 | - * | |
7 | - * This program is free software; you can redistribute it and/or | |
8 | - * modify it under the terms of version 2 of the GNU General Public License | |
9 | - * as published by the Free Software Foundation. | |
10 | - * | |
11 | - * The MFGPTs are documented in AMD Geode CS5536 Companion Device Data Book. | |
12 | - */ | |
13 | - | |
14 | -/* | |
15 | - * We are using the 32.768kHz input clock - it's the only one that has the | |
16 | - * ranges we find desirable. The following table lists the suitable | |
17 | - * divisors and the associated Hz, minimum interval and the maximum interval: | |
18 | - * | |
19 | - * Divisor Hz Min Delta (s) Max Delta (s) | |
20 | - * 1 32768 .00048828125 2.000 | |
21 | - * 2 16384 .0009765625 4.000 | |
22 | - * 4 8192 .001953125 8.000 | |
23 | - * 8 4096 .00390625 16.000 | |
24 | - * 16 2048 .0078125 32.000 | |
25 | - * 32 1024 .015625 64.000 | |
26 | - * 64 512 .03125 128.000 | |
27 | - * 128 256 .0625 256.000 | |
28 | - * 256 128 .125 512.000 | |
29 | - */ | |
30 | - | |
31 | -#include <linux/kernel.h> | |
32 | -#include <linux/interrupt.h> | |
33 | -#include <linux/module.h> | |
34 | -#include <asm/geode.h> | |
35 | - | |
36 | -#define MFGPT_DEFAULT_IRQ 7 | |
37 | - | |
38 | -static struct mfgpt_timer_t { | |
39 | - unsigned int avail:1; | |
40 | -} mfgpt_timers[MFGPT_MAX_TIMERS]; | |
41 | - | |
42 | -/* Selected from the table above */ | |
43 | - | |
44 | -#define MFGPT_DIVISOR 16 | |
45 | -#define MFGPT_SCALE 4 /* divisor = 2^(scale) */ | |
46 | -#define MFGPT_HZ (32768 / MFGPT_DIVISOR) | |
47 | -#define MFGPT_PERIODIC (MFGPT_HZ / HZ) | |
48 | - | |
49 | -/* Allow for disabling of MFGPTs */ | |
50 | -static int disable; | |
51 | -static int __init mfgpt_disable(char *s) | |
52 | -{ | |
53 | - disable = 1; | |
54 | - return 1; | |
55 | -} | |
56 | -__setup("nomfgpt", mfgpt_disable); | |
57 | - | |
58 | -/* Reset the MFGPT timers. This is required by some broken BIOSes which already | |
59 | - * do the same and leave the system in an unstable state. TinyBIOS 0.98 is | |
60 | - * affected at least (0.99 is OK with MFGPT workaround left to off). | |
61 | - */ | |
62 | -static int __init mfgpt_fix(char *s) | |
63 | -{ | |
64 | - u32 val, dummy; | |
65 | - | |
66 | - /* The following udocumented bit resets the MFGPT timers */ | |
67 | - val = 0xFF; dummy = 0; | |
68 | - wrmsr(MSR_MFGPT_SETUP, val, dummy); | |
69 | - return 1; | |
70 | -} | |
71 | -__setup("mfgptfix", mfgpt_fix); | |
72 | - | |
73 | -/* | |
74 | - * Check whether any MFGPTs are available for the kernel to use. In most | |
75 | - * cases, firmware that uses AMD's VSA code will claim all timers during | |
76 | - * bootup; we certainly don't want to take them if they're already in use. | |
77 | - * In other cases (such as with VSAless OpenFirmware), the system firmware | |
78 | - * leaves timers available for us to use. | |
79 | - */ | |
80 | - | |
81 | - | |
82 | -static int timers = -1; | |
83 | - | |
84 | -static void geode_mfgpt_detect(void) | |
85 | -{ | |
86 | - int i; | |
87 | - u16 val; | |
88 | - | |
89 | - timers = 0; | |
90 | - | |
91 | - if (disable) { | |
92 | - printk(KERN_INFO "geode-mfgpt: MFGPT support is disabled\n"); | |
93 | - goto done; | |
94 | - } | |
95 | - | |
96 | - if (!geode_get_dev_base(GEODE_DEV_MFGPT)) { | |
97 | - printk(KERN_INFO "geode-mfgpt: MFGPT LBAR is not set up\n"); | |
98 | - goto done; | |
99 | - } | |
100 | - | |
101 | - for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | |
102 | - val = geode_mfgpt_read(i, MFGPT_REG_SETUP); | |
103 | - if (!(val & MFGPT_SETUP_SETUP)) { | |
104 | - mfgpt_timers[i].avail = 1; | |
105 | - timers++; | |
106 | - } | |
107 | - } | |
108 | - | |
109 | -done: | |
110 | - printk(KERN_INFO "geode-mfgpt: %d MFGPT timers available.\n", timers); | |
111 | -} | |
112 | - | |
113 | -int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable) | |
114 | -{ | |
115 | - u32 msr, mask, value, dummy; | |
116 | - int shift = (cmp == MFGPT_CMP1) ? 0 : 8; | |
117 | - | |
118 | - if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | |
119 | - return -EIO; | |
120 | - | |
121 | - /* | |
122 | - * The register maps for these are described in sections 6.17.1.x of | |
123 | - * the AMD Geode CS5536 Companion Device Data Book. | |
124 | - */ | |
125 | - switch (event) { | |
126 | - case MFGPT_EVENT_RESET: | |
127 | - /* | |
128 | - * XXX: According to the docs, we cannot reset timers above | |
129 | - * 6; that is, resets for 7 and 8 will be ignored. Is this | |
130 | - * a problem? -dilinger | |
131 | - */ | |
132 | - msr = MSR_MFGPT_NR; | |
133 | - mask = 1 << (timer + 24); | |
134 | - break; | |
135 | - | |
136 | - case MFGPT_EVENT_NMI: | |
137 | - msr = MSR_MFGPT_NR; | |
138 | - mask = 1 << (timer + shift); | |
139 | - break; | |
140 | - | |
141 | - case MFGPT_EVENT_IRQ: | |
142 | - msr = MSR_MFGPT_IRQ; | |
143 | - mask = 1 << (timer + shift); | |
144 | - break; | |
145 | - | |
146 | - default: | |
147 | - return -EIO; | |
148 | - } | |
149 | - | |
150 | - rdmsr(msr, value, dummy); | |
151 | - | |
152 | - if (enable) | |
153 | - value |= mask; | |
154 | - else | |
155 | - value &= ~mask; | |
156 | - | |
157 | - wrmsr(msr, value, dummy); | |
158 | - return 0; | |
159 | -} | |
160 | -EXPORT_SYMBOL_GPL(geode_mfgpt_toggle_event); | |
161 | - | |
162 | -int geode_mfgpt_set_irq(int timer, int cmp, int *irq, int enable) | |
163 | -{ | |
164 | - u32 zsel, lpc, dummy; | |
165 | - int shift; | |
166 | - | |
167 | - if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | |
168 | - return -EIO; | |
169 | - | |
170 | - /* | |
171 | - * Unfortunately, MFGPTs come in pairs sharing their IRQ lines. If VSA | |
172 | - * is using the same CMP of the timer's Siamese twin, the IRQ is set to | |
173 | - * 2, and we mustn't use nor change it. | |
174 | - * XXX: Likewise, 2 Linux drivers might clash if the 2nd overwrites the | |
175 | - * IRQ of the 1st. This can only happen if forcing an IRQ, calling this | |
176 | - * with *irq==0 is safe. Currently there _are_ no 2 drivers. | |
177 | - */ | |
178 | - rdmsr(MSR_PIC_ZSEL_LOW, zsel, dummy); | |
179 | - shift = ((cmp == MFGPT_CMP1 ? 0 : 4) + timer % 4) * 4; | |
180 | - if (((zsel >> shift) & 0xF) == 2) | |
181 | - return -EIO; | |
182 | - | |
183 | - /* Choose IRQ: if none supplied, keep IRQ already set or use default */ | |
184 | - if (!*irq) | |
185 | - *irq = (zsel >> shift) & 0xF; | |
186 | - if (!*irq) | |
187 | - *irq = MFGPT_DEFAULT_IRQ; | |
188 | - | |
189 | - /* Can't use IRQ if it's 0 (=disabled), 2, or routed to LPC */ | |
190 | - if (*irq < 1 || *irq == 2 || *irq > 15) | |
191 | - return -EIO; | |
192 | - rdmsr(MSR_PIC_IRQM_LPC, lpc, dummy); | |
193 | - if (lpc & (1 << *irq)) | |
194 | - return -EIO; | |
195 | - | |
196 | - /* All chosen and checked - go for it */ | |
197 | - if (geode_mfgpt_toggle_event(timer, cmp, MFGPT_EVENT_IRQ, enable)) | |
198 | - return -EIO; | |
199 | - if (enable) { | |
200 | - zsel = (zsel & ~(0xF << shift)) | (*irq << shift); | |
201 | - wrmsr(MSR_PIC_ZSEL_LOW, zsel, dummy); | |
202 | - } | |
203 | - | |
204 | - return 0; | |
205 | -} | |
206 | - | |
207 | -static int mfgpt_get(int timer) | |
208 | -{ | |
209 | - mfgpt_timers[timer].avail = 0; | |
210 | - printk(KERN_INFO "geode-mfgpt: Registered timer %d\n", timer); | |
211 | - return timer; | |
212 | -} | |
213 | - | |
214 | -int geode_mfgpt_alloc_timer(int timer, int domain) | |
215 | -{ | |
216 | - int i; | |
217 | - | |
218 | - if (timers == -1) { | |
219 | - /* timers haven't been detected yet */ | |
220 | - geode_mfgpt_detect(); | |
221 | - } | |
222 | - | |
223 | - if (!timers) | |
224 | - return -1; | |
225 | - | |
226 | - if (timer >= MFGPT_MAX_TIMERS) | |
227 | - return -1; | |
228 | - | |
229 | - if (timer < 0) { | |
230 | - /* Try to find an available timer */ | |
231 | - for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | |
232 | - if (mfgpt_timers[i].avail) | |
233 | - return mfgpt_get(i); | |
234 | - | |
235 | - if (i == 5 && domain == MFGPT_DOMAIN_WORKING) | |
236 | - break; | |
237 | - } | |
238 | - } else { | |
239 | - /* If they requested a specific timer, try to honor that */ | |
240 | - if (mfgpt_timers[timer].avail) | |
241 | - return mfgpt_get(timer); | |
242 | - } | |
243 | - | |
244 | - /* No timers available - too bad */ | |
245 | - return -1; | |
246 | -} | |
247 | -EXPORT_SYMBOL_GPL(geode_mfgpt_alloc_timer); | |
248 | - | |
249 | - | |
250 | -#ifdef CONFIG_GEODE_MFGPT_TIMER | |
251 | - | |
252 | -/* | |
253 | - * The MFPGT timers on the CS5536 provide us with suitable timers to use | |
254 | - * as clock event sources - not as good as a HPET or APIC, but certainly | |
255 | - * better than the PIT. This isn't a general purpose MFGPT driver, but | |
256 | - * a simplified one designed specifically to act as a clock event source. | |
257 | - * For full details about the MFGPT, please consult the CS5536 data sheet. | |
258 | - */ | |
259 | - | |
260 | -#include <linux/clocksource.h> | |
261 | -#include <linux/clockchips.h> | |
262 | - | |
263 | -static unsigned int mfgpt_tick_mode = CLOCK_EVT_MODE_SHUTDOWN; | |
264 | -static u16 mfgpt_event_clock; | |
265 | - | |
266 | -static int irq; | |
267 | -static int __init mfgpt_setup(char *str) | |
268 | -{ | |
269 | - get_option(&str, &irq); | |
270 | - return 1; | |
271 | -} | |
272 | -__setup("mfgpt_irq=", mfgpt_setup); | |
273 | - | |
274 | -static void mfgpt_disable_timer(u16 clock) | |
275 | -{ | |
276 | - /* avoid races by clearing CMP1 and CMP2 unconditionally */ | |
277 | - geode_mfgpt_write(clock, MFGPT_REG_SETUP, (u16) ~MFGPT_SETUP_CNTEN | | |
278 | - MFGPT_SETUP_CMP1 | MFGPT_SETUP_CMP2); | |
279 | -} | |
280 | - | |
281 | -static int mfgpt_next_event(unsigned long, struct clock_event_device *); | |
282 | -static void mfgpt_set_mode(enum clock_event_mode, struct clock_event_device *); | |
283 | - | |
284 | -static struct clock_event_device mfgpt_clockevent = { | |
285 | - .name = "mfgpt-timer", | |
286 | - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | |
287 | - .set_mode = mfgpt_set_mode, | |
288 | - .set_next_event = mfgpt_next_event, | |
289 | - .rating = 250, | |
290 | - .cpumask = cpu_all_mask, | |
291 | - .shift = 32 | |
292 | -}; | |
293 | - | |
294 | -static void mfgpt_start_timer(u16 delta) | |
295 | -{ | |
296 | - geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_CMP2, (u16) delta); | |
297 | - geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | |
298 | - | |
299 | - geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | |
300 | - MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | |
301 | -} | |
302 | - | |
303 | -static void mfgpt_set_mode(enum clock_event_mode mode, | |
304 | - struct clock_event_device *evt) | |
305 | -{ | |
306 | - mfgpt_disable_timer(mfgpt_event_clock); | |
307 | - | |
308 | - if (mode == CLOCK_EVT_MODE_PERIODIC) | |
309 | - mfgpt_start_timer(MFGPT_PERIODIC); | |
310 | - | |
311 | - mfgpt_tick_mode = mode; | |
312 | -} | |
313 | - | |
314 | -static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) | |
315 | -{ | |
316 | - mfgpt_start_timer(delta); | |
317 | - return 0; | |
318 | -} | |
319 | - | |
320 | -static irqreturn_t mfgpt_tick(int irq, void *dev_id) | |
321 | -{ | |
322 | - u16 val = geode_mfgpt_read(mfgpt_event_clock, MFGPT_REG_SETUP); | |
323 | - | |
324 | - /* See if the interrupt was for us */ | |
325 | - if (!(val & (MFGPT_SETUP_SETUP | MFGPT_SETUP_CMP2 | MFGPT_SETUP_CMP1))) | |
326 | - return IRQ_NONE; | |
327 | - | |
328 | - /* Turn off the clock (and clear the event) */ | |
329 | - mfgpt_disable_timer(mfgpt_event_clock); | |
330 | - | |
331 | - if (mfgpt_tick_mode == CLOCK_EVT_MODE_SHUTDOWN) | |
332 | - return IRQ_HANDLED; | |
333 | - | |
334 | - /* Clear the counter */ | |
335 | - geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | |
336 | - | |
337 | - /* Restart the clock in periodic mode */ | |
338 | - | |
339 | - if (mfgpt_tick_mode == CLOCK_EVT_MODE_PERIODIC) { | |
340 | - geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | |
341 | - MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | |
342 | - } | |
343 | - | |
344 | - mfgpt_clockevent.event_handler(&mfgpt_clockevent); | |
345 | - return IRQ_HANDLED; | |
346 | -} | |
347 | - | |
348 | -static struct irqaction mfgptirq = { | |
349 | - .handler = mfgpt_tick, | |
350 | - .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, | |
351 | - .name = "mfgpt-timer" | |
352 | -}; | |
353 | - | |
354 | -int __init mfgpt_timer_setup(void) | |
355 | -{ | |
356 | - int timer, ret; | |
357 | - u16 val; | |
358 | - | |
359 | - timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING); | |
360 | - if (timer < 0) { | |
361 | - printk(KERN_ERR | |
362 | - "mfgpt-timer: Could not allocate a MFPGT timer\n"); | |
363 | - return -ENODEV; | |
364 | - } | |
365 | - | |
366 | - mfgpt_event_clock = timer; | |
367 | - | |
368 | - /* Set up the IRQ on the MFGPT side */ | |
369 | - if (geode_mfgpt_setup_irq(mfgpt_event_clock, MFGPT_CMP2, &irq)) { | |
370 | - printk(KERN_ERR "mfgpt-timer: Could not set up IRQ %d\n", irq); | |
371 | - return -EIO; | |
372 | - } | |
373 | - | |
374 | - /* And register it with the kernel */ | |
375 | - ret = setup_irq(irq, &mfgptirq); | |
376 | - | |
377 | - if (ret) { | |
378 | - printk(KERN_ERR | |
379 | - "mfgpt-timer: Unable to set up the interrupt.\n"); | |
380 | - goto err; | |
381 | - } | |
382 | - | |
383 | - /* Set the clock scale and enable the event mode for CMP2 */ | |
384 | - val = MFGPT_SCALE | (3 << 8); | |
385 | - | |
386 | - geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val); | |
387 | - | |
388 | - /* Set up the clock event */ | |
389 | - mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, | |
390 | - mfgpt_clockevent.shift); | |
391 | - mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF, | |
392 | - &mfgpt_clockevent); | |
393 | - mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE, | |
394 | - &mfgpt_clockevent); | |
395 | - | |
396 | - printk(KERN_INFO | |
397 | - "mfgpt-timer: Registering MFGPT timer %d as a clock event, using IRQ %d\n", | |
398 | - timer, irq); | |
399 | - clockevents_register_device(&mfgpt_clockevent); | |
400 | - | |
401 | - return 0; | |
402 | - | |
403 | -err: | |
404 | - geode_mfgpt_release_irq(mfgpt_event_clock, MFGPT_CMP2, &irq); | |
405 | - printk(KERN_ERR | |
406 | - "mfgpt-timer: Unable to set up the MFGPT clock source\n"); | |
407 | - return -EIO; | |
408 | -} | |
409 | - | |
410 | -#endif |
drivers/gpio/Kconfig
... | ... | @@ -176,7 +176,7 @@ |
176 | 176 | |
177 | 177 | config GPIO_CS5535 |
178 | 178 | tristate "AMD CS5535/CS5536 GPIO support" |
179 | - depends on PCI && !CS5535_GPIO && !MGEODE_LX | |
179 | + depends on PCI && !CS5535_GPIO | |
180 | 180 | help |
181 | 181 | The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that |
182 | 182 | can be used for quite a number of things. The CS5535/6 is found on |
drivers/misc/Kconfig