diff options
Diffstat (limited to 'arch/arm/plat-samsung')
72 files changed, 9740 insertions, 0 deletions
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 486a0d6301e7..d552c65fa1b0 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig | |||
@@ -7,11 +7,240 @@ | |||
7 | config PLAT_SAMSUNG | 7 | config PLAT_SAMSUNG |
8 | bool | 8 | bool |
9 | depends on ARCH_S3C2410 || ARCH_S3C24A0 || ARCH_S3C64XX || ARCH_S5PC1XX | 9 | depends on ARCH_S3C2410 || ARCH_S3C24A0 || ARCH_S3C64XX || ARCH_S5PC1XX |
10 | select NO_IOPORT | ||
10 | default y | 11 | default y |
11 | help | 12 | help |
12 | Base platform code for all Samsung SoC based systems | 13 | Base platform code for all Samsung SoC based systems |
13 | 14 | ||
14 | if PLAT_SAMSUNG | 15 | if PLAT_SAMSUNG |
15 | 16 | ||
17 | # boot configurations | ||
18 | |||
19 | comment "Boot options" | ||
20 | |||
21 | config S3C_BOOT_WATCHDOG | ||
22 | bool "S3C Initialisation watchdog" | ||
23 | depends on S3C2410_WATCHDOG | ||
24 | help | ||
25 | Say y to enable the watchdog during the kernel decompression | ||
26 | stage. If the kernel fails to uncompress, then the watchdog | ||
27 | will trigger a reset and the system should restart. | ||
28 | |||
29 | config S3C_BOOT_ERROR_RESET | ||
30 | bool "S3C Reboot on decompression error" | ||
31 | help | ||
32 | Say y here to use the watchdog to reset the system if the | ||
33 | kernel decompressor detects an error during decompression. | ||
34 | |||
35 | config S3C_BOOT_UART_FORCE_FIFO | ||
36 | bool "Force UART FIFO on during boot process" | ||
37 | default y | ||
38 | help | ||
39 | Say Y here to force the UART FIFOs on during the kernel | ||
40 | uncompressor | ||
41 | |||
42 | |||
43 | config S3C_LOWLEVEL_UART_PORT | ||
44 | int "S3C UART to use for low-level messages" | ||
45 | default 0 | ||
46 | help | ||
47 | Choice of which UART port to use for the low-level messages, | ||
48 | such as the `Uncompressing...` at start time. The value of | ||
49 | this configuration should be between zero and two. The port | ||
50 | must have been initialised by the boot-loader before use. | ||
51 | |||
52 | # clock options | ||
53 | |||
54 | config SAMSUNG_CLKSRC | ||
55 | bool | ||
56 | help | ||
57 | Select the clock code for the clksrc implementation | ||
58 | used by newer systems such as the S3C64XX. | ||
59 | |||
60 | # options for IRQ support | ||
61 | |||
62 | config SAMSUNG_IRQ_VIC_TIMER | ||
63 | bool | ||
64 | help | ||
65 | Internal configuration to build the VIC timer interrupt code. | ||
66 | |||
67 | config SAMSUNG_IRQ_UART | ||
68 | bool | ||
69 | help | ||
70 | Internal configuration to build the IRQ UART demux code. | ||
71 | |||
72 | # options for gpio configuration support | ||
73 | |||
74 | config SAMSUNG_GPIOLIB_4BIT | ||
75 | bool | ||
76 | help | ||
77 | GPIOlib file contains the 4 bit modification functions for gpio | ||
78 | configuration. GPIOlib shall be compiled only for S3C64XX and S5P | ||
79 | series of processors. | ||
80 | |||
81 | config S3C_GPIO_CFG_S3C24XX | ||
82 | bool | ||
83 | help | ||
84 | Internal configuration to enable S3C24XX style GPIO configuration | ||
85 | functions. | ||
86 | |||
87 | config S3C_GPIO_CFG_S3C64XX | ||
88 | bool | ||
89 | help | ||
90 | Internal configuration to enable S3C64XX style GPIO configuration | ||
91 | functions. | ||
92 | |||
93 | config S5P_GPIO_CFG_S5PC1XX | ||
94 | bool | ||
95 | help | ||
96 | Internal configuration to enable S5PC1XX style GPIO configuration | ||
97 | functions. | ||
98 | |||
99 | config S3C_GPIO_PULL_UPDOWN | ||
100 | bool | ||
101 | help | ||
102 | Internal configuration to enable the correct GPIO pull helper | ||
103 | |||
104 | config S3C_GPIO_PULL_DOWN | ||
105 | bool | ||
106 | help | ||
107 | Internal configuration to enable the correct GPIO pull helper | ||
108 | |||
109 | config S3C_GPIO_PULL_UP | ||
110 | bool | ||
111 | help | ||
112 | Internal configuration to enable the correct GPIO pull helper | ||
113 | |||
114 | config SAMSUNG_GPIO_EXTRA | ||
115 | int "Number of additional GPIO pins" | ||
116 | default 0 | ||
117 | help | ||
118 | Use additional GPIO space in addition to the GPIO's the SOC | ||
119 | provides. This allows expanding the GPIO space for use with | ||
120 | GPIO expanders. | ||
121 | |||
122 | config S3C_GPIO_SPACE | ||
123 | int "Space between gpio banks" | ||
124 | default 0 | ||
125 | help | ||
126 | Add a number of spare GPIO entries between each bank for debugging | ||
127 | purposes. This allows any problems where an counter overflows from | ||
128 | one bank to another to be caught, at the expense of using a little | ||
129 | more memory. | ||
130 | |||
131 | config S3C_GPIO_TRACK | ||
132 | bool | ||
133 | help | ||
134 | Internal configuration option to enable the s3c specific gpio | ||
135 | chip tracking if the platform requires it. | ||
136 | |||
137 | # ADC driver | ||
138 | |||
139 | config S3C_ADC | ||
140 | bool "ADC common driver support" | ||
141 | help | ||
142 | Core support for the ADC block found in the Samsung SoC systems | ||
143 | for drivers such as the touchscreen and hwmon to use to share | ||
144 | this resource. | ||
145 | |||
146 | # device definitions to compile in | ||
147 | |||
148 | config S3C_DEV_HSMMC | ||
149 | bool | ||
150 | help | ||
151 | Compile in platform device definitions for HSMMC code | ||
152 | |||
153 | config S3C_DEV_HSMMC1 | ||
154 | bool | ||
155 | help | ||
156 | Compile in platform device definitions for HSMMC channel 1 | ||
157 | |||
158 | config S3C_DEV_HSMMC2 | ||
159 | bool | ||
160 | help | ||
161 | Compile in platform device definitions for HSMMC channel 2 | ||
162 | |||
163 | config S3C_DEV_I2C1 | ||
164 | bool | ||
165 | help | ||
166 | Compile in platform device definitions for I2C channel 1 | ||
167 | |||
168 | config S3C_DEV_FB | ||
169 | bool | ||
170 | help | ||
171 | Compile in platform device definition for framebuffer | ||
172 | |||
173 | config S3C_DEV_USB_HOST | ||
174 | bool | ||
175 | help | ||
176 | Compile in platform device definition for USB host. | ||
177 | |||
178 | config S3C_DEV_USB_HSOTG | ||
179 | bool | ||
180 | help | ||
181 | Compile in platform device definition for USB high-speed OtG | ||
182 | |||
183 | config S3C_DEV_NAND | ||
184 | bool | ||
185 | help | ||
186 | Compile in platform device definition for NAND controller | ||
187 | |||
188 | config S3C64XX_DEV_SPI | ||
189 | bool | ||
190 | help | ||
191 | Compile in platform device definitions for S3C64XX's type | ||
192 | SPI controllers. | ||
193 | |||
194 | # DMA | ||
195 | |||
196 | config S3C_DMA | ||
197 | bool | ||
198 | help | ||
199 | Internal configuration for S3C DMA core | ||
200 | |||
201 | comment "Power management" | ||
202 | |||
203 | config SAMSUNG_PM_DEBUG | ||
204 | bool "S3C2410 PM Suspend debug" | ||
205 | depends on PM | ||
206 | help | ||
207 | Say Y here if you want verbose debugging from the PM Suspend and | ||
208 | Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> | ||
209 | for more information. | ||
210 | |||
211 | config S3C_PM_DEBUG_LED_SMDK | ||
212 | bool "SMDK LED suspend/resume debugging" | ||
213 | depends on PM && (MACH_SMDK6410) | ||
214 | help | ||
215 | Say Y here to enable the use of the SMDK LEDs on the baseboard | ||
216 | for debugging of the state of the suspend and resume process. | ||
217 | |||
218 | Note, this currently only works for S3C64XX based SMDK boards. | ||
219 | |||
220 | config SAMSUNG_PM_CHECK | ||
221 | bool "S3C2410 PM Suspend Memory CRC" | ||
222 | depends on PM && CRC32 | ||
223 | help | ||
224 | Enable the PM code's memory area checksum over sleep. This option | ||
225 | will generate CRCs of all blocks of memory, and store them before | ||
226 | going to sleep. The blocks are then checked on resume for any | ||
227 | errors. | ||
228 | |||
229 | Note, this can take several seconds depending on memory size | ||
230 | and CPU speed. | ||
231 | |||
232 | See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> | ||
233 | |||
234 | config SAMSUNG_PM_CHECK_CHUNKSIZE | ||
235 | int "S3C2410 PM Suspend CRC Chunksize (KiB)" | ||
236 | depends on PM && SAMSUNG_PM_CHECK | ||
237 | default 64 | ||
238 | help | ||
239 | Set the chunksize in Kilobytes of the CRC for checking memory | ||
240 | corruption over suspend and resume. A smaller value will mean that | ||
241 | the CRC data block will take more memory, but wil identify any | ||
242 | faults with better precision. | ||
243 | |||
244 | See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> | ||
16 | 245 | ||
17 | endif | 246 | endif |
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 4478b9f7dc34..22c89d08f6e5 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile | |||
@@ -9,3 +9,48 @@ obj-m := | |||
9 | obj-n := dummy.o | 9 | obj-n := dummy.o |
10 | obj- := | 10 | obj- := |
11 | 11 | ||
12 | # Objects we always build independent of SoC choice | ||
13 | |||
14 | obj-y += init.o | ||
15 | obj-y += time.o | ||
16 | obj-y += clock.o | ||
17 | obj-y += pwm-clock.o | ||
18 | obj-y += gpio.o | ||
19 | obj-y += gpio-config.o | ||
20 | |||
21 | obj-$(CONFIG_SAMSUNG_GPIOLIB_4BIT) += gpiolib.o | ||
22 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o | ||
23 | |||
24 | obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o | ||
25 | obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o | ||
26 | |||
27 | # ADC | ||
28 | |||
29 | obj-$(CONFIG_S3C_ADC) += adc.o | ||
30 | |||
31 | # devices | ||
32 | |||
33 | obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o | ||
34 | obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o | ||
35 | obj-$(CONFIG_S3C_DEV_HSMMC2) += dev-hsmmc2.o | ||
36 | obj-y += dev-i2c0.o | ||
37 | obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o | ||
38 | obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o | ||
39 | obj-y += dev-uart.o | ||
40 | obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o | ||
41 | obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o | ||
42 | obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o | ||
43 | |||
44 | # DMA support | ||
45 | |||
46 | obj-$(CONFIG_S3C_DMA) += dma.o | ||
47 | |||
48 | # PM support | ||
49 | |||
50 | obj-$(CONFIG_PM) += pm.o | ||
51 | obj-$(CONFIG_PM) += pm-gpio.o | ||
52 | obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o | ||
53 | |||
54 | # PWM support | ||
55 | |||
56 | obj-$(CONFIG_HAVE_PWM) += pwm.o | ||
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c new file mode 100644 index 000000000000..0b5833b9ac5b --- /dev/null +++ b/arch/arm/plat-samsung/adc.c | |||
@@ -0,0 +1,474 @@ | |||
1 | /* arch/arm/plat-samsung/adc.c | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> | ||
6 | * | ||
7 | * Samsung ADC device core | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include <plat/regs-adc.h> | ||
25 | #include <plat/adc.h> | ||
26 | |||
27 | /* This driver is designed to control the usage of the ADC block between | ||
28 | * the touchscreen and any other drivers that may need to use it, such as | ||
29 | * the hwmon driver. | ||
30 | * | ||
31 | * Priority will be given to the touchscreen driver, but as this itself is | ||
32 | * rate limited it should not starve other requests which are processed in | ||
33 | * order that they are received. | ||
34 | * | ||
35 | * Each user registers to get a client block which uniquely identifies it | ||
36 | * and stores information such as the necessary functions to callback when | ||
37 | * action is required. | ||
38 | */ | ||
39 | |||
40 | enum s3c_cpu_type { | ||
41 | TYPE_S3C24XX, | ||
42 | TYPE_S3C64XX | ||
43 | }; | ||
44 | |||
45 | struct s3c_adc_client { | ||
46 | struct platform_device *pdev; | ||
47 | struct list_head pend; | ||
48 | wait_queue_head_t *wait; | ||
49 | |||
50 | unsigned int nr_samples; | ||
51 | int result; | ||
52 | unsigned char is_ts; | ||
53 | unsigned char channel; | ||
54 | |||
55 | void (*select_cb)(struct s3c_adc_client *c, unsigned selected); | ||
56 | void (*convert_cb)(struct s3c_adc_client *c, | ||
57 | unsigned val1, unsigned val2, | ||
58 | unsigned *samples_left); | ||
59 | }; | ||
60 | |||
61 | struct adc_device { | ||
62 | struct platform_device *pdev; | ||
63 | struct platform_device *owner; | ||
64 | struct clk *clk; | ||
65 | struct s3c_adc_client *cur; | ||
66 | struct s3c_adc_client *ts_pend; | ||
67 | void __iomem *regs; | ||
68 | |||
69 | unsigned int prescale; | ||
70 | |||
71 | int irq; | ||
72 | }; | ||
73 | |||
74 | static struct adc_device *adc_dev; | ||
75 | |||
76 | static LIST_HEAD(adc_pending); | ||
77 | |||
78 | #define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg) | ||
79 | |||
80 | static inline void s3c_adc_convert(struct adc_device *adc) | ||
81 | { | ||
82 | unsigned con = readl(adc->regs + S3C2410_ADCCON); | ||
83 | |||
84 | con |= S3C2410_ADCCON_ENABLE_START; | ||
85 | writel(con, adc->regs + S3C2410_ADCCON); | ||
86 | } | ||
87 | |||
88 | static inline void s3c_adc_select(struct adc_device *adc, | ||
89 | struct s3c_adc_client *client) | ||
90 | { | ||
91 | unsigned con = readl(adc->regs + S3C2410_ADCCON); | ||
92 | |||
93 | client->select_cb(client, 1); | ||
94 | |||
95 | con &= ~S3C2410_ADCCON_MUXMASK; | ||
96 | con &= ~S3C2410_ADCCON_STDBM; | ||
97 | con &= ~S3C2410_ADCCON_STARTMASK; | ||
98 | |||
99 | if (!client->is_ts) | ||
100 | con |= S3C2410_ADCCON_SELMUX(client->channel); | ||
101 | |||
102 | writel(con, adc->regs + S3C2410_ADCCON); | ||
103 | } | ||
104 | |||
105 | static void s3c_adc_dbgshow(struct adc_device *adc) | ||
106 | { | ||
107 | adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n", | ||
108 | readl(adc->regs + S3C2410_ADCCON), | ||
109 | readl(adc->regs + S3C2410_ADCTSC), | ||
110 | readl(adc->regs + S3C2410_ADCDLY)); | ||
111 | } | ||
112 | |||
113 | static void s3c_adc_try(struct adc_device *adc) | ||
114 | { | ||
115 | struct s3c_adc_client *next = adc->ts_pend; | ||
116 | |||
117 | if (!next && !list_empty(&adc_pending)) { | ||
118 | next = list_first_entry(&adc_pending, | ||
119 | struct s3c_adc_client, pend); | ||
120 | list_del(&next->pend); | ||
121 | } else | ||
122 | adc->ts_pend = NULL; | ||
123 | |||
124 | if (next) { | ||
125 | adc_dbg(adc, "new client is %p\n", next); | ||
126 | adc->cur = next; | ||
127 | s3c_adc_select(adc, next); | ||
128 | s3c_adc_convert(adc); | ||
129 | s3c_adc_dbgshow(adc); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | int s3c_adc_start(struct s3c_adc_client *client, | ||
134 | unsigned int channel, unsigned int nr_samples) | ||
135 | { | ||
136 | struct adc_device *adc = adc_dev; | ||
137 | unsigned long flags; | ||
138 | |||
139 | if (!adc) { | ||
140 | printk(KERN_ERR "%s: failed to find adc\n", __func__); | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | |||
144 | if (client->is_ts && adc->ts_pend) | ||
145 | return -EAGAIN; | ||
146 | |||
147 | local_irq_save(flags); | ||
148 | |||
149 | client->channel = channel; | ||
150 | client->nr_samples = nr_samples; | ||
151 | |||
152 | if (client->is_ts) | ||
153 | adc->ts_pend = client; | ||
154 | else | ||
155 | list_add_tail(&client->pend, &adc_pending); | ||
156 | |||
157 | if (!adc->cur) | ||
158 | s3c_adc_try(adc); | ||
159 | local_irq_restore(flags); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | EXPORT_SYMBOL_GPL(s3c_adc_start); | ||
164 | |||
165 | static void s3c_convert_done(struct s3c_adc_client *client, | ||
166 | unsigned v, unsigned u, unsigned *left) | ||
167 | { | ||
168 | client->result = v; | ||
169 | wake_up(client->wait); | ||
170 | } | ||
171 | |||
172 | int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch) | ||
173 | { | ||
174 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); | ||
175 | int ret; | ||
176 | |||
177 | client->convert_cb = s3c_convert_done; | ||
178 | client->wait = &wake; | ||
179 | client->result = -1; | ||
180 | |||
181 | ret = s3c_adc_start(client, ch, 1); | ||
182 | if (ret < 0) | ||
183 | goto err; | ||
184 | |||
185 | ret = wait_event_timeout(wake, client->result >= 0, HZ / 2); | ||
186 | if (client->result < 0) { | ||
187 | ret = -ETIMEDOUT; | ||
188 | goto err; | ||
189 | } | ||
190 | |||
191 | client->convert_cb = NULL; | ||
192 | return client->result; | ||
193 | |||
194 | err: | ||
195 | return ret; | ||
196 | } | ||
197 | EXPORT_SYMBOL_GPL(s3c_adc_read); | ||
198 | |||
199 | static void s3c_adc_default_select(struct s3c_adc_client *client, | ||
200 | unsigned select) | ||
201 | { | ||
202 | } | ||
203 | |||
204 | struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, | ||
205 | void (*select)(struct s3c_adc_client *client, | ||
206 | unsigned int selected), | ||
207 | void (*conv)(struct s3c_adc_client *client, | ||
208 | unsigned d0, unsigned d1, | ||
209 | unsigned *samples_left), | ||
210 | unsigned int is_ts) | ||
211 | { | ||
212 | struct s3c_adc_client *client; | ||
213 | |||
214 | WARN_ON(!pdev); | ||
215 | |||
216 | if (!select) | ||
217 | select = s3c_adc_default_select; | ||
218 | |||
219 | if (!pdev) | ||
220 | return ERR_PTR(-EINVAL); | ||
221 | |||
222 | client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL); | ||
223 | if (!client) { | ||
224 | dev_err(&pdev->dev, "no memory for adc client\n"); | ||
225 | return ERR_PTR(-ENOMEM); | ||
226 | } | ||
227 | |||
228 | client->pdev = pdev; | ||
229 | client->is_ts = is_ts; | ||
230 | client->select_cb = select; | ||
231 | client->convert_cb = conv; | ||
232 | |||
233 | return client; | ||
234 | } | ||
235 | EXPORT_SYMBOL_GPL(s3c_adc_register); | ||
236 | |||
237 | void s3c_adc_release(struct s3c_adc_client *client) | ||
238 | { | ||
239 | /* We should really check that nothing is in progress. */ | ||
240 | if (adc_dev->cur == client) | ||
241 | adc_dev->cur = NULL; | ||
242 | if (adc_dev->ts_pend == client) | ||
243 | adc_dev->ts_pend = NULL; | ||
244 | else { | ||
245 | struct list_head *p, *n; | ||
246 | struct s3c_adc_client *tmp; | ||
247 | |||
248 | list_for_each_safe(p, n, &adc_pending) { | ||
249 | tmp = list_entry(p, struct s3c_adc_client, pend); | ||
250 | if (tmp == client) | ||
251 | list_del(&tmp->pend); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | if (adc_dev->cur == NULL) | ||
256 | s3c_adc_try(adc_dev); | ||
257 | kfree(client); | ||
258 | } | ||
259 | EXPORT_SYMBOL_GPL(s3c_adc_release); | ||
260 | |||
261 | static irqreturn_t s3c_adc_irq(int irq, void *pw) | ||
262 | { | ||
263 | struct adc_device *adc = pw; | ||
264 | struct s3c_adc_client *client = adc->cur; | ||
265 | enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data; | ||
266 | unsigned long flags; | ||
267 | unsigned data0, data1; | ||
268 | |||
269 | if (!client) { | ||
270 | dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__); | ||
271 | goto exit; | ||
272 | } | ||
273 | |||
274 | data0 = readl(adc->regs + S3C2410_ADCDAT0); | ||
275 | data1 = readl(adc->regs + S3C2410_ADCDAT1); | ||
276 | adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); | ||
277 | |||
278 | client->nr_samples--; | ||
279 | |||
280 | if (cpu == TYPE_S3C64XX) { | ||
281 | /* S3C64XX ADC resolution is 12-bit */ | ||
282 | data0 &= 0xfff; | ||
283 | data1 &= 0xfff; | ||
284 | } else { | ||
285 | data0 &= 0x3ff; | ||
286 | data1 &= 0x3ff; | ||
287 | } | ||
288 | |||
289 | if (client->convert_cb) | ||
290 | (client->convert_cb)(client, data0, data1, &client->nr_samples); | ||
291 | |||
292 | if (client->nr_samples > 0) { | ||
293 | /* fire another conversion for this */ | ||
294 | |||
295 | client->select_cb(client, 1); | ||
296 | s3c_adc_convert(adc); | ||
297 | } else { | ||
298 | local_irq_save(flags); | ||
299 | (client->select_cb)(client, 0); | ||
300 | adc->cur = NULL; | ||
301 | |||
302 | s3c_adc_try(adc); | ||
303 | local_irq_restore(flags); | ||
304 | } | ||
305 | |||
306 | exit: | ||
307 | if (cpu == TYPE_S3C64XX) { | ||
308 | /* Clear ADC interrupt */ | ||
309 | writel(0, adc->regs + S3C64XX_ADCCLRINT); | ||
310 | } | ||
311 | return IRQ_HANDLED; | ||
312 | } | ||
313 | |||
314 | static int s3c_adc_probe(struct platform_device *pdev) | ||
315 | { | ||
316 | struct device *dev = &pdev->dev; | ||
317 | struct adc_device *adc; | ||
318 | struct resource *regs; | ||
319 | int ret; | ||
320 | unsigned tmp; | ||
321 | |||
322 | adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL); | ||
323 | if (adc == NULL) { | ||
324 | dev_err(dev, "failed to allocate adc_device\n"); | ||
325 | return -ENOMEM; | ||
326 | } | ||
327 | |||
328 | adc->pdev = pdev; | ||
329 | adc->prescale = S3C2410_ADCCON_PRSCVL(49); | ||
330 | |||
331 | adc->irq = platform_get_irq(pdev, 1); | ||
332 | if (adc->irq <= 0) { | ||
333 | dev_err(dev, "failed to get adc irq\n"); | ||
334 | ret = -ENOENT; | ||
335 | goto err_alloc; | ||
336 | } | ||
337 | |||
338 | ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc); | ||
339 | if (ret < 0) { | ||
340 | dev_err(dev, "failed to attach adc irq\n"); | ||
341 | goto err_alloc; | ||
342 | } | ||
343 | |||
344 | adc->clk = clk_get(dev, "adc"); | ||
345 | if (IS_ERR(adc->clk)) { | ||
346 | dev_err(dev, "failed to get adc clock\n"); | ||
347 | ret = PTR_ERR(adc->clk); | ||
348 | goto err_irq; | ||
349 | } | ||
350 | |||
351 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
352 | if (!regs) { | ||
353 | dev_err(dev, "failed to find registers\n"); | ||
354 | ret = -ENXIO; | ||
355 | goto err_clk; | ||
356 | } | ||
357 | |||
358 | adc->regs = ioremap(regs->start, resource_size(regs)); | ||
359 | if (!adc->regs) { | ||
360 | dev_err(dev, "failed to map registers\n"); | ||
361 | ret = -ENXIO; | ||
362 | goto err_clk; | ||
363 | } | ||
364 | |||
365 | clk_enable(adc->clk); | ||
366 | |||
367 | tmp = adc->prescale | S3C2410_ADCCON_PRSCEN; | ||
368 | if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) { | ||
369 | /* Enable 12-bit ADC resolution */ | ||
370 | tmp |= S3C64XX_ADCCON_RESSEL; | ||
371 | } | ||
372 | writel(tmp, adc->regs + S3C2410_ADCCON); | ||
373 | |||
374 | dev_info(dev, "attached adc driver\n"); | ||
375 | |||
376 | platform_set_drvdata(pdev, adc); | ||
377 | adc_dev = adc; | ||
378 | |||
379 | return 0; | ||
380 | |||
381 | err_clk: | ||
382 | clk_put(adc->clk); | ||
383 | |||
384 | err_irq: | ||
385 | free_irq(adc->irq, adc); | ||
386 | |||
387 | err_alloc: | ||
388 | kfree(adc); | ||
389 | return ret; | ||
390 | } | ||
391 | |||
392 | static int __devexit s3c_adc_remove(struct platform_device *pdev) | ||
393 | { | ||
394 | struct adc_device *adc = platform_get_drvdata(pdev); | ||
395 | |||
396 | iounmap(adc->regs); | ||
397 | free_irq(adc->irq, adc); | ||
398 | clk_disable(adc->clk); | ||
399 | clk_put(adc->clk); | ||
400 | kfree(adc); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | #ifdef CONFIG_PM | ||
406 | static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state) | ||
407 | { | ||
408 | struct adc_device *adc = platform_get_drvdata(pdev); | ||
409 | u32 con; | ||
410 | |||
411 | con = readl(adc->regs + S3C2410_ADCCON); | ||
412 | con |= S3C2410_ADCCON_STDBM; | ||
413 | writel(con, adc->regs + S3C2410_ADCCON); | ||
414 | |||
415 | disable_irq(adc->irq); | ||
416 | clk_disable(adc->clk); | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int s3c_adc_resume(struct platform_device *pdev) | ||
422 | { | ||
423 | struct adc_device *adc = platform_get_drvdata(pdev); | ||
424 | |||
425 | clk_enable(adc->clk); | ||
426 | enable_irq(adc->irq); | ||
427 | |||
428 | writel(adc->prescale | S3C2410_ADCCON_PRSCEN, | ||
429 | adc->regs + S3C2410_ADCCON); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | #else | ||
435 | #define s3c_adc_suspend NULL | ||
436 | #define s3c_adc_resume NULL | ||
437 | #endif | ||
438 | |||
439 | static struct platform_device_id s3c_adc_driver_ids[] = { | ||
440 | { | ||
441 | .name = "s3c24xx-adc", | ||
442 | .driver_data = TYPE_S3C24XX, | ||
443 | }, { | ||
444 | .name = "s3c64xx-adc", | ||
445 | .driver_data = TYPE_S3C64XX, | ||
446 | }, | ||
447 | { } | ||
448 | }; | ||
449 | MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids); | ||
450 | |||
451 | static struct platform_driver s3c_adc_driver = { | ||
452 | .id_table = s3c_adc_driver_ids, | ||
453 | .driver = { | ||
454 | .name = "s3c-adc", | ||
455 | .owner = THIS_MODULE, | ||
456 | }, | ||
457 | .probe = s3c_adc_probe, | ||
458 | .remove = __devexit_p(s3c_adc_remove), | ||
459 | .suspend = s3c_adc_suspend, | ||
460 | .resume = s3c_adc_resume, | ||
461 | }; | ||
462 | |||
463 | static int __init adc_init(void) | ||
464 | { | ||
465 | int ret; | ||
466 | |||
467 | ret = platform_driver_register(&s3c_adc_driver); | ||
468 | if (ret) | ||
469 | printk(KERN_ERR "%s: failed to add adc driver\n", __func__); | ||
470 | |||
471 | return ret; | ||
472 | } | ||
473 | |||
474 | arch_initcall(adc_init); | ||
diff --git a/arch/arm/plat-samsung/clock-clksrc.c b/arch/arm/plat-samsung/clock-clksrc.c new file mode 100644 index 000000000000..ae8b8507663f --- /dev/null +++ b/arch/arm/plat-samsung/clock-clksrc.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* linux/arch/arm/plat-samsung/clock-clksrc.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/sysdev.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <plat/clock.h> | ||
23 | #include <plat/clock-clksrc.h> | ||
24 | #include <plat/cpu-freq.h> | ||
25 | |||
26 | static inline struct clksrc_clk *to_clksrc(struct clk *clk) | ||
27 | { | ||
28 | return container_of(clk, struct clksrc_clk, clk); | ||
29 | } | ||
30 | |||
31 | static inline u32 bit_mask(u32 shift, u32 nr_bits) | ||
32 | { | ||
33 | u32 mask = 0xffffffff >> (32 - nr_bits); | ||
34 | |||
35 | return mask << shift; | ||
36 | } | ||
37 | |||
38 | static unsigned long s3c_getrate_clksrc(struct clk *clk) | ||
39 | { | ||
40 | struct clksrc_clk *sclk = to_clksrc(clk); | ||
41 | unsigned long rate = clk_get_rate(clk->parent); | ||
42 | u32 clkdiv = __raw_readl(sclk->reg_div.reg); | ||
43 | u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size); | ||
44 | |||
45 | clkdiv &= mask; | ||
46 | clkdiv >>= sclk->reg_div.shift; | ||
47 | clkdiv++; | ||
48 | |||
49 | rate /= clkdiv; | ||
50 | return rate; | ||
51 | } | ||
52 | |||
53 | static int s3c_setrate_clksrc(struct clk *clk, unsigned long rate) | ||
54 | { | ||
55 | struct clksrc_clk *sclk = to_clksrc(clk); | ||
56 | void __iomem *reg = sclk->reg_div.reg; | ||
57 | unsigned int div; | ||
58 | u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size); | ||
59 | u32 val; | ||
60 | |||
61 | rate = clk_round_rate(clk, rate); | ||
62 | div = clk_get_rate(clk->parent) / rate; | ||
63 | if (div > (1 << sclk->reg_div.size)) | ||
64 | return -EINVAL; | ||
65 | |||
66 | val = __raw_readl(reg); | ||
67 | val &= ~mask; | ||
68 | val |= (div - 1) << sclk->reg_div.shift; | ||
69 | __raw_writel(val, reg); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int s3c_setparent_clksrc(struct clk *clk, struct clk *parent) | ||
75 | { | ||
76 | struct clksrc_clk *sclk = to_clksrc(clk); | ||
77 | struct clksrc_sources *srcs = sclk->sources; | ||
78 | u32 clksrc = __raw_readl(sclk->reg_src.reg); | ||
79 | u32 mask = bit_mask(sclk->reg_src.shift, sclk->reg_src.size); | ||
80 | int src_nr = -1; | ||
81 | int ptr; | ||
82 | |||
83 | for (ptr = 0; ptr < srcs->nr_sources; ptr++) | ||
84 | if (srcs->sources[ptr] == parent) { | ||
85 | src_nr = ptr; | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | if (src_nr >= 0) { | ||
90 | clk->parent = parent; | ||
91 | |||
92 | clksrc &= ~mask; | ||
93 | clksrc |= src_nr << sclk->reg_src.shift; | ||
94 | |||
95 | __raw_writel(clksrc, sclk->reg_src.reg); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | static unsigned long s3c_roundrate_clksrc(struct clk *clk, | ||
103 | unsigned long rate) | ||
104 | { | ||
105 | struct clksrc_clk *sclk = to_clksrc(clk); | ||
106 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
107 | int max_div = 1 << sclk->reg_div.size; | ||
108 | int div; | ||
109 | |||
110 | if (rate >= parent_rate) | ||
111 | rate = parent_rate; | ||
112 | else { | ||
113 | div = parent_rate / rate; | ||
114 | if (parent_rate % rate) | ||
115 | div++; | ||
116 | |||
117 | if (div == 0) | ||
118 | div = 1; | ||
119 | if (div > max_div) | ||
120 | div = max_div; | ||
121 | |||
122 | rate = parent_rate / div; | ||
123 | } | ||
124 | |||
125 | return rate; | ||
126 | } | ||
127 | |||
128 | /* Clock initialisation code */ | ||
129 | |||
130 | void __init_or_cpufreq s3c_set_clksrc(struct clksrc_clk *clk, bool announce) | ||
131 | { | ||
132 | struct clksrc_sources *srcs = clk->sources; | ||
133 | u32 mask = bit_mask(clk->reg_src.shift, clk->reg_src.size); | ||
134 | u32 clksrc; | ||
135 | |||
136 | if (!clk->reg_src.reg) { | ||
137 | if (!clk->clk.parent) | ||
138 | printk(KERN_ERR "%s: no parent clock specified\n", | ||
139 | clk->clk.name); | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | clksrc = __raw_readl(clk->reg_src.reg); | ||
144 | clksrc &= mask; | ||
145 | clksrc >>= clk->reg_src.shift; | ||
146 | |||
147 | if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) { | ||
148 | printk(KERN_ERR "%s: bad source %d\n", | ||
149 | clk->clk.name, clksrc); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | clk->clk.parent = srcs->sources[clksrc]; | ||
154 | |||
155 | if (announce) | ||
156 | printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n", | ||
157 | clk->clk.name, clk->clk.parent->name, clksrc, | ||
158 | clk_get_rate(&clk->clk)); | ||
159 | } | ||
160 | |||
161 | static struct clk_ops clksrc_ops = { | ||
162 | .set_parent = s3c_setparent_clksrc, | ||
163 | .get_rate = s3c_getrate_clksrc, | ||
164 | .set_rate = s3c_setrate_clksrc, | ||
165 | .round_rate = s3c_roundrate_clksrc, | ||
166 | }; | ||
167 | |||
168 | static struct clk_ops clksrc_ops_nodiv = { | ||
169 | .set_parent = s3c_setparent_clksrc, | ||
170 | }; | ||
171 | |||
172 | static struct clk_ops clksrc_ops_nosrc = { | ||
173 | .get_rate = s3c_getrate_clksrc, | ||
174 | .set_rate = s3c_setrate_clksrc, | ||
175 | .round_rate = s3c_roundrate_clksrc, | ||
176 | }; | ||
177 | |||
178 | void __init s3c_register_clksrc(struct clksrc_clk *clksrc, int size) | ||
179 | { | ||
180 | int ret; | ||
181 | |||
182 | for (; size > 0; size--, clksrc++) { | ||
183 | if (!clksrc->reg_div.reg && !clksrc->reg_src.reg) | ||
184 | printk(KERN_ERR "%s: clock %s has no registers set\n", | ||
185 | __func__, clksrc->clk.name); | ||
186 | |||
187 | /* fill in the default functions */ | ||
188 | |||
189 | if (!clksrc->clk.ops) { | ||
190 | if (!clksrc->reg_div.reg) | ||
191 | clksrc->clk.ops = &clksrc_ops_nodiv; | ||
192 | else if (!clksrc->reg_src.reg) | ||
193 | clksrc->clk.ops = &clksrc_ops_nosrc; | ||
194 | else | ||
195 | clksrc->clk.ops = &clksrc_ops; | ||
196 | } | ||
197 | |||
198 | /* setup the clocksource, but do not announce it | ||
199 | * as it may be re-set by the setup routines | ||
200 | * called after the rest of the clocks have been | ||
201 | * registered | ||
202 | */ | ||
203 | s3c_set_clksrc(clksrc, false); | ||
204 | |||
205 | ret = s3c24xx_register_clock(&clksrc->clk); | ||
206 | |||
207 | if (ret < 0) { | ||
208 | printk(KERN_ERR "%s: failed to register %s (%d)\n", | ||
209 | __func__, clksrc->clk.name, ret); | ||
210 | } | ||
211 | } | ||
212 | } | ||
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c new file mode 100644 index 000000000000..1b25c9d8c403 --- /dev/null +++ b/arch/arm/plat-samsung/clock.c | |||
@@ -0,0 +1,409 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/clock.c | ||
2 | * | ||
3 | * Copyright 2004-2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C24XX Core clock control support | ||
7 | * | ||
8 | * Based on, and code from linux/arch/arm/mach-versatile/clock.c | ||
9 | ** | ||
10 | ** Copyright (C) 2004 ARM Limited. | ||
11 | ** Written by Deep Blue Solutions Limited. | ||
12 | * | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
27 | */ | ||
28 | |||
29 | #include <linux/init.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/list.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/err.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/sysdev.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/ioport.h> | ||
39 | #include <linux/clk.h> | ||
40 | #include <linux/spinlock.h> | ||
41 | #include <linux/io.h> | ||
42 | |||
43 | #include <mach/hardware.h> | ||
44 | #include <asm/irq.h> | ||
45 | |||
46 | #include <plat/cpu-freq.h> | ||
47 | |||
48 | #include <plat/clock.h> | ||
49 | #include <plat/cpu.h> | ||
50 | |||
51 | /* clock information */ | ||
52 | |||
53 | static LIST_HEAD(clocks); | ||
54 | |||
55 | /* We originally used an mutex here, but some contexts (see resume) | ||
56 | * are calling functions such as clk_set_parent() with IRQs disabled | ||
57 | * causing an BUG to be triggered. | ||
58 | */ | ||
59 | DEFINE_SPINLOCK(clocks_lock); | ||
60 | |||
61 | /* enable and disable calls for use with the clk struct */ | ||
62 | |||
63 | static int clk_null_enable(struct clk *clk, int enable) | ||
64 | { | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | /* Clock API calls */ | ||
69 | |||
70 | struct clk *clk_get(struct device *dev, const char *id) | ||
71 | { | ||
72 | struct clk *p; | ||
73 | struct clk *clk = ERR_PTR(-ENOENT); | ||
74 | int idno; | ||
75 | |||
76 | if (dev == NULL || dev->bus != &platform_bus_type) | ||
77 | idno = -1; | ||
78 | else | ||
79 | idno = to_platform_device(dev)->id; | ||
80 | |||
81 | spin_lock(&clocks_lock); | ||
82 | |||
83 | list_for_each_entry(p, &clocks, list) { | ||
84 | if (p->id == idno && | ||
85 | strcmp(id, p->name) == 0 && | ||
86 | try_module_get(p->owner)) { | ||
87 | clk = p; | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /* check for the case where a device was supplied, but the | ||
93 | * clock that was being searched for is not device specific */ | ||
94 | |||
95 | if (IS_ERR(clk)) { | ||
96 | list_for_each_entry(p, &clocks, list) { | ||
97 | if (p->id == -1 && strcmp(id, p->name) == 0 && | ||
98 | try_module_get(p->owner)) { | ||
99 | clk = p; | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | spin_unlock(&clocks_lock); | ||
106 | return clk; | ||
107 | } | ||
108 | |||
109 | void clk_put(struct clk *clk) | ||
110 | { | ||
111 | module_put(clk->owner); | ||
112 | } | ||
113 | |||
114 | int clk_enable(struct clk *clk) | ||
115 | { | ||
116 | if (IS_ERR(clk) || clk == NULL) | ||
117 | return -EINVAL; | ||
118 | |||
119 | clk_enable(clk->parent); | ||
120 | |||
121 | spin_lock(&clocks_lock); | ||
122 | |||
123 | if ((clk->usage++) == 0) | ||
124 | (clk->enable)(clk, 1); | ||
125 | |||
126 | spin_unlock(&clocks_lock); | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | void clk_disable(struct clk *clk) | ||
131 | { | ||
132 | if (IS_ERR(clk) || clk == NULL) | ||
133 | return; | ||
134 | |||
135 | spin_lock(&clocks_lock); | ||
136 | |||
137 | if ((--clk->usage) == 0) | ||
138 | (clk->enable)(clk, 0); | ||
139 | |||
140 | spin_unlock(&clocks_lock); | ||
141 | clk_disable(clk->parent); | ||
142 | } | ||
143 | |||
144 | |||
145 | unsigned long clk_get_rate(struct clk *clk) | ||
146 | { | ||
147 | if (IS_ERR(clk)) | ||
148 | return 0; | ||
149 | |||
150 | if (clk->rate != 0) | ||
151 | return clk->rate; | ||
152 | |||
153 | if (clk->ops != NULL && clk->ops->get_rate != NULL) | ||
154 | return (clk->ops->get_rate)(clk); | ||
155 | |||
156 | if (clk->parent != NULL) | ||
157 | return clk_get_rate(clk->parent); | ||
158 | |||
159 | return clk->rate; | ||
160 | } | ||
161 | |||
162 | long clk_round_rate(struct clk *clk, unsigned long rate) | ||
163 | { | ||
164 | if (!IS_ERR(clk) && clk->ops && clk->ops->round_rate) | ||
165 | return (clk->ops->round_rate)(clk, rate); | ||
166 | |||
167 | return rate; | ||
168 | } | ||
169 | |||
170 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
171 | { | ||
172 | int ret; | ||
173 | |||
174 | if (IS_ERR(clk)) | ||
175 | return -EINVAL; | ||
176 | |||
177 | /* We do not default just do a clk->rate = rate as | ||
178 | * the clock may have been made this way by choice. | ||
179 | */ | ||
180 | |||
181 | WARN_ON(clk->ops == NULL); | ||
182 | WARN_ON(clk->ops && clk->ops->set_rate == NULL); | ||
183 | |||
184 | if (clk->ops == NULL || clk->ops->set_rate == NULL) | ||
185 | return -EINVAL; | ||
186 | |||
187 | spin_lock(&clocks_lock); | ||
188 | ret = (clk->ops->set_rate)(clk, rate); | ||
189 | spin_unlock(&clocks_lock); | ||
190 | |||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | struct clk *clk_get_parent(struct clk *clk) | ||
195 | { | ||
196 | return clk->parent; | ||
197 | } | ||
198 | |||
199 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
200 | { | ||
201 | int ret = 0; | ||
202 | |||
203 | if (IS_ERR(clk)) | ||
204 | return -EINVAL; | ||
205 | |||
206 | spin_lock(&clocks_lock); | ||
207 | |||
208 | if (clk->ops && clk->ops->set_parent) | ||
209 | ret = (clk->ops->set_parent)(clk, parent); | ||
210 | |||
211 | spin_unlock(&clocks_lock); | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | EXPORT_SYMBOL(clk_get); | ||
217 | EXPORT_SYMBOL(clk_put); | ||
218 | EXPORT_SYMBOL(clk_enable); | ||
219 | EXPORT_SYMBOL(clk_disable); | ||
220 | EXPORT_SYMBOL(clk_get_rate); | ||
221 | EXPORT_SYMBOL(clk_round_rate); | ||
222 | EXPORT_SYMBOL(clk_set_rate); | ||
223 | EXPORT_SYMBOL(clk_get_parent); | ||
224 | EXPORT_SYMBOL(clk_set_parent); | ||
225 | |||
226 | /* base clocks */ | ||
227 | |||
228 | int clk_default_setrate(struct clk *clk, unsigned long rate) | ||
229 | { | ||
230 | clk->rate = rate; | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | struct clk_ops clk_ops_def_setrate = { | ||
235 | .set_rate = clk_default_setrate, | ||
236 | }; | ||
237 | |||
238 | struct clk clk_xtal = { | ||
239 | .name = "xtal", | ||
240 | .id = -1, | ||
241 | .rate = 0, | ||
242 | .parent = NULL, | ||
243 | .ctrlbit = 0, | ||
244 | }; | ||
245 | |||
246 | struct clk clk_ext = { | ||
247 | .name = "ext", | ||
248 | .id = -1, | ||
249 | }; | ||
250 | |||
251 | struct clk clk_epll = { | ||
252 | .name = "epll", | ||
253 | .id = -1, | ||
254 | }; | ||
255 | |||
256 | struct clk clk_mpll = { | ||
257 | .name = "mpll", | ||
258 | .id = -1, | ||
259 | .ops = &clk_ops_def_setrate, | ||
260 | }; | ||
261 | |||
262 | struct clk clk_upll = { | ||
263 | .name = "upll", | ||
264 | .id = -1, | ||
265 | .parent = NULL, | ||
266 | .ctrlbit = 0, | ||
267 | }; | ||
268 | |||
269 | struct clk clk_f = { | ||
270 | .name = "fclk", | ||
271 | .id = -1, | ||
272 | .rate = 0, | ||
273 | .parent = &clk_mpll, | ||
274 | .ctrlbit = 0, | ||
275 | }; | ||
276 | |||
277 | struct clk clk_h = { | ||
278 | .name = "hclk", | ||
279 | .id = -1, | ||
280 | .rate = 0, | ||
281 | .parent = NULL, | ||
282 | .ctrlbit = 0, | ||
283 | .ops = &clk_ops_def_setrate, | ||
284 | }; | ||
285 | |||
286 | struct clk clk_p = { | ||
287 | .name = "pclk", | ||
288 | .id = -1, | ||
289 | .rate = 0, | ||
290 | .parent = NULL, | ||
291 | .ctrlbit = 0, | ||
292 | .ops = &clk_ops_def_setrate, | ||
293 | }; | ||
294 | |||
295 | struct clk clk_usb_bus = { | ||
296 | .name = "usb-bus", | ||
297 | .id = -1, | ||
298 | .rate = 0, | ||
299 | .parent = &clk_upll, | ||
300 | }; | ||
301 | |||
302 | |||
303 | struct clk s3c24xx_uclk = { | ||
304 | .name = "uclk", | ||
305 | .id = -1, | ||
306 | }; | ||
307 | |||
308 | /* initialise the clock system */ | ||
309 | |||
310 | /** | ||
311 | * s3c24xx_register_clock() - register a clock | ||
312 | * @clk: The clock to register | ||
313 | * | ||
314 | * Add the specified clock to the list of clocks known by the system. | ||
315 | */ | ||
316 | int s3c24xx_register_clock(struct clk *clk) | ||
317 | { | ||
318 | if (clk->enable == NULL) | ||
319 | clk->enable = clk_null_enable; | ||
320 | |||
321 | /* add to the list of available clocks */ | ||
322 | |||
323 | /* Quick check to see if this clock has already been registered. */ | ||
324 | BUG_ON(clk->list.prev != clk->list.next); | ||
325 | |||
326 | spin_lock(&clocks_lock); | ||
327 | list_add(&clk->list, &clocks); | ||
328 | spin_unlock(&clocks_lock); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /** | ||
334 | * s3c24xx_register_clocks() - register an array of clock pointers | ||
335 | * @clks: Pointer to an array of struct clk pointers | ||
336 | * @nr_clks: The number of clocks in the @clks array. | ||
337 | * | ||
338 | * Call s3c24xx_register_clock() for all the clock pointers contained | ||
339 | * in the @clks list. Returns the number of failures. | ||
340 | */ | ||
341 | int s3c24xx_register_clocks(struct clk **clks, int nr_clks) | ||
342 | { | ||
343 | int fails = 0; | ||
344 | |||
345 | for (; nr_clks > 0; nr_clks--, clks++) { | ||
346 | if (s3c24xx_register_clock(*clks) < 0) { | ||
347 | struct clk *clk = *clks; | ||
348 | printk(KERN_ERR "%s: failed to register %p: %s\n", | ||
349 | __func__, clk, clk->name); | ||
350 | fails++; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | return fails; | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * s3c_register_clocks() - register an array of clocks | ||
359 | * @clkp: Pointer to the first clock in the array. | ||
360 | * @nr_clks: Number of clocks to register. | ||
361 | * | ||
362 | * Call s3c24xx_register_clock() on the @clkp array given, printing an | ||
363 | * error if it fails to register the clock (unlikely). | ||
364 | */ | ||
365 | void __init s3c_register_clocks(struct clk *clkp, int nr_clks) | ||
366 | { | ||
367 | int ret; | ||
368 | |||
369 | for (; nr_clks > 0; nr_clks--, clkp++) { | ||
370 | ret = s3c24xx_register_clock(clkp); | ||
371 | |||
372 | if (ret < 0) { | ||
373 | printk(KERN_ERR "Failed to register clock %s (%d)\n", | ||
374 | clkp->name, ret); | ||
375 | } | ||
376 | } | ||
377 | } | ||
378 | |||
379 | /* initalise all the clocks */ | ||
380 | |||
381 | int __init s3c24xx_register_baseclocks(unsigned long xtal) | ||
382 | { | ||
383 | printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n"); | ||
384 | |||
385 | clk_xtal.rate = xtal; | ||
386 | |||
387 | /* register our clocks */ | ||
388 | |||
389 | if (s3c24xx_register_clock(&clk_xtal) < 0) | ||
390 | printk(KERN_ERR "failed to register master xtal\n"); | ||
391 | |||
392 | if (s3c24xx_register_clock(&clk_mpll) < 0) | ||
393 | printk(KERN_ERR "failed to register mpll clock\n"); | ||
394 | |||
395 | if (s3c24xx_register_clock(&clk_upll) < 0) | ||
396 | printk(KERN_ERR "failed to register upll clock\n"); | ||
397 | |||
398 | if (s3c24xx_register_clock(&clk_f) < 0) | ||
399 | printk(KERN_ERR "failed to register cpu fclk\n"); | ||
400 | |||
401 | if (s3c24xx_register_clock(&clk_h) < 0) | ||
402 | printk(KERN_ERR "failed to register cpu hclk\n"); | ||
403 | |||
404 | if (s3c24xx_register_clock(&clk_p) < 0) | ||
405 | printk(KERN_ERR "failed to register cpu pclk\n"); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
diff --git a/arch/arm/plat-samsung/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c new file mode 100644 index 000000000000..a90198fc4b0f --- /dev/null +++ b/arch/arm/plat-samsung/dev-fb.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-fb.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series device definition for framebuffer device | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/fb.h> | ||
18 | |||
19 | #include <mach/irqs.h> | ||
20 | #include <mach/map.h> | ||
21 | #include <mach/regs-fb.h> | ||
22 | |||
23 | #include <plat/fb.h> | ||
24 | #include <plat/devs.h> | ||
25 | #include <plat/cpu.h> | ||
26 | |||
27 | static struct resource s3c_fb_resource[] = { | ||
28 | [0] = { | ||
29 | .start = S3C_PA_FB, | ||
30 | .end = S3C_PA_FB + SZ_16K - 1, | ||
31 | .flags = IORESOURCE_MEM, | ||
32 | }, | ||
33 | [1] = { | ||
34 | .start = IRQ_LCD_VSYNC, | ||
35 | .end = IRQ_LCD_VSYNC, | ||
36 | .flags = IORESOURCE_IRQ, | ||
37 | }, | ||
38 | [2] = { | ||
39 | .start = IRQ_LCD_FIFO, | ||
40 | .end = IRQ_LCD_FIFO, | ||
41 | .flags = IORESOURCE_IRQ, | ||
42 | }, | ||
43 | [3] = { | ||
44 | .start = IRQ_LCD_SYSTEM, | ||
45 | .end = IRQ_LCD_SYSTEM, | ||
46 | .flags = IORESOURCE_IRQ, | ||
47 | }, | ||
48 | }; | ||
49 | |||
50 | struct platform_device s3c_device_fb = { | ||
51 | .name = "s3c-fb", | ||
52 | .id = -1, | ||
53 | .num_resources = ARRAY_SIZE(s3c_fb_resource), | ||
54 | .resource = s3c_fb_resource, | ||
55 | .dev.dma_mask = &s3c_device_fb.dev.coherent_dma_mask, | ||
56 | .dev.coherent_dma_mask = 0xffffffffUL, | ||
57 | }; | ||
58 | |||
59 | void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd) | ||
60 | { | ||
61 | struct s3c_fb_platdata *npd; | ||
62 | |||
63 | if (!pd) { | ||
64 | printk(KERN_ERR "%s: no platform data\n", __func__); | ||
65 | return; | ||
66 | } | ||
67 | |||
68 | npd = kmemdup(pd, sizeof(struct s3c_fb_platdata), GFP_KERNEL); | ||
69 | if (!npd) | ||
70 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
71 | |||
72 | s3c_device_fb.dev.platform_data = npd; | ||
73 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c new file mode 100644 index 000000000000..4c05b39810e2 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hsmmc.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-hsmmc.c | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series device definition for hsmmc devices | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/mmc/host.h> | ||
17 | |||
18 | #include <mach/map.h> | ||
19 | #include <plat/sdhci.h> | ||
20 | #include <plat/devs.h> | ||
21 | #include <plat/cpu.h> | ||
22 | |||
23 | #define S3C_SZ_HSMMC (0x1000) | ||
24 | |||
25 | static struct resource s3c_hsmmc_resource[] = { | ||
26 | [0] = { | ||
27 | .start = S3C_PA_HSMMC0, | ||
28 | .end = S3C_PA_HSMMC0 + S3C_SZ_HSMMC - 1, | ||
29 | .flags = IORESOURCE_MEM, | ||
30 | }, | ||
31 | [1] = { | ||
32 | .start = IRQ_HSMMC0, | ||
33 | .end = IRQ_HSMMC0, | ||
34 | .flags = IORESOURCE_IRQ, | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL; | ||
39 | |||
40 | struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = { | ||
41 | .max_width = 4, | ||
42 | .host_caps = (MMC_CAP_4_BIT_DATA | | ||
43 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | ||
44 | }; | ||
45 | |||
46 | struct platform_device s3c_device_hsmmc0 = { | ||
47 | .name = "s3c-sdhci", | ||
48 | .id = 0, | ||
49 | .num_resources = ARRAY_SIZE(s3c_hsmmc_resource), | ||
50 | .resource = s3c_hsmmc_resource, | ||
51 | .dev = { | ||
52 | .dma_mask = &s3c_device_hsmmc_dmamask, | ||
53 | .coherent_dma_mask = 0xffffffffUL, | ||
54 | .platform_data = &s3c_hsmmc0_def_platdata, | ||
55 | }, | ||
56 | }; | ||
57 | |||
58 | void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) | ||
59 | { | ||
60 | struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; | ||
61 | |||
62 | set->max_width = pd->max_width; | ||
63 | |||
64 | if (pd->cfg_gpio) | ||
65 | set->cfg_gpio = pd->cfg_gpio; | ||
66 | if (pd->cfg_card) | ||
67 | set->cfg_card = pd->cfg_card; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c new file mode 100644 index 000000000000..e49bc4cd0ee6 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hsmmc1.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-hsmmc1.c | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series device definition for hsmmc device 1 | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/mmc/host.h> | ||
17 | |||
18 | #include <mach/map.h> | ||
19 | #include <plat/sdhci.h> | ||
20 | #include <plat/devs.h> | ||
21 | #include <plat/cpu.h> | ||
22 | |||
23 | #define S3C_SZ_HSMMC (0x1000) | ||
24 | |||
25 | static struct resource s3c_hsmmc1_resource[] = { | ||
26 | [0] = { | ||
27 | .start = S3C_PA_HSMMC1, | ||
28 | .end = S3C_PA_HSMMC1 + S3C_SZ_HSMMC - 1, | ||
29 | .flags = IORESOURCE_MEM, | ||
30 | }, | ||
31 | [1] = { | ||
32 | .start = IRQ_HSMMC1, | ||
33 | .end = IRQ_HSMMC1, | ||
34 | .flags = IORESOURCE_IRQ, | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | static u64 s3c_device_hsmmc1_dmamask = 0xffffffffUL; | ||
39 | |||
40 | struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = { | ||
41 | .max_width = 4, | ||
42 | .host_caps = (MMC_CAP_4_BIT_DATA | | ||
43 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | ||
44 | }; | ||
45 | |||
46 | struct platform_device s3c_device_hsmmc1 = { | ||
47 | .name = "s3c-sdhci", | ||
48 | .id = 1, | ||
49 | .num_resources = ARRAY_SIZE(s3c_hsmmc1_resource), | ||
50 | .resource = s3c_hsmmc1_resource, | ||
51 | .dev = { | ||
52 | .dma_mask = &s3c_device_hsmmc1_dmamask, | ||
53 | .coherent_dma_mask = 0xffffffffUL, | ||
54 | .platform_data = &s3c_hsmmc1_def_platdata, | ||
55 | }, | ||
56 | }; | ||
57 | |||
58 | void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) | ||
59 | { | ||
60 | struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; | ||
61 | |||
62 | set->max_width = pd->max_width; | ||
63 | |||
64 | if (pd->cfg_gpio) | ||
65 | set->cfg_gpio = pd->cfg_gpio; | ||
66 | if (pd->cfg_card) | ||
67 | set->cfg_card = pd->cfg_card; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c new file mode 100644 index 000000000000..824580bc0e06 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hsmmc2.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-hsmmc2.c | ||
2 | * | ||
3 | * Copyright (c) 2009 Samsung Electronics | ||
4 | * Copyright (c) 2009 Maurus Cuelenaere | ||
5 | * | ||
6 | * Based on arch/arm/plat-s3c/dev-hsmmc1.c | ||
7 | * original file Copyright (c) 2008 Simtec Electronics | ||
8 | * | ||
9 | * S3C series device definition for hsmmc device 2 | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/mmc/host.h> | ||
19 | |||
20 | #include <mach/map.h> | ||
21 | #include <plat/sdhci.h> | ||
22 | #include <plat/devs.h> | ||
23 | |||
24 | #define S3C_SZ_HSMMC (0x1000) | ||
25 | |||
26 | static struct resource s3c_hsmmc2_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_HSMMC2, | ||
29 | .end = S3C_PA_HSMMC2 + S3C_SZ_HSMMC - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_HSMMC2, | ||
34 | .end = IRQ_HSMMC2, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | static u64 s3c_device_hsmmc2_dmamask = 0xffffffffUL; | ||
40 | |||
41 | struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = { | ||
42 | .max_width = 4, | ||
43 | .host_caps = (MMC_CAP_4_BIT_DATA | | ||
44 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | ||
45 | }; | ||
46 | |||
47 | struct platform_device s3c_device_hsmmc2 = { | ||
48 | .name = "s3c-sdhci", | ||
49 | .id = 2, | ||
50 | .num_resources = ARRAY_SIZE(s3c_hsmmc2_resource), | ||
51 | .resource = s3c_hsmmc2_resource, | ||
52 | .dev = { | ||
53 | .dma_mask = &s3c_device_hsmmc2_dmamask, | ||
54 | .coherent_dma_mask = 0xffffffffUL, | ||
55 | .platform_data = &s3c_hsmmc2_def_platdata, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd) | ||
60 | { | ||
61 | struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; | ||
62 | |||
63 | set->max_width = pd->max_width; | ||
64 | |||
65 | if (pd->cfg_gpio) | ||
66 | set->cfg_gpio = pd->cfg_gpio; | ||
67 | if (pd->cfg_card) | ||
68 | set->cfg_card = pd->cfg_card; | ||
69 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c new file mode 100644 index 000000000000..4c761529b949 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c0.c | |||
@@ -0,0 +1,71 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-i2c0.c | ||
2 | * | ||
3 | * Copyright 2008-2009 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series device definition for i2c device 0 | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/regs-iic.h> | ||
22 | #include <plat/iic.h> | ||
23 | #include <plat/devs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | |||
26 | static struct resource s3c_i2c_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_IIC, | ||
29 | .end = S3C_PA_IIC + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC, | ||
34 | .end = IRQ_IIC, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c0 = { | ||
40 | .name = "s3c2410-i2c", | ||
41 | #ifdef CONFIG_S3C_DEV_I2C1 | ||
42 | .id = 0, | ||
43 | #else | ||
44 | .id = -1, | ||
45 | #endif | ||
46 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
47 | .resource = s3c_i2c_resource, | ||
48 | }; | ||
49 | |||
50 | static struct s3c2410_platform_i2c default_i2c_data0 __initdata = { | ||
51 | .flags = 0, | ||
52 | .slave_addr = 0x10, | ||
53 | .frequency = 100*1000, | ||
54 | .sda_delay = 100, | ||
55 | }; | ||
56 | |||
57 | void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd) | ||
58 | { | ||
59 | struct s3c2410_platform_i2c *npd; | ||
60 | |||
61 | if (!pd) | ||
62 | pd = &default_i2c_data0; | ||
63 | |||
64 | npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); | ||
65 | if (!npd) | ||
66 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
67 | else if (!npd->cfg_gpio) | ||
68 | npd->cfg_gpio = s3c_i2c0_cfg_gpio; | ||
69 | |||
70 | s3c_device_i2c0.dev.platform_data = npd; | ||
71 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c new file mode 100644 index 000000000000..d44f79110506 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c1.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-i2c1.c | ||
2 | * | ||
3 | * Copyright 2008-2009 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series device definition for i2c device 1 | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/regs-iic.h> | ||
22 | #include <plat/iic.h> | ||
23 | #include <plat/devs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | |||
26 | static struct resource s3c_i2c_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_IIC1, | ||
29 | .end = S3C_PA_IIC1 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC1, | ||
34 | .end = IRQ_IIC1, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c1 = { | ||
40 | .name = "s3c2410-i2c", | ||
41 | .id = 1, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | static struct s3c2410_platform_i2c default_i2c_data1 __initdata = { | ||
47 | .flags = 0, | ||
48 | .bus_num = 1, | ||
49 | .slave_addr = 0x10, | ||
50 | .frequency = 100*1000, | ||
51 | .sda_delay = 100, | ||
52 | }; | ||
53 | |||
54 | void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd) | ||
55 | { | ||
56 | struct s3c2410_platform_i2c *npd; | ||
57 | |||
58 | if (!pd) | ||
59 | pd = &default_i2c_data1; | ||
60 | |||
61 | npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); | ||
62 | if (!npd) | ||
63 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
64 | else if (!npd->cfg_gpio) | ||
65 | npd->cfg_gpio = s3c_i2c1_cfg_gpio; | ||
66 | |||
67 | s3c_device_i2c1.dev.platform_data = npd; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c new file mode 100644 index 000000000000..a52fb6cf618f --- /dev/null +++ b/arch/arm/plat-samsung/dev-nand.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * S3C series device definition for nand device | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | |||
12 | #include <linux/mtd/mtd.h> | ||
13 | #include <linux/mtd/partitions.h> | ||
14 | |||
15 | #include <mach/map.h> | ||
16 | #include <plat/devs.h> | ||
17 | #include <plat/nand.h> | ||
18 | |||
19 | static struct resource s3c_nand_resource[] = { | ||
20 | [0] = { | ||
21 | .start = S3C_PA_NAND, | ||
22 | .end = S3C_PA_NAND + SZ_1M, | ||
23 | .flags = IORESOURCE_MEM, | ||
24 | } | ||
25 | }; | ||
26 | |||
27 | struct platform_device s3c_device_nand = { | ||
28 | .name = "s3c2410-nand", | ||
29 | .id = -1, | ||
30 | .num_resources = ARRAY_SIZE(s3c_nand_resource), | ||
31 | .resource = s3c_nand_resource, | ||
32 | }; | ||
33 | |||
34 | EXPORT_SYMBOL(s3c_device_nand); | ||
35 | |||
36 | /** | ||
37 | * s3c_nand_copy_set() - copy nand set data | ||
38 | * @set: The new structure, directly copied from the old. | ||
39 | * | ||
40 | * Copy all the fields from the NAND set field from what is probably __initdata | ||
41 | * to new kernel memory. The code returns 0 if the copy happened correctly or | ||
42 | * an error code for the calling function to display. | ||
43 | * | ||
44 | * Note, we currently do not try and look to see if we've already copied the | ||
45 | * data in a previous set. | ||
46 | */ | ||
47 | static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set) | ||
48 | { | ||
49 | void *ptr; | ||
50 | int size; | ||
51 | |||
52 | size = sizeof(struct mtd_partition) * set->nr_partitions; | ||
53 | if (size) { | ||
54 | ptr = kmemdup(set->partitions, size, GFP_KERNEL); | ||
55 | set->partitions = ptr; | ||
56 | |||
57 | if (!ptr) | ||
58 | return -ENOMEM; | ||
59 | } | ||
60 | |||
61 | if (set->nr_map && set->nr_chips) { | ||
62 | size = sizeof(int) * set->nr_chips; | ||
63 | ptr = kmemdup(set->nr_map, size, GFP_KERNEL); | ||
64 | set->nr_map = ptr; | ||
65 | |||
66 | if (!ptr) | ||
67 | return -ENOMEM; | ||
68 | } | ||
69 | |||
70 | if (set->ecc_layout) { | ||
71 | ptr = kmemdup(set->ecc_layout, | ||
72 | sizeof(struct nand_ecclayout), GFP_KERNEL); | ||
73 | set->ecc_layout = ptr; | ||
74 | |||
75 | if (!ptr) | ||
76 | return -ENOMEM; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand) | ||
83 | { | ||
84 | struct s3c2410_platform_nand *npd; | ||
85 | int size; | ||
86 | int ret; | ||
87 | |||
88 | /* note, if we get a failure in allocation, we simply drop out of the | ||
89 | * function. If there is so little memory available at initialisation | ||
90 | * time then there is little chance the system is going to run. | ||
91 | */ | ||
92 | |||
93 | npd = kmemdup(nand, sizeof(struct s3c2410_platform_nand), GFP_KERNEL); | ||
94 | if (!npd) { | ||
95 | printk(KERN_ERR "%s: failed copying platform data\n", __func__); | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | /* now see if we need to copy any of the nand set data */ | ||
100 | |||
101 | size = sizeof(struct s3c2410_nand_set) * npd->nr_sets; | ||
102 | if (size) { | ||
103 | struct s3c2410_nand_set *from = npd->sets; | ||
104 | struct s3c2410_nand_set *to; | ||
105 | int i; | ||
106 | |||
107 | to = kmemdup(from, size, GFP_KERNEL); | ||
108 | npd->sets = to; /* set, even if we failed */ | ||
109 | |||
110 | if (!to) { | ||
111 | printk(KERN_ERR "%s: no memory for sets\n", __func__); | ||
112 | return; | ||
113 | } | ||
114 | |||
115 | for (i = 0; i < npd->nr_sets; i++) { | ||
116 | ret = s3c_nand_copy_set(to); | ||
117 | if (ret) { | ||
118 | printk(KERN_ERR "%s: failed to copy set %d\n", | ||
119 | __func__, i); | ||
120 | return; | ||
121 | } | ||
122 | to++; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | s3c_device_nand.dev.platform_data = npd; | ||
127 | } | ||
128 | |||
129 | EXPORT_SYMBOL_GPL(s3c_nand_set_platdata); | ||
diff --git a/arch/arm/plat-samsung/dev-uart.c b/arch/arm/plat-samsung/dev-uart.c new file mode 100644 index 000000000000..3776cd952450 --- /dev/null +++ b/arch/arm/plat-samsung/dev-uart.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-uart.c | ||
2 | * originally from arch/arm/plat-s3c24xx/devs.c | ||
3 | *x | ||
4 | * Copyright (c) 2004 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * Base S3C24XX platform device definitions | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | /* uart devices */ | ||
19 | |||
20 | static struct platform_device s3c24xx_uart_device0 = { | ||
21 | .id = 0, | ||
22 | }; | ||
23 | |||
24 | static struct platform_device s3c24xx_uart_device1 = { | ||
25 | .id = 1, | ||
26 | }; | ||
27 | |||
28 | static struct platform_device s3c24xx_uart_device2 = { | ||
29 | .id = 2, | ||
30 | }; | ||
31 | |||
32 | static struct platform_device s3c24xx_uart_device3 = { | ||
33 | .id = 3, | ||
34 | }; | ||
35 | |||
36 | struct platform_device *s3c24xx_uart_src[4] = { | ||
37 | &s3c24xx_uart_device0, | ||
38 | &s3c24xx_uart_device1, | ||
39 | &s3c24xx_uart_device2, | ||
40 | &s3c24xx_uart_device3, | ||
41 | }; | ||
42 | |||
43 | struct platform_device *s3c24xx_uart_devs[4] = { | ||
44 | }; | ||
diff --git a/arch/arm/plat-samsung/dev-usb-hsotg.c b/arch/arm/plat-samsung/dev-usb-hsotg.c new file mode 100644 index 000000000000..33a844ab6917 --- /dev/null +++ b/arch/arm/plat-samsung/dev-usb-hsotg.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-usb-hsotg.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series device definition for USB high-speed UDC/OtG block | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | |||
19 | #include <mach/irqs.h> | ||
20 | #include <mach/map.h> | ||
21 | |||
22 | #include <plat/devs.h> | ||
23 | |||
24 | static struct resource s3c_usb_hsotg_resources[] = { | ||
25 | [0] = { | ||
26 | .start = S3C_PA_USB_HSOTG, | ||
27 | .end = S3C_PA_USB_HSOTG + 0x10000 - 1, | ||
28 | .flags = IORESOURCE_MEM, | ||
29 | }, | ||
30 | [1] = { | ||
31 | .start = IRQ_OTG, | ||
32 | .end = IRQ_OTG, | ||
33 | .flags = IORESOURCE_IRQ, | ||
34 | }, | ||
35 | }; | ||
36 | |||
37 | static u64 s3c_hsotg_dmamask = DMA_BIT_MASK(32); | ||
38 | |||
39 | struct platform_device s3c_device_usb_hsotg = { | ||
40 | .name = "s3c-hsotg", | ||
41 | .id = -1, | ||
42 | .num_resources = ARRAY_SIZE(s3c_usb_hsotg_resources), | ||
43 | .resource = s3c_usb_hsotg_resources, | ||
44 | .dev = { | ||
45 | .dma_mask = &s3c_hsotg_dmamask, | ||
46 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
47 | }, | ||
48 | }; | ||
diff --git a/arch/arm/plat-samsung/dev-usb.c b/arch/arm/plat-samsung/dev-usb.c new file mode 100644 index 000000000000..88165657fa53 --- /dev/null +++ b/arch/arm/plat-samsung/dev-usb.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-usb.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series device definition for USB host | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/devs.h> | ||
22 | #include <plat/usb-control.h> | ||
23 | |||
24 | static struct resource s3c_usb_resource[] = { | ||
25 | [0] = { | ||
26 | .start = S3C_PA_USBHOST, | ||
27 | .end = S3C_PA_USBHOST + 0x100 - 1, | ||
28 | .flags = IORESOURCE_MEM, | ||
29 | }, | ||
30 | [1] = { | ||
31 | .start = IRQ_USBH, | ||
32 | .end = IRQ_USBH, | ||
33 | .flags = IORESOURCE_IRQ, | ||
34 | } | ||
35 | }; | ||
36 | |||
37 | static u64 s3c_device_usb_dmamask = 0xffffffffUL; | ||
38 | |||
39 | struct platform_device s3c_device_ohci = { | ||
40 | .name = "s3c2410-ohci", | ||
41 | .id = -1, | ||
42 | .num_resources = ARRAY_SIZE(s3c_usb_resource), | ||
43 | .resource = s3c_usb_resource, | ||
44 | .dev = { | ||
45 | .dma_mask = &s3c_device_usb_dmamask, | ||
46 | .coherent_dma_mask = 0xffffffffUL | ||
47 | } | ||
48 | }; | ||
49 | |||
50 | EXPORT_SYMBOL(s3c_device_ohci); | ||
51 | |||
52 | /** | ||
53 | * s3c_ohci_set_platdata - initialise OHCI device platform data | ||
54 | * @info: The platform data. | ||
55 | * | ||
56 | * This call copies the @info passed in and sets the device .platform_data | ||
57 | * field to that copy. The @info is copied so that the original can be marked | ||
58 | * __initdata. | ||
59 | */ | ||
60 | void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info) | ||
61 | { | ||
62 | struct s3c2410_hcd_info *npd; | ||
63 | |||
64 | npd = kmemdup(info, sizeof(struct s3c2410_hcd_info), GFP_KERNEL); | ||
65 | if (!npd) | ||
66 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
67 | |||
68 | s3c_device_ohci.dev.platform_data = npd; | ||
69 | } | ||
diff --git a/arch/arm/plat-samsung/dma.c b/arch/arm/plat-samsung/dma.c new file mode 100644 index 000000000000..cb459dd95459 --- /dev/null +++ b/arch/arm/plat-samsung/dma.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dma.c | ||
2 | * | ||
3 | * Copyright (c) 2003-2009 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C DMA core | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | struct s3c2410_dma_buf; | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/errno.h> | ||
19 | |||
20 | #include <mach/dma.h> | ||
21 | #include <mach/irqs.h> | ||
22 | |||
23 | /* dma channel state information */ | ||
24 | struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS]; | ||
25 | struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX]; | ||
26 | |||
27 | /* s3c_dma_lookup_channel | ||
28 | * | ||
29 | * change the dma channel number given into a real dma channel id | ||
30 | */ | ||
31 | |||
32 | struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel) | ||
33 | { | ||
34 | if (channel & DMACH_LOW_LEVEL) | ||
35 | return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL]; | ||
36 | else | ||
37 | return s3c_dma_chan_map[channel]; | ||
38 | } | ||
39 | |||
40 | /* do we need to protect the settings of the fields from | ||
41 | * irq? | ||
42 | */ | ||
43 | |||
44 | int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn) | ||
45 | { | ||
46 | struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); | ||
47 | |||
48 | if (chan == NULL) | ||
49 | return -EINVAL; | ||
50 | |||
51 | pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn); | ||
52 | |||
53 | chan->op_fn = rtn; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL(s3c2410_dma_set_opfn); | ||
58 | |||
59 | int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn) | ||
60 | { | ||
61 | struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); | ||
62 | |||
63 | if (chan == NULL) | ||
64 | return -EINVAL; | ||
65 | |||
66 | pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn); | ||
67 | |||
68 | chan->callback_fn = rtn; | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); | ||
73 | |||
74 | int s3c2410_dma_setflags(unsigned int channel, unsigned int flags) | ||
75 | { | ||
76 | struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); | ||
77 | |||
78 | if (chan == NULL) | ||
79 | return -EINVAL; | ||
80 | |||
81 | chan->flags = flags; | ||
82 | return 0; | ||
83 | } | ||
84 | EXPORT_SYMBOL(s3c2410_dma_setflags); | ||
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c new file mode 100644 index 000000000000..44a84e896546 --- /dev/null +++ b/arch/arm/plat-samsung/gpio-config.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* linux/arch/arm/plat-s3c/gpio-config.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * S3C series GPIO configuration core | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
20 | #include <plat/gpio-core.h> | ||
21 | #include <plat/gpio-cfg.h> | ||
22 | #include <plat/gpio-cfg-helpers.h> | ||
23 | |||
24 | int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) | ||
25 | { | ||
26 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
27 | unsigned long flags; | ||
28 | int offset; | ||
29 | int ret; | ||
30 | |||
31 | if (!chip) | ||
32 | return -EINVAL; | ||
33 | |||
34 | offset = pin - chip->chip.base; | ||
35 | |||
36 | local_irq_save(flags); | ||
37 | ret = s3c_gpio_do_setcfg(chip, offset, config); | ||
38 | local_irq_restore(flags); | ||
39 | |||
40 | return ret; | ||
41 | } | ||
42 | EXPORT_SYMBOL(s3c_gpio_cfgpin); | ||
43 | |||
44 | int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) | ||
45 | { | ||
46 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
47 | unsigned long flags; | ||
48 | int offset, ret; | ||
49 | |||
50 | if (!chip) | ||
51 | return -EINVAL; | ||
52 | |||
53 | offset = pin - chip->chip.base; | ||
54 | |||
55 | local_irq_save(flags); | ||
56 | ret = s3c_gpio_do_setpull(chip, offset, pull); | ||
57 | local_irq_restore(flags); | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | EXPORT_SYMBOL(s3c_gpio_setpull); | ||
62 | |||
63 | #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX | ||
64 | int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip, | ||
65 | unsigned int off, unsigned int cfg) | ||
66 | { | ||
67 | void __iomem *reg = chip->base; | ||
68 | unsigned int shift = off; | ||
69 | u32 con; | ||
70 | |||
71 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
72 | cfg &= 0xf; | ||
73 | |||
74 | /* Map output to 0, and SFN2 to 1 */ | ||
75 | cfg -= 1; | ||
76 | if (cfg > 1) | ||
77 | return -EINVAL; | ||
78 | |||
79 | cfg <<= shift; | ||
80 | } | ||
81 | |||
82 | con = __raw_readl(reg); | ||
83 | con &= ~(0x1 << shift); | ||
84 | con |= cfg; | ||
85 | __raw_writel(con, reg); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
91 | unsigned int off, unsigned int cfg) | ||
92 | { | ||
93 | void __iomem *reg = chip->base; | ||
94 | unsigned int shift = off * 2; | ||
95 | u32 con; | ||
96 | |||
97 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
98 | cfg &= 0xf; | ||
99 | if (cfg > 3) | ||
100 | return -EINVAL; | ||
101 | |||
102 | cfg <<= shift; | ||
103 | } | ||
104 | |||
105 | con = __raw_readl(reg); | ||
106 | con &= ~(0x3 << shift); | ||
107 | con |= cfg; | ||
108 | __raw_writel(con, reg); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX | ||
115 | int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
116 | unsigned int off, unsigned int cfg) | ||
117 | { | ||
118 | void __iomem *reg = chip->base; | ||
119 | unsigned int shift = (off & 7) * 4; | ||
120 | u32 con; | ||
121 | |||
122 | if (off < 8 && chip->chip.ngpio > 8) | ||
123 | reg -= 4; | ||
124 | |||
125 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
126 | cfg &= 0xf; | ||
127 | cfg <<= shift; | ||
128 | } | ||
129 | |||
130 | con = __raw_readl(reg); | ||
131 | con &= ~(0xf << shift); | ||
132 | con |= cfg; | ||
133 | __raw_writel(con, reg); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */ | ||
138 | |||
139 | #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN | ||
140 | int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip, | ||
141 | unsigned int off, s3c_gpio_pull_t pull) | ||
142 | { | ||
143 | void __iomem *reg = chip->base + 0x08; | ||
144 | int shift = off * 2; | ||
145 | u32 pup; | ||
146 | |||
147 | pup = __raw_readl(reg); | ||
148 | pup &= ~(3 << shift); | ||
149 | pup |= pull << shift; | ||
150 | __raw_writel(pup, reg); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, | ||
156 | unsigned int off) | ||
157 | { | ||
158 | void __iomem *reg = chip->base + 0x08; | ||
159 | int shift = off * 2; | ||
160 | u32 pup = __raw_readl(reg); | ||
161 | |||
162 | pup >>= shift; | ||
163 | pup &= 0x3; | ||
164 | return (__force s3c_gpio_pull_t)pup; | ||
165 | } | ||
166 | #endif | ||
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c new file mode 100644 index 000000000000..28d2ab8a08db --- /dev/null +++ b/arch/arm/plat-samsung/gpio.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* linux/arch/arm/plat-s3c/gpio.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series GPIO core | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/gpio.h> | ||
18 | |||
19 | #include <plat/gpio-core.h> | ||
20 | |||
21 | #ifdef CONFIG_S3C_GPIO_TRACK | ||
22 | struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; | ||
23 | |||
24 | static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip) | ||
25 | { | ||
26 | unsigned int gpn; | ||
27 | int i; | ||
28 | |||
29 | gpn = chip->chip.base; | ||
30 | for (i = 0; i < chip->chip.ngpio; i++, gpn++) { | ||
31 | BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios)); | ||
32 | s3c_gpios[gpn] = chip; | ||
33 | } | ||
34 | } | ||
35 | #endif /* CONFIG_S3C_GPIO_TRACK */ | ||
36 | |||
37 | /* Default routines for controlling GPIO, based on the original S3C24XX | ||
38 | * GPIO functions which deal with the case where each gpio bank of the | ||
39 | * chip is as following: | ||
40 | * | ||
41 | * base + 0x00: Control register, 2 bits per gpio | ||
42 | * gpio n: 2 bits starting at (2*n) | ||
43 | * 00 = input, 01 = output, others mean special-function | ||
44 | * base + 0x04: Data register, 1 bit per gpio | ||
45 | * bit n: data bit n | ||
46 | */ | ||
47 | |||
48 | static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset) | ||
49 | { | ||
50 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
51 | void __iomem *base = ourchip->base; | ||
52 | unsigned long flags; | ||
53 | unsigned long con; | ||
54 | |||
55 | local_irq_save(flags); | ||
56 | |||
57 | con = __raw_readl(base + 0x00); | ||
58 | con &= ~(3 << (offset * 2)); | ||
59 | |||
60 | __raw_writel(con, base + 0x00); | ||
61 | |||
62 | local_irq_restore(flags); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int s3c_gpiolib_output(struct gpio_chip *chip, | ||
67 | unsigned offset, int value) | ||
68 | { | ||
69 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
70 | void __iomem *base = ourchip->base; | ||
71 | unsigned long flags; | ||
72 | unsigned long dat; | ||
73 | unsigned long con; | ||
74 | |||
75 | local_irq_save(flags); | ||
76 | |||
77 | dat = __raw_readl(base + 0x04); | ||
78 | dat &= ~(1 << offset); | ||
79 | if (value) | ||
80 | dat |= 1 << offset; | ||
81 | __raw_writel(dat, base + 0x04); | ||
82 | |||
83 | con = __raw_readl(base + 0x00); | ||
84 | con &= ~(3 << (offset * 2)); | ||
85 | con |= 1 << (offset * 2); | ||
86 | |||
87 | __raw_writel(con, base + 0x00); | ||
88 | __raw_writel(dat, base + 0x04); | ||
89 | |||
90 | local_irq_restore(flags); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static void s3c_gpiolib_set(struct gpio_chip *chip, | ||
95 | unsigned offset, int value) | ||
96 | { | ||
97 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
98 | void __iomem *base = ourchip->base; | ||
99 | unsigned long flags; | ||
100 | unsigned long dat; | ||
101 | |||
102 | local_irq_save(flags); | ||
103 | |||
104 | dat = __raw_readl(base + 0x04); | ||
105 | dat &= ~(1 << offset); | ||
106 | if (value) | ||
107 | dat |= 1 << offset; | ||
108 | __raw_writel(dat, base + 0x04); | ||
109 | |||
110 | local_irq_restore(flags); | ||
111 | } | ||
112 | |||
113 | static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) | ||
114 | { | ||
115 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
116 | unsigned long val; | ||
117 | |||
118 | val = __raw_readl(ourchip->base + 0x04); | ||
119 | val >>= offset; | ||
120 | val &= 1; | ||
121 | |||
122 | return val; | ||
123 | } | ||
124 | |||
125 | __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) | ||
126 | { | ||
127 | struct gpio_chip *gc = &chip->chip; | ||
128 | int ret; | ||
129 | |||
130 | BUG_ON(!chip->base); | ||
131 | BUG_ON(!gc->label); | ||
132 | BUG_ON(!gc->ngpio); | ||
133 | |||
134 | if (!gc->direction_input) | ||
135 | gc->direction_input = s3c_gpiolib_input; | ||
136 | if (!gc->direction_output) | ||
137 | gc->direction_output = s3c_gpiolib_output; | ||
138 | if (!gc->set) | ||
139 | gc->set = s3c_gpiolib_set; | ||
140 | if (!gc->get) | ||
141 | gc->get = s3c_gpiolib_get; | ||
142 | |||
143 | #ifdef CONFIG_PM | ||
144 | if (chip->pm != NULL) { | ||
145 | if (!chip->pm->save || !chip->pm->resume) | ||
146 | printk(KERN_ERR "gpio: %s has missing PM functions\n", | ||
147 | gc->label); | ||
148 | } else | ||
149 | printk(KERN_ERR "gpio: %s has no PM function\n", gc->label); | ||
150 | #endif | ||
151 | |||
152 | /* gpiochip_add() prints own failure message on error. */ | ||
153 | ret = gpiochip_add(gc); | ||
154 | if (ret >= 0) | ||
155 | s3c_gpiolib_track(chip); | ||
156 | } | ||
diff --git a/arch/arm/plat-samsung/gpiolib.c b/arch/arm/plat-samsung/gpiolib.c new file mode 100644 index 000000000000..8a8ba8bc1d96 --- /dev/null +++ b/arch/arm/plat-samsung/gpiolib.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* arch/arm/plat-samsung/gpiolib.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * Copyright (c) 2009 Samsung Electronics Co., Ltd. | ||
9 | * http://www.samsung.com/ | ||
10 | * | ||
11 | * SAMSUNG - GPIOlib support | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <mach/gpio.h> | ||
22 | #include <plat/gpio-core.h> | ||
23 | #include <plat/gpio-cfg.h> | ||
24 | #include <plat/gpio-cfg-helpers.h> | ||
25 | |||
26 | #ifndef DEBUG_GPIO | ||
27 | #define gpio_dbg(x...) do { } while (0) | ||
28 | #else | ||
29 | #define gpio_dbg(x...) printk(KERN_DEBUG x) | ||
30 | #endif | ||
31 | |||
32 | /* The samsung_gpiolib_4bit routines are to control the gpio banks where | ||
33 | * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the | ||
34 | * following example: | ||
35 | * | ||
36 | * base + 0x00: Control register, 4 bits per gpio | ||
37 | * gpio n: 4 bits starting at (4*n) | ||
38 | * 0000 = input, 0001 = output, others mean special-function | ||
39 | * base + 0x04: Data register, 1 bit per gpio | ||
40 | * bit n: data bit n | ||
41 | * | ||
42 | * Note, since the data register is one bit per gpio and is at base + 0x4 | ||
43 | * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of | ||
44 | * the output. | ||
45 | */ | ||
46 | |||
47 | static int samsung_gpiolib_4bit_input(struct gpio_chip *chip, | ||
48 | unsigned int offset) | ||
49 | { | ||
50 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
51 | void __iomem *base = ourchip->base; | ||
52 | unsigned long con; | ||
53 | |||
54 | con = __raw_readl(base + GPIOCON_OFF); | ||
55 | con &= ~(0xf << con_4bit_shift(offset)); | ||
56 | __raw_writel(con, base + GPIOCON_OFF); | ||
57 | |||
58 | gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int samsung_gpiolib_4bit_output(struct gpio_chip *chip, | ||
64 | unsigned int offset, int value) | ||
65 | { | ||
66 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
67 | void __iomem *base = ourchip->base; | ||
68 | unsigned long con; | ||
69 | unsigned long dat; | ||
70 | |||
71 | con = __raw_readl(base + GPIOCON_OFF); | ||
72 | con &= ~(0xf << con_4bit_shift(offset)); | ||
73 | con |= 0x1 << con_4bit_shift(offset); | ||
74 | |||
75 | dat = __raw_readl(base + GPIODAT_OFF); | ||
76 | |||
77 | if (value) | ||
78 | dat |= 1 << offset; | ||
79 | else | ||
80 | dat &= ~(1 << offset); | ||
81 | |||
82 | __raw_writel(dat, base + GPIODAT_OFF); | ||
83 | __raw_writel(con, base + GPIOCON_OFF); | ||
84 | __raw_writel(dat, base + GPIODAT_OFF); | ||
85 | |||
86 | gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | /* The next set of routines are for the case where the GPIO configuration | ||
92 | * registers are 4 bits per GPIO but there is more than one register (the | ||
93 | * bank has more than 8 GPIOs. | ||
94 | * | ||
95 | * This case is the similar to the 4 bit case, but the registers are as | ||
96 | * follows: | ||
97 | * | ||
98 | * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs) | ||
99 | * gpio n: 4 bits starting at (4*n) | ||
100 | * 0000 = input, 0001 = output, others mean special-function | ||
101 | * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs) | ||
102 | * gpio n: 4 bits starting at (4*n) | ||
103 | * 0000 = input, 0001 = output, others mean special-function | ||
104 | * base + 0x08: Data register, 1 bit per gpio | ||
105 | * bit n: data bit n | ||
106 | * | ||
107 | * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we | ||
108 | * store the 'base + 0x4' address so that these routines see the data | ||
109 | * register at ourchip->base + 0x04. | ||
110 | */ | ||
111 | |||
112 | static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip, | ||
113 | unsigned int offset) | ||
114 | { | ||
115 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
116 | void __iomem *base = ourchip->base; | ||
117 | void __iomem *regcon = base; | ||
118 | unsigned long con; | ||
119 | |||
120 | if (offset > 7) | ||
121 | offset -= 8; | ||
122 | else | ||
123 | regcon -= 4; | ||
124 | |||
125 | con = __raw_readl(regcon); | ||
126 | con &= ~(0xf << con_4bit_shift(offset)); | ||
127 | __raw_writel(con, regcon); | ||
128 | |||
129 | gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip, | ||
135 | unsigned int offset, int value) | ||
136 | { | ||
137 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
138 | void __iomem *base = ourchip->base; | ||
139 | void __iomem *regcon = base; | ||
140 | unsigned long con; | ||
141 | unsigned long dat; | ||
142 | unsigned con_offset = offset; | ||
143 | |||
144 | if (con_offset > 7) | ||
145 | con_offset -= 8; | ||
146 | else | ||
147 | regcon -= 4; | ||
148 | |||
149 | con = __raw_readl(regcon); | ||
150 | con &= ~(0xf << con_4bit_shift(con_offset)); | ||
151 | con |= 0x1 << con_4bit_shift(con_offset); | ||
152 | |||
153 | dat = __raw_readl(base + GPIODAT_OFF); | ||
154 | |||
155 | if (value) | ||
156 | dat |= 1 << offset; | ||
157 | else | ||
158 | dat &= ~(1 << offset); | ||
159 | |||
160 | __raw_writel(dat, base + GPIODAT_OFF); | ||
161 | __raw_writel(con, regcon); | ||
162 | __raw_writel(dat, base + GPIODAT_OFF); | ||
163 | |||
164 | gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip) | ||
170 | { | ||
171 | chip->chip.direction_input = samsung_gpiolib_4bit_input; | ||
172 | chip->chip.direction_output = samsung_gpiolib_4bit_output; | ||
173 | chip->pm = __gpio_pm(&s3c_gpio_pm_4bit); | ||
174 | } | ||
175 | |||
176 | void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip) | ||
177 | { | ||
178 | chip->chip.direction_input = samsung_gpiolib_4bit2_input; | ||
179 | chip->chip.direction_output = samsung_gpiolib_4bit2_output; | ||
180 | chip->pm = __gpio_pm(&s3c_gpio_pm_4bit); | ||
181 | } | ||
182 | |||
183 | void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip, | ||
184 | int nr_chips) | ||
185 | { | ||
186 | for (; nr_chips > 0; nr_chips--, chip++) { | ||
187 | samsung_gpiolib_add_4bit(chip); | ||
188 | s3c_gpiolib_add(chip); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, | ||
193 | int nr_chips) | ||
194 | { | ||
195 | for (; nr_chips > 0; nr_chips--, chip++) { | ||
196 | samsung_gpiolib_add_4bit2(chip); | ||
197 | s3c_gpiolib_add(chip); | ||
198 | } | ||
199 | } | ||
diff --git a/arch/arm/plat-samsung/include/plat/adc.h b/arch/arm/plat-samsung/include/plat/adc.h new file mode 100644 index 000000000000..e8382c7be10b --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/adc.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/adc.h | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * http://armlinux.simnte.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C ADC driver information | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASM_PLAT_ADC_H | ||
15 | #define __ASM_PLAT_ADC_H __FILE__ | ||
16 | |||
17 | struct s3c_adc_client; | ||
18 | |||
19 | extern int s3c_adc_start(struct s3c_adc_client *client, | ||
20 | unsigned int channel, unsigned int nr_samples); | ||
21 | |||
22 | extern int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch); | ||
23 | |||
24 | extern struct s3c_adc_client * | ||
25 | s3c_adc_register(struct platform_device *pdev, | ||
26 | void (*select)(struct s3c_adc_client *client, | ||
27 | unsigned selected), | ||
28 | void (*conv)(struct s3c_adc_client *client, | ||
29 | unsigned d0, unsigned d1, | ||
30 | unsigned *samples_left), | ||
31 | unsigned int is_ts); | ||
32 | |||
33 | extern void s3c_adc_release(struct s3c_adc_client *client); | ||
34 | |||
35 | #endif /* __ASM_PLAT_ADC_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h new file mode 100644 index 000000000000..e32f9edfd4b7 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/audio.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/audio.h | ||
2 | * | ||
3 | * Copyright (c) 2009 Samsung Electronics Co. Ltd | ||
4 | * Author: Jaswinder Singh <jassi.brar@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | /* The machine init code calls s3c*_ac97_setup_gpio with | ||
12 | * one of these defines in order to select appropriate bank | ||
13 | * of GPIO for AC97 pins | ||
14 | */ | ||
15 | #define S3C64XX_AC97_GPD 0 | ||
16 | #define S3C64XX_AC97_GPE 1 | ||
17 | extern void s3c64xx_ac97_setup_gpio(int); | ||
18 | |||
19 | /** | ||
20 | * struct s3c_audio_pdata - common platform data for audio device drivers | ||
21 | * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode | ||
22 | */ | ||
23 | struct s3c_audio_pdata { | ||
24 | int (*cfg_gpio)(struct platform_device *); | ||
25 | }; | ||
diff --git a/arch/arm/plat-samsung/include/plat/clock-clksrc.h b/arch/arm/plat-samsung/include/plat/clock-clksrc.h new file mode 100644 index 000000000000..50a8ca7c3760 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/clock-clksrc.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/clock-clksrc.h | ||
2 | * | ||
3 | * Parts taken from arch/arm/plat-s3c64xx/clock.c | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * Copyright 2009 Ben Dooks <ben-linux@fluff.org> | ||
10 | * Copyright 2009 Harald Welte | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * struct clksrc_sources - list of sources for a given clock | ||
19 | * @sources: array of pointers to clocks | ||
20 | * @nr_sources: The size of @sources | ||
21 | */ | ||
22 | struct clksrc_sources { | ||
23 | unsigned int nr_sources; | ||
24 | struct clk **sources; | ||
25 | }; | ||
26 | |||
27 | /** | ||
28 | * struct clksrc_reg - register definition for clock control bits | ||
29 | * @reg: pointer to the register in virtual memory. | ||
30 | * @shift: the shift in bits to where the bitfield is. | ||
31 | * @size: the size in bits of the bitfield. | ||
32 | * | ||
33 | * This specifies the size and position of the bits we are interested | ||
34 | * in within the register specified by @reg. | ||
35 | */ | ||
36 | struct clksrc_reg { | ||
37 | void __iomem *reg; | ||
38 | unsigned short shift; | ||
39 | unsigned short size; | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * struct clksrc_clk - class of clock for newer style samsung devices. | ||
44 | * @clk: the standard clock representation | ||
45 | * @sources: the sources for this clock | ||
46 | * @reg_src: the register definition for selecting the clock's source | ||
47 | * @reg_div: the register definition for the clock's output divisor | ||
48 | * | ||
49 | * This clock implements the features required by the newer SoCs where | ||
50 | * the standard clock block provides an input mux and a post-mux divisor | ||
51 | * to provide the periperhal's clock. | ||
52 | * | ||
53 | * The array of @sources provides the mapping of mux position to the | ||
54 | * clock, and @reg_src shows the code where to modify to change the mux | ||
55 | * position. The @reg_div defines how to change the divider settings on | ||
56 | * the output. | ||
57 | */ | ||
58 | struct clksrc_clk { | ||
59 | struct clk clk; | ||
60 | struct clksrc_sources *sources; | ||
61 | |||
62 | struct clksrc_reg reg_src; | ||
63 | struct clksrc_reg reg_div; | ||
64 | }; | ||
65 | |||
66 | /** | ||
67 | * s3c_set_clksrc() - setup the clock from the register settings | ||
68 | * @clk: The clock to setup. | ||
69 | * @announce: true to announce the setting to printk(). | ||
70 | * | ||
71 | * Setup the clock from the current register settings, for when the | ||
72 | * kernel boots or if it is resuming from a possibly unknown state. | ||
73 | */ | ||
74 | extern void s3c_set_clksrc(struct clksrc_clk *clk, bool announce); | ||
75 | |||
76 | /** | ||
77 | * s3c_register_clksrc() register clocks from an array of clksrc clocks | ||
78 | * @srcs: The array of clocks to register | ||
79 | * @size: The size of the @srcs array. | ||
80 | * | ||
81 | * Initialise and register the array of clocks described by @srcs. | ||
82 | */ | ||
83 | extern void s3c_register_clksrc(struct clksrc_clk *srcs, int size); | ||
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h new file mode 100644 index 000000000000..60b62692ac7a --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/clock.h | |||
@@ -0,0 +1,115 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/clock.h | ||
2 | * | ||
3 | * Copyright (c) 2004-2005 Simtec Electronics | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
5 | * Written by Ben Dooks, <ben@simtec.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/spinlock.h> | ||
13 | |||
14 | struct clk; | ||
15 | |||
16 | /** | ||
17 | * struct clk_ops - standard clock operations | ||
18 | * @set_rate: set the clock rate, see clk_set_rate(). | ||
19 | * @get_rate: get the clock rate, see clk_get_rate(). | ||
20 | * @round_rate: round a given clock rate, see clk_round_rate(). | ||
21 | * @set_parent: set the clock's parent, see clk_set_parent(). | ||
22 | * | ||
23 | * Group the common clock implementations together so that we | ||
24 | * don't have to keep setting the same fiels again. We leave | ||
25 | * enable in struct clk. | ||
26 | * | ||
27 | * Adding an extra layer of indirection into the process should | ||
28 | * not be a problem as it is unlikely these operations are going | ||
29 | * to need to be called quickly. | ||
30 | */ | ||
31 | struct clk_ops { | ||
32 | int (*set_rate)(struct clk *c, unsigned long rate); | ||
33 | unsigned long (*get_rate)(struct clk *c); | ||
34 | unsigned long (*round_rate)(struct clk *c, unsigned long rate); | ||
35 | int (*set_parent)(struct clk *c, struct clk *parent); | ||
36 | }; | ||
37 | |||
38 | struct clk { | ||
39 | struct list_head list; | ||
40 | struct module *owner; | ||
41 | struct clk *parent; | ||
42 | const char *name; | ||
43 | int id; | ||
44 | int usage; | ||
45 | unsigned long rate; | ||
46 | unsigned long ctrlbit; | ||
47 | |||
48 | struct clk_ops *ops; | ||
49 | int (*enable)(struct clk *, int enable); | ||
50 | }; | ||
51 | |||
52 | /* other clocks which may be registered by board support */ | ||
53 | |||
54 | extern struct clk s3c24xx_dclk0; | ||
55 | extern struct clk s3c24xx_dclk1; | ||
56 | extern struct clk s3c24xx_clkout0; | ||
57 | extern struct clk s3c24xx_clkout1; | ||
58 | extern struct clk s3c24xx_uclk; | ||
59 | |||
60 | extern struct clk clk_usb_bus; | ||
61 | |||
62 | /* core clock support */ | ||
63 | |||
64 | extern struct clk clk_f; | ||
65 | extern struct clk clk_h; | ||
66 | extern struct clk clk_p; | ||
67 | extern struct clk clk_mpll; | ||
68 | extern struct clk clk_upll; | ||
69 | extern struct clk clk_epll; | ||
70 | extern struct clk clk_xtal; | ||
71 | extern struct clk clk_ext; | ||
72 | |||
73 | /* S3C64XX specific clocks */ | ||
74 | extern struct clk clk_h2; | ||
75 | extern struct clk clk_27m; | ||
76 | extern struct clk clk_48m; | ||
77 | |||
78 | extern int clk_default_setrate(struct clk *clk, unsigned long rate); | ||
79 | extern struct clk_ops clk_ops_def_setrate; | ||
80 | |||
81 | /* exports for arch/arm/mach-s3c2410 | ||
82 | * | ||
83 | * Please DO NOT use these outside of arch/arm/mach-s3c2410 | ||
84 | */ | ||
85 | |||
86 | extern spinlock_t clocks_lock; | ||
87 | |||
88 | extern int s3c2410_clkcon_enable(struct clk *clk, int enable); | ||
89 | |||
90 | extern int s3c24xx_register_clock(struct clk *clk); | ||
91 | extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks); | ||
92 | |||
93 | extern void s3c_register_clocks(struct clk *clk, int nr_clks); | ||
94 | |||
95 | extern int s3c24xx_register_baseclocks(unsigned long xtal); | ||
96 | |||
97 | extern void s5p_register_clocks(unsigned long xtal_freq); | ||
98 | |||
99 | extern void s3c24xx_setup_clocks(unsigned long fclk, | ||
100 | unsigned long hclk, | ||
101 | unsigned long pclk); | ||
102 | |||
103 | extern void s3c2410_setup_clocks(void); | ||
104 | extern void s3c2412_setup_clocks(void); | ||
105 | extern void s3c244x_setup_clocks(void); | ||
106 | extern void s3c2443_setup_clocks(void); | ||
107 | |||
108 | /* S3C64XX specific functions and clocks */ | ||
109 | |||
110 | extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); | ||
111 | |||
112 | /* Init for pwm clock code */ | ||
113 | |||
114 | extern void s3c_pwmclk_init(void); | ||
115 | |||
diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq.h b/arch/arm/plat-samsung/include/plat/cpu-freq.h new file mode 100644 index 000000000000..80c4a809c721 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/cpu-freq.h | |||
@@ -0,0 +1,145 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/cpu-freq.h | ||
2 | * | ||
3 | * Copyright (c) 2006-2007 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C CPU frequency scaling support - driver and board | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/cpufreq.h> | ||
15 | |||
16 | struct s3c_cpufreq_info; | ||
17 | struct s3c_cpufreq_board; | ||
18 | struct s3c_iotimings; | ||
19 | |||
20 | /** | ||
21 | * struct s3c_freq - frequency information (mainly for core drivers) | ||
22 | * @fclk: The FCLK frequency in Hz. | ||
23 | * @armclk: The ARMCLK frequency in Hz. | ||
24 | * @hclk_tns: HCLK cycle time in 10ths of nano-seconds. | ||
25 | * @hclk: The HCLK frequency in Hz. | ||
26 | * @pclk: The PCLK frequency in Hz. | ||
27 | * | ||
28 | * This contains the frequency information about the current configuration | ||
29 | * mainly for the core drivers to ensure we do not end up passing about | ||
30 | * a large number of parameters. | ||
31 | * | ||
32 | * The @hclk_tns field is a useful cache for the parts of the drivers that | ||
33 | * need to calculate IO timings and suchlike. | ||
34 | */ | ||
35 | struct s3c_freq { | ||
36 | unsigned long fclk; | ||
37 | unsigned long armclk; | ||
38 | unsigned long hclk_tns; /* in 10ths of ns */ | ||
39 | unsigned long hclk; | ||
40 | unsigned long pclk; | ||
41 | }; | ||
42 | |||
43 | /** | ||
44 | * struct s3c_cpufreq_freqs - s3c cpufreq notification information. | ||
45 | * @freqs: The cpufreq setting information. | ||
46 | * @old: The old clock settings. | ||
47 | * @new: The new clock settings. | ||
48 | * @pll_changing: Set if the PLL is changing. | ||
49 | * | ||
50 | * Wrapper 'struct cpufreq_freqs' so that any drivers receiving the | ||
51 | * notification can use this information that is not provided by just | ||
52 | * having the core frequency alone. | ||
53 | * | ||
54 | * The pll_changing flag is used to indicate if the PLL itself is | ||
55 | * being set during this change. This is important as the clocks | ||
56 | * will temporarily be set to the XTAL clock during this time, so | ||
57 | * drivers may want to close down their output during this time. | ||
58 | * | ||
59 | * Note, this is not being used by any current drivers and therefore | ||
60 | * may be removed in the future. | ||
61 | */ | ||
62 | struct s3c_cpufreq_freqs { | ||
63 | struct cpufreq_freqs freqs; | ||
64 | struct s3c_freq old; | ||
65 | struct s3c_freq new; | ||
66 | |||
67 | unsigned int pll_changing:1; | ||
68 | }; | ||
69 | |||
70 | #define to_s3c_cpufreq(_cf) container_of(_cf, struct s3c_cpufreq_freqs, freqs) | ||
71 | |||
72 | /** | ||
73 | * struct s3c_clkdivs - clock divisor information | ||
74 | * @p_divisor: Divisor from FCLK to PCLK. | ||
75 | * @h_divisor: Divisor from FCLK to HCLK. | ||
76 | * @arm_divisor: Divisor from FCLK to ARMCLK (not all CPUs). | ||
77 | * @dvs: Non-zero if using DVS mode for ARMCLK. | ||
78 | * | ||
79 | * Divisor settings for the core clocks. | ||
80 | */ | ||
81 | struct s3c_clkdivs { | ||
82 | int p_divisor; | ||
83 | int h_divisor; | ||
84 | int arm_divisor; | ||
85 | unsigned char dvs; | ||
86 | }; | ||
87 | |||
88 | #define PLLVAL(_m, _p, _s) (((_m) << 12) | ((_p) << 4) | (_s)) | ||
89 | |||
90 | /** | ||
91 | * struct s3c_pllval - PLL value entry. | ||
92 | * @freq: The frequency for this entry in Hz. | ||
93 | * @pll_reg: The PLL register setting for this PLL value. | ||
94 | */ | ||
95 | struct s3c_pllval { | ||
96 | unsigned long freq; | ||
97 | unsigned long pll_reg; | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * struct s3c_cpufreq_board - per-board cpu frequency informatin | ||
102 | * @refresh: The SDRAM refresh period in nanoseconds. | ||
103 | * @auto_io: Set if the IO timing settings should be generated from the | ||
104 | * initialisation time hardware registers. | ||
105 | * @need_io: Set if the board has external IO on any of the chipselect | ||
106 | * lines that will require the hardware timing registers to be | ||
107 | * updated on a clock change. | ||
108 | * @max: The maxium frequency limits for the system. Any field that | ||
109 | * is left at zero will use the CPU's settings. | ||
110 | * | ||
111 | * This contains the board specific settings that affect how the CPU | ||
112 | * drivers chose settings. These include the memory refresh and IO | ||
113 | * timing information. | ||
114 | * | ||
115 | * Registration depends on the driver being used, the ARMCLK only | ||
116 | * implementation does not currently need this but the older style | ||
117 | * driver requires this to be available. | ||
118 | */ | ||
119 | struct s3c_cpufreq_board { | ||
120 | unsigned int refresh; | ||
121 | unsigned int auto_io:1; /* automatically init io timings. */ | ||
122 | unsigned int need_io:1; /* set if needs io timing support. */ | ||
123 | |||
124 | /* any non-zero field in here is taken as an upper limit. */ | ||
125 | struct s3c_freq max; /* frequency limits */ | ||
126 | }; | ||
127 | |||
128 | /* Things depending on frequency scaling. */ | ||
129 | #ifdef CONFIG_CPU_FREQ_S3C | ||
130 | #define __init_or_cpufreq | ||
131 | #else | ||
132 | #define __init_or_cpufreq __init | ||
133 | #endif | ||
134 | |||
135 | /* Board functions */ | ||
136 | |||
137 | #ifdef CONFIG_CPU_FREQ_S3C | ||
138 | extern int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board); | ||
139 | #else | ||
140 | |||
141 | static inline int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) | ||
142 | { | ||
143 | return 0; | ||
144 | } | ||
145 | #endif /* CONFIG_CPU_FREQ_S3C */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h new file mode 100644 index 000000000000..d316b4a579f4 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/cpu.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/cpu.h | ||
2 | * | ||
3 | * Copyright (c) 2004-2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for S3C24XX CPU support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | /* todo - fix when rmk changes iodescs to use `void __iomem *` */ | ||
14 | |||
15 | #ifndef __SAMSUNG_PLAT_CPU_H | ||
16 | #define __SAMSUNG_PLAT_CPU_H | ||
17 | |||
18 | #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } | ||
19 | |||
20 | #ifndef MHZ | ||
21 | #define MHZ (1000*1000) | ||
22 | #endif | ||
23 | |||
24 | #define print_mhz(m) ((m) / MHZ), (((m) / 1000) % 1000) | ||
25 | |||
26 | /* forward declaration */ | ||
27 | struct s3c24xx_uart_resources; | ||
28 | struct platform_device; | ||
29 | struct s3c2410_uartcfg; | ||
30 | struct map_desc; | ||
31 | |||
32 | /* per-cpu initialisation function table. */ | ||
33 | |||
34 | struct cpu_table { | ||
35 | unsigned long idcode; | ||
36 | unsigned long idmask; | ||
37 | void (*map_io)(void); | ||
38 | void (*init_uarts)(struct s3c2410_uartcfg *cfg, int no); | ||
39 | void (*init_clocks)(int xtal); | ||
40 | int (*init)(void); | ||
41 | const char *name; | ||
42 | }; | ||
43 | |||
44 | extern void s3c_init_cpu(unsigned long idcode, | ||
45 | struct cpu_table *cpus, unsigned int cputab_size); | ||
46 | |||
47 | /* core initialisation functions */ | ||
48 | |||
49 | extern void s3c24xx_init_irq(void); | ||
50 | extern void s3c64xx_init_irq(u32 vic0, u32 vic1); | ||
51 | extern void s5p_init_irq(u32 *vic, u32 num_vic); | ||
52 | |||
53 | extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); | ||
54 | extern void s3c64xx_init_io(struct map_desc *mach_desc, int size); | ||
55 | extern void s5p_init_io(struct map_desc *mach_desc, | ||
56 | int size, void __iomem *cpuid_addr); | ||
57 | |||
58 | extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
59 | |||
60 | extern void s3c24xx_init_clocks(int xtal); | ||
61 | |||
62 | extern void s3c24xx_init_uartdevs(char *name, | ||
63 | struct s3c24xx_uart_resources *res, | ||
64 | struct s3c2410_uartcfg *cfg, int no); | ||
65 | |||
66 | /* timer for 2410/2440 */ | ||
67 | |||
68 | struct sys_timer; | ||
69 | extern struct sys_timer s3c24xx_timer; | ||
70 | |||
71 | /* system device classes */ | ||
72 | |||
73 | extern struct sysdev_class s3c2410_sysclass; | ||
74 | extern struct sysdev_class s3c2410a_sysclass; | ||
75 | extern struct sysdev_class s3c2412_sysclass; | ||
76 | extern struct sysdev_class s3c2440_sysclass; | ||
77 | extern struct sysdev_class s3c2442_sysclass; | ||
78 | extern struct sysdev_class s3c2443_sysclass; | ||
79 | extern struct sysdev_class s3c6410_sysclass; | ||
80 | extern struct sysdev_class s3c64xx_sysclass; | ||
81 | |||
82 | extern void (*s5pc1xx_idle)(void); | ||
83 | |||
84 | #endif | ||
diff --git a/arch/arm/plat-samsung/include/plat/debug-macro.S b/arch/arm/plat-samsung/include/plat/debug-macro.S new file mode 100644 index 000000000000..dc6efd90e8ff --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/debug-macro.S | |||
@@ -0,0 +1,87 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/debug-macro.S | ||
2 | * | ||
3 | * Copyright 2005, 2007 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <plat/regs-serial.h> | ||
13 | |||
14 | /* The S5PV210/S5PC110 and S5P6442 implementations are as belows. */ | ||
15 | |||
16 | .macro fifo_level_s5pv210 rd, rx | ||
17 | ldr \rd, [ \rx, # S3C2410_UFSTAT ] | ||
18 | and \rd, \rd, #S5PV210_UFSTAT_TXMASK | ||
19 | .endm | ||
20 | |||
21 | .macro fifo_full_s5pv210 rd, rx | ||
22 | ldr \rd, [ \rx, # S3C2410_UFSTAT ] | ||
23 | tst \rd, #S5PV210_UFSTAT_TXFULL | ||
24 | .endm | ||
25 | |||
26 | /* The S3C2440 implementations are used by default as they are the | ||
27 | * most widely re-used */ | ||
28 | |||
29 | .macro fifo_level_s3c2440 rd, rx | ||
30 | ldr \rd, [ \rx, # S3C2410_UFSTAT ] | ||
31 | and \rd, \rd, #S3C2440_UFSTAT_TXMASK | ||
32 | .endm | ||
33 | |||
34 | #ifndef fifo_level | ||
35 | #define fifo_level fifo_level_s3c2440 | ||
36 | #endif | ||
37 | |||
38 | .macro fifo_full_s3c2440 rd, rx | ||
39 | ldr \rd, [ \rx, # S3C2410_UFSTAT ] | ||
40 | tst \rd, #S3C2440_UFSTAT_TXFULL | ||
41 | .endm | ||
42 | |||
43 | #ifndef fifo_full | ||
44 | #define fifo_full fifo_full_s3c2440 | ||
45 | #endif | ||
46 | |||
47 | .macro senduart,rd,rx | ||
48 | strb \rd, [\rx, # S3C2410_UTXH ] | ||
49 | .endm | ||
50 | |||
51 | .macro busyuart, rd, rx | ||
52 | ldr \rd, [ \rx, # S3C2410_UFCON ] | ||
53 | tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? | ||
54 | beq 1001f @ | ||
55 | @ FIFO enabled... | ||
56 | 1003: | ||
57 | fifo_full \rd, \rx | ||
58 | bne 1003b | ||
59 | b 1002f | ||
60 | |||
61 | 1001: | ||
62 | @ busy waiting for non fifo | ||
63 | ldr \rd, [ \rx, # S3C2410_UTRSTAT ] | ||
64 | tst \rd, #S3C2410_UTRSTAT_TXFE | ||
65 | beq 1001b | ||
66 | |||
67 | 1002: @ exit busyuart | ||
68 | .endm | ||
69 | |||
70 | .macro waituart,rd,rx | ||
71 | ldr \rd, [ \rx, # S3C2410_UFCON ] | ||
72 | tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? | ||
73 | beq 1001f @ | ||
74 | @ FIFO enabled... | ||
75 | 1003: | ||
76 | fifo_level \rd, \rx | ||
77 | teq \rd, #0 | ||
78 | bne 1003b | ||
79 | b 1002f | ||
80 | 1001: | ||
81 | @ idle waiting for non fifo | ||
82 | ldr \rd, [ \rx, # S3C2410_UTRSTAT ] | ||
83 | tst \rd, #S3C2410_UTRSTAT_TXFE | ||
84 | beq 1001b | ||
85 | |||
86 | 1002: @ exit busyuart | ||
87 | .endm | ||
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h new file mode 100644 index 000000000000..796d24258313 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/devs.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/devs.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for s3c2410 standard platform devices | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | struct s3c24xx_uart_resources { | ||
15 | struct resource *resources; | ||
16 | unsigned long nr_resources; | ||
17 | }; | ||
18 | |||
19 | extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; | ||
20 | extern struct s3c24xx_uart_resources s3c64xx_uart_resources[]; | ||
21 | extern struct s3c24xx_uart_resources s5p_uart_resources[]; | ||
22 | |||
23 | extern struct platform_device *s3c24xx_uart_devs[]; | ||
24 | extern struct platform_device *s3c24xx_uart_src[]; | ||
25 | |||
26 | extern struct platform_device s3c_device_timer[]; | ||
27 | |||
28 | extern struct platform_device s3c64xx_device_iis0; | ||
29 | extern struct platform_device s3c64xx_device_iis1; | ||
30 | extern struct platform_device s3c64xx_device_iisv4; | ||
31 | |||
32 | extern struct platform_device s3c64xx_device_spi0; | ||
33 | extern struct platform_device s3c64xx_device_spi1; | ||
34 | |||
35 | extern struct platform_device s3c64xx_device_pcm0; | ||
36 | extern struct platform_device s3c64xx_device_pcm1; | ||
37 | |||
38 | extern struct platform_device s3c64xx_device_ac97; | ||
39 | |||
40 | extern struct platform_device s3c_device_ts; | ||
41 | |||
42 | extern struct platform_device s3c_device_fb; | ||
43 | extern struct platform_device s3c_device_ohci; | ||
44 | extern struct platform_device s3c_device_lcd; | ||
45 | extern struct platform_device s3c_device_wdt; | ||
46 | extern struct platform_device s3c_device_i2c0; | ||
47 | extern struct platform_device s3c_device_i2c1; | ||
48 | extern struct platform_device s3c_device_rtc; | ||
49 | extern struct platform_device s3c_device_adc; | ||
50 | extern struct platform_device s3c_device_sdi; | ||
51 | extern struct platform_device s3c_device_iis; | ||
52 | extern struct platform_device s3c_device_hwmon; | ||
53 | extern struct platform_device s3c_device_hsmmc0; | ||
54 | extern struct platform_device s3c_device_hsmmc1; | ||
55 | extern struct platform_device s3c_device_hsmmc2; | ||
56 | |||
57 | extern struct platform_device s3c_device_spi0; | ||
58 | extern struct platform_device s3c_device_spi1; | ||
59 | |||
60 | extern struct platform_device s3c_device_hwmon; | ||
61 | |||
62 | extern struct platform_device s3c_device_nand; | ||
63 | |||
64 | extern struct platform_device s3c_device_usbgadget; | ||
65 | extern struct platform_device s3c_device_usb_hsotg; | ||
66 | |||
67 | /* s3c2440 specific devices */ | ||
68 | |||
69 | #ifdef CONFIG_CPU_S3C2440 | ||
70 | |||
71 | extern struct platform_device s3c_device_camif; | ||
72 | extern struct platform_device s3c_device_ac97; | ||
73 | |||
74 | #endif | ||
diff --git a/arch/arm/plat-samsung/include/plat/dma-core.h b/arch/arm/plat-samsung/include/plat/dma-core.h new file mode 100644 index 000000000000..32ff2a92cb3c --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/dma-core.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/dma.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * Samsung S3C DMA core support | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | extern struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel); | ||
16 | |||
17 | extern struct s3c2410_dma_chan *s3c_dma_chan_map[]; | ||
18 | |||
19 | /* the currently allocated channel information */ | ||
20 | extern struct s3c2410_dma_chan s3c2410_chans[]; | ||
21 | |||
22 | |||
diff --git a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h new file mode 100644 index 000000000000..336d5ac02035 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h | ||
2 | * | ||
3 | * Copyright (C) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Samsung S3C24XX DMA support - per SoC functions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <plat/dma-core.h> | ||
14 | |||
15 | extern struct sysdev_class dma_sysclass; | ||
16 | extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS]; | ||
17 | |||
18 | #define DMA_CH_VALID (1<<31) | ||
19 | #define DMA_CH_NEVER (1<<30) | ||
20 | |||
21 | struct s3c24xx_dma_addr { | ||
22 | unsigned long from; | ||
23 | unsigned long to; | ||
24 | }; | ||
25 | |||
26 | /* struct s3c24xx_dma_map | ||
27 | * | ||
28 | * this holds the mapping information for the channel selected | ||
29 | * to be connected to the specified device | ||
30 | */ | ||
31 | |||
32 | struct s3c24xx_dma_map { | ||
33 | const char *name; | ||
34 | struct s3c24xx_dma_addr hw_addr; | ||
35 | |||
36 | unsigned long channels[S3C_DMA_CHANNELS]; | ||
37 | unsigned long channels_rx[S3C_DMA_CHANNELS]; | ||
38 | }; | ||
39 | |||
40 | struct s3c24xx_dma_selection { | ||
41 | struct s3c24xx_dma_map *map; | ||
42 | unsigned long map_size; | ||
43 | unsigned long dcon_mask; | ||
44 | |||
45 | void (*select)(struct s3c2410_dma_chan *chan, | ||
46 | struct s3c24xx_dma_map *map); | ||
47 | |||
48 | void (*direction)(struct s3c2410_dma_chan *chan, | ||
49 | struct s3c24xx_dma_map *map, | ||
50 | enum s3c2410_dmasrc dir); | ||
51 | }; | ||
52 | |||
53 | extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel); | ||
54 | |||
55 | /* struct s3c24xx_dma_order_ch | ||
56 | * | ||
57 | * channel map for one of the `enum dma_ch` dma channels. the list | ||
58 | * entry contains a set of low-level channel numbers, orred with | ||
59 | * DMA_CH_VALID, which are checked in the order in the array. | ||
60 | */ | ||
61 | |||
62 | struct s3c24xx_dma_order_ch { | ||
63 | unsigned int list[S3C_DMA_CHANNELS]; /* list of channels */ | ||
64 | unsigned int flags; /* flags */ | ||
65 | }; | ||
66 | |||
67 | /* struct s3c24xx_dma_order | ||
68 | * | ||
69 | * information provided by either the core or the board to give the | ||
70 | * dma system a hint on how to allocate channels | ||
71 | */ | ||
72 | |||
73 | struct s3c24xx_dma_order { | ||
74 | struct s3c24xx_dma_order_ch channels[DMACH_MAX]; | ||
75 | }; | ||
76 | |||
77 | extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map); | ||
78 | |||
79 | /* DMA init code, called from the cpu support code */ | ||
80 | |||
81 | extern int s3c2410_dma_init(void); | ||
82 | |||
83 | extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq, | ||
84 | unsigned int stride); | ||
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h new file mode 100644 index 000000000000..7584d751ed51 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/dma.h | |||
@@ -0,0 +1,127 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/dma.h | ||
2 | * | ||
3 | * Copyright (C) 2003-2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Samsung S3C DMA support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | enum s3c2410_dma_buffresult { | ||
14 | S3C2410_RES_OK, | ||
15 | S3C2410_RES_ERR, | ||
16 | S3C2410_RES_ABORT | ||
17 | }; | ||
18 | |||
19 | enum s3c2410_dmasrc { | ||
20 | S3C2410_DMASRC_HW, /* source is memory */ | ||
21 | S3C2410_DMASRC_MEM /* source is hardware */ | ||
22 | }; | ||
23 | |||
24 | /* enum s3c2410_chan_op | ||
25 | * | ||
26 | * operation codes passed to the DMA code by the user, and also used | ||
27 | * to inform the current channel owner of any changes to the system state | ||
28 | */ | ||
29 | |||
30 | enum s3c2410_chan_op { | ||
31 | S3C2410_DMAOP_START, | ||
32 | S3C2410_DMAOP_STOP, | ||
33 | S3C2410_DMAOP_PAUSE, | ||
34 | S3C2410_DMAOP_RESUME, | ||
35 | S3C2410_DMAOP_FLUSH, | ||
36 | S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */ | ||
37 | S3C2410_DMAOP_STARTED, /* indicate channel started */ | ||
38 | }; | ||
39 | |||
40 | struct s3c2410_dma_client { | ||
41 | char *name; | ||
42 | }; | ||
43 | |||
44 | struct s3c2410_dma_chan; | ||
45 | |||
46 | /* s3c2410_dma_cbfn_t | ||
47 | * | ||
48 | * buffer callback routine type | ||
49 | */ | ||
50 | |||
51 | typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *, | ||
52 | void *buf, int size, | ||
53 | enum s3c2410_dma_buffresult result); | ||
54 | |||
55 | typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *, | ||
56 | enum s3c2410_chan_op ); | ||
57 | |||
58 | |||
59 | |||
60 | /* s3c2410_dma_request | ||
61 | * | ||
62 | * request a dma channel exclusivley | ||
63 | */ | ||
64 | |||
65 | extern int s3c2410_dma_request(unsigned int channel, | ||
66 | struct s3c2410_dma_client *, void *dev); | ||
67 | |||
68 | |||
69 | /* s3c2410_dma_ctrl | ||
70 | * | ||
71 | * change the state of the dma channel | ||
72 | */ | ||
73 | |||
74 | extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op); | ||
75 | |||
76 | /* s3c2410_dma_setflags | ||
77 | * | ||
78 | * set the channel's flags to a given state | ||
79 | */ | ||
80 | |||
81 | extern int s3c2410_dma_setflags(unsigned int channel, | ||
82 | unsigned int flags); | ||
83 | |||
84 | /* s3c2410_dma_free | ||
85 | * | ||
86 | * free the dma channel (will also abort any outstanding operations) | ||
87 | */ | ||
88 | |||
89 | extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *); | ||
90 | |||
91 | /* s3c2410_dma_enqueue | ||
92 | * | ||
93 | * place the given buffer onto the queue of operations for the channel. | ||
94 | * The buffer must be allocated from dma coherent memory, or the Dcache/WB | ||
95 | * drained before the buffer is given to the DMA system. | ||
96 | */ | ||
97 | |||
98 | extern int s3c2410_dma_enqueue(unsigned int channel, void *id, | ||
99 | dma_addr_t data, int size); | ||
100 | |||
101 | /* s3c2410_dma_config | ||
102 | * | ||
103 | * configure the dma channel | ||
104 | */ | ||
105 | |||
106 | extern int s3c2410_dma_config(unsigned int channel, int xferunit); | ||
107 | |||
108 | /* s3c2410_dma_devconfig | ||
109 | * | ||
110 | * configure the device we're talking to | ||
111 | */ | ||
112 | |||
113 | extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, | ||
114 | unsigned long devaddr); | ||
115 | |||
116 | /* s3c2410_dma_getposition | ||
117 | * | ||
118 | * get the position that the dma transfer is currently at | ||
119 | */ | ||
120 | |||
121 | extern int s3c2410_dma_getposition(unsigned int channel, | ||
122 | dma_addr_t *src, dma_addr_t *dest); | ||
123 | |||
124 | extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn); | ||
125 | extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn); | ||
126 | |||
127 | |||
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h new file mode 100644 index 000000000000..ffc01a76b7ce --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/fb.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/fb.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C - FB platform data definitions | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef __PLAT_S3C_FB_H | ||
16 | #define __PLAT_S3C_FB_H __FILE__ | ||
17 | |||
18 | /** | ||
19 | * struct s3c_fb_pd_win - per window setup data | ||
20 | * @win_mode: The display parameters to initialise (not for window 0) | ||
21 | * @virtual_x: The virtual X size. | ||
22 | * @virtual_y: The virtual Y size. | ||
23 | */ | ||
24 | struct s3c_fb_pd_win { | ||
25 | struct fb_videomode win_mode; | ||
26 | |||
27 | unsigned short default_bpp; | ||
28 | unsigned short max_bpp; | ||
29 | unsigned short virtual_x; | ||
30 | unsigned short virtual_y; | ||
31 | }; | ||
32 | |||
33 | /** | ||
34 | * struct s3c_fb_platdata - S3C driver platform specific information | ||
35 | * @setup_gpio: Setup the external GPIO pins to the right state to transfer | ||
36 | * the data from the display system to the connected display | ||
37 | * device. | ||
38 | * @vidcon0: The base vidcon0 values to control the panel data format. | ||
39 | * @vidcon1: The base vidcon1 values to control the panel data output. | ||
40 | * @win: The setup data for each hardware window, or NULL for unused. | ||
41 | * @display_mode: The LCD output display mode. | ||
42 | * | ||
43 | * The platform data supplies the video driver with all the information | ||
44 | * it requires to work with the display(s) attached to the machine. It | ||
45 | * controls the initial mode, the number of display windows (0 is always | ||
46 | * the base framebuffer) that are initialised etc. | ||
47 | * | ||
48 | */ | ||
49 | struct s3c_fb_platdata { | ||
50 | void (*setup_gpio)(void); | ||
51 | |||
52 | struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; | ||
53 | |||
54 | u32 vidcon0; | ||
55 | u32 vidcon1; | ||
56 | }; | ||
57 | |||
58 | /** | ||
59 | * s3c_fb_set_platdata() - Setup the FB device with platform data. | ||
60 | * @pd: The platform data to set. The data is copied from the passed structure | ||
61 | * so the machine data can mark the data __initdata so that any unused | ||
62 | * machines will end up dumping their data at runtime. | ||
63 | */ | ||
64 | extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd); | ||
65 | |||
66 | /** | ||
67 | * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD | ||
68 | * | ||
69 | * Initialise the GPIO for an 24bpp LCD display on the RGB interface. | ||
70 | */ | ||
71 | extern void s3c64xx_fb_gpio_setup_24bpp(void); | ||
72 | |||
73 | /** | ||
74 | * s5pc100_fb_gpio_setup_24bpp() - S5PC100 setup function for 24bpp LCD | ||
75 | * | ||
76 | * Initialise the GPIO for an 24bpp LCD display on the RGB interface. | ||
77 | */ | ||
78 | extern void s5pc100_fb_gpio_setup_24bpp(void); | ||
79 | |||
80 | #endif /* __PLAT_S3C_FB_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h new file mode 100644 index 000000000000..dda19da037ad --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h | |||
@@ -0,0 +1,176 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C Platform - GPIO pin configuration helper definitions | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* This is meant for core cpu support, machine or other driver files | ||
16 | * should not be including this header. | ||
17 | */ | ||
18 | |||
19 | #ifndef __PLAT_GPIO_CFG_HELPERS_H | ||
20 | #define __PLAT_GPIO_CFG_HELPERS_H __FILE__ | ||
21 | |||
22 | /* As a note, all gpio configuration functions are entered exclusively, either | ||
23 | * with the relevant lock held or the system prevented from doing anything else | ||
24 | * by disabling interrupts. | ||
25 | */ | ||
26 | |||
27 | static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip, | ||
28 | unsigned int off, unsigned int config) | ||
29 | { | ||
30 | return (chip->config->set_config)(chip, off, config); | ||
31 | } | ||
32 | |||
33 | static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip, | ||
34 | unsigned int off, s3c_gpio_pull_t pull) | ||
35 | { | ||
36 | return (chip->config->set_pull)(chip, off, pull); | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration. | ||
41 | * @chip: The gpio chip that is being configured. | ||
42 | * @off: The offset for the GPIO being configured. | ||
43 | * @cfg: The configuration value to set. | ||
44 | * | ||
45 | * This helper deal with the GPIO cases where the control register | ||
46 | * has two bits of configuration per gpio, which have the following | ||
47 | * functions: | ||
48 | * 00 = input | ||
49 | * 01 = output | ||
50 | * 1x = special function | ||
51 | */ | ||
52 | extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
53 | unsigned int off, unsigned int cfg); | ||
54 | |||
55 | /** | ||
56 | * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A) | ||
57 | * @chip: The gpio chip that is being configured. | ||
58 | * @off: The offset for the GPIO being configured. | ||
59 | * @cfg: The configuration value to set. | ||
60 | * | ||
61 | * This helper deal with the GPIO cases where the control register | ||
62 | * has one bit of configuration for the gpio, where setting the bit | ||
63 | * means the pin is in special function mode and unset means output. | ||
64 | */ | ||
65 | extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | ||
66 | unsigned int off, unsigned int cfg); | ||
67 | |||
68 | /** | ||
69 | * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config. | ||
70 | * @chip: The gpio chip that is being configured. | ||
71 | * @off: The offset for the GPIO being configured. | ||
72 | * @cfg: The configuration value to set. | ||
73 | * | ||
74 | * This helper deal with the GPIO cases where the control register has 4 bits | ||
75 | * of control per GPIO, generally in the form of: | ||
76 | * 0000 = Input | ||
77 | * 0001 = Output | ||
78 | * others = Special functions (dependant on bank) | ||
79 | * | ||
80 | * Note, since the code to deal with the case where there are two control | ||
81 | * registers instead of one, we do not have a separate set of functions for | ||
82 | * each case. | ||
83 | */ | ||
84 | extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
85 | unsigned int off, unsigned int cfg); | ||
86 | |||
87 | |||
88 | /* Pull-{up,down} resistor controls. | ||
89 | * | ||
90 | * S3C2410,S3C2440,S3C24A0 = Pull-UP, | ||
91 | * S3C2412,S3C2413 = Pull-Down | ||
92 | * S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef] | ||
93 | * S3C2443 = Pull-Both [not same as S3C6400] | ||
94 | */ | ||
95 | |||
96 | /** | ||
97 | * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none. | ||
98 | * @chip: The gpio chip that is being configured. | ||
99 | * @off: The offset for the GPIO being configured. | ||
100 | * @param: pull: The pull mode being requested. | ||
101 | * | ||
102 | * This is a helper function for the case where we have GPIOs with one | ||
103 | * bit configuring the presence of a pull-up resistor. | ||
104 | */ | ||
105 | extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, | ||
106 | unsigned int off, s3c_gpio_pull_t pull); | ||
107 | |||
108 | /** | ||
109 | * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none | ||
110 | * @chip: The gpio chip that is being configured | ||
111 | * @off: The offset for the GPIO being configured | ||
112 | * @param: pull: The pull mode being requested | ||
113 | * | ||
114 | * This is a helper function for the case where we have GPIOs with one | ||
115 | * bit configuring the presence of a pull-down resistor. | ||
116 | */ | ||
117 | extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip, | ||
118 | unsigned int off, s3c_gpio_pull_t pull); | ||
119 | |||
120 | /** | ||
121 | * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none | ||
122 | * @chip: The gpio chip that is being configured. | ||
123 | * @off: The offset for the GPIO being configured. | ||
124 | * @param: pull: The pull mode being requested. | ||
125 | * | ||
126 | * This is a helper function for the case where we have GPIOs with two | ||
127 | * bits configuring the presence of a pull resistor, in the following | ||
128 | * order: | ||
129 | * 00 = No pull resistor connected | ||
130 | * 01 = Pull-up resistor connected | ||
131 | * 10 = Pull-down resistor connected | ||
132 | */ | ||
133 | extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip, | ||
134 | unsigned int off, s3c_gpio_pull_t pull); | ||
135 | |||
136 | |||
137 | /** | ||
138 | * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none | ||
139 | * @chip: The gpio chip that the GPIO pin belongs to | ||
140 | * @off: The offset to the pin to get the configuration of. | ||
141 | * | ||
142 | * This helper function reads the state of the pull-{up,down} resistor for the | ||
143 | * given GPIO in the same case as s3c_gpio_setpull_upown. | ||
144 | */ | ||
145 | extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, | ||
146 | unsigned int off); | ||
147 | |||
148 | /** | ||
149 | * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443. | ||
150 | * @chip: The gpio chip that is being configured. | ||
151 | * @off: The offset for the GPIO being configured. | ||
152 | * @param: pull: The pull mode being requested. | ||
153 | * | ||
154 | * This is a helper function for the case where we have GPIOs with two | ||
155 | * bits configuring the presence of a pull resistor, in the following | ||
156 | * order: | ||
157 | * 00 = Pull-up resistor connected | ||
158 | * 10 = Pull-down resistor connected | ||
159 | * x1 = No pull up resistor | ||
160 | */ | ||
161 | extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, | ||
162 | unsigned int off, s3c_gpio_pull_t pull); | ||
163 | |||
164 | /** | ||
165 | * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors | ||
166 | * @chip: The gpio chip that the GPIO pin belongs to. | ||
167 | * @off: The offset to the pin to get the configuration of. | ||
168 | * | ||
169 | * This helper function reads the state of the pull-{up,down} resistor for the | ||
170 | * given GPIO in the same case as s3c_gpio_setpull_upown. | ||
171 | */ | ||
172 | extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip, | ||
173 | unsigned int off); | ||
174 | |||
175 | #endif /* __PLAT_GPIO_CFG_HELPERS_H */ | ||
176 | |||
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h new file mode 100644 index 000000000000..29cd6a86cade --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h | |||
@@ -0,0 +1,110 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C Platform - GPIO pin configuration | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* This file contains the necessary definitions to get the basic gpio | ||
16 | * pin configuration done such as setting a pin to input or output or | ||
17 | * changing the pull-{up,down} configurations. | ||
18 | */ | ||
19 | |||
20 | /* Note, this interface is being added to the s3c64xx arch first and will | ||
21 | * be added to the s3c24xx systems later. | ||
22 | */ | ||
23 | |||
24 | #ifndef __PLAT_GPIO_CFG_H | ||
25 | #define __PLAT_GPIO_CFG_H __FILE__ | ||
26 | |||
27 | typedef unsigned int __bitwise__ s3c_gpio_pull_t; | ||
28 | |||
29 | /* forward declaration if gpio-core.h hasn't been included */ | ||
30 | struct s3c_gpio_chip; | ||
31 | |||
32 | /** | ||
33 | * struct s3c_gpio_cfg GPIO configuration | ||
34 | * @cfg_eint: Configuration setting when used for external interrupt source | ||
35 | * @get_pull: Read the current pull configuration for the GPIO | ||
36 | * @set_pull: Set the current pull configuraiton for the GPIO | ||
37 | * @set_config: Set the current configuration for the GPIO | ||
38 | * @get_config: Read the current configuration for the GPIO | ||
39 | * | ||
40 | * Each chip can have more than one type of GPIO bank available and some | ||
41 | * have different capabilites even when they have the same control register | ||
42 | * layouts. Provide an point to vector control routine and provide any | ||
43 | * per-bank configuration information that other systems such as the | ||
44 | * external interrupt code will need. | ||
45 | */ | ||
46 | struct s3c_gpio_cfg { | ||
47 | unsigned int cfg_eint; | ||
48 | |||
49 | s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs); | ||
50 | int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs, | ||
51 | s3c_gpio_pull_t pull); | ||
52 | |||
53 | unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs); | ||
54 | int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs, | ||
55 | unsigned config); | ||
56 | }; | ||
57 | |||
58 | #define S3C_GPIO_SPECIAL_MARK (0xfffffff0) | ||
59 | #define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x)) | ||
60 | |||
61 | /* Defines for generic pin configurations */ | ||
62 | #define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0)) | ||
63 | #define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1)) | ||
64 | #define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x)) | ||
65 | |||
66 | #define s3c_gpio_is_cfg_special(_cfg) \ | ||
67 | (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK) | ||
68 | |||
69 | /** | ||
70 | * s3c_gpio_cfgpin() - Change the GPIO function of a pin. | ||
71 | * @pin pin The pin number to configure. | ||
72 | * @pin to The configuration for the pin's function. | ||
73 | * | ||
74 | * Configure which function is actually connected to the external | ||
75 | * pin, such as an gpio input, output or some form of special function | ||
76 | * connected to an internal peripheral block. | ||
77 | */ | ||
78 | extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); | ||
79 | |||
80 | /* Define values for the pull-{up,down} available for each gpio pin. | ||
81 | * | ||
82 | * These values control the state of the weak pull-{up,down} resistors | ||
83 | * available on most pins on the S3C series. Not all chips support both | ||
84 | * up or down settings, and it may be dependant on the chip that is being | ||
85 | * used to whether the particular mode is available. | ||
86 | */ | ||
87 | #define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00) | ||
88 | #define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01) | ||
89 | #define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02) | ||
90 | |||
91 | /** | ||
92 | * s3c_gpio_setpull() - set the state of a gpio pin pull resistor | ||
93 | * @pin: The pin number to configure the pull resistor. | ||
94 | * @pull: The configuration for the pull resistor. | ||
95 | * | ||
96 | * This function sets the state of the pull-{up,down} resistor for the | ||
97 | * specified pin. It will return 0 if successfull, or a negative error | ||
98 | * code if the pin cannot support the requested pull setting. | ||
99 | */ | ||
100 | extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull); | ||
101 | |||
102 | /** | ||
103 | * s3c_gpio_getpull() - get the pull resistor state of a gpio pin | ||
104 | * @pin: The pin number to get the settings for | ||
105 | * | ||
106 | * Read the pull resistor value for the specified pin. | ||
107 | */ | ||
108 | extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); | ||
109 | |||
110 | #endif /* __PLAT_GPIO_CFG_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h new file mode 100644 index 000000000000..49ff406a7066 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h | |||
@@ -0,0 +1,137 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/gpio-core.h | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C Platform - GPIO core | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #define GPIOCON_OFF (0x00) | ||
15 | #define GPIODAT_OFF (0x04) | ||
16 | |||
17 | #define con_4bit_shift(__off) ((__off) * 4) | ||
18 | |||
19 | /* Define the core gpiolib support functions that the s3c platforms may | ||
20 | * need to extend or change depending on the hardware and the s3c chip | ||
21 | * selected at build or found at run time. | ||
22 | * | ||
23 | * These definitions are not intended for driver inclusion, there is | ||
24 | * nothing here that should not live outside the platform and core | ||
25 | * specific code. | ||
26 | */ | ||
27 | |||
28 | struct s3c_gpio_chip; | ||
29 | |||
30 | /** | ||
31 | * struct s3c_gpio_pm - power management (suspend/resume) information | ||
32 | * @save: Routine to save the state of the GPIO block | ||
33 | * @resume: Routine to resume the GPIO block. | ||
34 | */ | ||
35 | struct s3c_gpio_pm { | ||
36 | void (*save)(struct s3c_gpio_chip *chip); | ||
37 | void (*resume)(struct s3c_gpio_chip *chip); | ||
38 | }; | ||
39 | |||
40 | struct s3c_gpio_cfg; | ||
41 | |||
42 | /** | ||
43 | * struct s3c_gpio_chip - wrapper for specific implementation of gpio | ||
44 | * @chip: The chip structure to be exported via gpiolib. | ||
45 | * @base: The base pointer to the gpio configuration registers. | ||
46 | * @config: special function and pull-resistor control information. | ||
47 | * @pm_save: Save information for suspend/resume support. | ||
48 | * | ||
49 | * This wrapper provides the necessary information for the Samsung | ||
50 | * specific gpios being registered with gpiolib. | ||
51 | */ | ||
52 | struct s3c_gpio_chip { | ||
53 | struct gpio_chip chip; | ||
54 | struct s3c_gpio_cfg *config; | ||
55 | struct s3c_gpio_pm *pm; | ||
56 | void __iomem *base; | ||
57 | #ifdef CONFIG_PM | ||
58 | u32 pm_save[4]; | ||
59 | #endif | ||
60 | }; | ||
61 | |||
62 | static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc) | ||
63 | { | ||
64 | return container_of(gpc, struct s3c_gpio_chip, chip); | ||
65 | } | ||
66 | |||
67 | /** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip. | ||
68 | * @chip: The chip to register | ||
69 | * | ||
70 | * This is a wrapper to gpiochip_add() that takes our specific gpio chip | ||
71 | * information and makes the necessary alterations for the platform and | ||
72 | * notes the information for use with the configuration systems and any | ||
73 | * other parts of the system. | ||
74 | */ | ||
75 | extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip); | ||
76 | |||
77 | /* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios | ||
78 | * for use with the configuration calls, and other parts of the s3c gpiolib | ||
79 | * support code. | ||
80 | * | ||
81 | * Not all s3c support code will need this, as some configurations of cpu | ||
82 | * may only support one or two different configuration options and have an | ||
83 | * easy gpio to s3c_gpio_chip mapping function. If this is the case, then | ||
84 | * the machine support file should provide its own s3c_gpiolib_getchip() | ||
85 | * and any other necessary functions. | ||
86 | */ | ||
87 | |||
88 | /** | ||
89 | * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config. | ||
90 | * @chip: The gpio chip that is being configured. | ||
91 | * @nr_chips: The no of chips (gpio ports) for the GPIO being configured. | ||
92 | * | ||
93 | * This helper deal with the GPIO cases where the control register has 4 bits | ||
94 | * of control per GPIO, generally in the form of: | ||
95 | * 0000 = Input | ||
96 | * 0001 = Output | ||
97 | * others = Special functions (dependant on bank) | ||
98 | * | ||
99 | * Note, since the code to deal with the case where there are two control | ||
100 | * registers instead of one, we do not have a seperate set of function | ||
101 | * (samsung_gpiolib_add_4bit2_chips)for each case. | ||
102 | */ | ||
103 | extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip, | ||
104 | int nr_chips); | ||
105 | extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, | ||
106 | int nr_chips); | ||
107 | |||
108 | extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); | ||
109 | extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); | ||
110 | |||
111 | #ifdef CONFIG_S3C_GPIO_TRACK | ||
112 | extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; | ||
113 | |||
114 | static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip) | ||
115 | { | ||
116 | return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL; | ||
117 | } | ||
118 | #else | ||
119 | /* machine specific code should provide s3c_gpiolib_getchip */ | ||
120 | |||
121 | #include <mach/gpio-track.h> | ||
122 | |||
123 | static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { } | ||
124 | #endif | ||
125 | |||
126 | #ifdef CONFIG_PM | ||
127 | extern struct s3c_gpio_pm s3c_gpio_pm_1bit; | ||
128 | extern struct s3c_gpio_pm s3c_gpio_pm_2bit; | ||
129 | extern struct s3c_gpio_pm s3c_gpio_pm_4bit; | ||
130 | #define __gpio_pm(x) x | ||
131 | #else | ||
132 | #define s3c_gpio_pm_1bit NULL | ||
133 | #define s3c_gpio_pm_2bit NULL | ||
134 | #define s3c_gpio_pm_4bit NULL | ||
135 | #define __gpio_pm(x) NULL | ||
136 | |||
137 | #endif /* CONFIG_PM */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/hwmon.h b/arch/arm/plat-samsung/include/plat/hwmon.h new file mode 100644 index 000000000000..1ba88ea0aa31 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/hwmon.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/hwmon.h | ||
2 | * | ||
3 | * Copyright 2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C - HWMon interface for ADC | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASM_ARCH_ADC_HWMON_H | ||
15 | #define __ASM_ARCH_ADC_HWMON_H __FILE__ | ||
16 | |||
17 | /** | ||
18 | * s3c_hwmon_chcfg - channel configuration | ||
19 | * @name: The name to give this channel. | ||
20 | * @mult: Multiply the ADC value read by this. | ||
21 | * @div: Divide the value from the ADC by this. | ||
22 | * | ||
23 | * The value read from the ADC is converted to a value that | ||
24 | * hwmon expects (mV) by result = (value_read * @mult) / @div. | ||
25 | */ | ||
26 | struct s3c_hwmon_chcfg { | ||
27 | const char *name; | ||
28 | unsigned int mult; | ||
29 | unsigned int div; | ||
30 | }; | ||
31 | |||
32 | /** | ||
33 | * s3c_hwmon_pdata - HWMON platform data | ||
34 | * @in: One configuration for each possible channel used. | ||
35 | */ | ||
36 | struct s3c_hwmon_pdata { | ||
37 | struct s3c_hwmon_chcfg *in[8]; | ||
38 | }; | ||
39 | |||
40 | #endif /* __ASM_ARCH_ADC_HWMON_H */ | ||
41 | |||
diff --git a/arch/arm/plat-samsung/include/plat/iic-core.h b/arch/arm/plat-samsung/include/plat/iic-core.h new file mode 100644 index 000000000000..36397ca20962 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/iic-core.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/iic-core.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C - I2C Controller core functions | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASM_ARCH_IIC_CORE_H | ||
15 | #define __ASM_ARCH_IIC_CORE_H __FILE__ | ||
16 | |||
17 | /* These functions are only for use with the core support code, such as | ||
18 | * the cpu specific initialisation code | ||
19 | */ | ||
20 | |||
21 | /* re-define device name depending on support. */ | ||
22 | static inline void s3c_i2c0_setname(char *name) | ||
23 | { | ||
24 | /* currently this device is always compiled in */ | ||
25 | s3c_device_i2c0.name = name; | ||
26 | } | ||
27 | |||
28 | static inline void s3c_i2c1_setname(char *name) | ||
29 | { | ||
30 | #ifdef CONFIG_S3C_DEV_I2C1 | ||
31 | s3c_device_i2c1.name = name; | ||
32 | #endif | ||
33 | } | ||
34 | |||
35 | #endif /* __ASM_ARCH_IIC_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h new file mode 100644 index 000000000000..3083df00dee6 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/iic.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/iic.h | ||
2 | * | ||
3 | * Copyright 2004-2009 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C - I2C Controller platform_device info | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_IIC_H | ||
14 | #define __ASM_ARCH_IIC_H __FILE__ | ||
15 | |||
16 | #define S3C_IICFLG_FILTER (1<<0) /* enable s3c2440 filter */ | ||
17 | |||
18 | /** | ||
19 | * struct s3c2410_platform_i2c - Platform data for s3c I2C. | ||
20 | * @bus_num: The bus number to use (if possible). | ||
21 | * @flags: Any flags for the I2C bus (E.g. S3C_IICFLK_FILTER). | ||
22 | * @slave_addr: The I2C address for the slave device (if enabled). | ||
23 | * @frequency: The desired frequency in Hz of the bus. This is | ||
24 | * guaranteed to not be exceeded. If the caller does | ||
25 | * not care, use zero and the driver will select a | ||
26 | * useful default. | ||
27 | * @sda_delay: The delay (in ns) applied to SDA edges. | ||
28 | * @cfg_gpio: A callback to configure the pins for I2C operation. | ||
29 | */ | ||
30 | struct s3c2410_platform_i2c { | ||
31 | int bus_num; | ||
32 | unsigned int flags; | ||
33 | unsigned int slave_addr; | ||
34 | unsigned long frequency; | ||
35 | unsigned int sda_delay; | ||
36 | |||
37 | void (*cfg_gpio)(struct platform_device *dev); | ||
38 | }; | ||
39 | |||
40 | /** | ||
41 | * s3c_i2c0_set_platdata - set platform data for i2c0 device | ||
42 | * @i2c: The platform data to set, or NULL for default data. | ||
43 | * | ||
44 | * Register the given platform data for use with the i2c0 device. This | ||
45 | * call copies the platform data, so the caller can use __initdata for | ||
46 | * their copy. | ||
47 | * | ||
48 | * This call will set cfg_gpio if is null to the default platform | ||
49 | * implementation. | ||
50 | * | ||
51 | * Any user of s3c_device_i2c0 should call this, even if it is with | ||
52 | * NULL to ensure that the device is given the default platform data | ||
53 | * as the driver will no longer carry defaults. | ||
54 | */ | ||
55 | extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
56 | extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
57 | |||
58 | /* defined by architecture to configure gpio */ | ||
59 | extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); | ||
60 | extern void s3c_i2c1_cfg_gpio(struct platform_device *dev); | ||
61 | |||
62 | #endif /* __ASM_ARCH_IIC_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/irq-uart.h b/arch/arm/plat-samsung/include/plat/irq-uart.h new file mode 100644 index 000000000000..a9331e49bea3 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/irq-uart.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/irq-uart.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for Samsung SoC UART IRQ demux for S3C64XX and later | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | struct s3c_uart_irq { | ||
14 | void __iomem *regs; | ||
15 | unsigned int base_irq; | ||
16 | unsigned int parent_irq; | ||
17 | }; | ||
18 | |||
19 | extern void s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs); | ||
20 | |||
diff --git a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h new file mode 100644 index 000000000000..a90b53431b5b --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h | |||
@@ -0,0 +1,13 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/irq-vic-timer.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for Samsung SoC IRQ VIC timer | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | extern void s3c_init_vic_timer_irq(unsigned int vic, unsigned int timer); | ||
diff --git a/arch/arm/plat-samsung/include/plat/map-base.h b/arch/arm/plat-samsung/include/plat/map-base.h new file mode 100644 index 000000000000..250be311c85b --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/map-base.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* linux/include/asm-arm/plat-s3c/map.h | ||
2 | * | ||
3 | * Copyright 2003, 2007 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C - Memory map definitions (virtual addresses) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASM_PLAT_MAP_H | ||
15 | #define __ASM_PLAT_MAP_H __FILE__ | ||
16 | |||
17 | /* Fit all our registers in at 0xF4000000 upwards, trying to use as | ||
18 | * little of the VA space as possible so vmalloc and friends have a | ||
19 | * better chance of getting memory. | ||
20 | * | ||
21 | * we try to ensure stuff like the IRQ registers are available for | ||
22 | * an single MOVS instruction (ie, only 8 bits of set data) | ||
23 | */ | ||
24 | |||
25 | #define S3C_ADDR_BASE (0xF4000000) | ||
26 | |||
27 | #ifndef __ASSEMBLY__ | ||
28 | #define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x)) | ||
29 | #else | ||
30 | #define S3C_ADDR(x) (S3C_ADDR_BASE + (x)) | ||
31 | #endif | ||
32 | |||
33 | #define S3C_VA_IRQ S3C_ADDR(0x00000000) /* irq controller(s) */ | ||
34 | #define S3C_VA_SYS S3C_ADDR(0x00100000) /* system control */ | ||
35 | #define S3C_VA_MEM S3C_ADDR(0x00200000) /* memory control */ | ||
36 | #define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */ | ||
37 | #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */ | ||
38 | #define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */ | ||
39 | |||
40 | /* This is used for the CPU specific mappings that may be needed, so that | ||
41 | * they do not need to directly used S3C_ADDR() and thus make it easier to | ||
42 | * modify the space for mapping. | ||
43 | */ | ||
44 | #define S3C_ADDR_CPU(x) S3C_ADDR(0x00500000 + (x)) | ||
45 | |||
46 | #endif /* __ASM_PLAT_MAP_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/nand.h b/arch/arm/plat-samsung/include/plat/nand.h new file mode 100644 index 000000000000..b64115fa93a4 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/nand.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/nand.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2410 - NAND device controller platform_device info | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | /** | ||
14 | * struct s3c2410_nand_set - define a set of one or more nand chips | ||
15 | * @disable_ecc: Entirely disable ECC - Dangerous | ||
16 | * @flash_bbt: Openmoko u-boot can create a Bad Block Table | ||
17 | * Setting this flag will allow the kernel to | ||
18 | * look for it at boot time and also skip the NAND | ||
19 | * scan. | ||
20 | * @options: Default value to set into 'struct nand_chip' options. | ||
21 | * @nr_chips: Number of chips in this set | ||
22 | * @nr_partitions: Number of partitions pointed to by @partitions | ||
23 | * @name: Name of set (optional) | ||
24 | * @nr_map: Map for low-layer logical to physical chip numbers (option) | ||
25 | * @partitions: The mtd partition list | ||
26 | * | ||
27 | * define a set of one or more nand chips registered with an unique mtd. Also | ||
28 | * allows to pass flag to the underlying NAND layer. 'disable_ecc' will trigger | ||
29 | * a warning at boot time. | ||
30 | */ | ||
31 | struct s3c2410_nand_set { | ||
32 | unsigned int disable_ecc:1; | ||
33 | unsigned int flash_bbt:1; | ||
34 | |||
35 | unsigned int options; | ||
36 | int nr_chips; | ||
37 | int nr_partitions; | ||
38 | char *name; | ||
39 | int *nr_map; | ||
40 | struct mtd_partition *partitions; | ||
41 | struct nand_ecclayout *ecc_layout; | ||
42 | }; | ||
43 | |||
44 | struct s3c2410_platform_nand { | ||
45 | /* timing information for controller, all times in nanoseconds */ | ||
46 | |||
47 | int tacls; /* time for active CLE/ALE to nWE/nOE */ | ||
48 | int twrph0; /* active time for nWE/nOE */ | ||
49 | int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */ | ||
50 | |||
51 | unsigned int ignore_unset_ecc:1; | ||
52 | |||
53 | int nr_sets; | ||
54 | struct s3c2410_nand_set *sets; | ||
55 | |||
56 | void (*select_chip)(struct s3c2410_nand_set *, | ||
57 | int chip); | ||
58 | }; | ||
59 | |||
60 | /** | ||
61 | * s3c_nand_set_platdata() - register NAND platform data. | ||
62 | * @nand: The NAND platform data to register with s3c_device_nand. | ||
63 | * | ||
64 | * This function copies the given NAND platform data, @nand and registers | ||
65 | * it with the s3c_device_nand. This allows @nand to be __initdata. | ||
66 | */ | ||
67 | extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand); | ||
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h new file mode 100644 index 000000000000..245836d91931 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/pm.h | |||
@@ -0,0 +1,189 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/pm.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Written by Ben Dooks, <ben@simtec.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | /* s3c_pm_init | ||
13 | * | ||
14 | * called from board at initialisation time to setup the power | ||
15 | * management | ||
16 | */ | ||
17 | |||
18 | #ifdef CONFIG_PM | ||
19 | |||
20 | extern __init int s3c_pm_init(void); | ||
21 | |||
22 | #else | ||
23 | |||
24 | static inline int s3c_pm_init(void) | ||
25 | { | ||
26 | return 0; | ||
27 | } | ||
28 | #endif | ||
29 | |||
30 | /* configuration for the IRQ mask over sleep */ | ||
31 | extern unsigned long s3c_irqwake_intmask; | ||
32 | extern unsigned long s3c_irqwake_eintmask; | ||
33 | |||
34 | /* IRQ masks for IRQs allowed to go to sleep (see irq.c) */ | ||
35 | extern unsigned long s3c_irqwake_intallow; | ||
36 | extern unsigned long s3c_irqwake_eintallow; | ||
37 | |||
38 | /* per-cpu sleep functions */ | ||
39 | |||
40 | extern void (*pm_cpu_prep)(void); | ||
41 | extern void (*pm_cpu_sleep)(void); | ||
42 | |||
43 | /* Flags for PM Control */ | ||
44 | |||
45 | extern unsigned long s3c_pm_flags; | ||
46 | |||
47 | extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */ | ||
48 | |||
49 | /* from sleep.S */ | ||
50 | |||
51 | extern int s3c_cpu_save(unsigned long *saveblk); | ||
52 | extern void s3c_cpu_resume(void); | ||
53 | |||
54 | extern void s3c2410_cpu_suspend(void); | ||
55 | |||
56 | extern unsigned long s3c_sleep_save_phys; | ||
57 | |||
58 | /* sleep save info */ | ||
59 | |||
60 | /** | ||
61 | * struct sleep_save - save information for shared peripherals. | ||
62 | * @reg: Pointer to the register to save. | ||
63 | * @val: Holder for the value saved from reg. | ||
64 | * | ||
65 | * This describes a list of registers which is used by the pm core and | ||
66 | * other subsystem to save and restore register values over suspend. | ||
67 | */ | ||
68 | struct sleep_save { | ||
69 | void __iomem *reg; | ||
70 | unsigned long val; | ||
71 | }; | ||
72 | |||
73 | #define SAVE_ITEM(x) \ | ||
74 | { .reg = (x) } | ||
75 | |||
76 | /** | ||
77 | * struct pm_uart_save - save block for core UART | ||
78 | * @ulcon: Save value for S3C2410_ULCON | ||
79 | * @ucon: Save value for S3C2410_UCON | ||
80 | * @ufcon: Save value for S3C2410_UFCON | ||
81 | * @umcon: Save value for S3C2410_UMCON | ||
82 | * @ubrdiv: Save value for S3C2410_UBRDIV | ||
83 | * | ||
84 | * Save block for UART registers to be held over sleep and restored if they | ||
85 | * are needed (say by debug). | ||
86 | */ | ||
87 | struct pm_uart_save { | ||
88 | u32 ulcon; | ||
89 | u32 ucon; | ||
90 | u32 ufcon; | ||
91 | u32 umcon; | ||
92 | u32 ubrdiv; | ||
93 | u32 udivslot; | ||
94 | }; | ||
95 | |||
96 | /* helper functions to save/restore lists of registers. */ | ||
97 | |||
98 | extern void s3c_pm_do_save(struct sleep_save *ptr, int count); | ||
99 | extern void s3c_pm_do_restore(struct sleep_save *ptr, int count); | ||
100 | extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count); | ||
101 | |||
102 | #ifdef CONFIG_PM | ||
103 | extern int s3c_irqext_wake(unsigned int irqno, unsigned int state); | ||
104 | extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state); | ||
105 | extern int s3c24xx_irq_resume(struct sys_device *dev); | ||
106 | #else | ||
107 | #define s3c_irqext_wake NULL | ||
108 | #define s3c24xx_irq_suspend NULL | ||
109 | #define s3c24xx_irq_resume NULL | ||
110 | #endif | ||
111 | |||
112 | /* PM debug functions */ | ||
113 | |||
114 | #ifdef CONFIG_SAMSUNG_PM_DEBUG | ||
115 | /** | ||
116 | * s3c_pm_dbg() - low level debug function for use in suspend/resume. | ||
117 | * @msg: The message to print. | ||
118 | * | ||
119 | * This function is used mainly to debug the resume process before the system | ||
120 | * can rely on printk/console output. It uses the low-level debugging output | ||
121 | * routine printascii() to do its work. | ||
122 | */ | ||
123 | extern void s3c_pm_dbg(const char *msg, ...); | ||
124 | |||
125 | #define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt) | ||
126 | #else | ||
127 | #define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt) | ||
128 | #endif | ||
129 | |||
130 | #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK | ||
131 | /** | ||
132 | * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs | ||
133 | * @set: set bits for the state of the LEDs | ||
134 | * @clear: clear bits for the state of the LEDs. | ||
135 | */ | ||
136 | extern void s3c_pm_debug_smdkled(u32 set, u32 clear); | ||
137 | |||
138 | #else | ||
139 | static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { } | ||
140 | #endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */ | ||
141 | |||
142 | /* suspend memory checking */ | ||
143 | |||
144 | #ifdef CONFIG_SAMSUNG_PM_CHECK | ||
145 | extern void s3c_pm_check_prepare(void); | ||
146 | extern void s3c_pm_check_restore(void); | ||
147 | extern void s3c_pm_check_cleanup(void); | ||
148 | extern void s3c_pm_check_store(void); | ||
149 | #else | ||
150 | #define s3c_pm_check_prepare() do { } while(0) | ||
151 | #define s3c_pm_check_restore() do { } while(0) | ||
152 | #define s3c_pm_check_cleanup() do { } while(0) | ||
153 | #define s3c_pm_check_store() do { } while(0) | ||
154 | #endif | ||
155 | |||
156 | /** | ||
157 | * s3c_pm_configure_extint() - ensure pins are correctly set for IRQ | ||
158 | * | ||
159 | * Setup all the necessary GPIO pins for waking the system on external | ||
160 | * interrupt. | ||
161 | */ | ||
162 | extern void s3c_pm_configure_extint(void); | ||
163 | |||
164 | /** | ||
165 | * s3c_pm_restore_gpios() - restore the state of the gpios after sleep. | ||
166 | * | ||
167 | * Restore the state of the GPIO pins after sleep, which may involve ensuring | ||
168 | * that we do not glitch the state of the pins from that the bootloader's | ||
169 | * resume code has done. | ||
170 | */ | ||
171 | extern void s3c_pm_restore_gpios(void); | ||
172 | |||
173 | /** | ||
174 | * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep. | ||
175 | * | ||
176 | * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios(). | ||
177 | */ | ||
178 | extern void s3c_pm_save_gpios(void); | ||
179 | |||
180 | /** | ||
181 | * s3c_pm_cb_flushcache - callback for assembly code | ||
182 | * | ||
183 | * Callback to issue flush_cache_all() as this call is | ||
184 | * not a directly callable object. | ||
185 | */ | ||
186 | extern void s3c_pm_cb_flushcache(void); | ||
187 | |||
188 | extern void s3c_pm_save_core(void); | ||
189 | extern void s3c_pm_restore_core(void); | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-ac97.h b/arch/arm/plat-samsung/include/plat/regs-ac97.h new file mode 100644 index 000000000000..c3878f7acb83 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-ac97.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-ac97.h | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * S3C2440 AC97 Controller | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_AC97_H | ||
14 | #define __ASM_ARCH_REGS_AC97_H __FILE__ | ||
15 | |||
16 | #define S3C_AC97_GLBCTRL (0x00) | ||
17 | |||
18 | #define S3C_AC97_GLBCTRL_CODECREADYIE (1<<22) | ||
19 | #define S3C_AC97_GLBCTRL_PCMOUTURIE (1<<21) | ||
20 | #define S3C_AC97_GLBCTRL_PCMINORIE (1<<20) | ||
21 | #define S3C_AC97_GLBCTRL_MICINORIE (1<<19) | ||
22 | #define S3C_AC97_GLBCTRL_PCMOUTTIE (1<<18) | ||
23 | #define S3C_AC97_GLBCTRL_PCMINTIE (1<<17) | ||
24 | #define S3C_AC97_GLBCTRL_MICINTIE (1<<16) | ||
25 | #define S3C_AC97_GLBCTRL_PCMOUTTM_OFF (0<<12) | ||
26 | #define S3C_AC97_GLBCTRL_PCMOUTTM_PIO (1<<12) | ||
27 | #define S3C_AC97_GLBCTRL_PCMOUTTM_DMA (2<<12) | ||
28 | #define S3C_AC97_GLBCTRL_PCMOUTTM_MASK (3<<12) | ||
29 | #define S3C_AC97_GLBCTRL_PCMINTM_OFF (0<<10) | ||
30 | #define S3C_AC97_GLBCTRL_PCMINTM_PIO (1<<10) | ||
31 | #define S3C_AC97_GLBCTRL_PCMINTM_DMA (2<<10) | ||
32 | #define S3C_AC97_GLBCTRL_PCMINTM_MASK (3<<10) | ||
33 | #define S3C_AC97_GLBCTRL_MICINTM_OFF (0<<8) | ||
34 | #define S3C_AC97_GLBCTRL_MICINTM_PIO (1<<8) | ||
35 | #define S3C_AC97_GLBCTRL_MICINTM_DMA (2<<8) | ||
36 | #define S3C_AC97_GLBCTRL_MICINTM_MASK (3<<8) | ||
37 | #define S3C_AC97_GLBCTRL_TRANSFERDATAENABLE (1<<3) | ||
38 | #define S3C_AC97_GLBCTRL_ACLINKON (1<<2) | ||
39 | #define S3C_AC97_GLBCTRL_WARMRESET (1<<1) | ||
40 | #define S3C_AC97_GLBCTRL_COLDRESET (1<<0) | ||
41 | |||
42 | #define S3C_AC97_GLBSTAT (0x04) | ||
43 | |||
44 | #define S3C_AC97_GLBSTAT_CODECREADY (1<<22) | ||
45 | #define S3C_AC97_GLBSTAT_PCMOUTUR (1<<21) | ||
46 | #define S3C_AC97_GLBSTAT_PCMINORI (1<<20) | ||
47 | #define S3C_AC97_GLBSTAT_MICINORI (1<<19) | ||
48 | #define S3C_AC97_GLBSTAT_PCMOUTTI (1<<18) | ||
49 | #define S3C_AC97_GLBSTAT_PCMINTI (1<<17) | ||
50 | #define S3C_AC97_GLBSTAT_MICINTI (1<<16) | ||
51 | #define S3C_AC97_GLBSTAT_MAINSTATE_IDLE (0<<0) | ||
52 | #define S3C_AC97_GLBSTAT_MAINSTATE_INIT (1<<0) | ||
53 | #define S3C_AC97_GLBSTAT_MAINSTATE_READY (2<<0) | ||
54 | #define S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE (3<<0) | ||
55 | #define S3C_AC97_GLBSTAT_MAINSTATE_LP (4<<0) | ||
56 | #define S3C_AC97_GLBSTAT_MAINSTATE_WARM (5<<0) | ||
57 | |||
58 | #define S3C_AC97_CODEC_CMD (0x08) | ||
59 | |||
60 | #define S3C_AC97_CODEC_CMD_READ (1<<23) | ||
61 | |||
62 | #define S3C_AC97_STAT (0x0c) | ||
63 | #define S3C_AC97_PCM_ADDR (0x10) | ||
64 | #define S3C_AC97_PCM_DATA (0x18) | ||
65 | #define S3C_AC97_MIC_DATA (0x1C) | ||
66 | |||
67 | #endif /* __ASM_ARCH_REGS_AC97_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-adc.h b/arch/arm/plat-samsung/include/plat/regs-adc.h new file mode 100644 index 000000000000..7554c4fcddb9 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-adc.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-adc.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Shannon Holland <holland@loser.net> | ||
4 | * | ||
5 | * This program is free software; yosu can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * S3C2410 ADC registers | ||
10 | */ | ||
11 | |||
12 | #ifndef __ASM_ARCH_REGS_ADC_H | ||
13 | #define __ASM_ARCH_REGS_ADC_H "regs-adc.h" | ||
14 | |||
15 | #define S3C2410_ADCREG(x) (x) | ||
16 | |||
17 | #define S3C2410_ADCCON S3C2410_ADCREG(0x00) | ||
18 | #define S3C2410_ADCTSC S3C2410_ADCREG(0x04) | ||
19 | #define S3C2410_ADCDLY S3C2410_ADCREG(0x08) | ||
20 | #define S3C2410_ADCDAT0 S3C2410_ADCREG(0x0C) | ||
21 | #define S3C2410_ADCDAT1 S3C2410_ADCREG(0x10) | ||
22 | #define S3C64XX_ADCUPDN S3C2410_ADCREG(0x14) | ||
23 | #define S3C64XX_ADCCLRINT S3C2410_ADCREG(0x18) | ||
24 | #define S3C64XX_ADCCLRINTPNDNUP S3C2410_ADCREG(0x20) | ||
25 | |||
26 | |||
27 | /* ADCCON Register Bits */ | ||
28 | #define S3C64XX_ADCCON_RESSEL (1<<16) | ||
29 | #define S3C2410_ADCCON_ECFLG (1<<15) | ||
30 | #define S3C2410_ADCCON_PRSCEN (1<<14) | ||
31 | #define S3C2410_ADCCON_PRSCVL(x) (((x)&0xFF)<<6) | ||
32 | #define S3C2410_ADCCON_PRSCVLMASK (0xFF<<6) | ||
33 | #define S3C2410_ADCCON_SELMUX(x) (((x)&0x7)<<3) | ||
34 | #define S3C2410_ADCCON_MUXMASK (0x7<<3) | ||
35 | #define S3C2410_ADCCON_STDBM (1<<2) | ||
36 | #define S3C2410_ADCCON_READ_START (1<<1) | ||
37 | #define S3C2410_ADCCON_ENABLE_START (1<<0) | ||
38 | #define S3C2410_ADCCON_STARTMASK (0x3<<0) | ||
39 | |||
40 | |||
41 | /* ADCTSC Register Bits */ | ||
42 | #define S3C2410_ADCTSC_YM_SEN (1<<7) | ||
43 | #define S3C2410_ADCTSC_YP_SEN (1<<6) | ||
44 | #define S3C2410_ADCTSC_XM_SEN (1<<5) | ||
45 | #define S3C2410_ADCTSC_XP_SEN (1<<4) | ||
46 | #define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3) | ||
47 | #define S3C2410_ADCTSC_AUTO_PST (1<<2) | ||
48 | #define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0) | ||
49 | |||
50 | /* ADCDAT0 Bits */ | ||
51 | #define S3C2410_ADCDAT0_UPDOWN (1<<15) | ||
52 | #define S3C2410_ADCDAT0_AUTO_PST (1<<14) | ||
53 | #define S3C2410_ADCDAT0_XY_PST (0x3<<12) | ||
54 | #define S3C2410_ADCDAT0_XPDATA_MASK (0x03FF) | ||
55 | |||
56 | /* ADCDAT1 Bits */ | ||
57 | #define S3C2410_ADCDAT1_UPDOWN (1<<15) | ||
58 | #define S3C2410_ADCDAT1_AUTO_PST (1<<14) | ||
59 | #define S3C2410_ADCDAT1_XY_PST (0x3<<12) | ||
60 | #define S3C2410_ADCDAT1_YPDATA_MASK (0x03FF) | ||
61 | |||
62 | #endif /* __ASM_ARCH_REGS_ADC_H */ | ||
63 | |||
64 | |||
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h new file mode 100644 index 000000000000..0f43599248ad --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h | |||
@@ -0,0 +1,235 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/regs-fb-v4.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C64XX - new-style framebuffer register definitions | ||
9 | * | ||
10 | * This is the register set for the new style framebuffer interface | ||
11 | * found from the S3C2443 onwards and specifically the S3C64XX series | ||
12 | * S3C6400 and S3C6410. | ||
13 | * | ||
14 | * The file contains the cpu specific items which change between whichever | ||
15 | * architecture is selected. See <plat/regs-fb.h> for the core definitions | ||
16 | * that are the same. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License version 2 as | ||
20 | * published by the Free Software Foundation. | ||
21 | */ | ||
22 | |||
23 | /* include the core definitions here, in case we really do need to | ||
24 | * override them at a later date. | ||
25 | */ | ||
26 | |||
27 | #include <plat/regs-fb.h> | ||
28 | |||
29 | #define S3C_FB_MAX_WIN (5) /* number of hardware windows available. */ | ||
30 | #define VIDCON1_FSTATUS_EVEN (1 << 15) | ||
31 | |||
32 | /* Video timing controls */ | ||
33 | #define VIDTCON0 (0x10) | ||
34 | #define VIDTCON1 (0x14) | ||
35 | #define VIDTCON2 (0x18) | ||
36 | |||
37 | /* Window position controls */ | ||
38 | |||
39 | #define WINCON(_win) (0x20 + ((_win) * 4)) | ||
40 | |||
41 | /* OSD1 and OSD4 do not have register D */ | ||
42 | |||
43 | #define VIDOSD_A(_win) (0x40 + ((_win) * 16)) | ||
44 | #define VIDOSD_B(_win) (0x44 + ((_win) * 16)) | ||
45 | #define VIDOSD_C(_win) (0x48 + ((_win) * 16)) | ||
46 | #define VIDOSD_D(_win) (0x4C + ((_win) * 16)) | ||
47 | |||
48 | |||
49 | #define VIDINTCON0 (0x130) | ||
50 | |||
51 | #define WxKEYCONy(_win, _con) ((0x140 + ((_win) * 8)) + ((_con) * 4)) | ||
52 | |||
53 | /* WINCONx */ | ||
54 | |||
55 | #define WINCONx_CSCWIDTH_MASK (0x3 << 26) | ||
56 | #define WINCONx_CSCWIDTH_SHIFT (26) | ||
57 | #define WINCONx_CSCWIDTH_WIDE (0x0 << 26) | ||
58 | #define WINCONx_CSCWIDTH_NARROW (0x3 << 26) | ||
59 | |||
60 | #define WINCONx_ENLOCAL (1 << 22) | ||
61 | #define WINCONx_BUFSTATUS (1 << 21) | ||
62 | #define WINCONx_BUFSEL (1 << 20) | ||
63 | #define WINCONx_BUFAUTOEN (1 << 19) | ||
64 | #define WINCONx_YCbCr (1 << 13) | ||
65 | |||
66 | #define WINCON1_LOCALSEL_CAMIF (1 << 23) | ||
67 | |||
68 | #define WINCON2_LOCALSEL_CAMIF (1 << 23) | ||
69 | #define WINCON2_BLD_PIX (1 << 6) | ||
70 | |||
71 | #define WINCON2_ALPHA_SEL (1 << 1) | ||
72 | #define WINCON2_BPPMODE_MASK (0xf << 2) | ||
73 | #define WINCON2_BPPMODE_SHIFT (2) | ||
74 | #define WINCON2_BPPMODE_1BPP (0x0 << 2) | ||
75 | #define WINCON2_BPPMODE_2BPP (0x1 << 2) | ||
76 | #define WINCON2_BPPMODE_4BPP (0x2 << 2) | ||
77 | #define WINCON2_BPPMODE_8BPP_1232 (0x4 << 2) | ||
78 | #define WINCON2_BPPMODE_16BPP_565 (0x5 << 2) | ||
79 | #define WINCON2_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
80 | #define WINCON2_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
81 | #define WINCON2_BPPMODE_18BPP_666 (0x8 << 2) | ||
82 | #define WINCON2_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
83 | #define WINCON2_BPPMODE_19BPP_A1666 (0xa << 2) | ||
84 | #define WINCON2_BPPMODE_24BPP_888 (0xb << 2) | ||
85 | #define WINCON2_BPPMODE_24BPP_A1887 (0xc << 2) | ||
86 | #define WINCON2_BPPMODE_25BPP_A1888 (0xd << 2) | ||
87 | #define WINCON2_BPPMODE_28BPP_A4888 (0xd << 2) | ||
88 | |||
89 | #define WINCON3_BLD_PIX (1 << 6) | ||
90 | |||
91 | #define WINCON3_ALPHA_SEL (1 << 1) | ||
92 | #define WINCON3_BPPMODE_MASK (0xf << 2) | ||
93 | #define WINCON3_BPPMODE_SHIFT (2) | ||
94 | #define WINCON3_BPPMODE_1BPP (0x0 << 2) | ||
95 | #define WINCON3_BPPMODE_2BPP (0x1 << 2) | ||
96 | #define WINCON3_BPPMODE_4BPP (0x2 << 2) | ||
97 | #define WINCON3_BPPMODE_16BPP_565 (0x5 << 2) | ||
98 | #define WINCON3_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
99 | #define WINCON3_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
100 | #define WINCON3_BPPMODE_18BPP_666 (0x8 << 2) | ||
101 | #define WINCON3_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
102 | #define WINCON3_BPPMODE_19BPP_A1666 (0xa << 2) | ||
103 | #define WINCON3_BPPMODE_24BPP_888 (0xb << 2) | ||
104 | #define WINCON3_BPPMODE_24BPP_A1887 (0xc << 2) | ||
105 | #define WINCON3_BPPMODE_25BPP_A1888 (0xd << 2) | ||
106 | #define WINCON3_BPPMODE_28BPP_A4888 (0xd << 2) | ||
107 | |||
108 | #define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5) | ||
109 | #define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5) | ||
110 | #define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5) | ||
111 | |||
112 | #define DITHMODE (0x170) | ||
113 | #define WINxMAP(_win) (0x180 + ((_win) * 4)) | ||
114 | |||
115 | |||
116 | #define DITHMODE_R_POS_MASK (0x3 << 5) | ||
117 | #define DITHMODE_R_POS_SHIFT (5) | ||
118 | #define DITHMODE_R_POS_8BIT (0x0 << 5) | ||
119 | #define DITHMODE_R_POS_6BIT (0x1 << 5) | ||
120 | #define DITHMODE_R_POS_5BIT (0x2 << 5) | ||
121 | |||
122 | #define DITHMODE_G_POS_MASK (0x3 << 3) | ||
123 | #define DITHMODE_G_POS_SHIFT (3) | ||
124 | #define DITHMODE_G_POS_8BIT (0x0 << 3) | ||
125 | #define DITHMODE_G_POS_6BIT (0x1 << 3) | ||
126 | #define DITHMODE_G_POS_5BIT (0x2 << 3) | ||
127 | |||
128 | #define DITHMODE_B_POS_MASK (0x3 << 1) | ||
129 | #define DITHMODE_B_POS_SHIFT (1) | ||
130 | #define DITHMODE_B_POS_8BIT (0x0 << 1) | ||
131 | #define DITHMODE_B_POS_6BIT (0x1 << 1) | ||
132 | #define DITHMODE_B_POS_5BIT (0x2 << 1) | ||
133 | |||
134 | #define DITHMODE_DITH_EN (1 << 0) | ||
135 | |||
136 | #define WPALCON (0x1A0) | ||
137 | |||
138 | /* Palette control */ | ||
139 | /* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L), | ||
140 | * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */ | ||
141 | #define WPALCON_W4PAL_16BPP_A555 (1 << 8) | ||
142 | #define WPALCON_W3PAL_16BPP_A555 (1 << 7) | ||
143 | #define WPALCON_W2PAL_16BPP_A555 (1 << 6) | ||
144 | |||
145 | |||
146 | /* system specific implementation code for palette sizes, and other | ||
147 | * information that changes depending on which architecture is being | ||
148 | * compiled. | ||
149 | */ | ||
150 | |||
151 | /* return true if window _win has OSD register D */ | ||
152 | #define s3c_fb_has_osd_d(_win) ((_win) != 4 && (_win) != 0) | ||
153 | |||
154 | static inline unsigned int s3c_fb_win_pal_size(unsigned int win) | ||
155 | { | ||
156 | if (win < 2) | ||
157 | return 256; | ||
158 | if (win < 4) | ||
159 | return 16; | ||
160 | if (win == 4) | ||
161 | return 4; | ||
162 | |||
163 | BUG(); /* shouldn't get here */ | ||
164 | } | ||
165 | |||
166 | static inline int s3c_fb_validate_win_bpp(unsigned int win, unsigned int bpp) | ||
167 | { | ||
168 | /* all windows can do 1/2 bpp */ | ||
169 | |||
170 | if ((bpp == 25 || bpp == 19) && win == 0) | ||
171 | return 0; /* win 0 does not have 19 or 25bpp modes */ | ||
172 | |||
173 | if (bpp == 4 && win == 4) | ||
174 | return 0; | ||
175 | |||
176 | if (bpp == 8 && (win >= 3)) | ||
177 | return 0; /* win 3/4 cannot do 8bpp in any mode */ | ||
178 | |||
179 | return 1; | ||
180 | } | ||
181 | |||
182 | static inline int s3c_fb_pal_is16(unsigned int window) | ||
183 | { | ||
184 | return window > 1; | ||
185 | } | ||
186 | |||
187 | struct s3c_fb_palette { | ||
188 | struct fb_bitfield r; | ||
189 | struct fb_bitfield g; | ||
190 | struct fb_bitfield b; | ||
191 | struct fb_bitfield a; | ||
192 | }; | ||
193 | |||
194 | static inline void s3c_fb_init_palette(unsigned int window, | ||
195 | struct s3c_fb_palette *palette) | ||
196 | { | ||
197 | if (window < 2) { | ||
198 | /* Windows 0/1 are 8/8/8 or A/8/8/8 */ | ||
199 | palette->r.offset = 16; | ||
200 | palette->r.length = 8; | ||
201 | palette->g.offset = 8; | ||
202 | palette->g.length = 8; | ||
203 | palette->b.offset = 0; | ||
204 | palette->b.length = 8; | ||
205 | } else { | ||
206 | /* currently we assume RGB 5/6/5 */ | ||
207 | palette->r.offset = 11; | ||
208 | palette->r.length = 5; | ||
209 | palette->g.offset = 5; | ||
210 | palette->g.length = 6; | ||
211 | palette->b.offset = 0; | ||
212 | palette->b.length = 5; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /* Notes on per-window bpp settings | ||
217 | * | ||
218 | * Value Win0 Win1 Win2 Win3 Win 4 | ||
219 | * 0000 1(P) 1(P) 1(P) 1(P) 1(P) | ||
220 | * 0001 2(P) 2(P) 2(P) 2(P) 2(P) | ||
221 | * 0010 4(P) 4(P) 4(P) 4(P) -none- | ||
222 | * 0011 8(P) 8(P) -none- -none- -none- | ||
223 | * 0100 -none- 8(A232) 8(A232) -none- -none- | ||
224 | * 0101 16(565) 16(565) 16(565) 16(565) 16(565) | ||
225 | * 0110 -none- 16(A555) 16(A555) 16(A555) 16(A555) | ||
226 | * 0111 16(I555) 16(I565) 16(I555) 16(I555) 16(I555) | ||
227 | * 1000 18(666) 18(666) 18(666) 18(666) 18(666) | ||
228 | * 1001 -none- 18(A665) 18(A665) 18(A665) 16(A665) | ||
229 | * 1010 -none- 19(A666) 19(A666) 19(A666) 19(A666) | ||
230 | * 1011 24(888) 24(888) 24(888) 24(888) 24(888) | ||
231 | * 1100 -none- 24(A887) 24(A887) 24(A887) 24(A887) | ||
232 | * 1101 -none- 25(A888) 25(A888) 25(A888) 25(A888) | ||
233 | * 1110 -none- -none- -none- -none- -none- | ||
234 | * 1111 -none- -none- -none- -none- -none- | ||
235 | */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h new file mode 100644 index 000000000000..0ef806e50344 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-fb.h | |||
@@ -0,0 +1,366 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/regs-fb.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C Platform - new-style framebuffer register definitions | ||
9 | * | ||
10 | * This is the register set for the new style framebuffer interface | ||
11 | * found from the S3C2443 onwards into the S3C2416, S3C2450 and the | ||
12 | * S3C64XX series such as the S3C6400 and S3C6410. | ||
13 | * | ||
14 | * The file does not contain the cpu specific items which are based on | ||
15 | * whichever architecture is selected, it only contains the core of the | ||
16 | * register set. See <mach/regs-fb.h> to get the specifics. | ||
17 | * | ||
18 | * Note, we changed to using regs-fb.h as it avoids any clashes with | ||
19 | * the original regs-lcd.h so out of the way of regs-lcd.h as well as | ||
20 | * indicating the newer block is much more than just an LCD interface. | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or modify | ||
23 | * it under the terms of the GNU General Public License version 2 as | ||
24 | * published by the Free Software Foundation. | ||
25 | */ | ||
26 | |||
27 | /* Please do not include this file directly, use <mach/regs-fb.h> to | ||
28 | * ensure all the localised SoC support is included as necessary. | ||
29 | */ | ||
30 | |||
31 | /* VIDCON0 */ | ||
32 | |||
33 | #define VIDCON0 (0x00) | ||
34 | #define VIDCON0_INTERLACE (1 << 29) | ||
35 | #define VIDCON0_VIDOUT_MASK (0x3 << 26) | ||
36 | #define VIDCON0_VIDOUT_SHIFT (26) | ||
37 | #define VIDCON0_VIDOUT_RGB (0x0 << 26) | ||
38 | #define VIDCON0_VIDOUT_TV (0x1 << 26) | ||
39 | #define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26) | ||
40 | #define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26) | ||
41 | |||
42 | #define VIDCON0_L1_DATA_MASK (0x7 << 23) | ||
43 | #define VIDCON0_L1_DATA_SHIFT (23) | ||
44 | #define VIDCON0_L1_DATA_16BPP (0x0 << 23) | ||
45 | #define VIDCON0_L1_DATA_18BPP16 (0x1 << 23) | ||
46 | #define VIDCON0_L1_DATA_18BPP9 (0x2 << 23) | ||
47 | #define VIDCON0_L1_DATA_24BPP (0x3 << 23) | ||
48 | #define VIDCON0_L1_DATA_18BPP (0x4 << 23) | ||
49 | #define VIDCON0_L1_DATA_16BPP8 (0x5 << 23) | ||
50 | |||
51 | #define VIDCON0_L0_DATA_MASK (0x7 << 20) | ||
52 | #define VIDCON0_L0_DATA_SHIFT (20) | ||
53 | #define VIDCON0_L0_DATA_16BPP (0x0 << 20) | ||
54 | #define VIDCON0_L0_DATA_18BPP16 (0x1 << 20) | ||
55 | #define VIDCON0_L0_DATA_18BPP9 (0x2 << 20) | ||
56 | #define VIDCON0_L0_DATA_24BPP (0x3 << 20) | ||
57 | #define VIDCON0_L0_DATA_18BPP (0x4 << 20) | ||
58 | #define VIDCON0_L0_DATA_16BPP8 (0x5 << 20) | ||
59 | |||
60 | #define VIDCON0_PNRMODE_MASK (0x3 << 17) | ||
61 | #define VIDCON0_PNRMODE_SHIFT (17) | ||
62 | #define VIDCON0_PNRMODE_RGB (0x0 << 17) | ||
63 | #define VIDCON0_PNRMODE_BGR (0x1 << 17) | ||
64 | #define VIDCON0_PNRMODE_SERIAL_RGB (0x2 << 17) | ||
65 | #define VIDCON0_PNRMODE_SERIAL_BGR (0x3 << 17) | ||
66 | |||
67 | #define VIDCON0_CLKVALUP (1 << 16) | ||
68 | #define VIDCON0_CLKVAL_F_MASK (0xff << 6) | ||
69 | #define VIDCON0_CLKVAL_F_SHIFT (6) | ||
70 | #define VIDCON0_CLKVAL_F_LIMIT (0xff) | ||
71 | #define VIDCON0_CLKVAL_F(_x) ((_x) << 6) | ||
72 | #define VIDCON0_VLCKFREE (1 << 5) | ||
73 | #define VIDCON0_CLKDIR (1 << 4) | ||
74 | |||
75 | #define VIDCON0_CLKSEL_MASK (0x3 << 2) | ||
76 | #define VIDCON0_CLKSEL_SHIFT (2) | ||
77 | #define VIDCON0_CLKSEL_HCLK (0x0 << 2) | ||
78 | #define VIDCON0_CLKSEL_LCD (0x1 << 2) | ||
79 | #define VIDCON0_CLKSEL_27M (0x3 << 2) | ||
80 | |||
81 | #define VIDCON0_ENVID (1 << 1) | ||
82 | #define VIDCON0_ENVID_F (1 << 0) | ||
83 | |||
84 | #define VIDCON1 (0x04) | ||
85 | #define VIDCON1_LINECNT_MASK (0x7ff << 16) | ||
86 | #define VIDCON1_LINECNT_SHIFT (16) | ||
87 | #define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff) | ||
88 | #define VIDCON1_VSTATUS_MASK (0x3 << 13) | ||
89 | #define VIDCON1_VSTATUS_SHIFT (13) | ||
90 | #define VIDCON1_VSTATUS_VSYNC (0x0 << 13) | ||
91 | #define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13) | ||
92 | #define VIDCON1_VSTATUS_ACTIVE (0x2 << 13) | ||
93 | #define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13) | ||
94 | |||
95 | #define VIDCON1_INV_VCLK (1 << 7) | ||
96 | #define VIDCON1_INV_HSYNC (1 << 6) | ||
97 | #define VIDCON1_INV_VSYNC (1 << 5) | ||
98 | #define VIDCON1_INV_VDEN (1 << 4) | ||
99 | |||
100 | /* VIDCON2 */ | ||
101 | |||
102 | #define VIDCON2 (0x08) | ||
103 | #define VIDCON2_EN601 (1 << 23) | ||
104 | #define VIDCON2_TVFMTSEL_SW (1 << 14) | ||
105 | |||
106 | #define VIDCON2_TVFMTSEL1_MASK (0x3 << 12) | ||
107 | #define VIDCON2_TVFMTSEL1_SHIFT (12) | ||
108 | #define VIDCON2_TVFMTSEL1_RGB (0x0 << 12) | ||
109 | #define VIDCON2_TVFMTSEL1_YUV422 (0x1 << 12) | ||
110 | #define VIDCON2_TVFMTSEL1_YUV444 (0x2 << 12) | ||
111 | |||
112 | #define VIDCON2_ORGYCbCr (1 << 8) | ||
113 | #define VIDCON2_YUVORDCrCb (1 << 7) | ||
114 | |||
115 | /* VIDTCON0 */ | ||
116 | |||
117 | #define VIDTCON0_VBPDE_MASK (0xff << 24) | ||
118 | #define VIDTCON0_VBPDE_SHIFT (24) | ||
119 | #define VIDTCON0_VBPDE_LIMIT (0xff) | ||
120 | #define VIDTCON0_VBPDE(_x) ((_x) << 24) | ||
121 | |||
122 | #define VIDTCON0_VBPD_MASK (0xff << 16) | ||
123 | #define VIDTCON0_VBPD_SHIFT (16) | ||
124 | #define VIDTCON0_VBPD_LIMIT (0xff) | ||
125 | #define VIDTCON0_VBPD(_x) ((_x) << 16) | ||
126 | |||
127 | #define VIDTCON0_VFPD_MASK (0xff << 8) | ||
128 | #define VIDTCON0_VFPD_SHIFT (8) | ||
129 | #define VIDTCON0_VFPD_LIMIT (0xff) | ||
130 | #define VIDTCON0_VFPD(_x) ((_x) << 8) | ||
131 | |||
132 | #define VIDTCON0_VSPW_MASK (0xff << 0) | ||
133 | #define VIDTCON0_VSPW_SHIFT (0) | ||
134 | #define VIDTCON0_VSPW_LIMIT (0xff) | ||
135 | #define VIDTCON0_VSPW(_x) ((_x) << 0) | ||
136 | |||
137 | /* VIDTCON1 */ | ||
138 | |||
139 | #define VIDTCON1_VFPDE_MASK (0xff << 24) | ||
140 | #define VIDTCON1_VFPDE_SHIFT (24) | ||
141 | #define VIDTCON1_VFPDE_LIMIT (0xff) | ||
142 | #define VIDTCON1_VFPDE(_x) ((_x) << 24) | ||
143 | |||
144 | #define VIDTCON1_HBPD_MASK (0xff << 16) | ||
145 | #define VIDTCON1_HBPD_SHIFT (16) | ||
146 | #define VIDTCON1_HBPD_LIMIT (0xff) | ||
147 | #define VIDTCON1_HBPD(_x) ((_x) << 16) | ||
148 | |||
149 | #define VIDTCON1_HFPD_MASK (0xff << 8) | ||
150 | #define VIDTCON1_HFPD_SHIFT (8) | ||
151 | #define VIDTCON1_HFPD_LIMIT (0xff) | ||
152 | #define VIDTCON1_HFPD(_x) ((_x) << 8) | ||
153 | |||
154 | #define VIDTCON1_HSPW_MASK (0xff << 0) | ||
155 | #define VIDTCON1_HSPW_SHIFT (0) | ||
156 | #define VIDTCON1_HSPW_LIMIT (0xff) | ||
157 | #define VIDTCON1_HSPW(_x) ((_x) << 0) | ||
158 | |||
159 | #define VIDTCON2 (0x18) | ||
160 | #define VIDTCON2_LINEVAL_MASK (0x7ff << 11) | ||
161 | #define VIDTCON2_LINEVAL_SHIFT (11) | ||
162 | #define VIDTCON2_LINEVAL_LIMIT (0x7ff) | ||
163 | #define VIDTCON2_LINEVAL(_x) ((_x) << 11) | ||
164 | |||
165 | #define VIDTCON2_HOZVAL_MASK (0x7ff << 0) | ||
166 | #define VIDTCON2_HOZVAL_SHIFT (0) | ||
167 | #define VIDTCON2_HOZVAL_LIMIT (0x7ff) | ||
168 | #define VIDTCON2_HOZVAL(_x) ((_x) << 0) | ||
169 | |||
170 | /* WINCONx */ | ||
171 | |||
172 | |||
173 | #define WINCONx_BITSWP (1 << 18) | ||
174 | #define WINCONx_BYTSWP (1 << 17) | ||
175 | #define WINCONx_HAWSWP (1 << 16) | ||
176 | #define WINCONx_BURSTLEN_MASK (0x3 << 9) | ||
177 | #define WINCONx_BURSTLEN_SHIFT (9) | ||
178 | #define WINCONx_BURSTLEN_16WORD (0x0 << 9) | ||
179 | #define WINCONx_BURSTLEN_8WORD (0x1 << 9) | ||
180 | #define WINCONx_BURSTLEN_4WORD (0x2 << 9) | ||
181 | |||
182 | #define WINCONx_ENWIN (1 << 0) | ||
183 | #define WINCON0_BPPMODE_MASK (0xf << 2) | ||
184 | #define WINCON0_BPPMODE_SHIFT (2) | ||
185 | #define WINCON0_BPPMODE_1BPP (0x0 << 2) | ||
186 | #define WINCON0_BPPMODE_2BPP (0x1 << 2) | ||
187 | #define WINCON0_BPPMODE_4BPP (0x2 << 2) | ||
188 | #define WINCON0_BPPMODE_8BPP_PALETTE (0x3 << 2) | ||
189 | #define WINCON0_BPPMODE_16BPP_565 (0x5 << 2) | ||
190 | #define WINCON0_BPPMODE_16BPP_1555 (0x7 << 2) | ||
191 | #define WINCON0_BPPMODE_18BPP_666 (0x8 << 2) | ||
192 | #define WINCON0_BPPMODE_24BPP_888 (0xb << 2) | ||
193 | |||
194 | #define WINCON1_BLD_PIX (1 << 6) | ||
195 | |||
196 | #define WINCON1_ALPHA_SEL (1 << 1) | ||
197 | #define WINCON1_BPPMODE_MASK (0xf << 2) | ||
198 | #define WINCON1_BPPMODE_SHIFT (2) | ||
199 | #define WINCON1_BPPMODE_1BPP (0x0 << 2) | ||
200 | #define WINCON1_BPPMODE_2BPP (0x1 << 2) | ||
201 | #define WINCON1_BPPMODE_4BPP (0x2 << 2) | ||
202 | #define WINCON1_BPPMODE_8BPP_PALETTE (0x3 << 2) | ||
203 | #define WINCON1_BPPMODE_8BPP_1232 (0x4 << 2) | ||
204 | #define WINCON1_BPPMODE_16BPP_565 (0x5 << 2) | ||
205 | #define WINCON1_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
206 | #define WINCON1_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
207 | #define WINCON1_BPPMODE_18BPP_666 (0x8 << 2) | ||
208 | #define WINCON1_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
209 | #define WINCON1_BPPMODE_19BPP_A1666 (0xa << 2) | ||
210 | #define WINCON1_BPPMODE_24BPP_888 (0xb << 2) | ||
211 | #define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2) | ||
212 | #define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2) | ||
213 | #define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2) | ||
214 | |||
215 | |||
216 | #define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) | ||
217 | #define VIDOSDxA_TOPLEFT_X_SHIFT (11) | ||
218 | #define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff) | ||
219 | #define VIDOSDxA_TOPLEFT_X(_x) ((_x) << 11) | ||
220 | |||
221 | #define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0) | ||
222 | #define VIDOSDxA_TOPLEFT_Y_SHIFT (0) | ||
223 | #define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff) | ||
224 | #define VIDOSDxA_TOPLEFT_Y(_x) ((_x) << 0) | ||
225 | |||
226 | #define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11) | ||
227 | #define VIDOSDxB_BOTRIGHT_X_SHIFT (11) | ||
228 | #define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff) | ||
229 | #define VIDOSDxB_BOTRIGHT_X(_x) ((_x) << 11) | ||
230 | |||
231 | #define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0) | ||
232 | #define VIDOSDxB_BOTRIGHT_Y_SHIFT (0) | ||
233 | #define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff) | ||
234 | #define VIDOSDxB_BOTRIGHT_Y(_x) ((_x) << 0) | ||
235 | |||
236 | /* For VIDOSD[1..4]C */ | ||
237 | #define VIDISD14C_ALPHA0_R(_x) ((_x) << 20) | ||
238 | #define VIDISD14C_ALPHA0_G_MASK (0xf << 16) | ||
239 | #define VIDISD14C_ALPHA0_G_SHIFT (16) | ||
240 | #define VIDISD14C_ALPHA0_G_LIMIT (0xf) | ||
241 | #define VIDISD14C_ALPHA0_G(_x) ((_x) << 16) | ||
242 | #define VIDISD14C_ALPHA0_B_MASK (0xf << 12) | ||
243 | #define VIDISD14C_ALPHA0_B_SHIFT (12) | ||
244 | #define VIDISD14C_ALPHA0_B_LIMIT (0xf) | ||
245 | #define VIDISD14C_ALPHA0_B(_x) ((_x) << 12) | ||
246 | #define VIDISD14C_ALPHA1_R_MASK (0xf << 8) | ||
247 | #define VIDISD14C_ALPHA1_R_SHIFT (8) | ||
248 | #define VIDISD14C_ALPHA1_R_LIMIT (0xf) | ||
249 | #define VIDISD14C_ALPHA1_R(_x) ((_x) << 8) | ||
250 | #define VIDISD14C_ALPHA1_G_MASK (0xf << 4) | ||
251 | #define VIDISD14C_ALPHA1_G_SHIFT (4) | ||
252 | #define VIDISD14C_ALPHA1_G_LIMIT (0xf) | ||
253 | #define VIDISD14C_ALPHA1_G(_x) ((_x) << 4) | ||
254 | #define VIDISD14C_ALPHA1_B_MASK (0xf << 0) | ||
255 | #define VIDISD14C_ALPHA1_B_SHIFT (0) | ||
256 | #define VIDISD14C_ALPHA1_B_LIMIT (0xf) | ||
257 | #define VIDISD14C_ALPHA1_B(_x) ((_x) << 0) | ||
258 | |||
259 | /* Video buffer addresses */ | ||
260 | #define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8)) | ||
261 | #define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8)) | ||
262 | #define VIDW_BUF_END(_buff) (0xD0 + ((_buff) * 8)) | ||
263 | #define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) | ||
264 | #define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4)) | ||
265 | |||
266 | #define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13) | ||
267 | #define VIDW_BUF_SIZE_OFFSET_SHIFT (13) | ||
268 | #define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff) | ||
269 | #define VIDW_BUF_SIZE_OFFSET(_x) ((_x) << 13) | ||
270 | |||
271 | #define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0) | ||
272 | #define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0) | ||
273 | #define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff) | ||
274 | #define VIDW_BUF_SIZE_PAGEWIDTH(_x) ((_x) << 0) | ||
275 | |||
276 | /* Interrupt controls and status */ | ||
277 | |||
278 | #define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20) | ||
279 | #define VIDINTCON0_FIFOINTERVAL_SHIFT (20) | ||
280 | #define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f) | ||
281 | #define VIDINTCON0_FIFOINTERVAL(_x) ((_x) << 20) | ||
282 | |||
283 | #define VIDINTCON0_INT_SYSMAINCON (1 << 19) | ||
284 | #define VIDINTCON0_INT_SYSSUBCON (1 << 18) | ||
285 | #define VIDINTCON0_INT_I80IFDONE (1 << 17) | ||
286 | |||
287 | #define VIDINTCON0_FRAMESEL0_MASK (0x3 << 15) | ||
288 | #define VIDINTCON0_FRAMESEL0_SHIFT (15) | ||
289 | #define VIDINTCON0_FRAMESEL0_BACKPORCH (0x0 << 15) | ||
290 | #define VIDINTCON0_FRAMESEL0_VSYNC (0x1 << 15) | ||
291 | #define VIDINTCON0_FRAMESEL0_ACTIVE (0x2 << 15) | ||
292 | #define VIDINTCON0_FRAMESEL0_FRONTPORCH (0x3 << 15) | ||
293 | |||
294 | #define VIDINTCON0_FRAMESEL1 (1 << 14) | ||
295 | #define VIDINTCON0_FRAMESEL1_NONE (0x0 << 14) | ||
296 | #define VIDINTCON0_FRAMESEL1_BACKPORCH (0x1 << 14) | ||
297 | #define VIDINTCON0_FRAMESEL1_VSYNC (0x2 << 14) | ||
298 | #define VIDINTCON0_FRAMESEL1_FRONTPORCH (0x3 << 14) | ||
299 | |||
300 | #define VIDINTCON0_INT_FRAME (1 << 12) | ||
301 | #define VIDINTCON0_FIFIOSEL_MASK (0x7f << 5) | ||
302 | #define VIDINTCON0_FIFIOSEL_SHIFT (5) | ||
303 | #define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5) | ||
304 | #define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5) | ||
305 | |||
306 | #define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2) | ||
307 | #define VIDINTCON0_FIFOLEVEL_SHIFT (2) | ||
308 | #define VIDINTCON0_FIFOLEVEL_TO25PC (0x0 << 2) | ||
309 | #define VIDINTCON0_FIFOLEVEL_TO50PC (0x1 << 2) | ||
310 | #define VIDINTCON0_FIFOLEVEL_TO75PC (0x2 << 2) | ||
311 | #define VIDINTCON0_FIFOLEVEL_EMPTY (0x3 << 2) | ||
312 | #define VIDINTCON0_FIFOLEVEL_FULL (0x4 << 2) | ||
313 | |||
314 | #define VIDINTCON0_INT_FIFO_MASK (0x3 << 0) | ||
315 | #define VIDINTCON0_INT_FIFO_SHIFT (0) | ||
316 | #define VIDINTCON0_INT_ENABLE (1 << 0) | ||
317 | |||
318 | #define VIDINTCON1 (0x134) | ||
319 | #define VIDINTCON1_INT_I180 (1 << 2) | ||
320 | #define VIDINTCON1_INT_FRAME (1 << 1) | ||
321 | #define VIDINTCON1_INT_FIFO (1 << 0) | ||
322 | |||
323 | /* Window colour-key control registers */ | ||
324 | |||
325 | #define WxKEYCON0_KEYBL_EN (1 << 26) | ||
326 | #define WxKEYCON0_KEYEN_F (1 << 25) | ||
327 | #define WxKEYCON0_DIRCON (1 << 24) | ||
328 | #define WxKEYCON0_COMPKEY_MASK (0xffffff << 0) | ||
329 | #define WxKEYCON0_COMPKEY_SHIFT (0) | ||
330 | #define WxKEYCON0_COMPKEY_LIMIT (0xffffff) | ||
331 | #define WxKEYCON0_COMPKEY(_x) ((_x) << 0) | ||
332 | #define WxKEYCON1_COLVAL_MASK (0xffffff << 0) | ||
333 | #define WxKEYCON1_COLVAL_SHIFT (0) | ||
334 | #define WxKEYCON1_COLVAL_LIMIT (0xffffff) | ||
335 | #define WxKEYCON1_COLVAL(_x) ((_x) << 0) | ||
336 | |||
337 | |||
338 | /* Window blanking (MAP) */ | ||
339 | |||
340 | #define WINxMAP_MAP (1 << 24) | ||
341 | #define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0) | ||
342 | #define WINxMAP_MAP_COLOUR_SHIFT (0) | ||
343 | #define WINxMAP_MAP_COLOUR_LIMIT (0xffffff) | ||
344 | #define WINxMAP_MAP_COLOUR(_x) ((_x) << 0) | ||
345 | |||
346 | #define WPALCON_PAL_UPDATE (1 << 9) | ||
347 | #define WPALCON_W1PAL_MASK (0x7 << 3) | ||
348 | #define WPALCON_W1PAL_SHIFT (3) | ||
349 | #define WPALCON_W1PAL_25BPP_A888 (0x0 << 3) | ||
350 | #define WPALCON_W1PAL_24BPP (0x1 << 3) | ||
351 | #define WPALCON_W1PAL_19BPP_A666 (0x2 << 3) | ||
352 | #define WPALCON_W1PAL_18BPP_A665 (0x3 << 3) | ||
353 | #define WPALCON_W1PAL_18BPP (0x4 << 3) | ||
354 | #define WPALCON_W1PAL_16BPP_A555 (0x5 << 3) | ||
355 | #define WPALCON_W1PAL_16BPP_565 (0x6 << 3) | ||
356 | |||
357 | #define WPALCON_W0PAL_MASK (0x7 << 0) | ||
358 | #define WPALCON_W0PAL_SHIFT (0) | ||
359 | #define WPALCON_W0PAL_25BPP_A888 (0x0 << 0) | ||
360 | #define WPALCON_W0PAL_24BPP (0x1 << 0) | ||
361 | #define WPALCON_W0PAL_19BPP_A666 (0x2 << 0) | ||
362 | #define WPALCON_W0PAL_18BPP_A665 (0x3 << 0) | ||
363 | #define WPALCON_W0PAL_18BPP (0x4 << 0) | ||
364 | #define WPALCON_W0PAL_16BPP_A555 (0x5 << 0) | ||
365 | #define WPALCON_W0PAL_16BPP_565 (0x6 << 0) | ||
366 | |||
diff --git a/arch/arm/plat-samsung/include/plat/regs-iic.h b/arch/arm/plat-samsung/include/plat/regs-iic.h new file mode 100644 index 000000000000..2f7c17de8ac8 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-iic.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-iic.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * S3C2410 I2C Controller | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_IIC_H | ||
14 | #define __ASM_ARCH_REGS_IIC_H __FILE__ | ||
15 | |||
16 | /* see s3c2410x user guide, v1.1, section 9 (p447) for more info */ | ||
17 | |||
18 | #define S3C2410_IICREG(x) (x) | ||
19 | |||
20 | #define S3C2410_IICCON S3C2410_IICREG(0x00) | ||
21 | #define S3C2410_IICSTAT S3C2410_IICREG(0x04) | ||
22 | #define S3C2410_IICADD S3C2410_IICREG(0x08) | ||
23 | #define S3C2410_IICDS S3C2410_IICREG(0x0C) | ||
24 | #define S3C2440_IICLC S3C2410_IICREG(0x10) | ||
25 | |||
26 | #define S3C2410_IICCON_ACKEN (1<<7) | ||
27 | #define S3C2410_IICCON_TXDIV_16 (0<<6) | ||
28 | #define S3C2410_IICCON_TXDIV_512 (1<<6) | ||
29 | #define S3C2410_IICCON_IRQEN (1<<5) | ||
30 | #define S3C2410_IICCON_IRQPEND (1<<4) | ||
31 | #define S3C2410_IICCON_SCALE(x) ((x)&15) | ||
32 | #define S3C2410_IICCON_SCALEMASK (0xf) | ||
33 | |||
34 | #define S3C2410_IICSTAT_MASTER_RX (2<<6) | ||
35 | #define S3C2410_IICSTAT_MASTER_TX (3<<6) | ||
36 | #define S3C2410_IICSTAT_SLAVE_RX (0<<6) | ||
37 | #define S3C2410_IICSTAT_SLAVE_TX (1<<6) | ||
38 | #define S3C2410_IICSTAT_MODEMASK (3<<6) | ||
39 | |||
40 | #define S3C2410_IICSTAT_START (1<<5) | ||
41 | #define S3C2410_IICSTAT_BUSBUSY (1<<5) | ||
42 | #define S3C2410_IICSTAT_TXRXEN (1<<4) | ||
43 | #define S3C2410_IICSTAT_ARBITR (1<<3) | ||
44 | #define S3C2410_IICSTAT_ASSLAVE (1<<2) | ||
45 | #define S3C2410_IICSTAT_ADDR0 (1<<1) | ||
46 | #define S3C2410_IICSTAT_LASTBIT (1<<0) | ||
47 | |||
48 | #define S3C2410_IICLC_SDA_DELAY0 (0 << 0) | ||
49 | #define S3C2410_IICLC_SDA_DELAY5 (1 << 0) | ||
50 | #define S3C2410_IICLC_SDA_DELAY10 (2 << 0) | ||
51 | #define S3C2410_IICLC_SDA_DELAY15 (3 << 0) | ||
52 | #define S3C2410_IICLC_SDA_DELAY_MASK (3 << 0) | ||
53 | |||
54 | #define S3C2410_IICLC_FILTER_ON (1<<2) | ||
55 | |||
56 | #endif /* __ASM_ARCH_REGS_IIC_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-irqtype.h b/arch/arm/plat-samsung/include/plat/regs-irqtype.h new file mode 100644 index 000000000000..c63cd3fc5ad3 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-irqtype.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/regs-irqtype.h | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C - IRQ detection types. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | /* values for S3C2410_EXTINT0/1/2 and other cpus in the series, including | ||
15 | * the S3C64XX | ||
16 | */ | ||
17 | #define S3C2410_EXTINT_LOWLEV (0x00) | ||
18 | #define S3C2410_EXTINT_HILEV (0x01) | ||
19 | #define S3C2410_EXTINT_FALLEDGE (0x02) | ||
20 | #define S3C2410_EXTINT_RISEEDGE (0x04) | ||
21 | #define S3C2410_EXTINT_BOTHEDGE (0x06) | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-nand.h b/arch/arm/plat-samsung/include/plat/regs-nand.h new file mode 100644 index 000000000000..238efea7b9e4 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-nand.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-nand.h | ||
2 | * | ||
3 | * Copyright (c) 2004-2005 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * S3C2410 NAND register definitions | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARM_REGS_NAND | ||
14 | #define __ASM_ARM_REGS_NAND | ||
15 | |||
16 | |||
17 | #define S3C2410_NFREG(x) (x) | ||
18 | |||
19 | #define S3C2410_NFCONF S3C2410_NFREG(0x00) | ||
20 | #define S3C2410_NFCMD S3C2410_NFREG(0x04) | ||
21 | #define S3C2410_NFADDR S3C2410_NFREG(0x08) | ||
22 | #define S3C2410_NFDATA S3C2410_NFREG(0x0C) | ||
23 | #define S3C2410_NFSTAT S3C2410_NFREG(0x10) | ||
24 | #define S3C2410_NFECC S3C2410_NFREG(0x14) | ||
25 | |||
26 | #define S3C2440_NFCONT S3C2410_NFREG(0x04) | ||
27 | #define S3C2440_NFCMD S3C2410_NFREG(0x08) | ||
28 | #define S3C2440_NFADDR S3C2410_NFREG(0x0C) | ||
29 | #define S3C2440_NFDATA S3C2410_NFREG(0x10) | ||
30 | #define S3C2440_NFECCD0 S3C2410_NFREG(0x14) | ||
31 | #define S3C2440_NFECCD1 S3C2410_NFREG(0x18) | ||
32 | #define S3C2440_NFECCD S3C2410_NFREG(0x1C) | ||
33 | #define S3C2440_NFSTAT S3C2410_NFREG(0x20) | ||
34 | #define S3C2440_NFESTAT0 S3C2410_NFREG(0x24) | ||
35 | #define S3C2440_NFESTAT1 S3C2410_NFREG(0x28) | ||
36 | #define S3C2440_NFMECC0 S3C2410_NFREG(0x2C) | ||
37 | #define S3C2440_NFMECC1 S3C2410_NFREG(0x30) | ||
38 | #define S3C2440_NFSECC S3C2410_NFREG(0x34) | ||
39 | #define S3C2440_NFSBLK S3C2410_NFREG(0x38) | ||
40 | #define S3C2440_NFEBLK S3C2410_NFREG(0x3C) | ||
41 | |||
42 | #define S3C2412_NFSBLK S3C2410_NFREG(0x20) | ||
43 | #define S3C2412_NFEBLK S3C2410_NFREG(0x24) | ||
44 | #define S3C2412_NFSTAT S3C2410_NFREG(0x28) | ||
45 | #define S3C2412_NFMECC_ERR0 S3C2410_NFREG(0x2C) | ||
46 | #define S3C2412_NFMECC_ERR1 S3C2410_NFREG(0x30) | ||
47 | #define S3C2412_NFMECC0 S3C2410_NFREG(0x34) | ||
48 | #define S3C2412_NFMECC1 S3C2410_NFREG(0x38) | ||
49 | #define S3C2412_NFSECC S3C2410_NFREG(0x3C) | ||
50 | |||
51 | #define S3C2410_NFCONF_EN (1<<15) | ||
52 | #define S3C2410_NFCONF_512BYTE (1<<14) | ||
53 | #define S3C2410_NFCONF_4STEP (1<<13) | ||
54 | #define S3C2410_NFCONF_INITECC (1<<12) | ||
55 | #define S3C2410_NFCONF_nFCE (1<<11) | ||
56 | #define S3C2410_NFCONF_TACLS(x) ((x)<<8) | ||
57 | #define S3C2410_NFCONF_TWRPH0(x) ((x)<<4) | ||
58 | #define S3C2410_NFCONF_TWRPH1(x) ((x)<<0) | ||
59 | |||
60 | #define S3C2410_NFSTAT_BUSY (1<<0) | ||
61 | |||
62 | #define S3C2440_NFCONF_BUSWIDTH_8 (0<<0) | ||
63 | #define S3C2440_NFCONF_BUSWIDTH_16 (1<<0) | ||
64 | #define S3C2440_NFCONF_ADVFLASH (1<<3) | ||
65 | #define S3C2440_NFCONF_TACLS(x) ((x)<<12) | ||
66 | #define S3C2440_NFCONF_TWRPH0(x) ((x)<<8) | ||
67 | #define S3C2440_NFCONF_TWRPH1(x) ((x)<<4) | ||
68 | |||
69 | #define S3C2440_NFCONT_LOCKTIGHT (1<<13) | ||
70 | #define S3C2440_NFCONT_SOFTLOCK (1<<12) | ||
71 | #define S3C2440_NFCONT_ILLEGALACC_EN (1<<10) | ||
72 | #define S3C2440_NFCONT_RNBINT_EN (1<<9) | ||
73 | #define S3C2440_NFCONT_RN_FALLING (1<<8) | ||
74 | #define S3C2440_NFCONT_SPARE_ECCLOCK (1<<6) | ||
75 | #define S3C2440_NFCONT_MAIN_ECCLOCK (1<<5) | ||
76 | #define S3C2440_NFCONT_INITECC (1<<4) | ||
77 | #define S3C2440_NFCONT_nFCE (1<<1) | ||
78 | #define S3C2440_NFCONT_ENABLE (1<<0) | ||
79 | |||
80 | #define S3C2440_NFSTAT_READY (1<<0) | ||
81 | #define S3C2440_NFSTAT_nCE (1<<1) | ||
82 | #define S3C2440_NFSTAT_RnB_CHANGE (1<<2) | ||
83 | #define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3) | ||
84 | |||
85 | #define S3C2412_NFCONF_NANDBOOT (1<<31) | ||
86 | #define S3C2412_NFCONF_ECCCLKCON (1<<30) | ||
87 | #define S3C2412_NFCONF_ECC_MLC (1<<24) | ||
88 | #define S3C2412_NFCONF_TACLS_MASK (7<<12) /* 1 extra bit of Tacls */ | ||
89 | |||
90 | #define S3C2412_NFCONT_ECC4_DIRWR (1<<18) | ||
91 | #define S3C2412_NFCONT_LOCKTIGHT (1<<17) | ||
92 | #define S3C2412_NFCONT_SOFTLOCK (1<<16) | ||
93 | #define S3C2412_NFCONT_ECC4_ENCINT (1<<13) | ||
94 | #define S3C2412_NFCONT_ECC4_DECINT (1<<12) | ||
95 | #define S3C2412_NFCONT_MAIN_ECC_LOCK (1<<7) | ||
96 | #define S3C2412_NFCONT_INIT_MAIN_ECC (1<<5) | ||
97 | #define S3C2412_NFCONT_nFCE1 (1<<2) | ||
98 | #define S3C2412_NFCONT_nFCE0 (1<<1) | ||
99 | |||
100 | #define S3C2412_NFSTAT_ECC_ENCDONE (1<<7) | ||
101 | #define S3C2412_NFSTAT_ECC_DECDONE (1<<6) | ||
102 | #define S3C2412_NFSTAT_ILLEGAL_ACCESS (1<<5) | ||
103 | #define S3C2412_NFSTAT_RnB_CHANGE (1<<4) | ||
104 | #define S3C2412_NFSTAT_nFCE1 (1<<3) | ||
105 | #define S3C2412_NFSTAT_nFCE0 (1<<2) | ||
106 | #define S3C2412_NFSTAT_Res1 (1<<1) | ||
107 | #define S3C2412_NFSTAT_READY (1<<0) | ||
108 | |||
109 | #define S3C2412_NFECCERR_SERRDATA(x) (((x) >> 21) & 0xf) | ||
110 | #define S3C2412_NFECCERR_SERRBIT(x) (((x) >> 18) & 0x7) | ||
111 | #define S3C2412_NFECCERR_MERRDATA(x) (((x) >> 7) & 0x3ff) | ||
112 | #define S3C2412_NFECCERR_MERRBIT(x) (((x) >> 4) & 0x7) | ||
113 | #define S3C2412_NFECCERR_SPARE_ERR(x) (((x) >> 2) & 0x3) | ||
114 | #define S3C2412_NFECCERR_MAIN_ERR(x) (((x) >> 2) & 0x3) | ||
115 | #define S3C2412_NFECCERR_NONE (0) | ||
116 | #define S3C2412_NFECCERR_1BIT (1) | ||
117 | #define S3C2412_NFECCERR_MULTIBIT (2) | ||
118 | #define S3C2412_NFECCERR_ECCAREA (3) | ||
119 | |||
120 | |||
121 | |||
122 | #endif /* __ASM_ARM_REGS_NAND */ | ||
123 | |||
diff --git a/arch/arm/plat-samsung/include/plat/regs-rtc.h b/arch/arm/plat-samsung/include/plat/regs-rtc.h new file mode 100644 index 000000000000..d5837cf8e402 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-rtc.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-rtc.h | ||
2 | * | ||
3 | * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * S3C2410 Internal RTC register definition | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_RTC_H | ||
14 | #define __ASM_ARCH_REGS_RTC_H __FILE__ | ||
15 | |||
16 | #define S3C2410_RTCREG(x) (x) | ||
17 | |||
18 | #define S3C2410_RTCCON S3C2410_RTCREG(0x40) | ||
19 | #define S3C2410_RTCCON_RTCEN (1<<0) | ||
20 | #define S3C2410_RTCCON_CLKSEL (1<<1) | ||
21 | #define S3C2410_RTCCON_CNTSEL (1<<2) | ||
22 | #define S3C2410_RTCCON_CLKRST (1<<3) | ||
23 | |||
24 | #define S3C2410_TICNT S3C2410_RTCREG(0x44) | ||
25 | #define S3C2410_TICNT_ENABLE (1<<7) | ||
26 | |||
27 | #define S3C2410_RTCALM S3C2410_RTCREG(0x50) | ||
28 | #define S3C2410_RTCALM_ALMEN (1<<6) | ||
29 | #define S3C2410_RTCALM_YEAREN (1<<5) | ||
30 | #define S3C2410_RTCALM_MONEN (1<<4) | ||
31 | #define S3C2410_RTCALM_DAYEN (1<<3) | ||
32 | #define S3C2410_RTCALM_HOUREN (1<<2) | ||
33 | #define S3C2410_RTCALM_MINEN (1<<1) | ||
34 | #define S3C2410_RTCALM_SECEN (1<<0) | ||
35 | |||
36 | #define S3C2410_RTCALM_ALL \ | ||
37 | S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\ | ||
38 | S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\ | ||
39 | S3C2410_RTCALM_SECEN | ||
40 | |||
41 | |||
42 | #define S3C2410_ALMSEC S3C2410_RTCREG(0x54) | ||
43 | #define S3C2410_ALMMIN S3C2410_RTCREG(0x58) | ||
44 | #define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c) | ||
45 | |||
46 | #define S3C2410_ALMDATE S3C2410_RTCREG(0x60) | ||
47 | #define S3C2410_ALMMON S3C2410_RTCREG(0x64) | ||
48 | #define S3C2410_ALMYEAR S3C2410_RTCREG(0x68) | ||
49 | |||
50 | #define S3C2410_RTCRST S3C2410_RTCREG(0x6c) | ||
51 | |||
52 | #define S3C2410_RTCSEC S3C2410_RTCREG(0x70) | ||
53 | #define S3C2410_RTCMIN S3C2410_RTCREG(0x74) | ||
54 | #define S3C2410_RTCHOUR S3C2410_RTCREG(0x78) | ||
55 | #define S3C2410_RTCDATE S3C2410_RTCREG(0x7c) | ||
56 | #define S3C2410_RTCDAY S3C2410_RTCREG(0x80) | ||
57 | #define S3C2410_RTCMON S3C2410_RTCREG(0x84) | ||
58 | #define S3C2410_RTCYEAR S3C2410_RTCREG(0x88) | ||
59 | |||
60 | |||
61 | #endif /* __ASM_ARCH_REGS_RTC_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-s3c2412-iis.h b/arch/arm/plat-samsung/include/plat/regs-s3c2412-iis.h new file mode 100644 index 000000000000..abf2fbc2eb2f --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-s3c2412-iis.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h | ||
2 | * | ||
3 | * Copyright 2007 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * S3C2412 IIS register definition | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_S3C2412_IIS_H | ||
14 | #define __ASM_ARCH_REGS_S3C2412_IIS_H | ||
15 | |||
16 | #define S3C2412_IISCON (0x00) | ||
17 | #define S3C2412_IISMOD (0x04) | ||
18 | #define S3C2412_IISFIC (0x08) | ||
19 | #define S3C2412_IISPSR (0x0C) | ||
20 | #define S3C2412_IISTXD (0x10) | ||
21 | #define S3C2412_IISRXD (0x14) | ||
22 | |||
23 | #define S3C2412_IISCON_LRINDEX (1 << 11) | ||
24 | #define S3C2412_IISCON_TXFIFO_EMPTY (1 << 10) | ||
25 | #define S3C2412_IISCON_RXFIFO_EMPTY (1 << 9) | ||
26 | #define S3C2412_IISCON_TXFIFO_FULL (1 << 8) | ||
27 | #define S3C2412_IISCON_RXFIFO_FULL (1 << 7) | ||
28 | #define S3C2412_IISCON_TXDMA_PAUSE (1 << 6) | ||
29 | #define S3C2412_IISCON_RXDMA_PAUSE (1 << 5) | ||
30 | #define S3C2412_IISCON_TXCH_PAUSE (1 << 4) | ||
31 | #define S3C2412_IISCON_RXCH_PAUSE (1 << 3) | ||
32 | #define S3C2412_IISCON_TXDMA_ACTIVE (1 << 2) | ||
33 | #define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1) | ||
34 | #define S3C2412_IISCON_IIS_ACTIVE (1 << 0) | ||
35 | |||
36 | #define S3C64XX_IISMOD_BLC_16BIT (0 << 13) | ||
37 | #define S3C64XX_IISMOD_BLC_8BIT (1 << 13) | ||
38 | #define S3C64XX_IISMOD_BLC_24BIT (2 << 13) | ||
39 | #define S3C64XX_IISMOD_BLC_MASK (3 << 13) | ||
40 | |||
41 | #define S3C64XX_IISMOD_IMS_PCLK (0 << 10) | ||
42 | #define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10) | ||
43 | |||
44 | #define S3C2412_IISMOD_MASTER_INTERNAL (0 << 10) | ||
45 | #define S3C2412_IISMOD_MASTER_EXTERNAL (1 << 10) | ||
46 | #define S3C2412_IISMOD_SLAVE (2 << 10) | ||
47 | #define S3C2412_IISMOD_MASTER_MASK (3 << 10) | ||
48 | #define S3C2412_IISMOD_MODE_TXONLY (0 << 8) | ||
49 | #define S3C2412_IISMOD_MODE_RXONLY (1 << 8) | ||
50 | #define S3C2412_IISMOD_MODE_TXRX (2 << 8) | ||
51 | #define S3C2412_IISMOD_MODE_MASK (3 << 8) | ||
52 | #define S3C2412_IISMOD_LR_LLOW (0 << 7) | ||
53 | #define S3C2412_IISMOD_LR_RLOW (1 << 7) | ||
54 | #define S3C2412_IISMOD_SDF_IIS (0 << 5) | ||
55 | #define S3C2412_IISMOD_SDF_MSB (1 << 5) | ||
56 | #define S3C2412_IISMOD_SDF_LSB (2 << 5) | ||
57 | #define S3C2412_IISMOD_SDF_MASK (3 << 5) | ||
58 | #define S3C2412_IISMOD_RCLK_256FS (0 << 3) | ||
59 | #define S3C2412_IISMOD_RCLK_512FS (1 << 3) | ||
60 | #define S3C2412_IISMOD_RCLK_384FS (2 << 3) | ||
61 | #define S3C2412_IISMOD_RCLK_768FS (3 << 3) | ||
62 | #define S3C2412_IISMOD_RCLK_MASK (3 << 3) | ||
63 | #define S3C2412_IISMOD_BCLK_32FS (0 << 1) | ||
64 | #define S3C2412_IISMOD_BCLK_48FS (1 << 1) | ||
65 | #define S3C2412_IISMOD_BCLK_16FS (2 << 1) | ||
66 | #define S3C2412_IISMOD_BCLK_24FS (3 << 1) | ||
67 | #define S3C2412_IISMOD_BCLK_MASK (3 << 1) | ||
68 | #define S3C2412_IISMOD_8BIT (1 << 0) | ||
69 | |||
70 | #define S3C64XX_IISMOD_CDCLKCON (1 << 12) | ||
71 | |||
72 | #define S3C2412_IISPSR_PSREN (1 << 15) | ||
73 | |||
74 | #define S3C2412_IISFIC_TXFLUSH (1 << 15) | ||
75 | #define S3C2412_IISFIC_RXFLUSH (1 << 7) | ||
76 | #define S3C2412_IISFIC_TXCOUNT(x) (((x) >> 8) & 0xf) | ||
77 | #define S3C2412_IISFIC_RXCOUNT(x) (((x) >> 0) & 0xf) | ||
78 | |||
79 | |||
80 | |||
81 | #endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */ | ||
82 | |||
diff --git a/arch/arm/plat-samsung/include/plat/regs-sdhci.h b/arch/arm/plat-samsung/include/plat/regs-sdhci.h new file mode 100644 index 000000000000..e34049ad44cc --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-sdhci.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/regs-sdhci.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C Platform - SDHCI (HSMMC) register definitions | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef __PLAT_S3C_SDHCI_REGS_H | ||
16 | #define __PLAT_S3C_SDHCI_REGS_H __FILE__ | ||
17 | |||
18 | #define S3C_SDHCI_CONTROL2 (0x80) | ||
19 | #define S3C_SDHCI_CONTROL3 (0x84) | ||
20 | #define S3C64XX_SDHCI_CONTROL4 (0x8C) | ||
21 | |||
22 | #define S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR (1 << 31) | ||
23 | #define S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK (1 << 30) | ||
24 | #define S3C_SDHCI_CTRL2_CDINVRXD3 (1 << 29) | ||
25 | #define S3C_SDHCI_CTRL2_SLCARDOUT (1 << 28) | ||
26 | |||
27 | #define S3C_SDHCI_CTRL2_FLTCLKSEL_MASK (0xf << 24) | ||
28 | #define S3C_SDHCI_CTRL2_FLTCLKSEL_SHIFT (24) | ||
29 | #define S3C_SDHCI_CTRL2_FLTCLKSEL(_x) ((_x) << 24) | ||
30 | |||
31 | #define S3C_SDHCI_CTRL2_LVLDAT_MASK (0xff << 16) | ||
32 | #define S3C_SDHCI_CTRL2_LVLDAT_SHIFT (16) | ||
33 | #define S3C_SDHCI_CTRL2_LVLDAT(_x) ((_x) << 16) | ||
34 | |||
35 | #define S3C_SDHCI_CTRL2_ENFBCLKTX (1 << 15) | ||
36 | #define S3C_SDHCI_CTRL2_ENFBCLKRX (1 << 14) | ||
37 | #define S3C_SDHCI_CTRL2_SDCDSEL (1 << 13) | ||
38 | #define S3C_SDHCI_CTRL2_SDSIGPC (1 << 12) | ||
39 | #define S3C_SDHCI_CTRL2_ENBUSYCHKTXSTART (1 << 11) | ||
40 | |||
41 | #define S3C_SDHCI_CTRL2_DFCNT_MASK (0x3 << 9) | ||
42 | #define S3C_SDHCI_CTRL2_DFCNT_SHIFT (9) | ||
43 | #define S3C_SDHCI_CTRL2_DFCNT_NONE (0x0 << 9) | ||
44 | #define S3C_SDHCI_CTRL2_DFCNT_4SDCLK (0x1 << 9) | ||
45 | #define S3C_SDHCI_CTRL2_DFCNT_16SDCLK (0x2 << 9) | ||
46 | #define S3C_SDHCI_CTRL2_DFCNT_64SDCLK (0x3 << 9) | ||
47 | |||
48 | #define S3C_SDHCI_CTRL2_ENCLKOUTHOLD (1 << 8) | ||
49 | #define S3C_SDHCI_CTRL2_RWAITMODE (1 << 7) | ||
50 | #define S3C_SDHCI_CTRL2_DISBUFRD (1 << 6) | ||
51 | #define S3C_SDHCI_CTRL2_SELBASECLK_MASK (0x3 << 4) | ||
52 | #define S3C_SDHCI_CTRL2_SELBASECLK_SHIFT (4) | ||
53 | #define S3C_SDHCI_CTRL2_PWRSYNC (1 << 3) | ||
54 | #define S3C_SDHCI_CTRL2_ENCLKOUTMSKCON (1 << 1) | ||
55 | #define S3C_SDHCI_CTRL2_HWINITFIN (1 << 0) | ||
56 | |||
57 | #define S3C_SDHCI_CTRL3_FCSEL3 (1 << 31) | ||
58 | #define S3C_SDHCI_CTRL3_FCSEL2 (1 << 23) | ||
59 | #define S3C_SDHCI_CTRL3_FCSEL1 (1 << 15) | ||
60 | #define S3C_SDHCI_CTRL3_FCSEL0 (1 << 7) | ||
61 | |||
62 | #define S3C_SDHCI_CTRL3_FIA3_MASK (0x7f << 24) | ||
63 | #define S3C_SDHCI_CTRL3_FIA3_SHIFT (24) | ||
64 | #define S3C_SDHCI_CTRL3_FIA3(_x) ((_x) << 24) | ||
65 | |||
66 | #define S3C_SDHCI_CTRL3_FIA2_MASK (0x7f << 16) | ||
67 | #define S3C_SDHCI_CTRL3_FIA2_SHIFT (16) | ||
68 | #define S3C_SDHCI_CTRL3_FIA2(_x) ((_x) << 16) | ||
69 | |||
70 | #define S3C_SDHCI_CTRL3_FIA1_MASK (0x7f << 8) | ||
71 | #define S3C_SDHCI_CTRL3_FIA1_SHIFT (8) | ||
72 | #define S3C_SDHCI_CTRL3_FIA1(_x) ((_x) << 8) | ||
73 | |||
74 | #define S3C_SDHCI_CTRL3_FIA0_MASK (0x7f << 0) | ||
75 | #define S3C_SDHCI_CTRL3_FIA0_SHIFT (0) | ||
76 | #define S3C_SDHCI_CTRL3_FIA0(_x) ((_x) << 0) | ||
77 | |||
78 | #define S3C64XX_SDHCI_CONTROL4_DRIVE_MASK (0x3 << 16) | ||
79 | #define S3C64XX_SDHCI_CONTROL4_DRIVE_SHIFT (16) | ||
80 | #define S3C64XX_SDHCI_CONTROL4_DRIVE_2mA (0x0 << 16) | ||
81 | #define S3C64XX_SDHCI_CONTROL4_DRIVE_4mA (0x1 << 16) | ||
82 | #define S3C64XX_SDHCI_CONTROL4_DRIVE_7mA (0x2 << 16) | ||
83 | #define S3C64XX_SDHCI_CONTROL4_DRIVE_9mA (0x3 << 16) | ||
84 | |||
85 | #define S3C64XX_SDHCI_CONTROL4_BUSY (1) | ||
86 | |||
87 | #endif /* __PLAT_S3C_SDHCI_REGS_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h new file mode 100644 index 000000000000..a6eba8496b24 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h | |||
@@ -0,0 +1,281 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/regs-serial.h | ||
2 | * | ||
3 | * From linux/include/asm-arm/hardware/serial_s3c2410.h | ||
4 | * | ||
5 | * Internal header file for Samsung S3C2410 serial ports (UART0-2) | ||
6 | * | ||
7 | * Copyright (C) 2002 Shane Nay (shane@minirl.com) | ||
8 | * | ||
9 | * Additional defines, Copyright 2003 Simtec Electronics (linux@simtec.co.uk) | ||
10 | * | ||
11 | * Adapted from: | ||
12 | * | ||
13 | * Internal header file for MX1ADS serial ports (UART1 & 2) | ||
14 | * | ||
15 | * Copyright (C) 2002 Shane Nay (shane@minirl.com) | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License as published by | ||
19 | * the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU General Public License for more details. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License | ||
28 | * along with this program; if not, write to the Free Software | ||
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
30 | */ | ||
31 | |||
32 | #ifndef __ASM_ARM_REGS_SERIAL_H | ||
33 | #define __ASM_ARM_REGS_SERIAL_H | ||
34 | |||
35 | #define S3C24XX_VA_UART0 (S3C_VA_UART) | ||
36 | #define S3C24XX_VA_UART1 (S3C_VA_UART + 0x4000 ) | ||
37 | #define S3C24XX_VA_UART2 (S3C_VA_UART + 0x8000 ) | ||
38 | #define S3C24XX_VA_UART3 (S3C_VA_UART + 0xC000 ) | ||
39 | |||
40 | #define S3C2410_PA_UART0 (S3C24XX_PA_UART) | ||
41 | #define S3C2410_PA_UART1 (S3C24XX_PA_UART + 0x4000 ) | ||
42 | #define S3C2410_PA_UART2 (S3C24XX_PA_UART + 0x8000 ) | ||
43 | #define S3C2443_PA_UART3 (S3C24XX_PA_UART + 0xC000 ) | ||
44 | |||
45 | #define S3C2410_URXH (0x24) | ||
46 | #define S3C2410_UTXH (0x20) | ||
47 | #define S3C2410_ULCON (0x00) | ||
48 | #define S3C2410_UCON (0x04) | ||
49 | #define S3C2410_UFCON (0x08) | ||
50 | #define S3C2410_UMCON (0x0C) | ||
51 | #define S3C2410_UBRDIV (0x28) | ||
52 | #define S3C2410_UTRSTAT (0x10) | ||
53 | #define S3C2410_UERSTAT (0x14) | ||
54 | #define S3C2410_UFSTAT (0x18) | ||
55 | #define S3C2410_UMSTAT (0x1C) | ||
56 | |||
57 | #define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3)) | ||
58 | |||
59 | #define S3C2410_LCON_CS5 (0x0) | ||
60 | #define S3C2410_LCON_CS6 (0x1) | ||
61 | #define S3C2410_LCON_CS7 (0x2) | ||
62 | #define S3C2410_LCON_CS8 (0x3) | ||
63 | #define S3C2410_LCON_CSMASK (0x3) | ||
64 | |||
65 | #define S3C2410_LCON_PNONE (0x0) | ||
66 | #define S3C2410_LCON_PEVEN (0x5 << 3) | ||
67 | #define S3C2410_LCON_PODD (0x4 << 3) | ||
68 | #define S3C2410_LCON_PMASK (0x7 << 3) | ||
69 | |||
70 | #define S3C2410_LCON_STOPB (1<<2) | ||
71 | #define S3C2410_LCON_IRM (1<<6) | ||
72 | |||
73 | #define S3C2440_UCON_CLKMASK (3<<10) | ||
74 | #define S3C2440_UCON_PCLK (0<<10) | ||
75 | #define S3C2440_UCON_UCLK (1<<10) | ||
76 | #define S3C2440_UCON_PCLK2 (2<<10) | ||
77 | #define S3C2440_UCON_FCLK (3<<10) | ||
78 | #define S3C2443_UCON_EPLL (3<<10) | ||
79 | |||
80 | #define S3C6400_UCON_CLKMASK (3<<10) | ||
81 | #define S3C6400_UCON_PCLK (0<<10) | ||
82 | #define S3C6400_UCON_PCLK2 (2<<10) | ||
83 | #define S3C6400_UCON_UCLK0 (1<<10) | ||
84 | #define S3C6400_UCON_UCLK1 (3<<10) | ||
85 | |||
86 | #define S3C2440_UCON2_FCLK_EN (1<<15) | ||
87 | #define S3C2440_UCON0_DIVMASK (15 << 12) | ||
88 | #define S3C2440_UCON1_DIVMASK (15 << 12) | ||
89 | #define S3C2440_UCON2_DIVMASK (7 << 12) | ||
90 | #define S3C2440_UCON_DIVSHIFT (12) | ||
91 | |||
92 | #define S3C2412_UCON_CLKMASK (3<<10) | ||
93 | #define S3C2412_UCON_UCLK (1<<10) | ||
94 | #define S3C2412_UCON_USYSCLK (3<<10) | ||
95 | #define S3C2412_UCON_PCLK (0<<10) | ||
96 | #define S3C2412_UCON_PCLK2 (2<<10) | ||
97 | |||
98 | #define S3C2410_UCON_UCLK (1<<10) | ||
99 | #define S3C2410_UCON_SBREAK (1<<4) | ||
100 | |||
101 | #define S3C2410_UCON_TXILEVEL (1<<9) | ||
102 | #define S3C2410_UCON_RXILEVEL (1<<8) | ||
103 | #define S3C2410_UCON_TXIRQMODE (1<<2) | ||
104 | #define S3C2410_UCON_RXIRQMODE (1<<0) | ||
105 | #define S3C2410_UCON_RXFIFO_TOI (1<<7) | ||
106 | #define S3C2443_UCON_RXERR_IRQEN (1<<6) | ||
107 | #define S3C2443_UCON_LOOPBACK (1<<5) | ||
108 | |||
109 | #define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | ||
110 | S3C2410_UCON_RXILEVEL | \ | ||
111 | S3C2410_UCON_TXIRQMODE | \ | ||
112 | S3C2410_UCON_RXIRQMODE | \ | ||
113 | S3C2410_UCON_RXFIFO_TOI) | ||
114 | |||
115 | #define S3C2410_UFCON_FIFOMODE (1<<0) | ||
116 | #define S3C2410_UFCON_TXTRIG0 (0<<6) | ||
117 | #define S3C2410_UFCON_RXTRIG8 (1<<4) | ||
118 | #define S3C2410_UFCON_RXTRIG12 (2<<4) | ||
119 | |||
120 | /* S3C2440 FIFO trigger levels */ | ||
121 | #define S3C2440_UFCON_RXTRIG1 (0<<4) | ||
122 | #define S3C2440_UFCON_RXTRIG8 (1<<4) | ||
123 | #define S3C2440_UFCON_RXTRIG16 (2<<4) | ||
124 | #define S3C2440_UFCON_RXTRIG32 (3<<4) | ||
125 | |||
126 | #define S3C2440_UFCON_TXTRIG0 (0<<6) | ||
127 | #define S3C2440_UFCON_TXTRIG16 (1<<6) | ||
128 | #define S3C2440_UFCON_TXTRIG32 (2<<6) | ||
129 | #define S3C2440_UFCON_TXTRIG48 (3<<6) | ||
130 | |||
131 | #define S3C2410_UFCON_RESETBOTH (3<<1) | ||
132 | #define S3C2410_UFCON_RESETTX (1<<2) | ||
133 | #define S3C2410_UFCON_RESETRX (1<<1) | ||
134 | |||
135 | #define S3C2410_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ | ||
136 | S3C2410_UFCON_TXTRIG0 | \ | ||
137 | S3C2410_UFCON_RXTRIG8 ) | ||
138 | |||
139 | #define S3C2410_UMCOM_AFC (1<<4) | ||
140 | #define S3C2410_UMCOM_RTS_LOW (1<<0) | ||
141 | |||
142 | #define S3C2412_UMCON_AFC_63 (0<<5) /* same as s3c2443 */ | ||
143 | #define S3C2412_UMCON_AFC_56 (1<<5) | ||
144 | #define S3C2412_UMCON_AFC_48 (2<<5) | ||
145 | #define S3C2412_UMCON_AFC_40 (3<<5) | ||
146 | #define S3C2412_UMCON_AFC_32 (4<<5) | ||
147 | #define S3C2412_UMCON_AFC_24 (5<<5) | ||
148 | #define S3C2412_UMCON_AFC_16 (6<<5) | ||
149 | #define S3C2412_UMCON_AFC_8 (7<<5) | ||
150 | |||
151 | #define S3C2410_UFSTAT_TXFULL (1<<9) | ||
152 | #define S3C2410_UFSTAT_RXFULL (1<<8) | ||
153 | #define S3C2410_UFSTAT_TXMASK (15<<4) | ||
154 | #define S3C2410_UFSTAT_TXSHIFT (4) | ||
155 | #define S3C2410_UFSTAT_RXMASK (15<<0) | ||
156 | #define S3C2410_UFSTAT_RXSHIFT (0) | ||
157 | |||
158 | /* UFSTAT S3C24A0 */ | ||
159 | #define S3C24A0_UFSTAT_TXFULL (1 << 14) | ||
160 | #define S3C24A0_UFSTAT_RXFULL (1 << 6) | ||
161 | #define S3C24A0_UFSTAT_TXMASK (63 << 8) | ||
162 | #define S3C24A0_UFSTAT_TXSHIFT (8) | ||
163 | #define S3C24A0_UFSTAT_RXMASK (63) | ||
164 | #define S3C24A0_UFSTAT_RXSHIFT (0) | ||
165 | |||
166 | /* UFSTAT S3C2443 same as S3C2440 */ | ||
167 | #define S3C2440_UFSTAT_TXFULL (1<<14) | ||
168 | #define S3C2440_UFSTAT_RXFULL (1<<6) | ||
169 | #define S3C2440_UFSTAT_TXSHIFT (8) | ||
170 | #define S3C2440_UFSTAT_RXSHIFT (0) | ||
171 | #define S3C2440_UFSTAT_TXMASK (63<<8) | ||
172 | #define S3C2440_UFSTAT_RXMASK (63) | ||
173 | |||
174 | #define S3C2410_UTRSTAT_TXE (1<<2) | ||
175 | #define S3C2410_UTRSTAT_TXFE (1<<1) | ||
176 | #define S3C2410_UTRSTAT_RXDR (1<<0) | ||
177 | |||
178 | #define S3C2410_UERSTAT_OVERRUN (1<<0) | ||
179 | #define S3C2410_UERSTAT_FRAME (1<<2) | ||
180 | #define S3C2410_UERSTAT_BREAK (1<<3) | ||
181 | #define S3C2443_UERSTAT_PARITY (1<<1) | ||
182 | |||
183 | #define S3C2410_UERSTAT_ANY (S3C2410_UERSTAT_OVERRUN | \ | ||
184 | S3C2410_UERSTAT_FRAME | \ | ||
185 | S3C2410_UERSTAT_BREAK) | ||
186 | |||
187 | #define S3C2410_UMSTAT_CTS (1<<0) | ||
188 | #define S3C2410_UMSTAT_DeltaCTS (1<<2) | ||
189 | |||
190 | #define S3C2443_DIVSLOT (0x2C) | ||
191 | |||
192 | /* S3C64XX interrupt registers. */ | ||
193 | #define S3C64XX_UINTP 0x30 | ||
194 | #define S3C64XX_UINTSP 0x34 | ||
195 | #define S3C64XX_UINTM 0x38 | ||
196 | |||
197 | /* Following are specific to S5PV210 and S5P6442 */ | ||
198 | #define S5PV210_UCON_CLKMASK (1<<10) | ||
199 | #define S5PV210_UCON_PCLK (0<<10) | ||
200 | #define S5PV210_UCON_UCLK (1<<10) | ||
201 | |||
202 | #define S5PV210_UFCON_TXTRIG0 (0<<8) | ||
203 | #define S5PV210_UFCON_TXTRIG4 (1<<8) | ||
204 | #define S5PV210_UFCON_TXTRIG8 (2<<8) | ||
205 | #define S5PV210_UFCON_TXTRIG16 (3<<8) | ||
206 | #define S5PV210_UFCON_TXTRIG32 (4<<8) | ||
207 | #define S5PV210_UFCON_TXTRIG64 (5<<8) | ||
208 | #define S5PV210_UFCON_TXTRIG128 (6<<8) | ||
209 | #define S5PV210_UFCON_TXTRIG256 (7<<8) | ||
210 | |||
211 | #define S5PV210_UFCON_RXTRIG1 (0<<4) | ||
212 | #define S5PV210_UFCON_RXTRIG4 (1<<4) | ||
213 | #define S5PV210_UFCON_RXTRIG8 (2<<4) | ||
214 | #define S5PV210_UFCON_RXTRIG16 (3<<4) | ||
215 | #define S5PV210_UFCON_RXTRIG32 (4<<4) | ||
216 | #define S5PV210_UFCON_RXTRIG64 (5<<4) | ||
217 | #define S5PV210_UFCON_RXTRIG128 (6<<4) | ||
218 | #define S5PV210_UFCON_RXTRIG256 (7<<4) | ||
219 | |||
220 | #define S5PV210_UFSTAT_TXFULL (1<<24) | ||
221 | #define S5PV210_UFSTAT_RXFULL (1<<8) | ||
222 | #define S5PV210_UFSTAT_TXMASK (255<<16) | ||
223 | #define S5PV210_UFSTAT_TXSHIFT (16) | ||
224 | #define S5PV210_UFSTAT_RXMASK (255<<0) | ||
225 | #define S5PV210_UFSTAT_RXSHIFT (0) | ||
226 | |||
227 | #ifndef __ASSEMBLY__ | ||
228 | |||
229 | /* struct s3c24xx_uart_clksrc | ||
230 | * | ||
231 | * this structure defines a named clock source that can be used for the | ||
232 | * uart, so that the best clock can be selected for the requested baud | ||
233 | * rate. | ||
234 | * | ||
235 | * min_baud and max_baud define the range of baud-rates this clock is | ||
236 | * acceptable for, if they are both zero, it is assumed any baud rate that | ||
237 | * can be generated from this clock will be used. | ||
238 | * | ||
239 | * divisor gives the divisor from the clock to the one seen by the uart | ||
240 | */ | ||
241 | |||
242 | struct s3c24xx_uart_clksrc { | ||
243 | const char *name; | ||
244 | unsigned int divisor; | ||
245 | unsigned int min_baud; | ||
246 | unsigned int max_baud; | ||
247 | }; | ||
248 | |||
249 | /* configuration structure for per-machine configurations for the | ||
250 | * serial port | ||
251 | * | ||
252 | * the pointer is setup by the machine specific initialisation from the | ||
253 | * arch/arm/mach-s3c2410/ directory. | ||
254 | */ | ||
255 | |||
256 | struct s3c2410_uartcfg { | ||
257 | unsigned char hwport; /* hardware port number */ | ||
258 | unsigned char unused; | ||
259 | unsigned short flags; | ||
260 | upf_t uart_flags; /* default uart flags */ | ||
261 | |||
262 | unsigned long ucon; /* value of ucon for port */ | ||
263 | unsigned long ulcon; /* value of ulcon for port */ | ||
264 | unsigned long ufcon; /* value of ufcon for port */ | ||
265 | |||
266 | struct s3c24xx_uart_clksrc *clocks; | ||
267 | unsigned int clocks_size; | ||
268 | }; | ||
269 | |||
270 | /* s3c24xx_uart_devs | ||
271 | * | ||
272 | * this is exported from the core as we cannot use driver_register(), | ||
273 | * or platform_add_device() before the console_initcall() | ||
274 | */ | ||
275 | |||
276 | extern struct platform_device *s3c24xx_uart_devs[4]; | ||
277 | |||
278 | #endif /* __ASSEMBLY__ */ | ||
279 | |||
280 | #endif /* __ASM_ARM_REGS_SERIAL_H */ | ||
281 | |||
diff --git a/arch/arm/plat-samsung/include/plat/regs-timer.h b/arch/arm/plat-samsung/include/plat/regs-timer.h new file mode 100644 index 000000000000..d097d92f8cc7 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-timer.h | |||
@@ -0,0 +1,124 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-timer.h | ||
2 | * | ||
3 | * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * S3C2410 Timer configuration | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_TIMER_H | ||
14 | #define __ASM_ARCH_REGS_TIMER_H | ||
15 | |||
16 | #define S3C_TIMERREG(x) (S3C_VA_TIMER + (x)) | ||
17 | #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c)) | ||
18 | |||
19 | #define S3C2410_TCFG0 S3C_TIMERREG(0x00) | ||
20 | #define S3C2410_TCFG1 S3C_TIMERREG(0x04) | ||
21 | #define S3C2410_TCON S3C_TIMERREG(0x08) | ||
22 | |||
23 | #define S3C64XX_TINT_CSTAT S3C_TIMERREG(0x44) | ||
24 | |||
25 | #define S3C2410_TCFG_PRESCALER0_MASK (255<<0) | ||
26 | #define S3C2410_TCFG_PRESCALER1_MASK (255<<8) | ||
27 | #define S3C2410_TCFG_PRESCALER1_SHIFT (8) | ||
28 | #define S3C2410_TCFG_DEADZONE_MASK (255<<16) | ||
29 | #define S3C2410_TCFG_DEADZONE_SHIFT (16) | ||
30 | |||
31 | #define S3C2410_TCFG1_MUX4_DIV2 (0<<16) | ||
32 | #define S3C2410_TCFG1_MUX4_DIV4 (1<<16) | ||
33 | #define S3C2410_TCFG1_MUX4_DIV8 (2<<16) | ||
34 | #define S3C2410_TCFG1_MUX4_DIV16 (3<<16) | ||
35 | #define S3C2410_TCFG1_MUX4_TCLK1 (4<<16) | ||
36 | #define S3C2410_TCFG1_MUX4_MASK (15<<16) | ||
37 | #define S3C2410_TCFG1_MUX4_SHIFT (16) | ||
38 | |||
39 | #define S3C2410_TCFG1_MUX3_DIV2 (0<<12) | ||
40 | #define S3C2410_TCFG1_MUX3_DIV4 (1<<12) | ||
41 | #define S3C2410_TCFG1_MUX3_DIV8 (2<<12) | ||
42 | #define S3C2410_TCFG1_MUX3_DIV16 (3<<12) | ||
43 | #define S3C2410_TCFG1_MUX3_TCLK1 (4<<12) | ||
44 | #define S3C2410_TCFG1_MUX3_MASK (15<<12) | ||
45 | |||
46 | |||
47 | #define S3C2410_TCFG1_MUX2_DIV2 (0<<8) | ||
48 | #define S3C2410_TCFG1_MUX2_DIV4 (1<<8) | ||
49 | #define S3C2410_TCFG1_MUX2_DIV8 (2<<8) | ||
50 | #define S3C2410_TCFG1_MUX2_DIV16 (3<<8) | ||
51 | #define S3C2410_TCFG1_MUX2_TCLK1 (4<<8) | ||
52 | #define S3C2410_TCFG1_MUX2_MASK (15<<8) | ||
53 | |||
54 | |||
55 | #define S3C2410_TCFG1_MUX1_DIV2 (0<<4) | ||
56 | #define S3C2410_TCFG1_MUX1_DIV4 (1<<4) | ||
57 | #define S3C2410_TCFG1_MUX1_DIV8 (2<<4) | ||
58 | #define S3C2410_TCFG1_MUX1_DIV16 (3<<4) | ||
59 | #define S3C2410_TCFG1_MUX1_TCLK0 (4<<4) | ||
60 | #define S3C2410_TCFG1_MUX1_MASK (15<<4) | ||
61 | |||
62 | #define S3C2410_TCFG1_MUX0_DIV2 (0<<0) | ||
63 | #define S3C2410_TCFG1_MUX0_DIV4 (1<<0) | ||
64 | #define S3C2410_TCFG1_MUX0_DIV8 (2<<0) | ||
65 | #define S3C2410_TCFG1_MUX0_DIV16 (3<<0) | ||
66 | #define S3C2410_TCFG1_MUX0_TCLK0 (4<<0) | ||
67 | #define S3C2410_TCFG1_MUX0_MASK (15<<0) | ||
68 | |||
69 | #define S3C2410_TCFG1_MUX_DIV2 (0<<0) | ||
70 | #define S3C2410_TCFG1_MUX_DIV4 (1<<0) | ||
71 | #define S3C2410_TCFG1_MUX_DIV8 (2<<0) | ||
72 | #define S3C2410_TCFG1_MUX_DIV16 (3<<0) | ||
73 | #define S3C2410_TCFG1_MUX_TCLK (4<<0) | ||
74 | #define S3C2410_TCFG1_MUX_MASK (15<<0) | ||
75 | |||
76 | #define S3C64XX_TCFG1_MUX_DIV1 (0<<0) | ||
77 | #define S3C64XX_TCFG1_MUX_DIV2 (1<<0) | ||
78 | #define S3C64XX_TCFG1_MUX_DIV4 (2<<0) | ||
79 | #define S3C64XX_TCFG1_MUX_DIV8 (3<<0) | ||
80 | #define S3C64XX_TCFG1_MUX_DIV16 (4<<0) | ||
81 | #define S3C64XX_TCFG1_MUX_TCLK (5<<0) /* 3 sets of TCLK */ | ||
82 | #define S3C64XX_TCFG1_MUX_MASK (15<<0) | ||
83 | |||
84 | #define S3C2410_TCFG1_SHIFT(x) ((x) * 4) | ||
85 | |||
86 | /* for each timer, we have an count buffer, an compare buffer and | ||
87 | * an observation buffer | ||
88 | */ | ||
89 | |||
90 | /* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */ | ||
91 | |||
92 | #define S3C2410_TCNTB(tmr) S3C_TIMERREG2(tmr, 0x00) | ||
93 | #define S3C2410_TCMPB(tmr) S3C_TIMERREG2(tmr, 0x04) | ||
94 | #define S3C2410_TCNTO(tmr) S3C_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08)) | ||
95 | |||
96 | #define S3C2410_TCON_T4RELOAD (1<<22) | ||
97 | #define S3C2410_TCON_T4MANUALUPD (1<<21) | ||
98 | #define S3C2410_TCON_T4START (1<<20) | ||
99 | |||
100 | #define S3C2410_TCON_T3RELOAD (1<<19) | ||
101 | #define S3C2410_TCON_T3INVERT (1<<18) | ||
102 | #define S3C2410_TCON_T3MANUALUPD (1<<17) | ||
103 | #define S3C2410_TCON_T3START (1<<16) | ||
104 | |||
105 | #define S3C2410_TCON_T2RELOAD (1<<15) | ||
106 | #define S3C2410_TCON_T2INVERT (1<<14) | ||
107 | #define S3C2410_TCON_T2MANUALUPD (1<<13) | ||
108 | #define S3C2410_TCON_T2START (1<<12) | ||
109 | |||
110 | #define S3C2410_TCON_T1RELOAD (1<<11) | ||
111 | #define S3C2410_TCON_T1INVERT (1<<10) | ||
112 | #define S3C2410_TCON_T1MANUALUPD (1<<9) | ||
113 | #define S3C2410_TCON_T1START (1<<8) | ||
114 | |||
115 | #define S3C2410_TCON_T0DEADZONE (1<<4) | ||
116 | #define S3C2410_TCON_T0RELOAD (1<<3) | ||
117 | #define S3C2410_TCON_T0INVERT (1<<2) | ||
118 | #define S3C2410_TCON_T0MANUALUPD (1<<1) | ||
119 | #define S3C2410_TCON_T0START (1<<0) | ||
120 | |||
121 | #endif /* __ASM_ARCH_REGS_TIMER_H */ | ||
122 | |||
123 | |||
124 | |||
diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h new file mode 100644 index 000000000000..a111ad871833 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C - USB2.0 Highspeed/OtG device PHY registers | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* Note, this is a separate header file as some of the clock framework | ||
16 | * needs to touch this if the clk_48m is used as the USB OHCI or other | ||
17 | * peripheral source. | ||
18 | */ | ||
19 | |||
20 | #ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H | ||
21 | #define __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H __FILE__ | ||
22 | |||
23 | /* S3C64XX_PA_USB_HSPHY */ | ||
24 | |||
25 | #define S3C_HSOTG_PHYREG(x) ((x) + S3C_VA_USB_HSPHY) | ||
26 | |||
27 | #define S3C_PHYPWR S3C_HSOTG_PHYREG(0x00) | ||
28 | #define SRC_PHYPWR_OTG_DISABLE (1 << 4) | ||
29 | #define SRC_PHYPWR_ANALOG_POWERDOWN (1 << 3) | ||
30 | #define SRC_PHYPWR_FORCE_SUSPEND (1 << 1) | ||
31 | |||
32 | #define S3C_PHYCLK S3C_HSOTG_PHYREG(0x04) | ||
33 | #define S3C_PHYCLK_MODE_USB11 (1 << 6) | ||
34 | #define S3C_PHYCLK_EXT_OSC (1 << 5) | ||
35 | #define S3C_PHYCLK_CLK_FORCE (1 << 4) | ||
36 | #define S3C_PHYCLK_ID_PULL (1 << 2) | ||
37 | #define S3C_PHYCLK_CLKSEL_MASK (0x3 << 0) | ||
38 | #define S3C_PHYCLK_CLKSEL_SHIFT (0) | ||
39 | #define S3C_PHYCLK_CLKSEL_48M (0x0 << 0) | ||
40 | #define S3C_PHYCLK_CLKSEL_12M (0x2 << 0) | ||
41 | #define S3C_PHYCLK_CLKSEL_24M (0x3 << 0) | ||
42 | |||
43 | #define S3C_RSTCON S3C_HSOTG_PHYREG(0x08) | ||
44 | #define S3C_RSTCON_PHYCLK (1 << 2) | ||
45 | #define S3C_RSTCON_HCLK (1 << 2) | ||
46 | #define S3C_RSTCON_PHY (1 << 0) | ||
47 | |||
48 | #define S3C_PHYTUNE S3C_HSOTG_PHYREG(0x20) | ||
49 | |||
50 | #endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h new file mode 100644 index 000000000000..8d18d9d4d148 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h | |||
@@ -0,0 +1,377 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C - USB2.0 Highspeed/OtG device block registers | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_H | ||
16 | #define __PLAT_S3C64XX_REGS_USB_HSOTG_H __FILE__ | ||
17 | |||
18 | #define S3C_HSOTG_REG(x) (x) | ||
19 | |||
20 | #define S3C_GOTGCTL S3C_HSOTG_REG(0x000) | ||
21 | #define S3C_GOTGCTL_BSESVLD (1 << 19) | ||
22 | #define S3C_GOTGCTL_ASESVLD (1 << 18) | ||
23 | #define S3C_GOTGCTL_DBNC_SHORT (1 << 17) | ||
24 | #define S3C_GOTGCTL_CONID_B (1 << 16) | ||
25 | #define S3C_GOTGCTL_DEVHNPEN (1 << 11) | ||
26 | #define S3C_GOTGCTL_HSSETHNPEN (1 << 10) | ||
27 | #define S3C_GOTGCTL_HNPREQ (1 << 9) | ||
28 | #define S3C_GOTGCTL_HSTNEGSCS (1 << 8) | ||
29 | #define S3C_GOTGCTL_SESREQ (1 << 1) | ||
30 | #define S3C_GOTGCTL_SESREQSCS (1 << 0) | ||
31 | |||
32 | #define S3C_GOTGINT S3C_HSOTG_REG(0x004) | ||
33 | #define S3C_GOTGINT_DbnceDone (1 << 19) | ||
34 | #define S3C_GOTGINT_ADevTOUTChg (1 << 18) | ||
35 | #define S3C_GOTGINT_HstNegDet (1 << 17) | ||
36 | #define S3C_GOTGINT_HstnegSucStsChng (1 << 9) | ||
37 | #define S3C_GOTGINT_SesReqSucStsChng (1 << 8) | ||
38 | #define S3C_GOTGINT_SesEndDet (1 << 2) | ||
39 | |||
40 | #define S3C_GAHBCFG S3C_HSOTG_REG(0x008) | ||
41 | #define S3C_GAHBCFG_PTxFEmpLvl (1 << 8) | ||
42 | #define S3C_GAHBCFG_NPTxFEmpLvl (1 << 7) | ||
43 | #define S3C_GAHBCFG_DMAEn (1 << 5) | ||
44 | #define S3C_GAHBCFG_HBstLen_MASK (0xf << 1) | ||
45 | #define S3C_GAHBCFG_HBstLen_SHIFT (1) | ||
46 | #define S3C_GAHBCFG_HBstLen_Single (0x0 << 1) | ||
47 | #define S3C_GAHBCFG_HBstLen_Incr (0x1 << 1) | ||
48 | #define S3C_GAHBCFG_HBstLen_Incr4 (0x3 << 1) | ||
49 | #define S3C_GAHBCFG_HBstLen_Incr8 (0x5 << 1) | ||
50 | #define S3C_GAHBCFG_HBstLen_Incr16 (0x7 << 1) | ||
51 | #define S3C_GAHBCFG_GlblIntrEn (1 << 0) | ||
52 | |||
53 | #define S3C_GUSBCFG S3C_HSOTG_REG(0x00C) | ||
54 | #define S3C_GUSBCFG_PHYLPClkSel (1 << 15) | ||
55 | #define S3C_GUSBCFG_HNPCap (1 << 9) | ||
56 | #define S3C_GUSBCFG_SRPCap (1 << 8) | ||
57 | #define S3C_GUSBCFG_PHYIf16 (1 << 3) | ||
58 | #define S3C_GUSBCFG_TOutCal_MASK (0x7 << 0) | ||
59 | #define S3C_GUSBCFG_TOutCal_SHIFT (0) | ||
60 | #define S3C_GUSBCFG_TOutCal_LIMIT (0x7) | ||
61 | #define S3C_GUSBCFG_TOutCal(_x) ((_x) << 0) | ||
62 | |||
63 | #define S3C_GRSTCTL S3C_HSOTG_REG(0x010) | ||
64 | |||
65 | #define S3C_GRSTCTL_AHBIdle (1 << 31) | ||
66 | #define S3C_GRSTCTL_DMAReq (1 << 30) | ||
67 | #define S3C_GRSTCTL_TxFNum_MASK (0x1f << 6) | ||
68 | #define S3C_GRSTCTL_TxFNum_SHIFT (6) | ||
69 | #define S3C_GRSTCTL_TxFNum_LIMIT (0x1f) | ||
70 | #define S3C_GRSTCTL_TxFNum(_x) ((_x) << 6) | ||
71 | #define S3C_GRSTCTL_TxFFlsh (1 << 5) | ||
72 | #define S3C_GRSTCTL_RxFFlsh (1 << 4) | ||
73 | #define S3C_GRSTCTL_INTknQFlsh (1 << 3) | ||
74 | #define S3C_GRSTCTL_FrmCntrRst (1 << 2) | ||
75 | #define S3C_GRSTCTL_HSftRst (1 << 1) | ||
76 | #define S3C_GRSTCTL_CSftRst (1 << 0) | ||
77 | |||
78 | #define S3C_GINTSTS S3C_HSOTG_REG(0x014) | ||
79 | #define S3C_GINTMSK S3C_HSOTG_REG(0x018) | ||
80 | |||
81 | #define S3C_GINTSTS_WkUpInt (1 << 31) | ||
82 | #define S3C_GINTSTS_SessReqInt (1 << 30) | ||
83 | #define S3C_GINTSTS_DisconnInt (1 << 29) | ||
84 | #define S3C_GINTSTS_ConIDStsChng (1 << 28) | ||
85 | #define S3C_GINTSTS_PTxFEmp (1 << 26) | ||
86 | #define S3C_GINTSTS_HChInt (1 << 25) | ||
87 | #define S3C_GINTSTS_PrtInt (1 << 24) | ||
88 | #define S3C_GINTSTS_FetSusp (1 << 22) | ||
89 | #define S3C_GINTSTS_incompIP (1 << 21) | ||
90 | #define S3C_GINTSTS_IncomplSOIN (1 << 20) | ||
91 | #define S3C_GINTSTS_OEPInt (1 << 19) | ||
92 | #define S3C_GINTSTS_IEPInt (1 << 18) | ||
93 | #define S3C_GINTSTS_EPMis (1 << 17) | ||
94 | #define S3C_GINTSTS_EOPF (1 << 15) | ||
95 | #define S3C_GINTSTS_ISOutDrop (1 << 14) | ||
96 | #define S3C_GINTSTS_EnumDone (1 << 13) | ||
97 | #define S3C_GINTSTS_USBRst (1 << 12) | ||
98 | #define S3C_GINTSTS_USBSusp (1 << 11) | ||
99 | #define S3C_GINTSTS_ErlySusp (1 << 10) | ||
100 | #define S3C_GINTSTS_GOUTNakEff (1 << 7) | ||
101 | #define S3C_GINTSTS_GINNakEff (1 << 6) | ||
102 | #define S3C_GINTSTS_NPTxFEmp (1 << 5) | ||
103 | #define S3C_GINTSTS_RxFLvl (1 << 4) | ||
104 | #define S3C_GINTSTS_SOF (1 << 3) | ||
105 | #define S3C_GINTSTS_OTGInt (1 << 2) | ||
106 | #define S3C_GINTSTS_ModeMis (1 << 1) | ||
107 | #define S3C_GINTSTS_CurMod_Host (1 << 0) | ||
108 | |||
109 | #define S3C_GRXSTSR S3C_HSOTG_REG(0x01C) | ||
110 | #define S3C_GRXSTSP S3C_HSOTG_REG(0x020) | ||
111 | |||
112 | #define S3C_GRXSTS_FN_MASK (0x7f << 25) | ||
113 | #define S3C_GRXSTS_FN_SHIFT (25) | ||
114 | |||
115 | #define S3C_GRXSTS_PktSts_MASK (0xf << 17) | ||
116 | #define S3C_GRXSTS_PktSts_SHIFT (17) | ||
117 | #define S3C_GRXSTS_PktSts_GlobalOutNAK (0x1 << 17) | ||
118 | #define S3C_GRXSTS_PktSts_OutRX (0x2 << 17) | ||
119 | #define S3C_GRXSTS_PktSts_OutDone (0x3 << 17) | ||
120 | #define S3C_GRXSTS_PktSts_SetupDone (0x4 << 17) | ||
121 | #define S3C_GRXSTS_PktSts_SetupRX (0x6 << 17) | ||
122 | |||
123 | #define S3C_GRXSTS_DPID_MASK (0x3 << 15) | ||
124 | #define S3C_GRXSTS_DPID_SHIFT (15) | ||
125 | #define S3C_GRXSTS_ByteCnt_MASK (0x7ff << 4) | ||
126 | #define S3C_GRXSTS_ByteCnt_SHIFT (4) | ||
127 | #define S3C_GRXSTS_EPNum_MASK (0xf << 0) | ||
128 | #define S3C_GRXSTS_EPNum_SHIFT (0) | ||
129 | |||
130 | #define S3C_GRXFSIZ S3C_HSOTG_REG(0x024) | ||
131 | |||
132 | #define S3C_GNPTXFSIZ S3C_HSOTG_REG(0x028) | ||
133 | |||
134 | #define S3C_GNPTXFSIZ_NPTxFDep_MASK (0xffff << 16) | ||
135 | #define S3C_GNPTXFSIZ_NPTxFDep_SHIFT (16) | ||
136 | #define S3C_GNPTXFSIZ_NPTxFDep_LIMIT (0xffff) | ||
137 | #define S3C_GNPTXFSIZ_NPTxFDep(_x) ((_x) << 16) | ||
138 | #define S3C_GNPTXFSIZ_NPTxFStAddr_MASK (0xffff << 0) | ||
139 | #define S3C_GNPTXFSIZ_NPTxFStAddr_SHIFT (0) | ||
140 | #define S3C_GNPTXFSIZ_NPTxFStAddr_LIMIT (0xffff) | ||
141 | #define S3C_GNPTXFSIZ_NPTxFStAddr(_x) ((_x) << 0) | ||
142 | |||
143 | #define S3C_GNPTXSTS S3C_HSOTG_REG(0x02C) | ||
144 | |||
145 | #define S3C_GNPTXSTS_NPtxQTop_MASK (0x7f << 24) | ||
146 | #define S3C_GNPTXSTS_NPtxQTop_SHIFT (24) | ||
147 | |||
148 | #define S3C_GNPTXSTS_NPTxQSpcAvail_MASK (0xff << 16) | ||
149 | #define S3C_GNPTXSTS_NPTxQSpcAvail_SHIFT (16) | ||
150 | #define S3C_GNPTXSTS_NPTxQSpcAvail_GET(_v) (((_v) >> 16) & 0xff) | ||
151 | |||
152 | #define S3C_GNPTXSTS_NPTxFSpcAvail_MASK (0xffff << 0) | ||
153 | #define S3C_GNPTXSTS_NPTxFSpcAvail_SHIFT (0) | ||
154 | #define S3C_GNPTXSTS_NPTxFSpcAvail_GET(_v) (((_v) >> 0) & 0xffff) | ||
155 | |||
156 | |||
157 | #define S3C_HPTXFSIZ S3C_HSOTG_REG(0x100) | ||
158 | |||
159 | #define S3C_DPTXFSIZn(_a) S3C_HSOTG_REG(0x104 + (((_a) - 1) * 4)) | ||
160 | |||
161 | #define S3C_DPTXFSIZn_DPTxFSize_MASK (0xffff << 16) | ||
162 | #define S3C_DPTXFSIZn_DPTxFSize_SHIFT (16) | ||
163 | #define S3C_DPTXFSIZn_DPTxFSize_GET(_v) (((_v) >> 16) & 0xffff) | ||
164 | #define S3C_DPTXFSIZn_DPTxFSize_LIMIT (0xffff) | ||
165 | #define S3C_DPTXFSIZn_DPTxFSize(_x) ((_x) << 16) | ||
166 | |||
167 | #define S3C_DPTXFSIZn_DPTxFStAddr_MASK (0xffff << 0) | ||
168 | #define S3C_DPTXFSIZn_DPTxFStAddr_SHIFT (0) | ||
169 | |||
170 | /* Device mode registers */ | ||
171 | #define S3C_DCFG S3C_HSOTG_REG(0x800) | ||
172 | |||
173 | #define S3C_DCFG_EPMisCnt_MASK (0x1f << 18) | ||
174 | #define S3C_DCFG_EPMisCnt_SHIFT (18) | ||
175 | #define S3C_DCFG_EPMisCnt_LIMIT (0x1f) | ||
176 | #define S3C_DCFG_EPMisCnt(_x) ((_x) << 18) | ||
177 | |||
178 | #define S3C_DCFG_PerFrInt_MASK (0x3 << 11) | ||
179 | #define S3C_DCFG_PerFrInt_SHIFT (11) | ||
180 | #define S3C_DCFG_PerFrInt_LIMIT (0x3) | ||
181 | #define S3C_DCFG_PerFrInt(_x) ((_x) << 11) | ||
182 | |||
183 | #define S3C_DCFG_DevAddr_MASK (0x7f << 4) | ||
184 | #define S3C_DCFG_DevAddr_SHIFT (4) | ||
185 | #define S3C_DCFG_DevAddr_LIMIT (0x7f) | ||
186 | #define S3C_DCFG_DevAddr(_x) ((_x) << 4) | ||
187 | |||
188 | #define S3C_DCFG_NZStsOUTHShk (1 << 2) | ||
189 | |||
190 | #define S3C_DCFG_DevSpd_MASK (0x3 << 0) | ||
191 | #define S3C_DCFG_DevSpd_SHIFT (0) | ||
192 | #define S3C_DCFG_DevSpd_HS (0x0 << 0) | ||
193 | #define S3C_DCFG_DevSpd_FS (0x1 << 0) | ||
194 | #define S3C_DCFG_DevSpd_LS (0x2 << 0) | ||
195 | #define S3C_DCFG_DevSpd_FS48 (0x3 << 0) | ||
196 | |||
197 | #define S3C_DCTL S3C_HSOTG_REG(0x804) | ||
198 | |||
199 | #define S3C_DCTL_PWROnPrgDone (1 << 11) | ||
200 | #define S3C_DCTL_CGOUTNak (1 << 10) | ||
201 | #define S3C_DCTL_SGOUTNak (1 << 9) | ||
202 | #define S3C_DCTL_CGNPInNAK (1 << 8) | ||
203 | #define S3C_DCTL_SGNPInNAK (1 << 7) | ||
204 | #define S3C_DCTL_TstCtl_MASK (0x7 << 4) | ||
205 | #define S3C_DCTL_TstCtl_SHIFT (4) | ||
206 | #define S3C_DCTL_GOUTNakSts (1 << 3) | ||
207 | #define S3C_DCTL_GNPINNakSts (1 << 2) | ||
208 | #define S3C_DCTL_SftDiscon (1 << 1) | ||
209 | #define S3C_DCTL_RmtWkUpSig (1 << 0) | ||
210 | |||
211 | #define S3C_DSTS S3C_HSOTG_REG(0x808) | ||
212 | |||
213 | #define S3C_DSTS_SOFFN_MASK (0x3fff << 8) | ||
214 | #define S3C_DSTS_SOFFN_SHIFT (8) | ||
215 | #define S3C_DSTS_SOFFN_LIMIT (0x3fff) | ||
216 | #define S3C_DSTS_SOFFN(_x) ((_x) << 8) | ||
217 | #define S3C_DSTS_ErraticErr (1 << 3) | ||
218 | #define S3C_DSTS_EnumSpd_MASK (0x3 << 1) | ||
219 | #define S3C_DSTS_EnumSpd_SHIFT (1) | ||
220 | #define S3C_DSTS_EnumSpd_HS (0x0 << 1) | ||
221 | #define S3C_DSTS_EnumSpd_FS (0x1 << 1) | ||
222 | #define S3C_DSTS_EnumSpd_LS (0x2 << 1) | ||
223 | #define S3C_DSTS_EnumSpd_FS48 (0x3 << 1) | ||
224 | |||
225 | #define S3C_DSTS_SuspSts (1 << 0) | ||
226 | |||
227 | #define S3C_DIEPMSK S3C_HSOTG_REG(0x810) | ||
228 | |||
229 | #define S3C_DIEPMSK_INEPNakEffMsk (1 << 6) | ||
230 | #define S3C_DIEPMSK_INTknEPMisMsk (1 << 5) | ||
231 | #define S3C_DIEPMSK_INTknTXFEmpMsk (1 << 4) | ||
232 | #define S3C_DIEPMSK_TimeOUTMsk (1 << 3) | ||
233 | #define S3C_DIEPMSK_AHBErrMsk (1 << 2) | ||
234 | #define S3C_DIEPMSK_EPDisbldMsk (1 << 1) | ||
235 | #define S3C_DIEPMSK_XferComplMsk (1 << 0) | ||
236 | |||
237 | #define S3C_DOEPMSK S3C_HSOTG_REG(0x814) | ||
238 | |||
239 | #define S3C_DOEPMSK_Back2BackSetup (1 << 6) | ||
240 | #define S3C_DOEPMSK_OUTTknEPdisMsk (1 << 4) | ||
241 | #define S3C_DOEPMSK_SetupMsk (1 << 3) | ||
242 | #define S3C_DOEPMSK_AHBErrMsk (1 << 2) | ||
243 | #define S3C_DOEPMSK_EPDisbldMsk (1 << 1) | ||
244 | #define S3C_DOEPMSK_XferComplMsk (1 << 0) | ||
245 | |||
246 | #define S3C_DAINT S3C_HSOTG_REG(0x818) | ||
247 | #define S3C_DAINTMSK S3C_HSOTG_REG(0x81C) | ||
248 | |||
249 | #define S3C_DAINT_OutEP_SHIFT (16) | ||
250 | #define S3C_DAINT_OutEP(x) (1 << ((x) + 16)) | ||
251 | #define S3C_DAINT_InEP(x) (1 << (x)) | ||
252 | |||
253 | #define S3C_DTKNQR1 S3C_HSOTG_REG(0x820) | ||
254 | #define S3C_DTKNQR2 S3C_HSOTG_REG(0x824) | ||
255 | #define S3C_DTKNQR3 S3C_HSOTG_REG(0x830) | ||
256 | #define S3C_DTKNQR4 S3C_HSOTG_REG(0x834) | ||
257 | |||
258 | #define S3C_DVBUSDIS S3C_HSOTG_REG(0x828) | ||
259 | #define S3C_DVBUSPULSE S3C_HSOTG_REG(0x82C) | ||
260 | |||
261 | #define S3C_DIEPCTL0 S3C_HSOTG_REG(0x900) | ||
262 | #define S3C_DOEPCTL0 S3C_HSOTG_REG(0xB00) | ||
263 | #define S3C_DIEPCTL(_a) S3C_HSOTG_REG(0x900 + ((_a) * 0x20)) | ||
264 | #define S3C_DOEPCTL(_a) S3C_HSOTG_REG(0xB00 + ((_a) * 0x20)) | ||
265 | |||
266 | /* EP0 specialness: | ||
267 | * bits[29..28] - reserved (no SetD0PID, SetD1PID) | ||
268 | * bits[25..22] - should always be zero, this isn't a periodic endpoint | ||
269 | * bits[10..0] - MPS setting differenct for EP0 | ||
270 | */ | ||
271 | #define S3C_D0EPCTL_MPS_MASK (0x3 << 0) | ||
272 | #define S3C_D0EPCTL_MPS_SHIFT (0) | ||
273 | #define S3C_D0EPCTL_MPS_64 (0x0 << 0) | ||
274 | #define S3C_D0EPCTL_MPS_32 (0x1 << 0) | ||
275 | #define S3C_D0EPCTL_MPS_16 (0x2 << 0) | ||
276 | #define S3C_D0EPCTL_MPS_8 (0x3 << 0) | ||
277 | |||
278 | #define S3C_DxEPCTL_EPEna (1 << 31) | ||
279 | #define S3C_DxEPCTL_EPDis (1 << 30) | ||
280 | #define S3C_DxEPCTL_SetD1PID (1 << 29) | ||
281 | #define S3C_DxEPCTL_SetOddFr (1 << 29) | ||
282 | #define S3C_DxEPCTL_SetD0PID (1 << 28) | ||
283 | #define S3C_DxEPCTL_SetEvenFr (1 << 28) | ||
284 | #define S3C_DxEPCTL_SNAK (1 << 27) | ||
285 | #define S3C_DxEPCTL_CNAK (1 << 26) | ||
286 | #define S3C_DxEPCTL_TxFNum_MASK (0xf << 22) | ||
287 | #define S3C_DxEPCTL_TxFNum_SHIFT (22) | ||
288 | #define S3C_DxEPCTL_TxFNum_LIMIT (0xf) | ||
289 | #define S3C_DxEPCTL_TxFNum(_x) ((_x) << 22) | ||
290 | |||
291 | #define S3C_DxEPCTL_Stall (1 << 21) | ||
292 | #define S3C_DxEPCTL_Snp (1 << 20) | ||
293 | #define S3C_DxEPCTL_EPType_MASK (0x3 << 18) | ||
294 | #define S3C_DxEPCTL_EPType_SHIFT (18) | ||
295 | #define S3C_DxEPCTL_EPType_Control (0x0 << 18) | ||
296 | #define S3C_DxEPCTL_EPType_Iso (0x1 << 18) | ||
297 | #define S3C_DxEPCTL_EPType_Bulk (0x2 << 18) | ||
298 | #define S3C_DxEPCTL_EPType_Intterupt (0x3 << 18) | ||
299 | |||
300 | #define S3C_DxEPCTL_NAKsts (1 << 17) | ||
301 | #define S3C_DxEPCTL_DPID (1 << 16) | ||
302 | #define S3C_DxEPCTL_EOFrNum (1 << 16) | ||
303 | #define S3C_DxEPCTL_USBActEp (1 << 15) | ||
304 | #define S3C_DxEPCTL_NextEp_MASK (0xf << 11) | ||
305 | #define S3C_DxEPCTL_NextEp_SHIFT (11) | ||
306 | #define S3C_DxEPCTL_NextEp_LIMIT (0xf) | ||
307 | #define S3C_DxEPCTL_NextEp(_x) ((_x) << 11) | ||
308 | |||
309 | #define S3C_DxEPCTL_MPS_MASK (0x7ff << 0) | ||
310 | #define S3C_DxEPCTL_MPS_SHIFT (0) | ||
311 | #define S3C_DxEPCTL_MPS_LIMIT (0x7ff) | ||
312 | #define S3C_DxEPCTL_MPS(_x) ((_x) << 0) | ||
313 | |||
314 | #define S3C_DIEPINT(_a) S3C_HSOTG_REG(0x908 + ((_a) * 0x20)) | ||
315 | #define S3C_DOEPINT(_a) S3C_HSOTG_REG(0xB08 + ((_a) * 0x20)) | ||
316 | |||
317 | #define S3C_DxEPINT_INEPNakEff (1 << 6) | ||
318 | #define S3C_DxEPINT_Back2BackSetup (1 << 6) | ||
319 | #define S3C_DxEPINT_INTknEPMis (1 << 5) | ||
320 | #define S3C_DxEPINT_INTknTXFEmp (1 << 4) | ||
321 | #define S3C_DxEPINT_OUTTknEPdis (1 << 4) | ||
322 | #define S3C_DxEPINT_Timeout (1 << 3) | ||
323 | #define S3C_DxEPINT_Setup (1 << 3) | ||
324 | #define S3C_DxEPINT_AHBErr (1 << 2) | ||
325 | #define S3C_DxEPINT_EPDisbld (1 << 1) | ||
326 | #define S3C_DxEPINT_XferCompl (1 << 0) | ||
327 | |||
328 | #define S3C_DIEPTSIZ0 S3C_HSOTG_REG(0x910) | ||
329 | |||
330 | #define S3C_DIEPTSIZ0_PktCnt_MASK (0x3 << 19) | ||
331 | #define S3C_DIEPTSIZ0_PktCnt_SHIFT (19) | ||
332 | #define S3C_DIEPTSIZ0_PktCnt_LIMIT (0x3) | ||
333 | #define S3C_DIEPTSIZ0_PktCnt(_x) ((_x) << 19) | ||
334 | |||
335 | #define S3C_DIEPTSIZ0_XferSize_MASK (0x7f << 0) | ||
336 | #define S3C_DIEPTSIZ0_XferSize_SHIFT (0) | ||
337 | #define S3C_DIEPTSIZ0_XferSize_LIMIT (0x7f) | ||
338 | #define S3C_DIEPTSIZ0_XferSize(_x) ((_x) << 0) | ||
339 | |||
340 | |||
341 | #define DOEPTSIZ0 S3C_HSOTG_REG(0xB10) | ||
342 | #define S3C_DOEPTSIZ0_SUPCnt_MASK (0x3 << 29) | ||
343 | #define S3C_DOEPTSIZ0_SUPCnt_SHIFT (29) | ||
344 | #define S3C_DOEPTSIZ0_SUPCnt_LIMIT (0x3) | ||
345 | #define S3C_DOEPTSIZ0_SUPCnt(_x) ((_x) << 29) | ||
346 | |||
347 | #define S3C_DOEPTSIZ0_PktCnt (1 << 19) | ||
348 | #define S3C_DOEPTSIZ0_XferSize_MASK (0x7f << 0) | ||
349 | #define S3C_DOEPTSIZ0_XferSize_SHIFT (0) | ||
350 | |||
351 | #define S3C_DIEPTSIZ(_a) S3C_HSOTG_REG(0x910 + ((_a) * 0x20)) | ||
352 | #define S3C_DOEPTSIZ(_a) S3C_HSOTG_REG(0xB10 + ((_a) * 0x20)) | ||
353 | |||
354 | #define S3C_DxEPTSIZ_MC_MASK (0x3 << 29) | ||
355 | #define S3C_DxEPTSIZ_MC_SHIFT (29) | ||
356 | #define S3C_DxEPTSIZ_MC_LIMIT (0x3) | ||
357 | #define S3C_DxEPTSIZ_MC(_x) ((_x) << 29) | ||
358 | |||
359 | #define S3C_DxEPTSIZ_PktCnt_MASK (0x3ff << 19) | ||
360 | #define S3C_DxEPTSIZ_PktCnt_SHIFT (19) | ||
361 | #define S3C_DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff) | ||
362 | #define S3C_DxEPTSIZ_PktCnt_LIMIT (0x3ff) | ||
363 | #define S3C_DxEPTSIZ_PktCnt(_x) ((_x) << 19) | ||
364 | |||
365 | #define S3C_DxEPTSIZ_XferSize_MASK (0x7ffff << 0) | ||
366 | #define S3C_DxEPTSIZ_XferSize_SHIFT (0) | ||
367 | #define S3C_DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff) | ||
368 | #define S3C_DxEPTSIZ_XferSize_LIMIT (0x7ffff) | ||
369 | #define S3C_DxEPTSIZ_XferSize(_x) ((_x) << 0) | ||
370 | |||
371 | |||
372 | #define S3C_DIEPDMA(_a) S3C_HSOTG_REG(0x914 + ((_a) * 0x20)) | ||
373 | #define S3C_DOEPDMA(_a) S3C_HSOTG_REG(0xB14 + ((_a) * 0x20)) | ||
374 | |||
375 | #define S3C_EPFIFO(_a) S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000)) | ||
376 | |||
377 | #endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/regs-watchdog.h b/arch/arm/plat-samsung/include/plat/regs-watchdog.h new file mode 100644 index 000000000000..4938492470f7 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-watchdog.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* arch/arm/mach-s3c2410/include/mach/regs-watchdog.h | ||
2 | * | ||
3 | * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * S3C2410 Watchdog timer control | ||
11 | */ | ||
12 | |||
13 | |||
14 | #ifndef __ASM_ARCH_REGS_WATCHDOG_H | ||
15 | #define __ASM_ARCH_REGS_WATCHDOG_H | ||
16 | |||
17 | #define S3C_WDOGREG(x) ((x) + S3C_VA_WATCHDOG) | ||
18 | |||
19 | #define S3C2410_WTCON S3C_WDOGREG(0x00) | ||
20 | #define S3C2410_WTDAT S3C_WDOGREG(0x04) | ||
21 | #define S3C2410_WTCNT S3C_WDOGREG(0x08) | ||
22 | |||
23 | /* the watchdog can either generate a reset pulse, or an | ||
24 | * interrupt. | ||
25 | */ | ||
26 | |||
27 | #define S3C2410_WTCON_RSTEN (0x01) | ||
28 | #define S3C2410_WTCON_INTEN (1<<2) | ||
29 | #define S3C2410_WTCON_ENABLE (1<<5) | ||
30 | |||
31 | #define S3C2410_WTCON_DIV16 (0<<3) | ||
32 | #define S3C2410_WTCON_DIV32 (1<<3) | ||
33 | #define S3C2410_WTCON_DIV64 (2<<3) | ||
34 | #define S3C2410_WTCON_DIV128 (3<<3) | ||
35 | |||
36 | #define S3C2410_WTCON_PRESCALE(x) ((x) << 8) | ||
37 | #define S3C2410_WTCON_PRESCALE_MASK (0xff00) | ||
38 | |||
39 | #endif /* __ASM_ARCH_REGS_WATCHDOG_H */ | ||
40 | |||
41 | |||
diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h new file mode 100644 index 000000000000..d17724149315 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | ||
2 | * | ||
3 | * Copyright (C) 2009 Samsung Electronics Ltd. | ||
4 | * Jaswinder Singh <jassi.brar@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __S3C64XX_PLAT_SPI_H | ||
12 | #define __S3C64XX_PLAT_SPI_H | ||
13 | |||
14 | /** | ||
15 | * struct s3c64xx_spi_csinfo - ChipSelect description | ||
16 | * @fb_delay: Slave specific feedback delay. | ||
17 | * Refer to FB_CLK_SEL register definition in SPI chapter. | ||
18 | * @line: Custom 'identity' of the CS line. | ||
19 | * @set_level: CS line control. | ||
20 | * | ||
21 | * This is per SPI-Slave Chipselect information. | ||
22 | * Allocate and initialize one in machine init code and make the | ||
23 | * spi_board_info.controller_data point to it. | ||
24 | */ | ||
25 | struct s3c64xx_spi_csinfo { | ||
26 | u8 fb_delay; | ||
27 | unsigned line; | ||
28 | void (*set_level)(unsigned line_id, int lvl); | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * struct s3c64xx_spi_info - SPI Controller defining structure | ||
33 | * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field. | ||
34 | * @src_clk_name: Platform name of the corresponding clock. | ||
35 | * @num_cs: Number of CS this controller emulates. | ||
36 | * @cfg_gpio: Configure pins for this SPI controller. | ||
37 | * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6 | ||
38 | * @rx_lvl_offset: Depends on tx fifo_lvl field and bus number | ||
39 | * @high_speed: If the controller supports HIGH_SPEED_EN bit | ||
40 | */ | ||
41 | struct s3c64xx_spi_info { | ||
42 | int src_clk_nr; | ||
43 | char *src_clk_name; | ||
44 | |||
45 | int num_cs; | ||
46 | |||
47 | int (*cfg_gpio)(struct platform_device *pdev); | ||
48 | |||
49 | /* Following two fields are for future compatibility */ | ||
50 | int fifo_lvl_mask; | ||
51 | int rx_lvl_offset; | ||
52 | int high_speed; | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * s3c64xx_spi_set_info - SPI Controller configure callback by the board | ||
57 | * initialization code. | ||
58 | * @cntrlr: SPI controller number the configuration is for. | ||
59 | * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks. | ||
60 | * @num_cs: Number of elements in the 'cs' array. | ||
61 | * | ||
62 | * Call this from machine init code for each SPI Controller that | ||
63 | * has some chips attached to it. | ||
64 | */ | ||
65 | extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); | ||
66 | |||
67 | #endif /* __S3C64XX_PLAT_SPI_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h new file mode 100644 index 000000000000..7d07cd7aa4f2 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/sdhci.h | |||
@@ -0,0 +1,221 @@ | |||
1 | /* linux/arch/arm/plat-s3c/include/plat/sdhci.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C Platform - SDHCI (HSMMC) platform data definitions | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef __PLAT_S3C_SDHCI_H | ||
16 | #define __PLAT_S3C_SDHCI_H __FILE__ | ||
17 | |||
18 | struct platform_device; | ||
19 | struct mmc_host; | ||
20 | struct mmc_card; | ||
21 | struct mmc_ios; | ||
22 | |||
23 | /** | ||
24 | * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI | ||
25 | * @max_width: The maximum number of data bits supported. | ||
26 | * @host_caps: Standard MMC host capabilities bit field. | ||
27 | * @cfg_gpio: Configure the GPIO for a specific card bit-width | ||
28 | * @cfg_card: Configure the interface for a specific card and speed. This | ||
29 | * is necessary the controllers and/or GPIO blocks require the | ||
30 | * changing of driver-strength and other controls dependant on | ||
31 | * the card and speed of operation. | ||
32 | * | ||
33 | * Initialisation data specific to either the machine or the platform | ||
34 | * for the device driver to use or call-back when configuring gpio or | ||
35 | * card speed information. | ||
36 | */ | ||
37 | struct s3c_sdhci_platdata { | ||
38 | unsigned int max_width; | ||
39 | unsigned int host_caps; | ||
40 | |||
41 | char **clocks; /* set of clock sources */ | ||
42 | |||
43 | void (*cfg_gpio)(struct platform_device *dev, int width); | ||
44 | void (*cfg_card)(struct platform_device *dev, | ||
45 | void __iomem *regbase, | ||
46 | struct mmc_ios *ios, | ||
47 | struct mmc_card *card); | ||
48 | }; | ||
49 | |||
50 | /** | ||
51 | * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device. | ||
52 | * @pd: Platform data to register to device. | ||
53 | * | ||
54 | * Register the given platform data for use withe S3C SDHCI device. | ||
55 | * The call will copy the platform data, so the board definitions can | ||
56 | * make the structure itself __initdata. | ||
57 | */ | ||
58 | extern void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd); | ||
59 | extern void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd); | ||
60 | extern void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd); | ||
61 | |||
62 | /* Default platform data, exported so that per-cpu initialisation can | ||
63 | * set the correct one when there are more than one cpu type selected. | ||
64 | */ | ||
65 | |||
66 | extern struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata; | ||
67 | extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata; | ||
68 | extern struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata; | ||
69 | |||
70 | /* Helper function availablity */ | ||
71 | |||
72 | extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w); | ||
73 | extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w); | ||
74 | extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w); | ||
75 | extern void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *, int w); | ||
76 | extern void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *, int w); | ||
77 | extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w); | ||
78 | |||
79 | /* S3C6400 SDHCI setup */ | ||
80 | |||
81 | #ifdef CONFIG_S3C64XX_SETUP_SDHCI | ||
82 | extern char *s3c64xx_hsmmc_clksrcs[4]; | ||
83 | |||
84 | #ifdef CONFIG_S3C_DEV_HSMMC | ||
85 | extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev, | ||
86 | void __iomem *r, | ||
87 | struct mmc_ios *ios, | ||
88 | struct mmc_card *card); | ||
89 | |||
90 | static inline void s3c6400_default_sdhci0(void) | ||
91 | { | ||
92 | s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs; | ||
93 | s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio; | ||
94 | s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card; | ||
95 | } | ||
96 | |||
97 | #else | ||
98 | static inline void s3c6400_default_sdhci0(void) { } | ||
99 | #endif /* CONFIG_S3C_DEV_HSMMC */ | ||
100 | |||
101 | #ifdef CONFIG_S3C_DEV_HSMMC1 | ||
102 | static inline void s3c6400_default_sdhci1(void) | ||
103 | { | ||
104 | s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs; | ||
105 | s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio; | ||
106 | s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card; | ||
107 | } | ||
108 | #else | ||
109 | static inline void s3c6400_default_sdhci1(void) { } | ||
110 | #endif /* CONFIG_S3C_DEV_HSMMC1 */ | ||
111 | |||
112 | #ifdef CONFIG_S3C_DEV_HSMMC2 | ||
113 | static inline void s3c6400_default_sdhci2(void) | ||
114 | { | ||
115 | s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs; | ||
116 | s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio; | ||
117 | s3c_hsmmc2_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card; | ||
118 | } | ||
119 | #else | ||
120 | static inline void s3c6400_default_sdhci2(void) { } | ||
121 | #endif /* CONFIG_S3C_DEV_HSMMC2 */ | ||
122 | |||
123 | /* S3C6410 SDHCI setup */ | ||
124 | |||
125 | extern void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev, | ||
126 | void __iomem *r, | ||
127 | struct mmc_ios *ios, | ||
128 | struct mmc_card *card); | ||
129 | |||
130 | #ifdef CONFIG_S3C_DEV_HSMMC | ||
131 | static inline void s3c6410_default_sdhci0(void) | ||
132 | { | ||
133 | s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs; | ||
134 | s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio; | ||
135 | s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card; | ||
136 | } | ||
137 | #else | ||
138 | static inline void s3c6410_default_sdhci0(void) { } | ||
139 | #endif /* CONFIG_S3C_DEV_HSMMC */ | ||
140 | |||
141 | #ifdef CONFIG_S3C_DEV_HSMMC1 | ||
142 | static inline void s3c6410_default_sdhci1(void) | ||
143 | { | ||
144 | s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs; | ||
145 | s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio; | ||
146 | s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card; | ||
147 | } | ||
148 | #else | ||
149 | static inline void s3c6410_default_sdhci1(void) { } | ||
150 | #endif /* CONFIG_S3C_DEV_HSMMC1 */ | ||
151 | |||
152 | #ifdef CONFIG_S3C_DEV_HSMMC2 | ||
153 | static inline void s3c6410_default_sdhci2(void) | ||
154 | { | ||
155 | s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs; | ||
156 | s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio; | ||
157 | s3c_hsmmc2_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card; | ||
158 | } | ||
159 | #else | ||
160 | static inline void s3c6410_default_sdhci2(void) { } | ||
161 | #endif /* CONFIG_S3C_DEV_HSMMC2 */ | ||
162 | |||
163 | #else | ||
164 | static inline void s3c6410_default_sdhci0(void) { } | ||
165 | static inline void s3c6410_default_sdhci1(void) { } | ||
166 | static inline void s3c6400_default_sdhci0(void) { } | ||
167 | static inline void s3c6400_default_sdhci1(void) { } | ||
168 | |||
169 | #endif /* CONFIG_S3C64XX_SETUP_SDHCI */ | ||
170 | |||
171 | /* S5PC100 SDHCI setup */ | ||
172 | |||
173 | #ifdef CONFIG_S5PC100_SETUP_SDHCI | ||
174 | extern char *s5pc100_hsmmc_clksrcs[4]; | ||
175 | |||
176 | extern void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev, | ||
177 | void __iomem *r, | ||
178 | struct mmc_ios *ios, | ||
179 | struct mmc_card *card); | ||
180 | |||
181 | #ifdef CONFIG_S3C_DEV_HSMMC | ||
182 | static inline void s5pc100_default_sdhci0(void) | ||
183 | { | ||
184 | s3c_hsmmc0_def_platdata.clocks = s5pc100_hsmmc_clksrcs; | ||
185 | s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio; | ||
186 | s3c_hsmmc0_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card; | ||
187 | } | ||
188 | #else | ||
189 | static inline void s5pc100_default_sdhci0(void) { } | ||
190 | #endif /* CONFIG_S3C_DEV_HSMMC */ | ||
191 | |||
192 | #ifdef CONFIG_S3C_DEV_HSMMC1 | ||
193 | static inline void s5pc100_default_sdhci1(void) | ||
194 | { | ||
195 | s3c_hsmmc1_def_platdata.clocks = s5pc100_hsmmc_clksrcs; | ||
196 | s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio; | ||
197 | s3c_hsmmc1_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card; | ||
198 | } | ||
199 | #else | ||
200 | static inline void s5pc100_default_sdhci1(void) { } | ||
201 | #endif /* CONFIG_S3C_DEV_HSMMC1 */ | ||
202 | |||
203 | #ifdef CONFIG_S3C_DEV_HSMMC2 | ||
204 | static inline void s5pc100_default_sdhci2(void) | ||
205 | { | ||
206 | s3c_hsmmc2_def_platdata.clocks = s5pc100_hsmmc_clksrcs; | ||
207 | s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio; | ||
208 | s3c_hsmmc2_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card; | ||
209 | } | ||
210 | #else | ||
211 | static inline void s5pc100_default_sdhci2(void) { } | ||
212 | #endif /* CONFIG_S3C_DEV_HSMMC1 */ | ||
213 | |||
214 | |||
215 | #else | ||
216 | static inline void s5pc100_default_sdhci0(void) { } | ||
217 | static inline void s5pc100_default_sdhci1(void) { } | ||
218 | static inline void s5pc100_default_sdhci2(void) { } | ||
219 | #endif /* CONFIG_S5PC100_SETUP_SDHCI */ | ||
220 | |||
221 | #endif /* __PLAT_S3C_SDHCI_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/udc-hs.h b/arch/arm/plat-samsung/include/plat/udc-hs.h new file mode 100644 index 000000000000..a22a4f2eea94 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/udc-hs.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/udc-hs.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * S3C USB2.0 High-speed / OtG platform information | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | enum s3c_hsotg_dmamode { | ||
16 | S3C_HSOTG_DMA_NONE, /* do not use DMA at-all */ | ||
17 | S3C_HSOTG_DMA_ONLY, /* always use DMA */ | ||
18 | S3C_HSOTG_DMA_DRV, /* DMA is chosen by driver */ | ||
19 | }; | ||
20 | |||
21 | /** | ||
22 | * struct s3c_hsotg_plat - platform data for high-speed otg/udc | ||
23 | * @dma: Whether to use DMA or not. | ||
24 | * @is_osc: The clock source is an oscillator, not a crystal | ||
25 | */ | ||
26 | struct s3c_hsotg_plat { | ||
27 | enum s3c_hsotg_dmamode dma; | ||
28 | unsigned int is_osc : 1; | ||
29 | }; | ||
diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h new file mode 100644 index 000000000000..7d6ed7263d57 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/uncompress.h | |||
@@ -0,0 +1,184 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/uncompress.h | ||
2 | * | ||
3 | * Copyright 2003, 2007 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C - uncompress code | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASM_PLAT_UNCOMPRESS_H | ||
15 | #define __ASM_PLAT_UNCOMPRESS_H | ||
16 | |||
17 | typedef unsigned int upf_t; /* cannot include linux/serial_core.h */ | ||
18 | |||
19 | /* uart setup */ | ||
20 | |||
21 | static unsigned int fifo_mask; | ||
22 | static unsigned int fifo_max; | ||
23 | |||
24 | /* forward declerations */ | ||
25 | |||
26 | static void arch_detect_cpu(void); | ||
27 | |||
28 | /* defines for UART registers */ | ||
29 | |||
30 | #include <plat/regs-serial.h> | ||
31 | #include <plat/regs-watchdog.h> | ||
32 | |||
33 | /* working in physical space... */ | ||
34 | #undef S3C2410_WDOGREG | ||
35 | #define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x))) | ||
36 | |||
37 | /* how many bytes we allow into the FIFO at a time in FIFO mode */ | ||
38 | #define FIFO_MAX (14) | ||
39 | |||
40 | #define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT) | ||
41 | |||
42 | static __inline__ void | ||
43 | uart_wr(unsigned int reg, unsigned int val) | ||
44 | { | ||
45 | volatile unsigned int *ptr; | ||
46 | |||
47 | ptr = (volatile unsigned int *)(reg + uart_base); | ||
48 | *ptr = val; | ||
49 | } | ||
50 | |||
51 | static __inline__ unsigned int | ||
52 | uart_rd(unsigned int reg) | ||
53 | { | ||
54 | volatile unsigned int *ptr; | ||
55 | |||
56 | ptr = (volatile unsigned int *)(reg + uart_base); | ||
57 | return *ptr; | ||
58 | } | ||
59 | |||
60 | /* we can deal with the case the UARTs are being run | ||
61 | * in FIFO mode, so that we don't hold up our execution | ||
62 | * waiting for tx to happen... | ||
63 | */ | ||
64 | |||
65 | static void putc(int ch) | ||
66 | { | ||
67 | if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) { | ||
68 | int level; | ||
69 | |||
70 | while (1) { | ||
71 | level = uart_rd(S3C2410_UFSTAT); | ||
72 | level &= fifo_mask; | ||
73 | |||
74 | if (level < fifo_max) | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | } else { | ||
79 | /* not using fifos */ | ||
80 | |||
81 | while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE) | ||
82 | barrier(); | ||
83 | } | ||
84 | |||
85 | /* write byte to transmission register */ | ||
86 | uart_wr(S3C2410_UTXH, ch); | ||
87 | } | ||
88 | |||
89 | static inline void flush(void) | ||
90 | { | ||
91 | } | ||
92 | |||
93 | #define __raw_writel(d, ad) \ | ||
94 | do { \ | ||
95 | *((volatile unsigned int __force *)(ad)) = (d); \ | ||
96 | } while (0) | ||
97 | |||
98 | /* CONFIG_S3C_BOOT_WATCHDOG | ||
99 | * | ||
100 | * Simple boot-time watchdog setup, to reboot the system if there is | ||
101 | * any problem with the boot process | ||
102 | */ | ||
103 | |||
104 | #ifdef CONFIG_S3C_BOOT_WATCHDOG | ||
105 | |||
106 | #define WDOG_COUNT (0xff00) | ||
107 | |||
108 | static inline void arch_decomp_wdog(void) | ||
109 | { | ||
110 | __raw_writel(WDOG_COUNT, S3C2410_WTCNT); | ||
111 | } | ||
112 | |||
113 | static void arch_decomp_wdog_start(void) | ||
114 | { | ||
115 | __raw_writel(WDOG_COUNT, S3C2410_WTDAT); | ||
116 | __raw_writel(WDOG_COUNT, S3C2410_WTCNT); | ||
117 | __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON); | ||
118 | } | ||
119 | |||
120 | #else | ||
121 | #define arch_decomp_wdog_start() | ||
122 | #define arch_decomp_wdog() | ||
123 | #endif | ||
124 | |||
125 | #ifdef CONFIG_S3C_BOOT_ERROR_RESET | ||
126 | |||
127 | static void arch_decomp_error(const char *x) | ||
128 | { | ||
129 | putstr("\n\n"); | ||
130 | putstr(x); | ||
131 | putstr("\n\n -- System resetting\n"); | ||
132 | |||
133 | __raw_writel(0x4000, S3C2410_WTDAT); | ||
134 | __raw_writel(0x4000, S3C2410_WTCNT); | ||
135 | __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON); | ||
136 | |||
137 | while(1); | ||
138 | } | ||
139 | |||
140 | #define arch_error arch_decomp_error | ||
141 | #endif | ||
142 | |||
143 | #ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO | ||
144 | static inline void arch_enable_uart_fifo(void) | ||
145 | { | ||
146 | u32 fifocon = uart_rd(S3C2410_UFCON); | ||
147 | |||
148 | if (!(fifocon & S3C2410_UFCON_FIFOMODE)) { | ||
149 | fifocon |= S3C2410_UFCON_RESETBOTH; | ||
150 | uart_wr(S3C2410_UFCON, fifocon); | ||
151 | |||
152 | /* wait for fifo reset to complete */ | ||
153 | while (1) { | ||
154 | fifocon = uart_rd(S3C2410_UFCON); | ||
155 | if (!(fifocon & S3C2410_UFCON_RESETBOTH)) | ||
156 | break; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | #else | ||
161 | #define arch_enable_uart_fifo() do { } while(0) | ||
162 | #endif | ||
163 | |||
164 | |||
165 | static void | ||
166 | arch_decomp_setup(void) | ||
167 | { | ||
168 | /* we may need to setup the uart(s) here if we are not running | ||
169 | * on an BAST... the BAST will have left the uarts configured | ||
170 | * after calling linux. | ||
171 | */ | ||
172 | |||
173 | arch_detect_cpu(); | ||
174 | arch_decomp_wdog_start(); | ||
175 | |||
176 | /* Enable the UART FIFOs if they where not enabled and our | ||
177 | * configuration says we should turn them on. | ||
178 | */ | ||
179 | |||
180 | arch_enable_uart_fifo(); | ||
181 | } | ||
182 | |||
183 | |||
184 | #endif /* __ASM_PLAT_UNCOMPRESS_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/usb-control.h b/arch/arm/plat-samsung/include/plat/usb-control.h new file mode 100644 index 000000000000..7fa1fbefc3f2 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/usb-control.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/usb-control.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C - USB host port information | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_USBCONTROL_H | ||
14 | #define __ASM_ARCH_USBCONTROL_H | ||
15 | |||
16 | #define S3C_HCDFLG_USED (1) | ||
17 | |||
18 | struct s3c2410_hcd_port { | ||
19 | unsigned char flags; | ||
20 | unsigned char power; | ||
21 | unsigned char oc_status; | ||
22 | unsigned char oc_changed; | ||
23 | }; | ||
24 | |||
25 | struct s3c2410_hcd_info { | ||
26 | struct usb_hcd *hcd; | ||
27 | struct s3c2410_hcd_port port[2]; | ||
28 | |||
29 | void (*power_control)(int port, int to); | ||
30 | void (*enable_oc)(struct s3c2410_hcd_info *, int on); | ||
31 | void (*report_oc)(struct s3c2410_hcd_info *, int ports); | ||
32 | }; | ||
33 | |||
34 | static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports) | ||
35 | { | ||
36 | if (info->report_oc != NULL) { | ||
37 | (info->report_oc)(info, ports); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | extern void s3c_ohci_set_platdata(struct s3c2410_hcd_info *info); | ||
42 | |||
43 | #endif /*__ASM_ARCH_USBCONTROL_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/watchdog-reset.h b/arch/arm/plat-samsung/include/plat/watchdog-reset.h new file mode 100644 index 000000000000..54b762acb5a0 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/watchdog-reset.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/watchdog-reset.h | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2410 - System define for arch_reset() function | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <plat/regs-watchdog.h> | ||
14 | #include <mach/map.h> | ||
15 | |||
16 | #include <linux/clk.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
20 | static inline void arch_wdt_reset(void) | ||
21 | { | ||
22 | struct clk *wdtclk; | ||
23 | |||
24 | printk("arch_reset: attempting watchdog reset\n"); | ||
25 | |||
26 | __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */ | ||
27 | |||
28 | wdtclk = clk_get(NULL, "watchdog"); | ||
29 | if (!IS_ERR(wdtclk)) { | ||
30 | clk_enable(wdtclk); | ||
31 | } else | ||
32 | printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__); | ||
33 | |||
34 | /* put initial values into count and data */ | ||
35 | __raw_writel(0x80, S3C2410_WTCNT); | ||
36 | __raw_writel(0x80, S3C2410_WTDAT); | ||
37 | |||
38 | /* set the watchdog to go and reset... */ | ||
39 | __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN | | ||
40 | S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON); | ||
41 | |||
42 | /* wait for reset to assert... */ | ||
43 | mdelay(500); | ||
44 | |||
45 | printk(KERN_ERR "Watchdog reset failed to assert reset\n"); | ||
46 | |||
47 | /* delay to allow the serial port to show the message */ | ||
48 | mdelay(50); | ||
49 | } | ||
diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c new file mode 100644 index 000000000000..6790edfaca6f --- /dev/null +++ b/arch/arm/plat-samsung/init.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* linux/arch/arm/plat-s3c/init.c | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C series CPU initialisation | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/ioport.h> | ||
18 | #include <linux/serial_core.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | |||
21 | #include <mach/hardware.h> | ||
22 | |||
23 | #include <asm/mach/arch.h> | ||
24 | #include <asm/mach/map.h> | ||
25 | |||
26 | #include <plat/cpu.h> | ||
27 | #include <plat/devs.h> | ||
28 | #include <plat/clock.h> | ||
29 | |||
30 | #include <plat/regs-serial.h> | ||
31 | |||
32 | static struct cpu_table *cpu; | ||
33 | |||
34 | static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode, | ||
35 | struct cpu_table *tab, | ||
36 | unsigned int count) | ||
37 | { | ||
38 | for (; count != 0; count--, tab++) { | ||
39 | if ((idcode & tab->idmask) == tab->idcode) | ||
40 | return tab; | ||
41 | } | ||
42 | |||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | void __init s3c_init_cpu(unsigned long idcode, | ||
47 | struct cpu_table *cputab, unsigned int cputab_size) | ||
48 | { | ||
49 | cpu = s3c_lookup_cpu(idcode, cputab, cputab_size); | ||
50 | |||
51 | if (cpu == NULL) { | ||
52 | printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode); | ||
53 | panic("Unknown S3C24XX CPU"); | ||
54 | } | ||
55 | |||
56 | printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); | ||
57 | |||
58 | if (cpu->map_io == NULL || cpu->init == NULL) { | ||
59 | printk(KERN_ERR "CPU %s support not enabled\n", cpu->name); | ||
60 | panic("Unsupported Samsung CPU"); | ||
61 | } | ||
62 | |||
63 | cpu->map_io(); | ||
64 | } | ||
65 | |||
66 | /* s3c24xx_init_clocks | ||
67 | * | ||
68 | * Initialise the clock subsystem and associated information from the | ||
69 | * given master crystal value. | ||
70 | * | ||
71 | * xtal = 0 -> use default PLL crystal value (normally 12MHz) | ||
72 | * != 0 -> PLL crystal value in Hz | ||
73 | */ | ||
74 | |||
75 | void __init s3c24xx_init_clocks(int xtal) | ||
76 | { | ||
77 | if (xtal == 0) | ||
78 | xtal = 12*1000*1000; | ||
79 | |||
80 | if (cpu == NULL) | ||
81 | panic("s3c24xx_init_clocks: no cpu setup?\n"); | ||
82 | |||
83 | if (cpu->init_clocks == NULL) | ||
84 | panic("s3c24xx_init_clocks: cpu has no clock init\n"); | ||
85 | else | ||
86 | (cpu->init_clocks)(xtal); | ||
87 | } | ||
88 | |||
89 | /* uart management */ | ||
90 | |||
91 | static int nr_uarts __initdata = 0; | ||
92 | |||
93 | static struct s3c2410_uartcfg uart_cfgs[CONFIG_SERIAL_SAMSUNG_UARTS]; | ||
94 | |||
95 | /* s3c24xx_init_uartdevs | ||
96 | * | ||
97 | * copy the specified platform data and configuration into our central | ||
98 | * set of devices, before the data is thrown away after the init process. | ||
99 | * | ||
100 | * This also fills in the array passed to the serial driver for the | ||
101 | * early initialisation of the console. | ||
102 | */ | ||
103 | |||
104 | void __init s3c24xx_init_uartdevs(char *name, | ||
105 | struct s3c24xx_uart_resources *res, | ||
106 | struct s3c2410_uartcfg *cfg, int no) | ||
107 | { | ||
108 | struct platform_device *platdev; | ||
109 | struct s3c2410_uartcfg *cfgptr = uart_cfgs; | ||
110 | struct s3c24xx_uart_resources *resp; | ||
111 | int uart; | ||
112 | |||
113 | memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no); | ||
114 | |||
115 | for (uart = 0; uart < no; uart++, cfg++, cfgptr++) { | ||
116 | platdev = s3c24xx_uart_src[cfgptr->hwport]; | ||
117 | |||
118 | resp = res + cfgptr->hwport; | ||
119 | |||
120 | s3c24xx_uart_devs[uart] = platdev; | ||
121 | |||
122 | platdev->name = name; | ||
123 | platdev->resource = resp->resources; | ||
124 | platdev->num_resources = resp->nr_resources; | ||
125 | |||
126 | platdev->dev.platform_data = cfgptr; | ||
127 | } | ||
128 | |||
129 | nr_uarts = no; | ||
130 | } | ||
131 | |||
132 | void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) | ||
133 | { | ||
134 | if (cpu == NULL) | ||
135 | return; | ||
136 | |||
137 | if (cpu->init_uarts == NULL) { | ||
138 | printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n"); | ||
139 | } else | ||
140 | (cpu->init_uarts)(cfg, no); | ||
141 | } | ||
142 | |||
143 | static int __init s3c_arch_init(void) | ||
144 | { | ||
145 | int ret; | ||
146 | |||
147 | // do the correct init for cpu | ||
148 | |||
149 | if (cpu == NULL) | ||
150 | panic("s3c_arch_init: NULL cpu\n"); | ||
151 | |||
152 | ret = (cpu->init)(); | ||
153 | if (ret != 0) | ||
154 | return ret; | ||
155 | |||
156 | ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | arch_initcall(s3c_arch_init); | ||
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c new file mode 100644 index 000000000000..4f8c102674ae --- /dev/null +++ b/arch/arm/plat-samsung/irq-uart.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* arch/arm/plat-samsung/irq-uart.c | ||
2 | * originally part of arch/arm/plat-s3c64xx/irq.c | ||
3 | * | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * Samsung- UART Interrupt handling | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/serial_core.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <mach/map.h> | ||
23 | #include <plat/irq-uart.h> | ||
24 | #include <plat/regs-serial.h> | ||
25 | #include <plat/cpu.h> | ||
26 | |||
27 | /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | ||
28 | * are consecutive when looking up the interrupt in the demux routines. | ||
29 | */ | ||
30 | |||
31 | static inline void __iomem *s3c_irq_uart_base(unsigned int irq) | ||
32 | { | ||
33 | struct s3c_uart_irq *uirq = get_irq_chip_data(irq); | ||
34 | return uirq->regs; | ||
35 | } | ||
36 | |||
37 | static inline unsigned int s3c_irq_uart_bit(unsigned int irq) | ||
38 | { | ||
39 | return irq & 3; | ||
40 | } | ||
41 | |||
42 | static void s3c_irq_uart_mask(unsigned int irq) | ||
43 | { | ||
44 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
45 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
46 | u32 reg; | ||
47 | |||
48 | reg = __raw_readl(regs + S3C64XX_UINTM); | ||
49 | reg |= (1 << bit); | ||
50 | __raw_writel(reg, regs + S3C64XX_UINTM); | ||
51 | } | ||
52 | |||
53 | static void s3c_irq_uart_maskack(unsigned int irq) | ||
54 | { | ||
55 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
56 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
57 | u32 reg; | ||
58 | |||
59 | reg = __raw_readl(regs + S3C64XX_UINTM); | ||
60 | reg |= (1 << bit); | ||
61 | __raw_writel(reg, regs + S3C64XX_UINTM); | ||
62 | __raw_writel(1 << bit, regs + S3C64XX_UINTP); | ||
63 | } | ||
64 | |||
65 | static void s3c_irq_uart_unmask(unsigned int irq) | ||
66 | { | ||
67 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
68 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
69 | u32 reg; | ||
70 | |||
71 | reg = __raw_readl(regs + S3C64XX_UINTM); | ||
72 | reg &= ~(1 << bit); | ||
73 | __raw_writel(reg, regs + S3C64XX_UINTM); | ||
74 | } | ||
75 | |||
76 | static void s3c_irq_uart_ack(unsigned int irq) | ||
77 | { | ||
78 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
79 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
80 | |||
81 | __raw_writel(1 << bit, regs + S3C64XX_UINTP); | ||
82 | } | ||
83 | |||
84 | static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) | ||
85 | { | ||
86 | struct s3c_uart_irq *uirq = desc->handler_data; | ||
87 | u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); | ||
88 | int base = uirq->base_irq; | ||
89 | |||
90 | if (pend & (1 << 0)) | ||
91 | generic_handle_irq(base); | ||
92 | if (pend & (1 << 1)) | ||
93 | generic_handle_irq(base + 1); | ||
94 | if (pend & (1 << 2)) | ||
95 | generic_handle_irq(base + 2); | ||
96 | if (pend & (1 << 3)) | ||
97 | generic_handle_irq(base + 3); | ||
98 | } | ||
99 | |||
100 | static struct irq_chip s3c_irq_uart = { | ||
101 | .name = "s3c-uart", | ||
102 | .mask = s3c_irq_uart_mask, | ||
103 | .unmask = s3c_irq_uart_unmask, | ||
104 | .mask_ack = s3c_irq_uart_maskack, | ||
105 | .ack = s3c_irq_uart_ack, | ||
106 | }; | ||
107 | |||
108 | static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) | ||
109 | { | ||
110 | struct irq_desc *desc = irq_to_desc(uirq->parent_irq); | ||
111 | void __iomem *reg_base = uirq->regs; | ||
112 | unsigned int irq; | ||
113 | int offs; | ||
114 | |||
115 | /* mask all interrupts at the start. */ | ||
116 | __raw_writel(0xf, reg_base + S3C64XX_UINTM); | ||
117 | |||
118 | for (offs = 0; offs < 3; offs++) { | ||
119 | irq = uirq->base_irq + offs; | ||
120 | |||
121 | set_irq_chip(irq, &s3c_irq_uart); | ||
122 | set_irq_chip_data(irq, uirq); | ||
123 | set_irq_handler(irq, handle_level_irq); | ||
124 | set_irq_flags(irq, IRQF_VALID); | ||
125 | } | ||
126 | |||
127 | desc->handler_data = uirq; | ||
128 | set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing | ||
133 | * @irq: The interrupt data for registering | ||
134 | * @nr_irqs: The number of interrupt descriptions in @irq. | ||
135 | * | ||
136 | * Register the UART interrupts specified by @irq including the demuxing | ||
137 | * routines. This supports the S3C6400 and newer style of devices. | ||
138 | */ | ||
139 | void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs) | ||
140 | { | ||
141 | for (; nr_irqs > 0; nr_irqs--, irq++) | ||
142 | s3c_init_uart_irq(irq); | ||
143 | } | ||
diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c new file mode 100644 index 000000000000..0270519fcabc --- /dev/null +++ b/arch/arm/plat-samsung/irq-vic-timer.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* arch/arm/plat-samsung/irq-vic-timer.c | ||
2 | * originally part of arch/arm/plat-s3c64xx/irq.c | ||
3 | * | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * S3C64XX - Interrupt handling | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <mach/map.h> | ||
22 | #include <plat/irq-vic-timer.h> | ||
23 | #include <plat/regs-timer.h> | ||
24 | |||
25 | static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc) | ||
26 | { | ||
27 | generic_handle_irq((int)desc->handler_data); | ||
28 | } | ||
29 | |||
30 | /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ | ||
31 | |||
32 | static void s3c_irq_timer_mask(unsigned int irq) | ||
33 | { | ||
34 | u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); | ||
35 | |||
36 | reg &= 0x1f; /* mask out pending interrupts */ | ||
37 | reg &= ~(1 << (irq - IRQ_TIMER0)); | ||
38 | __raw_writel(reg, S3C64XX_TINT_CSTAT); | ||
39 | } | ||
40 | |||
41 | static void s3c_irq_timer_unmask(unsigned int irq) | ||
42 | { | ||
43 | u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); | ||
44 | |||
45 | reg &= 0x1f; /* mask out pending interrupts */ | ||
46 | reg |= 1 << (irq - IRQ_TIMER0); | ||
47 | __raw_writel(reg, S3C64XX_TINT_CSTAT); | ||
48 | } | ||
49 | |||
50 | static void s3c_irq_timer_ack(unsigned int irq) | ||
51 | { | ||
52 | u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); | ||
53 | |||
54 | reg &= 0x1f; | ||
55 | reg |= (1 << 5) << (irq - IRQ_TIMER0); | ||
56 | __raw_writel(reg, S3C64XX_TINT_CSTAT); | ||
57 | } | ||
58 | |||
59 | static struct irq_chip s3c_irq_timer = { | ||
60 | .name = "s3c-timer", | ||
61 | .mask = s3c_irq_timer_mask, | ||
62 | .unmask = s3c_irq_timer_unmask, | ||
63 | .ack = s3c_irq_timer_ack, | ||
64 | }; | ||
65 | |||
66 | /** | ||
67 | * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\ | ||
68 | * @parent_irq: The parent IRQ on the VIC for the timer. | ||
69 | * @timer_irq: The IRQ to be used for the timer. | ||
70 | * | ||
71 | * Register the necessary IRQ chaining and support for the timer IRQs | ||
72 | * chained of the VIC. | ||
73 | */ | ||
74 | void __init s3c_init_vic_timer_irq(unsigned int parent_irq, | ||
75 | unsigned int timer_irq) | ||
76 | { | ||
77 | struct irq_desc *desc = irq_to_desc(parent_irq); | ||
78 | |||
79 | set_irq_chained_handler(parent_irq, s3c_irq_demux_vic_timer); | ||
80 | |||
81 | set_irq_chip(timer_irq, &s3c_irq_timer); | ||
82 | set_irq_handler(timer_irq, handle_level_irq); | ||
83 | set_irq_flags(timer_irq, IRQF_VALID); | ||
84 | |||
85 | desc->handler_data = (void *)timer_irq; | ||
86 | } | ||
diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c new file mode 100644 index 000000000000..0b5bb774192a --- /dev/null +++ b/arch/arm/plat-samsung/pm-check.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* linux/arch/arm/plat-s3c/pm-check.c | ||
2 | * originally in linux/arch/arm/plat-s3c24xx/pm.c | ||
3 | * | ||
4 | * Copyright (c) 2004-2008 Simtec Electronics | ||
5 | * http://armlinux.simtec.co.uk | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * S3C Power Mangament - suspend/resume memory corruptiuon check. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/suspend.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/crc32.h> | ||
19 | #include <linux/ioport.h> | ||
20 | |||
21 | #include <plat/pm.h> | ||
22 | |||
23 | #if CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE < 1 | ||
24 | #error CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE must be a positive non-zero value | ||
25 | #endif | ||
26 | |||
27 | /* suspend checking code... | ||
28 | * | ||
29 | * this next area does a set of crc checks over all the installed | ||
30 | * memory, so the system can verify if the resume was ok. | ||
31 | * | ||
32 | * CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE defines the block-size for the CRC, | ||
33 | * increasing it will mean that the area corrupted will be less easy to spot, | ||
34 | * and reducing the size will cause the CRC save area to grow | ||
35 | */ | ||
36 | |||
37 | #define CHECK_CHUNKSIZE (CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE * 1024) | ||
38 | |||
39 | static u32 crc_size; /* size needed for the crc block */ | ||
40 | static u32 *crcs; /* allocated over suspend/resume */ | ||
41 | |||
42 | typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg); | ||
43 | |||
44 | /* s3c_pm_run_res | ||
45 | * | ||
46 | * go through the given resource list, and look for system ram | ||
47 | */ | ||
48 | |||
49 | static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg) | ||
50 | { | ||
51 | while (ptr != NULL) { | ||
52 | if (ptr->child != NULL) | ||
53 | s3c_pm_run_res(ptr->child, fn, arg); | ||
54 | |||
55 | if ((ptr->flags & IORESOURCE_MEM) && | ||
56 | strcmp(ptr->name, "System RAM") == 0) { | ||
57 | S3C_PMDBG("Found system RAM at %08lx..%08lx\n", | ||
58 | (unsigned long)ptr->start, | ||
59 | (unsigned long)ptr->end); | ||
60 | arg = (fn)(ptr, arg); | ||
61 | } | ||
62 | |||
63 | ptr = ptr->sibling; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg) | ||
68 | { | ||
69 | s3c_pm_run_res(&iomem_resource, fn, arg); | ||
70 | } | ||
71 | |||
72 | static u32 *s3c_pm_countram(struct resource *res, u32 *val) | ||
73 | { | ||
74 | u32 size = (u32)(res->end - res->start)+1; | ||
75 | |||
76 | size += CHECK_CHUNKSIZE-1; | ||
77 | size /= CHECK_CHUNKSIZE; | ||
78 | |||
79 | S3C_PMDBG("Area %08lx..%08lx, %d blocks\n", | ||
80 | (unsigned long)res->start, (unsigned long)res->end, size); | ||
81 | |||
82 | *val += size * sizeof(u32); | ||
83 | return val; | ||
84 | } | ||
85 | |||
86 | /* s3c_pm_prepare_check | ||
87 | * | ||
88 | * prepare the necessary information for creating the CRCs. This | ||
89 | * must be done before the final save, as it will require memory | ||
90 | * allocating, and thus touching bits of the kernel we do not | ||
91 | * know about. | ||
92 | */ | ||
93 | |||
94 | void s3c_pm_check_prepare(void) | ||
95 | { | ||
96 | crc_size = 0; | ||
97 | |||
98 | s3c_pm_run_sysram(s3c_pm_countram, &crc_size); | ||
99 | |||
100 | S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size); | ||
101 | |||
102 | crcs = kmalloc(crc_size+4, GFP_KERNEL); | ||
103 | if (crcs == NULL) | ||
104 | printk(KERN_ERR "Cannot allocated CRC save area\n"); | ||
105 | } | ||
106 | |||
107 | static u32 *s3c_pm_makecheck(struct resource *res, u32 *val) | ||
108 | { | ||
109 | unsigned long addr, left; | ||
110 | |||
111 | for (addr = res->start; addr < res->end; | ||
112 | addr += CHECK_CHUNKSIZE) { | ||
113 | left = res->end - addr; | ||
114 | |||
115 | if (left > CHECK_CHUNKSIZE) | ||
116 | left = CHECK_CHUNKSIZE; | ||
117 | |||
118 | *val = crc32_le(~0, phys_to_virt(addr), left); | ||
119 | val++; | ||
120 | } | ||
121 | |||
122 | return val; | ||
123 | } | ||
124 | |||
125 | /* s3c_pm_check_store | ||
126 | * | ||
127 | * compute the CRC values for the memory blocks before the final | ||
128 | * sleep. | ||
129 | */ | ||
130 | |||
131 | void s3c_pm_check_store(void) | ||
132 | { | ||
133 | if (crcs != NULL) | ||
134 | s3c_pm_run_sysram(s3c_pm_makecheck, crcs); | ||
135 | } | ||
136 | |||
137 | /* in_region | ||
138 | * | ||
139 | * return TRUE if the area defined by ptr..ptr+size contains the | ||
140 | * what..what+whatsz | ||
141 | */ | ||
142 | |||
143 | static inline int in_region(void *ptr, int size, void *what, size_t whatsz) | ||
144 | { | ||
145 | if ((what+whatsz) < ptr) | ||
146 | return 0; | ||
147 | |||
148 | if (what > (ptr+size)) | ||
149 | return 0; | ||
150 | |||
151 | return 1; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * s3c_pm_runcheck() - helper to check a resource on restore. | ||
156 | * @res: The resource to check | ||
157 | * @vak: Pointer to list of CRC32 values to check. | ||
158 | * | ||
159 | * Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this | ||
160 | * function runs the given memory resource checking it against the stored | ||
161 | * CRC to ensure that memory is restored. The function tries to skip as | ||
162 | * many of the areas used during the suspend process. | ||
163 | */ | ||
164 | static u32 *s3c_pm_runcheck(struct resource *res, u32 *val) | ||
165 | { | ||
166 | void *save_at = phys_to_virt(s3c_sleep_save_phys); | ||
167 | unsigned long addr; | ||
168 | unsigned long left; | ||
169 | void *stkpage; | ||
170 | void *ptr; | ||
171 | u32 calc; | ||
172 | |||
173 | stkpage = (void *)((u32)&calc & ~PAGE_MASK); | ||
174 | |||
175 | for (addr = res->start; addr < res->end; | ||
176 | addr += CHECK_CHUNKSIZE) { | ||
177 | left = res->end - addr; | ||
178 | |||
179 | if (left > CHECK_CHUNKSIZE) | ||
180 | left = CHECK_CHUNKSIZE; | ||
181 | |||
182 | ptr = phys_to_virt(addr); | ||
183 | |||
184 | if (in_region(ptr, left, stkpage, 4096)) { | ||
185 | S3C_PMDBG("skipping %08lx, has stack in\n", addr); | ||
186 | goto skip_check; | ||
187 | } | ||
188 | |||
189 | if (in_region(ptr, left, crcs, crc_size)) { | ||
190 | S3C_PMDBG("skipping %08lx, has crc block in\n", addr); | ||
191 | goto skip_check; | ||
192 | } | ||
193 | |||
194 | if (in_region(ptr, left, save_at, 32*4 )) { | ||
195 | S3C_PMDBG("skipping %08lx, has save block in\n", addr); | ||
196 | goto skip_check; | ||
197 | } | ||
198 | |||
199 | /* calculate and check the checksum */ | ||
200 | |||
201 | calc = crc32_le(~0, ptr, left); | ||
202 | if (calc != *val) { | ||
203 | printk(KERN_ERR "Restore CRC error at " | ||
204 | "%08lx (%08x vs %08x)\n", addr, calc, *val); | ||
205 | |||
206 | S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n", | ||
207 | addr, calc, *val); | ||
208 | } | ||
209 | |||
210 | skip_check: | ||
211 | val++; | ||
212 | } | ||
213 | |||
214 | return val; | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * s3c_pm_check_restore() - memory check called on resume | ||
219 | * | ||
220 | * check the CRCs after the restore event and free the memory used | ||
221 | * to hold them | ||
222 | */ | ||
223 | void s3c_pm_check_restore(void) | ||
224 | { | ||
225 | if (crcs != NULL) | ||
226 | s3c_pm_run_sysram(s3c_pm_runcheck, crcs); | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * s3c_pm_check_cleanup() - free memory resources | ||
231 | * | ||
232 | * Free the resources that where allocated by the suspend | ||
233 | * memory check code. We do this separately from the | ||
234 | * s3c_pm_check_restore() function as we cannot call any | ||
235 | * functions that might sleep during that resume. | ||
236 | */ | ||
237 | void s3c_pm_check_cleanup(void) | ||
238 | { | ||
239 | kfree(crcs); | ||
240 | crcs = NULL; | ||
241 | } | ||
242 | |||
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c new file mode 100644 index 000000000000..69a4c7f02e25 --- /dev/null +++ b/arch/arm/plat-samsung/pm-gpio.c | |||
@@ -0,0 +1,380 @@ | |||
1 | |||
2 | /* linux/arch/arm/plat-s3c/pm-gpio.c | ||
3 | * | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * S3C series GPIO PM code | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/sysdev.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/gpio.h> | ||
21 | |||
22 | #include <plat/gpio-core.h> | ||
23 | #include <plat/pm.h> | ||
24 | |||
25 | /* PM GPIO helpers */ | ||
26 | |||
27 | #define OFFS_CON (0x00) | ||
28 | #define OFFS_DAT (0x04) | ||
29 | #define OFFS_UP (0x08) | ||
30 | |||
31 | static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip) | ||
32 | { | ||
33 | chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON); | ||
34 | chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT); | ||
35 | } | ||
36 | |||
37 | static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip) | ||
38 | { | ||
39 | void __iomem *base = chip->base; | ||
40 | u32 old_gpcon = __raw_readl(base + OFFS_CON); | ||
41 | u32 old_gpdat = __raw_readl(base + OFFS_DAT); | ||
42 | u32 gps_gpcon = chip->pm_save[0]; | ||
43 | u32 gps_gpdat = chip->pm_save[1]; | ||
44 | u32 gpcon; | ||
45 | |||
46 | /* GPACON only has one bit per control / data and no PULLUPs. | ||
47 | * GPACON[x] = 0 => Output, 1 => SFN */ | ||
48 | |||
49 | /* first set all SFN bits to SFN */ | ||
50 | |||
51 | gpcon = old_gpcon | gps_gpcon; | ||
52 | __raw_writel(gpcon, base + OFFS_CON); | ||
53 | |||
54 | /* now set all the other bits */ | ||
55 | |||
56 | __raw_writel(gps_gpdat, base + OFFS_DAT); | ||
57 | __raw_writel(gps_gpcon, base + OFFS_CON); | ||
58 | |||
59 | S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n", | ||
60 | chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat); | ||
61 | } | ||
62 | |||
63 | struct s3c_gpio_pm s3c_gpio_pm_1bit = { | ||
64 | .save = s3c_gpio_pm_1bit_save, | ||
65 | .resume = s3c_gpio_pm_1bit_resume, | ||
66 | }; | ||
67 | |||
68 | static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip) | ||
69 | { | ||
70 | chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON); | ||
71 | chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT); | ||
72 | chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP); | ||
73 | } | ||
74 | |||
75 | /* Test whether the given masked+shifted bits of an GPIO configuration | ||
76 | * are one of the SFN (special function) modes. */ | ||
77 | |||
78 | static inline int is_sfn(unsigned long con) | ||
79 | { | ||
80 | return con >= 2; | ||
81 | } | ||
82 | |||
83 | /* Test if the given masked+shifted GPIO configuration is an input */ | ||
84 | |||
85 | static inline int is_in(unsigned long con) | ||
86 | { | ||
87 | return con == 0; | ||
88 | } | ||
89 | |||
90 | /* Test if the given masked+shifted GPIO configuration is an output */ | ||
91 | |||
92 | static inline int is_out(unsigned long con) | ||
93 | { | ||
94 | return con == 1; | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank | ||
99 | * @chip: The chip information to resume. | ||
100 | * | ||
101 | * Restore one of the GPIO banks that was saved during suspend. This is | ||
102 | * not as simple as once thought, due to the possibility of glitches | ||
103 | * from the order that the CON and DAT registers are set in. | ||
104 | * | ||
105 | * The three states the pin can be are {IN,OUT,SFN} which gives us 9 | ||
106 | * combinations of changes to check. Three of these, if the pin stays | ||
107 | * in the same configuration can be discounted. This leaves us with | ||
108 | * the following: | ||
109 | * | ||
110 | * { IN => OUT } Change DAT first | ||
111 | * { IN => SFN } Change CON first | ||
112 | * { OUT => SFN } Change CON first, so new data will not glitch | ||
113 | * { OUT => IN } Change CON first, so new data will not glitch | ||
114 | * { SFN => IN } Change CON first | ||
115 | * { SFN => OUT } Change DAT first, so new data will not glitch [1] | ||
116 | * | ||
117 | * We do not currently deal with the UP registers as these control | ||
118 | * weak resistors, so a small delay in change should not need to bring | ||
119 | * these into the calculations. | ||
120 | * | ||
121 | * [1] this assumes that writing to a pin DAT whilst in SFN will set the | ||
122 | * state for when it is next output. | ||
123 | */ | ||
124 | static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip) | ||
125 | { | ||
126 | void __iomem *base = chip->base; | ||
127 | u32 old_gpcon = __raw_readl(base + OFFS_CON); | ||
128 | u32 old_gpdat = __raw_readl(base + OFFS_DAT); | ||
129 | u32 gps_gpcon = chip->pm_save[0]; | ||
130 | u32 gps_gpdat = chip->pm_save[1]; | ||
131 | u32 gpcon, old, new, mask; | ||
132 | u32 change_mask = 0x0; | ||
133 | int nr; | ||
134 | |||
135 | /* restore GPIO pull-up settings */ | ||
136 | __raw_writel(chip->pm_save[2], base + OFFS_UP); | ||
137 | |||
138 | /* Create a change_mask of all the items that need to have | ||
139 | * their CON value changed before their DAT value, so that | ||
140 | * we minimise the work between the two settings. | ||
141 | */ | ||
142 | |||
143 | for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) { | ||
144 | old = (old_gpcon & mask) >> nr; | ||
145 | new = (gps_gpcon & mask) >> nr; | ||
146 | |||
147 | /* If there is no change, then skip */ | ||
148 | |||
149 | if (old == new) | ||
150 | continue; | ||
151 | |||
152 | /* If both are special function, then skip */ | ||
153 | |||
154 | if (is_sfn(old) && is_sfn(new)) | ||
155 | continue; | ||
156 | |||
157 | /* Change is IN => OUT, do not change now */ | ||
158 | |||
159 | if (is_in(old) && is_out(new)) | ||
160 | continue; | ||
161 | |||
162 | /* Change is SFN => OUT, do not change now */ | ||
163 | |||
164 | if (is_sfn(old) && is_out(new)) | ||
165 | continue; | ||
166 | |||
167 | /* We should now be at the case of IN=>SFN, | ||
168 | * OUT=>SFN, OUT=>IN, SFN=>IN. */ | ||
169 | |||
170 | change_mask |= mask; | ||
171 | } | ||
172 | |||
173 | |||
174 | /* Write the new CON settings */ | ||
175 | |||
176 | gpcon = old_gpcon & ~change_mask; | ||
177 | gpcon |= gps_gpcon & change_mask; | ||
178 | |||
179 | __raw_writel(gpcon, base + OFFS_CON); | ||
180 | |||
181 | /* Now change any items that require DAT,CON */ | ||
182 | |||
183 | __raw_writel(gps_gpdat, base + OFFS_DAT); | ||
184 | __raw_writel(gps_gpcon, base + OFFS_CON); | ||
185 | |||
186 | S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n", | ||
187 | chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat); | ||
188 | } | ||
189 | |||
190 | struct s3c_gpio_pm s3c_gpio_pm_2bit = { | ||
191 | .save = s3c_gpio_pm_2bit_save, | ||
192 | .resume = s3c_gpio_pm_2bit_resume, | ||
193 | }; | ||
194 | |||
195 | #ifdef CONFIG_ARCH_S3C64XX | ||
196 | static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip) | ||
197 | { | ||
198 | chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON); | ||
199 | chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT); | ||
200 | chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP); | ||
201 | |||
202 | if (chip->chip.ngpio > 8) | ||
203 | chip->pm_save[0] = __raw_readl(chip->base - 4); | ||
204 | } | ||
205 | |||
206 | static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon) | ||
207 | { | ||
208 | u32 old, new, mask; | ||
209 | u32 change_mask = 0x0; | ||
210 | int nr; | ||
211 | |||
212 | for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) { | ||
213 | old = (old_gpcon & mask) >> nr; | ||
214 | new = (gps_gpcon & mask) >> nr; | ||
215 | |||
216 | /* If there is no change, then skip */ | ||
217 | |||
218 | if (old == new) | ||
219 | continue; | ||
220 | |||
221 | /* If both are special function, then skip */ | ||
222 | |||
223 | if (is_sfn(old) && is_sfn(new)) | ||
224 | continue; | ||
225 | |||
226 | /* Change is IN => OUT, do not change now */ | ||
227 | |||
228 | if (is_in(old) && is_out(new)) | ||
229 | continue; | ||
230 | |||
231 | /* Change is SFN => OUT, do not change now */ | ||
232 | |||
233 | if (is_sfn(old) && is_out(new)) | ||
234 | continue; | ||
235 | |||
236 | /* We should now be at the case of IN=>SFN, | ||
237 | * OUT=>SFN, OUT=>IN, SFN=>IN. */ | ||
238 | |||
239 | change_mask |= mask; | ||
240 | } | ||
241 | |||
242 | return change_mask; | ||
243 | } | ||
244 | |||
245 | static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index) | ||
246 | { | ||
247 | void __iomem *con = chip->base + (index * 4); | ||
248 | u32 old_gpcon = __raw_readl(con); | ||
249 | u32 gps_gpcon = chip->pm_save[index + 1]; | ||
250 | u32 gpcon, mask; | ||
251 | |||
252 | mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon); | ||
253 | |||
254 | gpcon = old_gpcon & ~mask; | ||
255 | gpcon |= gps_gpcon & mask; | ||
256 | |||
257 | __raw_writel(gpcon, con); | ||
258 | } | ||
259 | |||
260 | static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip) | ||
261 | { | ||
262 | void __iomem *base = chip->base; | ||
263 | u32 old_gpcon[2]; | ||
264 | u32 old_gpdat = __raw_readl(base + OFFS_DAT); | ||
265 | u32 gps_gpdat = chip->pm_save[2]; | ||
266 | |||
267 | /* First, modify the CON settings */ | ||
268 | |||
269 | old_gpcon[0] = 0; | ||
270 | old_gpcon[1] = __raw_readl(base + OFFS_CON); | ||
271 | |||
272 | s3c_gpio_pm_4bit_con(chip, 0); | ||
273 | if (chip->chip.ngpio > 8) { | ||
274 | old_gpcon[0] = __raw_readl(base - 4); | ||
275 | s3c_gpio_pm_4bit_con(chip, -1); | ||
276 | } | ||
277 | |||
278 | /* Now change the configurations that require DAT,CON */ | ||
279 | |||
280 | __raw_writel(chip->pm_save[2], base + OFFS_DAT); | ||
281 | __raw_writel(chip->pm_save[1], base + OFFS_CON); | ||
282 | if (chip->chip.ngpio > 8) | ||
283 | __raw_writel(chip->pm_save[0], base - 4); | ||
284 | |||
285 | __raw_writel(chip->pm_save[2], base + OFFS_DAT); | ||
286 | __raw_writel(chip->pm_save[3], base + OFFS_UP); | ||
287 | |||
288 | if (chip->chip.ngpio > 8) { | ||
289 | S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n", | ||
290 | chip->chip.label, old_gpcon[0], old_gpcon[1], | ||
291 | __raw_readl(base - 4), | ||
292 | __raw_readl(base + OFFS_CON), | ||
293 | old_gpdat, gps_gpdat); | ||
294 | } else | ||
295 | S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n", | ||
296 | chip->chip.label, old_gpcon[1], | ||
297 | __raw_readl(base + OFFS_CON), | ||
298 | old_gpdat, gps_gpdat); | ||
299 | } | ||
300 | |||
301 | struct s3c_gpio_pm s3c_gpio_pm_4bit = { | ||
302 | .save = s3c_gpio_pm_4bit_save, | ||
303 | .resume = s3c_gpio_pm_4bit_resume, | ||
304 | }; | ||
305 | #endif /* CONFIG_ARCH_S3C64XX */ | ||
306 | |||
307 | /** | ||
308 | * s3c_pm_save_gpio() - save gpio chip data for suspend | ||
309 | * @ourchip: The chip for suspend. | ||
310 | */ | ||
311 | static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip) | ||
312 | { | ||
313 | struct s3c_gpio_pm *pm = ourchip->pm; | ||
314 | |||
315 | if (pm == NULL || pm->save == NULL) | ||
316 | S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label); | ||
317 | else | ||
318 | pm->save(ourchip); | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * s3c_pm_save_gpios() - Save the state of the GPIO banks. | ||
323 | * | ||
324 | * For all the GPIO banks, save the state of each one ready for going | ||
325 | * into a suspend mode. | ||
326 | */ | ||
327 | void s3c_pm_save_gpios(void) | ||
328 | { | ||
329 | struct s3c_gpio_chip *ourchip; | ||
330 | unsigned int gpio_nr; | ||
331 | |||
332 | for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { | ||
333 | ourchip = s3c_gpiolib_getchip(gpio_nr); | ||
334 | if (!ourchip) | ||
335 | continue; | ||
336 | |||
337 | s3c_pm_save_gpio(ourchip); | ||
338 | |||
339 | S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n", | ||
340 | ourchip->chip.label, | ||
341 | ourchip->pm_save[0], | ||
342 | ourchip->pm_save[1], | ||
343 | ourchip->pm_save[2], | ||
344 | ourchip->pm_save[3]); | ||
345 | |||
346 | gpio_nr += ourchip->chip.ngpio; | ||
347 | gpio_nr += CONFIG_S3C_GPIO_SPACE; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * s3c_pm_resume_gpio() - restore gpio chip data after suspend | ||
353 | * @ourchip: The suspended chip. | ||
354 | */ | ||
355 | static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip) | ||
356 | { | ||
357 | struct s3c_gpio_pm *pm = ourchip->pm; | ||
358 | |||
359 | if (pm == NULL || pm->resume == NULL) | ||
360 | S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label); | ||
361 | else | ||
362 | pm->resume(ourchip); | ||
363 | } | ||
364 | |||
365 | void s3c_pm_restore_gpios(void) | ||
366 | { | ||
367 | struct s3c_gpio_chip *ourchip; | ||
368 | unsigned int gpio_nr; | ||
369 | |||
370 | for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { | ||
371 | ourchip = s3c_gpiolib_getchip(gpio_nr); | ||
372 | if (!ourchip) | ||
373 | continue; | ||
374 | |||
375 | s3c_pm_resume_gpio(ourchip); | ||
376 | |||
377 | gpio_nr += ourchip->chip.ngpio; | ||
378 | gpio_nr += CONFIG_S3C_GPIO_SPACE; | ||
379 | } | ||
380 | } | ||
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c new file mode 100644 index 000000000000..27cfca597699 --- /dev/null +++ b/arch/arm/plat-samsung/pm.c | |||
@@ -0,0 +1,378 @@ | |||
1 | /* linux/arch/arm/plat-s3c/pm.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2004-2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * S3C common power management (suspend to ram) support. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/suspend.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/serial_core.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <asm/cacheflush.h> | ||
23 | #include <mach/hardware.h> | ||
24 | #include <mach/map.h> | ||
25 | |||
26 | #include <plat/regs-serial.h> | ||
27 | #include <mach/regs-clock.h> | ||
28 | #include <mach/regs-irq.h> | ||
29 | #include <asm/irq.h> | ||
30 | |||
31 | #include <plat/pm.h> | ||
32 | #include <mach/pm-core.h> | ||
33 | |||
34 | /* for external use */ | ||
35 | |||
36 | unsigned long s3c_pm_flags; | ||
37 | |||
38 | /* Debug code: | ||
39 | * | ||
40 | * This code supports debug output to the low level UARTs for use on | ||
41 | * resume before the console layer is available. | ||
42 | */ | ||
43 | |||
44 | #ifdef CONFIG_SAMSUNG_PM_DEBUG | ||
45 | extern void printascii(const char *); | ||
46 | |||
47 | void s3c_pm_dbg(const char *fmt, ...) | ||
48 | { | ||
49 | va_list va; | ||
50 | char buff[256]; | ||
51 | |||
52 | va_start(va, fmt); | ||
53 | vsprintf(buff, fmt, va); | ||
54 | va_end(va); | ||
55 | |||
56 | printascii(buff); | ||
57 | } | ||
58 | |||
59 | static inline void s3c_pm_debug_init(void) | ||
60 | { | ||
61 | /* restart uart clocks so we can use them to output */ | ||
62 | s3c_pm_debug_init_uart(); | ||
63 | } | ||
64 | |||
65 | #else | ||
66 | #define s3c_pm_debug_init() do { } while(0) | ||
67 | |||
68 | #endif /* CONFIG_SAMSUNG_PM_DEBUG */ | ||
69 | |||
70 | /* Save the UART configurations if we are configured for debug. */ | ||
71 | |||
72 | unsigned char pm_uart_udivslot; | ||
73 | |||
74 | #ifdef CONFIG_SAMSUNG_PM_DEBUG | ||
75 | |||
76 | struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS]; | ||
77 | |||
78 | static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save) | ||
79 | { | ||
80 | void __iomem *regs = S3C_VA_UARTx(uart); | ||
81 | |||
82 | save->ulcon = __raw_readl(regs + S3C2410_ULCON); | ||
83 | save->ucon = __raw_readl(regs + S3C2410_UCON); | ||
84 | save->ufcon = __raw_readl(regs + S3C2410_UFCON); | ||
85 | save->umcon = __raw_readl(regs + S3C2410_UMCON); | ||
86 | save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV); | ||
87 | |||
88 | if (pm_uart_udivslot) | ||
89 | save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT); | ||
90 | |||
91 | S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n", | ||
92 | uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv); | ||
93 | } | ||
94 | |||
95 | static void s3c_pm_save_uarts(void) | ||
96 | { | ||
97 | struct pm_uart_save *save = uart_save; | ||
98 | unsigned int uart; | ||
99 | |||
100 | for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++) | ||
101 | s3c_pm_save_uart(uart, save); | ||
102 | } | ||
103 | |||
104 | static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save) | ||
105 | { | ||
106 | void __iomem *regs = S3C_VA_UARTx(uart); | ||
107 | |||
108 | s3c_pm_arch_update_uart(regs, save); | ||
109 | |||
110 | __raw_writel(save->ulcon, regs + S3C2410_ULCON); | ||
111 | __raw_writel(save->ucon, regs + S3C2410_UCON); | ||
112 | __raw_writel(save->ufcon, regs + S3C2410_UFCON); | ||
113 | __raw_writel(save->umcon, regs + S3C2410_UMCON); | ||
114 | __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV); | ||
115 | |||
116 | if (pm_uart_udivslot) | ||
117 | __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT); | ||
118 | } | ||
119 | |||
120 | static void s3c_pm_restore_uarts(void) | ||
121 | { | ||
122 | struct pm_uart_save *save = uart_save; | ||
123 | unsigned int uart; | ||
124 | |||
125 | for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++) | ||
126 | s3c_pm_restore_uart(uart, save); | ||
127 | } | ||
128 | #else | ||
129 | static void s3c_pm_save_uarts(void) { } | ||
130 | static void s3c_pm_restore_uarts(void) { } | ||
131 | #endif | ||
132 | |||
133 | /* The IRQ ext-int code goes here, it is too small to currently bother | ||
134 | * with its own file. */ | ||
135 | |||
136 | unsigned long s3c_irqwake_intmask = 0xffffffffL; | ||
137 | unsigned long s3c_irqwake_eintmask = 0xffffffffL; | ||
138 | |||
139 | int s3c_irqext_wake(unsigned int irqno, unsigned int state) | ||
140 | { | ||
141 | unsigned long bit = 1L << IRQ_EINT_BIT(irqno); | ||
142 | |||
143 | if (!(s3c_irqwake_eintallow & bit)) | ||
144 | return -ENOENT; | ||
145 | |||
146 | printk(KERN_INFO "wake %s for irq %d\n", | ||
147 | state ? "enabled" : "disabled", irqno); | ||
148 | |||
149 | if (!state) | ||
150 | s3c_irqwake_eintmask |= bit; | ||
151 | else | ||
152 | s3c_irqwake_eintmask &= ~bit; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /* helper functions to save and restore register state */ | ||
158 | |||
159 | /** | ||
160 | * s3c_pm_do_save() - save a set of registers for restoration on resume. | ||
161 | * @ptr: Pointer to an array of registers. | ||
162 | * @count: Size of the ptr array. | ||
163 | * | ||
164 | * Run through the list of registers given, saving their contents in the | ||
165 | * array for later restoration when we wakeup. | ||
166 | */ | ||
167 | void s3c_pm_do_save(struct sleep_save *ptr, int count) | ||
168 | { | ||
169 | for (; count > 0; count--, ptr++) { | ||
170 | ptr->val = __raw_readl(ptr->reg); | ||
171 | S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * s3c_pm_do_restore() - restore register values from the save list. | ||
177 | * @ptr: Pointer to an array of registers. | ||
178 | * @count: Size of the ptr array. | ||
179 | * | ||
180 | * Restore the register values saved from s3c_pm_do_save(). | ||
181 | * | ||
182 | * Note, we do not use S3C_PMDBG() in here, as the system may not have | ||
183 | * restore the UARTs state yet | ||
184 | */ | ||
185 | |||
186 | void s3c_pm_do_restore(struct sleep_save *ptr, int count) | ||
187 | { | ||
188 | for (; count > 0; count--, ptr++) { | ||
189 | printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n", | ||
190 | ptr->reg, ptr->val, __raw_readl(ptr->reg)); | ||
191 | |||
192 | __raw_writel(ptr->val, ptr->reg); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * s3c_pm_do_restore_core() - early restore register values from save list. | ||
198 | * | ||
199 | * This is similar to s3c_pm_do_restore() except we try and minimise the | ||
200 | * side effects of the function in case registers that hardware might need | ||
201 | * to work has been restored. | ||
202 | * | ||
203 | * WARNING: Do not put any debug in here that may effect memory or use | ||
204 | * peripherals, as things may be changing! | ||
205 | */ | ||
206 | |||
207 | void s3c_pm_do_restore_core(struct sleep_save *ptr, int count) | ||
208 | { | ||
209 | for (; count > 0; count--, ptr++) | ||
210 | __raw_writel(ptr->val, ptr->reg); | ||
211 | } | ||
212 | |||
213 | /* s3c2410_pm_show_resume_irqs | ||
214 | * | ||
215 | * print any IRQs asserted at resume time (ie, we woke from) | ||
216 | */ | ||
217 | static void s3c_pm_show_resume_irqs(int start, unsigned long which, | ||
218 | unsigned long mask) | ||
219 | { | ||
220 | int i; | ||
221 | |||
222 | which &= ~mask; | ||
223 | |||
224 | for (i = 0; i <= 31; i++) { | ||
225 | if (which & (1L<<i)) { | ||
226 | S3C_PMDBG("IRQ %d asserted at resume\n", start+i); | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | |||
231 | |||
232 | void (*pm_cpu_prep)(void); | ||
233 | void (*pm_cpu_sleep)(void); | ||
234 | |||
235 | #define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) | ||
236 | |||
237 | /* s3c_pm_enter | ||
238 | * | ||
239 | * central control for sleep/resume process | ||
240 | */ | ||
241 | |||
242 | static int s3c_pm_enter(suspend_state_t state) | ||
243 | { | ||
244 | static unsigned long regs_save[16]; | ||
245 | |||
246 | /* ensure the debug is initialised (if enabled) */ | ||
247 | |||
248 | s3c_pm_debug_init(); | ||
249 | |||
250 | S3C_PMDBG("%s(%d)\n", __func__, state); | ||
251 | |||
252 | if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { | ||
253 | printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | /* check if we have anything to wake-up with... bad things seem | ||
258 | * to happen if you suspend with no wakeup (system will often | ||
259 | * require a full power-cycle) | ||
260 | */ | ||
261 | |||
262 | if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) && | ||
263 | !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) { | ||
264 | printk(KERN_ERR "%s: No wake-up sources!\n", __func__); | ||
265 | printk(KERN_ERR "%s: Aborting sleep\n", __func__); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | /* store the physical address of the register recovery block */ | ||
270 | |||
271 | s3c_sleep_save_phys = virt_to_phys(regs_save); | ||
272 | |||
273 | S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); | ||
274 | |||
275 | /* save all necessary core registers not covered by the drivers */ | ||
276 | |||
277 | s3c_pm_save_gpios(); | ||
278 | s3c_pm_save_uarts(); | ||
279 | s3c_pm_save_core(); | ||
280 | |||
281 | /* set the irq configuration for wake */ | ||
282 | |||
283 | s3c_pm_configure_extint(); | ||
284 | |||
285 | S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n", | ||
286 | s3c_irqwake_intmask, s3c_irqwake_eintmask); | ||
287 | |||
288 | s3c_pm_arch_prepare_irqs(); | ||
289 | |||
290 | /* call cpu specific preparation */ | ||
291 | |||
292 | pm_cpu_prep(); | ||
293 | |||
294 | /* flush cache back to ram */ | ||
295 | |||
296 | flush_cache_all(); | ||
297 | |||
298 | s3c_pm_check_store(); | ||
299 | |||
300 | /* send the cpu to sleep... */ | ||
301 | |||
302 | s3c_pm_arch_stop_clocks(); | ||
303 | |||
304 | /* s3c_cpu_save will also act as our return point from when | ||
305 | * we resume as it saves its own register state and restores it | ||
306 | * during the resume. */ | ||
307 | |||
308 | s3c_cpu_save(regs_save); | ||
309 | |||
310 | /* restore the cpu state using the kernel's cpu init code. */ | ||
311 | |||
312 | cpu_init(); | ||
313 | |||
314 | /* restore the system state */ | ||
315 | |||
316 | s3c_pm_restore_core(); | ||
317 | s3c_pm_restore_uarts(); | ||
318 | s3c_pm_restore_gpios(); | ||
319 | |||
320 | s3c_pm_debug_init(); | ||
321 | |||
322 | /* check what irq (if any) restored the system */ | ||
323 | |||
324 | s3c_pm_arch_show_resume_irqs(); | ||
325 | |||
326 | S3C_PMDBG("%s: post sleep, preparing to return\n", __func__); | ||
327 | |||
328 | /* LEDs should now be 1110 */ | ||
329 | s3c_pm_debug_smdkled(1 << 1, 0); | ||
330 | |||
331 | s3c_pm_check_restore(); | ||
332 | |||
333 | /* ok, let's return from sleep */ | ||
334 | |||
335 | S3C_PMDBG("S3C PM Resume (post-restore)\n"); | ||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | /* callback from assembly code */ | ||
340 | void s3c_pm_cb_flushcache(void) | ||
341 | { | ||
342 | flush_cache_all(); | ||
343 | } | ||
344 | |||
345 | static int s3c_pm_prepare(void) | ||
346 | { | ||
347 | /* prepare check area if configured */ | ||
348 | |||
349 | s3c_pm_check_prepare(); | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static void s3c_pm_finish(void) | ||
354 | { | ||
355 | s3c_pm_check_cleanup(); | ||
356 | } | ||
357 | |||
358 | static struct platform_suspend_ops s3c_pm_ops = { | ||
359 | .enter = s3c_pm_enter, | ||
360 | .prepare = s3c_pm_prepare, | ||
361 | .finish = s3c_pm_finish, | ||
362 | .valid = suspend_valid_only_mem, | ||
363 | }; | ||
364 | |||
365 | /* s3c_pm_init | ||
366 | * | ||
367 | * Attach the power management functions. This should be called | ||
368 | * from the board specific initialisation if the board supports | ||
369 | * it. | ||
370 | */ | ||
371 | |||
372 | int __init s3c_pm_init(void) | ||
373 | { | ||
374 | printk("S3C Power Management, Copyright 2004 Simtec Electronics\n"); | ||
375 | |||
376 | suspend_set_ops(&s3c_pm_ops); | ||
377 | return 0; | ||
378 | } | ||
diff --git a/arch/arm/plat-samsung/pwm-clock.c b/arch/arm/plat-samsung/pwm-clock.c new file mode 100644 index 000000000000..46c9381e083b --- /dev/null +++ b/arch/arm/plat-samsung/pwm-clock.c | |||
@@ -0,0 +1,455 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/pwm-clock.c | ||
2 | * | ||
3 | * Copyright (c) 2007 Simtec Electronics | ||
4 | * Copyright (c) 2007, 2008 Ben Dooks | ||
5 | * Ben Dooks <ben-linux@fluff.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/log2.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <mach/hardware.h> | ||
23 | #include <mach/map.h> | ||
24 | #include <asm/irq.h> | ||
25 | |||
26 | #include <plat/clock.h> | ||
27 | #include <plat/cpu.h> | ||
28 | |||
29 | #include <plat/regs-timer.h> | ||
30 | #include <mach/pwm-clock.h> | ||
31 | |||
32 | /* Each of the timers 0 through 5 go through the following | ||
33 | * clock tree, with the inputs depending on the timers. | ||
34 | * | ||
35 | * pclk ---- [ prescaler 0 ] -+---> timer 0 | ||
36 | * +---> timer 1 | ||
37 | * | ||
38 | * pclk ---- [ prescaler 1 ] -+---> timer 2 | ||
39 | * +---> timer 3 | ||
40 | * \---> timer 4 | ||
41 | * | ||
42 | * Which are fed into the timers as so: | ||
43 | * | ||
44 | * prescaled 0 ---- [ div 2,4,8,16 ] ---\ | ||
45 | * [mux] -> timer 0 | ||
46 | * tclk 0 ------------------------------/ | ||
47 | * | ||
48 | * prescaled 0 ---- [ div 2,4,8,16 ] ---\ | ||
49 | * [mux] -> timer 1 | ||
50 | * tclk 0 ------------------------------/ | ||
51 | * | ||
52 | * | ||
53 | * prescaled 1 ---- [ div 2,4,8,16 ] ---\ | ||
54 | * [mux] -> timer 2 | ||
55 | * tclk 1 ------------------------------/ | ||
56 | * | ||
57 | * prescaled 1 ---- [ div 2,4,8,16 ] ---\ | ||
58 | * [mux] -> timer 3 | ||
59 | * tclk 1 ------------------------------/ | ||
60 | * | ||
61 | * prescaled 1 ---- [ div 2,4,8, 16 ] --\ | ||
62 | * [mux] -> timer 4 | ||
63 | * tclk 1 ------------------------------/ | ||
64 | * | ||
65 | * Since the mux and the divider are tied together in the | ||
66 | * same register space, it is impossible to set the parent | ||
67 | * and the rate at the same time. To avoid this, we add an | ||
68 | * intermediate 'prescaled-and-divided' clock to select | ||
69 | * as the parent for the timer input clock called tdiv. | ||
70 | * | ||
71 | * prescaled clk --> pwm-tdiv ---\ | ||
72 | * [ mux ] --> timer X | ||
73 | * tclk -------------------------/ | ||
74 | */ | ||
75 | |||
76 | static struct clk clk_timer_scaler[]; | ||
77 | |||
78 | static unsigned long clk_pwm_scaler_get_rate(struct clk *clk) | ||
79 | { | ||
80 | unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
81 | |||
82 | if (clk == &clk_timer_scaler[1]) { | ||
83 | tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK; | ||
84 | tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT; | ||
85 | } else { | ||
86 | tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK; | ||
87 | } | ||
88 | |||
89 | return clk_get_rate(clk->parent) / (tcfg0 + 1); | ||
90 | } | ||
91 | |||
92 | static unsigned long clk_pwm_scaler_round_rate(struct clk *clk, | ||
93 | unsigned long rate) | ||
94 | { | ||
95 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
96 | unsigned long divisor = parent_rate / rate; | ||
97 | |||
98 | if (divisor > 256) | ||
99 | divisor = 256; | ||
100 | else if (divisor < 2) | ||
101 | divisor = 2; | ||
102 | |||
103 | return parent_rate / divisor; | ||
104 | } | ||
105 | |||
106 | static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate) | ||
107 | { | ||
108 | unsigned long round = clk_pwm_scaler_round_rate(clk, rate); | ||
109 | unsigned long tcfg0; | ||
110 | unsigned long divisor; | ||
111 | unsigned long flags; | ||
112 | |||
113 | divisor = clk_get_rate(clk->parent) / round; | ||
114 | divisor--; | ||
115 | |||
116 | local_irq_save(flags); | ||
117 | tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
118 | |||
119 | if (clk == &clk_timer_scaler[1]) { | ||
120 | tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; | ||
121 | tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT; | ||
122 | } else { | ||
123 | tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; | ||
124 | tcfg0 |= divisor; | ||
125 | } | ||
126 | |||
127 | __raw_writel(tcfg0, S3C2410_TCFG0); | ||
128 | local_irq_restore(flags); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct clk_ops clk_pwm_scaler_ops = { | ||
134 | .get_rate = clk_pwm_scaler_get_rate, | ||
135 | .set_rate = clk_pwm_scaler_set_rate, | ||
136 | .round_rate = clk_pwm_scaler_round_rate, | ||
137 | }; | ||
138 | |||
139 | static struct clk clk_timer_scaler[] = { | ||
140 | [0] = { | ||
141 | .name = "pwm-scaler0", | ||
142 | .id = -1, | ||
143 | .ops = &clk_pwm_scaler_ops, | ||
144 | }, | ||
145 | [1] = { | ||
146 | .name = "pwm-scaler1", | ||
147 | .id = -1, | ||
148 | .ops = &clk_pwm_scaler_ops, | ||
149 | }, | ||
150 | }; | ||
151 | |||
152 | static struct clk clk_timer_tclk[] = { | ||
153 | [0] = { | ||
154 | .name = "pwm-tclk0", | ||
155 | .id = -1, | ||
156 | }, | ||
157 | [1] = { | ||
158 | .name = "pwm-tclk1", | ||
159 | .id = -1, | ||
160 | }, | ||
161 | }; | ||
162 | |||
163 | struct pwm_tdiv_clk { | ||
164 | struct clk clk; | ||
165 | unsigned int divisor; | ||
166 | }; | ||
167 | |||
168 | static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk) | ||
169 | { | ||
170 | return container_of(clk, struct pwm_tdiv_clk, clk); | ||
171 | } | ||
172 | |||
173 | static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) | ||
174 | { | ||
175 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
176 | unsigned int divisor; | ||
177 | |||
178 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | ||
179 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
180 | |||
181 | if (pwm_cfg_src_is_tclk(tcfg1)) | ||
182 | divisor = to_tdiv(clk)->divisor; | ||
183 | else | ||
184 | divisor = tcfg_to_divisor(tcfg1); | ||
185 | |||
186 | return clk_get_rate(clk->parent) / divisor; | ||
187 | } | ||
188 | |||
189 | static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, | ||
190 | unsigned long rate) | ||
191 | { | ||
192 | unsigned long parent_rate; | ||
193 | unsigned long divisor; | ||
194 | |||
195 | parent_rate = clk_get_rate(clk->parent); | ||
196 | divisor = parent_rate / rate; | ||
197 | |||
198 | if (divisor <= 1 && pwm_tdiv_has_div1()) | ||
199 | divisor = 1; | ||
200 | else if (divisor <= 2) | ||
201 | divisor = 2; | ||
202 | else if (divisor <= 4) | ||
203 | divisor = 4; | ||
204 | else if (divisor <= 8) | ||
205 | divisor = 8; | ||
206 | else | ||
207 | divisor = 16; | ||
208 | |||
209 | return parent_rate / divisor; | ||
210 | } | ||
211 | |||
212 | static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) | ||
213 | { | ||
214 | return pwm_tdiv_div_bits(divclk->divisor); | ||
215 | } | ||
216 | |||
217 | static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) | ||
218 | { | ||
219 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
220 | unsigned long bits = clk_pwm_tdiv_bits(divclk); | ||
221 | unsigned long flags; | ||
222 | unsigned long shift = S3C2410_TCFG1_SHIFT(divclk->clk.id); | ||
223 | |||
224 | local_irq_save(flags); | ||
225 | |||
226 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
227 | tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift); | ||
228 | tcfg1 |= bits << shift; | ||
229 | __raw_writel(tcfg1, S3C2410_TCFG1); | ||
230 | |||
231 | local_irq_restore(flags); | ||
232 | } | ||
233 | |||
234 | static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate) | ||
235 | { | ||
236 | struct pwm_tdiv_clk *divclk = to_tdiv(clk); | ||
237 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
238 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
239 | unsigned long divisor; | ||
240 | |||
241 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | ||
242 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
243 | |||
244 | rate = clk_round_rate(clk, rate); | ||
245 | divisor = parent_rate / rate; | ||
246 | |||
247 | if (divisor > 16) | ||
248 | return -EINVAL; | ||
249 | |||
250 | divclk->divisor = divisor; | ||
251 | |||
252 | /* Update the current MUX settings if we are currently | ||
253 | * selected as the clock source for this clock. */ | ||
254 | |||
255 | if (!pwm_cfg_src_is_tclk(tcfg1)) | ||
256 | clk_pwm_tdiv_update(divclk); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static struct clk_ops clk_tdiv_ops = { | ||
262 | .get_rate = clk_pwm_tdiv_get_rate, | ||
263 | .set_rate = clk_pwm_tdiv_set_rate, | ||
264 | .round_rate = clk_pwm_tdiv_round_rate, | ||
265 | }; | ||
266 | |||
267 | static struct pwm_tdiv_clk clk_timer_tdiv[] = { | ||
268 | [0] = { | ||
269 | .clk = { | ||
270 | .name = "pwm-tdiv", | ||
271 | .ops = &clk_tdiv_ops, | ||
272 | .parent = &clk_timer_scaler[0], | ||
273 | }, | ||
274 | }, | ||
275 | [1] = { | ||
276 | .clk = { | ||
277 | .name = "pwm-tdiv", | ||
278 | .ops = &clk_tdiv_ops, | ||
279 | .parent = &clk_timer_scaler[0], | ||
280 | } | ||
281 | }, | ||
282 | [2] = { | ||
283 | .clk = { | ||
284 | .name = "pwm-tdiv", | ||
285 | .ops = &clk_tdiv_ops, | ||
286 | .parent = &clk_timer_scaler[1], | ||
287 | }, | ||
288 | }, | ||
289 | [3] = { | ||
290 | .clk = { | ||
291 | .name = "pwm-tdiv", | ||
292 | .ops = &clk_tdiv_ops, | ||
293 | .parent = &clk_timer_scaler[1], | ||
294 | }, | ||
295 | }, | ||
296 | [4] = { | ||
297 | .clk = { | ||
298 | .name = "pwm-tdiv", | ||
299 | .ops = &clk_tdiv_ops, | ||
300 | .parent = &clk_timer_scaler[1], | ||
301 | }, | ||
302 | }, | ||
303 | }; | ||
304 | |||
305 | static int __init clk_pwm_tdiv_register(unsigned int id) | ||
306 | { | ||
307 | struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id]; | ||
308 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
309 | |||
310 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | ||
311 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
312 | |||
313 | divclk->clk.id = id; | ||
314 | divclk->divisor = tcfg_to_divisor(tcfg1); | ||
315 | |||
316 | return s3c24xx_register_clock(&divclk->clk); | ||
317 | } | ||
318 | |||
319 | static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id) | ||
320 | { | ||
321 | return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0]; | ||
322 | } | ||
323 | |||
324 | static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id) | ||
325 | { | ||
326 | return &clk_timer_tdiv[id].clk; | ||
327 | } | ||
328 | |||
329 | static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) | ||
330 | { | ||
331 | unsigned int id = clk->id; | ||
332 | unsigned long tcfg1; | ||
333 | unsigned long flags; | ||
334 | unsigned long bits; | ||
335 | unsigned long shift = S3C2410_TCFG1_SHIFT(id); | ||
336 | |||
337 | if (parent == s3c24xx_pwmclk_tclk(id)) | ||
338 | bits = S3C_TCFG1_MUX_TCLK << shift; | ||
339 | else if (parent == s3c24xx_pwmclk_tdiv(id)) | ||
340 | bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; | ||
341 | else | ||
342 | return -EINVAL; | ||
343 | |||
344 | clk->parent = parent; | ||
345 | |||
346 | local_irq_save(flags); | ||
347 | |||
348 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
349 | tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift); | ||
350 | __raw_writel(tcfg1 | bits, S3C2410_TCFG1); | ||
351 | |||
352 | local_irq_restore(flags); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static struct clk_ops clk_tin_ops = { | ||
358 | .set_parent = clk_pwm_tin_set_parent, | ||
359 | }; | ||
360 | |||
361 | static struct clk clk_tin[] = { | ||
362 | [0] = { | ||
363 | .name = "pwm-tin", | ||
364 | .id = 0, | ||
365 | .ops = &clk_tin_ops, | ||
366 | }, | ||
367 | [1] = { | ||
368 | .name = "pwm-tin", | ||
369 | .id = 1, | ||
370 | .ops = &clk_tin_ops, | ||
371 | }, | ||
372 | [2] = { | ||
373 | .name = "pwm-tin", | ||
374 | .id = 2, | ||
375 | .ops = &clk_tin_ops, | ||
376 | }, | ||
377 | [3] = { | ||
378 | .name = "pwm-tin", | ||
379 | .id = 3, | ||
380 | .ops = &clk_tin_ops, | ||
381 | }, | ||
382 | [4] = { | ||
383 | .name = "pwm-tin", | ||
384 | .id = 4, | ||
385 | .ops = &clk_tin_ops, | ||
386 | }, | ||
387 | }; | ||
388 | |||
389 | static __init int clk_pwm_tin_register(struct clk *pwm) | ||
390 | { | ||
391 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
392 | unsigned int id = pwm->id; | ||
393 | |||
394 | struct clk *parent; | ||
395 | int ret; | ||
396 | |||
397 | ret = s3c24xx_register_clock(pwm); | ||
398 | if (ret < 0) | ||
399 | return ret; | ||
400 | |||
401 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | ||
402 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | ||
403 | |||
404 | if (pwm_cfg_src_is_tclk(tcfg1)) | ||
405 | parent = s3c24xx_pwmclk_tclk(id); | ||
406 | else | ||
407 | parent = s3c24xx_pwmclk_tdiv(id); | ||
408 | |||
409 | return clk_set_parent(pwm, parent); | ||
410 | } | ||
411 | |||
412 | /** | ||
413 | * s3c_pwmclk_init() - initialise pwm clocks | ||
414 | * | ||
415 | * Initialise and register the clocks which provide the inputs for the | ||
416 | * pwm timer blocks. | ||
417 | * | ||
418 | * Note, this call is required by the time core, so must be called after | ||
419 | * the base clocks are added and before any of the initcalls are run. | ||
420 | */ | ||
421 | __init void s3c_pwmclk_init(void) | ||
422 | { | ||
423 | struct clk *clk_timers; | ||
424 | unsigned int clk; | ||
425 | int ret; | ||
426 | |||
427 | clk_timers = clk_get(NULL, "timers"); | ||
428 | if (IS_ERR(clk_timers)) { | ||
429 | printk(KERN_ERR "%s: no parent clock\n", __func__); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) | ||
434 | clk_timer_scaler[clk].parent = clk_timers; | ||
435 | |||
436 | s3c_register_clocks(clk_timer_scaler, ARRAY_SIZE(clk_timer_scaler)); | ||
437 | s3c_register_clocks(clk_timer_tclk, ARRAY_SIZE(clk_timer_tclk)); | ||
438 | |||
439 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) { | ||
440 | ret = clk_pwm_tdiv_register(clk); | ||
441 | |||
442 | if (ret < 0) { | ||
443 | printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); | ||
444 | return; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) { | ||
449 | ret = clk_pwm_tin_register(&clk_tin[clk]); | ||
450 | if (ret < 0) { | ||
451 | printk(KERN_ERR "error adding pwm%d tin clock\n", clk); | ||
452 | return; | ||
453 | } | ||
454 | } | ||
455 | } | ||
diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c new file mode 100644 index 000000000000..f2d11390d01c --- /dev/null +++ b/arch/arm/plat-samsung/pwm.c | |||
@@ -0,0 +1,445 @@ | |||
1 | /* arch/arm/plat-s3c/pwm.c | ||
2 | * | ||
3 | * Copyright (c) 2007 Ben Dooks | ||
4 | * Copyright (c) 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> | ||
6 | * | ||
7 | * S3C series PWM device core | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/pwm.h> | ||
21 | |||
22 | #include <mach/irqs.h> | ||
23 | #include <mach/map.h> | ||
24 | |||
25 | #include <plat/devs.h> | ||
26 | #include <plat/regs-timer.h> | ||
27 | |||
28 | struct pwm_device { | ||
29 | struct list_head list; | ||
30 | struct platform_device *pdev; | ||
31 | |||
32 | struct clk *clk_div; | ||
33 | struct clk *clk; | ||
34 | const char *label; | ||
35 | |||
36 | unsigned int period_ns; | ||
37 | unsigned int duty_ns; | ||
38 | |||
39 | unsigned char tcon_base; | ||
40 | unsigned char running; | ||
41 | unsigned char use_count; | ||
42 | unsigned char pwm_id; | ||
43 | }; | ||
44 | |||
45 | #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg) | ||
46 | |||
47 | static struct clk *clk_scaler[2]; | ||
48 | |||
49 | /* Standard setup for a timer block. */ | ||
50 | |||
51 | #define TIMER_RESOURCE_SIZE (1) | ||
52 | |||
53 | #define TIMER_RESOURCE(_tmr, _irq) \ | ||
54 | (struct resource [TIMER_RESOURCE_SIZE]) { \ | ||
55 | [0] = { \ | ||
56 | .start = _irq, \ | ||
57 | .end = _irq, \ | ||
58 | .flags = IORESOURCE_IRQ \ | ||
59 | } \ | ||
60 | } | ||
61 | |||
62 | #define DEFINE_S3C_TIMER(_tmr_no, _irq) \ | ||
63 | .name = "s3c24xx-pwm", \ | ||
64 | .id = _tmr_no, \ | ||
65 | .num_resources = TIMER_RESOURCE_SIZE, \ | ||
66 | .resource = TIMER_RESOURCE(_tmr_no, _irq), \ | ||
67 | |||
68 | /* since we already have an static mapping for the timer, we do not | ||
69 | * bother setting any IO resource for the base. | ||
70 | */ | ||
71 | |||
72 | struct platform_device s3c_device_timer[] = { | ||
73 | [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) }, | ||
74 | [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) }, | ||
75 | [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) }, | ||
76 | [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) }, | ||
77 | [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) }, | ||
78 | }; | ||
79 | |||
80 | static inline int pwm_is_tdiv(struct pwm_device *pwm) | ||
81 | { | ||
82 | return clk_get_parent(pwm->clk) == pwm->clk_div; | ||
83 | } | ||
84 | |||
85 | static DEFINE_MUTEX(pwm_lock); | ||
86 | static LIST_HEAD(pwm_list); | ||
87 | |||
88 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
89 | { | ||
90 | struct pwm_device *pwm; | ||
91 | int found = 0; | ||
92 | |||
93 | mutex_lock(&pwm_lock); | ||
94 | |||
95 | list_for_each_entry(pwm, &pwm_list, list) { | ||
96 | if (pwm->pwm_id == pwm_id) { | ||
97 | found = 1; | ||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | if (found) { | ||
103 | if (pwm->use_count == 0) { | ||
104 | pwm->use_count = 1; | ||
105 | pwm->label = label; | ||
106 | } else | ||
107 | pwm = ERR_PTR(-EBUSY); | ||
108 | } else | ||
109 | pwm = ERR_PTR(-ENOENT); | ||
110 | |||
111 | mutex_unlock(&pwm_lock); | ||
112 | return pwm; | ||
113 | } | ||
114 | |||
115 | EXPORT_SYMBOL(pwm_request); | ||
116 | |||
117 | |||
118 | void pwm_free(struct pwm_device *pwm) | ||
119 | { | ||
120 | mutex_lock(&pwm_lock); | ||
121 | |||
122 | if (pwm->use_count) { | ||
123 | pwm->use_count--; | ||
124 | pwm->label = NULL; | ||
125 | } else | ||
126 | printk(KERN_ERR "PWM%d device already freed\n", pwm->pwm_id); | ||
127 | |||
128 | mutex_unlock(&pwm_lock); | ||
129 | } | ||
130 | |||
131 | EXPORT_SYMBOL(pwm_free); | ||
132 | |||
133 | #define pwm_tcon_start(pwm) (1 << (pwm->tcon_base + 0)) | ||
134 | #define pwm_tcon_invert(pwm) (1 << (pwm->tcon_base + 2)) | ||
135 | #define pwm_tcon_autoreload(pwm) (1 << (pwm->tcon_base + 3)) | ||
136 | #define pwm_tcon_manulupdate(pwm) (1 << (pwm->tcon_base + 1)) | ||
137 | |||
138 | int pwm_enable(struct pwm_device *pwm) | ||
139 | { | ||
140 | unsigned long flags; | ||
141 | unsigned long tcon; | ||
142 | |||
143 | local_irq_save(flags); | ||
144 | |||
145 | tcon = __raw_readl(S3C2410_TCON); | ||
146 | tcon |= pwm_tcon_start(pwm); | ||
147 | __raw_writel(tcon, S3C2410_TCON); | ||
148 | |||
149 | local_irq_restore(flags); | ||
150 | |||
151 | pwm->running = 1; | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | EXPORT_SYMBOL(pwm_enable); | ||
156 | |||
157 | void pwm_disable(struct pwm_device *pwm) | ||
158 | { | ||
159 | unsigned long flags; | ||
160 | unsigned long tcon; | ||
161 | |||
162 | local_irq_save(flags); | ||
163 | |||
164 | tcon = __raw_readl(S3C2410_TCON); | ||
165 | tcon &= ~pwm_tcon_start(pwm); | ||
166 | __raw_writel(tcon, S3C2410_TCON); | ||
167 | |||
168 | local_irq_restore(flags); | ||
169 | |||
170 | pwm->running = 0; | ||
171 | } | ||
172 | |||
173 | EXPORT_SYMBOL(pwm_disable); | ||
174 | |||
175 | static unsigned long pwm_calc_tin(struct pwm_device *pwm, unsigned long freq) | ||
176 | { | ||
177 | unsigned long tin_parent_rate; | ||
178 | unsigned int div; | ||
179 | |||
180 | tin_parent_rate = clk_get_rate(clk_get_parent(pwm->clk_div)); | ||
181 | pwm_dbg(pwm, "tin parent at %lu\n", tin_parent_rate); | ||
182 | |||
183 | for (div = 2; div <= 16; div *= 2) { | ||
184 | if ((tin_parent_rate / (div << 16)) < freq) | ||
185 | return tin_parent_rate / div; | ||
186 | } | ||
187 | |||
188 | return tin_parent_rate / 16; | ||
189 | } | ||
190 | |||
191 | #define NS_IN_HZ (1000000000UL) | ||
192 | |||
193 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | ||
194 | { | ||
195 | unsigned long tin_rate; | ||
196 | unsigned long tin_ns; | ||
197 | unsigned long period; | ||
198 | unsigned long flags; | ||
199 | unsigned long tcon; | ||
200 | unsigned long tcnt; | ||
201 | long tcmp; | ||
202 | |||
203 | /* We currently avoid using 64bit arithmetic by using the | ||
204 | * fact that anything faster than 1Hz is easily representable | ||
205 | * by 32bits. */ | ||
206 | |||
207 | if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ) | ||
208 | return -ERANGE; | ||
209 | |||
210 | if (duty_ns > period_ns) | ||
211 | return -EINVAL; | ||
212 | |||
213 | if (period_ns == pwm->period_ns && | ||
214 | duty_ns == pwm->duty_ns) | ||
215 | return 0; | ||
216 | |||
217 | /* The TCMP and TCNT can be read without a lock, they're not | ||
218 | * shared between the timers. */ | ||
219 | |||
220 | tcmp = __raw_readl(S3C2410_TCMPB(pwm->pwm_id)); | ||
221 | tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id)); | ||
222 | |||
223 | period = NS_IN_HZ / period_ns; | ||
224 | |||
225 | pwm_dbg(pwm, "duty_ns=%d, period_ns=%d (%lu)\n", | ||
226 | duty_ns, period_ns, period); | ||
227 | |||
228 | /* Check to see if we are changing the clock rate of the PWM */ | ||
229 | |||
230 | if (pwm->period_ns != period_ns) { | ||
231 | if (pwm_is_tdiv(pwm)) { | ||
232 | tin_rate = pwm_calc_tin(pwm, period); | ||
233 | clk_set_rate(pwm->clk_div, tin_rate); | ||
234 | } else | ||
235 | tin_rate = clk_get_rate(pwm->clk); | ||
236 | |||
237 | pwm->period_ns = period_ns; | ||
238 | |||
239 | pwm_dbg(pwm, "tin_rate=%lu\n", tin_rate); | ||
240 | |||
241 | tin_ns = NS_IN_HZ / tin_rate; | ||
242 | tcnt = period_ns / tin_ns; | ||
243 | } else | ||
244 | tin_ns = NS_IN_HZ / clk_get_rate(pwm->clk); | ||
245 | |||
246 | /* Note, counters count down */ | ||
247 | |||
248 | tcmp = duty_ns / tin_ns; | ||
249 | tcmp = tcnt - tcmp; | ||
250 | /* the pwm hw only checks the compare register after a decrement, | ||
251 | so the pin never toggles if tcmp = tcnt */ | ||
252 | if (tcmp == tcnt) | ||
253 | tcmp--; | ||
254 | |||
255 | pwm_dbg(pwm, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt); | ||
256 | |||
257 | if (tcmp < 0) | ||
258 | tcmp = 0; | ||
259 | |||
260 | /* Update the PWM register block. */ | ||
261 | |||
262 | local_irq_save(flags); | ||
263 | |||
264 | __raw_writel(tcmp, S3C2410_TCMPB(pwm->pwm_id)); | ||
265 | __raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id)); | ||
266 | |||
267 | tcon = __raw_readl(S3C2410_TCON); | ||
268 | tcon |= pwm_tcon_manulupdate(pwm); | ||
269 | tcon |= pwm_tcon_autoreload(pwm); | ||
270 | __raw_writel(tcon, S3C2410_TCON); | ||
271 | |||
272 | tcon &= ~pwm_tcon_manulupdate(pwm); | ||
273 | __raw_writel(tcon, S3C2410_TCON); | ||
274 | |||
275 | local_irq_restore(flags); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | EXPORT_SYMBOL(pwm_config); | ||
281 | |||
282 | static int pwm_register(struct pwm_device *pwm) | ||
283 | { | ||
284 | pwm->duty_ns = -1; | ||
285 | pwm->period_ns = -1; | ||
286 | |||
287 | mutex_lock(&pwm_lock); | ||
288 | list_add_tail(&pwm->list, &pwm_list); | ||
289 | mutex_unlock(&pwm_lock); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int s3c_pwm_probe(struct platform_device *pdev) | ||
295 | { | ||
296 | struct device *dev = &pdev->dev; | ||
297 | struct pwm_device *pwm; | ||
298 | unsigned long flags; | ||
299 | unsigned long tcon; | ||
300 | unsigned int id = pdev->id; | ||
301 | int ret; | ||
302 | |||
303 | if (id == 4) { | ||
304 | dev_err(dev, "TIMER4 is currently not supported\n"); | ||
305 | return -ENXIO; | ||
306 | } | ||
307 | |||
308 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | ||
309 | if (pwm == NULL) { | ||
310 | dev_err(dev, "failed to allocate pwm_device\n"); | ||
311 | return -ENOMEM; | ||
312 | } | ||
313 | |||
314 | pwm->pdev = pdev; | ||
315 | pwm->pwm_id = id; | ||
316 | |||
317 | /* calculate base of control bits in TCON */ | ||
318 | pwm->tcon_base = id == 0 ? 0 : (id * 4) + 4; | ||
319 | |||
320 | pwm->clk = clk_get(dev, "pwm-tin"); | ||
321 | if (IS_ERR(pwm->clk)) { | ||
322 | dev_err(dev, "failed to get pwm tin clk\n"); | ||
323 | ret = PTR_ERR(pwm->clk); | ||
324 | goto err_alloc; | ||
325 | } | ||
326 | |||
327 | pwm->clk_div = clk_get(dev, "pwm-tdiv"); | ||
328 | if (IS_ERR(pwm->clk_div)) { | ||
329 | dev_err(dev, "failed to get pwm tdiv clk\n"); | ||
330 | ret = PTR_ERR(pwm->clk_div); | ||
331 | goto err_clk_tin; | ||
332 | } | ||
333 | |||
334 | local_irq_save(flags); | ||
335 | |||
336 | tcon = __raw_readl(S3C2410_TCON); | ||
337 | tcon |= pwm_tcon_invert(pwm); | ||
338 | __raw_writel(tcon, S3C2410_TCON); | ||
339 | |||
340 | local_irq_restore(flags); | ||
341 | |||
342 | |||
343 | ret = pwm_register(pwm); | ||
344 | if (ret) { | ||
345 | dev_err(dev, "failed to register pwm\n"); | ||
346 | goto err_clk_tdiv; | ||
347 | } | ||
348 | |||
349 | pwm_dbg(pwm, "config bits %02x\n", | ||
350 | (__raw_readl(S3C2410_TCON) >> pwm->tcon_base) & 0x0f); | ||
351 | |||
352 | dev_info(dev, "tin at %lu, tdiv at %lu, tin=%sclk, base %d\n", | ||
353 | clk_get_rate(pwm->clk), | ||
354 | clk_get_rate(pwm->clk_div), | ||
355 | pwm_is_tdiv(pwm) ? "div" : "ext", pwm->tcon_base); | ||
356 | |||
357 | platform_set_drvdata(pdev, pwm); | ||
358 | return 0; | ||
359 | |||
360 | err_clk_tdiv: | ||
361 | clk_put(pwm->clk_div); | ||
362 | |||
363 | err_clk_tin: | ||
364 | clk_put(pwm->clk); | ||
365 | |||
366 | err_alloc: | ||
367 | kfree(pwm); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | static int __devexit s3c_pwm_remove(struct platform_device *pdev) | ||
372 | { | ||
373 | struct pwm_device *pwm = platform_get_drvdata(pdev); | ||
374 | |||
375 | clk_put(pwm->clk_div); | ||
376 | clk_put(pwm->clk); | ||
377 | kfree(pwm); | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | #ifdef CONFIG_PM | ||
383 | static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state) | ||
384 | { | ||
385 | struct pwm_device *pwm = platform_get_drvdata(pdev); | ||
386 | |||
387 | /* No one preserve these values during suspend so reset them | ||
388 | * Otherwise driver leaves PWM unconfigured if same values | ||
389 | * passed to pwm_config | ||
390 | */ | ||
391 | pwm->period_ns = 0; | ||
392 | pwm->duty_ns = 0; | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static int s3c_pwm_resume(struct platform_device *pdev) | ||
398 | { | ||
399 | struct pwm_device *pwm = platform_get_drvdata(pdev); | ||
400 | unsigned long tcon; | ||
401 | |||
402 | /* Restore invertion */ | ||
403 | tcon = __raw_readl(S3C2410_TCON); | ||
404 | tcon |= pwm_tcon_invert(pwm); | ||
405 | __raw_writel(tcon, S3C2410_TCON); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | #else | ||
411 | #define s3c_pwm_suspend NULL | ||
412 | #define s3c_pwm_resume NULL | ||
413 | #endif | ||
414 | |||
415 | static struct platform_driver s3c_pwm_driver = { | ||
416 | .driver = { | ||
417 | .name = "s3c24xx-pwm", | ||
418 | .owner = THIS_MODULE, | ||
419 | }, | ||
420 | .probe = s3c_pwm_probe, | ||
421 | .remove = __devexit_p(s3c_pwm_remove), | ||
422 | .suspend = s3c_pwm_suspend, | ||
423 | .resume = s3c_pwm_resume, | ||
424 | }; | ||
425 | |||
426 | static int __init pwm_init(void) | ||
427 | { | ||
428 | int ret; | ||
429 | |||
430 | clk_scaler[0] = clk_get(NULL, "pwm-scaler0"); | ||
431 | clk_scaler[1] = clk_get(NULL, "pwm-scaler1"); | ||
432 | |||
433 | if (IS_ERR(clk_scaler[0]) || IS_ERR(clk_scaler[1])) { | ||
434 | printk(KERN_ERR "%s: failed to get scaler clocks\n", __func__); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | |||
438 | ret = platform_driver_register(&s3c_pwm_driver); | ||
439 | if (ret) | ||
440 | printk(KERN_ERR "%s: failed to add pwm driver\n", __func__); | ||
441 | |||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | arch_initcall(pwm_init); | ||
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c new file mode 100644 index 000000000000..2231d80ad817 --- /dev/null +++ b/arch/arm/plat-samsung/time.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* linux/arch/arm/plat-samsung/time.c | ||
2 | * | ||
3 | * Copyright (C) 2003-2005 Simtec Electronics | ||
4 | * Ben Dooks, <ben@simtec.co.uk> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | |||
31 | #include <asm/system.h> | ||
32 | #include <asm/leds.h> | ||
33 | #include <asm/mach-types.h> | ||
34 | |||
35 | #include <asm/irq.h> | ||
36 | #include <mach/map.h> | ||
37 | #include <plat/regs-timer.h> | ||
38 | #include <mach/regs-irq.h> | ||
39 | #include <asm/mach/time.h> | ||
40 | #include <mach/tick.h> | ||
41 | |||
42 | #include <plat/clock.h> | ||
43 | #include <plat/cpu.h> | ||
44 | |||
45 | static unsigned long timer_startval; | ||
46 | static unsigned long timer_usec_ticks; | ||
47 | |||
48 | #ifndef TICK_MAX | ||
49 | #define TICK_MAX (0xffff) | ||
50 | #endif | ||
51 | |||
52 | #define TIMER_USEC_SHIFT 16 | ||
53 | |||
54 | /* we use the shifted arithmetic to work out the ratio of timer ticks | ||
55 | * to usecs, as often the peripheral clock is not a nice even multiple | ||
56 | * of 1MHz. | ||
57 | * | ||
58 | * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok | ||
59 | * for the current HZ value of 200 without producing overflows. | ||
60 | * | ||
61 | * Original patch by Dimitry Andric, updated by Ben Dooks | ||
62 | */ | ||
63 | |||
64 | |||
65 | /* timer_mask_usec_ticks | ||
66 | * | ||
67 | * given a clock and divisor, make the value to pass into timer_ticks_to_usec | ||
68 | * to scale the ticks into usecs | ||
69 | */ | ||
70 | |||
71 | static inline unsigned long | ||
72 | timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk) | ||
73 | { | ||
74 | unsigned long den = pclk / 1000; | ||
75 | |||
76 | return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den; | ||
77 | } | ||
78 | |||
79 | /* timer_ticks_to_usec | ||
80 | * | ||
81 | * convert timer ticks to usec. | ||
82 | */ | ||
83 | |||
84 | static inline unsigned long timer_ticks_to_usec(unsigned long ticks) | ||
85 | { | ||
86 | unsigned long res; | ||
87 | |||
88 | res = ticks * timer_usec_ticks; | ||
89 | res += 1 << (TIMER_USEC_SHIFT - 4); /* round up slightly */ | ||
90 | |||
91 | return res >> TIMER_USEC_SHIFT; | ||
92 | } | ||
93 | |||
94 | /*** | ||
95 | * Returns microsecond since last clock interrupt. Note that interrupts | ||
96 | * will have been disabled by do_gettimeoffset() | ||
97 | * IRQs are disabled before entering here from do_gettimeofday() | ||
98 | */ | ||
99 | |||
100 | static unsigned long s3c2410_gettimeoffset (void) | ||
101 | { | ||
102 | unsigned long tdone; | ||
103 | unsigned long tval; | ||
104 | |||
105 | /* work out how many ticks have gone since last timer interrupt */ | ||
106 | |||
107 | tval = __raw_readl(S3C2410_TCNTO(4)); | ||
108 | tdone = timer_startval - tval; | ||
109 | |||
110 | /* check to see if there is an interrupt pending */ | ||
111 | |||
112 | if (s3c24xx_ostimer_pending()) { | ||
113 | /* re-read the timer, and try and fix up for the missed | ||
114 | * interrupt. Note, the interrupt may go off before the | ||
115 | * timer has re-loaded from wrapping. | ||
116 | */ | ||
117 | |||
118 | tval = __raw_readl(S3C2410_TCNTO(4)); | ||
119 | tdone = timer_startval - tval; | ||
120 | |||
121 | if (tval != 0) | ||
122 | tdone += timer_startval; | ||
123 | } | ||
124 | |||
125 | return timer_ticks_to_usec(tdone); | ||
126 | } | ||
127 | |||
128 | |||
129 | /* | ||
130 | * IRQ handler for the timer | ||
131 | */ | ||
132 | static irqreturn_t | ||
133 | s3c2410_timer_interrupt(int irq, void *dev_id) | ||
134 | { | ||
135 | timer_tick(); | ||
136 | return IRQ_HANDLED; | ||
137 | } | ||
138 | |||
139 | static struct irqaction s3c2410_timer_irq = { | ||
140 | .name = "S3C2410 Timer Tick", | ||
141 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | ||
142 | .handler = s3c2410_timer_interrupt, | ||
143 | }; | ||
144 | |||
145 | #define use_tclk1_12() ( \ | ||
146 | machine_is_bast() || \ | ||
147 | machine_is_vr1000() || \ | ||
148 | machine_is_anubis() || \ | ||
149 | machine_is_osiris()) | ||
150 | |||
151 | static struct clk *tin; | ||
152 | static struct clk *tdiv; | ||
153 | static struct clk *timerclk; | ||
154 | |||
155 | /* | ||
156 | * Set up timer interrupt, and return the current time in seconds. | ||
157 | * | ||
158 | * Currently we only use timer4, as it is the only timer which has no | ||
159 | * other function that can be exploited externally | ||
160 | */ | ||
161 | static void s3c2410_timer_setup (void) | ||
162 | { | ||
163 | unsigned long tcon; | ||
164 | unsigned long tcnt; | ||
165 | unsigned long tcfg1; | ||
166 | unsigned long tcfg0; | ||
167 | |||
168 | tcnt = TICK_MAX; /* default value for tcnt */ | ||
169 | |||
170 | /* configure the system for whichever machine is in use */ | ||
171 | |||
172 | if (use_tclk1_12()) { | ||
173 | /* timer is at 12MHz, scaler is 1 */ | ||
174 | timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); | ||
175 | tcnt = 12000000 / HZ; | ||
176 | |||
177 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
178 | tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; | ||
179 | tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; | ||
180 | __raw_writel(tcfg1, S3C2410_TCFG1); | ||
181 | } else { | ||
182 | unsigned long pclk; | ||
183 | struct clk *tscaler; | ||
184 | |||
185 | /* for the h1940 (and others), we use the pclk from the core | ||
186 | * to generate the timer values. since values around 50 to | ||
187 | * 70MHz are not values we can directly generate the timer | ||
188 | * value from, we need to pre-scale and divide before using it. | ||
189 | * | ||
190 | * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz | ||
191 | * (8.45 ticks per usec) | ||
192 | */ | ||
193 | |||
194 | pclk = clk_get_rate(timerclk); | ||
195 | |||
196 | /* configure clock tick */ | ||
197 | |||
198 | timer_usec_ticks = timer_mask_usec_ticks(6, pclk); | ||
199 | |||
200 | tscaler = clk_get_parent(tdiv); | ||
201 | |||
202 | clk_set_rate(tscaler, pclk / 3); | ||
203 | clk_set_rate(tdiv, pclk / 6); | ||
204 | clk_set_parent(tin, tdiv); | ||
205 | |||
206 | tcnt = clk_get_rate(tin) / HZ; | ||
207 | } | ||
208 | |||
209 | tcon = __raw_readl(S3C2410_TCON); | ||
210 | tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
211 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
212 | |||
213 | /* timers reload after counting zero, so reduce the count by 1 */ | ||
214 | |||
215 | tcnt--; | ||
216 | |||
217 | printk(KERN_DEBUG "timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n", | ||
218 | tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks); | ||
219 | |||
220 | /* check to see if timer is within 16bit range... */ | ||
221 | if (tcnt > TICK_MAX) { | ||
222 | panic("setup_timer: HZ is too small, cannot configure timer!"); | ||
223 | return; | ||
224 | } | ||
225 | |||
226 | __raw_writel(tcfg1, S3C2410_TCFG1); | ||
227 | __raw_writel(tcfg0, S3C2410_TCFG0); | ||
228 | |||
229 | timer_startval = tcnt; | ||
230 | __raw_writel(tcnt, S3C2410_TCNTB(4)); | ||
231 | |||
232 | /* ensure timer is stopped... */ | ||
233 | |||
234 | tcon &= ~(7<<20); | ||
235 | tcon |= S3C2410_TCON_T4RELOAD; | ||
236 | tcon |= S3C2410_TCON_T4MANUALUPD; | ||
237 | |||
238 | __raw_writel(tcon, S3C2410_TCON); | ||
239 | __raw_writel(tcnt, S3C2410_TCNTB(4)); | ||
240 | __raw_writel(tcnt, S3C2410_TCMPB(4)); | ||
241 | |||
242 | /* start the timer running */ | ||
243 | tcon |= S3C2410_TCON_T4START; | ||
244 | tcon &= ~S3C2410_TCON_T4MANUALUPD; | ||
245 | __raw_writel(tcon, S3C2410_TCON); | ||
246 | } | ||
247 | |||
248 | static void __init s3c2410_timer_resources(void) | ||
249 | { | ||
250 | struct platform_device tmpdev; | ||
251 | |||
252 | tmpdev.dev.bus = &platform_bus_type; | ||
253 | tmpdev.id = 4; | ||
254 | |||
255 | timerclk = clk_get(NULL, "timers"); | ||
256 | if (IS_ERR(timerclk)) | ||
257 | panic("failed to get clock for system timer"); | ||
258 | |||
259 | clk_enable(timerclk); | ||
260 | |||
261 | if (!use_tclk1_12()) { | ||
262 | tin = clk_get(&tmpdev.dev, "pwm-tin"); | ||
263 | if (IS_ERR(tin)) | ||
264 | panic("failed to get pwm-tin clock for system timer"); | ||
265 | |||
266 | tdiv = clk_get(&tmpdev.dev, "pwm-tdiv"); | ||
267 | if (IS_ERR(tdiv)) | ||
268 | panic("failed to get pwm-tdiv clock for system timer"); | ||
269 | } | ||
270 | |||
271 | clk_enable(tin); | ||
272 | } | ||
273 | |||
274 | static void __init s3c2410_timer_init(void) | ||
275 | { | ||
276 | s3c2410_timer_resources(); | ||
277 | s3c2410_timer_setup(); | ||
278 | setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); | ||
279 | } | ||
280 | |||
281 | struct sys_timer s3c24xx_timer = { | ||
282 | .init = s3c2410_timer_init, | ||
283 | .offset = s3c2410_gettimeoffset, | ||
284 | .resume = s3c2410_timer_setup | ||
285 | }; | ||