diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/plat-samsung | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/arm/plat-samsung')
48 files changed, 5593 insertions, 0 deletions
diff --git a/arch/arm/plat-samsung/dev-adc.c b/arch/arm/plat-samsung/dev-adc.c new file mode 100644 index 00000000000..9d903d4095e --- /dev/null +++ b/arch/arm/plat-samsung/dev-adc.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-adc.c | ||
2 | * | ||
3 | * Copyright 2010 Maurus Cuelenaere | ||
4 | * | ||
5 | * S3C64xx series device definition for ADC device | ||
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/kernel.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | #include <mach/irqs.h> | ||
17 | #include <mach/map.h> | ||
18 | |||
19 | #include <plat/adc.h> | ||
20 | #include <plat/devs.h> | ||
21 | #include <plat/cpu.h> | ||
22 | |||
23 | static struct resource s3c_adc_resource[] = { | ||
24 | [0] = { | ||
25 | .start = SAMSUNG_PA_ADC, | ||
26 | .end = SAMSUNG_PA_ADC + SZ_256 - 1, | ||
27 | .flags = IORESOURCE_MEM, | ||
28 | }, | ||
29 | [1] = { | ||
30 | .start = IRQ_TC, | ||
31 | .end = IRQ_TC, | ||
32 | .flags = IORESOURCE_IRQ, | ||
33 | }, | ||
34 | [2] = { | ||
35 | .start = IRQ_ADC, | ||
36 | .end = IRQ_ADC, | ||
37 | .flags = IORESOURCE_IRQ, | ||
38 | }, | ||
39 | }; | ||
40 | |||
41 | struct platform_device s3c_device_adc = { | ||
42 | .name = "samsung-adc", | ||
43 | .id = -1, | ||
44 | .num_resources = ARRAY_SIZE(s3c_adc_resource), | ||
45 | .resource = s3c_adc_resource, | ||
46 | }; | ||
diff --git a/arch/arm/plat-samsung/dev-asocdma.c b/arch/arm/plat-samsung/dev-asocdma.c new file mode 100644 index 00000000000..97e35d3c064 --- /dev/null +++ b/arch/arm/plat-samsung/dev-asocdma.c | |||
@@ -0,0 +1,35 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-asocdma.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co. 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 | #include <linux/platform_device.h> | ||
12 | #include <linux/dma-mapping.h> | ||
13 | #include <plat/devs.h> | ||
14 | |||
15 | static u64 audio_dmamask = DMA_BIT_MASK(32); | ||
16 | |||
17 | struct platform_device samsung_asoc_dma = { | ||
18 | .name = "samsung-audio", | ||
19 | .id = -1, | ||
20 | .dev = { | ||
21 | .dma_mask = &audio_dmamask, | ||
22 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
23 | } | ||
24 | }; | ||
25 | EXPORT_SYMBOL(samsung_asoc_dma); | ||
26 | |||
27 | struct platform_device samsung_asoc_idma = { | ||
28 | .name = "samsung-idma", | ||
29 | .id = -1, | ||
30 | .dev = { | ||
31 | .dma_mask = &audio_dmamask, | ||
32 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
33 | } | ||
34 | }; | ||
35 | EXPORT_SYMBOL(samsung_asoc_idma); | ||
diff --git a/arch/arm/plat-samsung/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c new file mode 100644 index 00000000000..49a1362fd25 --- /dev/null +++ b/arch/arm/plat-samsung/dev-fb.c | |||
@@ -0,0 +1,63 @@ | |||
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 | #include <linux/gfp.h> | ||
19 | |||
20 | #include <mach/irqs.h> | ||
21 | #include <mach/map.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 | s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata), | ||
62 | &s3c_device_fb); | ||
63 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c new file mode 100644 index 00000000000..db7a65c7f12 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hsmmc.c | |||
@@ -0,0 +1,79 @@ | |||
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 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
45 | }; | ||
46 | |||
47 | struct platform_device s3c_device_hsmmc0 = { | ||
48 | .name = "s3c-sdhci", | ||
49 | .id = 0, | ||
50 | .num_resources = ARRAY_SIZE(s3c_hsmmc_resource), | ||
51 | .resource = s3c_hsmmc_resource, | ||
52 | .dev = { | ||
53 | .dma_mask = &s3c_device_hsmmc_dmamask, | ||
54 | .coherent_dma_mask = 0xffffffffUL, | ||
55 | .platform_data = &s3c_hsmmc0_def_platdata, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) | ||
60 | { | ||
61 | struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; | ||
62 | |||
63 | set->cd_type = pd->cd_type; | ||
64 | set->ext_cd_init = pd->ext_cd_init; | ||
65 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | ||
66 | set->ext_cd_gpio = pd->ext_cd_gpio; | ||
67 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | ||
68 | |||
69 | if (pd->max_width) | ||
70 | set->max_width = pd->max_width; | ||
71 | if (pd->cfg_gpio) | ||
72 | set->cfg_gpio = pd->cfg_gpio; | ||
73 | if (pd->cfg_card) | ||
74 | set->cfg_card = pd->cfg_card; | ||
75 | if (pd->host_caps) | ||
76 | set->host_caps |= pd->host_caps; | ||
77 | if (pd->clk_type) | ||
78 | set->clk_type = pd->clk_type; | ||
79 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c new file mode 100644 index 00000000000..2497321f08d --- /dev/null +++ b/arch/arm/plat-samsung/dev-hsmmc1.c | |||
@@ -0,0 +1,79 @@ | |||
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 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
45 | }; | ||
46 | |||
47 | struct platform_device s3c_device_hsmmc1 = { | ||
48 | .name = "s3c-sdhci", | ||
49 | .id = 1, | ||
50 | .num_resources = ARRAY_SIZE(s3c_hsmmc1_resource), | ||
51 | .resource = s3c_hsmmc1_resource, | ||
52 | .dev = { | ||
53 | .dma_mask = &s3c_device_hsmmc1_dmamask, | ||
54 | .coherent_dma_mask = 0xffffffffUL, | ||
55 | .platform_data = &s3c_hsmmc1_def_platdata, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) | ||
60 | { | ||
61 | struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; | ||
62 | |||
63 | set->cd_type = pd->cd_type; | ||
64 | set->ext_cd_init = pd->ext_cd_init; | ||
65 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | ||
66 | set->ext_cd_gpio = pd->ext_cd_gpio; | ||
67 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | ||
68 | |||
69 | if (pd->max_width) | ||
70 | set->max_width = pd->max_width; | ||
71 | if (pd->cfg_gpio) | ||
72 | set->cfg_gpio = pd->cfg_gpio; | ||
73 | if (pd->cfg_card) | ||
74 | set->cfg_card = pd->cfg_card; | ||
75 | if (pd->host_caps) | ||
76 | set->host_caps |= pd->host_caps; | ||
77 | if (pd->clk_type) | ||
78 | set->clk_type = pd->clk_type; | ||
79 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c new file mode 100644 index 00000000000..f60aedba417 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hsmmc2.c | |||
@@ -0,0 +1,80 @@ | |||
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 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
46 | }; | ||
47 | |||
48 | struct platform_device s3c_device_hsmmc2 = { | ||
49 | .name = "s3c-sdhci", | ||
50 | .id = 2, | ||
51 | .num_resources = ARRAY_SIZE(s3c_hsmmc2_resource), | ||
52 | .resource = s3c_hsmmc2_resource, | ||
53 | .dev = { | ||
54 | .dma_mask = &s3c_device_hsmmc2_dmamask, | ||
55 | .coherent_dma_mask = 0xffffffffUL, | ||
56 | .platform_data = &s3c_hsmmc2_def_platdata, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd) | ||
61 | { | ||
62 | struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; | ||
63 | |||
64 | set->cd_type = pd->cd_type; | ||
65 | set->ext_cd_init = pd->ext_cd_init; | ||
66 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | ||
67 | set->ext_cd_gpio = pd->ext_cd_gpio; | ||
68 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | ||
69 | |||
70 | if (pd->max_width) | ||
71 | set->max_width = pd->max_width; | ||
72 | if (pd->cfg_gpio) | ||
73 | set->cfg_gpio = pd->cfg_gpio; | ||
74 | if (pd->cfg_card) | ||
75 | set->cfg_card = pd->cfg_card; | ||
76 | if (pd->host_caps) | ||
77 | set->host_caps |= pd->host_caps; | ||
78 | if (pd->clk_type) | ||
79 | set->clk_type = pd->clk_type; | ||
80 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c new file mode 100644 index 00000000000..ede776f20e6 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hsmmc3.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-hsmmc3.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Copyright (c) 2008 Simtec Electronics | ||
7 | * Ben Dooks <ben@simtec.co.uk> | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * | ||
10 | * Based on arch/arm/plat-samsung/dev-hsmmc1.c | ||
11 | * | ||
12 | * Samsung device definition for hsmmc device 3 | ||
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 version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mmc/host.h> | ||
22 | |||
23 | #include <mach/map.h> | ||
24 | #include <plat/sdhci.h> | ||
25 | #include <plat/devs.h> | ||
26 | |||
27 | #define S3C_SZ_HSMMC (0x1000) | ||
28 | |||
29 | static struct resource s3c_hsmmc3_resource[] = { | ||
30 | [0] = { | ||
31 | .start = S3C_PA_HSMMC3, | ||
32 | .end = S3C_PA_HSMMC3 + S3C_SZ_HSMMC - 1, | ||
33 | .flags = IORESOURCE_MEM, | ||
34 | }, | ||
35 | [1] = { | ||
36 | .start = IRQ_HSMMC3, | ||
37 | .end = IRQ_HSMMC3, | ||
38 | .flags = IORESOURCE_IRQ, | ||
39 | } | ||
40 | }; | ||
41 | |||
42 | static u64 s3c_device_hsmmc3_dmamask = 0xffffffffUL; | ||
43 | |||
44 | struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = { | ||
45 | .max_width = 4, | ||
46 | .host_caps = (MMC_CAP_4_BIT_DATA | | ||
47 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | ||
48 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
49 | }; | ||
50 | |||
51 | struct platform_device s3c_device_hsmmc3 = { | ||
52 | .name = "s3c-sdhci", | ||
53 | .id = 3, | ||
54 | .num_resources = ARRAY_SIZE(s3c_hsmmc3_resource), | ||
55 | .resource = s3c_hsmmc3_resource, | ||
56 | .dev = { | ||
57 | .dma_mask = &s3c_device_hsmmc3_dmamask, | ||
58 | .coherent_dma_mask = 0xffffffffUL, | ||
59 | .platform_data = &s3c_hsmmc3_def_platdata, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd) | ||
64 | { | ||
65 | struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata; | ||
66 | |||
67 | set->cd_type = pd->cd_type; | ||
68 | set->ext_cd_init = pd->ext_cd_init; | ||
69 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | ||
70 | set->ext_cd_gpio = pd->ext_cd_gpio; | ||
71 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | ||
72 | |||
73 | if (pd->max_width) | ||
74 | set->max_width = pd->max_width; | ||
75 | if (pd->cfg_gpio) | ||
76 | set->cfg_gpio = pd->cfg_gpio; | ||
77 | if (pd->cfg_card) | ||
78 | set->cfg_card = pd->cfg_card; | ||
79 | if (pd->host_caps) | ||
80 | set->host_caps |= pd->host_caps; | ||
81 | if (pd->clk_type) | ||
82 | set->clk_type = pd->clk_type; | ||
83 | } | ||
diff --git a/arch/arm/plat-samsung/dev-hwmon.c b/arch/arm/plat-samsung/dev-hwmon.c new file mode 100644 index 00000000000..c91a79ce8f3 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hwmon.c | |||
@@ -0,0 +1,32 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-hwmon.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * Adapted for HWMON by Maurus Cuelenaere | ||
8 | * | ||
9 | * Samsung series device definition for HWMON | ||
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 | |||
19 | #include <plat/devs.h> | ||
20 | #include <plat/hwmon.h> | ||
21 | |||
22 | struct platform_device s3c_device_hwmon = { | ||
23 | .name = "s3c-hwmon", | ||
24 | .id = -1, | ||
25 | .dev.parent = &s3c_device_adc.dev, | ||
26 | }; | ||
27 | |||
28 | void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd) | ||
29 | { | ||
30 | s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata), | ||
31 | &s3c_device_hwmon); | ||
32 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c new file mode 100644 index 00000000000..f8251f5098b --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c0.c | |||
@@ -0,0 +1,70 @@ | |||
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/gfp.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <mach/irqs.h> | ||
20 | #include <mach/map.h> | ||
21 | |||
22 | #include <plat/regs-iic.h> | ||
23 | #include <plat/iic.h> | ||
24 | #include <plat/devs.h> | ||
25 | #include <plat/cpu.h> | ||
26 | |||
27 | static struct resource s3c_i2c_resource[] = { | ||
28 | [0] = { | ||
29 | .start = S3C_PA_IIC, | ||
30 | .end = S3C_PA_IIC + SZ_4K - 1, | ||
31 | .flags = IORESOURCE_MEM, | ||
32 | }, | ||
33 | [1] = { | ||
34 | .start = IRQ_IIC, | ||
35 | .end = IRQ_IIC, | ||
36 | .flags = IORESOURCE_IRQ, | ||
37 | }, | ||
38 | }; | ||
39 | |||
40 | struct platform_device s3c_device_i2c0 = { | ||
41 | .name = "s3c2410-i2c", | ||
42 | #ifdef CONFIG_S3C_DEV_I2C1 | ||
43 | .id = 0, | ||
44 | #else | ||
45 | .id = -1, | ||
46 | #endif | ||
47 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
48 | .resource = s3c_i2c_resource, | ||
49 | }; | ||
50 | |||
51 | struct s3c2410_platform_i2c default_i2c_data __initdata = { | ||
52 | .flags = 0, | ||
53 | .slave_addr = 0x10, | ||
54 | .frequency = 100*1000, | ||
55 | .sda_delay = 100, | ||
56 | }; | ||
57 | |||
58 | void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd) | ||
59 | { | ||
60 | struct s3c2410_platform_i2c *npd; | ||
61 | |||
62 | if (!pd) | ||
63 | pd = &default_i2c_data; | ||
64 | |||
65 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
66 | &s3c_device_i2c0); | ||
67 | |||
68 | if (!npd->cfg_gpio) | ||
69 | npd->cfg_gpio = s3c_i2c0_cfg_gpio; | ||
70 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c new file mode 100644 index 00000000000..3b7c7bec1cf --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c1.c | |||
@@ -0,0 +1,61 @@ | |||
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/gfp.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <mach/irqs.h> | ||
20 | #include <mach/map.h> | ||
21 | |||
22 | #include <plat/regs-iic.h> | ||
23 | #include <plat/iic.h> | ||
24 | #include <plat/devs.h> | ||
25 | #include <plat/cpu.h> | ||
26 | |||
27 | static struct resource s3c_i2c_resource[] = { | ||
28 | [0] = { | ||
29 | .start = S3C_PA_IIC1, | ||
30 | .end = S3C_PA_IIC1 + SZ_4K - 1, | ||
31 | .flags = IORESOURCE_MEM, | ||
32 | }, | ||
33 | [1] = { | ||
34 | .start = IRQ_IIC1, | ||
35 | .end = IRQ_IIC1, | ||
36 | .flags = IORESOURCE_IRQ, | ||
37 | }, | ||
38 | }; | ||
39 | |||
40 | struct platform_device s3c_device_i2c1 = { | ||
41 | .name = "s3c2410-i2c", | ||
42 | .id = 1, | ||
43 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
44 | .resource = s3c_i2c_resource, | ||
45 | }; | ||
46 | |||
47 | void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd) | ||
48 | { | ||
49 | struct s3c2410_platform_i2c *npd; | ||
50 | |||
51 | if (!pd) { | ||
52 | pd = &default_i2c_data; | ||
53 | pd->bus_num = 1; | ||
54 | } | ||
55 | |||
56 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
57 | &s3c_device_i2c1); | ||
58 | |||
59 | if (!npd->cfg_gpio) | ||
60 | npd->cfg_gpio = s3c_i2c1_cfg_gpio; | ||
61 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c new file mode 100644 index 00000000000..07e9fd0b1b8 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c2.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* linux/arch/arm/plat-s3c/dev-i2c2.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S3C series device definition for i2c device 2 | ||
7 | * | ||
8 | * Based on plat-samsung/dev-i2c0.c | ||
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/gfp.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | #include <mach/irqs.h> | ||
21 | #include <mach/map.h> | ||
22 | |||
23 | #include <plat/regs-iic.h> | ||
24 | #include <plat/iic.h> | ||
25 | #include <plat/devs.h> | ||
26 | #include <plat/cpu.h> | ||
27 | |||
28 | static struct resource s3c_i2c_resource[] = { | ||
29 | [0] = { | ||
30 | .start = S3C_PA_IIC2, | ||
31 | .end = S3C_PA_IIC2 + SZ_4K - 1, | ||
32 | .flags = IORESOURCE_MEM, | ||
33 | }, | ||
34 | [1] = { | ||
35 | .start = IRQ_IIC2, | ||
36 | .end = IRQ_IIC2, | ||
37 | .flags = IORESOURCE_IRQ, | ||
38 | }, | ||
39 | }; | ||
40 | |||
41 | struct platform_device s3c_device_i2c2 = { | ||
42 | .name = "s3c2410-i2c", | ||
43 | .id = 2, | ||
44 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
45 | .resource = s3c_i2c_resource, | ||
46 | }; | ||
47 | |||
48 | void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd) | ||
49 | { | ||
50 | struct s3c2410_platform_i2c *npd; | ||
51 | |||
52 | if (!pd) { | ||
53 | pd = &default_i2c_data; | ||
54 | pd->bus_num = 2; | ||
55 | } | ||
56 | |||
57 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
58 | &s3c_device_i2c2); | ||
59 | |||
60 | if (!npd->cfg_gpio) | ||
61 | npd->cfg_gpio = s3c_i2c2_cfg_gpio; | ||
62 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c new file mode 100644 index 00000000000..d48efa93c6e --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c3.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c3.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 3 | ||
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 <linux/gfp.h> | ||
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_IIC3, | ||
29 | .end = S3C_PA_IIC3 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC3, | ||
34 | .end = IRQ_IIC3, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c3 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 3, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd) | ||
47 | { | ||
48 | struct s3c2410_platform_i2c *npd; | ||
49 | |||
50 | if (!pd) { | ||
51 | pd = &default_i2c_data; | ||
52 | pd->bus_num = 3; | ||
53 | } | ||
54 | |||
55 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
56 | &s3c_device_i2c3); | ||
57 | |||
58 | if (!npd->cfg_gpio) | ||
59 | npd->cfg_gpio = s3c_i2c3_cfg_gpio; | ||
60 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c new file mode 100644 index 00000000000..07e26444efe --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c4.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c4.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 3 | ||
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 <linux/gfp.h> | ||
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_IIC4, | ||
29 | .end = S3C_PA_IIC4 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC4, | ||
34 | .end = IRQ_IIC4, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c4 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 4, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd) | ||
47 | { | ||
48 | struct s3c2410_platform_i2c *npd; | ||
49 | |||
50 | if (!pd) { | ||
51 | pd = &default_i2c_data; | ||
52 | pd->bus_num = 4; | ||
53 | } | ||
54 | |||
55 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
56 | &s3c_device_i2c4); | ||
57 | |||
58 | if (!npd->cfg_gpio) | ||
59 | npd->cfg_gpio = s3c_i2c4_cfg_gpio; | ||
60 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c new file mode 100644 index 00000000000..f4965578456 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c5.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c3.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 3 | ||
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 <linux/gfp.h> | ||
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_IIC5, | ||
29 | .end = S3C_PA_IIC5 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC5, | ||
34 | .end = IRQ_IIC5, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c5 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 5, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd) | ||
47 | { | ||
48 | struct s3c2410_platform_i2c *npd; | ||
49 | |||
50 | if (!pd) { | ||
51 | pd = &default_i2c_data; | ||
52 | pd->bus_num = 5; | ||
53 | } | ||
54 | |||
55 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
56 | &s3c_device_i2c5); | ||
57 | |||
58 | if (!npd->cfg_gpio) | ||
59 | npd->cfg_gpio = s3c_i2c5_cfg_gpio; | ||
60 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c new file mode 100644 index 00000000000..141d799944e --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c6.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c6.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 6 | ||
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 <linux/gfp.h> | ||
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_IIC6, | ||
29 | .end = S3C_PA_IIC6 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC6, | ||
34 | .end = IRQ_IIC6, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c6 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 6, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd) | ||
47 | { | ||
48 | struct s3c2410_platform_i2c *npd; | ||
49 | |||
50 | if (!pd) { | ||
51 | pd = &default_i2c_data; | ||
52 | pd->bus_num = 6; | ||
53 | } | ||
54 | |||
55 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
56 | &s3c_device_i2c6); | ||
57 | |||
58 | if (!npd->cfg_gpio) | ||
59 | npd->cfg_gpio = s3c_i2c6_cfg_gpio; | ||
60 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c new file mode 100644 index 00000000000..9dddcd1665b --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c7.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c7.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 7 | ||
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 <linux/gfp.h> | ||
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_IIC7, | ||
29 | .end = S3C_PA_IIC7 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC7, | ||
34 | .end = IRQ_IIC7, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c7 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 7, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd) | ||
47 | { | ||
48 | struct s3c2410_platform_i2c *npd; | ||
49 | |||
50 | if (!pd) { | ||
51 | pd = &default_i2c_data; | ||
52 | pd->bus_num = 7; | ||
53 | } | ||
54 | |||
55 | npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c), | ||
56 | &s3c_device_i2c7); | ||
57 | |||
58 | if (!npd->cfg_gpio) | ||
59 | npd->cfg_gpio = s3c_i2c7_cfg_gpio; | ||
60 | } | ||
diff --git a/arch/arm/plat-samsung/dev-ide.c b/arch/arm/plat-samsung/dev-ide.c new file mode 100644 index 00000000000..b497982795a --- /dev/null +++ b/arch/arm/plat-samsung/dev-ide.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-ide.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Samsung CF-ATA device definition. | ||
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 <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | |||
17 | #include <mach/map.h> | ||
18 | #include <plat/ata.h> | ||
19 | #include <plat/devs.h> | ||
20 | |||
21 | static struct resource s3c_cfcon_resource[] = { | ||
22 | [0] = { | ||
23 | .start = SAMSUNG_PA_CFCON, | ||
24 | .end = SAMSUNG_PA_CFCON + SZ_16K - 1, | ||
25 | .flags = IORESOURCE_MEM, | ||
26 | }, | ||
27 | [1] = { | ||
28 | .start = IRQ_CFCON, | ||
29 | .end = IRQ_CFCON, | ||
30 | .flags = IORESOURCE_IRQ, | ||
31 | }, | ||
32 | }; | ||
33 | |||
34 | struct platform_device s3c_device_cfcon = { | ||
35 | .id = 0, | ||
36 | .num_resources = ARRAY_SIZE(s3c_cfcon_resource), | ||
37 | .resource = s3c_cfcon_resource, | ||
38 | }; | ||
39 | |||
40 | void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata) | ||
41 | { | ||
42 | s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata), | ||
43 | &s3c_device_cfcon); | ||
44 | } | ||
diff --git a/arch/arm/plat-samsung/dev-keypad.c b/arch/arm/plat-samsung/dev-keypad.c new file mode 100644 index 00000000000..677c2d731b6 --- /dev/null +++ b/arch/arm/plat-samsung/dev-keypad.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-samsung/dev-keypad.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | #include <mach/irqs.h> | ||
16 | #include <mach/map.h> | ||
17 | #include <plat/cpu.h> | ||
18 | #include <plat/devs.h> | ||
19 | #include <plat/keypad.h> | ||
20 | |||
21 | static struct resource samsung_keypad_resources[] = { | ||
22 | [0] = { | ||
23 | .start = SAMSUNG_PA_KEYPAD, | ||
24 | .end = SAMSUNG_PA_KEYPAD + 0x20 - 1, | ||
25 | .flags = IORESOURCE_MEM, | ||
26 | }, | ||
27 | [1] = { | ||
28 | .start = IRQ_KEYPAD, | ||
29 | .end = IRQ_KEYPAD, | ||
30 | .flags = IORESOURCE_IRQ, | ||
31 | }, | ||
32 | }; | ||
33 | |||
34 | struct platform_device samsung_device_keypad = { | ||
35 | .name = "samsung-keypad", | ||
36 | .id = -1, | ||
37 | .num_resources = ARRAY_SIZE(samsung_keypad_resources), | ||
38 | .resource = samsung_keypad_resources, | ||
39 | }; | ||
40 | |||
41 | void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd) | ||
42 | { | ||
43 | struct samsung_keypad_platdata *npd; | ||
44 | |||
45 | npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata), | ||
46 | &samsung_device_keypad); | ||
47 | |||
48 | if (!npd->cfg_gpio) | ||
49 | npd->cfg_gpio = samsung_keypad_cfg_gpio; | ||
50 | } | ||
diff --git a/arch/arm/plat-samsung/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c new file mode 100644 index 00000000000..b8e30ec6ac2 --- /dev/null +++ b/arch/arm/plat-samsung/dev-nand.c | |||
@@ -0,0 +1,125 @@ | |||
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/gfp.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | #include <linux/mtd/mtd.h> | ||
14 | #include <linux/mtd/partitions.h> | ||
15 | |||
16 | #include <mach/map.h> | ||
17 | #include <plat/devs.h> | ||
18 | #include <plat/nand.h> | ||
19 | |||
20 | static struct resource s3c_nand_resource[] = { | ||
21 | [0] = { | ||
22 | .start = S3C_PA_NAND, | ||
23 | .end = S3C_PA_NAND + SZ_1M, | ||
24 | .flags = IORESOURCE_MEM, | ||
25 | } | ||
26 | }; | ||
27 | |||
28 | struct platform_device s3c_device_nand = { | ||
29 | .name = "s3c2410-nand", | ||
30 | .id = -1, | ||
31 | .num_resources = ARRAY_SIZE(s3c_nand_resource), | ||
32 | .resource = s3c_nand_resource, | ||
33 | }; | ||
34 | |||
35 | EXPORT_SYMBOL(s3c_device_nand); | ||
36 | |||
37 | /** | ||
38 | * s3c_nand_copy_set() - copy nand set data | ||
39 | * @set: The new structure, directly copied from the old. | ||
40 | * | ||
41 | * Copy all the fields from the NAND set field from what is probably __initdata | ||
42 | * to new kernel memory. The code returns 0 if the copy happened correctly or | ||
43 | * an error code for the calling function to display. | ||
44 | * | ||
45 | * Note, we currently do not try and look to see if we've already copied the | ||
46 | * data in a previous set. | ||
47 | */ | ||
48 | static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set) | ||
49 | { | ||
50 | void *ptr; | ||
51 | int size; | ||
52 | |||
53 | size = sizeof(struct mtd_partition) * set->nr_partitions; | ||
54 | if (size) { | ||
55 | ptr = kmemdup(set->partitions, size, GFP_KERNEL); | ||
56 | set->partitions = ptr; | ||
57 | |||
58 | if (!ptr) | ||
59 | return -ENOMEM; | ||
60 | } | ||
61 | |||
62 | if (set->nr_map && set->nr_chips) { | ||
63 | size = sizeof(int) * set->nr_chips; | ||
64 | ptr = kmemdup(set->nr_map, size, GFP_KERNEL); | ||
65 | set->nr_map = ptr; | ||
66 | |||
67 | if (!ptr) | ||
68 | return -ENOMEM; | ||
69 | } | ||
70 | |||
71 | if (set->ecc_layout) { | ||
72 | ptr = kmemdup(set->ecc_layout, | ||
73 | sizeof(struct nand_ecclayout), GFP_KERNEL); | ||
74 | set->ecc_layout = ptr; | ||
75 | |||
76 | if (!ptr) | ||
77 | return -ENOMEM; | ||
78 | } | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand) | ||
84 | { | ||
85 | struct s3c2410_platform_nand *npd; | ||
86 | int size; | ||
87 | int ret; | ||
88 | |||
89 | /* note, if we get a failure in allocation, we simply drop out of the | ||
90 | * function. If there is so little memory available at initialisation | ||
91 | * time then there is little chance the system is going to run. | ||
92 | */ | ||
93 | |||
94 | npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand), | ||
95 | &s3c_device_nand); | ||
96 | if (!npd) | ||
97 | return; | ||
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 | } | ||
diff --git a/arch/arm/plat-samsung/dev-onenand.c b/arch/arm/plat-samsung/dev-onenand.c new file mode 100644 index 00000000000..f54ae71f0cd --- /dev/null +++ b/arch/arm/plat-samsung/dev-onenand.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-samsung/dev-onenand.c | ||
3 | * | ||
4 | * Copyright (c) 2008-2010 Samsung Electronics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * | ||
7 | * S3C64XX/S5PC100 series device definition for OneNAND 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 | |||
17 | #include <mach/irqs.h> | ||
18 | #include <mach/map.h> | ||
19 | |||
20 | static struct resource s3c_onenand_resources[] = { | ||
21 | [0] = { | ||
22 | .start = S3C_PA_ONENAND, | ||
23 | .end = S3C_PA_ONENAND + 0x400 - 1, | ||
24 | .flags = IORESOURCE_MEM, | ||
25 | }, | ||
26 | [1] = { | ||
27 | .start = S3C_PA_ONENAND_BUF, | ||
28 | .end = S3C_PA_ONENAND_BUF + S3C_SZ_ONENAND_BUF - 1, | ||
29 | .flags = IORESOURCE_MEM, | ||
30 | }, | ||
31 | [2] = { | ||
32 | .start = IRQ_ONENAND, | ||
33 | .end = IRQ_ONENAND, | ||
34 | .flags = IORESOURCE_IRQ, | ||
35 | }, | ||
36 | }; | ||
37 | |||
38 | struct platform_device s3c_device_onenand = { | ||
39 | .name = "samsung-onenand", | ||
40 | .id = 0, | ||
41 | .num_resources = ARRAY_SIZE(s3c_onenand_resources), | ||
42 | .resource = s3c_onenand_resources, | ||
43 | }; | ||
diff --git a/arch/arm/plat-samsung/dev-pwm.c b/arch/arm/plat-samsung/dev-pwm.c new file mode 100644 index 00000000000..dab47b0e190 --- /dev/null +++ b/arch/arm/plat-samsung/dev-pwm.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-pwm.c | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Copyright (c) 2007 Ben Dooks | ||
7 | * Copyright (c) 2008 Simtec Electronics | ||
8 | * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> | ||
9 | * | ||
10 | * S3C series device definition for the PWM timer | ||
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 | #include <linux/kernel.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | #include <mach/irqs.h> | ||
21 | |||
22 | #include <plat/devs.h> | ||
23 | |||
24 | #define TIMER_RESOURCE_SIZE (1) | ||
25 | |||
26 | #define TIMER_RESOURCE(_tmr, _irq) \ | ||
27 | (struct resource [TIMER_RESOURCE_SIZE]) { \ | ||
28 | [0] = { \ | ||
29 | .start = _irq, \ | ||
30 | .end = _irq, \ | ||
31 | .flags = IORESOURCE_IRQ \ | ||
32 | } \ | ||
33 | } | ||
34 | |||
35 | #define DEFINE_S3C_TIMER(_tmr_no, _irq) \ | ||
36 | .name = "s3c24xx-pwm", \ | ||
37 | .id = _tmr_no, \ | ||
38 | .num_resources = TIMER_RESOURCE_SIZE, \ | ||
39 | .resource = TIMER_RESOURCE(_tmr_no, _irq), \ | ||
40 | |||
41 | /* | ||
42 | * since we already have an static mapping for the timer, | ||
43 | * we do not bother setting any IO resource for the base. | ||
44 | */ | ||
45 | |||
46 | struct platform_device s3c_device_timer[] = { | ||
47 | [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) }, | ||
48 | [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) }, | ||
49 | [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) }, | ||
50 | [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) }, | ||
51 | [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) }, | ||
52 | }; | ||
53 | EXPORT_SYMBOL(s3c_device_timer); | ||
diff --git a/arch/arm/plat-samsung/dev-rtc.c b/arch/arm/plat-samsung/dev-rtc.c new file mode 100644 index 00000000000..bf4e2267333 --- /dev/null +++ b/arch/arm/plat-samsung/dev-rtc.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-rtc.c | ||
2 | * | ||
3 | * Copyright 2009 by Maurus Cuelenaere <mcuelenaere@gmail.com> | ||
4 | * | ||
5 | * This program is free software; you 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 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <mach/irqs.h> | ||
15 | #include <mach/map.h> | ||
16 | |||
17 | #include <plat/devs.h> | ||
18 | |||
19 | static struct resource s3c_rtc_resource[] = { | ||
20 | [0] = { | ||
21 | .start = S3C_PA_RTC, | ||
22 | .end = S3C_PA_RTC + 0xff, | ||
23 | .flags = IORESOURCE_MEM, | ||
24 | }, | ||
25 | [1] = { | ||
26 | .start = IRQ_RTC_ALARM, | ||
27 | .end = IRQ_RTC_ALARM, | ||
28 | .flags = IORESOURCE_IRQ, | ||
29 | }, | ||
30 | [2] = { | ||
31 | .start = IRQ_RTC_TIC, | ||
32 | .end = IRQ_RTC_TIC, | ||
33 | .flags = IORESOURCE_IRQ | ||
34 | } | ||
35 | }; | ||
36 | |||
37 | struct platform_device s3c_device_rtc = { | ||
38 | .name = "s3c64xx-rtc", | ||
39 | .id = -1, | ||
40 | .num_resources = ARRAY_SIZE(s3c_rtc_resource), | ||
41 | .resource = s3c_rtc_resource, | ||
42 | }; | ||
43 | EXPORT_SYMBOL(s3c_device_rtc); | ||
diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c new file mode 100644 index 00000000000..82543f0248a --- /dev/null +++ b/arch/arm/plat-samsung/dev-ts.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* linux/arch/arm/mach-s3c64xx/dev-ts.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 | * Adapted by Maurus Cuelenaere for s3c64xx | ||
8 | * | ||
9 | * S3C64XX series device definition for touchscreen device | ||
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/string.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | #include <mach/irqs.h> | ||
21 | #include <mach/map.h> | ||
22 | |||
23 | #include <plat/devs.h> | ||
24 | #include <plat/ts.h> | ||
25 | |||
26 | static struct resource s3c_ts_resource[] = { | ||
27 | [0] = { | ||
28 | .start = SAMSUNG_PA_ADC, | ||
29 | .end = SAMSUNG_PA_ADC + SZ_256 - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_TC, | ||
34 | .end = IRQ_TC, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_ts = { | ||
40 | .name = "s3c64xx-ts", | ||
41 | .id = -1, | ||
42 | .num_resources = ARRAY_SIZE(s3c_ts_resource), | ||
43 | .resource = s3c_ts_resource, | ||
44 | }; | ||
45 | |||
46 | void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd) | ||
47 | { | ||
48 | s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info), | ||
49 | &s3c_device_ts); | ||
50 | } | ||
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 00000000000..33a844ab691 --- /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 00000000000..33fbaa96770 --- /dev/null +++ b/arch/arm/plat-samsung/dev-usb.c | |||
@@ -0,0 +1,65 @@ | |||
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/gfp.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <mach/irqs.h> | ||
20 | #include <mach/map.h> | ||
21 | |||
22 | #include <plat/devs.h> | ||
23 | #include <plat/usb-control.h> | ||
24 | |||
25 | static struct resource s3c_usb_resource[] = { | ||
26 | [0] = { | ||
27 | .start = S3C_PA_USBHOST, | ||
28 | .end = S3C_PA_USBHOST + 0x100 - 1, | ||
29 | .flags = IORESOURCE_MEM, | ||
30 | }, | ||
31 | [1] = { | ||
32 | .start = IRQ_USBH, | ||
33 | .end = IRQ_USBH, | ||
34 | .flags = IORESOURCE_IRQ, | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | static u64 s3c_device_usb_dmamask = 0xffffffffUL; | ||
39 | |||
40 | struct platform_device s3c_device_ohci = { | ||
41 | .name = "s3c2410-ohci", | ||
42 | .id = -1, | ||
43 | .num_resources = ARRAY_SIZE(s3c_usb_resource), | ||
44 | .resource = s3c_usb_resource, | ||
45 | .dev = { | ||
46 | .dma_mask = &s3c_device_usb_dmamask, | ||
47 | .coherent_dma_mask = 0xffffffffUL | ||
48 | } | ||
49 | }; | ||
50 | |||
51 | EXPORT_SYMBOL(s3c_device_ohci); | ||
52 | |||
53 | /** | ||
54 | * s3c_ohci_set_platdata - initialise OHCI device platform data | ||
55 | * @info: The platform data. | ||
56 | * | ||
57 | * This call copies the @info passed in and sets the device .platform_data | ||
58 | * field to that copy. The @info is copied so that the original can be marked | ||
59 | * __initdata. | ||
60 | */ | ||
61 | void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info) | ||
62 | { | ||
63 | s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info), | ||
64 | &s3c_device_ohci); | ||
65 | } | ||
diff --git a/arch/arm/plat-samsung/dev-wdt.c b/arch/arm/plat-samsung/dev-wdt.c new file mode 100644 index 00000000000..019b5b8cf14 --- /dev/null +++ b/arch/arm/plat-samsung/dev-wdt.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-wdt.c | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C series device definition for the watchdog 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 | #include <linux/kernel.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | #include <mach/irqs.h> | ||
17 | #include <mach/map.h> | ||
18 | |||
19 | #include <plat/devs.h> | ||
20 | |||
21 | static struct resource s3c_wdt_resource[] = { | ||
22 | [0] = { | ||
23 | .start = S3C_PA_WDT, | ||
24 | .end = S3C_PA_WDT + SZ_1K, | ||
25 | .flags = IORESOURCE_MEM, | ||
26 | }, | ||
27 | [1] = { | ||
28 | .start = IRQ_WDT, | ||
29 | .end = IRQ_WDT, | ||
30 | .flags = IORESOURCE_IRQ, | ||
31 | } | ||
32 | }; | ||
33 | |||
34 | struct platform_device s3c_device_wdt = { | ||
35 | .name = "s3c2410-wdt", | ||
36 | .id = -1, | ||
37 | .num_resources = ARRAY_SIZE(s3c_wdt_resource), | ||
38 | .resource = s3c_wdt_resource, | ||
39 | }; | ||
40 | EXPORT_SYMBOL(s3c_device_wdt); | ||
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c new file mode 100644 index 00000000000..1c0b0401594 --- /dev/null +++ b/arch/arm/plat-samsung/gpio-config.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* linux/arch/arm/plat-s3c/gpio-config.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008-2010 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 | s3c_gpio_lock(chip, flags); | ||
37 | ret = s3c_gpio_do_setcfg(chip, offset, config); | ||
38 | s3c_gpio_unlock(chip, flags); | ||
39 | |||
40 | return ret; | ||
41 | } | ||
42 | EXPORT_SYMBOL(s3c_gpio_cfgpin); | ||
43 | |||
44 | int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, | ||
45 | unsigned int cfg) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | for (; nr > 0; nr--, start++) { | ||
50 | ret = s3c_gpio_cfgpin(start, cfg); | ||
51 | if (ret != 0) | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range); | ||
58 | |||
59 | int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, | ||
60 | unsigned int cfg, s3c_gpio_pull_t pull) | ||
61 | { | ||
62 | int ret; | ||
63 | |||
64 | for (; nr > 0; nr--, start++) { | ||
65 | s3c_gpio_setpull(start, pull); | ||
66 | ret = s3c_gpio_cfgpin(start, cfg); | ||
67 | if (ret != 0) | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range); | ||
74 | |||
75 | unsigned s3c_gpio_getcfg(unsigned int pin) | ||
76 | { | ||
77 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
78 | unsigned long flags; | ||
79 | unsigned ret = 0; | ||
80 | int offset; | ||
81 | |||
82 | if (chip) { | ||
83 | offset = pin - chip->chip.base; | ||
84 | |||
85 | s3c_gpio_lock(chip, flags); | ||
86 | ret = s3c_gpio_do_getcfg(chip, offset); | ||
87 | s3c_gpio_unlock(chip, flags); | ||
88 | } | ||
89 | |||
90 | return ret; | ||
91 | } | ||
92 | EXPORT_SYMBOL(s3c_gpio_getcfg); | ||
93 | |||
94 | |||
95 | int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) | ||
96 | { | ||
97 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
98 | unsigned long flags; | ||
99 | int offset, ret; | ||
100 | |||
101 | if (!chip) | ||
102 | return -EINVAL; | ||
103 | |||
104 | offset = pin - chip->chip.base; | ||
105 | |||
106 | s3c_gpio_lock(chip, flags); | ||
107 | ret = s3c_gpio_do_setpull(chip, offset, pull); | ||
108 | s3c_gpio_unlock(chip, flags); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | EXPORT_SYMBOL(s3c_gpio_setpull); | ||
113 | |||
114 | s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin) | ||
115 | { | ||
116 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
117 | unsigned long flags; | ||
118 | int offset; | ||
119 | u32 pup = 0; | ||
120 | |||
121 | if (chip) { | ||
122 | offset = pin - chip->chip.base; | ||
123 | |||
124 | s3c_gpio_lock(chip, flags); | ||
125 | pup = s3c_gpio_do_getpull(chip, offset); | ||
126 | s3c_gpio_unlock(chip, flags); | ||
127 | } | ||
128 | |||
129 | return (__force s3c_gpio_pull_t)pup; | ||
130 | } | ||
131 | EXPORT_SYMBOL(s3c_gpio_getpull); | ||
132 | |||
133 | #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX | ||
134 | int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | ||
135 | unsigned int off, unsigned int cfg) | ||
136 | { | ||
137 | void __iomem *reg = chip->base; | ||
138 | unsigned int shift = off; | ||
139 | u32 con; | ||
140 | |||
141 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
142 | cfg &= 0xf; | ||
143 | |||
144 | /* Map output to 0, and SFN2 to 1 */ | ||
145 | cfg -= 1; | ||
146 | if (cfg > 1) | ||
147 | return -EINVAL; | ||
148 | |||
149 | cfg <<= shift; | ||
150 | } | ||
151 | |||
152 | con = __raw_readl(reg); | ||
153 | con &= ~(0x1 << shift); | ||
154 | con |= cfg; | ||
155 | __raw_writel(con, reg); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | ||
161 | unsigned int off) | ||
162 | { | ||
163 | u32 con; | ||
164 | |||
165 | con = __raw_readl(chip->base); | ||
166 | con >>= off; | ||
167 | con &= 1; | ||
168 | con++; | ||
169 | |||
170 | return S3C_GPIO_SFN(con); | ||
171 | } | ||
172 | |||
173 | int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
174 | unsigned int off, unsigned int cfg) | ||
175 | { | ||
176 | void __iomem *reg = chip->base; | ||
177 | unsigned int shift = off * 2; | ||
178 | u32 con; | ||
179 | |||
180 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
181 | cfg &= 0xf; | ||
182 | if (cfg > 3) | ||
183 | return -EINVAL; | ||
184 | |||
185 | cfg <<= shift; | ||
186 | } | ||
187 | |||
188 | con = __raw_readl(reg); | ||
189 | con &= ~(0x3 << shift); | ||
190 | con |= cfg; | ||
191 | __raw_writel(con, reg); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip, | ||
197 | unsigned int off) | ||
198 | { | ||
199 | u32 con; | ||
200 | |||
201 | con = __raw_readl(chip->base); | ||
202 | con >>= off * 2; | ||
203 | con &= 3; | ||
204 | |||
205 | /* this conversion works for IN and OUT as well as special mode */ | ||
206 | return S3C_GPIO_SPECIAL(con); | ||
207 | } | ||
208 | #endif | ||
209 | |||
210 | #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX | ||
211 | int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
212 | unsigned int off, unsigned int cfg) | ||
213 | { | ||
214 | void __iomem *reg = chip->base; | ||
215 | unsigned int shift = (off & 7) * 4; | ||
216 | u32 con; | ||
217 | |||
218 | if (off < 8 && chip->chip.ngpio > 8) | ||
219 | reg -= 4; | ||
220 | |||
221 | if (s3c_gpio_is_cfg_special(cfg)) { | ||
222 | cfg &= 0xf; | ||
223 | cfg <<= shift; | ||
224 | } | ||
225 | |||
226 | con = __raw_readl(reg); | ||
227 | con &= ~(0xf << shift); | ||
228 | con |= cfg; | ||
229 | __raw_writel(con, reg); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, | ||
235 | unsigned int off) | ||
236 | { | ||
237 | void __iomem *reg = chip->base; | ||
238 | unsigned int shift = (off & 7) * 4; | ||
239 | u32 con; | ||
240 | |||
241 | if (off < 8 && chip->chip.ngpio > 8) | ||
242 | reg -= 4; | ||
243 | |||
244 | con = __raw_readl(reg); | ||
245 | con >>= shift; | ||
246 | con &= 0xf; | ||
247 | |||
248 | /* this conversion works for IN and OUT as well as special mode */ | ||
249 | return S3C_GPIO_SPECIAL(con); | ||
250 | } | ||
251 | |||
252 | #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */ | ||
253 | |||
254 | #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN | ||
255 | int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip, | ||
256 | unsigned int off, s3c_gpio_pull_t pull) | ||
257 | { | ||
258 | void __iomem *reg = chip->base + 0x08; | ||
259 | int shift = off * 2; | ||
260 | u32 pup; | ||
261 | |||
262 | pup = __raw_readl(reg); | ||
263 | pup &= ~(3 << shift); | ||
264 | pup |= pull << shift; | ||
265 | __raw_writel(pup, reg); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, | ||
271 | unsigned int off) | ||
272 | { | ||
273 | void __iomem *reg = chip->base + 0x08; | ||
274 | int shift = off * 2; | ||
275 | u32 pup = __raw_readl(reg); | ||
276 | |||
277 | pup >>= shift; | ||
278 | pup &= 0x3; | ||
279 | return (__force s3c_gpio_pull_t)pup; | ||
280 | } | ||
281 | |||
282 | #ifdef CONFIG_S3C_GPIO_PULL_S3C2443 | ||
283 | int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip, | ||
284 | unsigned int off, s3c_gpio_pull_t pull) | ||
285 | { | ||
286 | switch (pull) { | ||
287 | case S3C_GPIO_PULL_NONE: | ||
288 | pull = 0x01; | ||
289 | break; | ||
290 | case S3C_GPIO_PULL_UP: | ||
291 | pull = 0x00; | ||
292 | break; | ||
293 | case S3C_GPIO_PULL_DOWN: | ||
294 | pull = 0x02; | ||
295 | break; | ||
296 | } | ||
297 | return s3c_gpio_setpull_updown(chip, off, pull); | ||
298 | } | ||
299 | |||
300 | s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip, | ||
301 | unsigned int off) | ||
302 | { | ||
303 | s3c_gpio_pull_t pull; | ||
304 | |||
305 | pull = s3c_gpio_getpull_updown(chip, off); | ||
306 | |||
307 | switch (pull) { | ||
308 | case 0x00: | ||
309 | pull = S3C_GPIO_PULL_UP; | ||
310 | break; | ||
311 | case 0x01: | ||
312 | case 0x03: | ||
313 | pull = S3C_GPIO_PULL_NONE; | ||
314 | break; | ||
315 | case 0x02: | ||
316 | pull = S3C_GPIO_PULL_DOWN; | ||
317 | break; | ||
318 | } | ||
319 | |||
320 | return pull; | ||
321 | } | ||
322 | #endif | ||
323 | #endif | ||
324 | |||
325 | #if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN) | ||
326 | static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip, | ||
327 | unsigned int off, s3c_gpio_pull_t pull, | ||
328 | s3c_gpio_pull_t updown) | ||
329 | { | ||
330 | void __iomem *reg = chip->base + 0x08; | ||
331 | u32 pup = __raw_readl(reg); | ||
332 | |||
333 | if (pull == updown) | ||
334 | pup &= ~(1 << off); | ||
335 | else if (pull == S3C_GPIO_PULL_NONE) | ||
336 | pup |= (1 << off); | ||
337 | else | ||
338 | return -EINVAL; | ||
339 | |||
340 | __raw_writel(pup, reg); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip, | ||
345 | unsigned int off, s3c_gpio_pull_t updown) | ||
346 | { | ||
347 | void __iomem *reg = chip->base + 0x08; | ||
348 | u32 pup = __raw_readl(reg); | ||
349 | |||
350 | pup &= (1 << off); | ||
351 | return pup ? S3C_GPIO_PULL_NONE : updown; | ||
352 | } | ||
353 | #endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */ | ||
354 | |||
355 | #ifdef CONFIG_S3C_GPIO_PULL_UP | ||
356 | s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, | ||
357 | unsigned int off) | ||
358 | { | ||
359 | return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP); | ||
360 | } | ||
361 | |||
362 | int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, | ||
363 | unsigned int off, s3c_gpio_pull_t pull) | ||
364 | { | ||
365 | return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP); | ||
366 | } | ||
367 | #endif /* CONFIG_S3C_GPIO_PULL_UP */ | ||
368 | |||
369 | #ifdef CONFIG_S3C_GPIO_PULL_DOWN | ||
370 | s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip, | ||
371 | unsigned int off) | ||
372 | { | ||
373 | return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN); | ||
374 | } | ||
375 | |||
376 | int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip, | ||
377 | unsigned int off, s3c_gpio_pull_t pull) | ||
378 | { | ||
379 | return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN); | ||
380 | } | ||
381 | #endif /* CONFIG_S3C_GPIO_PULL_DOWN */ | ||
382 | |||
383 | #ifdef CONFIG_S5P_GPIO_DRVSTR | ||
384 | s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) | ||
385 | { | ||
386 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
387 | unsigned int off; | ||
388 | void __iomem *reg; | ||
389 | int shift; | ||
390 | u32 drvstr; | ||
391 | |||
392 | if (!chip) | ||
393 | return -EINVAL; | ||
394 | |||
395 | off = pin - chip->chip.base; | ||
396 | shift = off * 2; | ||
397 | reg = chip->base + 0x0C; | ||
398 | |||
399 | drvstr = __raw_readl(reg); | ||
400 | drvstr = drvstr >> shift; | ||
401 | drvstr &= 0x3; | ||
402 | |||
403 | return (__force s5p_gpio_drvstr_t)drvstr; | ||
404 | } | ||
405 | EXPORT_SYMBOL(s5p_gpio_get_drvstr); | ||
406 | |||
407 | int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) | ||
408 | { | ||
409 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
410 | unsigned int off; | ||
411 | void __iomem *reg; | ||
412 | int shift; | ||
413 | u32 tmp; | ||
414 | |||
415 | if (!chip) | ||
416 | return -EINVAL; | ||
417 | |||
418 | off = pin - chip->chip.base; | ||
419 | shift = off * 2; | ||
420 | reg = chip->base + 0x0C; | ||
421 | |||
422 | tmp = __raw_readl(reg); | ||
423 | tmp &= ~(0x3 << shift); | ||
424 | tmp |= drvstr << shift; | ||
425 | |||
426 | __raw_writel(tmp, reg); | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | EXPORT_SYMBOL(s5p_gpio_set_drvstr); | ||
431 | #endif /* CONFIG_S5P_GPIO_DRVSTR */ | ||
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c new file mode 100644 index 00000000000..7743c4b8b2f --- /dev/null +++ b/arch/arm/plat-samsung/gpio.c | |||
@@ -0,0 +1,167 @@ | |||
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 | #include <linux/spinlock.h> | ||
19 | |||
20 | #include <plat/gpio-core.h> | ||
21 | |||
22 | #ifdef CONFIG_S3C_GPIO_TRACK | ||
23 | struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; | ||
24 | |||
25 | static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip) | ||
26 | { | ||
27 | unsigned int gpn; | ||
28 | int i; | ||
29 | |||
30 | gpn = chip->chip.base; | ||
31 | for (i = 0; i < chip->chip.ngpio; i++, gpn++) { | ||
32 | BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios)); | ||
33 | s3c_gpios[gpn] = chip; | ||
34 | } | ||
35 | } | ||
36 | #endif /* CONFIG_S3C_GPIO_TRACK */ | ||
37 | |||
38 | /* Default routines for controlling GPIO, based on the original S3C24XX | ||
39 | * GPIO functions which deal with the case where each gpio bank of the | ||
40 | * chip is as following: | ||
41 | * | ||
42 | * base + 0x00: Control register, 2 bits per gpio | ||
43 | * gpio n: 2 bits starting at (2*n) | ||
44 | * 00 = input, 01 = output, others mean special-function | ||
45 | * base + 0x04: Data register, 1 bit per gpio | ||
46 | * bit n: data bit n | ||
47 | */ | ||
48 | |||
49 | static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset) | ||
50 | { | ||
51 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
52 | void __iomem *base = ourchip->base; | ||
53 | unsigned long flags; | ||
54 | unsigned long con; | ||
55 | |||
56 | s3c_gpio_lock(ourchip, flags); | ||
57 | |||
58 | con = __raw_readl(base + 0x00); | ||
59 | con &= ~(3 << (offset * 2)); | ||
60 | |||
61 | __raw_writel(con, base + 0x00); | ||
62 | |||
63 | s3c_gpio_unlock(ourchip, flags); | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int s3c_gpiolib_output(struct gpio_chip *chip, | ||
68 | unsigned offset, int value) | ||
69 | { | ||
70 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
71 | void __iomem *base = ourchip->base; | ||
72 | unsigned long flags; | ||
73 | unsigned long dat; | ||
74 | unsigned long con; | ||
75 | |||
76 | s3c_gpio_lock(ourchip, flags); | ||
77 | |||
78 | dat = __raw_readl(base + 0x04); | ||
79 | dat &= ~(1 << offset); | ||
80 | if (value) | ||
81 | dat |= 1 << offset; | ||
82 | __raw_writel(dat, base + 0x04); | ||
83 | |||
84 | con = __raw_readl(base + 0x00); | ||
85 | con &= ~(3 << (offset * 2)); | ||
86 | con |= 1 << (offset * 2); | ||
87 | |||
88 | __raw_writel(con, base + 0x00); | ||
89 | __raw_writel(dat, base + 0x04); | ||
90 | |||
91 | s3c_gpio_unlock(ourchip, flags); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static void s3c_gpiolib_set(struct gpio_chip *chip, | ||
96 | unsigned offset, int value) | ||
97 | { | ||
98 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
99 | void __iomem *base = ourchip->base; | ||
100 | unsigned long flags; | ||
101 | unsigned long dat; | ||
102 | |||
103 | s3c_gpio_lock(ourchip, flags); | ||
104 | |||
105 | dat = __raw_readl(base + 0x04); | ||
106 | dat &= ~(1 << offset); | ||
107 | if (value) | ||
108 | dat |= 1 << offset; | ||
109 | __raw_writel(dat, base + 0x04); | ||
110 | |||
111 | s3c_gpio_unlock(ourchip, flags); | ||
112 | } | ||
113 | |||
114 | static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) | ||
115 | { | ||
116 | struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); | ||
117 | unsigned long val; | ||
118 | |||
119 | val = __raw_readl(ourchip->base + 0x04); | ||
120 | val >>= offset; | ||
121 | val &= 1; | ||
122 | |||
123 | return val; | ||
124 | } | ||
125 | |||
126 | __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) | ||
127 | { | ||
128 | struct gpio_chip *gc = &chip->chip; | ||
129 | int ret; | ||
130 | |||
131 | BUG_ON(!chip->base); | ||
132 | BUG_ON(!gc->label); | ||
133 | BUG_ON(!gc->ngpio); | ||
134 | |||
135 | spin_lock_init(&chip->lock); | ||
136 | |||
137 | if (!gc->direction_input) | ||
138 | gc->direction_input = s3c_gpiolib_input; | ||
139 | if (!gc->direction_output) | ||
140 | gc->direction_output = s3c_gpiolib_output; | ||
141 | if (!gc->set) | ||
142 | gc->set = s3c_gpiolib_set; | ||
143 | if (!gc->get) | ||
144 | gc->get = s3c_gpiolib_get; | ||
145 | |||
146 | #ifdef CONFIG_PM | ||
147 | if (chip->pm != NULL) { | ||
148 | if (!chip->pm->save || !chip->pm->resume) | ||
149 | printk(KERN_ERR "gpio: %s has missing PM functions\n", | ||
150 | gc->label); | ||
151 | } else | ||
152 | printk(KERN_ERR "gpio: %s has no PM function\n", gc->label); | ||
153 | #endif | ||
154 | |||
155 | /* gpiochip_add() prints own failure message on error. */ | ||
156 | ret = gpiochip_add(gc); | ||
157 | if (ret >= 0) | ||
158 | s3c_gpiolib_track(chip); | ||
159 | } | ||
160 | |||
161 | int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) | ||
162 | { | ||
163 | struct s3c_gpio_chip *s3c_chip = container_of(chip, | ||
164 | struct s3c_gpio_chip, chip); | ||
165 | |||
166 | return s3c_chip->irq_base + offset; | ||
167 | } | ||
diff --git a/arch/arm/plat-samsung/include/plat/ata.h b/arch/arm/plat-samsung/include/plat/ata.h new file mode 100644 index 00000000000..2a3855a8372 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/ata.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/ata.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Samsung CF-ATA 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_PLAT_ATA_H | ||
14 | #define __ASM_PLAT_ATA_H __FILE__ | ||
15 | |||
16 | /** | ||
17 | * struct s3c_ide_platdata - S3C IDE driver platform data. | ||
18 | * @setup_gpio: Setup the external GPIO pins to the right state for data | ||
19 | * transfer in true-ide mode. | ||
20 | */ | ||
21 | struct s3c_ide_platdata { | ||
22 | void (*setup_gpio)(void); | ||
23 | }; | ||
24 | |||
25 | /* | ||
26 | * s3c_ide_set_platdata() - Setup the platform specifc data for IDE driver. | ||
27 | * @pdata: Platform data for IDE driver. | ||
28 | */ | ||
29 | extern void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata); | ||
30 | |||
31 | /* architecture-specific IDE configuration */ | ||
32 | extern void s3c64xx_ide_setup_gpio(void); | ||
33 | extern void s5pc100_ide_setup_gpio(void); | ||
34 | extern void s5pv210_ide_setup_gpio(void); | ||
35 | |||
36 | #endif /*__ASM_PLAT_ATA_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 00000000000..aa9875f77c4 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/audio.h | |||
@@ -0,0 +1,59 @@ | |||
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 | * The machine init code calls s5p*_spdif_setup_gpio with | ||
21 | * one of these defines in order to select appropriate bank | ||
22 | * of GPIO for S/PDIF pins | ||
23 | */ | ||
24 | #define S5PC100_SPDIF_GPD 0 | ||
25 | #define S5PC100_SPDIF_GPG3 1 | ||
26 | extern void s5pc100_spdif_setup_gpio(int); | ||
27 | |||
28 | struct samsung_i2s { | ||
29 | /* If the Primary DAI has 5.1 Channels */ | ||
30 | #define QUIRK_PRI_6CHAN (1 << 0) | ||
31 | /* If the I2S block has a Stereo Overlay Channel */ | ||
32 | #define QUIRK_SEC_DAI (1 << 1) | ||
33 | /* | ||
34 | * If the I2S block has no internal prescalar or MUX (I2SMOD[10] bit) | ||
35 | * The Machine driver must provide suitably set clock to the I2S block. | ||
36 | */ | ||
37 | #define QUIRK_NO_MUXPSR (1 << 2) | ||
38 | #define QUIRK_NEED_RSTCLR (1 << 3) | ||
39 | /* Quirks of the I2S controller */ | ||
40 | u32 quirks; | ||
41 | |||
42 | /* | ||
43 | * Array of clock names that can be used to generate I2S signals. | ||
44 | * Also corresponds to clocks of I2SMOD[10] | ||
45 | */ | ||
46 | const char **src_clk; | ||
47 | dma_addr_t idma_addr; | ||
48 | }; | ||
49 | |||
50 | /** | ||
51 | * struct s3c_audio_pdata - common platform data for audio device drivers | ||
52 | * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode | ||
53 | */ | ||
54 | struct s3c_audio_pdata { | ||
55 | int (*cfg_gpio)(struct platform_device *); | ||
56 | union { | ||
57 | struct samsung_i2s i2s; | ||
58 | } type; | ||
59 | }; | ||
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 00000000000..c167e4429bc --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/hwmon.h | |||
@@ -0,0 +1,51 @@ | |||
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 | /** | ||
41 | * s3c_hwmon_set_platdata - Set platform data for S3C HWMON device | ||
42 | * @pd: Platform data to register to device. | ||
43 | * | ||
44 | * Register the given platform data for use with the S3C HWMON device. | ||
45 | * The call will copy the platform data, so the board definitions can | ||
46 | * make the structure itself __initdata. | ||
47 | */ | ||
48 | extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd); | ||
49 | |||
50 | #endif /* __ASM_ARCH_ADC_HWMON_H */ | ||
51 | |||
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 00000000000..56b0059439e --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/iic.h | |||
@@ -0,0 +1,76 @@ | |||
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 | extern void s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
58 | extern void s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
59 | extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
60 | extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
61 | extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
62 | extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
63 | |||
64 | /* defined by architecture to configure gpio */ | ||
65 | extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); | ||
66 | extern void s3c_i2c1_cfg_gpio(struct platform_device *dev); | ||
67 | extern void s3c_i2c2_cfg_gpio(struct platform_device *dev); | ||
68 | extern void s3c_i2c3_cfg_gpio(struct platform_device *dev); | ||
69 | extern void s3c_i2c4_cfg_gpio(struct platform_device *dev); | ||
70 | extern void s3c_i2c5_cfg_gpio(struct platform_device *dev); | ||
71 | extern void s3c_i2c6_cfg_gpio(struct platform_device *dev); | ||
72 | extern void s3c_i2c7_cfg_gpio(struct platform_device *dev); | ||
73 | |||
74 | extern struct s3c2410_platform_i2c default_i2c_data; | ||
75 | |||
76 | #endif /* __ASM_ARCH_IIC_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 00000000000..b64115fa93a --- /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/pd.h b/arch/arm/plat-samsung/include/plat/pd.h new file mode 100644 index 00000000000..abb4bc32716 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/pd.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/pd.h | ||
2 | * | ||
3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.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 __ASM_PLAT_SAMSUNG_PD_H | ||
12 | #define __ASM_PLAT_SAMSUNG_PD_H __FILE__ | ||
13 | |||
14 | struct samsung_pd_info { | ||
15 | int (*enable)(struct device *dev); | ||
16 | int (*disable)(struct device *dev); | ||
17 | void __iomem *base; | ||
18 | }; | ||
19 | |||
20 | enum exynos4_pd_block { | ||
21 | PD_MFC, | ||
22 | PD_G3D, | ||
23 | PD_LCD0, | ||
24 | PD_LCD1, | ||
25 | PD_TV, | ||
26 | PD_CAM, | ||
27 | PD_GPS | ||
28 | }; | ||
29 | |||
30 | #endif /* __ASM_PLAT_SAMSUNG_PD_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/pll6553x.h b/arch/arm/plat-samsung/include/plat/pll6553x.h new file mode 100644 index 00000000000..b8b7e1d884f --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/pll6553x.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/pll6553x.h | ||
2 | * partially from arch/arm/mach-s3c64xx/include/mach/pll.h | ||
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 PLL6553x PLL 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 | /* S3C6400 and compatible (S3C2416, etc.) EPLL code */ | ||
17 | |||
18 | #define PLL6553X_MDIV_MASK ((1 << (23-16)) - 1) | ||
19 | #define PLL6553X_PDIV_MASK ((1 << (13-8)) - 1) | ||
20 | #define PLL6553X_SDIV_MASK ((1 << (2-0)) - 1) | ||
21 | #define PLL6553X_MDIV_SHIFT (16) | ||
22 | #define PLL6553X_PDIV_SHIFT (8) | ||
23 | #define PLL6553X_SDIV_SHIFT (0) | ||
24 | #define PLL6553X_KDIV_MASK (0xffff) | ||
25 | |||
26 | static inline unsigned long s3c_get_pll6553x(unsigned long baseclk, | ||
27 | u32 pll0, u32 pll1) | ||
28 | { | ||
29 | unsigned long result; | ||
30 | u32 mdiv, pdiv, sdiv, kdiv; | ||
31 | u64 tmp; | ||
32 | |||
33 | mdiv = (pll0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK; | ||
34 | pdiv = (pll0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK; | ||
35 | sdiv = (pll0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK; | ||
36 | kdiv = pll1 & PLL6553X_KDIV_MASK; | ||
37 | |||
38 | /* We need to multiple baseclk by mdiv (the integer part) and kdiv | ||
39 | * which is in 2^16ths, so shift mdiv up (does not overflow) and | ||
40 | * add kdiv before multiplying. The use of tmp is to avoid any | ||
41 | * overflows before shifting bac down into result when multipling | ||
42 | * by the mdiv and kdiv pair. | ||
43 | */ | ||
44 | |||
45 | tmp = baseclk; | ||
46 | tmp *= (mdiv << 16) + kdiv; | ||
47 | do_div(tmp, (pdiv << sdiv)); | ||
48 | result = tmp >> 16; | ||
49 | |||
50 | return result; | ||
51 | } | ||
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 00000000000..4c3647f8005 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h | |||
@@ -0,0 +1,159 @@ | |||
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_BASE (0x40) | ||
44 | |||
45 | #define VIDINTCON0 (0x130) | ||
46 | |||
47 | /* WINCONx */ | ||
48 | |||
49 | #define WINCONx_CSCWIDTH_MASK (0x3 << 26) | ||
50 | #define WINCONx_CSCWIDTH_SHIFT (26) | ||
51 | #define WINCONx_CSCWIDTH_WIDE (0x0 << 26) | ||
52 | #define WINCONx_CSCWIDTH_NARROW (0x3 << 26) | ||
53 | |||
54 | #define WINCONx_ENLOCAL (1 << 22) | ||
55 | #define WINCONx_BUFSTATUS (1 << 21) | ||
56 | #define WINCONx_BUFSEL (1 << 20) | ||
57 | #define WINCONx_BUFAUTOEN (1 << 19) | ||
58 | #define WINCONx_YCbCr (1 << 13) | ||
59 | |||
60 | #define WINCON1_LOCALSEL_CAMIF (1 << 23) | ||
61 | |||
62 | #define WINCON2_LOCALSEL_CAMIF (1 << 23) | ||
63 | #define WINCON2_BLD_PIX (1 << 6) | ||
64 | |||
65 | #define WINCON2_ALPHA_SEL (1 << 1) | ||
66 | #define WINCON2_BPPMODE_MASK (0xf << 2) | ||
67 | #define WINCON2_BPPMODE_SHIFT (2) | ||
68 | #define WINCON2_BPPMODE_1BPP (0x0 << 2) | ||
69 | #define WINCON2_BPPMODE_2BPP (0x1 << 2) | ||
70 | #define WINCON2_BPPMODE_4BPP (0x2 << 2) | ||
71 | #define WINCON2_BPPMODE_8BPP_1232 (0x4 << 2) | ||
72 | #define WINCON2_BPPMODE_16BPP_565 (0x5 << 2) | ||
73 | #define WINCON2_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
74 | #define WINCON2_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
75 | #define WINCON2_BPPMODE_18BPP_666 (0x8 << 2) | ||
76 | #define WINCON2_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
77 | #define WINCON2_BPPMODE_19BPP_A1666 (0xa << 2) | ||
78 | #define WINCON2_BPPMODE_24BPP_888 (0xb << 2) | ||
79 | #define WINCON2_BPPMODE_24BPP_A1887 (0xc << 2) | ||
80 | #define WINCON2_BPPMODE_25BPP_A1888 (0xd << 2) | ||
81 | #define WINCON2_BPPMODE_28BPP_A4888 (0xd << 2) | ||
82 | |||
83 | #define WINCON3_BLD_PIX (1 << 6) | ||
84 | |||
85 | #define WINCON3_ALPHA_SEL (1 << 1) | ||
86 | #define WINCON3_BPPMODE_MASK (0xf << 2) | ||
87 | #define WINCON3_BPPMODE_SHIFT (2) | ||
88 | #define WINCON3_BPPMODE_1BPP (0x0 << 2) | ||
89 | #define WINCON3_BPPMODE_2BPP (0x1 << 2) | ||
90 | #define WINCON3_BPPMODE_4BPP (0x2 << 2) | ||
91 | #define WINCON3_BPPMODE_16BPP_565 (0x5 << 2) | ||
92 | #define WINCON3_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
93 | #define WINCON3_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
94 | #define WINCON3_BPPMODE_18BPP_666 (0x8 << 2) | ||
95 | #define WINCON3_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
96 | #define WINCON3_BPPMODE_19BPP_A1666 (0xa << 2) | ||
97 | #define WINCON3_BPPMODE_24BPP_888 (0xb << 2) | ||
98 | #define WINCON3_BPPMODE_24BPP_A1887 (0xc << 2) | ||
99 | #define WINCON3_BPPMODE_25BPP_A1888 (0xd << 2) | ||
100 | #define WINCON3_BPPMODE_28BPP_A4888 (0xd << 2) | ||
101 | |||
102 | #define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5) | ||
103 | #define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5) | ||
104 | #define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5) | ||
105 | |||
106 | #define DITHMODE (0x170) | ||
107 | #define WINxMAP(_win) (0x180 + ((_win) * 4)) | ||
108 | |||
109 | |||
110 | #define DITHMODE_R_POS_MASK (0x3 << 5) | ||
111 | #define DITHMODE_R_POS_SHIFT (5) | ||
112 | #define DITHMODE_R_POS_8BIT (0x0 << 5) | ||
113 | #define DITHMODE_R_POS_6BIT (0x1 << 5) | ||
114 | #define DITHMODE_R_POS_5BIT (0x2 << 5) | ||
115 | |||
116 | #define DITHMODE_G_POS_MASK (0x3 << 3) | ||
117 | #define DITHMODE_G_POS_SHIFT (3) | ||
118 | #define DITHMODE_G_POS_8BIT (0x0 << 3) | ||
119 | #define DITHMODE_G_POS_6BIT (0x1 << 3) | ||
120 | #define DITHMODE_G_POS_5BIT (0x2 << 3) | ||
121 | |||
122 | #define DITHMODE_B_POS_MASK (0x3 << 1) | ||
123 | #define DITHMODE_B_POS_SHIFT (1) | ||
124 | #define DITHMODE_B_POS_8BIT (0x0 << 1) | ||
125 | #define DITHMODE_B_POS_6BIT (0x1 << 1) | ||
126 | #define DITHMODE_B_POS_5BIT (0x2 << 1) | ||
127 | |||
128 | #define DITHMODE_DITH_EN (1 << 0) | ||
129 | |||
130 | #define WPALCON (0x1A0) | ||
131 | |||
132 | /* Palette control */ | ||
133 | /* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L), | ||
134 | * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */ | ||
135 | #define WPALCON_W4PAL_16BPP_A555 (1 << 8) | ||
136 | #define WPALCON_W3PAL_16BPP_A555 (1 << 7) | ||
137 | #define WPALCON_W2PAL_16BPP_A555 (1 << 6) | ||
138 | |||
139 | |||
140 | /* Notes on per-window bpp settings | ||
141 | * | ||
142 | * Value Win0 Win1 Win2 Win3 Win 4 | ||
143 | * 0000 1(P) 1(P) 1(P) 1(P) 1(P) | ||
144 | * 0001 2(P) 2(P) 2(P) 2(P) 2(P) | ||
145 | * 0010 4(P) 4(P) 4(P) 4(P) -none- | ||
146 | * 0011 8(P) 8(P) -none- -none- -none- | ||
147 | * 0100 -none- 8(A232) 8(A232) -none- -none- | ||
148 | * 0101 16(565) 16(565) 16(565) 16(565) 16(565) | ||
149 | * 0110 -none- 16(A555) 16(A555) 16(A555) 16(A555) | ||
150 | * 0111 16(I555) 16(I565) 16(I555) 16(I555) 16(I555) | ||
151 | * 1000 18(666) 18(666) 18(666) 18(666) 18(666) | ||
152 | * 1001 -none- 18(A665) 18(A665) 18(A665) 16(A665) | ||
153 | * 1010 -none- 19(A666) 19(A666) 19(A666) 19(A666) | ||
154 | * 1011 24(888) 24(888) 24(888) 24(888) 24(888) | ||
155 | * 1100 -none- 24(A887) 24(A887) 24(A887) 24(A887) | ||
156 | * 1101 -none- 25(A888) 25(A888) 25(A888) 25(A888) | ||
157 | * 1110 -none- -none- -none- -none- -none- | ||
158 | * 1111 -none- -none- -none- -none- -none- | ||
159 | */ | ||
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 00000000000..8f39aa5b26e --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-fb.h | |||
@@ -0,0 +1,386 @@ | |||
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 | /* PRTCON (S3C6410, S5PC100) | ||
116 | * Might not be present in the S3C6410 documentation, | ||
117 | * but tests prove it's there almost for sure; shouldn't hurt in any case. | ||
118 | */ | ||
119 | #define PRTCON (0x0c) | ||
120 | #define PRTCON_PROTECT (1 << 11) | ||
121 | |||
122 | /* VIDTCON0 */ | ||
123 | |||
124 | #define VIDTCON0_VBPDE_MASK (0xff << 24) | ||
125 | #define VIDTCON0_VBPDE_SHIFT (24) | ||
126 | #define VIDTCON0_VBPDE_LIMIT (0xff) | ||
127 | #define VIDTCON0_VBPDE(_x) ((_x) << 24) | ||
128 | |||
129 | #define VIDTCON0_VBPD_MASK (0xff << 16) | ||
130 | #define VIDTCON0_VBPD_SHIFT (16) | ||
131 | #define VIDTCON0_VBPD_LIMIT (0xff) | ||
132 | #define VIDTCON0_VBPD(_x) ((_x) << 16) | ||
133 | |||
134 | #define VIDTCON0_VFPD_MASK (0xff << 8) | ||
135 | #define VIDTCON0_VFPD_SHIFT (8) | ||
136 | #define VIDTCON0_VFPD_LIMIT (0xff) | ||
137 | #define VIDTCON0_VFPD(_x) ((_x) << 8) | ||
138 | |||
139 | #define VIDTCON0_VSPW_MASK (0xff << 0) | ||
140 | #define VIDTCON0_VSPW_SHIFT (0) | ||
141 | #define VIDTCON0_VSPW_LIMIT (0xff) | ||
142 | #define VIDTCON0_VSPW(_x) ((_x) << 0) | ||
143 | |||
144 | /* VIDTCON1 */ | ||
145 | |||
146 | #define VIDTCON1_VFPDE_MASK (0xff << 24) | ||
147 | #define VIDTCON1_VFPDE_SHIFT (24) | ||
148 | #define VIDTCON1_VFPDE_LIMIT (0xff) | ||
149 | #define VIDTCON1_VFPDE(_x) ((_x) << 24) | ||
150 | |||
151 | #define VIDTCON1_HBPD_MASK (0xff << 16) | ||
152 | #define VIDTCON1_HBPD_SHIFT (16) | ||
153 | #define VIDTCON1_HBPD_LIMIT (0xff) | ||
154 | #define VIDTCON1_HBPD(_x) ((_x) << 16) | ||
155 | |||
156 | #define VIDTCON1_HFPD_MASK (0xff << 8) | ||
157 | #define VIDTCON1_HFPD_SHIFT (8) | ||
158 | #define VIDTCON1_HFPD_LIMIT (0xff) | ||
159 | #define VIDTCON1_HFPD(_x) ((_x) << 8) | ||
160 | |||
161 | #define VIDTCON1_HSPW_MASK (0xff << 0) | ||
162 | #define VIDTCON1_HSPW_SHIFT (0) | ||
163 | #define VIDTCON1_HSPW_LIMIT (0xff) | ||
164 | #define VIDTCON1_HSPW(_x) ((_x) << 0) | ||
165 | |||
166 | #define VIDTCON2 (0x18) | ||
167 | #define VIDTCON2_LINEVAL_MASK (0x7ff << 11) | ||
168 | #define VIDTCON2_LINEVAL_SHIFT (11) | ||
169 | #define VIDTCON2_LINEVAL_LIMIT (0x7ff) | ||
170 | #define VIDTCON2_LINEVAL(_x) ((_x) << 11) | ||
171 | |||
172 | #define VIDTCON2_HOZVAL_MASK (0x7ff << 0) | ||
173 | #define VIDTCON2_HOZVAL_SHIFT (0) | ||
174 | #define VIDTCON2_HOZVAL_LIMIT (0x7ff) | ||
175 | #define VIDTCON2_HOZVAL(_x) ((_x) << 0) | ||
176 | |||
177 | /* WINCONx */ | ||
178 | |||
179 | |||
180 | #define WINCONx_BITSWP (1 << 18) | ||
181 | #define WINCONx_BYTSWP (1 << 17) | ||
182 | #define WINCONx_HAWSWP (1 << 16) | ||
183 | #define WINCONx_WSWP (1 << 15) | ||
184 | #define WINCONx_BURSTLEN_MASK (0x3 << 9) | ||
185 | #define WINCONx_BURSTLEN_SHIFT (9) | ||
186 | #define WINCONx_BURSTLEN_16WORD (0x0 << 9) | ||
187 | #define WINCONx_BURSTLEN_8WORD (0x1 << 9) | ||
188 | #define WINCONx_BURSTLEN_4WORD (0x2 << 9) | ||
189 | |||
190 | #define WINCONx_ENWIN (1 << 0) | ||
191 | #define WINCON0_BPPMODE_MASK (0xf << 2) | ||
192 | #define WINCON0_BPPMODE_SHIFT (2) | ||
193 | #define WINCON0_BPPMODE_1BPP (0x0 << 2) | ||
194 | #define WINCON0_BPPMODE_2BPP (0x1 << 2) | ||
195 | #define WINCON0_BPPMODE_4BPP (0x2 << 2) | ||
196 | #define WINCON0_BPPMODE_8BPP_PALETTE (0x3 << 2) | ||
197 | #define WINCON0_BPPMODE_16BPP_565 (0x5 << 2) | ||
198 | #define WINCON0_BPPMODE_16BPP_1555 (0x7 << 2) | ||
199 | #define WINCON0_BPPMODE_18BPP_666 (0x8 << 2) | ||
200 | #define WINCON0_BPPMODE_24BPP_888 (0xb << 2) | ||
201 | |||
202 | #define WINCON1_BLD_PIX (1 << 6) | ||
203 | |||
204 | #define WINCON1_ALPHA_SEL (1 << 1) | ||
205 | #define WINCON1_BPPMODE_MASK (0xf << 2) | ||
206 | #define WINCON1_BPPMODE_SHIFT (2) | ||
207 | #define WINCON1_BPPMODE_1BPP (0x0 << 2) | ||
208 | #define WINCON1_BPPMODE_2BPP (0x1 << 2) | ||
209 | #define WINCON1_BPPMODE_4BPP (0x2 << 2) | ||
210 | #define WINCON1_BPPMODE_8BPP_PALETTE (0x3 << 2) | ||
211 | #define WINCON1_BPPMODE_8BPP_1232 (0x4 << 2) | ||
212 | #define WINCON1_BPPMODE_16BPP_565 (0x5 << 2) | ||
213 | #define WINCON1_BPPMODE_16BPP_A1555 (0x6 << 2) | ||
214 | #define WINCON1_BPPMODE_16BPP_I1555 (0x7 << 2) | ||
215 | #define WINCON1_BPPMODE_18BPP_666 (0x8 << 2) | ||
216 | #define WINCON1_BPPMODE_18BPP_A1665 (0x9 << 2) | ||
217 | #define WINCON1_BPPMODE_19BPP_A1666 (0xa << 2) | ||
218 | #define WINCON1_BPPMODE_24BPP_888 (0xb << 2) | ||
219 | #define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2) | ||
220 | #define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2) | ||
221 | #define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2) | ||
222 | |||
223 | /* S5PV210 */ | ||
224 | #define SHADOWCON (0x34) | ||
225 | #define SHADOWCON_WINx_PROTECT(_win) (1 << (10 + (_win))) | ||
226 | /* DMA channels (all windows) */ | ||
227 | #define SHADOWCON_CHx_ENABLE(_win) (1 << (_win)) | ||
228 | /* Local input channels (windows 0-2) */ | ||
229 | #define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win))) | ||
230 | |||
231 | #define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) | ||
232 | #define VIDOSDxA_TOPLEFT_X_SHIFT (11) | ||
233 | #define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff) | ||
234 | #define VIDOSDxA_TOPLEFT_X(_x) ((_x) << 11) | ||
235 | |||
236 | #define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0) | ||
237 | #define VIDOSDxA_TOPLEFT_Y_SHIFT (0) | ||
238 | #define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff) | ||
239 | #define VIDOSDxA_TOPLEFT_Y(_x) ((_x) << 0) | ||
240 | |||
241 | #define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11) | ||
242 | #define VIDOSDxB_BOTRIGHT_X_SHIFT (11) | ||
243 | #define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff) | ||
244 | #define VIDOSDxB_BOTRIGHT_X(_x) ((_x) << 11) | ||
245 | |||
246 | #define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0) | ||
247 | #define VIDOSDxB_BOTRIGHT_Y_SHIFT (0) | ||
248 | #define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff) | ||
249 | #define VIDOSDxB_BOTRIGHT_Y(_x) ((_x) << 0) | ||
250 | |||
251 | /* For VIDOSD[1..4]C */ | ||
252 | #define VIDISD14C_ALPHA0_R(_x) ((_x) << 20) | ||
253 | #define VIDISD14C_ALPHA0_G_MASK (0xf << 16) | ||
254 | #define VIDISD14C_ALPHA0_G_SHIFT (16) | ||
255 | #define VIDISD14C_ALPHA0_G_LIMIT (0xf) | ||
256 | #define VIDISD14C_ALPHA0_G(_x) ((_x) << 16) | ||
257 | #define VIDISD14C_ALPHA0_B_MASK (0xf << 12) | ||
258 | #define VIDISD14C_ALPHA0_B_SHIFT (12) | ||
259 | #define VIDISD14C_ALPHA0_B_LIMIT (0xf) | ||
260 | #define VIDISD14C_ALPHA0_B(_x) ((_x) << 12) | ||
261 | #define VIDISD14C_ALPHA1_R_MASK (0xf << 8) | ||
262 | #define VIDISD14C_ALPHA1_R_SHIFT (8) | ||
263 | #define VIDISD14C_ALPHA1_R_LIMIT (0xf) | ||
264 | #define VIDISD14C_ALPHA1_R(_x) ((_x) << 8) | ||
265 | #define VIDISD14C_ALPHA1_G_MASK (0xf << 4) | ||
266 | #define VIDISD14C_ALPHA1_G_SHIFT (4) | ||
267 | #define VIDISD14C_ALPHA1_G_LIMIT (0xf) | ||
268 | #define VIDISD14C_ALPHA1_G(_x) ((_x) << 4) | ||
269 | #define VIDISD14C_ALPHA1_B_MASK (0xf << 0) | ||
270 | #define VIDISD14C_ALPHA1_B_SHIFT (0) | ||
271 | #define VIDISD14C_ALPHA1_B_LIMIT (0xf) | ||
272 | #define VIDISD14C_ALPHA1_B(_x) ((_x) << 0) | ||
273 | |||
274 | /* Video buffer addresses */ | ||
275 | #define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8)) | ||
276 | #define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8)) | ||
277 | #define VIDW_BUF_END(_buff) (0xD0 + ((_buff) * 8)) | ||
278 | #define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) | ||
279 | #define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4)) | ||
280 | |||
281 | #define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13) | ||
282 | #define VIDW_BUF_SIZE_OFFSET_SHIFT (13) | ||
283 | #define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff) | ||
284 | #define VIDW_BUF_SIZE_OFFSET(_x) ((_x) << 13) | ||
285 | |||
286 | #define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0) | ||
287 | #define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0) | ||
288 | #define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff) | ||
289 | #define VIDW_BUF_SIZE_PAGEWIDTH(_x) ((_x) << 0) | ||
290 | |||
291 | /* Interrupt controls and status */ | ||
292 | |||
293 | #define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20) | ||
294 | #define VIDINTCON0_FIFOINTERVAL_SHIFT (20) | ||
295 | #define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f) | ||
296 | #define VIDINTCON0_FIFOINTERVAL(_x) ((_x) << 20) | ||
297 | |||
298 | #define VIDINTCON0_INT_SYSMAINCON (1 << 19) | ||
299 | #define VIDINTCON0_INT_SYSSUBCON (1 << 18) | ||
300 | #define VIDINTCON0_INT_I80IFDONE (1 << 17) | ||
301 | |||
302 | #define VIDINTCON0_FRAMESEL0_MASK (0x3 << 15) | ||
303 | #define VIDINTCON0_FRAMESEL0_SHIFT (15) | ||
304 | #define VIDINTCON0_FRAMESEL0_BACKPORCH (0x0 << 15) | ||
305 | #define VIDINTCON0_FRAMESEL0_VSYNC (0x1 << 15) | ||
306 | #define VIDINTCON0_FRAMESEL0_ACTIVE (0x2 << 15) | ||
307 | #define VIDINTCON0_FRAMESEL0_FRONTPORCH (0x3 << 15) | ||
308 | |||
309 | #define VIDINTCON0_FRAMESEL1 (1 << 13) | ||
310 | #define VIDINTCON0_FRAMESEL1_MASK (0x3 << 13) | ||
311 | #define VIDINTCON0_FRAMESEL1_NONE (0x0 << 13) | ||
312 | #define VIDINTCON0_FRAMESEL1_BACKPORCH (0x1 << 13) | ||
313 | #define VIDINTCON0_FRAMESEL1_VSYNC (0x2 << 13) | ||
314 | #define VIDINTCON0_FRAMESEL1_FRONTPORCH (0x3 << 13) | ||
315 | |||
316 | #define VIDINTCON0_INT_FRAME (1 << 12) | ||
317 | #define VIDINTCON0_FIFIOSEL_MASK (0x7f << 5) | ||
318 | #define VIDINTCON0_FIFIOSEL_SHIFT (5) | ||
319 | #define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5) | ||
320 | #define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5) | ||
321 | |||
322 | #define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2) | ||
323 | #define VIDINTCON0_FIFOLEVEL_SHIFT (2) | ||
324 | #define VIDINTCON0_FIFOLEVEL_TO25PC (0x0 << 2) | ||
325 | #define VIDINTCON0_FIFOLEVEL_TO50PC (0x1 << 2) | ||
326 | #define VIDINTCON0_FIFOLEVEL_TO75PC (0x2 << 2) | ||
327 | #define VIDINTCON0_FIFOLEVEL_EMPTY (0x3 << 2) | ||
328 | #define VIDINTCON0_FIFOLEVEL_FULL (0x4 << 2) | ||
329 | |||
330 | #define VIDINTCON0_INT_FIFO_MASK (0x3 << 0) | ||
331 | #define VIDINTCON0_INT_FIFO_SHIFT (0) | ||
332 | #define VIDINTCON0_INT_ENABLE (1 << 0) | ||
333 | |||
334 | #define VIDINTCON1 (0x134) | ||
335 | #define VIDINTCON1_INT_I180 (1 << 2) | ||
336 | #define VIDINTCON1_INT_FRAME (1 << 1) | ||
337 | #define VIDINTCON1_INT_FIFO (1 << 0) | ||
338 | |||
339 | /* Window colour-key control registers */ | ||
340 | #define WKEYCON (0x140) /* 6410,V210 */ | ||
341 | |||
342 | #define WKEYCON0 (0x00) | ||
343 | #define WKEYCON1 (0x04) | ||
344 | |||
345 | #define WxKEYCON0_KEYBL_EN (1 << 26) | ||
346 | #define WxKEYCON0_KEYEN_F (1 << 25) | ||
347 | #define WxKEYCON0_DIRCON (1 << 24) | ||
348 | #define WxKEYCON0_COMPKEY_MASK (0xffffff << 0) | ||
349 | #define WxKEYCON0_COMPKEY_SHIFT (0) | ||
350 | #define WxKEYCON0_COMPKEY_LIMIT (0xffffff) | ||
351 | #define WxKEYCON0_COMPKEY(_x) ((_x) << 0) | ||
352 | #define WxKEYCON1_COLVAL_MASK (0xffffff << 0) | ||
353 | #define WxKEYCON1_COLVAL_SHIFT (0) | ||
354 | #define WxKEYCON1_COLVAL_LIMIT (0xffffff) | ||
355 | #define WxKEYCON1_COLVAL(_x) ((_x) << 0) | ||
356 | |||
357 | |||
358 | /* Window blanking (MAP) */ | ||
359 | |||
360 | #define WINxMAP_MAP (1 << 24) | ||
361 | #define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0) | ||
362 | #define WINxMAP_MAP_COLOUR_SHIFT (0) | ||
363 | #define WINxMAP_MAP_COLOUR_LIMIT (0xffffff) | ||
364 | #define WINxMAP_MAP_COLOUR(_x) ((_x) << 0) | ||
365 | |||
366 | #define WPALCON_PAL_UPDATE (1 << 9) | ||
367 | #define WPALCON_W1PAL_MASK (0x7 << 3) | ||
368 | #define WPALCON_W1PAL_SHIFT (3) | ||
369 | #define WPALCON_W1PAL_25BPP_A888 (0x0 << 3) | ||
370 | #define WPALCON_W1PAL_24BPP (0x1 << 3) | ||
371 | #define WPALCON_W1PAL_19BPP_A666 (0x2 << 3) | ||
372 | #define WPALCON_W1PAL_18BPP_A665 (0x3 << 3) | ||
373 | #define WPALCON_W1PAL_18BPP (0x4 << 3) | ||
374 | #define WPALCON_W1PAL_16BPP_A555 (0x5 << 3) | ||
375 | #define WPALCON_W1PAL_16BPP_565 (0x6 << 3) | ||
376 | |||
377 | #define WPALCON_W0PAL_MASK (0x7 << 0) | ||
378 | #define WPALCON_W0PAL_SHIFT (0) | ||
379 | #define WPALCON_W0PAL_25BPP_A888 (0x0 << 0) | ||
380 | #define WPALCON_W0PAL_24BPP (0x1 << 0) | ||
381 | #define WPALCON_W0PAL_19BPP_A666 (0x2 << 0) | ||
382 | #define WPALCON_W0PAL_18BPP_A665 (0x3 << 0) | ||
383 | #define WPALCON_W0PAL_18BPP (0x4 << 0) | ||
384 | #define WPALCON_W0PAL_16BPP_A555 (0x5 << 0) | ||
385 | #define WPALCON_W0PAL_16BPP_565 (0x6 << 0) | ||
386 | |||
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 00000000000..dc90f5ede88 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h | |||
@@ -0,0 +1,379 @@ | |||
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_TxFIFOEmpty (1 << 7) | ||
230 | #define S3C_DIEPMSK_INEPNakEffMsk (1 << 6) | ||
231 | #define S3C_DIEPMSK_INTknEPMisMsk (1 << 5) | ||
232 | #define S3C_DIEPMSK_INTknTXFEmpMsk (1 << 4) | ||
233 | #define S3C_DIEPMSK_TimeOUTMsk (1 << 3) | ||
234 | #define S3C_DIEPMSK_AHBErrMsk (1 << 2) | ||
235 | #define S3C_DIEPMSK_EPDisbldMsk (1 << 1) | ||
236 | #define S3C_DIEPMSK_XferComplMsk (1 << 0) | ||
237 | |||
238 | #define S3C_DOEPMSK S3C_HSOTG_REG(0x814) | ||
239 | |||
240 | #define S3C_DOEPMSK_Back2BackSetup (1 << 6) | ||
241 | #define S3C_DOEPMSK_OUTTknEPdisMsk (1 << 4) | ||
242 | #define S3C_DOEPMSK_SetupMsk (1 << 3) | ||
243 | #define S3C_DOEPMSK_AHBErrMsk (1 << 2) | ||
244 | #define S3C_DOEPMSK_EPDisbldMsk (1 << 1) | ||
245 | #define S3C_DOEPMSK_XferComplMsk (1 << 0) | ||
246 | |||
247 | #define S3C_DAINT S3C_HSOTG_REG(0x818) | ||
248 | #define S3C_DAINTMSK S3C_HSOTG_REG(0x81C) | ||
249 | |||
250 | #define S3C_DAINT_OutEP_SHIFT (16) | ||
251 | #define S3C_DAINT_OutEP(x) (1 << ((x) + 16)) | ||
252 | #define S3C_DAINT_InEP(x) (1 << (x)) | ||
253 | |||
254 | #define S3C_DTKNQR1 S3C_HSOTG_REG(0x820) | ||
255 | #define S3C_DTKNQR2 S3C_HSOTG_REG(0x824) | ||
256 | #define S3C_DTKNQR3 S3C_HSOTG_REG(0x830) | ||
257 | #define S3C_DTKNQR4 S3C_HSOTG_REG(0x834) | ||
258 | |||
259 | #define S3C_DVBUSDIS S3C_HSOTG_REG(0x828) | ||
260 | #define S3C_DVBUSPULSE S3C_HSOTG_REG(0x82C) | ||
261 | |||
262 | #define S3C_DIEPCTL0 S3C_HSOTG_REG(0x900) | ||
263 | #define S3C_DOEPCTL0 S3C_HSOTG_REG(0xB00) | ||
264 | #define S3C_DIEPCTL(_a) S3C_HSOTG_REG(0x900 + ((_a) * 0x20)) | ||
265 | #define S3C_DOEPCTL(_a) S3C_HSOTG_REG(0xB00 + ((_a) * 0x20)) | ||
266 | |||
267 | /* EP0 specialness: | ||
268 | * bits[29..28] - reserved (no SetD0PID, SetD1PID) | ||
269 | * bits[25..22] - should always be zero, this isn't a periodic endpoint | ||
270 | * bits[10..0] - MPS setting differenct for EP0 | ||
271 | */ | ||
272 | #define S3C_D0EPCTL_MPS_MASK (0x3 << 0) | ||
273 | #define S3C_D0EPCTL_MPS_SHIFT (0) | ||
274 | #define S3C_D0EPCTL_MPS_64 (0x0 << 0) | ||
275 | #define S3C_D0EPCTL_MPS_32 (0x1 << 0) | ||
276 | #define S3C_D0EPCTL_MPS_16 (0x2 << 0) | ||
277 | #define S3C_D0EPCTL_MPS_8 (0x3 << 0) | ||
278 | |||
279 | #define S3C_DxEPCTL_EPEna (1 << 31) | ||
280 | #define S3C_DxEPCTL_EPDis (1 << 30) | ||
281 | #define S3C_DxEPCTL_SetD1PID (1 << 29) | ||
282 | #define S3C_DxEPCTL_SetOddFr (1 << 29) | ||
283 | #define S3C_DxEPCTL_SetD0PID (1 << 28) | ||
284 | #define S3C_DxEPCTL_SetEvenFr (1 << 28) | ||
285 | #define S3C_DxEPCTL_SNAK (1 << 27) | ||
286 | #define S3C_DxEPCTL_CNAK (1 << 26) | ||
287 | #define S3C_DxEPCTL_TxFNum_MASK (0xf << 22) | ||
288 | #define S3C_DxEPCTL_TxFNum_SHIFT (22) | ||
289 | #define S3C_DxEPCTL_TxFNum_LIMIT (0xf) | ||
290 | #define S3C_DxEPCTL_TxFNum(_x) ((_x) << 22) | ||
291 | |||
292 | #define S3C_DxEPCTL_Stall (1 << 21) | ||
293 | #define S3C_DxEPCTL_Snp (1 << 20) | ||
294 | #define S3C_DxEPCTL_EPType_MASK (0x3 << 18) | ||
295 | #define S3C_DxEPCTL_EPType_SHIFT (18) | ||
296 | #define S3C_DxEPCTL_EPType_Control (0x0 << 18) | ||
297 | #define S3C_DxEPCTL_EPType_Iso (0x1 << 18) | ||
298 | #define S3C_DxEPCTL_EPType_Bulk (0x2 << 18) | ||
299 | #define S3C_DxEPCTL_EPType_Intterupt (0x3 << 18) | ||
300 | |||
301 | #define S3C_DxEPCTL_NAKsts (1 << 17) | ||
302 | #define S3C_DxEPCTL_DPID (1 << 16) | ||
303 | #define S3C_DxEPCTL_EOFrNum (1 << 16) | ||
304 | #define S3C_DxEPCTL_USBActEp (1 << 15) | ||
305 | #define S3C_DxEPCTL_NextEp_MASK (0xf << 11) | ||
306 | #define S3C_DxEPCTL_NextEp_SHIFT (11) | ||
307 | #define S3C_DxEPCTL_NextEp_LIMIT (0xf) | ||
308 | #define S3C_DxEPCTL_NextEp(_x) ((_x) << 11) | ||
309 | |||
310 | #define S3C_DxEPCTL_MPS_MASK (0x7ff << 0) | ||
311 | #define S3C_DxEPCTL_MPS_SHIFT (0) | ||
312 | #define S3C_DxEPCTL_MPS_LIMIT (0x7ff) | ||
313 | #define S3C_DxEPCTL_MPS(_x) ((_x) << 0) | ||
314 | |||
315 | #define S3C_DIEPINT(_a) S3C_HSOTG_REG(0x908 + ((_a) * 0x20)) | ||
316 | #define S3C_DOEPINT(_a) S3C_HSOTG_REG(0xB08 + ((_a) * 0x20)) | ||
317 | |||
318 | #define S3C_DxEPINT_INEPNakEff (1 << 6) | ||
319 | #define S3C_DxEPINT_Back2BackSetup (1 << 6) | ||
320 | #define S3C_DxEPINT_INTknEPMis (1 << 5) | ||
321 | #define S3C_DxEPINT_INTknTXFEmp (1 << 4) | ||
322 | #define S3C_DxEPINT_OUTTknEPdis (1 << 4) | ||
323 | #define S3C_DxEPINT_Timeout (1 << 3) | ||
324 | #define S3C_DxEPINT_Setup (1 << 3) | ||
325 | #define S3C_DxEPINT_AHBErr (1 << 2) | ||
326 | #define S3C_DxEPINT_EPDisbld (1 << 1) | ||
327 | #define S3C_DxEPINT_XferCompl (1 << 0) | ||
328 | |||
329 | #define S3C_DIEPTSIZ0 S3C_HSOTG_REG(0x910) | ||
330 | |||
331 | #define S3C_DIEPTSIZ0_PktCnt_MASK (0x3 << 19) | ||
332 | #define S3C_DIEPTSIZ0_PktCnt_SHIFT (19) | ||
333 | #define S3C_DIEPTSIZ0_PktCnt_LIMIT (0x3) | ||
334 | #define S3C_DIEPTSIZ0_PktCnt(_x) ((_x) << 19) | ||
335 | |||
336 | #define S3C_DIEPTSIZ0_XferSize_MASK (0x7f << 0) | ||
337 | #define S3C_DIEPTSIZ0_XferSize_SHIFT (0) | ||
338 | #define S3C_DIEPTSIZ0_XferSize_LIMIT (0x7f) | ||
339 | #define S3C_DIEPTSIZ0_XferSize(_x) ((_x) << 0) | ||
340 | |||
341 | |||
342 | #define DOEPTSIZ0 S3C_HSOTG_REG(0xB10) | ||
343 | #define S3C_DOEPTSIZ0_SUPCnt_MASK (0x3 << 29) | ||
344 | #define S3C_DOEPTSIZ0_SUPCnt_SHIFT (29) | ||
345 | #define S3C_DOEPTSIZ0_SUPCnt_LIMIT (0x3) | ||
346 | #define S3C_DOEPTSIZ0_SUPCnt(_x) ((_x) << 29) | ||
347 | |||
348 | #define S3C_DOEPTSIZ0_PktCnt (1 << 19) | ||
349 | #define S3C_DOEPTSIZ0_XferSize_MASK (0x7f << 0) | ||
350 | #define S3C_DOEPTSIZ0_XferSize_SHIFT (0) | ||
351 | |||
352 | #define S3C_DIEPTSIZ(_a) S3C_HSOTG_REG(0x910 + ((_a) * 0x20)) | ||
353 | #define S3C_DOEPTSIZ(_a) S3C_HSOTG_REG(0xB10 + ((_a) * 0x20)) | ||
354 | |||
355 | #define S3C_DxEPTSIZ_MC_MASK (0x3 << 29) | ||
356 | #define S3C_DxEPTSIZ_MC_SHIFT (29) | ||
357 | #define S3C_DxEPTSIZ_MC_LIMIT (0x3) | ||
358 | #define S3C_DxEPTSIZ_MC(_x) ((_x) << 29) | ||
359 | |||
360 | #define S3C_DxEPTSIZ_PktCnt_MASK (0x3ff << 19) | ||
361 | #define S3C_DxEPTSIZ_PktCnt_SHIFT (19) | ||
362 | #define S3C_DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff) | ||
363 | #define S3C_DxEPTSIZ_PktCnt_LIMIT (0x3ff) | ||
364 | #define S3C_DxEPTSIZ_PktCnt(_x) ((_x) << 19) | ||
365 | |||
366 | #define S3C_DxEPTSIZ_XferSize_MASK (0x7ffff << 0) | ||
367 | #define S3C_DxEPTSIZ_XferSize_SHIFT (0) | ||
368 | #define S3C_DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff) | ||
369 | #define S3C_DxEPTSIZ_XferSize_LIMIT (0x7ffff) | ||
370 | #define S3C_DxEPTSIZ_XferSize(_x) ((_x) << 0) | ||
371 | |||
372 | |||
373 | #define S3C_DIEPDMA(_a) S3C_HSOTG_REG(0x914 + ((_a) * 0x20)) | ||
374 | #define S3C_DOEPDMA(_a) S3C_HSOTG_REG(0xB14 + ((_a) * 0x20)) | ||
375 | #define S3C_DTXFSTS(_a) S3C_HSOTG_REG(0x918 + ((_a) * 0x20)) | ||
376 | |||
377 | #define S3C_EPFIFO(_a) S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000)) | ||
378 | |||
379 | #endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h new file mode 100644 index 00000000000..81074421312 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Samsung Electronics Co. Ltd. | ||
3 | * Jaswinder Singh <jassi.brar@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #ifndef __S3C_DMA_PL330_H_ | ||
12 | #define __S3C_DMA_PL330_H_ | ||
13 | |||
14 | #define S3C2410_DMAF_AUTOSTART (1 << 0) | ||
15 | #define S3C2410_DMAF_CIRCULAR (1 << 1) | ||
16 | |||
17 | /* | ||
18 | * PL330 can assign any channel to communicate with | ||
19 | * any of the peripherals attched to the DMAC. | ||
20 | * For the sake of consistency across client drivers, | ||
21 | * We keep the channel names unchanged and only add | ||
22 | * missing peripherals are added. | ||
23 | * Order is not important since S3C PL330 API driver | ||
24 | * use these just as IDs. | ||
25 | */ | ||
26 | enum dma_ch { | ||
27 | DMACH_UART0_RX, | ||
28 | DMACH_UART0_TX, | ||
29 | DMACH_UART1_RX, | ||
30 | DMACH_UART1_TX, | ||
31 | DMACH_UART2_RX, | ||
32 | DMACH_UART2_TX, | ||
33 | DMACH_UART3_RX, | ||
34 | DMACH_UART3_TX, | ||
35 | DMACH_UART4_RX, | ||
36 | DMACH_UART4_TX, | ||
37 | DMACH_UART5_RX, | ||
38 | DMACH_UART5_TX, | ||
39 | DMACH_USI_RX, | ||
40 | DMACH_USI_TX, | ||
41 | DMACH_IRDA, | ||
42 | DMACH_I2S0_RX, | ||
43 | DMACH_I2S0_TX, | ||
44 | DMACH_I2S0S_TX, | ||
45 | DMACH_I2S1_RX, | ||
46 | DMACH_I2S1_TX, | ||
47 | DMACH_I2S2_RX, | ||
48 | DMACH_I2S2_TX, | ||
49 | DMACH_SPI0_RX, | ||
50 | DMACH_SPI0_TX, | ||
51 | DMACH_SPI1_RX, | ||
52 | DMACH_SPI1_TX, | ||
53 | DMACH_SPI2_RX, | ||
54 | DMACH_SPI2_TX, | ||
55 | DMACH_AC97_MICIN, | ||
56 | DMACH_AC97_PCMIN, | ||
57 | DMACH_AC97_PCMOUT, | ||
58 | DMACH_EXTERNAL, | ||
59 | DMACH_PWM, | ||
60 | DMACH_SPDIF, | ||
61 | DMACH_HSI_RX, | ||
62 | DMACH_HSI_TX, | ||
63 | DMACH_PCM0_TX, | ||
64 | DMACH_PCM0_RX, | ||
65 | DMACH_PCM1_TX, | ||
66 | DMACH_PCM1_RX, | ||
67 | DMACH_PCM2_TX, | ||
68 | DMACH_PCM2_RX, | ||
69 | DMACH_MSM_REQ3, | ||
70 | DMACH_MSM_REQ2, | ||
71 | DMACH_MSM_REQ1, | ||
72 | DMACH_MSM_REQ0, | ||
73 | DMACH_SLIMBUS0_RX, | ||
74 | DMACH_SLIMBUS0_TX, | ||
75 | DMACH_SLIMBUS0AUX_RX, | ||
76 | DMACH_SLIMBUS0AUX_TX, | ||
77 | DMACH_SLIMBUS1_RX, | ||
78 | DMACH_SLIMBUS1_TX, | ||
79 | DMACH_SLIMBUS2_RX, | ||
80 | DMACH_SLIMBUS2_TX, | ||
81 | DMACH_SLIMBUS3_RX, | ||
82 | DMACH_SLIMBUS3_TX, | ||
83 | DMACH_SLIMBUS4_RX, | ||
84 | DMACH_SLIMBUS4_TX, | ||
85 | DMACH_SLIMBUS5_RX, | ||
86 | DMACH_SLIMBUS5_TX, | ||
87 | /* END Marker, also used to denote a reserved channel */ | ||
88 | DMACH_MAX, | ||
89 | }; | ||
90 | |||
91 | static inline bool s3c_dma_has_circular(void) | ||
92 | { | ||
93 | return true; | ||
94 | } | ||
95 | |||
96 | #include <plat/dma.h> | ||
97 | |||
98 | #endif /* __S3C_DMA_PL330_H_ */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h new file mode 100644 index 00000000000..bf5e2a9d408 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h | ||
2 | * | ||
3 | * Copyright (C) 2010 Samsung Electronics Co. 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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef __S3C_PL330_PDATA_H | ||
13 | #define __S3C_PL330_PDATA_H | ||
14 | |||
15 | #include <plat/s3c-dma-pl330.h> | ||
16 | |||
17 | /* | ||
18 | * Every PL330 DMAC has max 32 peripheral interfaces, | ||
19 | * of which some may be not be really used in your | ||
20 | * DMAC's configuration. | ||
21 | * Populate this array of 32 peri i/fs with relevant | ||
22 | * channel IDs for used peri i/f and DMACH_MAX for | ||
23 | * those unused. | ||
24 | * | ||
25 | * The platforms just need to provide this info | ||
26 | * to the S3C DMA API driver for PL330. | ||
27 | */ | ||
28 | struct s3c_pl330_platdata { | ||
29 | enum dma_ch peri[32]; | ||
30 | }; | ||
31 | |||
32 | #endif /* __S3C_PL330_PDATA_H */ | ||
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 00000000000..4c16fa3621b --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | |||
@@ -0,0 +1,75 @@ | |||
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 | * @clk_from_cmu: If the SPI clock/prescalar control block is present | ||
36 | * by the platform's clock-management-unit and not in SPI controller. | ||
37 | * @num_cs: Number of CS this controller emulates. | ||
38 | * @cfg_gpio: Configure pins for this SPI controller. | ||
39 | * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6 | ||
40 | * @rx_lvl_offset: Depends on tx fifo_lvl field and bus number | ||
41 | * @high_speed: If the controller supports HIGH_SPEED_EN bit | ||
42 | * @tx_st_done: Depends on tx fifo_lvl field | ||
43 | */ | ||
44 | struct s3c64xx_spi_info { | ||
45 | int src_clk_nr; | ||
46 | char *src_clk_name; | ||
47 | bool clk_from_cmu; | ||
48 | |||
49 | int num_cs; | ||
50 | |||
51 | int (*cfg_gpio)(struct platform_device *pdev); | ||
52 | |||
53 | /* Following two fields are for future compatibility */ | ||
54 | int fifo_lvl_mask; | ||
55 | int rx_lvl_offset; | ||
56 | int high_speed; | ||
57 | int tx_st_done; | ||
58 | }; | ||
59 | |||
60 | /** | ||
61 | * s3c64xx_spi_set_info - SPI Controller configure callback by the board | ||
62 | * initialization code. | ||
63 | * @cntrlr: SPI controller number the configuration is for. | ||
64 | * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks. | ||
65 | * @num_cs: Number of elements in the 'cs' array. | ||
66 | * | ||
67 | * Call this from machine init code for each SPI Controller that | ||
68 | * has some chips attached to it. | ||
69 | */ | ||
70 | extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); | ||
71 | extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); | ||
72 | extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); | ||
73 | extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); | ||
74 | |||
75 | #endif /* __S3C64XX_PLAT_SPI_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/ts.h b/arch/arm/plat-samsung/include/plat/ts.h new file mode 100644 index 00000000000..26fdb22e0fc --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/ts.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/ts.h | ||
2 | * | ||
3 | * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org> | ||
4 | * | ||
5 | * This program is free software; you 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 | |||
10 | #ifndef __ASM_ARM_TS_H | ||
11 | #define __ASM_ARM_TS_H | ||
12 | |||
13 | struct s3c2410_ts_mach_info { | ||
14 | int delay; | ||
15 | int presc; | ||
16 | int oversampling_shift; | ||
17 | void (*cfg_gpio)(struct platform_device *dev); | ||
18 | }; | ||
19 | |||
20 | extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *); | ||
21 | |||
22 | /* defined by architecture to configure gpio */ | ||
23 | extern void s3c24xx_ts_cfg_gpio(struct platform_device *dev); | ||
24 | |||
25 | #endif /* __ASM_ARM_TS_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 00000000000..a22a4f2eea9 --- /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/usb-control.h b/arch/arm/plat-samsung/include/plat/usb-control.h new file mode 100644 index 00000000000..7fa1fbefc3f --- /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/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c new file mode 100644 index 00000000000..3014c7226bd --- /dev/null +++ b/arch/arm/plat-samsung/irq-uart.c | |||
@@ -0,0 +1,96 @@ | |||
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 <asm/mach/irq.h> | ||
23 | |||
24 | #include <mach/map.h> | ||
25 | #include <plat/irq-uart.h> | ||
26 | #include <plat/regs-serial.h> | ||
27 | #include <plat/cpu.h> | ||
28 | |||
29 | /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | ||
30 | * are consecutive when looking up the interrupt in the demux routines. | ||
31 | */ | ||
32 | static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) | ||
33 | { | ||
34 | struct s3c_uart_irq *uirq = desc->irq_data.handler_data; | ||
35 | struct irq_chip *chip = irq_get_chip(irq); | ||
36 | u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); | ||
37 | int base = uirq->base_irq; | ||
38 | |||
39 | chained_irq_enter(chip, desc); | ||
40 | |||
41 | if (pend & (1 << 0)) | ||
42 | generic_handle_irq(base); | ||
43 | if (pend & (1 << 1)) | ||
44 | generic_handle_irq(base + 1); | ||
45 | if (pend & (1 << 2)) | ||
46 | generic_handle_irq(base + 2); | ||
47 | if (pend & (1 << 3)) | ||
48 | generic_handle_irq(base + 3); | ||
49 | |||
50 | chained_irq_exit(chip, desc); | ||
51 | } | ||
52 | |||
53 | static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) | ||
54 | { | ||
55 | void __iomem *reg_base = uirq->regs; | ||
56 | struct irq_chip_generic *gc; | ||
57 | struct irq_chip_type *ct; | ||
58 | |||
59 | /* mask all interrupts at the start. */ | ||
60 | __raw_writel(0xf, reg_base + S3C64XX_UINTM); | ||
61 | |||
62 | gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base, | ||
63 | handle_level_irq); | ||
64 | |||
65 | if (!gc) { | ||
66 | pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", | ||
67 | __func__, uirq->base_irq); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | ct = gc->chip_types; | ||
72 | ct->chip.irq_ack = irq_gc_ack_set_bit; | ||
73 | ct->chip.irq_mask = irq_gc_mask_set_bit; | ||
74 | ct->chip.irq_unmask = irq_gc_mask_clr_bit; | ||
75 | ct->regs.ack = S3C64XX_UINTP; | ||
76 | ct->regs.mask = S3C64XX_UINTM; | ||
77 | irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE, | ||
78 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
79 | |||
80 | irq_set_handler_data(uirq->parent_irq, uirq); | ||
81 | irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing | ||
86 | * @irq: The interrupt data for registering | ||
87 | * @nr_irqs: The number of interrupt descriptions in @irq. | ||
88 | * | ||
89 | * Register the UART interrupts specified by @irq including the demuxing | ||
90 | * routines. This supports the S3C6400 and newer style of devices. | ||
91 | */ | ||
92 | void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs) | ||
93 | { | ||
94 | for (; nr_irqs > 0; nr_irqs--, irq++) | ||
95 | s3c_init_uart_irq(irq); | ||
96 | } | ||
diff --git a/arch/arm/plat-samsung/pd.c b/arch/arm/plat-samsung/pd.c new file mode 100644 index 00000000000..efe1d564473 --- /dev/null +++ b/arch/arm/plat-samsung/pd.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* linux/arch/arm/plat-samsung/pd.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Samsung Power domain 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 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/pm_runtime.h> | ||
18 | |||
19 | #include <plat/pd.h> | ||
20 | |||
21 | static int samsung_pd_probe(struct platform_device *pdev) | ||
22 | { | ||
23 | struct samsung_pd_info *pdata = pdev->dev.platform_data; | ||
24 | struct device *dev = &pdev->dev; | ||
25 | |||
26 | if (!pdata) { | ||
27 | dev_err(dev, "no device data specified\n"); | ||
28 | return -ENOENT; | ||
29 | } | ||
30 | |||
31 | pm_runtime_set_active(dev); | ||
32 | pm_runtime_enable(dev); | ||
33 | |||
34 | dev_info(dev, "power domain registered\n"); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static int __devexit samsung_pd_remove(struct platform_device *pdev) | ||
39 | { | ||
40 | struct device *dev = &pdev->dev; | ||
41 | |||
42 | pm_runtime_disable(dev); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static int samsung_pd_runtime_suspend(struct device *dev) | ||
47 | { | ||
48 | struct samsung_pd_info *pdata = dev->platform_data; | ||
49 | int ret = 0; | ||
50 | |||
51 | if (pdata->disable) | ||
52 | ret = pdata->disable(dev); | ||
53 | |||
54 | dev_dbg(dev, "suspended\n"); | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | static int samsung_pd_runtime_resume(struct device *dev) | ||
59 | { | ||
60 | struct samsung_pd_info *pdata = dev->platform_data; | ||
61 | int ret = 0; | ||
62 | |||
63 | if (pdata->enable) | ||
64 | ret = pdata->enable(dev); | ||
65 | |||
66 | dev_dbg(dev, "resumed\n"); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | static const struct dev_pm_ops samsung_pd_pm_ops = { | ||
71 | .runtime_suspend = samsung_pd_runtime_suspend, | ||
72 | .runtime_resume = samsung_pd_runtime_resume, | ||
73 | }; | ||
74 | |||
75 | static struct platform_driver samsung_pd_driver = { | ||
76 | .driver = { | ||
77 | .name = "samsung-pd", | ||
78 | .owner = THIS_MODULE, | ||
79 | .pm = &samsung_pd_pm_ops, | ||
80 | }, | ||
81 | .probe = samsung_pd_probe, | ||
82 | .remove = __devexit_p(samsung_pd_remove), | ||
83 | }; | ||
84 | |||
85 | static int __init samsung_pd_init(void) | ||
86 | { | ||
87 | int ret; | ||
88 | |||
89 | ret = platform_driver_register(&samsung_pd_driver); | ||
90 | if (ret) | ||
91 | printk(KERN_ERR "%s: failed to add PD driver\n", __func__); | ||
92 | |||
93 | return ret; | ||
94 | } | ||
95 | arch_initcall(samsung_pd_init); | ||
diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c new file mode 100644 index 00000000000..f37457c5206 --- /dev/null +++ b/arch/arm/plat-samsung/pwm.c | |||
@@ -0,0 +1,413 @@ | |||
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/slab.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/pwm.h> | ||
22 | |||
23 | #include <mach/map.h> | ||
24 | |||
25 | #include <plat/regs-timer.h> | ||
26 | |||
27 | struct pwm_device { | ||
28 | struct list_head list; | ||
29 | struct platform_device *pdev; | ||
30 | |||
31 | struct clk *clk_div; | ||
32 | struct clk *clk; | ||
33 | const char *label; | ||
34 | |||
35 | unsigned int period_ns; | ||
36 | unsigned int duty_ns; | ||
37 | |||
38 | unsigned char tcon_base; | ||
39 | unsigned char running; | ||
40 | unsigned char use_count; | ||
41 | unsigned char pwm_id; | ||
42 | }; | ||
43 | |||
44 | #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg) | ||
45 | |||
46 | static struct clk *clk_scaler[2]; | ||
47 | |||
48 | static inline int pwm_is_tdiv(struct pwm_device *pwm) | ||
49 | { | ||
50 | return clk_get_parent(pwm->clk) == pwm->clk_div; | ||
51 | } | ||
52 | |||
53 | static DEFINE_MUTEX(pwm_lock); | ||
54 | static LIST_HEAD(pwm_list); | ||
55 | |||
56 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
57 | { | ||
58 | struct pwm_device *pwm; | ||
59 | int found = 0; | ||
60 | |||
61 | mutex_lock(&pwm_lock); | ||
62 | |||
63 | list_for_each_entry(pwm, &pwm_list, list) { | ||
64 | if (pwm->pwm_id == pwm_id) { | ||
65 | found = 1; | ||
66 | break; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | if (found) { | ||
71 | if (pwm->use_count == 0) { | ||
72 | pwm->use_count = 1; | ||
73 | pwm->label = label; | ||
74 | } else | ||
75 | pwm = ERR_PTR(-EBUSY); | ||
76 | } else | ||
77 | pwm = ERR_PTR(-ENOENT); | ||
78 | |||
79 | mutex_unlock(&pwm_lock); | ||
80 | return pwm; | ||
81 | } | ||
82 | |||
83 | EXPORT_SYMBOL(pwm_request); | ||
84 | |||
85 | |||
86 | void pwm_free(struct pwm_device *pwm) | ||
87 | { | ||
88 | mutex_lock(&pwm_lock); | ||
89 | |||
90 | if (pwm->use_count) { | ||
91 | pwm->use_count--; | ||
92 | pwm->label = NULL; | ||
93 | } else | ||
94 | printk(KERN_ERR "PWM%d device already freed\n", pwm->pwm_id); | ||
95 | |||
96 | mutex_unlock(&pwm_lock); | ||
97 | } | ||
98 | |||
99 | EXPORT_SYMBOL(pwm_free); | ||
100 | |||
101 | #define pwm_tcon_start(pwm) (1 << (pwm->tcon_base + 0)) | ||
102 | #define pwm_tcon_invert(pwm) (1 << (pwm->tcon_base + 2)) | ||
103 | #define pwm_tcon_autoreload(pwm) (1 << (pwm->tcon_base + 3)) | ||
104 | #define pwm_tcon_manulupdate(pwm) (1 << (pwm->tcon_base + 1)) | ||
105 | |||
106 | int pwm_enable(struct pwm_device *pwm) | ||
107 | { | ||
108 | unsigned long flags; | ||
109 | unsigned long tcon; | ||
110 | |||
111 | local_irq_save(flags); | ||
112 | |||
113 | tcon = __raw_readl(S3C2410_TCON); | ||
114 | tcon |= pwm_tcon_start(pwm); | ||
115 | __raw_writel(tcon, S3C2410_TCON); | ||
116 | |||
117 | local_irq_restore(flags); | ||
118 | |||
119 | pwm->running = 1; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | EXPORT_SYMBOL(pwm_enable); | ||
124 | |||
125 | void pwm_disable(struct pwm_device *pwm) | ||
126 | { | ||
127 | unsigned long flags; | ||
128 | unsigned long tcon; | ||
129 | |||
130 | local_irq_save(flags); | ||
131 | |||
132 | tcon = __raw_readl(S3C2410_TCON); | ||
133 | tcon &= ~pwm_tcon_start(pwm); | ||
134 | __raw_writel(tcon, S3C2410_TCON); | ||
135 | |||
136 | local_irq_restore(flags); | ||
137 | |||
138 | pwm->running = 0; | ||
139 | } | ||
140 | |||
141 | EXPORT_SYMBOL(pwm_disable); | ||
142 | |||
143 | static unsigned long pwm_calc_tin(struct pwm_device *pwm, unsigned long freq) | ||
144 | { | ||
145 | unsigned long tin_parent_rate; | ||
146 | unsigned int div; | ||
147 | |||
148 | tin_parent_rate = clk_get_rate(clk_get_parent(pwm->clk_div)); | ||
149 | pwm_dbg(pwm, "tin parent at %lu\n", tin_parent_rate); | ||
150 | |||
151 | for (div = 2; div <= 16; div *= 2) { | ||
152 | if ((tin_parent_rate / (div << 16)) < freq) | ||
153 | return tin_parent_rate / div; | ||
154 | } | ||
155 | |||
156 | return tin_parent_rate / 16; | ||
157 | } | ||
158 | |||
159 | #define NS_IN_HZ (1000000000UL) | ||
160 | |||
161 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | ||
162 | { | ||
163 | unsigned long tin_rate; | ||
164 | unsigned long tin_ns; | ||
165 | unsigned long period; | ||
166 | unsigned long flags; | ||
167 | unsigned long tcon; | ||
168 | unsigned long tcnt; | ||
169 | long tcmp; | ||
170 | |||
171 | /* We currently avoid using 64bit arithmetic by using the | ||
172 | * fact that anything faster than 1Hz is easily representable | ||
173 | * by 32bits. */ | ||
174 | |||
175 | if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ) | ||
176 | return -ERANGE; | ||
177 | |||
178 | if (duty_ns > period_ns) | ||
179 | return -EINVAL; | ||
180 | |||
181 | if (period_ns == pwm->period_ns && | ||
182 | duty_ns == pwm->duty_ns) | ||
183 | return 0; | ||
184 | |||
185 | /* The TCMP and TCNT can be read without a lock, they're not | ||
186 | * shared between the timers. */ | ||
187 | |||
188 | tcmp = __raw_readl(S3C2410_TCMPB(pwm->pwm_id)); | ||
189 | tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id)); | ||
190 | |||
191 | period = NS_IN_HZ / period_ns; | ||
192 | |||
193 | pwm_dbg(pwm, "duty_ns=%d, period_ns=%d (%lu)\n", | ||
194 | duty_ns, period_ns, period); | ||
195 | |||
196 | /* Check to see if we are changing the clock rate of the PWM */ | ||
197 | |||
198 | if (pwm->period_ns != period_ns) { | ||
199 | if (pwm_is_tdiv(pwm)) { | ||
200 | tin_rate = pwm_calc_tin(pwm, period); | ||
201 | clk_set_rate(pwm->clk_div, tin_rate); | ||
202 | } else | ||
203 | tin_rate = clk_get_rate(pwm->clk); | ||
204 | |||
205 | pwm->period_ns = period_ns; | ||
206 | |||
207 | pwm_dbg(pwm, "tin_rate=%lu\n", tin_rate); | ||
208 | |||
209 | tin_ns = NS_IN_HZ / tin_rate; | ||
210 | tcnt = period_ns / tin_ns; | ||
211 | } else | ||
212 | tin_ns = NS_IN_HZ / clk_get_rate(pwm->clk); | ||
213 | |||
214 | /* Note, counters count down */ | ||
215 | |||
216 | tcmp = duty_ns / tin_ns; | ||
217 | tcmp = tcnt - tcmp; | ||
218 | /* the pwm hw only checks the compare register after a decrement, | ||
219 | so the pin never toggles if tcmp = tcnt */ | ||
220 | if (tcmp == tcnt) | ||
221 | tcmp--; | ||
222 | |||
223 | pwm_dbg(pwm, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt); | ||
224 | |||
225 | if (tcmp < 0) | ||
226 | tcmp = 0; | ||
227 | |||
228 | /* Update the PWM register block. */ | ||
229 | |||
230 | local_irq_save(flags); | ||
231 | |||
232 | __raw_writel(tcmp, S3C2410_TCMPB(pwm->pwm_id)); | ||
233 | __raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id)); | ||
234 | |||
235 | tcon = __raw_readl(S3C2410_TCON); | ||
236 | tcon |= pwm_tcon_manulupdate(pwm); | ||
237 | tcon |= pwm_tcon_autoreload(pwm); | ||
238 | __raw_writel(tcon, S3C2410_TCON); | ||
239 | |||
240 | tcon &= ~pwm_tcon_manulupdate(pwm); | ||
241 | __raw_writel(tcon, S3C2410_TCON); | ||
242 | |||
243 | local_irq_restore(flags); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | EXPORT_SYMBOL(pwm_config); | ||
249 | |||
250 | static int pwm_register(struct pwm_device *pwm) | ||
251 | { | ||
252 | pwm->duty_ns = -1; | ||
253 | pwm->period_ns = -1; | ||
254 | |||
255 | mutex_lock(&pwm_lock); | ||
256 | list_add_tail(&pwm->list, &pwm_list); | ||
257 | mutex_unlock(&pwm_lock); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int s3c_pwm_probe(struct platform_device *pdev) | ||
263 | { | ||
264 | struct device *dev = &pdev->dev; | ||
265 | struct pwm_device *pwm; | ||
266 | unsigned long flags; | ||
267 | unsigned long tcon; | ||
268 | unsigned int id = pdev->id; | ||
269 | int ret; | ||
270 | |||
271 | if (id == 4) { | ||
272 | dev_err(dev, "TIMER4 is currently not supported\n"); | ||
273 | return -ENXIO; | ||
274 | } | ||
275 | |||
276 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | ||
277 | if (pwm == NULL) { | ||
278 | dev_err(dev, "failed to allocate pwm_device\n"); | ||
279 | return -ENOMEM; | ||
280 | } | ||
281 | |||
282 | pwm->pdev = pdev; | ||
283 | pwm->pwm_id = id; | ||
284 | |||
285 | /* calculate base of control bits in TCON */ | ||
286 | pwm->tcon_base = id == 0 ? 0 : (id * 4) + 4; | ||
287 | |||
288 | pwm->clk = clk_get(dev, "pwm-tin"); | ||
289 | if (IS_ERR(pwm->clk)) { | ||
290 | dev_err(dev, "failed to get pwm tin clk\n"); | ||
291 | ret = PTR_ERR(pwm->clk); | ||
292 | goto err_alloc; | ||
293 | } | ||
294 | |||
295 | pwm->clk_div = clk_get(dev, "pwm-tdiv"); | ||
296 | if (IS_ERR(pwm->clk_div)) { | ||
297 | dev_err(dev, "failed to get pwm tdiv clk\n"); | ||
298 | ret = PTR_ERR(pwm->clk_div); | ||
299 | goto err_clk_tin; | ||
300 | } | ||
301 | |||
302 | local_irq_save(flags); | ||
303 | |||
304 | tcon = __raw_readl(S3C2410_TCON); | ||
305 | tcon |= pwm_tcon_invert(pwm); | ||
306 | __raw_writel(tcon, S3C2410_TCON); | ||
307 | |||
308 | local_irq_restore(flags); | ||
309 | |||
310 | |||
311 | ret = pwm_register(pwm); | ||
312 | if (ret) { | ||
313 | dev_err(dev, "failed to register pwm\n"); | ||
314 | goto err_clk_tdiv; | ||
315 | } | ||
316 | |||
317 | pwm_dbg(pwm, "config bits %02x\n", | ||
318 | (__raw_readl(S3C2410_TCON) >> pwm->tcon_base) & 0x0f); | ||
319 | |||
320 | dev_info(dev, "tin at %lu, tdiv at %lu, tin=%sclk, base %d\n", | ||
321 | clk_get_rate(pwm->clk), | ||
322 | clk_get_rate(pwm->clk_div), | ||
323 | pwm_is_tdiv(pwm) ? "div" : "ext", pwm->tcon_base); | ||
324 | |||
325 | platform_set_drvdata(pdev, pwm); | ||
326 | return 0; | ||
327 | |||
328 | err_clk_tdiv: | ||
329 | clk_put(pwm->clk_div); | ||
330 | |||
331 | err_clk_tin: | ||
332 | clk_put(pwm->clk); | ||
333 | |||
334 | err_alloc: | ||
335 | kfree(pwm); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int __devexit s3c_pwm_remove(struct platform_device *pdev) | ||
340 | { | ||
341 | struct pwm_device *pwm = platform_get_drvdata(pdev); | ||
342 | |||
343 | clk_put(pwm->clk_div); | ||
344 | clk_put(pwm->clk); | ||
345 | kfree(pwm); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | #ifdef CONFIG_PM | ||
351 | static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state) | ||
352 | { | ||
353 | struct pwm_device *pwm = platform_get_drvdata(pdev); | ||
354 | |||
355 | /* No one preserve these values during suspend so reset them | ||
356 | * Otherwise driver leaves PWM unconfigured if same values | ||
357 | * passed to pwm_config | ||
358 | */ | ||
359 | pwm->period_ns = 0; | ||
360 | pwm->duty_ns = 0; | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int s3c_pwm_resume(struct platform_device *pdev) | ||
366 | { | ||
367 | struct pwm_device *pwm = platform_get_drvdata(pdev); | ||
368 | unsigned long tcon; | ||
369 | |||
370 | /* Restore invertion */ | ||
371 | tcon = __raw_readl(S3C2410_TCON); | ||
372 | tcon |= pwm_tcon_invert(pwm); | ||
373 | __raw_writel(tcon, S3C2410_TCON); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | #else | ||
379 | #define s3c_pwm_suspend NULL | ||
380 | #define s3c_pwm_resume NULL | ||
381 | #endif | ||
382 | |||
383 | static struct platform_driver s3c_pwm_driver = { | ||
384 | .driver = { | ||
385 | .name = "s3c24xx-pwm", | ||
386 | .owner = THIS_MODULE, | ||
387 | }, | ||
388 | .probe = s3c_pwm_probe, | ||
389 | .remove = __devexit_p(s3c_pwm_remove), | ||
390 | .suspend = s3c_pwm_suspend, | ||
391 | .resume = s3c_pwm_resume, | ||
392 | }; | ||
393 | |||
394 | static int __init pwm_init(void) | ||
395 | { | ||
396 | int ret; | ||
397 | |||
398 | clk_scaler[0] = clk_get(NULL, "pwm-scaler0"); | ||
399 | clk_scaler[1] = clk_get(NULL, "pwm-scaler1"); | ||
400 | |||
401 | if (IS_ERR(clk_scaler[0]) || IS_ERR(clk_scaler[1])) { | ||
402 | printk(KERN_ERR "%s: failed to get scaler clocks\n", __func__); | ||
403 | return -EINVAL; | ||
404 | } | ||
405 | |||
406 | ret = platform_driver_register(&s3c_pwm_driver); | ||
407 | if (ret) | ||
408 | printk(KERN_ERR "%s: failed to add pwm driver\n", __func__); | ||
409 | |||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | arch_initcall(pwm_init); | ||
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c new file mode 100644 index 00000000000..f85638c6f5a --- /dev/null +++ b/arch/arm/plat-samsung/s3c-pl330.c | |||
@@ -0,0 +1,1244 @@ | |||
1 | /* linux/arch/arm/plat-samsung/s3c-pl330.c | ||
2 | * | ||
3 | * Copyright (C) 2010 Samsung Electronics Co. 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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | ||
20 | |||
21 | #include <asm/hardware/pl330.h> | ||
22 | |||
23 | #include <plat/s3c-pl330-pdata.h> | ||
24 | |||
25 | /** | ||
26 | * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC. | ||
27 | * @busy_chan: Number of channels currently busy. | ||
28 | * @peri: List of IDs of peripherals this DMAC can work with. | ||
29 | * @node: To attach to the global list of DMACs. | ||
30 | * @pi: PL330 configuration info for the DMAC. | ||
31 | * @kmcache: Pool to quickly allocate xfers for all channels in the dmac. | ||
32 | * @clk: Pointer of DMAC operation clock. | ||
33 | */ | ||
34 | struct s3c_pl330_dmac { | ||
35 | unsigned busy_chan; | ||
36 | enum dma_ch *peri; | ||
37 | struct list_head node; | ||
38 | struct pl330_info *pi; | ||
39 | struct kmem_cache *kmcache; | ||
40 | struct clk *clk; | ||
41 | }; | ||
42 | |||
43 | /** | ||
44 | * struct s3c_pl330_xfer - A request submitted by S3C DMA clients. | ||
45 | * @token: Xfer ID provided by the client. | ||
46 | * @node: To attach to the list of xfers on a channel. | ||
47 | * @px: Xfer for PL330 core. | ||
48 | * @chan: Owner channel of this xfer. | ||
49 | */ | ||
50 | struct s3c_pl330_xfer { | ||
51 | void *token; | ||
52 | struct list_head node; | ||
53 | struct pl330_xfer px; | ||
54 | struct s3c_pl330_chan *chan; | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * struct s3c_pl330_chan - Logical channel to communicate with | ||
59 | * a Physical peripheral. | ||
60 | * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC. | ||
61 | * NULL if the channel is available to be acquired. | ||
62 | * @id: ID of the peripheral that this channel can communicate with. | ||
63 | * @options: Options specified by the client. | ||
64 | * @sdaddr: Address provided via s3c2410_dma_devconfig. | ||
65 | * @node: To attach to the global list of channels. | ||
66 | * @lrq: Pointer to the last submitted pl330_req to PL330 core. | ||
67 | * @xfer_list: To manage list of xfers enqueued. | ||
68 | * @req: Two requests to communicate with the PL330 engine. | ||
69 | * @callback_fn: Callback function to the client. | ||
70 | * @rqcfg: Channel configuration for the xfers. | ||
71 | * @xfer_head: Pointer to the xfer to be next executed. | ||
72 | * @dmac: Pointer to the DMAC that manages this channel, NULL if the | ||
73 | * channel is available to be acquired. | ||
74 | * @client: Client of this channel. NULL if the | ||
75 | * channel is available to be acquired. | ||
76 | */ | ||
77 | struct s3c_pl330_chan { | ||
78 | void *pl330_chan_id; | ||
79 | enum dma_ch id; | ||
80 | unsigned int options; | ||
81 | unsigned long sdaddr; | ||
82 | struct list_head node; | ||
83 | struct pl330_req *lrq; | ||
84 | struct list_head xfer_list; | ||
85 | struct pl330_req req[2]; | ||
86 | s3c2410_dma_cbfn_t callback_fn; | ||
87 | struct pl330_reqcfg rqcfg; | ||
88 | struct s3c_pl330_xfer *xfer_head; | ||
89 | struct s3c_pl330_dmac *dmac; | ||
90 | struct s3c2410_dma_client *client; | ||
91 | }; | ||
92 | |||
93 | /* All DMACs in the platform */ | ||
94 | static LIST_HEAD(dmac_list); | ||
95 | |||
96 | /* All channels to peripherals in the platform */ | ||
97 | static LIST_HEAD(chan_list); | ||
98 | |||
99 | /* | ||
100 | * Since we add resources(DMACs and Channels) to the global pool, | ||
101 | * we need to guard access to the resources using a global lock | ||
102 | */ | ||
103 | static DEFINE_SPINLOCK(res_lock); | ||
104 | |||
105 | /* Returns the channel with ID 'id' in the chan_list */ | ||
106 | static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id) | ||
107 | { | ||
108 | struct s3c_pl330_chan *ch; | ||
109 | |||
110 | list_for_each_entry(ch, &chan_list, node) | ||
111 | if (ch->id == id) | ||
112 | return ch; | ||
113 | |||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | /* Allocate a new channel with ID 'id' and add to chan_list */ | ||
118 | static void chan_add(const enum dma_ch id) | ||
119 | { | ||
120 | struct s3c_pl330_chan *ch = id_to_chan(id); | ||
121 | |||
122 | /* Return if the channel already exists */ | ||
123 | if (ch) | ||
124 | return; | ||
125 | |||
126 | ch = kmalloc(sizeof(*ch), GFP_KERNEL); | ||
127 | /* Return silently to work with other channels */ | ||
128 | if (!ch) | ||
129 | return; | ||
130 | |||
131 | ch->id = id; | ||
132 | ch->dmac = NULL; | ||
133 | |||
134 | list_add_tail(&ch->node, &chan_list); | ||
135 | } | ||
136 | |||
137 | /* If the channel is not yet acquired by any client */ | ||
138 | static bool chan_free(struct s3c_pl330_chan *ch) | ||
139 | { | ||
140 | if (!ch) | ||
141 | return false; | ||
142 | |||
143 | /* Channel points to some DMAC only when it's acquired */ | ||
144 | return ch->dmac ? false : true; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Returns 0 is peripheral i/f is invalid or not present on the dmac. | ||
149 | * Index + 1, otherwise. | ||
150 | */ | ||
151 | static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id) | ||
152 | { | ||
153 | enum dma_ch *id = dmac->peri; | ||
154 | int i; | ||
155 | |||
156 | /* Discount invalid markers */ | ||
157 | if (ch_id == DMACH_MAX) | ||
158 | return 0; | ||
159 | |||
160 | for (i = 0; i < PL330_MAX_PERI; i++) | ||
161 | if (id[i] == ch_id) | ||
162 | return i + 1; | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* If all channel threads of the DMAC are busy */ | ||
168 | static inline bool dmac_busy(struct s3c_pl330_dmac *dmac) | ||
169 | { | ||
170 | struct pl330_info *pi = dmac->pi; | ||
171 | |||
172 | return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Returns the number of free channels that | ||
177 | * can be handled by this dmac only. | ||
178 | */ | ||
179 | static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac) | ||
180 | { | ||
181 | enum dma_ch *id = dmac->peri; | ||
182 | struct s3c_pl330_dmac *d; | ||
183 | struct s3c_pl330_chan *ch; | ||
184 | unsigned found, count = 0; | ||
185 | enum dma_ch p; | ||
186 | int i; | ||
187 | |||
188 | for (i = 0; i < PL330_MAX_PERI; i++) { | ||
189 | p = id[i]; | ||
190 | ch = id_to_chan(p); | ||
191 | |||
192 | if (p == DMACH_MAX || !chan_free(ch)) | ||
193 | continue; | ||
194 | |||
195 | found = 0; | ||
196 | list_for_each_entry(d, &dmac_list, node) { | ||
197 | if (d != dmac && iface_of_dmac(d, ch->id)) { | ||
198 | found = 1; | ||
199 | break; | ||
200 | } | ||
201 | } | ||
202 | if (!found) | ||
203 | count++; | ||
204 | } | ||
205 | |||
206 | return count; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Measure of suitability of 'dmac' handling 'ch' | ||
211 | * | ||
212 | * 0 indicates 'dmac' can not handle 'ch' either | ||
213 | * because it is not supported by the hardware or | ||
214 | * because all dmac channels are currently busy. | ||
215 | * | ||
216 | * >0 vlaue indicates 'dmac' has the capability. | ||
217 | * The bigger the value the more suitable the dmac. | ||
218 | */ | ||
219 | #define MAX_SUIT UINT_MAX | ||
220 | #define MIN_SUIT 0 | ||
221 | |||
222 | static unsigned suitablility(struct s3c_pl330_dmac *dmac, | ||
223 | struct s3c_pl330_chan *ch) | ||
224 | { | ||
225 | struct pl330_info *pi = dmac->pi; | ||
226 | enum dma_ch *id = dmac->peri; | ||
227 | struct s3c_pl330_dmac *d; | ||
228 | unsigned s; | ||
229 | int i; | ||
230 | |||
231 | s = MIN_SUIT; | ||
232 | /* If all the DMAC channel threads are busy */ | ||
233 | if (dmac_busy(dmac)) | ||
234 | return s; | ||
235 | |||
236 | for (i = 0; i < PL330_MAX_PERI; i++) | ||
237 | if (id[i] == ch->id) | ||
238 | break; | ||
239 | |||
240 | /* If the 'dmac' can't talk to 'ch' */ | ||
241 | if (i == PL330_MAX_PERI) | ||
242 | return s; | ||
243 | |||
244 | s = MAX_SUIT; | ||
245 | list_for_each_entry(d, &dmac_list, node) { | ||
246 | /* | ||
247 | * If some other dmac can talk to this | ||
248 | * peri and has some channel free. | ||
249 | */ | ||
250 | if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) { | ||
251 | s = 0; | ||
252 | break; | ||
253 | } | ||
254 | } | ||
255 | if (s) | ||
256 | return s; | ||
257 | |||
258 | s = 100; | ||
259 | |||
260 | /* Good if free chans are more, bad otherwise */ | ||
261 | s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac); | ||
262 | |||
263 | return s; | ||
264 | } | ||
265 | |||
266 | /* More than one DMAC may have capability to transfer data with the | ||
267 | * peripheral. This function assigns most suitable DMAC to manage the | ||
268 | * channel and hence communicate with the peripheral. | ||
269 | */ | ||
270 | static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch) | ||
271 | { | ||
272 | struct s3c_pl330_dmac *d, *dmac = NULL; | ||
273 | unsigned sn, sl = MIN_SUIT; | ||
274 | |||
275 | list_for_each_entry(d, &dmac_list, node) { | ||
276 | sn = suitablility(d, ch); | ||
277 | |||
278 | if (sn == MAX_SUIT) | ||
279 | return d; | ||
280 | |||
281 | if (sn > sl) | ||
282 | dmac = d; | ||
283 | } | ||
284 | |||
285 | return dmac; | ||
286 | } | ||
287 | |||
288 | /* Acquire the channel for peripheral 'id' */ | ||
289 | static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id) | ||
290 | { | ||
291 | struct s3c_pl330_chan *ch = id_to_chan(id); | ||
292 | struct s3c_pl330_dmac *dmac; | ||
293 | |||
294 | /* If the channel doesn't exist or is already acquired */ | ||
295 | if (!ch || !chan_free(ch)) { | ||
296 | ch = NULL; | ||
297 | goto acq_exit; | ||
298 | } | ||
299 | |||
300 | dmac = map_chan_to_dmac(ch); | ||
301 | /* If couldn't map */ | ||
302 | if (!dmac) { | ||
303 | ch = NULL; | ||
304 | goto acq_exit; | ||
305 | } | ||
306 | |||
307 | dmac->busy_chan++; | ||
308 | ch->dmac = dmac; | ||
309 | |||
310 | acq_exit: | ||
311 | return ch; | ||
312 | } | ||
313 | |||
314 | /* Delete xfer from the queue */ | ||
315 | static inline void del_from_queue(struct s3c_pl330_xfer *xfer) | ||
316 | { | ||
317 | struct s3c_pl330_xfer *t; | ||
318 | struct s3c_pl330_chan *ch; | ||
319 | int found; | ||
320 | |||
321 | if (!xfer) | ||
322 | return; | ||
323 | |||
324 | ch = xfer->chan; | ||
325 | |||
326 | /* Make sure xfer is in the queue */ | ||
327 | found = 0; | ||
328 | list_for_each_entry(t, &ch->xfer_list, node) | ||
329 | if (t == xfer) { | ||
330 | found = 1; | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | if (!found) | ||
335 | return; | ||
336 | |||
337 | /* If xfer is last entry in the queue */ | ||
338 | if (xfer->node.next == &ch->xfer_list) | ||
339 | t = list_entry(ch->xfer_list.next, | ||
340 | struct s3c_pl330_xfer, node); | ||
341 | else | ||
342 | t = list_entry(xfer->node.next, | ||
343 | struct s3c_pl330_xfer, node); | ||
344 | |||
345 | /* If there was only one node left */ | ||
346 | if (t == xfer) | ||
347 | ch->xfer_head = NULL; | ||
348 | else if (ch->xfer_head == xfer) | ||
349 | ch->xfer_head = t; | ||
350 | |||
351 | list_del(&xfer->node); | ||
352 | } | ||
353 | |||
354 | /* Provides pointer to the next xfer in the queue. | ||
355 | * If CIRCULAR option is set, the list is left intact, | ||
356 | * otherwise the xfer is removed from the list. | ||
357 | * Forced delete 'pluck' can be set to override the CIRCULAR option. | ||
358 | */ | ||
359 | static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch, | ||
360 | int pluck) | ||
361 | { | ||
362 | struct s3c_pl330_xfer *xfer = ch->xfer_head; | ||
363 | |||
364 | if (!xfer) | ||
365 | return NULL; | ||
366 | |||
367 | /* If xfer is last entry in the queue */ | ||
368 | if (xfer->node.next == &ch->xfer_list) | ||
369 | ch->xfer_head = list_entry(ch->xfer_list.next, | ||
370 | struct s3c_pl330_xfer, node); | ||
371 | else | ||
372 | ch->xfer_head = list_entry(xfer->node.next, | ||
373 | struct s3c_pl330_xfer, node); | ||
374 | |||
375 | if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR)) | ||
376 | del_from_queue(xfer); | ||
377 | |||
378 | return xfer; | ||
379 | } | ||
380 | |||
381 | static inline void add_to_queue(struct s3c_pl330_chan *ch, | ||
382 | struct s3c_pl330_xfer *xfer, int front) | ||
383 | { | ||
384 | struct pl330_xfer *xt; | ||
385 | |||
386 | /* If queue empty */ | ||
387 | if (ch->xfer_head == NULL) | ||
388 | ch->xfer_head = xfer; | ||
389 | |||
390 | xt = &ch->xfer_head->px; | ||
391 | /* If the head already submitted (CIRCULAR head) */ | ||
392 | if (ch->options & S3C2410_DMAF_CIRCULAR && | ||
393 | (xt == ch->req[0].x || xt == ch->req[1].x)) | ||
394 | ch->xfer_head = xfer; | ||
395 | |||
396 | /* If this is a resubmission, it should go at the head */ | ||
397 | if (front) { | ||
398 | ch->xfer_head = xfer; | ||
399 | list_add(&xfer->node, &ch->xfer_list); | ||
400 | } else { | ||
401 | list_add_tail(&xfer->node, &ch->xfer_list); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | static inline void _finish_off(struct s3c_pl330_xfer *xfer, | ||
406 | enum s3c2410_dma_buffresult res, int ffree) | ||
407 | { | ||
408 | struct s3c_pl330_chan *ch; | ||
409 | |||
410 | if (!xfer) | ||
411 | return; | ||
412 | |||
413 | ch = xfer->chan; | ||
414 | |||
415 | /* Do callback */ | ||
416 | if (ch->callback_fn) | ||
417 | ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res); | ||
418 | |||
419 | /* Force Free or if buffer is not needed anymore */ | ||
420 | if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR)) | ||
421 | kmem_cache_free(ch->dmac->kmcache, xfer); | ||
422 | } | ||
423 | |||
424 | static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch, | ||
425 | struct pl330_req *r) | ||
426 | { | ||
427 | struct s3c_pl330_xfer *xfer; | ||
428 | int ret = 0; | ||
429 | |||
430 | /* If already submitted */ | ||
431 | if (r->x) | ||
432 | return 0; | ||
433 | |||
434 | xfer = get_from_queue(ch, 0); | ||
435 | if (xfer) { | ||
436 | r->x = &xfer->px; | ||
437 | |||
438 | /* Use max bandwidth for M<->M xfers */ | ||
439 | if (r->rqtype == MEMTOMEM) { | ||
440 | struct pl330_info *pi = xfer->chan->dmac->pi; | ||
441 | int burst = 1 << ch->rqcfg.brst_size; | ||
442 | u32 bytes = r->x->bytes; | ||
443 | int bl; | ||
444 | |||
445 | bl = pi->pcfg.data_bus_width / 8; | ||
446 | bl *= pi->pcfg.data_buf_dep; | ||
447 | bl /= burst; | ||
448 | |||
449 | /* src/dst_burst_len can't be more than 16 */ | ||
450 | if (bl > 16) | ||
451 | bl = 16; | ||
452 | |||
453 | while (bl > 1) { | ||
454 | if (!(bytes % (bl * burst))) | ||
455 | break; | ||
456 | bl--; | ||
457 | } | ||
458 | |||
459 | ch->rqcfg.brst_len = bl; | ||
460 | } else { | ||
461 | ch->rqcfg.brst_len = 1; | ||
462 | } | ||
463 | |||
464 | ret = pl330_submit_req(ch->pl330_chan_id, r); | ||
465 | |||
466 | /* If submission was successful */ | ||
467 | if (!ret) { | ||
468 | ch->lrq = r; /* latest submitted req */ | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | r->x = NULL; | ||
473 | |||
474 | /* If both of the PL330 ping-pong buffers filled */ | ||
475 | if (ret == -EAGAIN) { | ||
476 | dev_err(ch->dmac->pi->dev, "%s:%d!\n", | ||
477 | __func__, __LINE__); | ||
478 | /* Queue back again */ | ||
479 | add_to_queue(ch, xfer, 1); | ||
480 | ret = 0; | ||
481 | } else { | ||
482 | dev_err(ch->dmac->pi->dev, "%s:%d!\n", | ||
483 | __func__, __LINE__); | ||
484 | _finish_off(xfer, S3C2410_RES_ERR, 0); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | static void s3c_pl330_rq(struct s3c_pl330_chan *ch, | ||
492 | struct pl330_req *r, enum pl330_op_err err) | ||
493 | { | ||
494 | unsigned long flags; | ||
495 | struct s3c_pl330_xfer *xfer; | ||
496 | struct pl330_xfer *xl = r->x; | ||
497 | enum s3c2410_dma_buffresult res; | ||
498 | |||
499 | spin_lock_irqsave(&res_lock, flags); | ||
500 | |||
501 | r->x = NULL; | ||
502 | |||
503 | s3c_pl330_submit(ch, r); | ||
504 | |||
505 | spin_unlock_irqrestore(&res_lock, flags); | ||
506 | |||
507 | /* Map result to S3C DMA API */ | ||
508 | if (err == PL330_ERR_NONE) | ||
509 | res = S3C2410_RES_OK; | ||
510 | else if (err == PL330_ERR_ABORT) | ||
511 | res = S3C2410_RES_ABORT; | ||
512 | else | ||
513 | res = S3C2410_RES_ERR; | ||
514 | |||
515 | /* If last request had some xfer */ | ||
516 | if (xl) { | ||
517 | xfer = container_of(xl, struct s3c_pl330_xfer, px); | ||
518 | _finish_off(xfer, res, 0); | ||
519 | } else { | ||
520 | dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n", | ||
521 | __func__, __LINE__); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | static void s3c_pl330_rq0(void *token, enum pl330_op_err err) | ||
526 | { | ||
527 | struct pl330_req *r = token; | ||
528 | struct s3c_pl330_chan *ch = container_of(r, | ||
529 | struct s3c_pl330_chan, req[0]); | ||
530 | s3c_pl330_rq(ch, r, err); | ||
531 | } | ||
532 | |||
533 | static void s3c_pl330_rq1(void *token, enum pl330_op_err err) | ||
534 | { | ||
535 | struct pl330_req *r = token; | ||
536 | struct s3c_pl330_chan *ch = container_of(r, | ||
537 | struct s3c_pl330_chan, req[1]); | ||
538 | s3c_pl330_rq(ch, r, err); | ||
539 | } | ||
540 | |||
541 | /* Release an acquired channel */ | ||
542 | static void chan_release(struct s3c_pl330_chan *ch) | ||
543 | { | ||
544 | struct s3c_pl330_dmac *dmac; | ||
545 | |||
546 | if (chan_free(ch)) | ||
547 | return; | ||
548 | |||
549 | dmac = ch->dmac; | ||
550 | ch->dmac = NULL; | ||
551 | dmac->busy_chan--; | ||
552 | } | ||
553 | |||
554 | int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op) | ||
555 | { | ||
556 | struct s3c_pl330_xfer *xfer; | ||
557 | enum pl330_chan_op pl330op; | ||
558 | struct s3c_pl330_chan *ch; | ||
559 | unsigned long flags; | ||
560 | int idx, ret; | ||
561 | |||
562 | spin_lock_irqsave(&res_lock, flags); | ||
563 | |||
564 | ch = id_to_chan(id); | ||
565 | |||
566 | if (!ch || chan_free(ch)) { | ||
567 | ret = -EINVAL; | ||
568 | goto ctrl_exit; | ||
569 | } | ||
570 | |||
571 | switch (op) { | ||
572 | case S3C2410_DMAOP_START: | ||
573 | /* Make sure both reqs are enqueued */ | ||
574 | idx = (ch->lrq == &ch->req[0]) ? 1 : 0; | ||
575 | s3c_pl330_submit(ch, &ch->req[idx]); | ||
576 | s3c_pl330_submit(ch, &ch->req[1 - idx]); | ||
577 | pl330op = PL330_OP_START; | ||
578 | break; | ||
579 | |||
580 | case S3C2410_DMAOP_STOP: | ||
581 | pl330op = PL330_OP_ABORT; | ||
582 | break; | ||
583 | |||
584 | case S3C2410_DMAOP_FLUSH: | ||
585 | pl330op = PL330_OP_FLUSH; | ||
586 | break; | ||
587 | |||
588 | case S3C2410_DMAOP_PAUSE: | ||
589 | case S3C2410_DMAOP_RESUME: | ||
590 | case S3C2410_DMAOP_TIMEOUT: | ||
591 | case S3C2410_DMAOP_STARTED: | ||
592 | spin_unlock_irqrestore(&res_lock, flags); | ||
593 | return 0; | ||
594 | |||
595 | default: | ||
596 | spin_unlock_irqrestore(&res_lock, flags); | ||
597 | return -EINVAL; | ||
598 | } | ||
599 | |||
600 | ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op); | ||
601 | |||
602 | if (pl330op == PL330_OP_START) { | ||
603 | spin_unlock_irqrestore(&res_lock, flags); | ||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | idx = (ch->lrq == &ch->req[0]) ? 1 : 0; | ||
608 | |||
609 | /* Abort the current xfer */ | ||
610 | if (ch->req[idx].x) { | ||
611 | xfer = container_of(ch->req[idx].x, | ||
612 | struct s3c_pl330_xfer, px); | ||
613 | |||
614 | /* Drop xfer during FLUSH */ | ||
615 | if (pl330op == PL330_OP_FLUSH) | ||
616 | del_from_queue(xfer); | ||
617 | |||
618 | ch->req[idx].x = NULL; | ||
619 | |||
620 | spin_unlock_irqrestore(&res_lock, flags); | ||
621 | _finish_off(xfer, S3C2410_RES_ABORT, | ||
622 | pl330op == PL330_OP_FLUSH ? 1 : 0); | ||
623 | spin_lock_irqsave(&res_lock, flags); | ||
624 | } | ||
625 | |||
626 | /* Flush the whole queue */ | ||
627 | if (pl330op == PL330_OP_FLUSH) { | ||
628 | |||
629 | if (ch->req[1 - idx].x) { | ||
630 | xfer = container_of(ch->req[1 - idx].x, | ||
631 | struct s3c_pl330_xfer, px); | ||
632 | |||
633 | del_from_queue(xfer); | ||
634 | |||
635 | ch->req[1 - idx].x = NULL; | ||
636 | |||
637 | spin_unlock_irqrestore(&res_lock, flags); | ||
638 | _finish_off(xfer, S3C2410_RES_ABORT, 1); | ||
639 | spin_lock_irqsave(&res_lock, flags); | ||
640 | } | ||
641 | |||
642 | /* Finish off the remaining in the queue */ | ||
643 | xfer = ch->xfer_head; | ||
644 | while (xfer) { | ||
645 | |||
646 | del_from_queue(xfer); | ||
647 | |||
648 | spin_unlock_irqrestore(&res_lock, flags); | ||
649 | _finish_off(xfer, S3C2410_RES_ABORT, 1); | ||
650 | spin_lock_irqsave(&res_lock, flags); | ||
651 | |||
652 | xfer = ch->xfer_head; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | ctrl_exit: | ||
657 | spin_unlock_irqrestore(&res_lock, flags); | ||
658 | |||
659 | return ret; | ||
660 | } | ||
661 | EXPORT_SYMBOL(s3c2410_dma_ctrl); | ||
662 | |||
663 | int s3c2410_dma_enqueue(enum dma_ch id, void *token, | ||
664 | dma_addr_t addr, int size) | ||
665 | { | ||
666 | struct s3c_pl330_chan *ch; | ||
667 | struct s3c_pl330_xfer *xfer; | ||
668 | unsigned long flags; | ||
669 | int idx, ret = 0; | ||
670 | |||
671 | spin_lock_irqsave(&res_lock, flags); | ||
672 | |||
673 | ch = id_to_chan(id); | ||
674 | |||
675 | /* Error if invalid or free channel */ | ||
676 | if (!ch || chan_free(ch)) { | ||
677 | ret = -EINVAL; | ||
678 | goto enq_exit; | ||
679 | } | ||
680 | |||
681 | /* Error if size is unaligned */ | ||
682 | if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) { | ||
683 | ret = -EINVAL; | ||
684 | goto enq_exit; | ||
685 | } | ||
686 | |||
687 | xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC); | ||
688 | if (!xfer) { | ||
689 | ret = -ENOMEM; | ||
690 | goto enq_exit; | ||
691 | } | ||
692 | |||
693 | xfer->token = token; | ||
694 | xfer->chan = ch; | ||
695 | xfer->px.bytes = size; | ||
696 | xfer->px.next = NULL; /* Single request */ | ||
697 | |||
698 | /* For S3C DMA API, direction is always fixed for all xfers */ | ||
699 | if (ch->req[0].rqtype == MEMTODEV) { | ||
700 | xfer->px.src_addr = addr; | ||
701 | xfer->px.dst_addr = ch->sdaddr; | ||
702 | } else { | ||
703 | xfer->px.src_addr = ch->sdaddr; | ||
704 | xfer->px.dst_addr = addr; | ||
705 | } | ||
706 | |||
707 | add_to_queue(ch, xfer, 0); | ||
708 | |||
709 | /* Try submitting on either request */ | ||
710 | idx = (ch->lrq == &ch->req[0]) ? 1 : 0; | ||
711 | |||
712 | if (!ch->req[idx].x) | ||
713 | s3c_pl330_submit(ch, &ch->req[idx]); | ||
714 | else | ||
715 | s3c_pl330_submit(ch, &ch->req[1 - idx]); | ||
716 | |||
717 | spin_unlock_irqrestore(&res_lock, flags); | ||
718 | |||
719 | if (ch->options & S3C2410_DMAF_AUTOSTART) | ||
720 | s3c2410_dma_ctrl(id, S3C2410_DMAOP_START); | ||
721 | |||
722 | return 0; | ||
723 | |||
724 | enq_exit: | ||
725 | spin_unlock_irqrestore(&res_lock, flags); | ||
726 | |||
727 | return ret; | ||
728 | } | ||
729 | EXPORT_SYMBOL(s3c2410_dma_enqueue); | ||
730 | |||
731 | int s3c2410_dma_request(enum dma_ch id, | ||
732 | struct s3c2410_dma_client *client, | ||
733 | void *dev) | ||
734 | { | ||
735 | struct s3c_pl330_dmac *dmac; | ||
736 | struct s3c_pl330_chan *ch; | ||
737 | unsigned long flags; | ||
738 | int ret = 0; | ||
739 | |||
740 | spin_lock_irqsave(&res_lock, flags); | ||
741 | |||
742 | ch = chan_acquire(id); | ||
743 | if (!ch) { | ||
744 | ret = -EBUSY; | ||
745 | goto req_exit; | ||
746 | } | ||
747 | |||
748 | dmac = ch->dmac; | ||
749 | |||
750 | ch->pl330_chan_id = pl330_request_channel(dmac->pi); | ||
751 | if (!ch->pl330_chan_id) { | ||
752 | chan_release(ch); | ||
753 | ret = -EBUSY; | ||
754 | goto req_exit; | ||
755 | } | ||
756 | |||
757 | ch->client = client; | ||
758 | ch->options = 0; /* Clear any option */ | ||
759 | ch->callback_fn = NULL; /* Clear any callback */ | ||
760 | ch->lrq = NULL; | ||
761 | |||
762 | ch->rqcfg.brst_size = 2; /* Default word size */ | ||
763 | ch->rqcfg.swap = SWAP_NO; | ||
764 | ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */ | ||
765 | ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */ | ||
766 | ch->rqcfg.privileged = 0; | ||
767 | ch->rqcfg.insnaccess = 0; | ||
768 | |||
769 | /* Set invalid direction */ | ||
770 | ch->req[0].rqtype = DEVTODEV; | ||
771 | ch->req[1].rqtype = ch->req[0].rqtype; | ||
772 | |||
773 | ch->req[0].cfg = &ch->rqcfg; | ||
774 | ch->req[1].cfg = ch->req[0].cfg; | ||
775 | |||
776 | ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */ | ||
777 | ch->req[1].peri = ch->req[0].peri; | ||
778 | |||
779 | ch->req[0].token = &ch->req[0]; | ||
780 | ch->req[0].xfer_cb = s3c_pl330_rq0; | ||
781 | ch->req[1].token = &ch->req[1]; | ||
782 | ch->req[1].xfer_cb = s3c_pl330_rq1; | ||
783 | |||
784 | ch->req[0].x = NULL; | ||
785 | ch->req[1].x = NULL; | ||
786 | |||
787 | /* Reset xfer list */ | ||
788 | INIT_LIST_HEAD(&ch->xfer_list); | ||
789 | ch->xfer_head = NULL; | ||
790 | |||
791 | req_exit: | ||
792 | spin_unlock_irqrestore(&res_lock, flags); | ||
793 | |||
794 | return ret; | ||
795 | } | ||
796 | EXPORT_SYMBOL(s3c2410_dma_request); | ||
797 | |||
798 | int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client) | ||
799 | { | ||
800 | struct s3c_pl330_chan *ch; | ||
801 | struct s3c_pl330_xfer *xfer; | ||
802 | unsigned long flags; | ||
803 | int ret = 0; | ||
804 | unsigned idx; | ||
805 | |||
806 | spin_lock_irqsave(&res_lock, flags); | ||
807 | |||
808 | ch = id_to_chan(id); | ||
809 | |||
810 | if (!ch || chan_free(ch)) | ||
811 | goto free_exit; | ||
812 | |||
813 | /* Refuse if someone else wanted to free the channel */ | ||
814 | if (ch->client != client) { | ||
815 | ret = -EBUSY; | ||
816 | goto free_exit; | ||
817 | } | ||
818 | |||
819 | /* Stop any active xfer, Flushe the queue and do callbacks */ | ||
820 | pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH); | ||
821 | |||
822 | /* Abort the submitted requests */ | ||
823 | idx = (ch->lrq == &ch->req[0]) ? 1 : 0; | ||
824 | |||
825 | if (ch->req[idx].x) { | ||
826 | xfer = container_of(ch->req[idx].x, | ||
827 | struct s3c_pl330_xfer, px); | ||
828 | |||
829 | ch->req[idx].x = NULL; | ||
830 | del_from_queue(xfer); | ||
831 | |||
832 | spin_unlock_irqrestore(&res_lock, flags); | ||
833 | _finish_off(xfer, S3C2410_RES_ABORT, 1); | ||
834 | spin_lock_irqsave(&res_lock, flags); | ||
835 | } | ||
836 | |||
837 | if (ch->req[1 - idx].x) { | ||
838 | xfer = container_of(ch->req[1 - idx].x, | ||
839 | struct s3c_pl330_xfer, px); | ||
840 | |||
841 | ch->req[1 - idx].x = NULL; | ||
842 | del_from_queue(xfer); | ||
843 | |||
844 | spin_unlock_irqrestore(&res_lock, flags); | ||
845 | _finish_off(xfer, S3C2410_RES_ABORT, 1); | ||
846 | spin_lock_irqsave(&res_lock, flags); | ||
847 | } | ||
848 | |||
849 | /* Pluck and Abort the queued requests in order */ | ||
850 | do { | ||
851 | xfer = get_from_queue(ch, 1); | ||
852 | |||
853 | spin_unlock_irqrestore(&res_lock, flags); | ||
854 | _finish_off(xfer, S3C2410_RES_ABORT, 1); | ||
855 | spin_lock_irqsave(&res_lock, flags); | ||
856 | } while (xfer); | ||
857 | |||
858 | ch->client = NULL; | ||
859 | |||
860 | pl330_release_channel(ch->pl330_chan_id); | ||
861 | |||
862 | ch->pl330_chan_id = NULL; | ||
863 | |||
864 | chan_release(ch); | ||
865 | |||
866 | free_exit: | ||
867 | spin_unlock_irqrestore(&res_lock, flags); | ||
868 | |||
869 | return ret; | ||
870 | } | ||
871 | EXPORT_SYMBOL(s3c2410_dma_free); | ||
872 | |||
873 | int s3c2410_dma_config(enum dma_ch id, int xferunit) | ||
874 | { | ||
875 | struct s3c_pl330_chan *ch; | ||
876 | struct pl330_info *pi; | ||
877 | unsigned long flags; | ||
878 | int i, dbwidth, ret = 0; | ||
879 | |||
880 | spin_lock_irqsave(&res_lock, flags); | ||
881 | |||
882 | ch = id_to_chan(id); | ||
883 | |||
884 | if (!ch || chan_free(ch)) { | ||
885 | ret = -EINVAL; | ||
886 | goto cfg_exit; | ||
887 | } | ||
888 | |||
889 | pi = ch->dmac->pi; | ||
890 | dbwidth = pi->pcfg.data_bus_width / 8; | ||
891 | |||
892 | /* Max size of xfer can be pcfg.data_bus_width */ | ||
893 | if (xferunit > dbwidth) { | ||
894 | ret = -EINVAL; | ||
895 | goto cfg_exit; | ||
896 | } | ||
897 | |||
898 | i = 0; | ||
899 | while (xferunit != (1 << i)) | ||
900 | i++; | ||
901 | |||
902 | /* If valid value */ | ||
903 | if (xferunit == (1 << i)) | ||
904 | ch->rqcfg.brst_size = i; | ||
905 | else | ||
906 | ret = -EINVAL; | ||
907 | |||
908 | cfg_exit: | ||
909 | spin_unlock_irqrestore(&res_lock, flags); | ||
910 | |||
911 | return ret; | ||
912 | } | ||
913 | EXPORT_SYMBOL(s3c2410_dma_config); | ||
914 | |||
915 | /* Options that are supported by this driver */ | ||
916 | #define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART) | ||
917 | |||
918 | int s3c2410_dma_setflags(enum dma_ch id, unsigned int options) | ||
919 | { | ||
920 | struct s3c_pl330_chan *ch; | ||
921 | unsigned long flags; | ||
922 | int ret = 0; | ||
923 | |||
924 | spin_lock_irqsave(&res_lock, flags); | ||
925 | |||
926 | ch = id_to_chan(id); | ||
927 | |||
928 | if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS)) | ||
929 | ret = -EINVAL; | ||
930 | else | ||
931 | ch->options = options; | ||
932 | |||
933 | spin_unlock_irqrestore(&res_lock, flags); | ||
934 | |||
935 | return 0; | ||
936 | } | ||
937 | EXPORT_SYMBOL(s3c2410_dma_setflags); | ||
938 | |||
939 | int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn) | ||
940 | { | ||
941 | struct s3c_pl330_chan *ch; | ||
942 | unsigned long flags; | ||
943 | int ret = 0; | ||
944 | |||
945 | spin_lock_irqsave(&res_lock, flags); | ||
946 | |||
947 | ch = id_to_chan(id); | ||
948 | |||
949 | if (!ch || chan_free(ch)) | ||
950 | ret = -EINVAL; | ||
951 | else | ||
952 | ch->callback_fn = rtn; | ||
953 | |||
954 | spin_unlock_irqrestore(&res_lock, flags); | ||
955 | |||
956 | return ret; | ||
957 | } | ||
958 | EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); | ||
959 | |||
960 | int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source, | ||
961 | unsigned long address) | ||
962 | { | ||
963 | struct s3c_pl330_chan *ch; | ||
964 | unsigned long flags; | ||
965 | int ret = 0; | ||
966 | |||
967 | spin_lock_irqsave(&res_lock, flags); | ||
968 | |||
969 | ch = id_to_chan(id); | ||
970 | |||
971 | if (!ch || chan_free(ch)) { | ||
972 | ret = -EINVAL; | ||
973 | goto devcfg_exit; | ||
974 | } | ||
975 | |||
976 | switch (source) { | ||
977 | case S3C2410_DMASRC_HW: /* P->M */ | ||
978 | ch->req[0].rqtype = DEVTOMEM; | ||
979 | ch->req[1].rqtype = DEVTOMEM; | ||
980 | ch->rqcfg.src_inc = 0; | ||
981 | ch->rqcfg.dst_inc = 1; | ||
982 | break; | ||
983 | case S3C2410_DMASRC_MEM: /* M->P */ | ||
984 | ch->req[0].rqtype = MEMTODEV; | ||
985 | ch->req[1].rqtype = MEMTODEV; | ||
986 | ch->rqcfg.src_inc = 1; | ||
987 | ch->rqcfg.dst_inc = 0; | ||
988 | break; | ||
989 | default: | ||
990 | ret = -EINVAL; | ||
991 | goto devcfg_exit; | ||
992 | } | ||
993 | |||
994 | ch->sdaddr = address; | ||
995 | |||
996 | devcfg_exit: | ||
997 | spin_unlock_irqrestore(&res_lock, flags); | ||
998 | |||
999 | return ret; | ||
1000 | } | ||
1001 | EXPORT_SYMBOL(s3c2410_dma_devconfig); | ||
1002 | |||
1003 | int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst) | ||
1004 | { | ||
1005 | struct s3c_pl330_chan *ch = id_to_chan(id); | ||
1006 | struct pl330_chanstatus status; | ||
1007 | int ret; | ||
1008 | |||
1009 | if (!ch || chan_free(ch)) | ||
1010 | return -EINVAL; | ||
1011 | |||
1012 | ret = pl330_chan_status(ch->pl330_chan_id, &status); | ||
1013 | if (ret < 0) | ||
1014 | return ret; | ||
1015 | |||
1016 | *src = status.src_addr; | ||
1017 | *dst = status.dst_addr; | ||
1018 | |||
1019 | return 0; | ||
1020 | } | ||
1021 | EXPORT_SYMBOL(s3c2410_dma_getposition); | ||
1022 | |||
1023 | static irqreturn_t pl330_irq_handler(int irq, void *data) | ||
1024 | { | ||
1025 | if (pl330_update(data)) | ||
1026 | return IRQ_HANDLED; | ||
1027 | else | ||
1028 | return IRQ_NONE; | ||
1029 | } | ||
1030 | |||
1031 | static int pl330_probe(struct platform_device *pdev) | ||
1032 | { | ||
1033 | struct s3c_pl330_dmac *s3c_pl330_dmac; | ||
1034 | struct s3c_pl330_platdata *pl330pd; | ||
1035 | struct pl330_info *pl330_info; | ||
1036 | struct resource *res; | ||
1037 | int i, ret, irq; | ||
1038 | |||
1039 | pl330pd = pdev->dev.platform_data; | ||
1040 | |||
1041 | /* Can't do without the list of _32_ peripherals */ | ||
1042 | if (!pl330pd || !pl330pd->peri) { | ||
1043 | dev_err(&pdev->dev, "platform data missing!\n"); | ||
1044 | return -ENODEV; | ||
1045 | } | ||
1046 | |||
1047 | pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL); | ||
1048 | if (!pl330_info) | ||
1049 | return -ENOMEM; | ||
1050 | |||
1051 | pl330_info->pl330_data = NULL; | ||
1052 | pl330_info->dev = &pdev->dev; | ||
1053 | |||
1054 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1055 | if (!res) { | ||
1056 | ret = -ENODEV; | ||
1057 | goto probe_err1; | ||
1058 | } | ||
1059 | |||
1060 | request_mem_region(res->start, resource_size(res), pdev->name); | ||
1061 | |||
1062 | pl330_info->base = ioremap(res->start, resource_size(res)); | ||
1063 | if (!pl330_info->base) { | ||
1064 | ret = -ENXIO; | ||
1065 | goto probe_err2; | ||
1066 | } | ||
1067 | |||
1068 | irq = platform_get_irq(pdev, 0); | ||
1069 | if (irq < 0) { | ||
1070 | ret = irq; | ||
1071 | goto probe_err3; | ||
1072 | } | ||
1073 | |||
1074 | ret = request_irq(irq, pl330_irq_handler, 0, | ||
1075 | dev_name(&pdev->dev), pl330_info); | ||
1076 | if (ret) | ||
1077 | goto probe_err4; | ||
1078 | |||
1079 | /* Allocate a new DMAC */ | ||
1080 | s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL); | ||
1081 | if (!s3c_pl330_dmac) { | ||
1082 | ret = -ENOMEM; | ||
1083 | goto probe_err5; | ||
1084 | } | ||
1085 | |||
1086 | /* Get operation clock and enable it */ | ||
1087 | s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma"); | ||
1088 | if (IS_ERR(s3c_pl330_dmac->clk)) { | ||
1089 | dev_err(&pdev->dev, "Cannot get operation clock.\n"); | ||
1090 | ret = -EINVAL; | ||
1091 | goto probe_err6; | ||
1092 | } | ||
1093 | clk_enable(s3c_pl330_dmac->clk); | ||
1094 | |||
1095 | ret = pl330_add(pl330_info); | ||
1096 | if (ret) | ||
1097 | goto probe_err7; | ||
1098 | |||
1099 | /* Hook the info */ | ||
1100 | s3c_pl330_dmac->pi = pl330_info; | ||
1101 | |||
1102 | /* No busy channels */ | ||
1103 | s3c_pl330_dmac->busy_chan = 0; | ||
1104 | |||
1105 | s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev), | ||
1106 | sizeof(struct s3c_pl330_xfer), 0, 0, NULL); | ||
1107 | |||
1108 | if (!s3c_pl330_dmac->kmcache) { | ||
1109 | ret = -ENOMEM; | ||
1110 | goto probe_err8; | ||
1111 | } | ||
1112 | |||
1113 | /* Get the list of peripherals */ | ||
1114 | s3c_pl330_dmac->peri = pl330pd->peri; | ||
1115 | |||
1116 | /* Attach to the list of DMACs */ | ||
1117 | list_add_tail(&s3c_pl330_dmac->node, &dmac_list); | ||
1118 | |||
1119 | /* Create a channel for each peripheral in the DMAC | ||
1120 | * that is, if it doesn't already exist | ||
1121 | */ | ||
1122 | for (i = 0; i < PL330_MAX_PERI; i++) | ||
1123 | if (s3c_pl330_dmac->peri[i] != DMACH_MAX) | ||
1124 | chan_add(s3c_pl330_dmac->peri[i]); | ||
1125 | |||
1126 | printk(KERN_INFO | ||
1127 | "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name); | ||
1128 | printk(KERN_INFO | ||
1129 | "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", | ||
1130 | pl330_info->pcfg.data_buf_dep, | ||
1131 | pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan, | ||
1132 | pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events); | ||
1133 | |||
1134 | return 0; | ||
1135 | |||
1136 | probe_err8: | ||
1137 | pl330_del(pl330_info); | ||
1138 | probe_err7: | ||
1139 | clk_disable(s3c_pl330_dmac->clk); | ||
1140 | clk_put(s3c_pl330_dmac->clk); | ||
1141 | probe_err6: | ||
1142 | kfree(s3c_pl330_dmac); | ||
1143 | probe_err5: | ||
1144 | free_irq(irq, pl330_info); | ||
1145 | probe_err4: | ||
1146 | probe_err3: | ||
1147 | iounmap(pl330_info->base); | ||
1148 | probe_err2: | ||
1149 | release_mem_region(res->start, resource_size(res)); | ||
1150 | probe_err1: | ||
1151 | kfree(pl330_info); | ||
1152 | |||
1153 | return ret; | ||
1154 | } | ||
1155 | |||
1156 | static int pl330_remove(struct platform_device *pdev) | ||
1157 | { | ||
1158 | struct s3c_pl330_dmac *dmac, *d; | ||
1159 | struct s3c_pl330_chan *ch; | ||
1160 | unsigned long flags; | ||
1161 | int del, found; | ||
1162 | |||
1163 | if (!pdev->dev.platform_data) | ||
1164 | return -EINVAL; | ||
1165 | |||
1166 | spin_lock_irqsave(&res_lock, flags); | ||
1167 | |||
1168 | found = 0; | ||
1169 | list_for_each_entry(d, &dmac_list, node) | ||
1170 | if (d->pi->dev == &pdev->dev) { | ||
1171 | found = 1; | ||
1172 | break; | ||
1173 | } | ||
1174 | |||
1175 | if (!found) { | ||
1176 | spin_unlock_irqrestore(&res_lock, flags); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | dmac = d; | ||
1181 | |||
1182 | /* Remove all Channels that are managed only by this DMAC */ | ||
1183 | list_for_each_entry(ch, &chan_list, node) { | ||
1184 | |||
1185 | /* Only channels that are handled by this DMAC */ | ||
1186 | if (iface_of_dmac(dmac, ch->id)) | ||
1187 | del = 1; | ||
1188 | else | ||
1189 | continue; | ||
1190 | |||
1191 | /* Don't remove if some other DMAC has it too */ | ||
1192 | list_for_each_entry(d, &dmac_list, node) | ||
1193 | if (d != dmac && iface_of_dmac(d, ch->id)) { | ||
1194 | del = 0; | ||
1195 | break; | ||
1196 | } | ||
1197 | |||
1198 | if (del) { | ||
1199 | spin_unlock_irqrestore(&res_lock, flags); | ||
1200 | s3c2410_dma_free(ch->id, ch->client); | ||
1201 | spin_lock_irqsave(&res_lock, flags); | ||
1202 | list_del(&ch->node); | ||
1203 | kfree(ch); | ||
1204 | } | ||
1205 | } | ||
1206 | |||
1207 | /* Disable operation clock */ | ||
1208 | clk_disable(dmac->clk); | ||
1209 | clk_put(dmac->clk); | ||
1210 | |||
1211 | /* Remove the DMAC */ | ||
1212 | list_del(&dmac->node); | ||
1213 | kfree(dmac); | ||
1214 | |||
1215 | spin_unlock_irqrestore(&res_lock, flags); | ||
1216 | |||
1217 | return 0; | ||
1218 | } | ||
1219 | |||
1220 | static struct platform_driver pl330_driver = { | ||
1221 | .driver = { | ||
1222 | .owner = THIS_MODULE, | ||
1223 | .name = "s3c-pl330", | ||
1224 | }, | ||
1225 | .probe = pl330_probe, | ||
1226 | .remove = pl330_remove, | ||
1227 | }; | ||
1228 | |||
1229 | static int __init pl330_init(void) | ||
1230 | { | ||
1231 | return platform_driver_register(&pl330_driver); | ||
1232 | } | ||
1233 | module_init(pl330_init); | ||
1234 | |||
1235 | static void __exit pl330_exit(void) | ||
1236 | { | ||
1237 | platform_driver_unregister(&pl330_driver); | ||
1238 | return; | ||
1239 | } | ||
1240 | module_exit(pl330_exit); | ||
1241 | |||
1242 | MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); | ||
1243 | MODULE_DESCRIPTION("Driver for PL330 DMA Controller"); | ||
1244 | MODULE_LICENSE("GPL"); | ||