diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-03 05:31:54 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-03 05:31:58 -0500 |
commit | cde9efef401563943d5a58eb9b7274bfdc08ca9b (patch) | |
tree | 858a436055612db6282dc63db0fe3ba41147056a | |
parent | 50401d77ee4904673042dd737eed436067cc23f5 (diff) | |
parent | 60ebe1568fd15b7ffa101acc645069e27d546ed6 (diff) |
Merge branch 'ux500-core' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson into devel-stable
55 files changed, 3387 insertions, 1629 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d571cdb79d81..4d1c3093a133 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -798,6 +798,7 @@ config ARCH_U8500 | |||
798 | select GENERIC_CLOCKEVENTS | 798 | select GENERIC_CLOCKEVENTS |
799 | select COMMON_CLKDEV | 799 | select COMMON_CLKDEV |
800 | select ARCH_REQUIRE_GPIOLIB | 800 | select ARCH_REQUIRE_GPIOLIB |
801 | select ARCH_HAS_CPUFREQ | ||
801 | help | 802 | help |
802 | Support for ST-Ericsson's Ux500 architecture | 803 | Support for ST-Ericsson's Ux500 architecture |
803 | 804 | ||
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 9e27a84433cb..12052e8e064c 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile | |||
@@ -2,14 +2,16 @@ | |||
2 | # Makefile for the linux kernel, U8500 machine. | 2 | # Makefile for the linux kernel, U8500 machine. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := clock.o cpu.o devices.o | 5 | obj-y := clock.o cpu.o devices.o devices-common.o |
6 | obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o | 6 | obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o |
7 | obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o | 7 | obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o |
8 | obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o | 8 | obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o \ |
9 | obj-$(CONFIG_MACH_U5500) += board-u5500.o | 9 | board-mop500-keypads.o |
10 | obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o | ||
10 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 11 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
11 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 12 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
12 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | 13 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o |
13 | obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o | 14 | obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o |
14 | obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o | 15 | obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o |
15 | obj-$(CONFIG_U5500_MBOX) += mbox.o | 16 | obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o |
17 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | ||
diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c new file mode 100644 index 000000000000..70318c354d32 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-keypads.c | |||
@@ -0,0 +1,229 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * | ||
6 | * Keypad layouts for various boards | ||
7 | */ | ||
8 | |||
9 | #include <linux/i2c.h> | ||
10 | #include <linux/gpio.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/mfd/stmpe.h> | ||
14 | #include <linux/mfd/tc3589x.h> | ||
15 | #include <linux/input/matrix_keypad.h> | ||
16 | |||
17 | #include <plat/pincfg.h> | ||
18 | #include <plat/ske.h> | ||
19 | |||
20 | #include <mach/devices.h> | ||
21 | #include <mach/hardware.h> | ||
22 | |||
23 | #include "devices-db8500.h" | ||
24 | #include "board-mop500.h" | ||
25 | |||
26 | /* STMPE/SKE keypad use this key layout */ | ||
27 | static const unsigned int mop500_keymap[] = { | ||
28 | KEY(2, 5, KEY_END), | ||
29 | KEY(4, 1, KEY_POWER), | ||
30 | KEY(3, 5, KEY_VOLUMEDOWN), | ||
31 | KEY(1, 3, KEY_3), | ||
32 | KEY(5, 2, KEY_RIGHT), | ||
33 | KEY(5, 0, KEY_9), | ||
34 | |||
35 | KEY(0, 5, KEY_MENU), | ||
36 | KEY(7, 6, KEY_ENTER), | ||
37 | KEY(4, 5, KEY_0), | ||
38 | KEY(6, 7, KEY_2), | ||
39 | KEY(3, 4, KEY_UP), | ||
40 | KEY(3, 3, KEY_DOWN), | ||
41 | |||
42 | KEY(6, 4, KEY_SEND), | ||
43 | KEY(6, 2, KEY_BACK), | ||
44 | KEY(4, 2, KEY_VOLUMEUP), | ||
45 | KEY(5, 5, KEY_1), | ||
46 | KEY(4, 3, KEY_LEFT), | ||
47 | KEY(3, 2, KEY_7), | ||
48 | }; | ||
49 | |||
50 | static const struct matrix_keymap_data mop500_keymap_data = { | ||
51 | .keymap = mop500_keymap, | ||
52 | .keymap_size = ARRAY_SIZE(mop500_keymap), | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * Nomadik SKE keypad | ||
57 | */ | ||
58 | #define ROW_PIN_I0 164 | ||
59 | #define ROW_PIN_I1 163 | ||
60 | #define ROW_PIN_I2 162 | ||
61 | #define ROW_PIN_I3 161 | ||
62 | #define ROW_PIN_I4 156 | ||
63 | #define ROW_PIN_I5 155 | ||
64 | #define ROW_PIN_I6 154 | ||
65 | #define ROW_PIN_I7 153 | ||
66 | #define COL_PIN_O0 168 | ||
67 | #define COL_PIN_O1 167 | ||
68 | #define COL_PIN_O2 166 | ||
69 | #define COL_PIN_O3 165 | ||
70 | #define COL_PIN_O4 160 | ||
71 | #define COL_PIN_O5 159 | ||
72 | #define COL_PIN_O6 158 | ||
73 | #define COL_PIN_O7 157 | ||
74 | |||
75 | #define SKE_KPD_MAX_ROWS 8 | ||
76 | #define SKE_KPD_MAX_COLS 8 | ||
77 | |||
78 | static int ske_kp_rows[] = { | ||
79 | ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3, | ||
80 | ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7, | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * ske_set_gpio_row: request and set gpio rows | ||
85 | */ | ||
86 | static int ske_set_gpio_row(int gpio) | ||
87 | { | ||
88 | int ret; | ||
89 | |||
90 | ret = gpio_request(gpio, "ske-kp"); | ||
91 | if (ret < 0) { | ||
92 | pr_err("ske_set_gpio_row: gpio request failed\n"); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | ret = gpio_direction_output(gpio, 1); | ||
97 | if (ret < 0) { | ||
98 | pr_err("ske_set_gpio_row: gpio direction failed\n"); | ||
99 | gpio_free(gpio); | ||
100 | } | ||
101 | |||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * ske_kp_init - enable the gpio configuration | ||
107 | */ | ||
108 | static int ske_kp_init(void) | ||
109 | { | ||
110 | int ret, i; | ||
111 | |||
112 | for (i = 0; i < SKE_KPD_MAX_ROWS; i++) { | ||
113 | ret = ske_set_gpio_row(ske_kp_rows[i]); | ||
114 | if (ret < 0) { | ||
115 | pr_err("ske_kp_init: failed init\n"); | ||
116 | return ret; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static struct ske_keypad_platform_data ske_keypad_board = { | ||
124 | .init = ske_kp_init, | ||
125 | .keymap_data = &mop500_keymap_data, | ||
126 | .no_autorepeat = true, | ||
127 | .krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */ | ||
128 | .kcol = SKE_KPD_MAX_COLS, | ||
129 | .debounce_ms = 40, /* in millisecs */ | ||
130 | }; | ||
131 | |||
132 | /* | ||
133 | * STMPE1601 | ||
134 | */ | ||
135 | static struct stmpe_keypad_platform_data stmpe1601_keypad_data = { | ||
136 | .debounce_ms = 64, | ||
137 | .scan_count = 8, | ||
138 | .no_autorepeat = true, | ||
139 | .keymap_data = &mop500_keymap_data, | ||
140 | }; | ||
141 | |||
142 | static struct stmpe_platform_data stmpe1601_data = { | ||
143 | .id = 1, | ||
144 | .blocks = STMPE_BLOCK_KEYPAD, | ||
145 | .irq_trigger = IRQF_TRIGGER_FALLING, | ||
146 | .irq_base = MOP500_STMPE1601_IRQ(0), | ||
147 | .keypad = &stmpe1601_keypad_data, | ||
148 | .autosleep = true, | ||
149 | .autosleep_timeout = 1024, | ||
150 | }; | ||
151 | |||
152 | static struct i2c_board_info mop500_i2c0_devices_stuib[] = { | ||
153 | { | ||
154 | I2C_BOARD_INFO("stmpe1601", 0x40), | ||
155 | .irq = NOMADIK_GPIO_TO_IRQ(218), | ||
156 | .platform_data = &stmpe1601_data, | ||
157 | .flags = I2C_CLIENT_WAKE, | ||
158 | }, | ||
159 | }; | ||
160 | |||
161 | /* | ||
162 | * TC35893 | ||
163 | */ | ||
164 | |||
165 | static const unsigned int uib_keymap[] = { | ||
166 | KEY(3, 1, KEY_END), | ||
167 | KEY(4, 1, KEY_POWER), | ||
168 | KEY(6, 4, KEY_VOLUMEDOWN), | ||
169 | KEY(4, 2, KEY_EMAIL), | ||
170 | KEY(3, 3, KEY_RIGHT), | ||
171 | KEY(2, 5, KEY_BACKSPACE), | ||
172 | |||
173 | KEY(6, 7, KEY_MENU), | ||
174 | KEY(5, 0, KEY_ENTER), | ||
175 | KEY(4, 3, KEY_0), | ||
176 | KEY(3, 4, KEY_DOT), | ||
177 | KEY(5, 2, KEY_UP), | ||
178 | KEY(3, 5, KEY_DOWN), | ||
179 | |||
180 | KEY(4, 5, KEY_SEND), | ||
181 | KEY(0, 5, KEY_BACK), | ||
182 | KEY(6, 2, KEY_VOLUMEUP), | ||
183 | KEY(1, 3, KEY_SPACE), | ||
184 | KEY(7, 6, KEY_LEFT), | ||
185 | KEY(5, 5, KEY_SEARCH), | ||
186 | }; | ||
187 | |||
188 | static struct matrix_keymap_data uib_keymap_data = { | ||
189 | .keymap = uib_keymap, | ||
190 | .keymap_size = ARRAY_SIZE(uib_keymap), | ||
191 | }; | ||
192 | |||
193 | static struct tc3589x_keypad_platform_data tc35893_data = { | ||
194 | .krow = TC_KPD_ROWS, | ||
195 | .kcol = TC_KPD_COLUMNS, | ||
196 | .debounce_period = TC_KPD_DEBOUNCE_PERIOD, | ||
197 | .settle_time = TC_KPD_SETTLE_TIME, | ||
198 | .irqtype = IRQF_TRIGGER_FALLING, | ||
199 | .enable_wakeup = true, | ||
200 | .keymap_data = &uib_keymap_data, | ||
201 | .no_autorepeat = true, | ||
202 | }; | ||
203 | |||
204 | static struct tc3589x_platform_data tc3589x_keypad_data = { | ||
205 | .block = TC3589x_BLOCK_KEYPAD, | ||
206 | .keypad = &tc35893_data, | ||
207 | .irq_base = MOP500_EGPIO_IRQ_BASE, | ||
208 | }; | ||
209 | |||
210 | static struct i2c_board_info mop500_i2c0_devices_uib[] = { | ||
211 | { | ||
212 | I2C_BOARD_INFO("tc3589x", 0x44), | ||
213 | .platform_data = &tc3589x_keypad_data, | ||
214 | .irq = NOMADIK_GPIO_TO_IRQ(218), | ||
215 | .flags = I2C_CLIENT_WAKE, | ||
216 | }, | ||
217 | }; | ||
218 | |||
219 | void mop500_keypad_init(void) | ||
220 | { | ||
221 | db8500_add_ske_keypad(&ske_keypad_board); | ||
222 | |||
223 | i2c_register_board_info(0, mop500_i2c0_devices_stuib, | ||
224 | ARRAY_SIZE(mop500_i2c0_devices_stuib)); | ||
225 | |||
226 | i2c_register_board_info(0, mop500_i2c0_devices_uib, | ||
227 | ARRAY_SIZE(mop500_i2c0_devices_uib)); | ||
228 | |||
229 | } | ||
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index bac995665b58..4b996676594e 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c | |||
@@ -16,10 +16,24 @@ | |||
16 | #include <mach/devices.h> | 16 | #include <mach/devices.h> |
17 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
18 | 18 | ||
19 | #include "devices-db8500.h" | ||
19 | #include "pins-db8500.h" | 20 | #include "pins-db8500.h" |
20 | #include "board-mop500.h" | 21 | #include "board-mop500.h" |
21 | 22 | ||
22 | static pin_cfg_t mop500_sdi_pins[] = { | 23 | static pin_cfg_t mop500_sdi_pins[] = { |
24 | /* SDI0 (MicroSD slot) */ | ||
25 | GPIO18_MC0_CMDDIR, | ||
26 | GPIO19_MC0_DAT0DIR, | ||
27 | GPIO20_MC0_DAT2DIR, | ||
28 | GPIO21_MC0_DAT31DIR, | ||
29 | GPIO22_MC0_FBCLK, | ||
30 | GPIO23_MC0_CLK, | ||
31 | GPIO24_MC0_CMD, | ||
32 | GPIO25_MC0_DAT0, | ||
33 | GPIO26_MC0_DAT1, | ||
34 | GPIO27_MC0_DAT2, | ||
35 | GPIO28_MC0_DAT3, | ||
36 | |||
23 | /* SDI4 (on-board eMMC) */ | 37 | /* SDI4 (on-board eMMC) */ |
24 | GPIO197_MC4_DAT3, | 38 | GPIO197_MC4_DAT3, |
25 | GPIO198_MC4_DAT2, | 39 | GPIO198_MC4_DAT2, |
@@ -50,6 +64,55 @@ static pin_cfg_t mop500_sdi2_pins[] = { | |||
50 | }; | 64 | }; |
51 | 65 | ||
52 | /* | 66 | /* |
67 | * SDI 0 (MicroSD slot) | ||
68 | */ | ||
69 | |||
70 | /* MMCIPOWER bits */ | ||
71 | #define MCI_DATA2DIREN (1 << 2) | ||
72 | #define MCI_CMDDIREN (1 << 3) | ||
73 | #define MCI_DATA0DIREN (1 << 4) | ||
74 | #define MCI_DATA31DIREN (1 << 5) | ||
75 | #define MCI_FBCLKEN (1 << 7) | ||
76 | |||
77 | static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd, | ||
78 | unsigned char power_mode) | ||
79 | { | ||
80 | if (power_mode == MMC_POWER_UP) | ||
81 | gpio_set_value_cansleep(GPIO_SDMMC_EN, 1); | ||
82 | else if (power_mode == MMC_POWER_OFF) | ||
83 | gpio_set_value_cansleep(GPIO_SDMMC_EN, 0); | ||
84 | |||
85 | return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN | | ||
86 | MCI_DATA2DIREN | MCI_DATA31DIREN; | ||
87 | } | ||
88 | |||
89 | static struct mmci_platform_data mop500_sdi0_data = { | ||
90 | .vdd_handler = mop500_sdi0_vdd_handler, | ||
91 | .ocr_mask = MMC_VDD_29_30, | ||
92 | .f_max = 100000000, | ||
93 | .capabilities = MMC_CAP_4_BIT_DATA, | ||
94 | .gpio_cd = GPIO_SDMMC_CD, | ||
95 | .gpio_wp = -1, | ||
96 | }; | ||
97 | |||
98 | void mop500_sdi_tc35892_init(void) | ||
99 | { | ||
100 | int ret; | ||
101 | |||
102 | ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN"); | ||
103 | if (!ret) | ||
104 | ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL, | ||
105 | "GPIO_SDMMC_1V8_3V_SEL"); | ||
106 | if (ret) | ||
107 | return; | ||
108 | |||
109 | gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1); | ||
110 | gpio_direction_output(GPIO_SDMMC_EN, 0); | ||
111 | |||
112 | db8500_add_sdi0(&mop500_sdi0_data); | ||
113 | } | ||
114 | |||
115 | /* | ||
53 | * SDI 2 (POP eMMC, not on DB8500ed) | 116 | * SDI 2 (POP eMMC, not on DB8500ed) |
54 | */ | 117 | */ |
55 | 118 | ||
@@ -74,18 +137,24 @@ static struct mmci_platform_data mop500_sdi4_data = { | |||
74 | .gpio_wp = -1, | 137 | .gpio_wp = -1, |
75 | }; | 138 | }; |
76 | 139 | ||
77 | void mop500_sdi_init(void) | 140 | void __init mop500_sdi_init(void) |
78 | { | 141 | { |
79 | nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); | 142 | nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); |
80 | 143 | ||
81 | u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data; | 144 | /* |
82 | u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data; | 145 | * sdi0 will finally be added when the TC35892 initializes and calls |
146 | * mop500_sdi_tc35892_init() above. | ||
147 | */ | ||
83 | 148 | ||
149 | /* PoP:ed eMMC */ | ||
84 | if (!cpu_is_u8500ed()) { | 150 | if (!cpu_is_u8500ed()) { |
85 | nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins)); | 151 | nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins)); |
86 | amba_device_register(&u8500_sdi2_device, &iomem_resource); | 152 | /* POP eMMC on v1.0 has problems with high speed */ |
153 | if (!cpu_is_u8500v10()) | ||
154 | mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED; | ||
155 | db8500_add_sdi2(&mop500_sdi2_data); | ||
87 | } | 156 | } |
88 | 157 | ||
89 | /* On-board eMMC */ | 158 | /* On-board eMMC */ |
90 | amba_device_register(&u8500_sdi4_device, &iomem_resource); | 159 | db8500_add_sdi4(&mop500_sdi4_data); |
91 | } | 160 | } |
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index cac83a694880..a1c9ea1a66df 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c | |||
@@ -13,25 +13,26 @@ | |||
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/i2c.h> | ||
16 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
17 | #include <linux/amba/bus.h> | 18 | #include <linux/amba/bus.h> |
18 | #include <linux/amba/pl022.h> | 19 | #include <linux/amba/pl022.h> |
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
20 | #include <linux/mfd/ab8500.h> | 21 | #include <linux/mfd/ab8500.h> |
21 | #include <linux/input/matrix_keypad.h> | 22 | #include <linux/mfd/tc3589x.h> |
22 | 23 | ||
23 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
24 | #include <asm/mach/arch.h> | 25 | #include <asm/mach/arch.h> |
25 | 26 | ||
26 | #include <plat/pincfg.h> | 27 | #include <plat/pincfg.h> |
27 | #include <plat/i2c.h> | 28 | #include <plat/i2c.h> |
28 | #include <plat/ske.h> | ||
29 | 29 | ||
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/setup.h> | 31 | #include <mach/setup.h> |
32 | #include <mach/devices.h> | 32 | #include <mach/devices.h> |
33 | #include <mach/irqs.h> | 33 | #include <mach/irqs.h> |
34 | 34 | ||
35 | #include "devices-db8500.h" | ||
35 | #include "pins-db8500.h" | 36 | #include "pins-db8500.h" |
36 | #include "board-mop500.h" | 37 | #include "board-mop500.h" |
37 | 38 | ||
@@ -69,22 +70,12 @@ static pin_cfg_t mop500_pins[] = { | |||
69 | GPIO166_KP_O2, | 70 | GPIO166_KP_O2, |
70 | GPIO167_KP_O1, | 71 | GPIO167_KP_O1, |
71 | GPIO168_KP_O0, | 72 | GPIO168_KP_O0, |
72 | }; | ||
73 | 73 | ||
74 | static void ab4500_spi_cs_control(u32 command) | 74 | /* GPIO_EXP_INT */ |
75 | { | 75 | GPIO217_GPIO, |
76 | /* set the FRM signal, which is CS - TODO */ | ||
77 | } | ||
78 | 76 | ||
79 | struct pl022_config_chip ab4500_chip_info = { | 77 | /* STMPE1601 IRQ */ |
80 | .com_mode = INTERRUPT_TRANSFER, | 78 | GPIO218_GPIO | PIN_INPUT_PULLUP, |
81 | .iface = SSP_INTERFACE_MOTOROLA_SPI, | ||
82 | /* we can act as master only */ | ||
83 | .hierarchy = SSP_MASTER, | ||
84 | .slave_tx_disable = 0, | ||
85 | .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, | ||
86 | .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, | ||
87 | .cs_control = ab4500_spi_cs_control, | ||
88 | }; | 79 | }; |
89 | 80 | ||
90 | static struct ab8500_platform_data ab8500_platdata = { | 81 | static struct ab8500_platform_data ab8500_platdata = { |
@@ -93,9 +84,9 @@ static struct ab8500_platform_data ab8500_platdata = { | |||
93 | 84 | ||
94 | static struct resource ab8500_resources[] = { | 85 | static struct resource ab8500_resources[] = { |
95 | [0] = { | 86 | [0] = { |
96 | .start = IRQ_AB8500, | 87 | .start = IRQ_DB8500_AB8500, |
97 | .end = IRQ_AB8500, | 88 | .end = IRQ_DB8500_AB8500, |
98 | .flags = IORESOURCE_IRQ | 89 | .flags = IORESOURCE_IRQ |
99 | } | 90 | } |
100 | }; | 91 | }; |
101 | 92 | ||
@@ -109,19 +100,6 @@ struct platform_device ab8500_device = { | |||
109 | .resource = ab8500_resources, | 100 | .resource = ab8500_resources, |
110 | }; | 101 | }; |
111 | 102 | ||
112 | static struct spi_board_info ab8500_spi_devices[] = { | ||
113 | { | ||
114 | .modalias = "ab8500-spi", | ||
115 | .controller_data = &ab4500_chip_info, | ||
116 | .platform_data = &ab8500_platdata, | ||
117 | .max_speed_hz = 12000000, | ||
118 | .bus_num = 0, | ||
119 | .chip_select = 0, | ||
120 | .mode = SPI_MODE_3, | ||
121 | .irq = IRQ_DB8500_AB8500, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static struct pl022_ssp_controller ssp0_platform_data = { | 103 | static struct pl022_ssp_controller ssp0_platform_data = { |
126 | .bus_id = 0, | 104 | .bus_id = 0, |
127 | /* pl022 not yet supports dma */ | 105 | /* pl022 not yet supports dma */ |
@@ -132,6 +110,34 @@ static struct pl022_ssp_controller ssp0_platform_data = { | |||
132 | .num_chipselect = 5, | 110 | .num_chipselect = 5, |
133 | }; | 111 | }; |
134 | 112 | ||
113 | /* | ||
114 | * TC35892 | ||
115 | */ | ||
116 | |||
117 | static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base) | ||
118 | { | ||
119 | mop500_sdi_tc35892_init(); | ||
120 | } | ||
121 | |||
122 | static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { | ||
123 | .gpio_base = MOP500_EGPIO(0), | ||
124 | .setup = mop500_tc35892_init, | ||
125 | }; | ||
126 | |||
127 | static struct tc3589x_platform_data mop500_tc35892_data = { | ||
128 | .block = TC3589x_BLOCK_GPIO, | ||
129 | .gpio = &mop500_tc35892_gpio_data, | ||
130 | .irq_base = MOP500_EGPIO_IRQ_BASE, | ||
131 | }; | ||
132 | |||
133 | static struct i2c_board_info mop500_i2c0_devices[] = { | ||
134 | { | ||
135 | I2C_BOARD_INFO("tc3589x", 0x42), | ||
136 | .irq = NOMADIK_GPIO_TO_IRQ(217), | ||
137 | .platform_data = &mop500_tc35892_data, | ||
138 | }, | ||
139 | }; | ||
140 | |||
135 | #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ | 141 | #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ |
136 | static struct nmk_i2c_controller u8500_i2c##id##_data = { \ | 142 | static struct nmk_i2c_controller u8500_i2c##id##_data = { \ |
137 | /* \ | 143 | /* \ |
@@ -161,159 +167,49 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); | |||
161 | U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); | 167 | U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); |
162 | U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); | 168 | U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); |
163 | 169 | ||
164 | static struct amba_device *amba_devs[] __initdata = { | 170 | static void __init mop500_i2c_init(void) |
165 | &ux500_uart0_device, | 171 | { |
166 | &ux500_uart1_device, | 172 | db8500_add_i2c0(&u8500_i2c0_data); |
167 | &ux500_uart2_device, | 173 | db8500_add_i2c1(&u8500_i2c1_data); |
168 | &u8500_ssp0_device, | 174 | db8500_add_i2c2(&u8500_i2c2_data); |
169 | }; | 175 | db8500_add_i2c3(&u8500_i2c3_data); |
170 | 176 | } | |
171 | static const unsigned int ux500_keymap[] = { | ||
172 | KEY(2, 5, KEY_END), | ||
173 | KEY(4, 1, KEY_POWER), | ||
174 | KEY(3, 5, KEY_VOLUMEDOWN), | ||
175 | KEY(1, 3, KEY_3), | ||
176 | KEY(5, 2, KEY_RIGHT), | ||
177 | KEY(5, 0, KEY_9), | ||
178 | |||
179 | KEY(0, 5, KEY_MENU), | ||
180 | KEY(7, 6, KEY_ENTER), | ||
181 | KEY(4, 5, KEY_0), | ||
182 | KEY(6, 7, KEY_2), | ||
183 | KEY(3, 4, KEY_UP), | ||
184 | KEY(3, 3, KEY_DOWN), | ||
185 | |||
186 | KEY(6, 4, KEY_SEND), | ||
187 | KEY(6, 2, KEY_BACK), | ||
188 | KEY(4, 2, KEY_VOLUMEUP), | ||
189 | KEY(5, 5, KEY_1), | ||
190 | KEY(4, 3, KEY_LEFT), | ||
191 | KEY(3, 2, KEY_7), | ||
192 | }; | ||
193 | |||
194 | static const struct matrix_keymap_data ux500_keymap_data = { | ||
195 | .keymap = ux500_keymap, | ||
196 | .keymap_size = ARRAY_SIZE(ux500_keymap), | ||
197 | }; | ||
198 | 177 | ||
199 | /* | 178 | /* add any platform devices here - TODO */ |
200 | * Nomadik SKE keypad | 179 | static struct platform_device *platform_devs[] __initdata = { |
201 | */ | ||
202 | #define ROW_PIN_I0 164 | ||
203 | #define ROW_PIN_I1 163 | ||
204 | #define ROW_PIN_I2 162 | ||
205 | #define ROW_PIN_I3 161 | ||
206 | #define ROW_PIN_I4 156 | ||
207 | #define ROW_PIN_I5 155 | ||
208 | #define ROW_PIN_I6 154 | ||
209 | #define ROW_PIN_I7 153 | ||
210 | #define COL_PIN_O0 168 | ||
211 | #define COL_PIN_O1 167 | ||
212 | #define COL_PIN_O2 166 | ||
213 | #define COL_PIN_O3 165 | ||
214 | #define COL_PIN_O4 160 | ||
215 | #define COL_PIN_O5 159 | ||
216 | #define COL_PIN_O6 158 | ||
217 | #define COL_PIN_O7 157 | ||
218 | |||
219 | #define SKE_KPD_MAX_ROWS 8 | ||
220 | #define SKE_KPD_MAX_COLS 8 | ||
221 | |||
222 | static int ske_kp_rows[] = { | ||
223 | ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3, | ||
224 | ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7, | ||
225 | }; | 180 | }; |
226 | 181 | ||
227 | /* | 182 | static void __init mop500_spi_init(void) |
228 | * ske_set_gpio_row: request and set gpio rows | ||
229 | */ | ||
230 | static int ske_set_gpio_row(int gpio) | ||
231 | { | 183 | { |
232 | int ret; | 184 | db8500_add_ssp0(&ssp0_platform_data); |
233 | |||
234 | ret = gpio_request(gpio, "ske-kp"); | ||
235 | if (ret < 0) { | ||
236 | pr_err("ske_set_gpio_row: gpio request failed\n"); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | ret = gpio_direction_output(gpio, 1); | ||
241 | if (ret < 0) { | ||
242 | pr_err("ske_set_gpio_row: gpio direction failed\n"); | ||
243 | gpio_free(gpio); | ||
244 | } | ||
245 | |||
246 | return ret; | ||
247 | } | 185 | } |
248 | 186 | ||
249 | /* | 187 | static void __init mop500_uart_init(void) |
250 | * ske_kp_init - enable the gpio configuration | ||
251 | */ | ||
252 | static int ske_kp_init(void) | ||
253 | { | 188 | { |
254 | int ret, i; | 189 | db8500_add_uart0(); |
255 | 190 | db8500_add_uart1(); | |
256 | for (i = 0; i < SKE_KPD_MAX_ROWS; i++) { | 191 | db8500_add_uart2(); |
257 | ret = ske_set_gpio_row(ske_kp_rows[i]); | ||
258 | if (ret < 0) { | ||
259 | pr_err("ske_kp_init: failed init\n"); | ||
260 | return ret; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | 192 | } |
266 | 193 | ||
267 | static struct ske_keypad_platform_data ske_keypad_board = { | ||
268 | .init = ske_kp_init, | ||
269 | .keymap_data = &ux500_keymap_data, | ||
270 | .no_autorepeat = true, | ||
271 | .krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */ | ||
272 | .kcol = SKE_KPD_MAX_COLS, | ||
273 | .debounce_ms = 40, /* in millsecs */ | ||
274 | }; | ||
275 | |||
276 | |||
277 | |||
278 | /* add any platform devices here - TODO */ | ||
279 | static struct platform_device *platform_devs[] __initdata = { | ||
280 | &u8500_i2c0_device, | ||
281 | &ux500_i2c1_device, | ||
282 | &ux500_i2c2_device, | ||
283 | &ux500_i2c3_device, | ||
284 | &ux500_ske_keypad_device, | ||
285 | }; | ||
286 | |||
287 | static void __init u8500_init_machine(void) | 194 | static void __init u8500_init_machine(void) |
288 | { | 195 | { |
289 | int i; | ||
290 | |||
291 | u8500_init_devices(); | 196 | u8500_init_devices(); |
292 | 197 | ||
293 | nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins)); | 198 | nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins)); |
294 | 199 | ||
295 | u8500_i2c0_device.dev.platform_data = &u8500_i2c0_data; | ||
296 | ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data; | ||
297 | ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data; | ||
298 | ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data; | ||
299 | ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board; | ||
300 | |||
301 | u8500_ssp0_device.dev.platform_data = &ssp0_platform_data; | ||
302 | |||
303 | /* Register the active AMBA devices on this board */ | ||
304 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) | ||
305 | amba_device_register(amba_devs[i], &iomem_resource); | ||
306 | |||
307 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); | 200 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); |
308 | 201 | ||
202 | mop500_i2c_init(); | ||
309 | mop500_sdi_init(); | 203 | mop500_sdi_init(); |
204 | mop500_spi_init(); | ||
205 | mop500_uart_init(); | ||
206 | |||
207 | mop500_keypad_init(); | ||
208 | |||
209 | platform_device_register(&ab8500_device); | ||
310 | 210 | ||
311 | /* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */ | 211 | i2c_register_board_info(0, mop500_i2c0_devices, |
312 | if (cpu_is_u8500ed() || cpu_is_u8500v10()) | 212 | ARRAY_SIZE(mop500_i2c0_devices)); |
313 | spi_register_board_info(ab8500_spi_devices, | ||
314 | ARRAY_SIZE(ab8500_spi_devices)); | ||
315 | else /* If HW is v.1.1 or later use I2C to access AB8500 */ | ||
316 | platform_device_register(&ab8500_device); | ||
317 | } | 213 | } |
318 | 214 | ||
319 | MACHINE_START(U8500, "ST-Ericsson MOP500 platform") | 215 | MACHINE_START(U8500, "ST-Ericsson MOP500 platform") |
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 2d240322fa6f..3104ae2a02c2 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h | |||
@@ -7,6 +7,15 @@ | |||
7 | #ifndef __BOARD_MOP500_H | 7 | #ifndef __BOARD_MOP500_H |
8 | #define __BOARD_MOP500_H | 8 | #define __BOARD_MOP500_H |
9 | 9 | ||
10 | #define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x)) | ||
11 | |||
12 | /* GPIOs on the TC35892 expander */ | ||
13 | #define GPIO_SDMMC_CD MOP500_EGPIO(3) | ||
14 | #define GPIO_SDMMC_EN MOP500_EGPIO(17) | ||
15 | #define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18) | ||
16 | |||
10 | extern void mop500_sdi_init(void); | 17 | extern void mop500_sdi_init(void); |
18 | extern void mop500_sdi_tc35892_init(void); | ||
19 | extern void mop500_keypad_init(void); | ||
11 | 20 | ||
12 | #endif | 21 | #endif |
diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c new file mode 100644 index 000000000000..54712acc0394 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-sdi.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Hanumath Prasad <ulf.hansson@stericsson.com> | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/amba/mmci.h> | ||
9 | #include <linux/mmc/host.h> | ||
10 | #include <linux/gpio.h> | ||
11 | |||
12 | #include <plat/pincfg.h> | ||
13 | #include <mach/db5500-regs.h> | ||
14 | #include <plat/ste_dma40.h> | ||
15 | |||
16 | #include "pins-db5500.h" | ||
17 | #include "devices-db5500.h" | ||
18 | #include "ste-dma40-db5500.h" | ||
19 | |||
20 | static pin_cfg_t u5500_sdi_pins[] = { | ||
21 | /* SDI0 (POP eMMC) */ | ||
22 | GPIO5_MC0_DAT0 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
23 | GPIO6_MC0_DAT1 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
24 | GPIO7_MC0_DAT2 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
25 | GPIO8_MC0_DAT3 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
26 | GPIO9_MC0_DAT4 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
27 | GPIO10_MC0_DAT5 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
28 | GPIO11_MC0_DAT6 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
29 | GPIO12_MC0_DAT7 | PIN_DIR_INPUT | PIN_PULL_UP, | ||
30 | GPIO13_MC0_CMD | PIN_DIR_INPUT | PIN_PULL_UP, | ||
31 | GPIO14_MC0_CLK | PIN_DIR_OUTPUT | PIN_VAL_LOW, | ||
32 | }; | ||
33 | |||
34 | static struct mmci_platform_data u5500_sdi0_data = { | ||
35 | .ocr_mask = MMC_VDD_165_195, | ||
36 | .f_max = 50000000, | ||
37 | .capabilities = MMC_CAP_4_BIT_DATA | | ||
38 | MMC_CAP_8_BIT_DATA | | ||
39 | MMC_CAP_MMC_HIGHSPEED, | ||
40 | .gpio_cd = -1, | ||
41 | .gpio_wp = -1, | ||
42 | }; | ||
43 | |||
44 | void __init u5500_sdi_init(void) | ||
45 | { | ||
46 | nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins)); | ||
47 | |||
48 | db5500_add_sdi0(&u5500_sdi0_data); | ||
49 | } | ||
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 1ca094a45e71..39d370c1f3b4 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
10 | #include <linux/amba/bus.h> | 10 | #include <linux/amba/bus.h> |
11 | #include <linux/gpio.h> | 11 | #include <linux/gpio.h> |
12 | #include <linux/irq.h> | ||
12 | 13 | ||
13 | #include <asm/mach/arch.h> | 14 | #include <asm/mach/arch.h> |
14 | #include <asm/mach-types.h> | 15 | #include <asm/mach-types.h> |
@@ -17,20 +18,24 @@ | |||
17 | #include <mach/devices.h> | 18 | #include <mach/devices.h> |
18 | #include <mach/setup.h> | 19 | #include <mach/setup.h> |
19 | 20 | ||
20 | static struct amba_device *amba_board_devs[] __initdata = { | 21 | #include "devices-db5500.h" |
21 | &ux500_uart0_device, | 22 | |
22 | &ux500_uart1_device, | 23 | static void __init u5500_uart_init(void) |
23 | &ux500_uart2_device, | 24 | { |
24 | }; | 25 | db5500_add_uart0(); |
26 | db5500_add_uart1(); | ||
27 | db5500_add_uart2(); | ||
28 | } | ||
25 | 29 | ||
26 | static void __init u5500_init_machine(void) | 30 | static void __init u5500_init_machine(void) |
27 | { | 31 | { |
28 | u5500_init_devices(); | 32 | u5500_init_devices(); |
29 | 33 | ||
30 | amba_add_devices(amba_board_devs, ARRAY_SIZE(amba_board_devs)); | 34 | u5500_sdi_init(); |
35 | u5500_uart_init(); | ||
31 | } | 36 | } |
32 | 37 | ||
33 | MACHINE_START(U8500, "ST-Ericsson U5500 Platform") | 38 | MACHINE_START(U5500, "ST-Ericsson U5500 Platform") |
34 | .boot_params = 0x00000100, | 39 | .boot_params = 0x00000100, |
35 | .map_io = u5500_map_io, | 40 | .map_io = u5500_map_io, |
36 | .init_irq = ux500_init_irq, | 41 | .init_irq = ux500_init_irq, |
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 1675047daf20..912d1cc18c57 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c | |||
@@ -20,6 +20,12 @@ | |||
20 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
21 | #include "clock.h" | 21 | #include "clock.h" |
22 | 22 | ||
23 | #ifdef CONFIG_DEBUG_FS | ||
24 | #include <linux/debugfs.h> | ||
25 | #include <linux/uaccess.h> /* for copy_from_user */ | ||
26 | static LIST_HEAD(clk_list); | ||
27 | #endif | ||
28 | |||
23 | #define PRCC_PCKEN 0x00 | 29 | #define PRCC_PCKEN 0x00 |
24 | #define PRCC_PCKDIS 0x04 | 30 | #define PRCC_PCKDIS 0x04 |
25 | #define PRCC_KCKEN 0x08 | 31 | #define PRCC_KCKEN 0x08 |
@@ -133,7 +139,7 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) | |||
133 | { | 139 | { |
134 | void __iomem *addr = __io_address(UX500_PRCMU_BASE) | 140 | void __iomem *addr = __io_address(UX500_PRCMU_BASE) |
135 | + PRCM_TCR; | 141 | + PRCM_TCR; |
136 | u32 tcr = readl(addr); | 142 | u32 tcr; |
137 | int mtu = (int) clk->data; | 143 | int mtu = (int) clk->data; |
138 | /* | 144 | /* |
139 | * One of these is selected eventually | 145 | * One of these is selected eventually |
@@ -144,6 +150,14 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) | |||
144 | unsigned long mturate; | 150 | unsigned long mturate; |
145 | unsigned long retclk; | 151 | unsigned long retclk; |
146 | 152 | ||
153 | /* | ||
154 | * On a startup, always conifgure the TCR to the doze mode; | ||
155 | * bootloaders do it for us. Do this in the kernel too. | ||
156 | */ | ||
157 | writel(PRCM_TCR_DOZE_MODE, addr); | ||
158 | |||
159 | tcr = readl(addr); | ||
160 | |||
147 | /* Get the rate from the parent as a default */ | 161 | /* Get the rate from the parent as a default */ |
148 | if (clk->parent_periph) | 162 | if (clk->parent_periph) |
149 | mturate = clk_get_rate(clk->parent_periph); | 163 | mturate = clk_get_rate(clk->parent_periph); |
@@ -153,45 +167,6 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) | |||
153 | /* We need to be connected SOMEWHERE */ | 167 | /* We need to be connected SOMEWHERE */ |
154 | BUG(); | 168 | BUG(); |
155 | 169 | ||
156 | /* | ||
157 | * Are we in doze mode? | ||
158 | * In this mode the parent peripheral or the fixed 32768 Hz | ||
159 | * clock is fed into the block. | ||
160 | */ | ||
161 | if (!(tcr & PRCM_TCR_DOZE_MODE)) { | ||
162 | /* | ||
163 | * Here we're using the clock input from the APE ULP | ||
164 | * clock domain. But first: are the timers stopped? | ||
165 | */ | ||
166 | if (tcr & PRCM_TCR_STOPPED) { | ||
167 | clk32k = 0; | ||
168 | mturate = 0; | ||
169 | } else { | ||
170 | /* Else default mode: 0 and 2.4 MHz */ | ||
171 | clk32k = 0; | ||
172 | if (cpu_is_u5500()) | ||
173 | /* DB5500 divides by 8 */ | ||
174 | mturate /= 8; | ||
175 | else if (cpu_is_u8500ed()) { | ||
176 | /* | ||
177 | * This clocking setting must not be used | ||
178 | * in the ED chip, it is simply not | ||
179 | * connected anywhere! | ||
180 | */ | ||
181 | mturate = 0; | ||
182 | BUG(); | ||
183 | } else | ||
184 | /* | ||
185 | * In this mode the ulp38m4 clock is divided | ||
186 | * by a factor 16, on the DB8500 typically | ||
187 | * 38400000 / 16 ~ 2.4 MHz. | ||
188 | * TODO: Replace the constant with a reference | ||
189 | * to the ULP source once this is modeled. | ||
190 | */ | ||
191 | mturate = 38400000 / 16; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | /* Return the clock selected for this MTU */ | 170 | /* Return the clock selected for this MTU */ |
196 | if (tcr & (1 << mtu)) | 171 | if (tcr & (1 << mtu)) |
197 | retclk = clk32k; | 172 | retclk = clk32k; |
@@ -317,6 +292,7 @@ static struct clkops clk_prcc_ops = { | |||
317 | }; | 292 | }; |
318 | 293 | ||
319 | static struct clk clk_32khz = { | 294 | static struct clk clk_32khz = { |
295 | .name = "clk_32khz", | ||
320 | .rate = 32000, | 296 | .rate = 32000, |
321 | }; | 297 | }; |
322 | 298 | ||
@@ -366,94 +342,96 @@ static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */ | |||
366 | */ | 342 | */ |
367 | 343 | ||
368 | /* Peripheral Cluster #1 */ | 344 | /* Peripheral Cluster #1 */ |
369 | static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); | 345 | static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); |
370 | static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); | 346 | static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); |
371 | static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); | 347 | static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); |
372 | static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL); | 348 | static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL); |
373 | static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL); | 349 | static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL); |
374 | static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); | 350 | static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); |
375 | static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk); | 351 | static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk); |
376 | static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk); | 352 | static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk); |
377 | static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk); | 353 | static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk); |
378 | static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); | 354 | static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); |
379 | static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); | 355 | static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); |
380 | static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); | 356 | static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); |
381 | static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); | 357 | static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); |
382 | 358 | ||
383 | /* Peripheral Cluster #2 */ | 359 | /* Peripheral Cluster #2 */ |
384 | 360 | ||
385 | static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL); | 361 | static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL); |
386 | static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL); | 362 | static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL); |
387 | static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL); | 363 | static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL); |
388 | static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL); | 364 | static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL); |
389 | static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk); | 365 | static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk); |
390 | static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk); | 366 | static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk); |
391 | static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk); | 367 | static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk); |
392 | static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk); | 368 | static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk); |
393 | static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL); | 369 | static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL); |
394 | static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL); | 370 | static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL); |
395 | static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL); | 371 | static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL); |
396 | static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk); | 372 | static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk); |
397 | 373 | ||
398 | static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL); | 374 | static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL); |
399 | static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL); | 375 | static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL); |
400 | static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL); | 376 | static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL); |
401 | static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL); | 377 | static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL); |
402 | static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk); | 378 | static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk); |
403 | static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk); | 379 | static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk); |
404 | static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk); | 380 | static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk); |
405 | static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk); | 381 | static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk); |
406 | static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL); | 382 | static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL); |
407 | static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL); | 383 | static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL); |
408 | static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL); | 384 | static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL); |
409 | static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk); | 385 | static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk); |
410 | 386 | ||
411 | /* Peripheral Cluster #3 */ | 387 | /* Peripheral Cluster #3 */ |
412 | static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); | 388 | static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); |
413 | static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); | 389 | static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); |
414 | static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); | 390 | static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); |
415 | static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); | 391 | static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); |
416 | static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); | 392 | static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); |
417 | static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); | 393 | static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); |
418 | static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk); | 394 | static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk); |
419 | static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk); | 395 | static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk); |
420 | static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk); | 396 | static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk); |
421 | static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk); | 397 | static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk); |
422 | static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); | 398 | static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); |
423 | 399 | ||
424 | /* Peripheral Cluster #4 is in the always on domain */ | 400 | /* Peripheral Cluster #4 is in the always on domain */ |
425 | 401 | ||
426 | /* Peripheral Cluster #5 */ | 402 | /* Peripheral Cluster #5 */ |
427 | static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); | 403 | static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); |
428 | static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk); | 404 | static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk); |
429 | static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL); | 405 | static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL); |
430 | 406 | ||
431 | /* Peripheral Cluster #6 */ | 407 | /* Peripheral Cluster #6 */ |
432 | 408 | ||
433 | /* MTU ID in data */ | 409 | /* MTU ID in data */ |
434 | static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1); | 410 | static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1); |
435 | static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0); | 411 | static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0); |
436 | static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); | 412 | static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); |
437 | static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); | 413 | static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); |
438 | static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); | 414 | static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); |
439 | static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk); | 415 | static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk); |
440 | static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL); | 416 | static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL); |
441 | static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL); | 417 | static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL); |
442 | static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL); | 418 | static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL); |
443 | static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL); | 419 | static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL); |
444 | static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk); | 420 | static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk); |
445 | static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk); | 421 | static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk); |
446 | 422 | ||
447 | /* Peripheral Cluster #7 */ | 423 | /* Peripheral Cluster #7 */ |
448 | 424 | ||
449 | static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); | 425 | static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); |
450 | /* MTU ID in data */ | 426 | /* MTU ID in data */ |
451 | static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1); | 427 | static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1); |
452 | static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0); | 428 | static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0); |
453 | static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); | 429 | static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); |
454 | static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); | 430 | static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); |
455 | 431 | ||
456 | static struct clk clk_dummy_apb_pclk; | 432 | static struct clk clk_dummy_apb_pclk = { |
433 | .name = "apb_pclk", | ||
434 | }; | ||
457 | 435 | ||
458 | static struct clk_lookup u8500_common_clks[] = { | 436 | static struct clk_lookup u8500_common_clks[] = { |
459 | CLK(dummy_apb_pclk, NULL, "apb_pclk"), | 437 | CLK(dummy_apb_pclk, NULL, "apb_pclk"), |
@@ -554,7 +532,7 @@ static struct clk_lookup u8500_ed_clks[] = { | |||
554 | 532 | ||
555 | static struct clk_lookup u8500_v1_clks[] = { | 533 | static struct clk_lookup u8500_v1_clks[] = { |
556 | /* Peripheral Cluster #1 */ | 534 | /* Peripheral Cluster #1 */ |
557 | CLK(i2c4, "nmk-i2c.4", NULL), | 535 | CLK(i2c4, "nmk-i2c.4", NULL), |
558 | CLK(spi3_v1, "spi3", NULL), | 536 | CLK(spi3_v1, "spi3", NULL), |
559 | CLK(msp1_v1, "msp1", NULL), | 537 | CLK(msp1_v1, "msp1", NULL), |
560 | 538 | ||
@@ -599,6 +577,183 @@ static struct clk_lookup u8500_v1_clks[] = { | |||
599 | CLK(uiccclk, "uicc", NULL), | 577 | CLK(uiccclk, "uicc", NULL), |
600 | }; | 578 | }; |
601 | 579 | ||
580 | #ifdef CONFIG_DEBUG_FS | ||
581 | /* | ||
582 | * debugfs support to trace clock tree hierarchy and attributes with | ||
583 | * powerdebug | ||
584 | */ | ||
585 | static struct dentry *clk_debugfs_root; | ||
586 | |||
587 | void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num) | ||
588 | { | ||
589 | while (num--) { | ||
590 | /* Check that the clock has not been already registered */ | ||
591 | if (!(cl->clk->list.prev != cl->clk->list.next)) | ||
592 | list_add_tail(&cl->clk->list, &clk_list); | ||
593 | |||
594 | cl++; | ||
595 | } | ||
596 | } | ||
597 | |||
598 | static ssize_t usecount_dbg_read(struct file *file, char __user *buf, | ||
599 | size_t size, loff_t *off) | ||
600 | { | ||
601 | struct clk *clk = file->f_dentry->d_inode->i_private; | ||
602 | char cusecount[128]; | ||
603 | unsigned int len; | ||
604 | |||
605 | len = sprintf(cusecount, "%u\n", clk->enabled); | ||
606 | return simple_read_from_buffer(buf, size, off, cusecount, len); | ||
607 | } | ||
608 | |||
609 | static ssize_t rate_dbg_read(struct file *file, char __user *buf, | ||
610 | size_t size, loff_t *off) | ||
611 | { | ||
612 | struct clk *clk = file->f_dentry->d_inode->i_private; | ||
613 | char crate[128]; | ||
614 | unsigned int rate; | ||
615 | unsigned int len; | ||
616 | |||
617 | rate = clk_get_rate(clk); | ||
618 | len = sprintf(crate, "%u\n", rate); | ||
619 | return simple_read_from_buffer(buf, size, off, crate, len); | ||
620 | } | ||
621 | |||
622 | static const struct file_operations usecount_fops = { | ||
623 | .read = usecount_dbg_read, | ||
624 | }; | ||
625 | |||
626 | static const struct file_operations set_rate_fops = { | ||
627 | .read = rate_dbg_read, | ||
628 | }; | ||
629 | |||
630 | static struct dentry *clk_debugfs_register_dir(struct clk *c, | ||
631 | struct dentry *p_dentry) | ||
632 | { | ||
633 | struct dentry *d, *clk_d, *child, *child_tmp; | ||
634 | char s[255]; | ||
635 | char *p = s; | ||
636 | |||
637 | if (c->name == NULL) | ||
638 | p += sprintf(p, "BUG"); | ||
639 | else | ||
640 | p += sprintf(p, "%s", c->name); | ||
641 | |||
642 | clk_d = debugfs_create_dir(s, p_dentry); | ||
643 | if (!clk_d) | ||
644 | return NULL; | ||
645 | |||
646 | d = debugfs_create_file("usecount", S_IRUGO, | ||
647 | clk_d, c, &usecount_fops); | ||
648 | if (!d) | ||
649 | goto err_out; | ||
650 | d = debugfs_create_file("rate", S_IRUGO, | ||
651 | clk_d, c, &set_rate_fops); | ||
652 | if (!d) | ||
653 | goto err_out; | ||
654 | /* | ||
655 | * TODO : not currently available in ux500 | ||
656 | * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags); | ||
657 | * if (!d) | ||
658 | * goto err_out; | ||
659 | */ | ||
660 | |||
661 | return clk_d; | ||
662 | |||
663 | err_out: | ||
664 | d = clk_d; | ||
665 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
666 | debugfs_remove(child); | ||
667 | debugfs_remove(clk_d); | ||
668 | return NULL; | ||
669 | } | ||
670 | |||
671 | static void clk_debugfs_remove_dir(struct dentry *cdentry) | ||
672 | { | ||
673 | struct dentry *d, *child, *child_tmp; | ||
674 | |||
675 | d = cdentry; | ||
676 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
677 | debugfs_remove(child); | ||
678 | debugfs_remove(cdentry); | ||
679 | return ; | ||
680 | } | ||
681 | |||
682 | static int clk_debugfs_register_one(struct clk *c) | ||
683 | { | ||
684 | struct clk *pa = c->parent_periph; | ||
685 | struct clk *bpa = c->parent_cluster; | ||
686 | |||
687 | if (!(bpa && !pa)) { | ||
688 | c->dent = clk_debugfs_register_dir(c, | ||
689 | pa ? pa->dent : clk_debugfs_root); | ||
690 | if (!c->dent) | ||
691 | return -ENOMEM; | ||
692 | } | ||
693 | |||
694 | if (bpa) { | ||
695 | c->dent_bus = clk_debugfs_register_dir(c, | ||
696 | bpa->dent_bus ? bpa->dent_bus : bpa->dent); | ||
697 | if ((!c->dent_bus) && (c->dent)) { | ||
698 | clk_debugfs_remove_dir(c->dent); | ||
699 | c->dent = NULL; | ||
700 | return -ENOMEM; | ||
701 | } | ||
702 | } | ||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | static int clk_debugfs_register(struct clk *c) | ||
707 | { | ||
708 | int err; | ||
709 | struct clk *pa = c->parent_periph; | ||
710 | struct clk *bpa = c->parent_cluster; | ||
711 | |||
712 | if (pa && (!pa->dent && !pa->dent_bus)) { | ||
713 | err = clk_debugfs_register(pa); | ||
714 | if (err) | ||
715 | return err; | ||
716 | } | ||
717 | |||
718 | if (bpa && (!bpa->dent && !bpa->dent_bus)) { | ||
719 | err = clk_debugfs_register(bpa); | ||
720 | if (err) | ||
721 | return err; | ||
722 | } | ||
723 | |||
724 | if ((!c->dent) && (!c->dent_bus)) { | ||
725 | err = clk_debugfs_register_one(c); | ||
726 | if (err) | ||
727 | return err; | ||
728 | } | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int __init clk_debugfs_init(void) | ||
733 | { | ||
734 | struct clk *c; | ||
735 | struct dentry *d; | ||
736 | int err; | ||
737 | |||
738 | d = debugfs_create_dir("clock", NULL); | ||
739 | if (!d) | ||
740 | return -ENOMEM; | ||
741 | clk_debugfs_root = d; | ||
742 | |||
743 | list_for_each_entry(c, &clk_list, list) { | ||
744 | err = clk_debugfs_register(c); | ||
745 | if (err) | ||
746 | goto err_out; | ||
747 | } | ||
748 | return 0; | ||
749 | err_out: | ||
750 | debugfs_remove_recursive(clk_debugfs_root); | ||
751 | return err; | ||
752 | } | ||
753 | |||
754 | late_initcall(clk_debugfs_init); | ||
755 | #endif /* defined(CONFIG_DEBUG_FS) */ | ||
756 | |||
602 | int __init clk_init(void) | 757 | int __init clk_init(void) |
603 | { | 758 | { |
604 | if (cpu_is_u8500ed()) { | 759 | if (cpu_is_u8500ed()) { |
@@ -609,7 +764,8 @@ int __init clk_init(void) | |||
609 | /* Clock tree for U5500 not implemented yet */ | 764 | /* Clock tree for U5500 not implemented yet */ |
610 | clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; | 765 | clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; |
611 | clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; | 766 | clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; |
612 | clk_per6clk.rate = 26000000; | 767 | clk_uartclk.rate = 36360000; |
768 | clk_sdmmcclk.rate = 99900000; | ||
613 | } | 769 | } |
614 | 770 | ||
615 | clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); | 771 | clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); |
@@ -618,5 +774,12 @@ int __init clk_init(void) | |||
618 | else | 774 | else |
619 | clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); | 775 | clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); |
620 | 776 | ||
777 | #ifdef CONFIG_DEBUG_FS | ||
778 | clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); | ||
779 | if (cpu_is_u8500ed()) | ||
780 | clk_debugfs_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks)); | ||
781 | else | ||
782 | clk_debugfs_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); | ||
783 | #endif | ||
621 | return 0; | 784 | return 0; |
622 | } | 785 | } |
diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h index a05802501527..074490705229 100644 --- a/arch/arm/mach-ux500/clock.h +++ b/arch/arm/mach-ux500/clock.h | |||
@@ -90,6 +90,10 @@ struct clk { | |||
90 | 90 | ||
91 | struct clk *parent_cluster; | 91 | struct clk *parent_cluster; |
92 | struct clk *parent_periph; | 92 | struct clk *parent_periph; |
93 | #if defined(CONFIG_DEBUG_FS) | ||
94 | struct dentry *dent; /* For visible tree hierarchy */ | ||
95 | struct dentry *dent_bus; /* For visible tree hierarchy */ | ||
96 | #endif | ||
93 | }; | 97 | }; |
94 | 98 | ||
95 | #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ | 99 | #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ |
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 2f87075e9d6f..acc841e48de4 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c | |||
@@ -8,14 +8,19 @@ | |||
8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
9 | #include <linux/amba/bus.h> | 9 | #include <linux/amba/bus.h> |
10 | #include <linux/io.h> | 10 | #include <linux/io.h> |
11 | #include <linux/irq.h> | ||
11 | 12 | ||
12 | #include <asm/mach/map.h> | 13 | #include <asm/mach/map.h> |
13 | 14 | ||
15 | #include <plat/gpio.h> | ||
16 | |||
14 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
15 | #include <mach/devices.h> | 18 | #include <mach/devices.h> |
16 | #include <mach/setup.h> | 19 | #include <mach/setup.h> |
17 | #include <mach/irqs.h> | 20 | #include <mach/irqs.h> |
18 | 21 | ||
22 | #include "devices-db5500.h" | ||
23 | |||
19 | static struct map_desc u5500_io_desc[] __initdata = { | 24 | static struct map_desc u5500_io_desc[] __initdata = { |
20 | __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), | 25 | __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), |
21 | __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K), | 26 | __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K), |
@@ -110,19 +115,32 @@ static struct platform_device mbox2_device = { | |||
110 | }; | 115 | }; |
111 | 116 | ||
112 | static struct platform_device *u5500_platform_devs[] __initdata = { | 117 | static struct platform_device *u5500_platform_devs[] __initdata = { |
113 | &u5500_gpio_devs[0], | ||
114 | &u5500_gpio_devs[1], | ||
115 | &u5500_gpio_devs[2], | ||
116 | &u5500_gpio_devs[3], | ||
117 | &u5500_gpio_devs[4], | ||
118 | &u5500_gpio_devs[5], | ||
119 | &u5500_gpio_devs[6], | ||
120 | &u5500_gpio_devs[7], | ||
121 | &mbox0_device, | 118 | &mbox0_device, |
122 | &mbox1_device, | 119 | &mbox1_device, |
123 | &mbox2_device, | 120 | &mbox2_device, |
124 | }; | 121 | }; |
125 | 122 | ||
123 | static resource_size_t __initdata db5500_gpio_base[] = { | ||
124 | U5500_GPIOBANK0_BASE, | ||
125 | U5500_GPIOBANK1_BASE, | ||
126 | U5500_GPIOBANK2_BASE, | ||
127 | U5500_GPIOBANK3_BASE, | ||
128 | U5500_GPIOBANK4_BASE, | ||
129 | U5500_GPIOBANK5_BASE, | ||
130 | U5500_GPIOBANK6_BASE, | ||
131 | U5500_GPIOBANK7_BASE, | ||
132 | }; | ||
133 | |||
134 | static void __init db5500_add_gpios(void) | ||
135 | { | ||
136 | struct nmk_gpio_platform_data pdata = { | ||
137 | /* No custom data yet */ | ||
138 | }; | ||
139 | |||
140 | dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base), | ||
141 | IRQ_DB5500_GPIO0, &pdata); | ||
142 | } | ||
143 | |||
126 | void __init u5500_map_io(void) | 144 | void __init u5500_map_io(void) |
127 | { | 145 | { |
128 | ux500_map_io(); | 146 | ux500_map_io(); |
@@ -132,7 +150,9 @@ void __init u5500_map_io(void) | |||
132 | 150 | ||
133 | void __init u5500_init_devices(void) | 151 | void __init u5500_init_devices(void) |
134 | { | 152 | { |
135 | ux500_init_devices(); | 153 | db5500_add_gpios(); |
154 | db5500_dma_init(); | ||
155 | db5500_add_rtc(); | ||
136 | 156 | ||
137 | platform_add_devices(u5500_platform_devs, | 157 | platform_add_devices(u5500_platform_devs, |
138 | ARRAY_SIZE(u5500_platform_devs)); | 158 | ARRAY_SIZE(u5500_platform_devs)); |
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 4acab7544b3c..c0f34a404c53 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c | |||
@@ -22,23 +22,15 @@ | |||
22 | #include <mach/setup.h> | 22 | #include <mach/setup.h> |
23 | #include <mach/devices.h> | 23 | #include <mach/devices.h> |
24 | 24 | ||
25 | #include "devices-db8500.h" | ||
26 | |||
25 | static struct platform_device *platform_devs[] __initdata = { | 27 | static struct platform_device *platform_devs[] __initdata = { |
26 | &u8500_gpio_devs[0], | ||
27 | &u8500_gpio_devs[1], | ||
28 | &u8500_gpio_devs[2], | ||
29 | &u8500_gpio_devs[3], | ||
30 | &u8500_gpio_devs[4], | ||
31 | &u8500_gpio_devs[5], | ||
32 | &u8500_gpio_devs[6], | ||
33 | &u8500_gpio_devs[7], | ||
34 | &u8500_gpio_devs[8], | ||
35 | &u8500_dma40_device, | 28 | &u8500_dma40_device, |
36 | }; | 29 | }; |
37 | 30 | ||
38 | /* minimum static i/o mapping required to boot U8500 platforms */ | 31 | /* minimum static i/o mapping required to boot U8500 platforms */ |
39 | static struct map_desc u8500_io_desc[] __initdata = { | 32 | static struct map_desc u8500_io_desc[] __initdata = { |
40 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), | 33 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), |
41 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), | ||
42 | __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), | 34 | __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), |
43 | __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), | 35 | __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), |
44 | __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), | 36 | __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), |
@@ -46,13 +38,18 @@ static struct map_desc u8500_io_desc[] __initdata = { | |||
46 | __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M), | 38 | __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M), |
47 | }; | 39 | }; |
48 | 40 | ||
49 | static struct map_desc u8500ed_io_desc[] __initdata = { | 41 | static struct map_desc u8500_ed_io_desc[] __initdata = { |
50 | __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), | 42 | __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), |
51 | __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), | 43 | __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), |
52 | }; | 44 | }; |
53 | 45 | ||
54 | static struct map_desc u8500v1_io_desc[] __initdata = { | 46 | static struct map_desc u8500_v1_io_desc[] __initdata = { |
55 | __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), | 47 | __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), |
48 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K), | ||
49 | }; | ||
50 | |||
51 | static struct map_desc u8500_v2_io_desc[] __initdata = { | ||
52 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), | ||
56 | }; | 53 | }; |
57 | 54 | ||
58 | /* | 55 | /* |
@@ -125,14 +122,38 @@ void __init u8500_map_io(void) | |||
125 | iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); | 122 | iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); |
126 | 123 | ||
127 | if (cpu_is_u8500ed()) | 124 | if (cpu_is_u8500ed()) |
128 | iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); | 125 | iotable_init(u8500_ed_io_desc, ARRAY_SIZE(u8500_ed_io_desc)); |
129 | else | 126 | else if (cpu_is_u8500v1()) |
130 | iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); | 127 | iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc)); |
128 | else if (cpu_is_u8500v2()) | ||
129 | iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); | ||
131 | 130 | ||
132 | /* Read out the ASIC ID as early as we can */ | 131 | /* Read out the ASIC ID as early as we can */ |
133 | get_db8500_asic_id(); | 132 | get_db8500_asic_id(); |
134 | } | 133 | } |
135 | 134 | ||
135 | static resource_size_t __initdata db8500_gpio_base[] = { | ||
136 | U8500_GPIOBANK0_BASE, | ||
137 | U8500_GPIOBANK1_BASE, | ||
138 | U8500_GPIOBANK2_BASE, | ||
139 | U8500_GPIOBANK3_BASE, | ||
140 | U8500_GPIOBANK4_BASE, | ||
141 | U8500_GPIOBANK5_BASE, | ||
142 | U8500_GPIOBANK6_BASE, | ||
143 | U8500_GPIOBANK7_BASE, | ||
144 | U8500_GPIOBANK8_BASE, | ||
145 | }; | ||
146 | |||
147 | static void __init db8500_add_gpios(void) | ||
148 | { | ||
149 | struct nmk_gpio_platform_data pdata = { | ||
150 | /* No custom data yet */ | ||
151 | }; | ||
152 | |||
153 | dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), | ||
154 | IRQ_DB8500_GPIO0, &pdata); | ||
155 | } | ||
156 | |||
136 | /* | 157 | /* |
137 | * This function is called from the board init | 158 | * This function is called from the board init |
138 | */ | 159 | */ |
@@ -152,12 +173,13 @@ void __init u8500_init_devices(void) | |||
152 | else | 173 | else |
153 | pr_warning("ASIC: UNKNOWN SILICON VERSION!\n"); | 174 | pr_warning("ASIC: UNKNOWN SILICON VERSION!\n"); |
154 | 175 | ||
155 | ux500_init_devices(); | ||
156 | |||
157 | if (cpu_is_u8500ed()) | 176 | if (cpu_is_u8500ed()) |
158 | dma40_u8500ed_fixup(); | 177 | dma40_u8500ed_fixup(); |
159 | 178 | ||
160 | /* Register the platform devices */ | 179 | db8500_add_rtc(); |
180 | db8500_add_gpios(); | ||
181 | |||
182 | platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); | ||
161 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); | 183 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); |
162 | 184 | ||
163 | return ; | 185 | return ; |
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 608a1372b172..a3700bc374d3 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c | |||
@@ -6,7 +6,6 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
9 | #include <linux/amba/bus.h> | ||
10 | #include <linux/io.h> | 9 | #include <linux/io.h> |
11 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
12 | 11 | ||
@@ -20,6 +19,7 @@ | |||
20 | #include <mach/hardware.h> | 19 | #include <mach/hardware.h> |
21 | #include <mach/setup.h> | 20 | #include <mach/setup.h> |
22 | #include <mach/devices.h> | 21 | #include <mach/devices.h> |
22 | #include <mach/prcmu.h> | ||
23 | 23 | ||
24 | #include "clock.h" | 24 | #include "clock.h" |
25 | 25 | ||
@@ -45,20 +45,11 @@ static struct map_desc ux500_io_desc[] __initdata = { | |||
45 | __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K), | 45 | __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K), |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static struct amba_device *ux500_amba_devs[] __initdata = { | ||
49 | &ux500_pl031_device, | ||
50 | }; | ||
51 | |||
52 | void __init ux500_map_io(void) | 48 | void __init ux500_map_io(void) |
53 | { | 49 | { |
54 | iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc)); | 50 | iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc)); |
55 | } | 51 | } |
56 | 52 | ||
57 | void __init ux500_init_devices(void) | ||
58 | { | ||
59 | amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs)); | ||
60 | } | ||
61 | |||
62 | void __init ux500_init_irq(void) | 53 | void __init ux500_init_irq(void) |
63 | { | 54 | { |
64 | gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); | 55 | gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); |
@@ -68,6 +59,8 @@ void __init ux500_init_irq(void) | |||
68 | * Init clocks here so that they are available for system timer | 59 | * Init clocks here so that they are available for system timer |
69 | * initialization. | 60 | * initialization. |
70 | */ | 61 | */ |
62 | if (cpu_is_u8500()) | ||
63 | prcmu_early_init(); | ||
71 | clk_init(); | 64 | clk_init(); |
72 | } | 65 | } |
73 | 66 | ||
diff --git a/arch/arm/mach-ux500/cpufreq.c b/arch/arm/mach-ux500/cpufreq.c new file mode 100644 index 000000000000..5c5b747f134d --- /dev/null +++ b/arch/arm/mach-ux500/cpufreq.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * CPU frequency scaling for u8500 | ||
3 | * Inspired by linux/arch/arm/mach-davinci/cpufreq.c | ||
4 | * | ||
5 | * Copyright (C) STMicroelectronics 2009 | ||
6 | * Copyright (C) ST-Ericsson SA 2010 | ||
7 | * | ||
8 | * License Terms: GNU General Public License v2 | ||
9 | * | ||
10 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> | ||
11 | * Author: Martin Persson <martin.persson@stericsson.com> | ||
12 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/cpufreq.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #include <mach/hardware.h> | ||
22 | #include <mach/prcmu.h> | ||
23 | #include <mach/prcmu-defs.h> | ||
24 | |||
25 | #define DRIVER_NAME "cpufreq-u8500" | ||
26 | #define CPUFREQ_NAME "u8500" | ||
27 | |||
28 | static struct device *dev; | ||
29 | |||
30 | static struct cpufreq_frequency_table freq_table[] = { | ||
31 | [0] = { | ||
32 | .index = 0, | ||
33 | .frequency = 200000, | ||
34 | }, | ||
35 | [1] = { | ||
36 | .index = 1, | ||
37 | .frequency = 300000, | ||
38 | }, | ||
39 | [2] = { | ||
40 | .index = 2, | ||
41 | .frequency = 600000, | ||
42 | }, | ||
43 | [3] = { | ||
44 | /* Used for CPU_OPP_MAX, if available */ | ||
45 | .index = 3, | ||
46 | .frequency = CPUFREQ_TABLE_END, | ||
47 | }, | ||
48 | [4] = { | ||
49 | .index = 4, | ||
50 | .frequency = CPUFREQ_TABLE_END, | ||
51 | }, | ||
52 | }; | ||
53 | |||
54 | static enum prcmu_cpu_opp index2opp[] = { | ||
55 | CPU_OPP_EXT_CLK, | ||
56 | CPU_OPP_50, | ||
57 | CPU_OPP_100, | ||
58 | CPU_OPP_MAX | ||
59 | }; | ||
60 | |||
61 | static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy) | ||
62 | { | ||
63 | return cpufreq_frequency_table_verify(policy, freq_table); | ||
64 | } | ||
65 | |||
66 | static int u8500_cpufreq_target(struct cpufreq_policy *policy, | ||
67 | unsigned int target_freq, | ||
68 | unsigned int relation) | ||
69 | { | ||
70 | struct cpufreq_freqs freqs; | ||
71 | unsigned int index; | ||
72 | int ret = 0; | ||
73 | |||
74 | /* | ||
75 | * Ensure desired rate is within allowed range. Some govenors | ||
76 | * (ondemand) will just pass target_freq=0 to get the minimum. | ||
77 | */ | ||
78 | if (target_freq < policy->cpuinfo.min_freq) | ||
79 | target_freq = policy->cpuinfo.min_freq; | ||
80 | if (target_freq > policy->cpuinfo.max_freq) | ||
81 | target_freq = policy->cpuinfo.max_freq; | ||
82 | |||
83 | ret = cpufreq_frequency_table_target(policy, freq_table, | ||
84 | target_freq, relation, &index); | ||
85 | if (ret < 0) { | ||
86 | dev_err(dev, "Could not look up next frequency\n"); | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | freqs.old = policy->cur; | ||
91 | freqs.new = freq_table[index].frequency; | ||
92 | freqs.cpu = policy->cpu; | ||
93 | |||
94 | if (freqs.old == freqs.new) { | ||
95 | dev_dbg(dev, "Current and target frequencies are equal\n"); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new); | ||
100 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
101 | |||
102 | ret = prcmu_set_cpu_opp(index2opp[index]); | ||
103 | if (ret < 0) { | ||
104 | dev_err(dev, "Failed to set OPP level\n"); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static unsigned int u8500_cpufreq_getspeed(unsigned int cpu) | ||
114 | { | ||
115 | int i; | ||
116 | |||
117 | for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++) | ||
118 | ; | ||
119 | return freq_table[i].frequency; | ||
120 | } | ||
121 | |||
122 | static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy) | ||
123 | { | ||
124 | int res; | ||
125 | |||
126 | BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table)); | ||
127 | |||
128 | if (cpu_is_u8500v2()) { | ||
129 | freq_table[1].frequency = 400000; | ||
130 | freq_table[2].frequency = 800000; | ||
131 | if (prcmu_has_arm_maxopp()) | ||
132 | freq_table[3].frequency = 1000000; | ||
133 | } | ||
134 | |||
135 | /* get policy fields based on the table */ | ||
136 | res = cpufreq_frequency_table_cpuinfo(policy, freq_table); | ||
137 | if (!res) | ||
138 | cpufreq_frequency_table_get_attr(freq_table, policy->cpu); | ||
139 | else { | ||
140 | dev_err(dev, "u8500-cpufreq : Failed to read policy table\n"); | ||
141 | return res; | ||
142 | } | ||
143 | |||
144 | policy->min = policy->cpuinfo.min_freq; | ||
145 | policy->max = policy->cpuinfo.max_freq; | ||
146 | policy->cur = u8500_cpufreq_getspeed(policy->cpu); | ||
147 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
148 | |||
149 | /* | ||
150 | * FIXME : Need to take time measurement across the target() | ||
151 | * function with no/some/all drivers in the notification | ||
152 | * list. | ||
153 | */ | ||
154 | policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */ | ||
155 | |||
156 | /* policy sharing between dual CPUs */ | ||
157 | cpumask_copy(policy->cpus, &cpu_present_map); | ||
158 | |||
159 | policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; | ||
160 | |||
161 | return res; | ||
162 | } | ||
163 | |||
164 | static struct freq_attr *u8500_cpufreq_attr[] = { | ||
165 | &cpufreq_freq_attr_scaling_available_freqs, | ||
166 | NULL, | ||
167 | }; | ||
168 | static int u8500_cpu_exit(struct cpufreq_policy *policy) | ||
169 | { | ||
170 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static struct cpufreq_driver u8500_driver = { | ||
175 | .owner = THIS_MODULE, | ||
176 | .flags = CPUFREQ_STICKY, | ||
177 | .verify = u8500_cpufreq_verify_speed, | ||
178 | .target = u8500_cpufreq_target, | ||
179 | .get = u8500_cpufreq_getspeed, | ||
180 | .init = u8500_cpu_init, | ||
181 | .exit = u8500_cpu_exit, | ||
182 | .name = CPUFREQ_NAME, | ||
183 | .attr = u8500_cpufreq_attr, | ||
184 | }; | ||
185 | |||
186 | static int __init u8500_cpufreq_probe(struct platform_device *pdev) | ||
187 | { | ||
188 | dev = &pdev->dev; | ||
189 | return cpufreq_register_driver(&u8500_driver); | ||
190 | } | ||
191 | |||
192 | static int __exit u8500_cpufreq_remove(struct platform_device *pdev) | ||
193 | { | ||
194 | return cpufreq_unregister_driver(&u8500_driver); | ||
195 | } | ||
196 | |||
197 | static struct platform_driver u8500_cpufreq_driver = { | ||
198 | .driver = { | ||
199 | .name = DRIVER_NAME, | ||
200 | .owner = THIS_MODULE, | ||
201 | }, | ||
202 | .remove = __exit_p(u8500_cpufreq_remove), | ||
203 | }; | ||
204 | |||
205 | static int __init u8500_cpufreq_init(void) | ||
206 | { | ||
207 | return platform_driver_probe(&u8500_cpufreq_driver, | ||
208 | &u8500_cpufreq_probe); | ||
209 | } | ||
210 | |||
211 | device_initcall(u8500_cpufreq_init); | ||
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c new file mode 100644 index 000000000000..fe69f5fac1bb --- /dev/null +++ b/arch/arm/mach-ux500/devices-common.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
5 | * License terms: GNU General Public License (GPL), version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/dma-mapping.h> | ||
10 | #include <linux/err.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/amba/bus.h> | ||
15 | |||
16 | #include <plat/gpio.h> | ||
17 | |||
18 | #include <mach/hardware.h> | ||
19 | |||
20 | #include "devices-common.h" | ||
21 | |||
22 | struct amba_device * | ||
23 | dbx500_add_amba_device(const char *name, resource_size_t base, | ||
24 | int irq, void *pdata, unsigned int periphid) | ||
25 | { | ||
26 | struct amba_device *dev; | ||
27 | int ret; | ||
28 | |||
29 | dev = kzalloc(sizeof *dev, GFP_KERNEL); | ||
30 | if (!dev) | ||
31 | return ERR_PTR(-ENOMEM); | ||
32 | |||
33 | dev->dev.init_name = name; | ||
34 | |||
35 | dev->res.start = base; | ||
36 | dev->res.end = base + SZ_4K - 1; | ||
37 | dev->res.flags = IORESOURCE_MEM; | ||
38 | |||
39 | dev->dma_mask = DMA_BIT_MASK(32); | ||
40 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
41 | |||
42 | dev->irq[0] = irq; | ||
43 | dev->irq[1] = NO_IRQ; | ||
44 | |||
45 | dev->periphid = periphid; | ||
46 | |||
47 | dev->dev.platform_data = pdata; | ||
48 | |||
49 | ret = amba_device_register(dev, &iomem_resource); | ||
50 | if (ret) { | ||
51 | kfree(dev); | ||
52 | return ERR_PTR(ret); | ||
53 | } | ||
54 | |||
55 | return dev; | ||
56 | } | ||
57 | |||
58 | static struct platform_device * | ||
59 | dbx500_add_platform_device(const char *name, int id, void *pdata, | ||
60 | struct resource *res, int resnum) | ||
61 | { | ||
62 | struct platform_device *dev; | ||
63 | int ret; | ||
64 | |||
65 | dev = platform_device_alloc(name, id); | ||
66 | if (!dev) | ||
67 | return ERR_PTR(-ENOMEM); | ||
68 | |||
69 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
70 | dev->dev.dma_mask = &dev->dev.coherent_dma_mask; | ||
71 | |||
72 | ret = platform_device_add_resources(dev, res, resnum); | ||
73 | if (ret) | ||
74 | goto out_free; | ||
75 | |||
76 | dev->dev.platform_data = pdata; | ||
77 | |||
78 | ret = platform_device_add(dev); | ||
79 | if (ret) | ||
80 | goto out_free; | ||
81 | |||
82 | return dev; | ||
83 | |||
84 | out_free: | ||
85 | platform_device_put(dev); | ||
86 | return ERR_PTR(ret); | ||
87 | } | ||
88 | |||
89 | struct platform_device * | ||
90 | dbx500_add_platform_device_4k1irq(const char *name, int id, | ||
91 | resource_size_t base, | ||
92 | int irq, void *pdata) | ||
93 | { | ||
94 | struct resource resources[] = { | ||
95 | [0] = { | ||
96 | .start = base, | ||
97 | .end = base + SZ_4K - 1, | ||
98 | .flags = IORESOURCE_MEM, | ||
99 | }, | ||
100 | [1] = { | ||
101 | .start = irq, | ||
102 | .end = irq, | ||
103 | .flags = IORESOURCE_IRQ, | ||
104 | } | ||
105 | }; | ||
106 | |||
107 | return dbx500_add_platform_device(name, id, pdata, resources, | ||
108 | ARRAY_SIZE(resources)); | ||
109 | } | ||
110 | |||
111 | static struct platform_device * | ||
112 | dbx500_add_gpio(int id, resource_size_t addr, int irq, | ||
113 | struct nmk_gpio_platform_data *pdata) | ||
114 | { | ||
115 | struct resource resources[] = { | ||
116 | { | ||
117 | .start = addr, | ||
118 | .end = addr + 127, | ||
119 | .flags = IORESOURCE_MEM, | ||
120 | }, | ||
121 | { | ||
122 | .start = irq, | ||
123 | .end = irq, | ||
124 | .flags = IORESOURCE_IRQ, | ||
125 | } | ||
126 | }; | ||
127 | |||
128 | return platform_device_register_resndata(NULL, "gpio", id, | ||
129 | resources, ARRAY_SIZE(resources), | ||
130 | pdata, sizeof(*pdata)); | ||
131 | } | ||
132 | |||
133 | void dbx500_add_gpios(resource_size_t *base, int num, int irq, | ||
134 | struct nmk_gpio_platform_data *pdata) | ||
135 | { | ||
136 | int first = 0; | ||
137 | int i; | ||
138 | |||
139 | for (i = 0; i < num; i++, first += 32, irq++) { | ||
140 | pdata->first_gpio = first; | ||
141 | pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); | ||
142 | |||
143 | dbx500_add_gpio(i, base[i], irq, pdata); | ||
144 | } | ||
145 | } | ||
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h new file mode 100644 index 000000000000..cbadc117d2db --- /dev/null +++ b/arch/arm/mach-ux500/devices-common.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
5 | * License terms: GNU General Public License (GPL), version 2. | ||
6 | */ | ||
7 | |||
8 | #ifndef __DEVICES_COMMON_H | ||
9 | #define __DEVICES_COMMON_H | ||
10 | |||
11 | extern struct amba_device * | ||
12 | dbx500_add_amba_device(const char *name, resource_size_t base, | ||
13 | int irq, void *pdata, unsigned int periphid); | ||
14 | |||
15 | extern struct platform_device * | ||
16 | dbx500_add_platform_device_4k1irq(const char *name, int id, | ||
17 | resource_size_t base, | ||
18 | int irq, void *pdata); | ||
19 | |||
20 | struct spi_master_cntlr; | ||
21 | |||
22 | static inline struct amba_device * | ||
23 | dbx500_add_msp_spi(const char *name, resource_size_t base, int irq, | ||
24 | struct spi_master_cntlr *pdata) | ||
25 | { | ||
26 | return dbx500_add_amba_device(name, base, irq, pdata, 0); | ||
27 | } | ||
28 | |||
29 | static inline struct amba_device * | ||
30 | dbx500_add_spi(const char *name, resource_size_t base, int irq, | ||
31 | struct spi_master_cntlr *pdata) | ||
32 | { | ||
33 | return dbx500_add_amba_device(name, base, irq, pdata, 0); | ||
34 | } | ||
35 | |||
36 | struct mmci_platform_data; | ||
37 | |||
38 | static inline struct amba_device * | ||
39 | dbx500_add_sdi(const char *name, resource_size_t base, int irq, | ||
40 | struct mmci_platform_data *pdata) | ||
41 | { | ||
42 | return dbx500_add_amba_device(name, base, irq, pdata, 0); | ||
43 | } | ||
44 | |||
45 | static inline struct amba_device * | ||
46 | dbx500_add_uart(const char *name, resource_size_t base, int irq) | ||
47 | { | ||
48 | return dbx500_add_amba_device(name, base, irq, NULL, 0); | ||
49 | } | ||
50 | |||
51 | struct nmk_i2c_controller; | ||
52 | |||
53 | static inline struct platform_device * | ||
54 | dbx500_add_i2c(int id, resource_size_t base, int irq, | ||
55 | struct nmk_i2c_controller *pdata) | ||
56 | { | ||
57 | return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq, | ||
58 | pdata); | ||
59 | } | ||
60 | |||
61 | struct msp_i2s_platform_data; | ||
62 | |||
63 | static inline struct platform_device * | ||
64 | dbx500_add_msp_i2s(int id, resource_size_t base, int irq, | ||
65 | struct msp_i2s_platform_data *pdata) | ||
66 | { | ||
67 | return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq, | ||
68 | pdata); | ||
69 | } | ||
70 | |||
71 | static inline struct amba_device * | ||
72 | dbx500_add_rtc(resource_size_t base, int irq) | ||
73 | { | ||
74 | return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0); | ||
75 | } | ||
76 | |||
77 | struct nmk_gpio_platform_data; | ||
78 | |||
79 | void dbx500_add_gpios(resource_size_t *base, int num, int irq, | ||
80 | struct nmk_gpio_platform_data *pdata); | ||
81 | |||
82 | #endif | ||
diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c deleted file mode 100644 index 33e5b56bebb6..000000000000 --- a/arch/arm/mach-ux500/devices-db5500.c +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/platform_device.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/gpio.h> | ||
11 | |||
12 | #include <mach/hardware.h> | ||
13 | #include <mach/devices.h> | ||
14 | |||
15 | static struct nmk_gpio_platform_data u5500_gpio_data[] = { | ||
16 | GPIO_DATA("GPIO-0-31", 0), | ||
17 | GPIO_DATA("GPIO-32-63", 32), /* 36..63 not routed to pin */ | ||
18 | GPIO_DATA("GPIO-64-95", 64), /* 83..95 not routed to pin */ | ||
19 | GPIO_DATA("GPIO-96-127", 96), /* 102..127 not routed to pin */ | ||
20 | GPIO_DATA("GPIO-128-159", 128), /* 149..159 not routed to pin */ | ||
21 | GPIO_DATA("GPIO-160-191", 160), | ||
22 | GPIO_DATA("GPIO-192-223", 192), | ||
23 | GPIO_DATA("GPIO-224-255", 224), /* 228..255 not routed to pin */ | ||
24 | }; | ||
25 | |||
26 | static struct resource u5500_gpio_resources[] = { | ||
27 | GPIO_RESOURCE(0), | ||
28 | GPIO_RESOURCE(1), | ||
29 | GPIO_RESOURCE(2), | ||
30 | GPIO_RESOURCE(3), | ||
31 | GPIO_RESOURCE(4), | ||
32 | GPIO_RESOURCE(5), | ||
33 | GPIO_RESOURCE(6), | ||
34 | GPIO_RESOURCE(7), | ||
35 | }; | ||
36 | |||
37 | struct platform_device u5500_gpio_devs[] = { | ||
38 | GPIO_DEVICE(0), | ||
39 | GPIO_DEVICE(1), | ||
40 | GPIO_DEVICE(2), | ||
41 | GPIO_DEVICE(3), | ||
42 | GPIO_DEVICE(4), | ||
43 | GPIO_DEVICE(5), | ||
44 | GPIO_DEVICE(6), | ||
45 | GPIO_DEVICE(7), | ||
46 | }; | ||
diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h new file mode 100644 index 000000000000..c8d7901c1f2d --- /dev/null +++ b/arch/arm/mach-ux500/devices-db5500.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
5 | * License terms: GNU General Public License (GPL), version 2. | ||
6 | */ | ||
7 | |||
8 | #ifndef __DEVICES_DB5500_H | ||
9 | #define __DEVICES_DB5500_H | ||
10 | |||
11 | #include "devices-common.h" | ||
12 | |||
13 | #define db5500_add_i2c1(pdata) \ | ||
14 | dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata) | ||
15 | #define db5500_add_i2c2(pdata) \ | ||
16 | dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata) | ||
17 | #define db5500_add_i2c3(pdata) \ | ||
18 | dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata) | ||
19 | |||
20 | #define db5500_add_msp0_i2s(pdata) \ | ||
21 | dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) | ||
22 | #define db5500_add_msp1_i2s(pdata) \ | ||
23 | dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) | ||
24 | #define db5500_add_msp2_i2s(pdata) \ | ||
25 | dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) | ||
26 | |||
27 | #define db5500_add_msp0_spi(pdata) \ | ||
28 | dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) | ||
29 | #define db5500_add_msp1_spi(pdata) \ | ||
30 | dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) | ||
31 | #define db5500_add_msp2_spi(pdata) \ | ||
32 | dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) | ||
33 | |||
34 | #define db5500_add_rtc() \ | ||
35 | dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC); | ||
36 | |||
37 | #define db5500_add_sdi0(pdata) \ | ||
38 | dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata) | ||
39 | #define db5500_add_sdi1(pdata) \ | ||
40 | dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata) | ||
41 | #define db5500_add_sdi2(pdata) \ | ||
42 | dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata) | ||
43 | #define db5500_add_sdi3(pdata) \ | ||
44 | dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata) | ||
45 | #define db5500_add_sdi4(pdata) \ | ||
46 | dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata) | ||
47 | |||
48 | #define db5500_add_spi0(pdata) \ | ||
49 | dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata) | ||
50 | #define db5500_add_spi1(pdata) \ | ||
51 | dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata) | ||
52 | #define db5500_add_spi2(pdata) \ | ||
53 | dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata) | ||
54 | #define db5500_add_spi3(pdata) \ | ||
55 | dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata) | ||
56 | |||
57 | #define db5500_add_uart0() \ | ||
58 | dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0) | ||
59 | #define db5500_add_uart1() \ | ||
60 | dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1) | ||
61 | #define db5500_add_uart2() \ | ||
62 | dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2) | ||
63 | #define db5500_add_uart3() \ | ||
64 | dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3) | ||
65 | |||
66 | #endif | ||
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 4a94be3304b9..23c695d54977 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c | |||
@@ -19,173 +19,6 @@ | |||
19 | 19 | ||
20 | #include "ste-dma40-db8500.h" | 20 | #include "ste-dma40-db8500.h" |
21 | 21 | ||
22 | static struct nmk_gpio_platform_data u8500_gpio_data[] = { | ||
23 | GPIO_DATA("GPIO-0-31", 0), | ||
24 | GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */ | ||
25 | GPIO_DATA("GPIO-64-95", 64), | ||
26 | GPIO_DATA("GPIO-96-127", 96), /* 98..127 not routed to pin */ | ||
27 | GPIO_DATA("GPIO-128-159", 128), | ||
28 | GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */ | ||
29 | GPIO_DATA("GPIO-192-223", 192), | ||
30 | GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */ | ||
31 | GPIO_DATA("GPIO-256-288", 256), /* 268..288 not routed to pin */ | ||
32 | }; | ||
33 | |||
34 | static struct resource u8500_gpio_resources[] = { | ||
35 | GPIO_RESOURCE(0), | ||
36 | GPIO_RESOURCE(1), | ||
37 | GPIO_RESOURCE(2), | ||
38 | GPIO_RESOURCE(3), | ||
39 | GPIO_RESOURCE(4), | ||
40 | GPIO_RESOURCE(5), | ||
41 | GPIO_RESOURCE(6), | ||
42 | GPIO_RESOURCE(7), | ||
43 | GPIO_RESOURCE(8), | ||
44 | }; | ||
45 | |||
46 | struct platform_device u8500_gpio_devs[] = { | ||
47 | GPIO_DEVICE(0), | ||
48 | GPIO_DEVICE(1), | ||
49 | GPIO_DEVICE(2), | ||
50 | GPIO_DEVICE(3), | ||
51 | GPIO_DEVICE(4), | ||
52 | GPIO_DEVICE(5), | ||
53 | GPIO_DEVICE(6), | ||
54 | GPIO_DEVICE(7), | ||
55 | GPIO_DEVICE(8), | ||
56 | }; | ||
57 | |||
58 | struct amba_device u8500_ssp0_device = { | ||
59 | .dev = { | ||
60 | .coherent_dma_mask = ~0, | ||
61 | .init_name = "ssp0", | ||
62 | }, | ||
63 | .res = { | ||
64 | .start = U8500_SSP0_BASE, | ||
65 | .end = U8500_SSP0_BASE + SZ_4K - 1, | ||
66 | .flags = IORESOURCE_MEM, | ||
67 | }, | ||
68 | .irq = {IRQ_DB8500_SSP0, NO_IRQ }, | ||
69 | /* ST-Ericsson modified id */ | ||
70 | .periphid = SSP_PER_ID, | ||
71 | }; | ||
72 | |||
73 | static struct resource u8500_i2c0_resources[] = { | ||
74 | [0] = { | ||
75 | .start = U8500_I2C0_BASE, | ||
76 | .end = U8500_I2C0_BASE + SZ_4K - 1, | ||
77 | .flags = IORESOURCE_MEM, | ||
78 | }, | ||
79 | [1] = { | ||
80 | .start = IRQ_DB8500_I2C0, | ||
81 | .end = IRQ_DB8500_I2C0, | ||
82 | .flags = IORESOURCE_IRQ, | ||
83 | } | ||
84 | }; | ||
85 | |||
86 | struct platform_device u8500_i2c0_device = { | ||
87 | .name = "nmk-i2c", | ||
88 | .id = 0, | ||
89 | .resource = u8500_i2c0_resources, | ||
90 | .num_resources = ARRAY_SIZE(u8500_i2c0_resources), | ||
91 | }; | ||
92 | |||
93 | static struct resource u8500_i2c4_resources[] = { | ||
94 | [0] = { | ||
95 | .start = U8500_I2C4_BASE, | ||
96 | .end = U8500_I2C4_BASE + SZ_4K - 1, | ||
97 | .flags = IORESOURCE_MEM, | ||
98 | }, | ||
99 | [1] = { | ||
100 | .start = IRQ_DB8500_I2C4, | ||
101 | .end = IRQ_DB8500_I2C4, | ||
102 | .flags = IORESOURCE_IRQ, | ||
103 | } | ||
104 | }; | ||
105 | |||
106 | struct platform_device u8500_i2c4_device = { | ||
107 | .name = "nmk-i2c", | ||
108 | .id = 4, | ||
109 | .resource = u8500_i2c4_resources, | ||
110 | .num_resources = ARRAY_SIZE(u8500_i2c4_resources), | ||
111 | }; | ||
112 | |||
113 | /* | ||
114 | * SD/MMC | ||
115 | */ | ||
116 | |||
117 | struct amba_device u8500_sdi0_device = { | ||
118 | .dev = { | ||
119 | .init_name = "sdi0", | ||
120 | }, | ||
121 | .res = { | ||
122 | .start = U8500_SDI0_BASE, | ||
123 | .end = U8500_SDI0_BASE + SZ_4K - 1, | ||
124 | .flags = IORESOURCE_MEM, | ||
125 | }, | ||
126 | .irq = {IRQ_DB8500_SDMMC0, NO_IRQ}, | ||
127 | }; | ||
128 | |||
129 | struct amba_device u8500_sdi1_device = { | ||
130 | .dev = { | ||
131 | .init_name = "sdi1", | ||
132 | }, | ||
133 | .res = { | ||
134 | .start = U8500_SDI1_BASE, | ||
135 | .end = U8500_SDI1_BASE + SZ_4K - 1, | ||
136 | .flags = IORESOURCE_MEM, | ||
137 | }, | ||
138 | .irq = {IRQ_DB8500_SDMMC1, NO_IRQ}, | ||
139 | }; | ||
140 | |||
141 | struct amba_device u8500_sdi2_device = { | ||
142 | .dev = { | ||
143 | .init_name = "sdi2", | ||
144 | }, | ||
145 | .res = { | ||
146 | .start = U8500_SDI2_BASE, | ||
147 | .end = U8500_SDI2_BASE + SZ_4K - 1, | ||
148 | .flags = IORESOURCE_MEM, | ||
149 | }, | ||
150 | .irq = {IRQ_DB8500_SDMMC2, NO_IRQ}, | ||
151 | }; | ||
152 | |||
153 | struct amba_device u8500_sdi3_device = { | ||
154 | .dev = { | ||
155 | .init_name = "sdi3", | ||
156 | }, | ||
157 | .res = { | ||
158 | .start = U8500_SDI3_BASE, | ||
159 | .end = U8500_SDI3_BASE + SZ_4K - 1, | ||
160 | .flags = IORESOURCE_MEM, | ||
161 | }, | ||
162 | .irq = {IRQ_DB8500_SDMMC3, NO_IRQ}, | ||
163 | }; | ||
164 | |||
165 | struct amba_device u8500_sdi4_device = { | ||
166 | .dev = { | ||
167 | .init_name = "sdi4", | ||
168 | }, | ||
169 | .res = { | ||
170 | .start = U8500_SDI4_BASE, | ||
171 | .end = U8500_SDI4_BASE + SZ_4K - 1, | ||
172 | .flags = IORESOURCE_MEM, | ||
173 | }, | ||
174 | .irq = {IRQ_DB8500_SDMMC4, NO_IRQ}, | ||
175 | }; | ||
176 | |||
177 | struct amba_device u8500_sdi5_device = { | ||
178 | .dev = { | ||
179 | .init_name = "sdi5", | ||
180 | }, | ||
181 | .res = { | ||
182 | .start = U8500_SDI5_BASE, | ||
183 | .end = U8500_SDI5_BASE + SZ_4K - 1, | ||
184 | .flags = IORESOURCE_MEM, | ||
185 | }, | ||
186 | .irq = {IRQ_DB8500_SDMMC5, NO_IRQ}, | ||
187 | }; | ||
188 | |||
189 | static struct resource dma40_resources[] = { | 22 | static struct resource dma40_resources[] = { |
190 | [0] = { | 23 | [0] = { |
191 | .start = U8500_DMA_BASE, | 24 | .start = U8500_DMA_BASE, |
@@ -295,7 +128,7 @@ struct resource keypad_resources[] = { | |||
295 | }, | 128 | }, |
296 | }; | 129 | }; |
297 | 130 | ||
298 | struct platform_device ux500_ske_keypad_device = { | 131 | struct platform_device u8500_ske_keypad_device = { |
299 | .name = "nmk-ske-keypad", | 132 | .name = "nmk-ske-keypad", |
300 | .id = -1, | 133 | .id = -1, |
301 | .num_resources = ARRAY_SIZE(keypad_resources), | 134 | .num_resources = ARRAY_SIZE(keypad_resources), |
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h new file mode 100644 index 000000000000..3a770c756979 --- /dev/null +++ b/arch/arm/mach-ux500/devices-db8500.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
5 | * License terms: GNU General Public License (GPL), version 2. | ||
6 | */ | ||
7 | |||
8 | #ifndef __DEVICES_DB8500_H | ||
9 | #define __DEVICES_DB8500_H | ||
10 | |||
11 | #include "devices-common.h" | ||
12 | |||
13 | struct ske_keypad_platform_data; | ||
14 | struct pl022_ssp_controller; | ||
15 | |||
16 | static inline struct platform_device * | ||
17 | db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata) | ||
18 | { | ||
19 | return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1, | ||
20 | U8500_SKE_BASE, | ||
21 | IRQ_DB8500_KB, pdata); | ||
22 | } | ||
23 | |||
24 | static inline struct amba_device * | ||
25 | db8500_add_ssp(const char *name, resource_size_t base, int irq, | ||
26 | struct pl022_ssp_controller *pdata) | ||
27 | { | ||
28 | return dbx500_add_amba_device(name, base, irq, pdata, SSP_PER_ID); | ||
29 | } | ||
30 | |||
31 | |||
32 | #define db8500_add_i2c0(pdata) \ | ||
33 | dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata) | ||
34 | #define db8500_add_i2c1(pdata) \ | ||
35 | dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata) | ||
36 | #define db8500_add_i2c2(pdata) \ | ||
37 | dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata) | ||
38 | #define db8500_add_i2c3(pdata) \ | ||
39 | dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata) | ||
40 | #define db8500_add_i2c4(pdata) \ | ||
41 | dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata) | ||
42 | |||
43 | #define db8500_add_msp0_i2s(pdata) \ | ||
44 | dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) | ||
45 | #define db8500_add_msp1_i2s(pdata) \ | ||
46 | dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) | ||
47 | #define db8500_add_msp2_i2s(pdata) \ | ||
48 | dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) | ||
49 | #define db8500_add_msp3_i2s(pdata) \ | ||
50 | dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) | ||
51 | |||
52 | #define db8500_add_msp0_spi(pdata) \ | ||
53 | dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) | ||
54 | #define db8500_add_msp1_spi(pdata) \ | ||
55 | dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) | ||
56 | #define db8500_add_msp2_spi(pdata) \ | ||
57 | dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) | ||
58 | #define db8500_add_msp3_spi(pdata) \ | ||
59 | dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) | ||
60 | |||
61 | #define db8500_add_rtc() \ | ||
62 | dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC); | ||
63 | |||
64 | #define db8500_add_sdi0(pdata) \ | ||
65 | dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata) | ||
66 | #define db8500_add_sdi1(pdata) \ | ||
67 | dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata) | ||
68 | #define db8500_add_sdi2(pdata) \ | ||
69 | dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata) | ||
70 | #define db8500_add_sdi3(pdata) \ | ||
71 | dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata) | ||
72 | #define db8500_add_sdi4(pdata) \ | ||
73 | dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata) | ||
74 | #define db8500_add_sdi5(pdata) \ | ||
75 | dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata) | ||
76 | |||
77 | #define db8500_add_ssp0(pdata) \ | ||
78 | db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata) | ||
79 | #define db8500_add_ssp1(pdata) \ | ||
80 | db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata) | ||
81 | |||
82 | #define db8500_add_spi0(pdata) \ | ||
83 | dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata) | ||
84 | #define db8500_add_spi1(pdata) \ | ||
85 | dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata) | ||
86 | #define db8500_add_spi2(pdata) \ | ||
87 | dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata) | ||
88 | #define db8500_add_spi3(pdata) \ | ||
89 | dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata) | ||
90 | |||
91 | #define db8500_add_uart0() \ | ||
92 | dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0) | ||
93 | #define db8500_add_uart1() \ | ||
94 | dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1) | ||
95 | #define db8500_add_uart2() \ | ||
96 | dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2) | ||
97 | |||
98 | #endif | ||
diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c index 8a268893cb7f..ea0a2f92ca70 100644 --- a/arch/arm/mach-ux500/devices.c +++ b/arch/arm/mach-ux500/devices.c | |||
@@ -14,69 +14,6 @@ | |||
14 | #include <mach/hardware.h> | 14 | #include <mach/hardware.h> |
15 | #include <mach/setup.h> | 15 | #include <mach/setup.h> |
16 | 16 | ||
17 | #define __MEM_4K_RESOURCE(x) \ | ||
18 | .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} | ||
19 | |||
20 | struct amba_device ux500_pl031_device = { | ||
21 | .dev = { | ||
22 | .init_name = "pl031", | ||
23 | }, | ||
24 | .res = { | ||
25 | .start = UX500_RTC_BASE, | ||
26 | .end = UX500_RTC_BASE + SZ_4K - 1, | ||
27 | .flags = IORESOURCE_MEM, | ||
28 | }, | ||
29 | .irq = {IRQ_RTC_RTT, NO_IRQ}, | ||
30 | }; | ||
31 | |||
32 | struct amba_device ux500_uart0_device = { | ||
33 | .dev = { .init_name = "uart0" }, | ||
34 | __MEM_4K_RESOURCE(UX500_UART0_BASE), | ||
35 | .irq = {IRQ_UART0, NO_IRQ}, | ||
36 | }; | ||
37 | |||
38 | struct amba_device ux500_uart1_device = { | ||
39 | .dev = { .init_name = "uart1" }, | ||
40 | __MEM_4K_RESOURCE(UX500_UART1_BASE), | ||
41 | .irq = {IRQ_UART1, NO_IRQ}, | ||
42 | }; | ||
43 | |||
44 | struct amba_device ux500_uart2_device = { | ||
45 | .dev = { .init_name = "uart2" }, | ||
46 | __MEM_4K_RESOURCE(UX500_UART2_BASE), | ||
47 | .irq = {IRQ_UART2, NO_IRQ}, | ||
48 | }; | ||
49 | |||
50 | #define UX500_I2C_RESOURCES(id, size) \ | ||
51 | static struct resource ux500_i2c##id##_resources[] = { \ | ||
52 | [0] = { \ | ||
53 | .start = UX500_I2C##id##_BASE, \ | ||
54 | .end = UX500_I2C##id##_BASE + size - 1, \ | ||
55 | .flags = IORESOURCE_MEM, \ | ||
56 | }, \ | ||
57 | [1] = { \ | ||
58 | .start = IRQ_I2C##id, \ | ||
59 | .end = IRQ_I2C##id, \ | ||
60 | .flags = IORESOURCE_IRQ \ | ||
61 | } \ | ||
62 | } | ||
63 | |||
64 | UX500_I2C_RESOURCES(1, SZ_4K); | ||
65 | UX500_I2C_RESOURCES(2, SZ_4K); | ||
66 | UX500_I2C_RESOURCES(3, SZ_4K); | ||
67 | |||
68 | #define UX500_I2C_PDEVICE(cid) \ | ||
69 | struct platform_device ux500_i2c##cid##_device = { \ | ||
70 | .name = "nmk-i2c", \ | ||
71 | .id = cid, \ | ||
72 | .num_resources = 2, \ | ||
73 | .resource = ux500_i2c##cid##_resources, \ | ||
74 | } | ||
75 | |||
76 | UX500_I2C_PDEVICE(1); | ||
77 | UX500_I2C_PDEVICE(2); | ||
78 | UX500_I2C_PDEVICE(3); | ||
79 | |||
80 | void __init amba_add_devices(struct amba_device *devs[], int num) | 17 | void __init amba_add_devices(struct amba_device *devs[], int num) |
81 | { | 18 | { |
82 | int i; | 19 | int i; |
diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c new file mode 100644 index 000000000000..32a061f8a95b --- /dev/null +++ b/arch/arm/mach-ux500/dma-db5500.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson | ||
5 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson | ||
6 | * Author: Rabin Vincent <rabinv.vincent@stericsson.com> for ST-Ericsson | ||
7 | * | ||
8 | * License terms: GNU General Public License (GPL), version 2 | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <plat/ste_dma40.h> | ||
15 | #include <mach/setup.h> | ||
16 | #include <mach/hardware.h> | ||
17 | |||
18 | #include "ste-dma40-db5500.h" | ||
19 | |||
20 | static struct resource dma40_resources[] = { | ||
21 | [0] = { | ||
22 | .start = U5500_DMA_BASE, | ||
23 | .end = U5500_DMA_BASE + SZ_4K - 1, | ||
24 | .flags = IORESOURCE_MEM, | ||
25 | .name = "base", | ||
26 | }, | ||
27 | [1] = { | ||
28 | .start = U5500_DMA_LCPA_BASE, | ||
29 | .end = U5500_DMA_LCPA_BASE + 2 * SZ_1K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | .name = "lcpa", | ||
32 | }, | ||
33 | [2] = { | ||
34 | .start = IRQ_DB5500_DMA, | ||
35 | .end = IRQ_DB5500_DMA, | ||
36 | .flags = IORESOURCE_IRQ | ||
37 | } | ||
38 | }; | ||
39 | |||
40 | /* Default configuration for physical memcpy */ | ||
41 | static struct stedma40_chan_cfg dma40_memcpy_conf_phy = { | ||
42 | .mode = STEDMA40_MODE_PHYSICAL, | ||
43 | .dir = STEDMA40_MEM_TO_MEM, | ||
44 | |||
45 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | ||
46 | .src_info.psize = STEDMA40_PSIZE_PHY_1, | ||
47 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
48 | |||
49 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | ||
50 | .dst_info.psize = STEDMA40_PSIZE_PHY_1, | ||
51 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
52 | }; | ||
53 | |||
54 | /* Default configuration for logical memcpy */ | ||
55 | static struct stedma40_chan_cfg dma40_memcpy_conf_log = { | ||
56 | .dir = STEDMA40_MEM_TO_MEM, | ||
57 | |||
58 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | ||
59 | .src_info.psize = STEDMA40_PSIZE_LOG_1, | ||
60 | .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
61 | |||
62 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | ||
63 | .dst_info.psize = STEDMA40_PSIZE_LOG_1, | ||
64 | .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * Mapping between soruce event lines and physical device address This was | ||
69 | * created assuming that the event line is tied to a device and therefore the | ||
70 | * address is constant, however this is not true for at least USB, and the | ||
71 | * values are just placeholders for USB. This table is preserved and used for | ||
72 | * now. | ||
73 | */ | ||
74 | static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = { | ||
75 | [DB5500_DMA_DEV24_SDMMC0_RX] = -1, | ||
76 | }; | ||
77 | |||
78 | /* Mapping between destination event lines and physical device address */ | ||
79 | static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = { | ||
80 | [DB5500_DMA_DEV24_SDMMC0_TX] = -1, | ||
81 | }; | ||
82 | |||
83 | static int dma40_memcpy_event[] = { | ||
84 | DB5500_DMA_MEMCPY_TX_1, | ||
85 | DB5500_DMA_MEMCPY_TX_2, | ||
86 | DB5500_DMA_MEMCPY_TX_3, | ||
87 | DB5500_DMA_MEMCPY_TX_4, | ||
88 | DB5500_DMA_MEMCPY_TX_5, | ||
89 | }; | ||
90 | |||
91 | static struct stedma40_platform_data dma40_plat_data = { | ||
92 | .dev_len = ARRAY_SIZE(dma40_rx_map), | ||
93 | .dev_rx = dma40_rx_map, | ||
94 | .dev_tx = dma40_tx_map, | ||
95 | .memcpy = dma40_memcpy_event, | ||
96 | .memcpy_len = ARRAY_SIZE(dma40_memcpy_event), | ||
97 | .memcpy_conf_phy = &dma40_memcpy_conf_phy, | ||
98 | .memcpy_conf_log = &dma40_memcpy_conf_log, | ||
99 | .disabled_channels = {-1}, | ||
100 | }; | ||
101 | |||
102 | static struct platform_device dma40_device = { | ||
103 | .dev = { | ||
104 | .platform_data = &dma40_plat_data, | ||
105 | }, | ||
106 | .name = "dma40", | ||
107 | .id = 0, | ||
108 | .num_resources = ARRAY_SIZE(dma40_resources), | ||
109 | .resource = dma40_resources | ||
110 | }; | ||
111 | |||
112 | void __init db5500_dma_init(void) | ||
113 | { | ||
114 | int ret; | ||
115 | |||
116 | ret = platform_device_register(&dma40_device); | ||
117 | if (ret) | ||
118 | dev_err(&dma40_device.dev, "unable to register device: %d\n", ret); | ||
119 | |||
120 | } | ||
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h index 3eafc0e24ba5..bd88c1e74060 100644 --- a/arch/arm/mach-ux500/include/mach/db5500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h | |||
@@ -114,4 +114,8 @@ | |||
114 | #define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20) | 114 | #define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20) |
115 | #define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F) | 115 | #define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F) |
116 | 116 | ||
117 | #define U5500_ESRAM_BASE 0x40000000 | ||
118 | #define U5500_ESRAM_DMA_LCPA_OFFSET 0x10000 | ||
119 | #define U5500_DMA_LCPA_BASE (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET) | ||
120 | |||
117 | #endif | 121 | #endif |
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index f07d0986409d..0fefb34c11e4 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h | |||
@@ -92,7 +92,8 @@ | |||
92 | #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) | 92 | #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) |
93 | #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) | 93 | #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) |
94 | #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) | 94 | #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) |
95 | #define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x0f000) | 95 | #define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000) |
96 | #define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) | ||
96 | 97 | ||
97 | /* per3 base addresses */ | 98 | /* per3 base addresses */ |
98 | #define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) | 99 | #define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) |
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index b91a4d1211a2..020b6369a30a 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h | |||
@@ -14,27 +14,10 @@ extern struct platform_device u5500_gpio_devs[]; | |||
14 | extern struct platform_device u8500_gpio_devs[]; | 14 | extern struct platform_device u8500_gpio_devs[]; |
15 | 15 | ||
16 | extern struct amba_device ux500_pl031_device; | 16 | extern struct amba_device ux500_pl031_device; |
17 | extern struct amba_device u8500_ssp0_device; | ||
18 | extern struct amba_device ux500_uart0_device; | ||
19 | extern struct amba_device ux500_uart1_device; | ||
20 | extern struct amba_device ux500_uart2_device; | ||
21 | 17 | ||
22 | extern struct platform_device ux500_i2c1_device; | ||
23 | extern struct platform_device ux500_i2c2_device; | ||
24 | extern struct platform_device ux500_i2c3_device; | ||
25 | |||
26 | extern struct platform_device u8500_i2c0_device; | ||
27 | extern struct platform_device u8500_i2c4_device; | ||
28 | extern struct platform_device u8500_dma40_device; | 18 | extern struct platform_device u8500_dma40_device; |
29 | extern struct platform_device ux500_ske_keypad_device; | 19 | extern struct platform_device ux500_ske_keypad_device; |
30 | 20 | ||
31 | extern struct amba_device u8500_sdi0_device; | ||
32 | extern struct amba_device u8500_sdi1_device; | ||
33 | extern struct amba_device u8500_sdi2_device; | ||
34 | extern struct amba_device u8500_sdi3_device; | ||
35 | extern struct amba_device u8500_sdi4_device; | ||
36 | extern struct amba_device u8500_sdi5_device; | ||
37 | |||
38 | void dma40_u8500ed_fixup(void); | 21 | void dma40_u8500ed_fixup(void); |
39 | 22 | ||
40 | #endif | 23 | #endif |
diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h index d548a622e7d2..3c4cd31ad9f7 100644 --- a/arch/arm/mach-ux500/include/mach/gpio.h +++ b/arch/arm/mach-ux500/include/mach/gpio.h | |||
@@ -9,42 +9,4 @@ | |||
9 | 9 | ||
10 | #include <plat/gpio.h> | 10 | #include <plat/gpio.h> |
11 | 11 | ||
12 | #define __GPIO_RESOURCE(soc, block) \ | ||
13 | { \ | ||
14 | .start = soc##_GPIOBANK##block##_BASE, \ | ||
15 | .end = soc##_GPIOBANK##block##_BASE + 127, \ | ||
16 | .flags = IORESOURCE_MEM, \ | ||
17 | }, \ | ||
18 | { \ | ||
19 | .start = IRQ_GPIO##block, \ | ||
20 | .end = IRQ_GPIO##block, \ | ||
21 | .flags = IORESOURCE_IRQ, \ | ||
22 | } | ||
23 | |||
24 | #define __GPIO_DEVICE(soc, block) \ | ||
25 | { \ | ||
26 | .name = "gpio", \ | ||
27 | .id = block, \ | ||
28 | .num_resources = 2, \ | ||
29 | .resource = &soc##_gpio_resources[block * 2], \ | ||
30 | .dev = { \ | ||
31 | .platform_data = &soc##_gpio_data[block], \ | ||
32 | }, \ | ||
33 | } | ||
34 | |||
35 | #define GPIO_DATA(_name, first) \ | ||
36 | { \ | ||
37 | .name = _name, \ | ||
38 | .first_gpio = first, \ | ||
39 | .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ | ||
40 | } | ||
41 | |||
42 | #ifdef CONFIG_UX500_SOC_DB8500 | ||
43 | #define GPIO_RESOURCE(block) __GPIO_RESOURCE(U8500, block) | ||
44 | #define GPIO_DEVICE(block) __GPIO_DEVICE(u8500, block) | ||
45 | #elif defined(CONFIG_UX500_SOC_DB5500) | ||
46 | #define GPIO_RESOURCE(block) __GPIO_RESOURCE(U5500, block) | ||
47 | #define GPIO_DEVICE(block) __GPIO_DEVICE(u5500, block) | ||
48 | #endif | ||
49 | |||
50 | #endif /* __ASM_ARCH_GPIO_H */ | 12 | #endif /* __ASM_ARCH_GPIO_H */ |
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 32e883a8f2a2..6295cc581355 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h | |||
@@ -142,6 +142,8 @@ static inline bool cpu_is_u5500(void) | |||
142 | #endif | 142 | #endif |
143 | } | 143 | } |
144 | 144 | ||
145 | #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) | ||
146 | |||
145 | #endif | 147 | #endif |
146 | 148 | ||
147 | #endif /* __MACH_HARDWARE_H */ | 149 | #endif /* __MACH_HARDWARE_H */ |
diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index cca4f705601e..7cdeb2af0ebb 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h | |||
@@ -8,12 +8,36 @@ | |||
8 | #ifndef __MACH_IRQS_BOARD_MOP500_H | 8 | #ifndef __MACH_IRQS_BOARD_MOP500_H |
9 | #define __MACH_IRQS_BOARD_MOP500_H | 9 | #define __MACH_IRQS_BOARD_MOP500_H |
10 | 10 | ||
11 | #define AB8500_NR_IRQS 104 | 11 | /* Number of AB8500 irqs is taken from header file */ |
12 | #include <linux/mfd/ab8500.h> | ||
12 | 13 | ||
13 | #define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START | 14 | #define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START |
14 | #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ | 15 | #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ |
15 | + AB8500_NR_IRQS) | 16 | + AB8500_NR_IRQS) |
16 | #define MOP500_IRQ_END MOP500_AB8500_IRQ_END | 17 | |
18 | /* TC35892 */ | ||
19 | #define TC35892_NR_INTERNAL_IRQS 8 | ||
20 | #define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x)) | ||
21 | #define TC35892_NR_GPIOS 24 | ||
22 | #define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS) | ||
23 | |||
24 | #define MOP500_EGPIO_NR_IRQS TC35892_NR_IRQS | ||
25 | |||
26 | #define MOP500_EGPIO_IRQ_BASE MOP500_AB8500_IRQ_END | ||
27 | #define MOP500_EGPIO_IRQ_END (MOP500_EGPIO_IRQ_BASE \ | ||
28 | + MOP500_EGPIO_NR_IRQS) | ||
29 | /* STMPE1601 irqs */ | ||
30 | #define STMPE_NR_INTERNAL_IRQS 9 | ||
31 | #define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x)) | ||
32 | #define STMPE_NR_GPIOS 24 | ||
33 | #define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS) | ||
34 | |||
35 | #define MOP500_STMPE1601_IRQBASE MOP500_EGPIO_IRQ_END | ||
36 | #define MOP500_STMPE1601_IRQ(x) (MOP500_STMPE1601_IRQBASE + (x)) | ||
37 | |||
38 | #define MOP500_NR_IRQS MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS) | ||
39 | |||
40 | #define MOP500_IRQ_END MOP500_NR_IRQS | ||
17 | 41 | ||
18 | #if MOP500_IRQ_END > IRQ_BOARD_END | 42 | #if MOP500_IRQ_END > IRQ_BOARD_END |
19 | #undef IRQ_BOARD_END | 43 | #undef IRQ_BOARD_END |
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 693aa57de88d..880ae45bc235 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h | |||
@@ -21,50 +21,6 @@ | |||
21 | 21 | ||
22 | /* Interrupt numbers generic for shared peripheral */ | 22 | /* Interrupt numbers generic for shared peripheral */ |
23 | #define IRQ_MTU0 (IRQ_SHPI_START + 4) | 23 | #define IRQ_MTU0 (IRQ_SHPI_START + 4) |
24 | #define IRQ_SPI2 (IRQ_SHPI_START + 6) | ||
25 | #define IRQ_SPI0 (IRQ_SHPI_START + 8) | ||
26 | #define IRQ_UART0 (IRQ_SHPI_START + 11) | ||
27 | #define IRQ_I2C3 (IRQ_SHPI_START + 12) | ||
28 | #define IRQ_SSP0 (IRQ_SHPI_START + 14) | ||
29 | #define IRQ_MTU1 (IRQ_SHPI_START + 17) | ||
30 | #define IRQ_RTC_RTT (IRQ_SHPI_START + 18) | ||
31 | #define IRQ_UART1 (IRQ_SHPI_START + 19) | ||
32 | #define IRQ_I2C0 (IRQ_SHPI_START + 21) | ||
33 | #define IRQ_I2C1 (IRQ_SHPI_START + 22) | ||
34 | #define IRQ_USBOTG (IRQ_SHPI_START + 23) | ||
35 | #define IRQ_DMA (IRQ_SHPI_START + 25) | ||
36 | #define IRQ_UART2 (IRQ_SHPI_START + 26) | ||
37 | #define IRQ_HSIR_EXCEP (IRQ_SHPI_START + 29) | ||
38 | #define IRQ_MSP0 (IRQ_SHPI_START + 31) | ||
39 | #define IRQ_HSIR_CH0_OVRRUN (IRQ_SHPI_START + 32) | ||
40 | #define IRQ_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33) | ||
41 | #define IRQ_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34) | ||
42 | #define IRQ_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35) | ||
43 | #define IRQ_AB8500 (IRQ_SHPI_START + 40) | ||
44 | #define IRQ_PRCMU (IRQ_SHPI_START + 47) | ||
45 | #define IRQ_DISP (IRQ_SHPI_START + 48) | ||
46 | #define IRQ_SiPI3 (IRQ_SHPI_START + 49) | ||
47 | #define IRQ_I2C4 (IRQ_SHPI_START + 51) | ||
48 | #define IRQ_SSP1 (IRQ_SHPI_START + 52) | ||
49 | #define IRQ_I2C2 (IRQ_SHPI_START + 55) | ||
50 | #define IRQ_SDMMC0 (IRQ_SHPI_START + 60) | ||
51 | #define IRQ_MSP1 (IRQ_SHPI_START + 62) | ||
52 | #define IRQ_SPI1 (IRQ_SHPI_START + 96) | ||
53 | #define IRQ_MSP2 (IRQ_SHPI_START + 98) | ||
54 | #define IRQ_SDMMC4 (IRQ_SHPI_START + 99) | ||
55 | #define IRQ_HSIRD0 (IRQ_SHPI_START + 104) | ||
56 | #define IRQ_HSIRD1 (IRQ_SHPI_START + 105) | ||
57 | #define IRQ_HSITD0 (IRQ_SHPI_START + 106) | ||
58 | #define IRQ_HSITD1 (IRQ_SHPI_START + 107) | ||
59 | #define IRQ_GPIO0 (IRQ_SHPI_START + 119) | ||
60 | #define IRQ_GPIO1 (IRQ_SHPI_START + 120) | ||
61 | #define IRQ_GPIO2 (IRQ_SHPI_START + 121) | ||
62 | #define IRQ_GPIO3 (IRQ_SHPI_START + 122) | ||
63 | #define IRQ_GPIO4 (IRQ_SHPI_START + 123) | ||
64 | #define IRQ_GPIO5 (IRQ_SHPI_START + 124) | ||
65 | #define IRQ_GPIO6 (IRQ_SHPI_START + 125) | ||
66 | #define IRQ_GPIO7 (IRQ_SHPI_START + 126) | ||
67 | #define IRQ_GPIO8 (IRQ_SHPI_START + 127) | ||
68 | 24 | ||
69 | /* There are 128 shared peripheral interrupts assigned to | 25 | /* There are 128 shared peripheral interrupts assigned to |
70 | * INTID[160:32]. The first 32 interrupts are reserved. | 26 | * INTID[160:32]. The first 32 interrupts are reserved. |
diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox-db5500.h index 7f9da4d2fbda..7f9da4d2fbda 100644 --- a/arch/arm/mach-ux500/include/mach/mbox.h +++ b/arch/arm/mach-ux500/include/mach/mbox-db5500.h | |||
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-defs.h b/arch/arm/mach-ux500/include/mach/prcmu-defs.h new file mode 100644 index 000000000000..848ba64b561f --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/prcmu-defs.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics 2009 | ||
3 | * Copyright (C) ST-Ericsson SA 2010 | ||
4 | * | ||
5 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> | ||
6 | * Author: Martin Persson <martin.persson@stericsson.com> | ||
7 | * | ||
8 | * License Terms: GNU General Public License v2 | ||
9 | * | ||
10 | * PRCM Unit definitions | ||
11 | */ | ||
12 | |||
13 | #ifndef __MACH_PRCMU_DEFS_H | ||
14 | #define __MACH_PRCMU_DEFS_H | ||
15 | |||
16 | enum prcmu_cpu_opp { | ||
17 | CPU_OPP_INIT = 0x00, | ||
18 | CPU_OPP_NO_CHANGE = 0x01, | ||
19 | CPU_OPP_100 = 0x02, | ||
20 | CPU_OPP_50 = 0x03, | ||
21 | CPU_OPP_MAX = 0x04, | ||
22 | CPU_OPP_EXT_CLK = 0x07 | ||
23 | }; | ||
24 | enum prcmu_ape_opp { | ||
25 | APE_OPP_NO_CHANGE = 0x00, | ||
26 | APE_OPP_100 = 0x02, | ||
27 | APE_OPP_50 = 0x03, | ||
28 | }; | ||
29 | |||
30 | #endif /* __MACH_PRCMU_DEFS_H */ | ||
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h index 8885f39a6421..455467e88791 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h | |||
@@ -1,10 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2009 ST-Ericsson SA | 2 | * Copyright (C) STMicroelectronics 2009 |
3 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | 4 | * |
4 | * This program is free software; you can redistribute it and/or modify | 5 | * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> |
5 | * it under the terms of the GNU General Public License version 2 | 6 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> |
6 | * as published by the Free Software Foundation. | 7 | * |
8 | * License Terms: GNU General Public License v2 | ||
9 | * | ||
10 | * PRCM Unit registers | ||
7 | */ | 11 | */ |
12 | |||
8 | #ifndef __MACH_PRCMU_REGS_H | 13 | #ifndef __MACH_PRCMU_REGS_H |
9 | #define __MACH_PRCMU_REGS_H | 14 | #define __MACH_PRCMU_REGS_H |
10 | 15 | ||
@@ -88,4 +93,4 @@ | |||
88 | /* Miscellaneous unit registers */ | 93 | /* Miscellaneous unit registers */ |
89 | #define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) | 94 | #define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) |
90 | 95 | ||
91 | #endif /* __MACH_PRCMU__REGS_H */ | 96 | #endif /* __MACH_PRCMU_REGS_H */ |
diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h index 549843ff6dbe..c49e456162ef 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu.h +++ b/arch/arm/mach-ux500/include/mach/prcmu.h | |||
@@ -2,14 +2,27 @@ | |||
2 | * Copyright (C) STMicroelectronics 2009 | 2 | * Copyright (C) STMicroelectronics 2009 |
3 | * Copyright (C) ST-Ericsson SA 2010 | 3 | * Copyright (C) ST-Ericsson SA 2010 |
4 | * | 4 | * |
5 | * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> | ||
6 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> | ||
7 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> | ||
8 | * | ||
5 | * License Terms: GNU General Public License v2 | 9 | * License Terms: GNU General Public License v2 |
6 | * | 10 | * |
7 | * PRCMU f/w APIs | 11 | * PRCM Unit f/w API |
8 | */ | 12 | */ |
9 | #ifndef __MACH_PRCMU_H | 13 | #ifndef __MACH_PRCMU_H |
10 | #define __MACH_PRCMU_H | 14 | #define __MACH_PRCMU_H |
15 | #include <mach/prcmu-defs.h> | ||
11 | 16 | ||
17 | void __init prcmu_early_init(void); | ||
12 | int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); | 18 | int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); |
13 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); | 19 | int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); |
20 | int prcmu_set_ape_opp(enum prcmu_ape_opp opp); | ||
21 | int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp); | ||
22 | int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp, | ||
23 | enum prcmu_cpu_opp cpu_opp); | ||
24 | int prcmu_get_ape_opp(void); | ||
25 | int prcmu_get_cpu_opp(void); | ||
26 | bool prcmu_has_arm_maxopp(void); | ||
14 | 27 | ||
15 | #endif /* __MACH_PRCMU_H */ | 28 | #endif /* __MACH_PRCMU_H */ |
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 54bbe648bf58..469877e0de90 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h | |||
@@ -18,14 +18,19 @@ extern void __init ux500_map_io(void); | |||
18 | extern void __init u5500_map_io(void); | 18 | extern void __init u5500_map_io(void); |
19 | extern void __init u8500_map_io(void); | 19 | extern void __init u8500_map_io(void); |
20 | 20 | ||
21 | extern void __init ux500_init_devices(void); | ||
22 | extern void __init u5500_init_devices(void); | 21 | extern void __init u5500_init_devices(void); |
23 | extern void __init u8500_init_devices(void); | 22 | extern void __init u8500_init_devices(void); |
24 | 23 | ||
25 | extern void __init ux500_init_irq(void); | 24 | extern void __init ux500_init_irq(void); |
25 | |||
26 | extern void __init u5500_sdi_init(void); | ||
27 | |||
28 | extern void __init db5500_dma_init(void); | ||
29 | |||
26 | /* We re-use nomadik_timer for this platform */ | 30 | /* We re-use nomadik_timer for this platform */ |
27 | extern void nmdk_timer_init(void); | 31 | extern void nmdk_timer_init(void); |
28 | 32 | ||
33 | struct amba_device; | ||
29 | extern void __init amba_add_devices(struct amba_device *devs[], int num); | 34 | extern void __init amba_add_devices(struct amba_device *devs[], int num); |
30 | 35 | ||
31 | struct sys_timer; | 36 | struct sys_timer; |
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h index 0271ca0a83df..9a6614c6808e 100644 --- a/arch/arm/mach-ux500/include/mach/uncompress.h +++ b/arch/arm/mach-ux500/include/mach/uncompress.h | |||
@@ -19,38 +19,43 @@ | |||
19 | #define __ASM_ARCH_UNCOMPRESS_H | 19 | #define __ASM_ARCH_UNCOMPRESS_H |
20 | 20 | ||
21 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
22 | #include <asm/mach-types.h> | ||
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/amba/serial.h> | ||
23 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
24 | 26 | ||
25 | #define U8500_UART_DR 0x80007000 | 27 | static u32 ux500_uart_base; |
26 | #define U8500_UART_LCRH 0x8000702c | ||
27 | #define U8500_UART_CR 0x80007030 | ||
28 | #define U8500_UART_FR 0x80007018 | ||
29 | 28 | ||
30 | static void putc(const char c) | 29 | static void putc(const char c) |
31 | { | 30 | { |
32 | /* Do nothing if the UART is not enabled. */ | 31 | /* Do nothing if the UART is not enabled. */ |
33 | if (!(__raw_readb(U8500_UART_CR) & 0x1)) | 32 | if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1)) |
34 | return; | 33 | return; |
35 | 34 | ||
36 | if (c == '\n') | 35 | if (c == '\n') |
37 | putc('\r'); | 36 | putc('\r'); |
38 | 37 | ||
39 | while (__raw_readb(U8500_UART_FR) & (1 << 5)) | 38 | while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 5)) |
40 | barrier(); | 39 | barrier(); |
41 | __raw_writeb(c, U8500_UART_DR); | 40 | __raw_writeb(c, ux500_uart_base + UART01x_DR); |
42 | } | 41 | } |
43 | 42 | ||
44 | static void flush(void) | 43 | static void flush(void) |
45 | { | 44 | { |
46 | if (!(__raw_readb(U8500_UART_CR) & 0x1)) | 45 | if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1)) |
47 | return; | 46 | return; |
48 | while (__raw_readb(U8500_UART_FR) & (1 << 3)) | 47 | while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 3)) |
49 | barrier(); | 48 | barrier(); |
50 | } | 49 | } |
51 | 50 | ||
52 | static inline void arch_decomp_setup(void) | 51 | static inline void arch_decomp_setup(void) |
53 | { | 52 | { |
53 | if (machine_is_u8500()) | ||
54 | ux500_uart_base = U8500_UART2_BASE; | ||
55 | else if (machine_is_u5500()) | ||
56 | ux500_uart_base = U5500_UART0_BASE; | ||
57 | else /* not much can be done to help here */ | ||
58 | ux500_uart_base = U8500_UART2_BASE; | ||
54 | } | 59 | } |
55 | 60 | ||
56 | #define arch_decomp_wdog() /* nothing to do here */ | 61 | #define arch_decomp_wdog() /* nothing to do here */ |
diff --git a/arch/arm/mach-ux500/mbox.c b/arch/arm/mach-ux500/mbox-db5500.c index 63435389c544..cbf15718fc3c 100644 --- a/arch/arm/mach-ux500/mbox.c +++ b/arch/arm/mach-ux500/mbox-db5500.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/debugfs.h> | 38 | #include <linux/debugfs.h> |
39 | #include <linux/seq_file.h> | 39 | #include <linux/seq_file.h> |
40 | #include <linux/completion.h> | 40 | #include <linux/completion.h> |
41 | #include <mach/mbox.h> | 41 | #include <mach/mbox-db5500.h> |
42 | 42 | ||
43 | #define MBOX_NAME "mbox" | 43 | #define MBOX_NAME "mbox" |
44 | 44 | ||
diff --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem-irq-db5500.c index 3187f8871169..3187f8871169 100644 --- a/arch/arm/mach-ux500/modem_irq.c +++ b/arch/arm/mach-ux500/modem-irq-db5500.c | |||
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 9e4c678de785..ade2e17f253c 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * control for which core is the next to come out of the secondary | 26 | * control for which core is the next to come out of the secondary |
27 | * boot "holding pen" | 27 | * boot "holding pen" |
28 | */ | 28 | */ |
29 | volatile int __cpuinitdata pen_release = -1; | 29 | volatile int pen_release = -1; |
30 | 30 | ||
31 | static unsigned int __init get_core_count(void) | 31 | static unsigned int __init get_core_count(void) |
32 | { | 32 | { |
diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c index 293274d1342a..c522d26ef348 100644 --- a/arch/arm/mach-ux500/prcmu.c +++ b/arch/arm/mach-ux500/prcmu.c | |||
@@ -1,10 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) ST Ericsson SA 2010 | 2 | * Copyright (C) STMicroelectronics 2009 |
3 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | 4 | * |
4 | * License Terms: GNU General Public License v2 | 5 | * License Terms: GNU General Public License v2 |
6 | * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> | ||
7 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> | ||
5 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> | 8 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> |
6 | * | 9 | * |
7 | * U8500 PRCMU driver. | 10 | * U8500 PRCM Unit interface driver |
11 | * | ||
8 | */ | 12 | */ |
9 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
10 | #include <linux/module.h> | 14 | #include <linux/module.h> |
@@ -19,11 +23,26 @@ | |||
19 | 23 | ||
20 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
21 | #include <mach/prcmu-regs.h> | 25 | #include <mach/prcmu-regs.h> |
26 | #include <mach/prcmu-defs.h> | ||
27 | |||
28 | /* Global var to runtime determine TCDM base for v2 or v1 */ | ||
29 | static __iomem void *tcdm_base; | ||
30 | |||
31 | #define _MBOX_HEADER (tcdm_base + 0xFE8) | ||
32 | #define MBOX_HEADER_REQ_MB0 (_MBOX_HEADER + 0x0) | ||
33 | |||
34 | #define REQ_MB1 (tcdm_base + 0xFD0) | ||
35 | #define REQ_MB5 (tcdm_base + 0xE44) | ||
22 | 36 | ||
23 | #define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE) | 37 | #define REQ_MB1_ARMOPP (REQ_MB1 + 0x0) |
38 | #define REQ_MB1_APEOPP (REQ_MB1 + 0x1) | ||
39 | #define REQ_MB1_BOOSTOPP (REQ_MB1 + 0x2) | ||
24 | 40 | ||
25 | #define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44) | 41 | #define ACK_MB1 (tcdm_base + 0xE04) |
26 | #define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4) | 42 | #define ACK_MB5 (tcdm_base + 0xDF4) |
43 | |||
44 | #define ACK_MB1_CURR_ARMOPP (ACK_MB1 + 0x0) | ||
45 | #define ACK_MB1_CURR_APEOPP (ACK_MB1 + 0x1) | ||
27 | 46 | ||
28 | #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5) | 47 | #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5) |
29 | #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1) | 48 | #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1) |
@@ -33,10 +52,33 @@ | |||
33 | #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1) | 52 | #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1) |
34 | #define ACK_MB5_I2C_VAL (ACK_MB5 + 3) | 53 | #define ACK_MB5_I2C_VAL (ACK_MB5 + 3) |
35 | 54 | ||
36 | #define I2C_WRITE(slave) ((slave) << 1) | 55 | #define PRCM_AVS_VARM_MAX_OPP (tcdm_base + 0x2E4) |
37 | #define I2C_READ(slave) (((slave) << 1) | BIT(0)) | 56 | #define PRCM_AVS_ISMODEENABLE 7 |
57 | #define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE) | ||
58 | |||
59 | #define I2C_WRITE(slave) \ | ||
60 | (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0)) | ||
61 | #define I2C_READ(slave) \ | ||
62 | (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0)) | ||
38 | #define I2C_STOP_EN BIT(3) | 63 | #define I2C_STOP_EN BIT(3) |
39 | 64 | ||
65 | enum mb1_h { | ||
66 | MB1H_ARM_OPP = 1, | ||
67 | MB1H_APE_OPP, | ||
68 | MB1H_ARM_APE_OPP, | ||
69 | }; | ||
70 | |||
71 | static struct { | ||
72 | struct mutex lock; | ||
73 | struct completion work; | ||
74 | struct { | ||
75 | u8 arm_opp; | ||
76 | u8 ape_opp; | ||
77 | u8 arm_status; | ||
78 | u8 ape_status; | ||
79 | } ack; | ||
80 | } mb1_transfer; | ||
81 | |||
40 | enum ack_mb5_status { | 82 | enum ack_mb5_status { |
41 | I2C_WR_OK = 0x01, | 83 | I2C_WR_OK = 0x01, |
42 | I2C_RD_OK = 0x02, | 84 | I2C_RD_OK = 0x02, |
@@ -145,6 +187,104 @@ unlock_and_return: | |||
145 | } | 187 | } |
146 | EXPORT_SYMBOL(prcmu_abb_write); | 188 | EXPORT_SYMBOL(prcmu_abb_write); |
147 | 189 | ||
190 | static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp, | ||
191 | enum prcmu_cpu_opp cpu_opp) | ||
192 | { | ||
193 | bool do_ape; | ||
194 | bool do_arm; | ||
195 | int err = 0; | ||
196 | |||
197 | do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP)); | ||
198 | do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP)); | ||
199 | |||
200 | mutex_lock(&mb1_transfer.lock); | ||
201 | |||
202 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | ||
203 | cpu_relax(); | ||
204 | |||
205 | writeb(0, MBOX_HEADER_REQ_MB0); | ||
206 | writeb(cpu_opp, REQ_MB1_ARMOPP); | ||
207 | writeb(ape_opp, REQ_MB1_APEOPP); | ||
208 | writeb(0, REQ_MB1_BOOSTOPP); | ||
209 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | ||
210 | wait_for_completion(&mb1_transfer.work); | ||
211 | if ((do_ape) && (mb1_transfer.ack.ape_status != 0)) | ||
212 | err = -EIO; | ||
213 | if ((do_arm) && (mb1_transfer.ack.arm_status != 0)) | ||
214 | err = -EIO; | ||
215 | |||
216 | mutex_unlock(&mb1_transfer.lock); | ||
217 | |||
218 | return err; | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * prcmu_set_ape_opp() - Set the OPP of the APE. | ||
223 | * @opp: The OPP to set. | ||
224 | * | ||
225 | * This function sets the OPP of the APE. | ||
226 | */ | ||
227 | int prcmu_set_ape_opp(enum prcmu_ape_opp opp) | ||
228 | { | ||
229 | return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE); | ||
230 | } | ||
231 | EXPORT_SYMBOL(prcmu_set_ape_opp); | ||
232 | |||
233 | /** | ||
234 | * prcmu_set_cpu_opp() - Set the OPP of the CPU. | ||
235 | * @opp: The OPP to set. | ||
236 | * | ||
237 | * This function sets the OPP of the CPU. | ||
238 | */ | ||
239 | int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp) | ||
240 | { | ||
241 | return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp); | ||
242 | } | ||
243 | EXPORT_SYMBOL(prcmu_set_cpu_opp); | ||
244 | |||
245 | /** | ||
246 | * prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU. | ||
247 | * @ape_opp: The APE OPP to set. | ||
248 | * @cpu_opp: The CPU OPP to set. | ||
249 | * | ||
250 | * This function sets the OPPs of the APE and the CPU. | ||
251 | */ | ||
252 | int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp, | ||
253 | enum prcmu_cpu_opp cpu_opp) | ||
254 | { | ||
255 | return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp); | ||
256 | } | ||
257 | EXPORT_SYMBOL(prcmu_set_ape_cpu_opps); | ||
258 | |||
259 | /** | ||
260 | * prcmu_get_ape_opp() - Get the OPP of the APE. | ||
261 | * | ||
262 | * This function gets the OPP of the APE. | ||
263 | */ | ||
264 | enum prcmu_ape_opp prcmu_get_ape_opp(void) | ||
265 | { | ||
266 | return readb(ACK_MB1_CURR_APEOPP); | ||
267 | } | ||
268 | EXPORT_SYMBOL(prcmu_get_ape_opp); | ||
269 | |||
270 | /** | ||
271 | * prcmu_get_cpu_opp() - Get the OPP of the CPU. | ||
272 | * | ||
273 | * This function gets the OPP of the CPU. The OPP is specified in %%. | ||
274 | * PRCMU_OPP_EXT is a special OPP value, not specified in %%. | ||
275 | */ | ||
276 | int prcmu_get_cpu_opp(void) | ||
277 | { | ||
278 | return readb(ACK_MB1_CURR_ARMOPP); | ||
279 | } | ||
280 | EXPORT_SYMBOL(prcmu_get_cpu_opp); | ||
281 | |||
282 | bool prcmu_has_arm_maxopp(void) | ||
283 | { | ||
284 | return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK) | ||
285 | == PRCM_AVS_ISMODEENABLE_MASK; | ||
286 | } | ||
287 | |||
148 | static void read_mailbox_0(void) | 288 | static void read_mailbox_0(void) |
149 | { | 289 | { |
150 | writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); | 290 | writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); |
@@ -152,6 +292,9 @@ static void read_mailbox_0(void) | |||
152 | 292 | ||
153 | static void read_mailbox_1(void) | 293 | static void read_mailbox_1(void) |
154 | { | 294 | { |
295 | mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP); | ||
296 | mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP); | ||
297 | complete(&mb1_transfer.work); | ||
155 | writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); | 298 | writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); |
156 | } | 299 | } |
157 | 300 | ||
@@ -217,15 +360,35 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data) | |||
217 | return IRQ_HANDLED; | 360 | return IRQ_HANDLED; |
218 | } | 361 | } |
219 | 362 | ||
363 | void __init prcmu_early_init(void) | ||
364 | { | ||
365 | if (cpu_is_u8500v11() || cpu_is_u8500ed()) { | ||
366 | tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1); | ||
367 | } else if (cpu_is_u8500v2()) { | ||
368 | tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); | ||
369 | } else { | ||
370 | pr_err("prcmu: Unsupported chip version\n"); | ||
371 | BUG(); | ||
372 | } | ||
373 | } | ||
374 | |||
220 | static int __init prcmu_init(void) | 375 | static int __init prcmu_init(void) |
221 | { | 376 | { |
377 | if (cpu_is_u8500ed()) { | ||
378 | pr_err("prcmu: Unsupported chip version\n"); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | mutex_init(&mb1_transfer.lock); | ||
383 | init_completion(&mb1_transfer.work); | ||
222 | mutex_init(&mb5_transfer.lock); | 384 | mutex_init(&mb5_transfer.lock); |
223 | init_completion(&mb5_transfer.work); | 385 | init_completion(&mb5_transfer.work); |
224 | 386 | ||
225 | /* Clean up the mailbox interrupts after pre-kernel code. */ | 387 | /* Clean up the mailbox interrupts after pre-kernel code. */ |
226 | writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR); | 388 | writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR); |
227 | 389 | ||
228 | return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL); | 390 | return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0, |
391 | "prcmu", NULL); | ||
229 | } | 392 | } |
230 | 393 | ||
231 | arch_initcall(prcmu_init); | 394 | arch_initcall(prcmu_init); |
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 85e6fd212a41..eda4e3a11a3d 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c | |||
@@ -119,7 +119,7 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, | |||
119 | } | 119 | } |
120 | 120 | ||
121 | static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | 121 | static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, |
122 | pin_cfg_t cfg) | 122 | pin_cfg_t cfg, bool sleep) |
123 | { | 123 | { |
124 | static const char *afnames[] = { | 124 | static const char *afnames[] = { |
125 | [NMK_GPIO_ALT_GPIO] = "GPIO", | 125 | [NMK_GPIO_ALT_GPIO] = "GPIO", |
@@ -145,11 +145,34 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | |||
145 | int output = PIN_DIR(cfg); | 145 | int output = PIN_DIR(cfg); |
146 | int val = PIN_VAL(cfg); | 146 | int val = PIN_VAL(cfg); |
147 | 147 | ||
148 | dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n", | 148 | dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n", |
149 | pin, afnames[af], pullnames[pull], slpmnames[slpm], | 149 | pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm], |
150 | output ? "output " : "input", | 150 | output ? "output " : "input", |
151 | output ? (val ? "high" : "low") : ""); | 151 | output ? (val ? "high" : "low") : ""); |
152 | 152 | ||
153 | if (sleep) { | ||
154 | int slpm_pull = PIN_SLPM_PULL(cfg); | ||
155 | int slpm_output = PIN_SLPM_DIR(cfg); | ||
156 | int slpm_val = PIN_SLPM_VAL(cfg); | ||
157 | |||
158 | /* | ||
159 | * The SLPM_* values are normal values + 1 to allow zero to | ||
160 | * mean "same as normal". | ||
161 | */ | ||
162 | if (slpm_pull) | ||
163 | pull = slpm_pull - 1; | ||
164 | if (slpm_output) | ||
165 | output = slpm_output - 1; | ||
166 | if (slpm_val) | ||
167 | val = slpm_val - 1; | ||
168 | |||
169 | dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n", | ||
170 | pin, | ||
171 | slpm_pull ? pullnames[pull] : "same", | ||
172 | slpm_output ? (output ? "output" : "input") : "same", | ||
173 | slpm_val ? (val ? "high" : "low") : "same"); | ||
174 | } | ||
175 | |||
153 | if (output) | 176 | if (output) |
154 | __nmk_gpio_make_output(nmk_chip, offset, val); | 177 | __nmk_gpio_make_output(nmk_chip, offset, val); |
155 | else { | 178 | else { |
@@ -175,7 +198,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, | |||
175 | * side-effects. The gpio can be manipulated later using standard GPIO API | 198 | * side-effects. The gpio can be manipulated later using standard GPIO API |
176 | * calls. | 199 | * calls. |
177 | */ | 200 | */ |
178 | int nmk_config_pin(pin_cfg_t cfg) | 201 | int nmk_config_pin(pin_cfg_t cfg, bool sleep) |
179 | { | 202 | { |
180 | struct nmk_gpio_chip *nmk_chip; | 203 | struct nmk_gpio_chip *nmk_chip; |
181 | int gpio = PIN_NUM(cfg); | 204 | int gpio = PIN_NUM(cfg); |
@@ -186,7 +209,7 @@ int nmk_config_pin(pin_cfg_t cfg) | |||
186 | return -EINVAL; | 209 | return -EINVAL; |
187 | 210 | ||
188 | spin_lock_irqsave(&nmk_chip->lock, flags); | 211 | spin_lock_irqsave(&nmk_chip->lock, flags); |
189 | __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg); | 212 | __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep); |
190 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 213 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
191 | 214 | ||
192 | return 0; | 215 | return 0; |
@@ -207,7 +230,7 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num) | |||
207 | int i; | 230 | int i; |
208 | 231 | ||
209 | for (i = 0; i < num; i++) { | 232 | for (i = 0; i < num; i++) { |
210 | int ret = nmk_config_pin(cfgs[i]); | 233 | ret = nmk_config_pin(cfgs[i], false); |
211 | if (ret) | 234 | if (ret) |
212 | break; | 235 | break; |
213 | } | 236 | } |
@@ -216,6 +239,21 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num) | |||
216 | } | 239 | } |
217 | EXPORT_SYMBOL(nmk_config_pins); | 240 | EXPORT_SYMBOL(nmk_config_pins); |
218 | 241 | ||
242 | int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num) | ||
243 | { | ||
244 | int ret = 0; | ||
245 | int i; | ||
246 | |||
247 | for (i = 0; i < num; i++) { | ||
248 | ret = nmk_config_pin(cfgs[i], true); | ||
249 | if (ret) | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | EXPORT_SYMBOL(nmk_config_pins_sleep); | ||
256 | |||
219 | /** | 257 | /** |
220 | * nmk_gpio_set_slpm() - configure the sleep mode of a pin | 258 | * nmk_gpio_set_slpm() - configure the sleep mode of a pin |
221 | * @gpio: pin number | 259 | * @gpio: pin number |
@@ -634,7 +672,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) | |||
634 | 672 | ||
635 | chip = &nmk_chip->chip; | 673 | chip = &nmk_chip->chip; |
636 | chip->base = pdata->first_gpio; | 674 | chip->base = pdata->first_gpio; |
637 | chip->label = pdata->name; | 675 | chip->label = pdata->name ?: dev_name(&dev->dev); |
638 | chip->dev = &dev->dev; | 676 | chip->dev = &dev->dev; |
639 | chip->owner = THIS_MODULE; | 677 | chip->owner = THIS_MODULE; |
640 | 678 | ||
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 8c5ae3f2acf8..05a3936ae6d1 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h | |||
@@ -19,16 +19,22 @@ | |||
19 | * bit 9..10 - Alternate Function Selection | 19 | * bit 9..10 - Alternate Function Selection |
20 | * bit 11..12 - Pull up/down state | 20 | * bit 11..12 - Pull up/down state |
21 | * bit 13 - Sleep mode behaviour | 21 | * bit 13 - Sleep mode behaviour |
22 | * bit 14 - (sleep mode) Direction | 22 | * bit 14 - Direction |
23 | * bit 15 - (sleep mode) Value (if output) | 23 | * bit 15 - Value (if output) |
24 | * bit 16..18 - SLPM pull up/down state | ||
25 | * bit 19..20 - SLPM direction | ||
26 | * bit 21..22 - SLPM Value (if output) | ||
24 | * | 27 | * |
25 | * to facilitate the definition, the following macros are provided | 28 | * to facilitate the definition, the following macros are provided |
26 | * | 29 | * |
27 | * PIN_CFG_DEFAULT - default config (0): | 30 | * PIN_CFG_DEFAULT - default config (0): |
28 | * pull up/down = disabled | 31 | * pull up/down = disabled |
29 | * sleep mode = input/wakeup | 32 | * sleep mode = input/wakeup |
30 | * (sleep mode) direction = input | 33 | * direction = input |
31 | * (sleep mode) value = low | 34 | * value = low |
35 | * SLPM direction = same as normal | ||
36 | * SLPM pull = same as normal | ||
37 | * SLPM value = same as normal | ||
32 | * | 38 | * |
33 | * PIN_CFG - default config with alternate function | 39 | * PIN_CFG - default config with alternate function |
34 | * PIN_CFG_PULL - default config with alternate function and pull up/down | 40 | * PIN_CFG_PULL - default config with alternate function and pull up/down |
@@ -75,30 +81,64 @@ typedef unsigned long pin_cfg_t; | |||
75 | #define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) | 81 | #define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) |
76 | #define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) | 82 | #define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) |
77 | 83 | ||
78 | /* Shortcuts. Use these instead of separate DIR and VAL. */ | 84 | #define PIN_SLPM_PULL_SHIFT 16 |
79 | #define PIN_INPUT PIN_DIR_INPUT | 85 | #define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT) |
86 | #define PIN_SLPM_PULL(x) \ | ||
87 | (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT) | ||
88 | #define PIN_SLPM_PULL_NONE \ | ||
89 | ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT) | ||
90 | #define PIN_SLPM_PULL_UP \ | ||
91 | ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT) | ||
92 | #define PIN_SLPM_PULL_DOWN \ | ||
93 | ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT) | ||
94 | |||
95 | #define PIN_SLPM_DIR_SHIFT 19 | ||
96 | #define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT) | ||
97 | #define PIN_SLPM_DIR(x) \ | ||
98 | (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT) | ||
99 | #define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT) | ||
100 | #define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT) | ||
101 | |||
102 | #define PIN_SLPM_VAL_SHIFT 21 | ||
103 | #define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT) | ||
104 | #define PIN_SLPM_VAL(x) \ | ||
105 | (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT) | ||
106 | #define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) | ||
107 | #define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) | ||
108 | |||
109 | /* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ | ||
110 | #define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) | ||
111 | #define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) | ||
112 | #define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE) | ||
80 | #define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) | 113 | #define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) |
81 | #define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) | 114 | #define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) |
82 | 115 | ||
83 | /* | 116 | #define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN) |
84 | * These are the same as the ones above, but should make more sense to the | 117 | #define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP) |
85 | * reader when seen along with a setting a pin to AF mode. | 118 | #define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE) |
86 | */ | 119 | #define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW) |
87 | #define PIN_SLPM_INPUT PIN_INPUT | 120 | #define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH) |
88 | #define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW | ||
89 | #define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH | ||
90 | 121 | ||
91 | #define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) | 122 | #define PIN_CFG_DEFAULT (0) |
92 | 123 | ||
93 | #define PIN_CFG(num, alt) \ | 124 | #define PIN_CFG(num, alt) \ |
94 | (PIN_CFG_DEFAULT |\ | 125 | (PIN_CFG_DEFAULT |\ |
95 | (PIN_NUM(num) | PIN_##alt)) | 126 | (PIN_NUM(num) | PIN_##alt)) |
96 | 127 | ||
128 | #define PIN_CFG_INPUT(num, alt, pull) \ | ||
129 | (PIN_CFG_DEFAULT |\ | ||
130 | (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull)) | ||
131 | |||
132 | #define PIN_CFG_OUTPUT(num, alt, val) \ | ||
133 | (PIN_CFG_DEFAULT |\ | ||
134 | (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) | ||
135 | |||
97 | #define PIN_CFG_PULL(num, alt, pull) \ | 136 | #define PIN_CFG_PULL(num, alt, pull) \ |
98 | ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ | 137 | ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ |
99 | (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) | 138 | (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) |
100 | 139 | ||
101 | extern int nmk_config_pin(pin_cfg_t cfg); | 140 | extern int nmk_config_pin(pin_cfg_t cfg, bool sleep); |
102 | extern int nmk_config_pins(pin_cfg_t *cfgs, int num); | 141 | extern int nmk_config_pins(pin_cfg_t *cfgs, int num); |
142 | extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num); | ||
103 | 143 | ||
104 | #endif | 144 | #endif |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3143ac795eb0..082495bb08a7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -230,11 +230,11 @@ config GPIO_STMPE | |||
230 | This enables support for the GPIOs found on the STMPE I/O | 230 | This enables support for the GPIOs found on the STMPE I/O |
231 | Expanders. | 231 | Expanders. |
232 | 232 | ||
233 | config GPIO_TC35892 | 233 | config GPIO_TC3589X |
234 | bool "TC35892 GPIOs" | 234 | bool "TC3589X GPIOs" |
235 | depends on MFD_TC35892 | 235 | depends on MFD_TC3589X |
236 | help | 236 | help |
237 | This enables support for the GPIOs found on the TC35892 | 237 | This enables support for the GPIOs found on the TC3589X |
238 | I/O Expander. | 238 | I/O Expander. |
239 | 239 | ||
240 | config GPIO_TWL4030 | 240 | config GPIO_TWL4030 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index bdf3ddec0652..39bfd7a37650 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | |||
24 | obj-$(CONFIG_GPIO_PCH) += pch_gpio.o | 24 | obj-$(CONFIG_GPIO_PCH) += pch_gpio.o |
25 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 25 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
26 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o | 26 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o |
27 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o | 27 | obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o |
28 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o | 28 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o |
29 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 29 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
30 | obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o | 30 | obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o |
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c deleted file mode 100644 index 7e10c935a047..000000000000 --- a/drivers/gpio/tc35892-gpio.c +++ /dev/null | |||
@@ -1,389 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson | ||
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/mfd/tc35892.h> | ||
17 | |||
18 | /* | ||
19 | * These registers are modified under the irq bus lock and cached to avoid | ||
20 | * unnecessary writes in bus_sync_unlock. | ||
21 | */ | ||
22 | enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; | ||
23 | |||
24 | #define CACHE_NR_REGS 4 | ||
25 | #define CACHE_NR_BANKS 3 | ||
26 | |||
27 | struct tc35892_gpio { | ||
28 | struct gpio_chip chip; | ||
29 | struct tc35892 *tc35892; | ||
30 | struct device *dev; | ||
31 | struct mutex irq_lock; | ||
32 | |||
33 | int irq_base; | ||
34 | |||
35 | /* Caches of interrupt control registers for bus_lock */ | ||
36 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
37 | u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
38 | }; | ||
39 | |||
40 | static inline struct tc35892_gpio *to_tc35892_gpio(struct gpio_chip *chip) | ||
41 | { | ||
42 | return container_of(chip, struct tc35892_gpio, chip); | ||
43 | } | ||
44 | |||
45 | static int tc35892_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
46 | { | ||
47 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
48 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
49 | u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2; | ||
50 | u8 mask = 1 << (offset % 8); | ||
51 | int ret; | ||
52 | |||
53 | ret = tc35892_reg_read(tc35892, reg); | ||
54 | if (ret < 0) | ||
55 | return ret; | ||
56 | |||
57 | return ret & mask; | ||
58 | } | ||
59 | |||
60 | static void tc35892_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
61 | { | ||
62 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
63 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
64 | u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2; | ||
65 | unsigned pos = offset % 8; | ||
66 | u8 data[] = {!!val << pos, 1 << pos}; | ||
67 | |||
68 | tc35892_block_write(tc35892, reg, ARRAY_SIZE(data), data); | ||
69 | } | ||
70 | |||
71 | static int tc35892_gpio_direction_output(struct gpio_chip *chip, | ||
72 | unsigned offset, int val) | ||
73 | { | ||
74 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
75 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
76 | u8 reg = TC35892_GPIODIR0 + offset / 8; | ||
77 | unsigned pos = offset % 8; | ||
78 | |||
79 | tc35892_gpio_set(chip, offset, val); | ||
80 | |||
81 | return tc35892_set_bits(tc35892, reg, 1 << pos, 1 << pos); | ||
82 | } | ||
83 | |||
84 | static int tc35892_gpio_direction_input(struct gpio_chip *chip, | ||
85 | unsigned offset) | ||
86 | { | ||
87 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
88 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
89 | u8 reg = TC35892_GPIODIR0 + offset / 8; | ||
90 | unsigned pos = offset % 8; | ||
91 | |||
92 | return tc35892_set_bits(tc35892, reg, 1 << pos, 0); | ||
93 | } | ||
94 | |||
95 | static int tc35892_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
96 | { | ||
97 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
98 | |||
99 | return tc35892_gpio->irq_base + offset; | ||
100 | } | ||
101 | |||
102 | static struct gpio_chip template_chip = { | ||
103 | .label = "tc35892", | ||
104 | .owner = THIS_MODULE, | ||
105 | .direction_input = tc35892_gpio_direction_input, | ||
106 | .get = tc35892_gpio_get, | ||
107 | .direction_output = tc35892_gpio_direction_output, | ||
108 | .set = tc35892_gpio_set, | ||
109 | .to_irq = tc35892_gpio_to_irq, | ||
110 | .can_sleep = 1, | ||
111 | }; | ||
112 | |||
113 | static int tc35892_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
114 | { | ||
115 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
116 | int offset = irq - tc35892_gpio->irq_base; | ||
117 | int regoffset = offset / 8; | ||
118 | int mask = 1 << (offset % 8); | ||
119 | |||
120 | if (type == IRQ_TYPE_EDGE_BOTH) { | ||
121 | tc35892_gpio->regs[REG_IBE][regoffset] |= mask; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | tc35892_gpio->regs[REG_IBE][regoffset] &= ~mask; | ||
126 | |||
127 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | ||
128 | tc35892_gpio->regs[REG_IS][regoffset] |= mask; | ||
129 | else | ||
130 | tc35892_gpio->regs[REG_IS][regoffset] &= ~mask; | ||
131 | |||
132 | if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) | ||
133 | tc35892_gpio->regs[REG_IEV][regoffset] |= mask; | ||
134 | else | ||
135 | tc35892_gpio->regs[REG_IEV][regoffset] &= ~mask; | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void tc35892_gpio_irq_lock(unsigned int irq) | ||
141 | { | ||
142 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
143 | |||
144 | mutex_lock(&tc35892_gpio->irq_lock); | ||
145 | } | ||
146 | |||
147 | static void tc35892_gpio_irq_sync_unlock(unsigned int irq) | ||
148 | { | ||
149 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
150 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
151 | static const u8 regmap[] = { | ||
152 | [REG_IBE] = TC35892_GPIOIBE0, | ||
153 | [REG_IEV] = TC35892_GPIOIEV0, | ||
154 | [REG_IS] = TC35892_GPIOIS0, | ||
155 | [REG_IE] = TC35892_GPIOIE0, | ||
156 | }; | ||
157 | int i, j; | ||
158 | |||
159 | for (i = 0; i < CACHE_NR_REGS; i++) { | ||
160 | for (j = 0; j < CACHE_NR_BANKS; j++) { | ||
161 | u8 old = tc35892_gpio->oldregs[i][j]; | ||
162 | u8 new = tc35892_gpio->regs[i][j]; | ||
163 | |||
164 | if (new == old) | ||
165 | continue; | ||
166 | |||
167 | tc35892_gpio->oldregs[i][j] = new; | ||
168 | tc35892_reg_write(tc35892, regmap[i] + j * 8, new); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | mutex_unlock(&tc35892_gpio->irq_lock); | ||
173 | } | ||
174 | |||
175 | static void tc35892_gpio_irq_mask(unsigned int irq) | ||
176 | { | ||
177 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
178 | int offset = irq - tc35892_gpio->irq_base; | ||
179 | int regoffset = offset / 8; | ||
180 | int mask = 1 << (offset % 8); | ||
181 | |||
182 | tc35892_gpio->regs[REG_IE][regoffset] &= ~mask; | ||
183 | } | ||
184 | |||
185 | static void tc35892_gpio_irq_unmask(unsigned int irq) | ||
186 | { | ||
187 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
188 | int offset = irq - tc35892_gpio->irq_base; | ||
189 | int regoffset = offset / 8; | ||
190 | int mask = 1 << (offset % 8); | ||
191 | |||
192 | tc35892_gpio->regs[REG_IE][regoffset] |= mask; | ||
193 | } | ||
194 | |||
195 | static struct irq_chip tc35892_gpio_irq_chip = { | ||
196 | .name = "tc35892-gpio", | ||
197 | .bus_lock = tc35892_gpio_irq_lock, | ||
198 | .bus_sync_unlock = tc35892_gpio_irq_sync_unlock, | ||
199 | .mask = tc35892_gpio_irq_mask, | ||
200 | .unmask = tc35892_gpio_irq_unmask, | ||
201 | .set_type = tc35892_gpio_irq_set_type, | ||
202 | }; | ||
203 | |||
204 | static irqreturn_t tc35892_gpio_irq(int irq, void *dev) | ||
205 | { | ||
206 | struct tc35892_gpio *tc35892_gpio = dev; | ||
207 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
208 | u8 status[CACHE_NR_BANKS]; | ||
209 | int ret; | ||
210 | int i; | ||
211 | |||
212 | ret = tc35892_block_read(tc35892, TC35892_GPIOMIS0, | ||
213 | ARRAY_SIZE(status), status); | ||
214 | if (ret < 0) | ||
215 | return IRQ_NONE; | ||
216 | |||
217 | for (i = 0; i < ARRAY_SIZE(status); i++) { | ||
218 | unsigned int stat = status[i]; | ||
219 | if (!stat) | ||
220 | continue; | ||
221 | |||
222 | while (stat) { | ||
223 | int bit = __ffs(stat); | ||
224 | int line = i * 8 + bit; | ||
225 | |||
226 | handle_nested_irq(tc35892_gpio->irq_base + line); | ||
227 | stat &= ~(1 << bit); | ||
228 | } | ||
229 | |||
230 | tc35892_reg_write(tc35892, TC35892_GPIOIC0 + i, status[i]); | ||
231 | } | ||
232 | |||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio) | ||
237 | { | ||
238 | int base = tc35892_gpio->irq_base; | ||
239 | int irq; | ||
240 | |||
241 | for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) { | ||
242 | set_irq_chip_data(irq, tc35892_gpio); | ||
243 | set_irq_chip_and_handler(irq, &tc35892_gpio_irq_chip, | ||
244 | handle_simple_irq); | ||
245 | set_irq_nested_thread(irq, 1); | ||
246 | #ifdef CONFIG_ARM | ||
247 | set_irq_flags(irq, IRQF_VALID); | ||
248 | #else | ||
249 | set_irq_noprobe(irq); | ||
250 | #endif | ||
251 | } | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio) | ||
257 | { | ||
258 | int base = tc35892_gpio->irq_base; | ||
259 | int irq; | ||
260 | |||
261 | for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) { | ||
262 | #ifdef CONFIG_ARM | ||
263 | set_irq_flags(irq, 0); | ||
264 | #endif | ||
265 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
266 | set_irq_chip_data(irq, NULL); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static int __devinit tc35892_gpio_probe(struct platform_device *pdev) | ||
271 | { | ||
272 | struct tc35892 *tc35892 = dev_get_drvdata(pdev->dev.parent); | ||
273 | struct tc35892_gpio_platform_data *pdata; | ||
274 | struct tc35892_gpio *tc35892_gpio; | ||
275 | int ret; | ||
276 | int irq; | ||
277 | |||
278 | pdata = tc35892->pdata->gpio; | ||
279 | if (!pdata) | ||
280 | return -ENODEV; | ||
281 | |||
282 | irq = platform_get_irq(pdev, 0); | ||
283 | if (irq < 0) | ||
284 | return irq; | ||
285 | |||
286 | tc35892_gpio = kzalloc(sizeof(struct tc35892_gpio), GFP_KERNEL); | ||
287 | if (!tc35892_gpio) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | mutex_init(&tc35892_gpio->irq_lock); | ||
291 | |||
292 | tc35892_gpio->dev = &pdev->dev; | ||
293 | tc35892_gpio->tc35892 = tc35892; | ||
294 | |||
295 | tc35892_gpio->chip = template_chip; | ||
296 | tc35892_gpio->chip.ngpio = tc35892->num_gpio; | ||
297 | tc35892_gpio->chip.dev = &pdev->dev; | ||
298 | tc35892_gpio->chip.base = pdata->gpio_base; | ||
299 | |||
300 | tc35892_gpio->irq_base = tc35892->irq_base + TC35892_INT_GPIO(0); | ||
301 | |||
302 | /* Bring the GPIO module out of reset */ | ||
303 | ret = tc35892_set_bits(tc35892, TC35892_RSTCTRL, | ||
304 | TC35892_RSTCTRL_GPIRST, 0); | ||
305 | if (ret < 0) | ||
306 | goto out_free; | ||
307 | |||
308 | ret = tc35892_gpio_irq_init(tc35892_gpio); | ||
309 | if (ret) | ||
310 | goto out_free; | ||
311 | |||
312 | ret = request_threaded_irq(irq, NULL, tc35892_gpio_irq, IRQF_ONESHOT, | ||
313 | "tc35892-gpio", tc35892_gpio); | ||
314 | if (ret) { | ||
315 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
316 | goto out_removeirq; | ||
317 | } | ||
318 | |||
319 | ret = gpiochip_add(&tc35892_gpio->chip); | ||
320 | if (ret) { | ||
321 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
322 | goto out_freeirq; | ||
323 | } | ||
324 | |||
325 | if (pdata->setup) | ||
326 | pdata->setup(tc35892, tc35892_gpio->chip.base); | ||
327 | |||
328 | platform_set_drvdata(pdev, tc35892_gpio); | ||
329 | |||
330 | return 0; | ||
331 | |||
332 | out_freeirq: | ||
333 | free_irq(irq, tc35892_gpio); | ||
334 | out_removeirq: | ||
335 | tc35892_gpio_irq_remove(tc35892_gpio); | ||
336 | out_free: | ||
337 | kfree(tc35892_gpio); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static int __devexit tc35892_gpio_remove(struct platform_device *pdev) | ||
342 | { | ||
343 | struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev); | ||
344 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
345 | struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio; | ||
346 | int irq = platform_get_irq(pdev, 0); | ||
347 | int ret; | ||
348 | |||
349 | if (pdata->remove) | ||
350 | pdata->remove(tc35892, tc35892_gpio->chip.base); | ||
351 | |||
352 | ret = gpiochip_remove(&tc35892_gpio->chip); | ||
353 | if (ret < 0) { | ||
354 | dev_err(tc35892_gpio->dev, | ||
355 | "unable to remove gpiochip: %d\n", ret); | ||
356 | return ret; | ||
357 | } | ||
358 | |||
359 | free_irq(irq, tc35892_gpio); | ||
360 | tc35892_gpio_irq_remove(tc35892_gpio); | ||
361 | |||
362 | platform_set_drvdata(pdev, NULL); | ||
363 | kfree(tc35892_gpio); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static struct platform_driver tc35892_gpio_driver = { | ||
369 | .driver.name = "tc35892-gpio", | ||
370 | .driver.owner = THIS_MODULE, | ||
371 | .probe = tc35892_gpio_probe, | ||
372 | .remove = __devexit_p(tc35892_gpio_remove), | ||
373 | }; | ||
374 | |||
375 | static int __init tc35892_gpio_init(void) | ||
376 | { | ||
377 | return platform_driver_register(&tc35892_gpio_driver); | ||
378 | } | ||
379 | subsys_initcall(tc35892_gpio_init); | ||
380 | |||
381 | static void __exit tc35892_gpio_exit(void) | ||
382 | { | ||
383 | platform_driver_unregister(&tc35892_gpio_driver); | ||
384 | } | ||
385 | module_exit(tc35892_gpio_exit); | ||
386 | |||
387 | MODULE_LICENSE("GPL v2"); | ||
388 | MODULE_DESCRIPTION("TC35892 GPIO driver"); | ||
389 | MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); | ||
diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c new file mode 100644 index 000000000000..180d584454fb --- /dev/null +++ b/drivers/gpio/tc3589x-gpio.c | |||
@@ -0,0 +1,389 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson | ||
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/mfd/tc3589x.h> | ||
17 | |||
18 | /* | ||
19 | * These registers are modified under the irq bus lock and cached to avoid | ||
20 | * unnecessary writes in bus_sync_unlock. | ||
21 | */ | ||
22 | enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; | ||
23 | |||
24 | #define CACHE_NR_REGS 4 | ||
25 | #define CACHE_NR_BANKS 3 | ||
26 | |||
27 | struct tc3589x_gpio { | ||
28 | struct gpio_chip chip; | ||
29 | struct tc3589x *tc3589x; | ||
30 | struct device *dev; | ||
31 | struct mutex irq_lock; | ||
32 | |||
33 | int irq_base; | ||
34 | |||
35 | /* Caches of interrupt control registers for bus_lock */ | ||
36 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
37 | u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
38 | }; | ||
39 | |||
40 | static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip) | ||
41 | { | ||
42 | return container_of(chip, struct tc3589x_gpio, chip); | ||
43 | } | ||
44 | |||
45 | static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
46 | { | ||
47 | struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); | ||
48 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | ||
49 | u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; | ||
50 | u8 mask = 1 << (offset % 8); | ||
51 | int ret; | ||
52 | |||
53 | ret = tc3589x_reg_read(tc3589x, reg); | ||
54 | if (ret < 0) | ||
55 | return ret; | ||
56 | |||
57 | return ret & mask; | ||
58 | } | ||
59 | |||
60 | static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
61 | { | ||
62 | struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); | ||
63 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | ||
64 | u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; | ||
65 | unsigned pos = offset % 8; | ||
66 | u8 data[] = {!!val << pos, 1 << pos}; | ||
67 | |||
68 | tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); | ||
69 | } | ||
70 | |||
71 | static int tc3589x_gpio_direction_output(struct gpio_chip *chip, | ||
72 | unsigned offset, int val) | ||
73 | { | ||
74 | struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); | ||
75 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | ||
76 | u8 reg = TC3589x_GPIODIR0 + offset / 8; | ||
77 | unsigned pos = offset % 8; | ||
78 | |||
79 | tc3589x_gpio_set(chip, offset, val); | ||
80 | |||
81 | return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos); | ||
82 | } | ||
83 | |||
84 | static int tc3589x_gpio_direction_input(struct gpio_chip *chip, | ||
85 | unsigned offset) | ||
86 | { | ||
87 | struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); | ||
88 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | ||
89 | u8 reg = TC3589x_GPIODIR0 + offset / 8; | ||
90 | unsigned pos = offset % 8; | ||
91 | |||
92 | return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); | ||
93 | } | ||
94 | |||
95 | static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
96 | { | ||
97 | struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); | ||
98 | |||
99 | return tc3589x_gpio->irq_base + offset; | ||
100 | } | ||
101 | |||
102 | static struct gpio_chip template_chip = { | ||
103 | .label = "tc3589x", | ||
104 | .owner = THIS_MODULE, | ||
105 | .direction_input = tc3589x_gpio_direction_input, | ||
106 | .get = tc3589x_gpio_get, | ||
107 | .direction_output = tc3589x_gpio_direction_output, | ||
108 | .set = tc3589x_gpio_set, | ||
109 | .to_irq = tc3589x_gpio_to_irq, | ||
110 | .can_sleep = 1, | ||
111 | }; | ||
112 | |||
113 | static int tc3589x_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
114 | { | ||
115 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | ||
116 | int offset = irq - tc3589x_gpio->irq_base; | ||
117 | int regoffset = offset / 8; | ||
118 | int mask = 1 << (offset % 8); | ||
119 | |||
120 | if (type == IRQ_TYPE_EDGE_BOTH) { | ||
121 | tc3589x_gpio->regs[REG_IBE][regoffset] |= mask; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask; | ||
126 | |||
127 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | ||
128 | tc3589x_gpio->regs[REG_IS][regoffset] |= mask; | ||
129 | else | ||
130 | tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask; | ||
131 | |||
132 | if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) | ||
133 | tc3589x_gpio->regs[REG_IEV][regoffset] |= mask; | ||
134 | else | ||
135 | tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask; | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void tc3589x_gpio_irq_lock(unsigned int irq) | ||
141 | { | ||
142 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | ||
143 | |||
144 | mutex_lock(&tc3589x_gpio->irq_lock); | ||
145 | } | ||
146 | |||
147 | static void tc3589x_gpio_irq_sync_unlock(unsigned int irq) | ||
148 | { | ||
149 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | ||
150 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | ||
151 | static const u8 regmap[] = { | ||
152 | [REG_IBE] = TC3589x_GPIOIBE0, | ||
153 | [REG_IEV] = TC3589x_GPIOIEV0, | ||
154 | [REG_IS] = TC3589x_GPIOIS0, | ||
155 | [REG_IE] = TC3589x_GPIOIE0, | ||
156 | }; | ||
157 | int i, j; | ||
158 | |||
159 | for (i = 0; i < CACHE_NR_REGS; i++) { | ||
160 | for (j = 0; j < CACHE_NR_BANKS; j++) { | ||
161 | u8 old = tc3589x_gpio->oldregs[i][j]; | ||
162 | u8 new = tc3589x_gpio->regs[i][j]; | ||
163 | |||
164 | if (new == old) | ||
165 | continue; | ||
166 | |||
167 | tc3589x_gpio->oldregs[i][j] = new; | ||
168 | tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | mutex_unlock(&tc3589x_gpio->irq_lock); | ||
173 | } | ||
174 | |||
175 | static void tc3589x_gpio_irq_mask(unsigned int irq) | ||
176 | { | ||
177 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | ||
178 | int offset = irq - tc3589x_gpio->irq_base; | ||
179 | int regoffset = offset / 8; | ||
180 | int mask = 1 << (offset % 8); | ||
181 | |||
182 | tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; | ||
183 | } | ||
184 | |||
185 | static void tc3589x_gpio_irq_unmask(unsigned int irq) | ||
186 | { | ||
187 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | ||
188 | int offset = irq - tc3589x_gpio->irq_base; | ||
189 | int regoffset = offset / 8; | ||
190 | int mask = 1 << (offset % 8); | ||
191 | |||
192 | tc3589x_gpio->regs[REG_IE][regoffset] |= mask; | ||
193 | } | ||
194 | |||
195 | static struct irq_chip tc3589x_gpio_irq_chip = { | ||
196 | .name = "tc3589x-gpio", | ||
197 | .bus_lock = tc3589x_gpio_irq_lock, | ||
198 | .bus_sync_unlock = tc3589x_gpio_irq_sync_unlock, | ||
199 | .mask = tc3589x_gpio_irq_mask, | ||
200 | .unmask = tc3589x_gpio_irq_unmask, | ||
201 | .set_type = tc3589x_gpio_irq_set_type, | ||
202 | }; | ||
203 | |||
204 | static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) | ||
205 | { | ||
206 | struct tc3589x_gpio *tc3589x_gpio = dev; | ||
207 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | ||
208 | u8 status[CACHE_NR_BANKS]; | ||
209 | int ret; | ||
210 | int i; | ||
211 | |||
212 | ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0, | ||
213 | ARRAY_SIZE(status), status); | ||
214 | if (ret < 0) | ||
215 | return IRQ_NONE; | ||
216 | |||
217 | for (i = 0; i < ARRAY_SIZE(status); i++) { | ||
218 | unsigned int stat = status[i]; | ||
219 | if (!stat) | ||
220 | continue; | ||
221 | |||
222 | while (stat) { | ||
223 | int bit = __ffs(stat); | ||
224 | int line = i * 8 + bit; | ||
225 | |||
226 | handle_nested_irq(tc3589x_gpio->irq_base + line); | ||
227 | stat &= ~(1 << bit); | ||
228 | } | ||
229 | |||
230 | tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]); | ||
231 | } | ||
232 | |||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio) | ||
237 | { | ||
238 | int base = tc3589x_gpio->irq_base; | ||
239 | int irq; | ||
240 | |||
241 | for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { | ||
242 | set_irq_chip_data(irq, tc3589x_gpio); | ||
243 | set_irq_chip_and_handler(irq, &tc3589x_gpio_irq_chip, | ||
244 | handle_simple_irq); | ||
245 | set_irq_nested_thread(irq, 1); | ||
246 | #ifdef CONFIG_ARM | ||
247 | set_irq_flags(irq, IRQF_VALID); | ||
248 | #else | ||
249 | set_irq_noprobe(irq); | ||
250 | #endif | ||
251 | } | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio) | ||
257 | { | ||
258 | int base = tc3589x_gpio->irq_base; | ||
259 | int irq; | ||
260 | |||
261 | for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { | ||
262 | #ifdef CONFIG_ARM | ||
263 | set_irq_flags(irq, 0); | ||
264 | #endif | ||
265 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
266 | set_irq_chip_data(irq, NULL); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) | ||
271 | { | ||
272 | struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); | ||
273 | struct tc3589x_gpio_platform_data *pdata; | ||
274 | struct tc3589x_gpio *tc3589x_gpio; | ||
275 | int ret; | ||
276 | int irq; | ||
277 | |||
278 | pdata = tc3589x->pdata->gpio; | ||
279 | if (!pdata) | ||
280 | return -ENODEV; | ||
281 | |||
282 | irq = platform_get_irq(pdev, 0); | ||
283 | if (irq < 0) | ||
284 | return irq; | ||
285 | |||
286 | tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL); | ||
287 | if (!tc3589x_gpio) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | mutex_init(&tc3589x_gpio->irq_lock); | ||
291 | |||
292 | tc3589x_gpio->dev = &pdev->dev; | ||
293 | tc3589x_gpio->tc3589x = tc3589x; | ||
294 | |||
295 | tc3589x_gpio->chip = template_chip; | ||
296 | tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; | ||
297 | tc3589x_gpio->chip.dev = &pdev->dev; | ||
298 | tc3589x_gpio->chip.base = pdata->gpio_base; | ||
299 | |||
300 | tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0); | ||
301 | |||
302 | /* Bring the GPIO module out of reset */ | ||
303 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, | ||
304 | TC3589x_RSTCTRL_GPIRST, 0); | ||
305 | if (ret < 0) | ||
306 | goto out_free; | ||
307 | |||
308 | ret = tc3589x_gpio_irq_init(tc3589x_gpio); | ||
309 | if (ret) | ||
310 | goto out_free; | ||
311 | |||
312 | ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT, | ||
313 | "tc3589x-gpio", tc3589x_gpio); | ||
314 | if (ret) { | ||
315 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
316 | goto out_removeirq; | ||
317 | } | ||
318 | |||
319 | ret = gpiochip_add(&tc3589x_gpio->chip); | ||
320 | if (ret) { | ||
321 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
322 | goto out_freeirq; | ||
323 | } | ||
324 | |||
325 | if (pdata->setup) | ||
326 | pdata->setup(tc3589x, tc3589x_gpio->chip.base); | ||
327 | |||
328 | platform_set_drvdata(pdev, tc3589x_gpio); | ||
329 | |||
330 | return 0; | ||
331 | |||
332 | out_freeirq: | ||
333 | free_irq(irq, tc3589x_gpio); | ||
334 | out_removeirq: | ||
335 | tc3589x_gpio_irq_remove(tc3589x_gpio); | ||
336 | out_free: | ||
337 | kfree(tc3589x_gpio); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static int __devexit tc3589x_gpio_remove(struct platform_device *pdev) | ||
342 | { | ||
343 | struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev); | ||
344 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | ||
345 | struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio; | ||
346 | int irq = platform_get_irq(pdev, 0); | ||
347 | int ret; | ||
348 | |||
349 | if (pdata->remove) | ||
350 | pdata->remove(tc3589x, tc3589x_gpio->chip.base); | ||
351 | |||
352 | ret = gpiochip_remove(&tc3589x_gpio->chip); | ||
353 | if (ret < 0) { | ||
354 | dev_err(tc3589x_gpio->dev, | ||
355 | "unable to remove gpiochip: %d\n", ret); | ||
356 | return ret; | ||
357 | } | ||
358 | |||
359 | free_irq(irq, tc3589x_gpio); | ||
360 | tc3589x_gpio_irq_remove(tc3589x_gpio); | ||
361 | |||
362 | platform_set_drvdata(pdev, NULL); | ||
363 | kfree(tc3589x_gpio); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static struct platform_driver tc3589x_gpio_driver = { | ||
369 | .driver.name = "tc3589x-gpio", | ||
370 | .driver.owner = THIS_MODULE, | ||
371 | .probe = tc3589x_gpio_probe, | ||
372 | .remove = __devexit_p(tc3589x_gpio_remove), | ||
373 | }; | ||
374 | |||
375 | static int __init tc3589x_gpio_init(void) | ||
376 | { | ||
377 | return platform_driver_register(&tc3589x_gpio_driver); | ||
378 | } | ||
379 | subsys_initcall(tc3589x_gpio_init); | ||
380 | |||
381 | static void __exit tc3589x_gpio_exit(void) | ||
382 | { | ||
383 | platform_driver_unregister(&tc3589x_gpio_driver); | ||
384 | } | ||
385 | module_exit(tc3589x_gpio_exit); | ||
386 | |||
387 | MODULE_LICENSE("GPL v2"); | ||
388 | MODULE_DESCRIPTION("TC3589x GPIO driver"); | ||
389 | MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 3a87f3ba5f75..c76bd3183beb 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -459,6 +459,16 @@ config KEYBOARD_OMAP4 | |||
459 | To compile this driver as a module, choose M here: the | 459 | To compile this driver as a module, choose M here: the |
460 | module will be called omap4-keypad. | 460 | module will be called omap4-keypad. |
461 | 461 | ||
462 | config KEYBOARD_TC3589X | ||
463 | tristate "TC3589X Keypad support" | ||
464 | depends on MFD_TC3589X | ||
465 | help | ||
466 | Say Y here if you want to use the keypad controller on | ||
467 | TC35892/3 I/O expander. | ||
468 | |||
469 | To compile this driver as a module, choose M here: the | ||
470 | module will be called tc3589x-keypad. | ||
471 | |||
462 | config KEYBOARD_TNETV107X | 472 | config KEYBOARD_TNETV107X |
463 | tristate "TI TNETV107X keypad support" | 473 | tristate "TI TNETV107X keypad support" |
464 | depends on ARCH_DAVINCI_TNETV107X | 474 | depends on ARCH_DAVINCI_TNETV107X |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 622de73a445d..2aa6ce248b71 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | |||
41 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o | 41 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o |
42 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 42 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
43 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 43 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
44 | obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o | ||
44 | obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o | 45 | obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o |
45 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 46 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
46 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 47 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c new file mode 100644 index 000000000000..69dc0cb20a00 --- /dev/null +++ b/drivers/input/keyboard/tc3589x-keypad.c | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com> | ||
5 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> | ||
6 | * | ||
7 | * License Terms: GNU General Public License, version 2 | ||
8 | * | ||
9 | * TC35893 MFD Keypad Controller driver | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/input/matrix_keypad.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/mfd/tc3589x.h> | ||
21 | |||
22 | /* Maximum supported keypad matrix row/columns size */ | ||
23 | #define TC3589x_MAX_KPROW 8 | ||
24 | #define TC3589x_MAX_KPCOL 12 | ||
25 | |||
26 | /* keypad related Constants */ | ||
27 | #define TC3589x_MAX_DEBOUNCE_SETTLE 0xFF | ||
28 | #define DEDICATED_KEY_VAL 0xFF | ||
29 | |||
30 | /* Pull up/down masks */ | ||
31 | #define TC3589x_NO_PULL_MASK 0x0 | ||
32 | #define TC3589x_PULL_DOWN_MASK 0x1 | ||
33 | #define TC3589x_PULL_UP_MASK 0x2 | ||
34 | #define TC3589x_PULLUP_ALL_MASK 0xAA | ||
35 | #define TC3589x_IO_PULL_VAL(index, mask) ((mask)<<((index)%4)*2)) | ||
36 | |||
37 | /* Bit masks for IOCFG register */ | ||
38 | #define IOCFG_BALLCFG 0x01 | ||
39 | #define IOCFG_IG 0x08 | ||
40 | |||
41 | #define KP_EVCODE_COL_MASK 0x0F | ||
42 | #define KP_EVCODE_ROW_MASK 0x70 | ||
43 | #define KP_RELEASE_EVT_MASK 0x80 | ||
44 | |||
45 | #define KP_ROW_SHIFT 4 | ||
46 | |||
47 | #define KP_NO_VALID_KEY_MASK 0x7F | ||
48 | |||
49 | /* bit masks for RESTCTRL register */ | ||
50 | #define TC3589x_KBDRST 0x2 | ||
51 | #define TC3589x_IRQRST 0x10 | ||
52 | #define TC3589x_RESET_ALL 0x1B | ||
53 | |||
54 | /* KBDMFS register bit mask */ | ||
55 | #define TC3589x_KBDMFS_EN 0x1 | ||
56 | |||
57 | /* CLKEN register bitmask */ | ||
58 | #define KPD_CLK_EN 0x1 | ||
59 | |||
60 | /* RSTINTCLR register bit mask */ | ||
61 | #define IRQ_CLEAR 0x1 | ||
62 | |||
63 | /* bit masks for keyboard interrupts*/ | ||
64 | #define TC3589x_EVT_LOSS_INT 0x8 | ||
65 | #define TC3589x_EVT_INT 0x4 | ||
66 | #define TC3589x_KBD_LOSS_INT 0x2 | ||
67 | #define TC3589x_KBD_INT 0x1 | ||
68 | |||
69 | /* bit masks for keyboard interrupt clear*/ | ||
70 | #define TC3589x_EVT_INT_CLR 0x2 | ||
71 | #define TC3589x_KBD_INT_CLR 0x1 | ||
72 | |||
73 | #define TC3589x_KBD_KEYMAP_SIZE 64 | ||
74 | |||
75 | /** | ||
76 | * struct tc_keypad - data structure used by keypad driver | ||
77 | * @input: pointer to input device object | ||
78 | * @board: keypad platform device | ||
79 | * @krow: number of rows | ||
80 | * @kcol: number of coloumns | ||
81 | * @keymap: matrix scan code table for keycodes | ||
82 | */ | ||
83 | struct tc_keypad { | ||
84 | struct tc3589x *tc3589x; | ||
85 | struct input_dev *input; | ||
86 | const struct tc3589x_keypad_platform_data *board; | ||
87 | unsigned int krow; | ||
88 | unsigned int kcol; | ||
89 | unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE]; | ||
90 | bool keypad_stopped; | ||
91 | }; | ||
92 | |||
93 | static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) | ||
94 | { | ||
95 | int ret; | ||
96 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
97 | u8 settle_time = keypad->board->settle_time; | ||
98 | u8 dbounce_period = keypad->board->debounce_period; | ||
99 | u8 rows = keypad->board->krow & 0xf; /* mask out the nibble */ | ||
100 | u8 column = keypad->board->kcol & 0xf; /* mask out the nibble */ | ||
101 | |||
102 | /* validate platform configurations */ | ||
103 | if (keypad->board->kcol > TC3589x_MAX_KPCOL || | ||
104 | keypad->board->krow > TC3589x_MAX_KPROW || | ||
105 | keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE || | ||
106 | keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE) | ||
107 | return -EINVAL; | ||
108 | |||
109 | /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */ | ||
110 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE, | ||
111 | (rows << KP_ROW_SHIFT) | column); | ||
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | /* configure dedicated key config, no dedicated key selected */ | ||
116 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL); | ||
121 | if (ret < 0) | ||
122 | return ret; | ||
123 | |||
124 | /* Configure settle time */ | ||
125 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time); | ||
126 | if (ret < 0) | ||
127 | return ret; | ||
128 | |||
129 | /* Configure debounce time */ | ||
130 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | |||
134 | /* Start of initialise keypad GPIOs */ | ||
135 | ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | /* Configure pull-up resistors for all row GPIOs */ | ||
140 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB, | ||
141 | TC3589x_PULLUP_ALL_MASK); | ||
142 | if (ret < 0) | ||
143 | return ret; | ||
144 | |||
145 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB, | ||
146 | TC3589x_PULLUP_ALL_MASK); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | /* Configure pull-up resistors for all column GPIOs */ | ||
151 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB, | ||
152 | TC3589x_PULLUP_ALL_MASK); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB, | ||
157 | TC3589x_PULLUP_ALL_MASK); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
161 | ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB, | ||
162 | TC3589x_PULLUP_ALL_MASK); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | #define TC35893_DATA_REGS 4 | ||
168 | #define TC35893_KEYCODE_FIFO_EMPTY 0x7f | ||
169 | #define TC35893_KEYCODE_FIFO_CLEAR 0xff | ||
170 | #define TC35893_KEYPAD_ROW_SHIFT 0x3 | ||
171 | |||
172 | static irqreturn_t tc3589x_keypad_irq(int irq, void *dev) | ||
173 | { | ||
174 | struct tc_keypad *keypad = dev; | ||
175 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
176 | u8 i, row_index, col_index, kbd_code, up; | ||
177 | u8 code; | ||
178 | |||
179 | for (i = 0; i < TC35893_DATA_REGS * 2; i++) { | ||
180 | kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO); | ||
181 | |||
182 | /* loop till fifo is empty and no more keys are pressed */ | ||
183 | if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY || | ||
184 | kbd_code == TC35893_KEYCODE_FIFO_CLEAR) | ||
185 | continue; | ||
186 | |||
187 | /* valid key is found */ | ||
188 | col_index = kbd_code & KP_EVCODE_COL_MASK; | ||
189 | row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT; | ||
190 | code = MATRIX_SCAN_CODE(row_index, col_index, | ||
191 | TC35893_KEYPAD_ROW_SHIFT); | ||
192 | up = kbd_code & KP_RELEASE_EVT_MASK; | ||
193 | |||
194 | input_event(keypad->input, EV_MSC, MSC_SCAN, code); | ||
195 | input_report_key(keypad->input, keypad->keymap[code], !up); | ||
196 | input_sync(keypad->input); | ||
197 | } | ||
198 | |||
199 | /* clear IRQ */ | ||
200 | tc3589x_set_bits(tc3589x, TC3589x_KBDIC, | ||
201 | 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); | ||
202 | /* enable IRQ */ | ||
203 | tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, | ||
204 | 0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); | ||
205 | |||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
209 | static int tc3589x_keypad_enable(struct tc_keypad *keypad) | ||
210 | { | ||
211 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
212 | int ret; | ||
213 | |||
214 | /* pull the keypad module out of reset */ | ||
215 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0); | ||
216 | if (ret < 0) | ||
217 | return ret; | ||
218 | |||
219 | /* configure KBDMFS */ | ||
220 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN); | ||
221 | if (ret < 0) | ||
222 | return ret; | ||
223 | |||
224 | /* enable the keypad clock */ | ||
225 | ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | |||
229 | /* clear pending IRQs */ | ||
230 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
233 | |||
234 | /* enable the IRQs */ | ||
235 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0, | ||
236 | TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); | ||
237 | if (ret < 0) | ||
238 | return ret; | ||
239 | |||
240 | keypad->keypad_stopped = false; | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static int tc3589x_keypad_disable(struct tc_keypad *keypad) | ||
246 | { | ||
247 | struct tc3589x *tc3589x = keypad->tc3589x; | ||
248 | int ret; | ||
249 | |||
250 | /* clear IRQ */ | ||
251 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC, | ||
252 | 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); | ||
253 | if (ret < 0) | ||
254 | return ret; | ||
255 | |||
256 | /* disable all interrupts */ | ||
257 | ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, | ||
258 | ~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0); | ||
259 | if (ret < 0) | ||
260 | return ret; | ||
261 | |||
262 | /* disable the keypad module */ | ||
263 | ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0); | ||
264 | if (ret < 0) | ||
265 | return ret; | ||
266 | |||
267 | /* put the keypad module into reset */ | ||
268 | ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1); | ||
269 | |||
270 | keypad->keypad_stopped = true; | ||
271 | |||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | static int tc3589x_keypad_open(struct input_dev *input) | ||
276 | { | ||
277 | int error; | ||
278 | struct tc_keypad *keypad = input_get_drvdata(input); | ||
279 | |||
280 | /* enable the keypad module */ | ||
281 | error = tc3589x_keypad_enable(keypad); | ||
282 | if (error < 0) { | ||
283 | dev_err(&input->dev, "failed to enable keypad module\n"); | ||
284 | return error; | ||
285 | } | ||
286 | |||
287 | error = tc3589x_keypad_init_key_hardware(keypad); | ||
288 | if (error < 0) { | ||
289 | dev_err(&input->dev, "failed to configure keypad module\n"); | ||
290 | return error; | ||
291 | } | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static void tc3589x_keypad_close(struct input_dev *input) | ||
297 | { | ||
298 | struct tc_keypad *keypad = input_get_drvdata(input); | ||
299 | |||
300 | /* disable the keypad module */ | ||
301 | tc3589x_keypad_disable(keypad); | ||
302 | } | ||
303 | |||
304 | static int __devinit tc3589x_keypad_probe(struct platform_device *pdev) | ||
305 | { | ||
306 | struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); | ||
307 | struct tc_keypad *keypad; | ||
308 | struct input_dev *input; | ||
309 | const struct tc3589x_keypad_platform_data *plat; | ||
310 | int error, irq; | ||
311 | |||
312 | plat = tc3589x->pdata->keypad; | ||
313 | if (!plat) { | ||
314 | dev_err(&pdev->dev, "invalid keypad platform data\n"); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | irq = platform_get_irq(pdev, 0); | ||
319 | if (irq < 0) | ||
320 | return irq; | ||
321 | |||
322 | keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL); | ||
323 | input = input_allocate_device(); | ||
324 | if (!keypad || !input) { | ||
325 | dev_err(&pdev->dev, "failed to allocate keypad memory\n"); | ||
326 | error = -ENOMEM; | ||
327 | goto err_free_mem; | ||
328 | } | ||
329 | |||
330 | keypad->board = plat; | ||
331 | keypad->input = input; | ||
332 | keypad->tc3589x = tc3589x; | ||
333 | |||
334 | input->id.bustype = BUS_I2C; | ||
335 | input->name = pdev->name; | ||
336 | input->dev.parent = &pdev->dev; | ||
337 | |||
338 | input->keycode = keypad->keymap; | ||
339 | input->keycodesize = sizeof(keypad->keymap[0]); | ||
340 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
341 | |||
342 | input->open = tc3589x_keypad_open; | ||
343 | input->close = tc3589x_keypad_close; | ||
344 | |||
345 | input_set_drvdata(input, keypad); | ||
346 | |||
347 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
348 | |||
349 | __set_bit(EV_KEY, input->evbit); | ||
350 | if (!plat->no_autorepeat) | ||
351 | __set_bit(EV_REP, input->evbit); | ||
352 | |||
353 | matrix_keypad_build_keymap(plat->keymap_data, 0x3, | ||
354 | input->keycode, input->keybit); | ||
355 | |||
356 | error = request_threaded_irq(irq, NULL, | ||
357 | tc3589x_keypad_irq, plat->irqtype, | ||
358 | "tc3589x-keypad", keypad); | ||
359 | if (error < 0) { | ||
360 | dev_err(&pdev->dev, | ||
361 | "Could not allocate irq %d,error %d\n", | ||
362 | irq, error); | ||
363 | goto err_free_mem; | ||
364 | } | ||
365 | |||
366 | error = input_register_device(input); | ||
367 | if (error) { | ||
368 | dev_err(&pdev->dev, "Could not register input device\n"); | ||
369 | goto err_free_irq; | ||
370 | } | ||
371 | |||
372 | /* let platform decide if keypad is a wakeup source or not */ | ||
373 | device_init_wakeup(&pdev->dev, plat->enable_wakeup); | ||
374 | device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup); | ||
375 | |||
376 | platform_set_drvdata(pdev, keypad); | ||
377 | |||
378 | return 0; | ||
379 | |||
380 | err_free_irq: | ||
381 | free_irq(irq, keypad); | ||
382 | err_free_mem: | ||
383 | input_free_device(input); | ||
384 | kfree(keypad); | ||
385 | return error; | ||
386 | } | ||
387 | |||
388 | static int __devexit tc3589x_keypad_remove(struct platform_device *pdev) | ||
389 | { | ||
390 | struct tc_keypad *keypad = platform_get_drvdata(pdev); | ||
391 | int irq = platform_get_irq(pdev, 0); | ||
392 | |||
393 | if (!keypad->keypad_stopped) | ||
394 | tc3589x_keypad_disable(keypad); | ||
395 | |||
396 | free_irq(irq, keypad); | ||
397 | |||
398 | input_unregister_device(keypad->input); | ||
399 | |||
400 | kfree(keypad); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | #ifdef CONFIG_PM | ||
406 | static int tc3589x_keypad_suspend(struct device *dev) | ||
407 | { | ||
408 | struct platform_device *pdev = to_platform_device(dev); | ||
409 | struct tc_keypad *keypad = platform_get_drvdata(pdev); | ||
410 | int irq = platform_get_irq(pdev, 0); | ||
411 | |||
412 | /* keypad is already off; we do nothing */ | ||
413 | if (keypad->keypad_stopped) | ||
414 | return 0; | ||
415 | |||
416 | /* if device is not a wakeup source, disable it for powersave */ | ||
417 | if (!device_may_wakeup(&pdev->dev)) | ||
418 | tc3589x_keypad_disable(keypad); | ||
419 | else | ||
420 | enable_irq_wake(irq); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int tc3589x_keypad_resume(struct device *dev) | ||
426 | { | ||
427 | struct platform_device *pdev = to_platform_device(dev); | ||
428 | struct tc_keypad *keypad = platform_get_drvdata(pdev); | ||
429 | int irq = platform_get_irq(pdev, 0); | ||
430 | |||
431 | if (!keypad->keypad_stopped) | ||
432 | return 0; | ||
433 | |||
434 | /* enable the device to resume normal operations */ | ||
435 | if (!device_may_wakeup(&pdev->dev)) | ||
436 | tc3589x_keypad_enable(keypad); | ||
437 | else | ||
438 | disable_irq_wake(irq); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, | ||
444 | tc3589x_keypad_suspend, tc3589x_keypad_resume); | ||
445 | #endif | ||
446 | |||
447 | static struct platform_driver tc3589x_keypad_driver = { | ||
448 | .driver.name = "tc3589x-keypad", | ||
449 | .driver.owner = THIS_MODULE, | ||
450 | #ifdef CONFIG_PM | ||
451 | .driver.pm = &tc3589x_keypad_dev_pm_ops, | ||
452 | #endif | ||
453 | .probe = tc3589x_keypad_probe, | ||
454 | .remove = __devexit_p(tc3589x_keypad_remove), | ||
455 | }; | ||
456 | |||
457 | static int __init tc3589x_keypad_init(void) | ||
458 | { | ||
459 | return platform_driver_register(&tc3589x_keypad_driver); | ||
460 | } | ||
461 | module_init(tc3589x_keypad_init); | ||
462 | |||
463 | static void __exit tc3589x_keypad_exit(void) | ||
464 | { | ||
465 | return platform_driver_unregister(&tc3589x_keypad_driver); | ||
466 | } | ||
467 | module_exit(tc3589x_keypad_exit); | ||
468 | |||
469 | MODULE_LICENSE("GPL v2"); | ||
470 | MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer"); | ||
471 | MODULE_DESCRIPTION("TC35893 Keypad Driver"); | ||
472 | MODULE_ALIAS("platform:tc3589x-keypad") | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3a1493b8b5e5..e8e704f52746 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -218,12 +218,12 @@ config MFD_STMPE | |||
218 | Keypad: stmpe-keypad | 218 | Keypad: stmpe-keypad |
219 | Touchscreen: stmpe-ts | 219 | Touchscreen: stmpe-ts |
220 | 220 | ||
221 | config MFD_TC35892 | 221 | config MFD_TC3589X |
222 | bool "Support Toshiba TC35892" | 222 | bool "Support Toshiba TC35892 and variants" |
223 | depends on I2C=y && GENERIC_HARDIRQS | 223 | depends on I2C=y && GENERIC_HARDIRQS |
224 | select MFD_CORE | 224 | select MFD_CORE |
225 | help | 225 | help |
226 | Support for the Toshiba TC35892 I/O Expander. | 226 | Support for the Toshiba TC35892 and variants I/O Expander. |
227 | 227 | ||
228 | This driver provides common support for accessing the device, | 228 | This driver provides common support for accessing the device, |
229 | additional drivers must be enabled in order to use the | 229 | additional drivers must be enabled in order to use the |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f54b3659abbb..e590d1e44cf0 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -16,7 +16,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o | |||
16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o | 16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o |
17 | 17 | ||
18 | obj-$(CONFIG_MFD_STMPE) += stmpe.o | 18 | obj-$(CONFIG_MFD_STMPE) += stmpe.o |
19 | obj-$(CONFIG_MFD_TC35892) += tc35892.o | 19 | obj-$(CONFIG_MFD_TC3589X) += tc3589x.o |
20 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o | 20 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o |
21 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o | 21 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o |
22 | obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o | 22 | obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o |
diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c deleted file mode 100644 index e619e2a55997..000000000000 --- a/drivers/mfd/tc35892.c +++ /dev/null | |||
@@ -1,345 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson | ||
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mfd/core.h> | ||
15 | #include <linux/mfd/tc35892.h> | ||
16 | |||
17 | /** | ||
18 | * tc35892_reg_read() - read a single TC35892 register | ||
19 | * @tc35892: Device to read from | ||
20 | * @reg: Register to read | ||
21 | */ | ||
22 | int tc35892_reg_read(struct tc35892 *tc35892, u8 reg) | ||
23 | { | ||
24 | int ret; | ||
25 | |||
26 | ret = i2c_smbus_read_byte_data(tc35892->i2c, reg); | ||
27 | if (ret < 0) | ||
28 | dev_err(tc35892->dev, "failed to read reg %#x: %d\n", | ||
29 | reg, ret); | ||
30 | |||
31 | return ret; | ||
32 | } | ||
33 | EXPORT_SYMBOL_GPL(tc35892_reg_read); | ||
34 | |||
35 | /** | ||
36 | * tc35892_reg_read() - write a single TC35892 register | ||
37 | * @tc35892: Device to write to | ||
38 | * @reg: Register to read | ||
39 | * @data: Value to write | ||
40 | */ | ||
41 | int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data) | ||
42 | { | ||
43 | int ret; | ||
44 | |||
45 | ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data); | ||
46 | if (ret < 0) | ||
47 | dev_err(tc35892->dev, "failed to write reg %#x: %d\n", | ||
48 | reg, ret); | ||
49 | |||
50 | return ret; | ||
51 | } | ||
52 | EXPORT_SYMBOL_GPL(tc35892_reg_write); | ||
53 | |||
54 | /** | ||
55 | * tc35892_block_read() - read multiple TC35892 registers | ||
56 | * @tc35892: Device to read from | ||
57 | * @reg: First register | ||
58 | * @length: Number of registers | ||
59 | * @values: Buffer to write to | ||
60 | */ | ||
61 | int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values); | ||
66 | if (ret < 0) | ||
67 | dev_err(tc35892->dev, "failed to read regs %#x: %d\n", | ||
68 | reg, ret); | ||
69 | |||
70 | return ret; | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(tc35892_block_read); | ||
73 | |||
74 | /** | ||
75 | * tc35892_block_write() - write multiple TC35892 registers | ||
76 | * @tc35892: Device to write to | ||
77 | * @reg: First register | ||
78 | * @length: Number of registers | ||
79 | * @values: Values to write | ||
80 | */ | ||
81 | int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, | ||
82 | const u8 *values) | ||
83 | { | ||
84 | int ret; | ||
85 | |||
86 | ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length, | ||
87 | values); | ||
88 | if (ret < 0) | ||
89 | dev_err(tc35892->dev, "failed to write regs %#x: %d\n", | ||
90 | reg, ret); | ||
91 | |||
92 | return ret; | ||
93 | } | ||
94 | EXPORT_SYMBOL_GPL(tc35892_block_write); | ||
95 | |||
96 | /** | ||
97 | * tc35892_set_bits() - set the value of a bitfield in a TC35892 register | ||
98 | * @tc35892: Device to write to | ||
99 | * @reg: Register to write | ||
100 | * @mask: Mask of bits to set | ||
101 | * @values: Value to set | ||
102 | */ | ||
103 | int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val) | ||
104 | { | ||
105 | int ret; | ||
106 | |||
107 | mutex_lock(&tc35892->lock); | ||
108 | |||
109 | ret = tc35892_reg_read(tc35892, reg); | ||
110 | if (ret < 0) | ||
111 | goto out; | ||
112 | |||
113 | ret &= ~mask; | ||
114 | ret |= val; | ||
115 | |||
116 | ret = tc35892_reg_write(tc35892, reg, ret); | ||
117 | |||
118 | out: | ||
119 | mutex_unlock(&tc35892->lock); | ||
120 | return ret; | ||
121 | } | ||
122 | EXPORT_SYMBOL_GPL(tc35892_set_bits); | ||
123 | |||
124 | static struct resource gpio_resources[] = { | ||
125 | { | ||
126 | .start = TC35892_INT_GPIIRQ, | ||
127 | .end = TC35892_INT_GPIIRQ, | ||
128 | .flags = IORESOURCE_IRQ, | ||
129 | }, | ||
130 | }; | ||
131 | |||
132 | static struct mfd_cell tc35892_devs[] = { | ||
133 | { | ||
134 | .name = "tc35892-gpio", | ||
135 | .num_resources = ARRAY_SIZE(gpio_resources), | ||
136 | .resources = &gpio_resources[0], | ||
137 | }, | ||
138 | }; | ||
139 | |||
140 | static irqreturn_t tc35892_irq(int irq, void *data) | ||
141 | { | ||
142 | struct tc35892 *tc35892 = data; | ||
143 | int status; | ||
144 | |||
145 | status = tc35892_reg_read(tc35892, TC35892_IRQST); | ||
146 | if (status < 0) | ||
147 | return IRQ_NONE; | ||
148 | |||
149 | while (status) { | ||
150 | int bit = __ffs(status); | ||
151 | |||
152 | handle_nested_irq(tc35892->irq_base + bit); | ||
153 | status &= ~(1 << bit); | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * A dummy read or write (to any register) appears to be necessary to | ||
158 | * have the last interrupt clear (for example, GPIO IC write) take | ||
159 | * effect. | ||
160 | */ | ||
161 | tc35892_reg_read(tc35892, TC35892_IRQST); | ||
162 | |||
163 | return IRQ_HANDLED; | ||
164 | } | ||
165 | |||
166 | static void tc35892_irq_dummy(unsigned int irq) | ||
167 | { | ||
168 | /* No mask/unmask at this level */ | ||
169 | } | ||
170 | |||
171 | static struct irq_chip tc35892_irq_chip = { | ||
172 | .name = "tc35892", | ||
173 | .mask = tc35892_irq_dummy, | ||
174 | .unmask = tc35892_irq_dummy, | ||
175 | }; | ||
176 | |||
177 | static int tc35892_irq_init(struct tc35892 *tc35892) | ||
178 | { | ||
179 | int base = tc35892->irq_base; | ||
180 | int irq; | ||
181 | |||
182 | for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { | ||
183 | set_irq_chip_data(irq, tc35892); | ||
184 | set_irq_chip_and_handler(irq, &tc35892_irq_chip, | ||
185 | handle_edge_irq); | ||
186 | set_irq_nested_thread(irq, 1); | ||
187 | #ifdef CONFIG_ARM | ||
188 | set_irq_flags(irq, IRQF_VALID); | ||
189 | #else | ||
190 | set_irq_noprobe(irq); | ||
191 | #endif | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static void tc35892_irq_remove(struct tc35892 *tc35892) | ||
198 | { | ||
199 | int base = tc35892->irq_base; | ||
200 | int irq; | ||
201 | |||
202 | for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { | ||
203 | #ifdef CONFIG_ARM | ||
204 | set_irq_flags(irq, 0); | ||
205 | #endif | ||
206 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
207 | set_irq_chip_data(irq, NULL); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static int tc35892_chip_init(struct tc35892 *tc35892) | ||
212 | { | ||
213 | int manf, ver, ret; | ||
214 | |||
215 | manf = tc35892_reg_read(tc35892, TC35892_MANFCODE); | ||
216 | if (manf < 0) | ||
217 | return manf; | ||
218 | |||
219 | ver = tc35892_reg_read(tc35892, TC35892_VERSION); | ||
220 | if (ver < 0) | ||
221 | return ver; | ||
222 | |||
223 | if (manf != TC35892_MANFCODE_MAGIC) { | ||
224 | dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf); | ||
225 | return -EINVAL; | ||
226 | } | ||
227 | |||
228 | dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver); | ||
229 | |||
230 | /* Put everything except the IRQ module into reset */ | ||
231 | ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL, | ||
232 | TC35892_RSTCTRL_TIMRST | ||
233 | | TC35892_RSTCTRL_ROTRST | ||
234 | | TC35892_RSTCTRL_KBDRST | ||
235 | | TC35892_RSTCTRL_GPIRST); | ||
236 | if (ret < 0) | ||
237 | return ret; | ||
238 | |||
239 | /* Clear the reset interrupt. */ | ||
240 | return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1); | ||
241 | } | ||
242 | |||
243 | static int __devinit tc35892_probe(struct i2c_client *i2c, | ||
244 | const struct i2c_device_id *id) | ||
245 | { | ||
246 | struct tc35892_platform_data *pdata = i2c->dev.platform_data; | ||
247 | struct tc35892 *tc35892; | ||
248 | int ret; | ||
249 | |||
250 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA | ||
251 | | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
252 | return -EIO; | ||
253 | |||
254 | tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL); | ||
255 | if (!tc35892) | ||
256 | return -ENOMEM; | ||
257 | |||
258 | mutex_init(&tc35892->lock); | ||
259 | |||
260 | tc35892->dev = &i2c->dev; | ||
261 | tc35892->i2c = i2c; | ||
262 | tc35892->pdata = pdata; | ||
263 | tc35892->irq_base = pdata->irq_base; | ||
264 | tc35892->num_gpio = id->driver_data; | ||
265 | |||
266 | i2c_set_clientdata(i2c, tc35892); | ||
267 | |||
268 | ret = tc35892_chip_init(tc35892); | ||
269 | if (ret) | ||
270 | goto out_free; | ||
271 | |||
272 | ret = tc35892_irq_init(tc35892); | ||
273 | if (ret) | ||
274 | goto out_free; | ||
275 | |||
276 | ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq, | ||
277 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
278 | "tc35892", tc35892); | ||
279 | if (ret) { | ||
280 | dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret); | ||
281 | goto out_removeirq; | ||
282 | } | ||
283 | |||
284 | ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs, | ||
285 | ARRAY_SIZE(tc35892_devs), NULL, | ||
286 | tc35892->irq_base); | ||
287 | if (ret) { | ||
288 | dev_err(tc35892->dev, "failed to add children\n"); | ||
289 | goto out_freeirq; | ||
290 | } | ||
291 | |||
292 | return 0; | ||
293 | |||
294 | out_freeirq: | ||
295 | free_irq(tc35892->i2c->irq, tc35892); | ||
296 | out_removeirq: | ||
297 | tc35892_irq_remove(tc35892); | ||
298 | out_free: | ||
299 | kfree(tc35892); | ||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | static int __devexit tc35892_remove(struct i2c_client *client) | ||
304 | { | ||
305 | struct tc35892 *tc35892 = i2c_get_clientdata(client); | ||
306 | |||
307 | mfd_remove_devices(tc35892->dev); | ||
308 | |||
309 | free_irq(tc35892->i2c->irq, tc35892); | ||
310 | tc35892_irq_remove(tc35892); | ||
311 | |||
312 | kfree(tc35892); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static const struct i2c_device_id tc35892_id[] = { | ||
318 | { "tc35892", 24 }, | ||
319 | { } | ||
320 | }; | ||
321 | MODULE_DEVICE_TABLE(i2c, tc35892_id); | ||
322 | |||
323 | static struct i2c_driver tc35892_driver = { | ||
324 | .driver.name = "tc35892", | ||
325 | .driver.owner = THIS_MODULE, | ||
326 | .probe = tc35892_probe, | ||
327 | .remove = __devexit_p(tc35892_remove), | ||
328 | .id_table = tc35892_id, | ||
329 | }; | ||
330 | |||
331 | static int __init tc35892_init(void) | ||
332 | { | ||
333 | return i2c_add_driver(&tc35892_driver); | ||
334 | } | ||
335 | subsys_initcall(tc35892_init); | ||
336 | |||
337 | static void __exit tc35892_exit(void) | ||
338 | { | ||
339 | i2c_del_driver(&tc35892_driver); | ||
340 | } | ||
341 | module_exit(tc35892_exit); | ||
342 | |||
343 | MODULE_LICENSE("GPL v2"); | ||
344 | MODULE_DESCRIPTION("TC35892 MFD core driver"); | ||
345 | MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); | ||
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c new file mode 100644 index 000000000000..729dbeed2ce0 --- /dev/null +++ b/drivers/mfd/tc3589x.c | |||
@@ -0,0 +1,422 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson | ||
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mfd/core.h> | ||
15 | #include <linux/mfd/tc3589x.h> | ||
16 | |||
17 | #define TC3589x_CLKMODE_MODCTL_SLEEP 0x0 | ||
18 | #define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0) | ||
19 | |||
20 | /** | ||
21 | * tc3589x_reg_read() - read a single TC3589x register | ||
22 | * @tc3589x: Device to read from | ||
23 | * @reg: Register to read | ||
24 | */ | ||
25 | int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg) | ||
26 | { | ||
27 | int ret; | ||
28 | |||
29 | ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg); | ||
30 | if (ret < 0) | ||
31 | dev_err(tc3589x->dev, "failed to read reg %#x: %d\n", | ||
32 | reg, ret); | ||
33 | |||
34 | return ret; | ||
35 | } | ||
36 | EXPORT_SYMBOL_GPL(tc3589x_reg_read); | ||
37 | |||
38 | /** | ||
39 | * tc3589x_reg_read() - write a single TC3589x register | ||
40 | * @tc3589x: Device to write to | ||
41 | * @reg: Register to read | ||
42 | * @data: Value to write | ||
43 | */ | ||
44 | int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data) | ||
45 | { | ||
46 | int ret; | ||
47 | |||
48 | ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data); | ||
49 | if (ret < 0) | ||
50 | dev_err(tc3589x->dev, "failed to write reg %#x: %d\n", | ||
51 | reg, ret); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(tc3589x_reg_write); | ||
56 | |||
57 | /** | ||
58 | * tc3589x_block_read() - read multiple TC3589x registers | ||
59 | * @tc3589x: Device to read from | ||
60 | * @reg: First register | ||
61 | * @length: Number of registers | ||
62 | * @values: Buffer to write to | ||
63 | */ | ||
64 | int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values) | ||
65 | { | ||
66 | int ret; | ||
67 | |||
68 | ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values); | ||
69 | if (ret < 0) | ||
70 | dev_err(tc3589x->dev, "failed to read regs %#x: %d\n", | ||
71 | reg, ret); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(tc3589x_block_read); | ||
76 | |||
77 | /** | ||
78 | * tc3589x_block_write() - write multiple TC3589x registers | ||
79 | * @tc3589x: Device to write to | ||
80 | * @reg: First register | ||
81 | * @length: Number of registers | ||
82 | * @values: Values to write | ||
83 | */ | ||
84 | int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, | ||
85 | const u8 *values) | ||
86 | { | ||
87 | int ret; | ||
88 | |||
89 | ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length, | ||
90 | values); | ||
91 | if (ret < 0) | ||
92 | dev_err(tc3589x->dev, "failed to write regs %#x: %d\n", | ||
93 | reg, ret); | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(tc3589x_block_write); | ||
98 | |||
99 | /** | ||
100 | * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register | ||
101 | * @tc3589x: Device to write to | ||
102 | * @reg: Register to write | ||
103 | * @mask: Mask of bits to set | ||
104 | * @values: Value to set | ||
105 | */ | ||
106 | int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | mutex_lock(&tc3589x->lock); | ||
111 | |||
112 | ret = tc3589x_reg_read(tc3589x, reg); | ||
113 | if (ret < 0) | ||
114 | goto out; | ||
115 | |||
116 | ret &= ~mask; | ||
117 | ret |= val; | ||
118 | |||
119 | ret = tc3589x_reg_write(tc3589x, reg, ret); | ||
120 | |||
121 | out: | ||
122 | mutex_unlock(&tc3589x->lock); | ||
123 | return ret; | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(tc3589x_set_bits); | ||
126 | |||
127 | static struct resource gpio_resources[] = { | ||
128 | { | ||
129 | .start = TC3589x_INT_GPIIRQ, | ||
130 | .end = TC3589x_INT_GPIIRQ, | ||
131 | .flags = IORESOURCE_IRQ, | ||
132 | }, | ||
133 | }; | ||
134 | |||
135 | static struct resource keypad_resources[] = { | ||
136 | { | ||
137 | .start = TC3589x_INT_KBDIRQ, | ||
138 | .end = TC3589x_INT_KBDIRQ, | ||
139 | .flags = IORESOURCE_IRQ, | ||
140 | }, | ||
141 | }; | ||
142 | |||
143 | static struct mfd_cell tc3589x_dev_gpio[] = { | ||
144 | { | ||
145 | .name = "tc3589x-gpio", | ||
146 | .num_resources = ARRAY_SIZE(gpio_resources), | ||
147 | .resources = &gpio_resources[0], | ||
148 | }, | ||
149 | }; | ||
150 | |||
151 | static struct mfd_cell tc3589x_dev_keypad[] = { | ||
152 | { | ||
153 | .name = "tc3589x-keypad", | ||
154 | .num_resources = ARRAY_SIZE(keypad_resources), | ||
155 | .resources = &keypad_resources[0], | ||
156 | }, | ||
157 | }; | ||
158 | |||
159 | static irqreturn_t tc3589x_irq(int irq, void *data) | ||
160 | { | ||
161 | struct tc3589x *tc3589x = data; | ||
162 | int status; | ||
163 | |||
164 | again: | ||
165 | status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); | ||
166 | if (status < 0) | ||
167 | return IRQ_NONE; | ||
168 | |||
169 | while (status) { | ||
170 | int bit = __ffs(status); | ||
171 | |||
172 | handle_nested_irq(tc3589x->irq_base + bit); | ||
173 | status &= ~(1 << bit); | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * A dummy read or write (to any register) appears to be necessary to | ||
178 | * have the last interrupt clear (for example, GPIO IC write) take | ||
179 | * effect. In such a case, recheck for any interrupt which is still | ||
180 | * pending. | ||
181 | */ | ||
182 | status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); | ||
183 | if (status) | ||
184 | goto again; | ||
185 | |||
186 | return IRQ_HANDLED; | ||
187 | } | ||
188 | |||
189 | static int tc3589x_irq_init(struct tc3589x *tc3589x) | ||
190 | { | ||
191 | int base = tc3589x->irq_base; | ||
192 | int irq; | ||
193 | |||
194 | for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { | ||
195 | set_irq_chip_data(irq, tc3589x); | ||
196 | set_irq_chip_and_handler(irq, &dummy_irq_chip, | ||
197 | handle_edge_irq); | ||
198 | set_irq_nested_thread(irq, 1); | ||
199 | #ifdef CONFIG_ARM | ||
200 | set_irq_flags(irq, IRQF_VALID); | ||
201 | #else | ||
202 | set_irq_noprobe(irq); | ||
203 | #endif | ||
204 | } | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static void tc3589x_irq_remove(struct tc3589x *tc3589x) | ||
210 | { | ||
211 | int base = tc3589x->irq_base; | ||
212 | int irq; | ||
213 | |||
214 | for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { | ||
215 | #ifdef CONFIG_ARM | ||
216 | set_irq_flags(irq, 0); | ||
217 | #endif | ||
218 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
219 | set_irq_chip_data(irq, NULL); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static int tc3589x_chip_init(struct tc3589x *tc3589x) | ||
224 | { | ||
225 | int manf, ver, ret; | ||
226 | |||
227 | manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE); | ||
228 | if (manf < 0) | ||
229 | return manf; | ||
230 | |||
231 | ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION); | ||
232 | if (ver < 0) | ||
233 | return ver; | ||
234 | |||
235 | if (manf != TC3589x_MANFCODE_MAGIC) { | ||
236 | dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf); | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); | ||
241 | |||
242 | /* | ||
243 | * Put everything except the IRQ module into reset; | ||
244 | * also spare the GPIO module for any pin initialization | ||
245 | * done during pre-kernel boot | ||
246 | */ | ||
247 | ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, | ||
248 | TC3589x_RSTCTRL_TIMRST | ||
249 | | TC3589x_RSTCTRL_ROTRST | ||
250 | | TC3589x_RSTCTRL_KBDRST); | ||
251 | if (ret < 0) | ||
252 | return ret; | ||
253 | |||
254 | /* Clear the reset interrupt. */ | ||
255 | return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); | ||
256 | } | ||
257 | |||
258 | static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) | ||
259 | { | ||
260 | int ret = 0; | ||
261 | unsigned int blocks = tc3589x->pdata->block; | ||
262 | |||
263 | if (blocks & TC3589x_BLOCK_GPIO) { | ||
264 | ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, | ||
265 | ARRAY_SIZE(tc3589x_dev_gpio), NULL, | ||
266 | tc3589x->irq_base); | ||
267 | if (ret) { | ||
268 | dev_err(tc3589x->dev, "failed to add gpio child\n"); | ||
269 | return ret; | ||
270 | } | ||
271 | dev_info(tc3589x->dev, "added gpio block\n"); | ||
272 | } | ||
273 | |||
274 | if (blocks & TC3589x_BLOCK_KEYPAD) { | ||
275 | ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, | ||
276 | ARRAY_SIZE(tc3589x_dev_keypad), NULL, | ||
277 | tc3589x->irq_base); | ||
278 | if (ret) { | ||
279 | dev_err(tc3589x->dev, "failed to keypad child\n"); | ||
280 | return ret; | ||
281 | } | ||
282 | dev_info(tc3589x->dev, "added keypad block\n"); | ||
283 | } | ||
284 | |||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | static int __devinit tc3589x_probe(struct i2c_client *i2c, | ||
289 | const struct i2c_device_id *id) | ||
290 | { | ||
291 | struct tc3589x_platform_data *pdata = i2c->dev.platform_data; | ||
292 | struct tc3589x *tc3589x; | ||
293 | int ret; | ||
294 | |||
295 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA | ||
296 | | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
297 | return -EIO; | ||
298 | |||
299 | tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL); | ||
300 | if (!tc3589x) | ||
301 | return -ENOMEM; | ||
302 | |||
303 | mutex_init(&tc3589x->lock); | ||
304 | |||
305 | tc3589x->dev = &i2c->dev; | ||
306 | tc3589x->i2c = i2c; | ||
307 | tc3589x->pdata = pdata; | ||
308 | tc3589x->irq_base = pdata->irq_base; | ||
309 | tc3589x->num_gpio = id->driver_data; | ||
310 | |||
311 | i2c_set_clientdata(i2c, tc3589x); | ||
312 | |||
313 | ret = tc3589x_chip_init(tc3589x); | ||
314 | if (ret) | ||
315 | goto out_free; | ||
316 | |||
317 | ret = tc3589x_irq_init(tc3589x); | ||
318 | if (ret) | ||
319 | goto out_free; | ||
320 | |||
321 | ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq, | ||
322 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
323 | "tc3589x", tc3589x); | ||
324 | if (ret) { | ||
325 | dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret); | ||
326 | goto out_removeirq; | ||
327 | } | ||
328 | |||
329 | ret = tc3589x_device_init(tc3589x); | ||
330 | if (ret) { | ||
331 | dev_err(tc3589x->dev, "failed to add child devices\n"); | ||
332 | goto out_freeirq; | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | |||
337 | out_freeirq: | ||
338 | free_irq(tc3589x->i2c->irq, tc3589x); | ||
339 | out_removeirq: | ||
340 | tc3589x_irq_remove(tc3589x); | ||
341 | out_free: | ||
342 | kfree(tc3589x); | ||
343 | return ret; | ||
344 | } | ||
345 | |||
346 | static int __devexit tc3589x_remove(struct i2c_client *client) | ||
347 | { | ||
348 | struct tc3589x *tc3589x = i2c_get_clientdata(client); | ||
349 | |||
350 | mfd_remove_devices(tc3589x->dev); | ||
351 | |||
352 | free_irq(tc3589x->i2c->irq, tc3589x); | ||
353 | tc3589x_irq_remove(tc3589x); | ||
354 | |||
355 | kfree(tc3589x); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int tc3589x_suspend(struct device *dev) | ||
361 | { | ||
362 | struct tc3589x *tc3589x = dev_get_drvdata(dev); | ||
363 | struct i2c_client *client = tc3589x->i2c; | ||
364 | int ret = 0; | ||
365 | |||
366 | /* put the system to sleep mode */ | ||
367 | if (!device_may_wakeup(&client->dev)) | ||
368 | ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, | ||
369 | TC3589x_CLKMODE_MODCTL_SLEEP); | ||
370 | |||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | static int tc3589x_resume(struct device *dev) | ||
375 | { | ||
376 | struct tc3589x *tc3589x = dev_get_drvdata(dev); | ||
377 | struct i2c_client *client = tc3589x->i2c; | ||
378 | int ret = 0; | ||
379 | |||
380 | /* enable the system into operation */ | ||
381 | if (!device_may_wakeup(&client->dev)) | ||
382 | ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, | ||
383 | TC3589x_CLKMODE_MODCTL_OPERATION); | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, | ||
389 | tc3589x_resume); | ||
390 | |||
391 | static const struct i2c_device_id tc3589x_id[] = { | ||
392 | { "tc3589x", 24 }, | ||
393 | { } | ||
394 | }; | ||
395 | MODULE_DEVICE_TABLE(i2c, tc3589x_id); | ||
396 | |||
397 | static struct i2c_driver tc3589x_driver = { | ||
398 | .driver.name = "tc3589x", | ||
399 | .driver.owner = THIS_MODULE, | ||
400 | #ifdef CONFIG_PM | ||
401 | .driver.pm = &tc3589x_dev_pm_ops, | ||
402 | #endif | ||
403 | .probe = tc3589x_probe, | ||
404 | .remove = __devexit_p(tc3589x_remove), | ||
405 | .id_table = tc3589x_id, | ||
406 | }; | ||
407 | |||
408 | static int __init tc3589x_init(void) | ||
409 | { | ||
410 | return i2c_add_driver(&tc3589x_driver); | ||
411 | } | ||
412 | subsys_initcall(tc3589x_init); | ||
413 | |||
414 | static void __exit tc3589x_exit(void) | ||
415 | { | ||
416 | i2c_del_driver(&tc3589x_driver); | ||
417 | } | ||
418 | module_exit(tc3589x_exit); | ||
419 | |||
420 | MODULE_LICENSE("GPL v2"); | ||
421 | MODULE_DESCRIPTION("TC3589x MFD core driver"); | ||
422 | MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); | ||
diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c index 32b1c6fb2de1..5f771ab712c4 100644 --- a/drivers/net/caif/caif_shm_u5500.c +++ b/drivers/net/caif/caif_shm_u5500.c | |||
@@ -11,7 +11,7 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
14 | #include <mach/mbox.h> | 14 | #include <mach/mbox-db5500.h> |
15 | #include <net/caif/caif_shm.h> | 15 | #include <net/caif/caif_shm.h> |
16 | 16 | ||
17 | MODULE_LICENSE("GPL"); | 17 | MODULE_LICENSE("GPL"); |
diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h deleted file mode 100644 index eff3094ca84e..000000000000 --- a/include/linux/mfd/tc35892.h +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | */ | ||
6 | |||
7 | #ifndef __LINUX_MFD_TC35892_H | ||
8 | #define __LINUX_MFD_TC35892_H | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | |||
12 | #define TC35892_RSTCTRL_IRQRST (1 << 4) | ||
13 | #define TC35892_RSTCTRL_TIMRST (1 << 3) | ||
14 | #define TC35892_RSTCTRL_ROTRST (1 << 2) | ||
15 | #define TC35892_RSTCTRL_KBDRST (1 << 1) | ||
16 | #define TC35892_RSTCTRL_GPIRST (1 << 0) | ||
17 | |||
18 | #define TC35892_IRQST 0x91 | ||
19 | |||
20 | #define TC35892_MANFCODE_MAGIC 0x03 | ||
21 | #define TC35892_MANFCODE 0x80 | ||
22 | #define TC35892_VERSION 0x81 | ||
23 | #define TC35892_IOCFG 0xA7 | ||
24 | |||
25 | #define TC35892_CLKMODE 0x88 | ||
26 | #define TC35892_CLKCFG 0x89 | ||
27 | #define TC35892_CLKEN 0x8A | ||
28 | |||
29 | #define TC35892_RSTCTRL 0x82 | ||
30 | #define TC35892_EXTRSTN 0x83 | ||
31 | #define TC35892_RSTINTCLR 0x84 | ||
32 | |||
33 | #define TC35892_GPIOIS0 0xC9 | ||
34 | #define TC35892_GPIOIS1 0xCA | ||
35 | #define TC35892_GPIOIS2 0xCB | ||
36 | #define TC35892_GPIOIBE0 0xCC | ||
37 | #define TC35892_GPIOIBE1 0xCD | ||
38 | #define TC35892_GPIOIBE2 0xCE | ||
39 | #define TC35892_GPIOIEV0 0xCF | ||
40 | #define TC35892_GPIOIEV1 0xD0 | ||
41 | #define TC35892_GPIOIEV2 0xD1 | ||
42 | #define TC35892_GPIOIE0 0xD2 | ||
43 | #define TC35892_GPIOIE1 0xD3 | ||
44 | #define TC35892_GPIOIE2 0xD4 | ||
45 | #define TC35892_GPIORIS0 0xD6 | ||
46 | #define TC35892_GPIORIS1 0xD7 | ||
47 | #define TC35892_GPIORIS2 0xD8 | ||
48 | #define TC35892_GPIOMIS0 0xD9 | ||
49 | #define TC35892_GPIOMIS1 0xDA | ||
50 | #define TC35892_GPIOMIS2 0xDB | ||
51 | #define TC35892_GPIOIC0 0xDC | ||
52 | #define TC35892_GPIOIC1 0xDD | ||
53 | #define TC35892_GPIOIC2 0xDE | ||
54 | |||
55 | #define TC35892_GPIODATA0 0xC0 | ||
56 | #define TC35892_GPIOMASK0 0xc1 | ||
57 | #define TC35892_GPIODATA1 0xC2 | ||
58 | #define TC35892_GPIOMASK1 0xc3 | ||
59 | #define TC35892_GPIODATA2 0xC4 | ||
60 | #define TC35892_GPIOMASK2 0xC5 | ||
61 | |||
62 | #define TC35892_GPIODIR0 0xC6 | ||
63 | #define TC35892_GPIODIR1 0xC7 | ||
64 | #define TC35892_GPIODIR2 0xC8 | ||
65 | |||
66 | #define TC35892_GPIOSYNC0 0xE6 | ||
67 | #define TC35892_GPIOSYNC1 0xE7 | ||
68 | #define TC35892_GPIOSYNC2 0xE8 | ||
69 | |||
70 | #define TC35892_GPIOWAKE0 0xE9 | ||
71 | #define TC35892_GPIOWAKE1 0xEA | ||
72 | #define TC35892_GPIOWAKE2 0xEB | ||
73 | |||
74 | #define TC35892_GPIOODM0 0xE0 | ||
75 | #define TC35892_GPIOODE0 0xE1 | ||
76 | #define TC35892_GPIOODM1 0xE2 | ||
77 | #define TC35892_GPIOODE1 0xE3 | ||
78 | #define TC35892_GPIOODM2 0xE4 | ||
79 | #define TC35892_GPIOODE2 0xE5 | ||
80 | |||
81 | #define TC35892_INT_GPIIRQ 0 | ||
82 | #define TC35892_INT_TI0IRQ 1 | ||
83 | #define TC35892_INT_TI1IRQ 2 | ||
84 | #define TC35892_INT_TI2IRQ 3 | ||
85 | #define TC35892_INT_ROTIRQ 5 | ||
86 | #define TC35892_INT_KBDIRQ 6 | ||
87 | #define TC35892_INT_PORIRQ 7 | ||
88 | |||
89 | #define TC35892_NR_INTERNAL_IRQS 8 | ||
90 | #define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x)) | ||
91 | |||
92 | struct tc35892 { | ||
93 | struct mutex lock; | ||
94 | struct device *dev; | ||
95 | struct i2c_client *i2c; | ||
96 | |||
97 | int irq_base; | ||
98 | int num_gpio; | ||
99 | struct tc35892_platform_data *pdata; | ||
100 | }; | ||
101 | |||
102 | extern int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data); | ||
103 | extern int tc35892_reg_read(struct tc35892 *tc35892, u8 reg); | ||
104 | extern int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, | ||
105 | u8 *values); | ||
106 | extern int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, | ||
107 | const u8 *values); | ||
108 | extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val); | ||
109 | |||
110 | /** | ||
111 | * struct tc35892_gpio_platform_data - TC35892 GPIO platform data | ||
112 | * @gpio_base: first gpio number assigned to TC35892. A maximum of | ||
113 | * %TC35892_NR_GPIOS GPIOs will be allocated. | ||
114 | * @setup: callback for board-specific initialization | ||
115 | * @remove: callback for board-specific teardown | ||
116 | */ | ||
117 | struct tc35892_gpio_platform_data { | ||
118 | int gpio_base; | ||
119 | void (*setup)(struct tc35892 *tc35892, unsigned gpio_base); | ||
120 | void (*remove)(struct tc35892 *tc35892, unsigned gpio_base); | ||
121 | }; | ||
122 | |||
123 | /** | ||
124 | * struct tc35892_platform_data - TC35892 platform data | ||
125 | * @irq_base: base IRQ number. %TC35892_NR_IRQS irqs will be used. | ||
126 | * @gpio: GPIO-specific platform data | ||
127 | */ | ||
128 | struct tc35892_platform_data { | ||
129 | int irq_base; | ||
130 | struct tc35892_gpio_platform_data *gpio; | ||
131 | }; | ||
132 | |||
133 | #define TC35892_NR_GPIOS 24 | ||
134 | #define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS) | ||
135 | |||
136 | #endif | ||
diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h new file mode 100644 index 000000000000..16c76e124f9c --- /dev/null +++ b/include/linux/mfd/tc3589x.h | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | */ | ||
6 | |||
7 | #ifndef __LINUX_MFD_TC3589x_H | ||
8 | #define __LINUX_MFD_TC3589x_H | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | |||
12 | enum tx3589x_block { | ||
13 | TC3589x_BLOCK_GPIO = 1 << 0, | ||
14 | TC3589x_BLOCK_KEYPAD = 1 << 1, | ||
15 | }; | ||
16 | |||
17 | #define TC3589x_RSTCTRL_IRQRST (1 << 4) | ||
18 | #define TC3589x_RSTCTRL_TIMRST (1 << 3) | ||
19 | #define TC3589x_RSTCTRL_ROTRST (1 << 2) | ||
20 | #define TC3589x_RSTCTRL_KBDRST (1 << 1) | ||
21 | #define TC3589x_RSTCTRL_GPIRST (1 << 0) | ||
22 | |||
23 | /* Keyboard Configuration Registers */ | ||
24 | #define TC3589x_KBDSETTLE_REG 0x01 | ||
25 | #define TC3589x_KBDBOUNCE 0x02 | ||
26 | #define TC3589x_KBDSIZE 0x03 | ||
27 | #define TC3589x_KBCFG_LSB 0x04 | ||
28 | #define TC3589x_KBCFG_MSB 0x05 | ||
29 | #define TC3589x_KBDIC 0x08 | ||
30 | #define TC3589x_KBDMSK 0x09 | ||
31 | #define TC3589x_EVTCODE_FIFO 0x10 | ||
32 | #define TC3589x_KBDMFS 0x8F | ||
33 | |||
34 | #define TC3589x_IRQST 0x91 | ||
35 | |||
36 | #define TC3589x_MANFCODE_MAGIC 0x03 | ||
37 | #define TC3589x_MANFCODE 0x80 | ||
38 | #define TC3589x_VERSION 0x81 | ||
39 | #define TC3589x_IOCFG 0xA7 | ||
40 | |||
41 | #define TC3589x_CLKMODE 0x88 | ||
42 | #define TC3589x_CLKCFG 0x89 | ||
43 | #define TC3589x_CLKEN 0x8A | ||
44 | |||
45 | #define TC3589x_RSTCTRL 0x82 | ||
46 | #define TC3589x_EXTRSTN 0x83 | ||
47 | #define TC3589x_RSTINTCLR 0x84 | ||
48 | |||
49 | /* Pull up/down configuration registers */ | ||
50 | #define TC3589x_IOCFG 0xA7 | ||
51 | #define TC3589x_IOPULLCFG0_LSB 0xAA | ||
52 | #define TC3589x_IOPULLCFG0_MSB 0xAB | ||
53 | #define TC3589x_IOPULLCFG1_LSB 0xAC | ||
54 | #define TC3589x_IOPULLCFG1_MSB 0xAD | ||
55 | #define TC3589x_IOPULLCFG2_LSB 0xAE | ||
56 | |||
57 | #define TC3589x_GPIOIS0 0xC9 | ||
58 | #define TC3589x_GPIOIS1 0xCA | ||
59 | #define TC3589x_GPIOIS2 0xCB | ||
60 | #define TC3589x_GPIOIBE0 0xCC | ||
61 | #define TC3589x_GPIOIBE1 0xCD | ||
62 | #define TC3589x_GPIOIBE2 0xCE | ||
63 | #define TC3589x_GPIOIEV0 0xCF | ||
64 | #define TC3589x_GPIOIEV1 0xD0 | ||
65 | #define TC3589x_GPIOIEV2 0xD1 | ||
66 | #define TC3589x_GPIOIE0 0xD2 | ||
67 | #define TC3589x_GPIOIE1 0xD3 | ||
68 | #define TC3589x_GPIOIE2 0xD4 | ||
69 | #define TC3589x_GPIORIS0 0xD6 | ||
70 | #define TC3589x_GPIORIS1 0xD7 | ||
71 | #define TC3589x_GPIORIS2 0xD8 | ||
72 | #define TC3589x_GPIOMIS0 0xD9 | ||
73 | #define TC3589x_GPIOMIS1 0xDA | ||
74 | #define TC3589x_GPIOMIS2 0xDB | ||
75 | #define TC3589x_GPIOIC0 0xDC | ||
76 | #define TC3589x_GPIOIC1 0xDD | ||
77 | #define TC3589x_GPIOIC2 0xDE | ||
78 | |||
79 | #define TC3589x_GPIODATA0 0xC0 | ||
80 | #define TC3589x_GPIOMASK0 0xc1 | ||
81 | #define TC3589x_GPIODATA1 0xC2 | ||
82 | #define TC3589x_GPIOMASK1 0xc3 | ||
83 | #define TC3589x_GPIODATA2 0xC4 | ||
84 | #define TC3589x_GPIOMASK2 0xC5 | ||
85 | |||
86 | #define TC3589x_GPIODIR0 0xC6 | ||
87 | #define TC3589x_GPIODIR1 0xC7 | ||
88 | #define TC3589x_GPIODIR2 0xC8 | ||
89 | |||
90 | #define TC3589x_GPIOSYNC0 0xE6 | ||
91 | #define TC3589x_GPIOSYNC1 0xE7 | ||
92 | #define TC3589x_GPIOSYNC2 0xE8 | ||
93 | |||
94 | #define TC3589x_GPIOWAKE0 0xE9 | ||
95 | #define TC3589x_GPIOWAKE1 0xEA | ||
96 | #define TC3589x_GPIOWAKE2 0xEB | ||
97 | |||
98 | #define TC3589x_GPIOODM0 0xE0 | ||
99 | #define TC3589x_GPIOODE0 0xE1 | ||
100 | #define TC3589x_GPIOODM1 0xE2 | ||
101 | #define TC3589x_GPIOODE1 0xE3 | ||
102 | #define TC3589x_GPIOODM2 0xE4 | ||
103 | #define TC3589x_GPIOODE2 0xE5 | ||
104 | |||
105 | #define TC3589x_INT_GPIIRQ 0 | ||
106 | #define TC3589x_INT_TI0IRQ 1 | ||
107 | #define TC3589x_INT_TI1IRQ 2 | ||
108 | #define TC3589x_INT_TI2IRQ 3 | ||
109 | #define TC3589x_INT_ROTIRQ 5 | ||
110 | #define TC3589x_INT_KBDIRQ 6 | ||
111 | #define TC3589x_INT_PORIRQ 7 | ||
112 | |||
113 | #define TC3589x_NR_INTERNAL_IRQS 8 | ||
114 | #define TC3589x_INT_GPIO(x) (TC3589x_NR_INTERNAL_IRQS + (x)) | ||
115 | |||
116 | struct tc3589x { | ||
117 | struct mutex lock; | ||
118 | struct device *dev; | ||
119 | struct i2c_client *i2c; | ||
120 | |||
121 | int irq_base; | ||
122 | int num_gpio; | ||
123 | struct tc3589x_platform_data *pdata; | ||
124 | }; | ||
125 | |||
126 | extern int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data); | ||
127 | extern int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg); | ||
128 | extern int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, | ||
129 | u8 *values); | ||
130 | extern int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, | ||
131 | const u8 *values); | ||
132 | extern int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val); | ||
133 | |||
134 | /* | ||
135 | * Keypad related platform specific constants | ||
136 | * These values may be modified for fine tuning | ||
137 | */ | ||
138 | #define TC_KPD_ROWS 0x8 | ||
139 | #define TC_KPD_COLUMNS 0x8 | ||
140 | #define TC_KPD_DEBOUNCE_PERIOD 0xA3 | ||
141 | #define TC_KPD_SETTLE_TIME 0xA3 | ||
142 | |||
143 | /** | ||
144 | * struct tc35893_platform_data - data structure for platform specific data | ||
145 | * @keymap_data: matrix scan code table for keycodes | ||
146 | * @krow: mask for available rows, value is 0xFF | ||
147 | * @kcol: mask for available columns, value is 0xFF | ||
148 | * @debounce_period: platform specific debounce time | ||
149 | * @settle_time: platform specific settle down time | ||
150 | * @irqtype: type of interrupt, falling or rising edge | ||
151 | * @enable_wakeup: specifies if keypad event can wake up system from sleep | ||
152 | * @no_autorepeat: flag for auto repetition | ||
153 | */ | ||
154 | struct tc3589x_keypad_platform_data { | ||
155 | const struct matrix_keymap_data *keymap_data; | ||
156 | u8 krow; | ||
157 | u8 kcol; | ||
158 | u8 debounce_period; | ||
159 | u8 settle_time; | ||
160 | unsigned long irqtype; | ||
161 | bool enable_wakeup; | ||
162 | bool no_autorepeat; | ||
163 | }; | ||
164 | |||
165 | /** | ||
166 | * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data | ||
167 | * @gpio_base: first gpio number assigned to TC3589x. A maximum of | ||
168 | * %TC3589x_NR_GPIOS GPIOs will be allocated. | ||
169 | * @setup: callback for board-specific initialization | ||
170 | * @remove: callback for board-specific teardown | ||
171 | */ | ||
172 | struct tc3589x_gpio_platform_data { | ||
173 | int gpio_base; | ||
174 | void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base); | ||
175 | void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base); | ||
176 | }; | ||
177 | |||
178 | /** | ||
179 | * struct tc3589x_platform_data - TC3589x platform data | ||
180 | * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*) | ||
181 | * @irq_base: base IRQ number. %TC3589x_NR_IRQS irqs will be used. | ||
182 | * @gpio: GPIO-specific platform data | ||
183 | * @keypad: keypad-specific platform data | ||
184 | */ | ||
185 | struct tc3589x_platform_data { | ||
186 | unsigned int block; | ||
187 | int irq_base; | ||
188 | struct tc3589x_gpio_platform_data *gpio; | ||
189 | const struct tc3589x_keypad_platform_data *keypad; | ||
190 | }; | ||
191 | |||
192 | #define TC3589x_NR_GPIOS 24 | ||
193 | #define TC3589x_NR_IRQS TC3589x_INT_GPIO(TC3589x_NR_GPIOS) | ||
194 | |||
195 | #endif | ||