diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2010-08-13 19:59:15 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2010-08-13 19:59:15 -0400 |
commit | 7d72e6fa56c4100b9669efe0044f77ed9eb785a1 (patch) | |
tree | 5e90bf4969809a1ab20b97432b85be20ccfaa1f4 /drivers | |
parent | ba00376b0b13f234d839541a7b36a5bf5c2a4036 (diff) | |
parent | 2be1f3a73dd02e38e181cf5abacb3d45a6a2d6b8 (diff) |
Merge branch 'master' into for-linus
Diffstat (limited to 'drivers')
492 files changed, 20848 insertions, 3755 deletions
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 864dd46c346f..18645f4e83cd 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/uaccess.h> | 33 | #include <linux/uaccess.h> |
34 | #include <linux/cper.h> | 34 | #include <linux/cper.h> |
35 | #include <linux/nmi.h> | 35 | #include <linux/nmi.h> |
36 | #include <linux/hardirq.h> | ||
36 | #include <acpi/apei.h> | 37 | #include <acpi/apei.h> |
37 | 38 | ||
38 | #include "apei-internal.h" | 39 | #include "apei-internal.h" |
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 146135e7a6a1..295dbfa2db9c 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c | |||
@@ -96,7 +96,8 @@ static const struct acpi_dlevel acpi_debug_levels[] = { | |||
96 | /* -------------------------------------------------------------------------- | 96 | /* -------------------------------------------------------------------------- |
97 | FS Interface (/sys) | 97 | FS Interface (/sys) |
98 | -------------------------------------------------------------------------- */ | 98 | -------------------------------------------------------------------------- */ |
99 | static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { | 99 | static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) |
100 | { | ||
100 | int result = 0; | 101 | int result = 0; |
101 | int i; | 102 | int i; |
102 | 103 | ||
@@ -118,7 +119,8 @@ static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { | |||
118 | return result; | 119 | return result; |
119 | } | 120 | } |
120 | 121 | ||
121 | static int param_get_debug_level(char *buffer, struct kernel_param *kp) { | 122 | static int param_get_debug_level(char *buffer, const struct kernel_param *kp) |
123 | { | ||
122 | int result = 0; | 124 | int result = 0; |
123 | int i; | 125 | int i; |
124 | 126 | ||
@@ -137,8 +139,18 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) { | |||
137 | return result; | 139 | return result; |
138 | } | 140 | } |
139 | 141 | ||
140 | module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); | 142 | static struct kernel_param_ops acpi_debug_layer_ops = { |
141 | module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); | 143 | .set = param_set_uint, |
144 | .get = param_get_debug_layer, | ||
145 | }; | ||
146 | |||
147 | static struct kernel_param_ops acpi_debug_level_ops = { | ||
148 | .set = param_set_uint, | ||
149 | .get = param_get_debug_level, | ||
150 | }; | ||
151 | |||
152 | module_param_cb(debug_layer, &acpi_debug_layer_ops, &acpi_dbg_layer, 0644); | ||
153 | module_param_cb(debug_level, &acpi_debug_level_ops, &acpi_dbg_level, 0644); | ||
142 | 154 | ||
143 | static char trace_method_name[6]; | 155 | static char trace_method_name[6]; |
144 | module_param_string(trace_method_name, trace_method_name, 6, 0644); | 156 | module_param_string(trace_method_name, trace_method_name, 6, 0644); |
@@ -147,7 +159,7 @@ module_param(trace_debug_layer, uint, 0644); | |||
147 | static unsigned int trace_debug_level; | 159 | static unsigned int trace_debug_level; |
148 | module_param(trace_debug_level, uint, 0644); | 160 | module_param(trace_debug_level, uint, 0644); |
149 | 161 | ||
150 | static int param_set_trace_state(const char *val, struct kernel_param *kp) | 162 | static int param_set_trace_state(const char *val, const struct kernel_param *kp) |
151 | { | 163 | { |
152 | int result = 0; | 164 | int result = 0; |
153 | 165 | ||
@@ -181,7 +193,7 @@ exit: | |||
181 | return result; | 193 | return result; |
182 | } | 194 | } |
183 | 195 | ||
184 | static int param_get_trace_state(char *buffer, struct kernel_param *kp) | 196 | static int param_get_trace_state(char *buffer, const struct kernel_param *kp) |
185 | { | 197 | { |
186 | if (!acpi_gbl_trace_method_name) | 198 | if (!acpi_gbl_trace_method_name) |
187 | return sprintf(buffer, "disable"); | 199 | return sprintf(buffer, "disable"); |
@@ -194,8 +206,12 @@ static int param_get_trace_state(char *buffer, struct kernel_param *kp) | |||
194 | return 0; | 206 | return 0; |
195 | } | 207 | } |
196 | 208 | ||
197 | module_param_call(trace_state, param_set_trace_state, param_get_trace_state, | 209 | static struct kernel_param_ops param_ops_trace_state = { |
198 | NULL, 0644); | 210 | .set = param_set_trace_state, |
211 | .get = param_get_trace_state, | ||
212 | }; | ||
213 | |||
214 | module_param_cb(trace_state, ¶m_ops_trace_state, NULL, 0644); | ||
199 | 215 | ||
200 | /* -------------------------------------------------------------------------- | 216 | /* -------------------------------------------------------------------------- |
201 | DebugFS Interface | 217 | DebugFS Interface |
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 8fae6afd6a3d..65e3e2708371 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -651,6 +651,17 @@ config PATA_VIA | |||
651 | 651 | ||
652 | If unsure, say N. | 652 | If unsure, say N. |
653 | 653 | ||
654 | config PATA_PXA | ||
655 | tristate "PXA DMA-capable PATA support" | ||
656 | depends on ARCH_PXA | ||
657 | help | ||
658 | This option enables support for harddrive attached to PXA CPU's bus. | ||
659 | |||
660 | NOTE: This driver utilizes PXA DMA controller, in case your hardware | ||
661 | is not capable of doing MWDMA, use pata_platform instead. | ||
662 | |||
663 | If unsure, say N. | ||
664 | |||
654 | config PATA_WINBOND | 665 | config PATA_WINBOND |
655 | tristate "Winbond SL82C105 PATA support" | 666 | tristate "Winbond SL82C105 PATA support" |
656 | depends on PCI | 667 | depends on PCI |
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 6540632bda08..158eaa961b1e 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
@@ -91,6 +91,8 @@ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o | |||
91 | obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o | 91 | obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o |
92 | obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o | 92 | obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o |
93 | 93 | ||
94 | obj-$(CONFIG_PATA_PXA) += pata_pxa.o | ||
95 | |||
94 | # Should be last but two libata driver | 96 | # Should be last but two libata driver |
95 | obj-$(CONFIG_PATA_ACPI) += pata_acpi.o | 97 | obj-$(CONFIG_PATA_ACPI) += pata_acpi.o |
96 | # Should be last but one libata driver | 98 | # Should be last but one libata driver |
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index f087ab55b1df..8cc536e49a0a 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c | |||
@@ -680,7 +680,7 @@ mpc52xx_ata_remove_one(struct device *dev) | |||
680 | /* ======================================================================== */ | 680 | /* ======================================================================== */ |
681 | 681 | ||
682 | static int __devinit | 682 | static int __devinit |
683 | mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) | 683 | mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match) |
684 | { | 684 | { |
685 | unsigned int ipb_freq; | 685 | unsigned int ipb_freq; |
686 | struct resource res_mem; | 686 | struct resource res_mem; |
@@ -821,7 +821,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) | |||
821 | } | 821 | } |
822 | 822 | ||
823 | static int | 823 | static int |
824 | mpc52xx_ata_remove(struct of_device *op) | 824 | mpc52xx_ata_remove(struct platform_device *op) |
825 | { | 825 | { |
826 | struct mpc52xx_ata_priv *priv; | 826 | struct mpc52xx_ata_priv *priv; |
827 | int task_irq; | 827 | int task_irq; |
@@ -848,7 +848,7 @@ mpc52xx_ata_remove(struct of_device *op) | |||
848 | #ifdef CONFIG_PM | 848 | #ifdef CONFIG_PM |
849 | 849 | ||
850 | static int | 850 | static int |
851 | mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) | 851 | mpc52xx_ata_suspend(struct platform_device *op, pm_message_t state) |
852 | { | 852 | { |
853 | struct ata_host *host = dev_get_drvdata(&op->dev); | 853 | struct ata_host *host = dev_get_drvdata(&op->dev); |
854 | 854 | ||
@@ -856,7 +856,7 @@ mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) | |||
856 | } | 856 | } |
857 | 857 | ||
858 | static int | 858 | static int |
859 | mpc52xx_ata_resume(struct of_device *op) | 859 | mpc52xx_ata_resume(struct platform_device *op) |
860 | { | 860 | { |
861 | struct ata_host *host = dev_get_drvdata(&op->dev); | 861 | struct ata_host *host = dev_get_drvdata(&op->dev); |
862 | struct mpc52xx_ata_priv *priv = host->private_data; | 862 | struct mpc52xx_ata_priv *priv = host->private_data; |
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 5a1b82c08be9..480e043ce6b8 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
15 | #include <linux/ata_platform.h> | 15 | #include <linux/ata_platform.h> |
16 | 16 | ||
17 | static int __devinit pata_of_platform_probe(struct of_device *ofdev, | 17 | static int __devinit pata_of_platform_probe(struct platform_device *ofdev, |
18 | const struct of_device_id *match) | 18 | const struct of_device_id *match) |
19 | { | 19 | { |
20 | int ret; | 20 | int ret; |
@@ -78,7 +78,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev, | |||
78 | reg_shift, pio_mask); | 78 | reg_shift, pio_mask); |
79 | } | 79 | } |
80 | 80 | ||
81 | static int __devexit pata_of_platform_remove(struct of_device *ofdev) | 81 | static int __devexit pata_of_platform_remove(struct platform_device *ofdev) |
82 | { | 82 | { |
83 | return __pata_platform_remove(&ofdev->dev); | 83 | return __pata_platform_remove(&ofdev->dev); |
84 | } | 84 | } |
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c new file mode 100644 index 000000000000..1898c6ed4b4e --- /dev/null +++ b/drivers/ata/pata_pxa.c | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | * Generic PXA PATA driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.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, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; see the file COPYING. If not, write to | ||
18 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/blkdev.h> | ||
25 | #include <linux/ata.h> | ||
26 | #include <linux/libata.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/gpio.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/completion.h> | ||
31 | |||
32 | #include <scsi/scsi_host.h> | ||
33 | |||
34 | #include <mach/pxa2xx-regs.h> | ||
35 | #include <mach/pata_pxa.h> | ||
36 | #include <mach/dma.h> | ||
37 | |||
38 | #define DRV_NAME "pata_pxa" | ||
39 | #define DRV_VERSION "0.1" | ||
40 | |||
41 | struct pata_pxa_data { | ||
42 | uint32_t dma_channel; | ||
43 | struct pxa_dma_desc *dma_desc; | ||
44 | dma_addr_t dma_desc_addr; | ||
45 | uint32_t dma_desc_id; | ||
46 | |||
47 | /* DMA IO physical address */ | ||
48 | uint32_t dma_io_addr; | ||
49 | /* PXA DREQ<0:2> pin selector */ | ||
50 | uint32_t dma_dreq; | ||
51 | /* DMA DCSR register value */ | ||
52 | uint32_t dma_dcsr; | ||
53 | |||
54 | struct completion dma_done; | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * Setup the DMA descriptors. The size is transfer capped at 4k per descriptor, | ||
59 | * if the transfer is longer, it is split into multiple chained descriptors. | ||
60 | */ | ||
61 | static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc) | ||
62 | { | ||
63 | struct pata_pxa_data *pd = qc->ap->private_data; | ||
64 | |||
65 | uint32_t cpu_len, seg_len; | ||
66 | dma_addr_t cpu_addr; | ||
67 | |||
68 | cpu_addr = sg_dma_address(sg); | ||
69 | cpu_len = sg_dma_len(sg); | ||
70 | |||
71 | do { | ||
72 | seg_len = (cpu_len > 0x1000) ? 0x1000 : cpu_len; | ||
73 | |||
74 | pd->dma_desc[pd->dma_desc_id].ddadr = pd->dma_desc_addr + | ||
75 | ((pd->dma_desc_id + 1) * sizeof(struct pxa_dma_desc)); | ||
76 | |||
77 | pd->dma_desc[pd->dma_desc_id].dcmd = DCMD_BURST32 | | ||
78 | DCMD_WIDTH2 | (DCMD_LENGTH & seg_len); | ||
79 | |||
80 | if (qc->tf.flags & ATA_TFLAG_WRITE) { | ||
81 | pd->dma_desc[pd->dma_desc_id].dsadr = cpu_addr; | ||
82 | pd->dma_desc[pd->dma_desc_id].dtadr = pd->dma_io_addr; | ||
83 | pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCSRCADDR | | ||
84 | DCMD_FLOWTRG; | ||
85 | } else { | ||
86 | pd->dma_desc[pd->dma_desc_id].dsadr = pd->dma_io_addr; | ||
87 | pd->dma_desc[pd->dma_desc_id].dtadr = cpu_addr; | ||
88 | pd->dma_desc[pd->dma_desc_id].dcmd |= DCMD_INCTRGADDR | | ||
89 | DCMD_FLOWSRC; | ||
90 | } | ||
91 | |||
92 | cpu_len -= seg_len; | ||
93 | cpu_addr += seg_len; | ||
94 | pd->dma_desc_id++; | ||
95 | |||
96 | } while (cpu_len); | ||
97 | |||
98 | /* Should not happen */ | ||
99 | if (seg_len & 0x1f) | ||
100 | DALGN |= (1 << pd->dma_dreq); | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Prepare taskfile for submission. | ||
105 | */ | ||
106 | static void pxa_qc_prep(struct ata_queued_cmd *qc) | ||
107 | { | ||
108 | struct pata_pxa_data *pd = qc->ap->private_data; | ||
109 | int si = 0; | ||
110 | struct scatterlist *sg; | ||
111 | |||
112 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) | ||
113 | return; | ||
114 | |||
115 | pd->dma_desc_id = 0; | ||
116 | |||
117 | DCSR(pd->dma_channel) = 0; | ||
118 | DALGN &= ~(1 << pd->dma_dreq); | ||
119 | |||
120 | for_each_sg(qc->sg, sg, qc->n_elem, si) | ||
121 | pxa_load_dmac(sg, qc); | ||
122 | |||
123 | pd->dma_desc[pd->dma_desc_id - 1].ddadr = DDADR_STOP; | ||
124 | |||
125 | /* Fire IRQ only at the end of last block */ | ||
126 | pd->dma_desc[pd->dma_desc_id - 1].dcmd |= DCMD_ENDIRQEN; | ||
127 | |||
128 | DDADR(pd->dma_channel) = pd->dma_desc_addr; | ||
129 | DRCMR(pd->dma_dreq) = DRCMR_MAPVLD | pd->dma_channel; | ||
130 | |||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Configure the DMA controller, load the DMA descriptors, but don't start the | ||
135 | * DMA controller yet. Only issue the ATA command. | ||
136 | */ | ||
137 | static void pxa_bmdma_setup(struct ata_queued_cmd *qc) | ||
138 | { | ||
139 | qc->ap->ops->sff_exec_command(qc->ap, &qc->tf); | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * Execute the DMA transfer. | ||
144 | */ | ||
145 | static void pxa_bmdma_start(struct ata_queued_cmd *qc) | ||
146 | { | ||
147 | struct pata_pxa_data *pd = qc->ap->private_data; | ||
148 | init_completion(&pd->dma_done); | ||
149 | DCSR(pd->dma_channel) = DCSR_RUN; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Wait until the DMA transfer completes, then stop the DMA controller. | ||
154 | */ | ||
155 | static void pxa_bmdma_stop(struct ata_queued_cmd *qc) | ||
156 | { | ||
157 | struct pata_pxa_data *pd = qc->ap->private_data; | ||
158 | |||
159 | if ((DCSR(pd->dma_channel) & DCSR_RUN) && | ||
160 | wait_for_completion_timeout(&pd->dma_done, HZ)) | ||
161 | dev_err(qc->ap->dev, "Timeout waiting for DMA completion!"); | ||
162 | |||
163 | DCSR(pd->dma_channel) = 0; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * Read DMA status. The bmdma_stop() will take care of properly finishing the | ||
168 | * DMA transfer so we always have DMA-complete interrupt here. | ||
169 | */ | ||
170 | static unsigned char pxa_bmdma_status(struct ata_port *ap) | ||
171 | { | ||
172 | struct pata_pxa_data *pd = ap->private_data; | ||
173 | unsigned char ret = ATA_DMA_INTR; | ||
174 | |||
175 | if (pd->dma_dcsr & DCSR_BUSERR) | ||
176 | ret |= ATA_DMA_ERR; | ||
177 | |||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * No IRQ register present so we do nothing. | ||
183 | */ | ||
184 | static void pxa_irq_clear(struct ata_port *ap) | ||
185 | { | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Check for ATAPI DMA. ATAPI DMA is unsupported by this driver. It's still | ||
190 | * unclear why ATAPI has DMA issues. | ||
191 | */ | ||
192 | static int pxa_check_atapi_dma(struct ata_queued_cmd *qc) | ||
193 | { | ||
194 | return -EOPNOTSUPP; | ||
195 | } | ||
196 | |||
197 | static struct scsi_host_template pxa_ata_sht = { | ||
198 | ATA_BMDMA_SHT(DRV_NAME), | ||
199 | }; | ||
200 | |||
201 | static struct ata_port_operations pxa_ata_port_ops = { | ||
202 | .inherits = &ata_bmdma_port_ops, | ||
203 | .cable_detect = ata_cable_40wire, | ||
204 | |||
205 | .bmdma_setup = pxa_bmdma_setup, | ||
206 | .bmdma_start = pxa_bmdma_start, | ||
207 | .bmdma_stop = pxa_bmdma_stop, | ||
208 | .bmdma_status = pxa_bmdma_status, | ||
209 | |||
210 | .check_atapi_dma = pxa_check_atapi_dma, | ||
211 | |||
212 | .sff_irq_clear = pxa_irq_clear, | ||
213 | |||
214 | .qc_prep = pxa_qc_prep, | ||
215 | }; | ||
216 | |||
217 | /* | ||
218 | * DMA interrupt handler. | ||
219 | */ | ||
220 | static void pxa_ata_dma_irq(int dma, void *port) | ||
221 | { | ||
222 | struct ata_port *ap = port; | ||
223 | struct pata_pxa_data *pd = ap->private_data; | ||
224 | |||
225 | pd->dma_dcsr = DCSR(dma); | ||
226 | DCSR(dma) = pd->dma_dcsr; | ||
227 | |||
228 | if (pd->dma_dcsr & DCSR_STOPSTATE) | ||
229 | complete(&pd->dma_done); | ||
230 | } | ||
231 | |||
232 | static int __devinit pxa_ata_probe(struct platform_device *pdev) | ||
233 | { | ||
234 | struct ata_host *host; | ||
235 | struct ata_port *ap; | ||
236 | struct pata_pxa_data *data; | ||
237 | struct resource *cmd_res; | ||
238 | struct resource *ctl_res; | ||
239 | struct resource *dma_res; | ||
240 | struct resource *irq_res; | ||
241 | struct pata_pxa_pdata *pdata = pdev->dev.platform_data; | ||
242 | int ret = 0; | ||
243 | |||
244 | /* | ||
245 | * Resource validation, three resources are needed: | ||
246 | * - CMD port base address | ||
247 | * - CTL port base address | ||
248 | * - DMA port base address | ||
249 | * - IRQ pin | ||
250 | */ | ||
251 | if (pdev->num_resources != 4) { | ||
252 | dev_err(&pdev->dev, "invalid number of resources\n"); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * CMD port base address | ||
258 | */ | ||
259 | cmd_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
260 | if (unlikely(cmd_res == NULL)) | ||
261 | return -EINVAL; | ||
262 | |||
263 | /* | ||
264 | * CTL port base address | ||
265 | */ | ||
266 | ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
267 | if (unlikely(ctl_res == NULL)) | ||
268 | return -EINVAL; | ||
269 | |||
270 | /* | ||
271 | * DMA port base address | ||
272 | */ | ||
273 | dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
274 | if (unlikely(dma_res == NULL)) | ||
275 | return -EINVAL; | ||
276 | |||
277 | /* | ||
278 | * IRQ pin | ||
279 | */ | ||
280 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
281 | if (unlikely(irq_res == NULL)) | ||
282 | return -EINVAL; | ||
283 | |||
284 | /* | ||
285 | * Allocate the host | ||
286 | */ | ||
287 | host = ata_host_alloc(&pdev->dev, 1); | ||
288 | if (!host) | ||
289 | return -ENOMEM; | ||
290 | |||
291 | ap = host->ports[0]; | ||
292 | ap->ops = &pxa_ata_port_ops; | ||
293 | ap->pio_mask = ATA_PIO4; | ||
294 | ap->mwdma_mask = ATA_MWDMA2; | ||
295 | ap->flags = ATA_FLAG_MMIO; | ||
296 | |||
297 | ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, cmd_res->start, | ||
298 | resource_size(cmd_res)); | ||
299 | ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start, | ||
300 | resource_size(ctl_res)); | ||
301 | ap->ioaddr.bmdma_addr = devm_ioremap(&pdev->dev, dma_res->start, | ||
302 | resource_size(dma_res)); | ||
303 | |||
304 | /* | ||
305 | * Adjust register offsets | ||
306 | */ | ||
307 | ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; | ||
308 | ap->ioaddr.data_addr = ap->ioaddr.cmd_addr + | ||
309 | (ATA_REG_DATA << pdata->reg_shift); | ||
310 | ap->ioaddr.error_addr = ap->ioaddr.cmd_addr + | ||
311 | (ATA_REG_ERR << pdata->reg_shift); | ||
312 | ap->ioaddr.feature_addr = ap->ioaddr.cmd_addr + | ||
313 | (ATA_REG_FEATURE << pdata->reg_shift); | ||
314 | ap->ioaddr.nsect_addr = ap->ioaddr.cmd_addr + | ||
315 | (ATA_REG_NSECT << pdata->reg_shift); | ||
316 | ap->ioaddr.lbal_addr = ap->ioaddr.cmd_addr + | ||
317 | (ATA_REG_LBAL << pdata->reg_shift); | ||
318 | ap->ioaddr.lbam_addr = ap->ioaddr.cmd_addr + | ||
319 | (ATA_REG_LBAM << pdata->reg_shift); | ||
320 | ap->ioaddr.lbah_addr = ap->ioaddr.cmd_addr + | ||
321 | (ATA_REG_LBAH << pdata->reg_shift); | ||
322 | ap->ioaddr.device_addr = ap->ioaddr.cmd_addr + | ||
323 | (ATA_REG_DEVICE << pdata->reg_shift); | ||
324 | ap->ioaddr.status_addr = ap->ioaddr.cmd_addr + | ||
325 | (ATA_REG_STATUS << pdata->reg_shift); | ||
326 | ap->ioaddr.command_addr = ap->ioaddr.cmd_addr + | ||
327 | (ATA_REG_CMD << pdata->reg_shift); | ||
328 | |||
329 | /* | ||
330 | * Allocate and load driver's internal data structure | ||
331 | */ | ||
332 | data = devm_kzalloc(&pdev->dev, sizeof(struct pata_pxa_data), | ||
333 | GFP_KERNEL); | ||
334 | if (!data) | ||
335 | return -ENOMEM; | ||
336 | |||
337 | ap->private_data = data; | ||
338 | data->dma_dreq = pdata->dma_dreq; | ||
339 | data->dma_io_addr = dma_res->start; | ||
340 | |||
341 | /* | ||
342 | * Allocate space for the DMA descriptors | ||
343 | */ | ||
344 | data->dma_desc = dmam_alloc_coherent(&pdev->dev, PAGE_SIZE, | ||
345 | &data->dma_desc_addr, GFP_KERNEL); | ||
346 | if (!data->dma_desc) | ||
347 | return -EINVAL; | ||
348 | |||
349 | /* | ||
350 | * Request the DMA channel | ||
351 | */ | ||
352 | data->dma_channel = pxa_request_dma(DRV_NAME, DMA_PRIO_LOW, | ||
353 | pxa_ata_dma_irq, ap); | ||
354 | if (data->dma_channel < 0) | ||
355 | return -EBUSY; | ||
356 | |||
357 | /* | ||
358 | * Stop and clear the DMA channel | ||
359 | */ | ||
360 | DCSR(data->dma_channel) = 0; | ||
361 | |||
362 | /* | ||
363 | * Activate the ATA host | ||
364 | */ | ||
365 | ret = ata_host_activate(host, irq_res->start, ata_sff_interrupt, | ||
366 | pdata->irq_flags, &pxa_ata_sht); | ||
367 | if (ret) | ||
368 | pxa_free_dma(data->dma_channel); | ||
369 | |||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | static int __devexit pxa_ata_remove(struct platform_device *pdev) | ||
374 | { | ||
375 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
376 | struct pata_pxa_data *data = host->ports[0]->private_data; | ||
377 | |||
378 | pxa_free_dma(data->dma_channel); | ||
379 | |||
380 | ata_host_detach(host); | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static struct platform_driver pxa_ata_driver = { | ||
386 | .probe = pxa_ata_probe, | ||
387 | .remove = __devexit_p(pxa_ata_remove), | ||
388 | .driver = { | ||
389 | .name = DRV_NAME, | ||
390 | .owner = THIS_MODULE, | ||
391 | }, | ||
392 | }; | ||
393 | |||
394 | static int __init pxa_ata_init(void) | ||
395 | { | ||
396 | return platform_driver_register(&pxa_ata_driver); | ||
397 | } | ||
398 | |||
399 | static void __exit pxa_ata_exit(void) | ||
400 | { | ||
401 | platform_driver_unregister(&pxa_ata_driver); | ||
402 | } | ||
403 | |||
404 | module_init(pxa_ata_init); | ||
405 | module_exit(pxa_ata_exit); | ||
406 | |||
407 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
408 | MODULE_DESCRIPTION("DMA-capable driver for PATA on PXA CPU"); | ||
409 | MODULE_LICENSE("GPL"); | ||
410 | MODULE_VERSION(DRV_VERSION); | ||
411 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 18c986dbb7f1..7325f77480dc 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c | |||
@@ -1296,7 +1296,7 @@ static const struct ata_port_info sata_fsl_port_info[] = { | |||
1296 | }, | 1296 | }, |
1297 | }; | 1297 | }; |
1298 | 1298 | ||
1299 | static int sata_fsl_probe(struct of_device *ofdev, | 1299 | static int sata_fsl_probe(struct platform_device *ofdev, |
1300 | const struct of_device_id *match) | 1300 | const struct of_device_id *match) |
1301 | { | 1301 | { |
1302 | int retval = -ENXIO; | 1302 | int retval = -ENXIO; |
@@ -1370,7 +1370,7 @@ error_exit_with_cleanup: | |||
1370 | return retval; | 1370 | return retval; |
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | static int sata_fsl_remove(struct of_device *ofdev) | 1373 | static int sata_fsl_remove(struct platform_device *ofdev) |
1374 | { | 1374 | { |
1375 | struct ata_host *host = dev_get_drvdata(&ofdev->dev); | 1375 | struct ata_host *host = dev_get_drvdata(&ofdev->dev); |
1376 | struct sata_fsl_host_priv *host_priv = host->private_data; | 1376 | struct sata_fsl_host_priv *host_priv = host->private_data; |
@@ -1387,13 +1387,13 @@ static int sata_fsl_remove(struct of_device *ofdev) | |||
1387 | } | 1387 | } |
1388 | 1388 | ||
1389 | #ifdef CONFIG_PM | 1389 | #ifdef CONFIG_PM |
1390 | static int sata_fsl_suspend(struct of_device *op, pm_message_t state) | 1390 | static int sata_fsl_suspend(struct platform_device *op, pm_message_t state) |
1391 | { | 1391 | { |
1392 | struct ata_host *host = dev_get_drvdata(&op->dev); | 1392 | struct ata_host *host = dev_get_drvdata(&op->dev); |
1393 | return ata_host_suspend(host, state); | 1393 | return ata_host_suspend(host, state); |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | static int sata_fsl_resume(struct of_device *op) | 1396 | static int sata_fsl_resume(struct platform_device *op) |
1397 | { | 1397 | { |
1398 | struct ata_host *host = dev_get_drvdata(&op->dev); | 1398 | struct ata_host *host = dev_get_drvdata(&op->dev); |
1399 | struct sata_fsl_host_priv *host_priv = host->private_data; | 1399 | struct sata_fsl_host_priv *host_priv = host->private_data; |
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index b7385e077717..c8fc69c85a06 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c | |||
@@ -674,7 +674,7 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) | |||
674 | 674 | ||
675 | static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) | 675 | static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) |
676 | { | 676 | { |
677 | struct of_device *op = fore200e->bus_dev; | 677 | struct platform_device *op = fore200e->bus_dev; |
678 | u32 dma_addr; | 678 | u32 dma_addr; |
679 | 679 | ||
680 | dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); | 680 | dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); |
@@ -687,7 +687,7 @@ static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int | |||
687 | 687 | ||
688 | static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | 688 | static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
689 | { | 689 | { |
690 | struct of_device *op = fore200e->bus_dev; | 690 | struct platform_device *op = fore200e->bus_dev; |
691 | 691 | ||
692 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", | 692 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", |
693 | dma_addr, size, direction); | 693 | dma_addr, size, direction); |
@@ -697,7 +697,7 @@ static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int | |||
697 | 697 | ||
698 | static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | 698 | static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
699 | { | 699 | { |
700 | struct of_device *op = fore200e->bus_dev; | 700 | struct platform_device *op = fore200e->bus_dev; |
701 | 701 | ||
702 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 702 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); |
703 | 703 | ||
@@ -706,7 +706,7 @@ static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_add | |||
706 | 706 | ||
707 | static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | 707 | static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
708 | { | 708 | { |
709 | struct of_device *op = fore200e->bus_dev; | 709 | struct platform_device *op = fore200e->bus_dev; |
710 | 710 | ||
711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); |
712 | 712 | ||
@@ -719,7 +719,7 @@ static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_ | |||
719 | static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, | 719 | static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, |
720 | int size, int nbr, int alignment) | 720 | int size, int nbr, int alignment) |
721 | { | 721 | { |
722 | struct of_device *op = fore200e->bus_dev; | 722 | struct platform_device *op = fore200e->bus_dev; |
723 | 723 | ||
724 | chunk->alloc_size = chunk->align_size = size * nbr; | 724 | chunk->alloc_size = chunk->align_size = size * nbr; |
725 | 725 | ||
@@ -738,7 +738,7 @@ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk | |||
738 | /* free a DVMA consistent chunk of memory */ | 738 | /* free a DVMA consistent chunk of memory */ |
739 | static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) | 739 | static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) |
740 | { | 740 | { |
741 | struct of_device *op = fore200e->bus_dev; | 741 | struct platform_device *op = fore200e->bus_dev; |
742 | 742 | ||
743 | dma_free_coherent(&op->dev, chunk->alloc_size, | 743 | dma_free_coherent(&op->dev, chunk->alloc_size, |
744 | chunk->alloc_addr, chunk->dma_addr); | 744 | chunk->alloc_addr, chunk->dma_addr); |
@@ -770,7 +770,7 @@ static void fore200e_sba_reset(struct fore200e *fore200e) | |||
770 | 770 | ||
771 | static int __init fore200e_sba_map(struct fore200e *fore200e) | 771 | static int __init fore200e_sba_map(struct fore200e *fore200e) |
772 | { | 772 | { |
773 | struct of_device *op = fore200e->bus_dev; | 773 | struct platform_device *op = fore200e->bus_dev; |
774 | unsigned int bursts; | 774 | unsigned int bursts; |
775 | 775 | ||
776 | /* gain access to the SBA specific registers */ | 776 | /* gain access to the SBA specific registers */ |
@@ -800,7 +800,7 @@ static int __init fore200e_sba_map(struct fore200e *fore200e) | |||
800 | 800 | ||
801 | static void fore200e_sba_unmap(struct fore200e *fore200e) | 801 | static void fore200e_sba_unmap(struct fore200e *fore200e) |
802 | { | 802 | { |
803 | struct of_device *op = fore200e->bus_dev; | 803 | struct platform_device *op = fore200e->bus_dev; |
804 | 804 | ||
805 | of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); | 805 | of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); |
806 | of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); | 806 | of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); |
@@ -816,7 +816,7 @@ static int __init fore200e_sba_configure(struct fore200e *fore200e) | |||
816 | 816 | ||
817 | static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) | 817 | static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) |
818 | { | 818 | { |
819 | struct of_device *op = fore200e->bus_dev; | 819 | struct platform_device *op = fore200e->bus_dev; |
820 | const u8 *prop; | 820 | const u8 *prop; |
821 | int len; | 821 | int len; |
822 | 822 | ||
@@ -840,7 +840,7 @@ static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_ | |||
840 | 840 | ||
841 | static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) | 841 | static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) |
842 | { | 842 | { |
843 | struct of_device *op = fore200e->bus_dev; | 843 | struct platform_device *op = fore200e->bus_dev; |
844 | const struct linux_prom_registers *regs; | 844 | const struct linux_prom_registers *regs; |
845 | 845 | ||
846 | regs = of_get_property(op->dev.of_node, "reg", NULL); | 846 | regs = of_get_property(op->dev.of_node, "reg", NULL); |
@@ -2513,7 +2513,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) | |||
2513 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; | 2513 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; |
2514 | #ifdef CONFIG_SBUS | 2514 | #ifdef CONFIG_SBUS |
2515 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) | 2515 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) |
2516 | device = &((struct of_device *) fore200e->bus_dev)->dev; | 2516 | device = &((struct platform_device *) fore200e->bus_dev)->dev; |
2517 | #endif | 2517 | #endif |
2518 | else | 2518 | else |
2519 | return err; | 2519 | return err; |
@@ -2643,7 +2643,7 @@ fore200e_init(struct fore200e* fore200e) | |||
2643 | } | 2643 | } |
2644 | 2644 | ||
2645 | #ifdef CONFIG_SBUS | 2645 | #ifdef CONFIG_SBUS |
2646 | static int __devinit fore200e_sba_probe(struct of_device *op, | 2646 | static int __devinit fore200e_sba_probe(struct platform_device *op, |
2647 | const struct of_device_id *match) | 2647 | const struct of_device_id *match) |
2648 | { | 2648 | { |
2649 | const struct fore200e_bus *bus = match->data; | 2649 | const struct fore200e_bus *bus = match->data; |
@@ -2675,7 +2675,7 @@ static int __devinit fore200e_sba_probe(struct of_device *op, | |||
2675 | return 0; | 2675 | return 0; |
2676 | } | 2676 | } |
2677 | 2677 | ||
2678 | static int __devexit fore200e_sba_remove(struct of_device *op) | 2678 | static int __devexit fore200e_sba_remove(struct platform_device *op) |
2679 | { | 2679 | { |
2680 | struct fore200e *fore200e = dev_get_drvdata(&op->dev); | 2680 | struct fore200e *fore200e = dev_get_drvdata(&op->dev); |
2681 | 2681 | ||
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index b71888b909a0..2982b3ee9465 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -1194,7 +1194,7 @@ static struct platform_driver ace_platform_driver = { | |||
1194 | 1194 | ||
1195 | #if defined(CONFIG_OF) | 1195 | #if defined(CONFIG_OF) |
1196 | static int __devinit | 1196 | static int __devinit |
1197 | ace_of_probe(struct of_device *op, const struct of_device_id *match) | 1197 | ace_of_probe(struct platform_device *op, const struct of_device_id *match) |
1198 | { | 1198 | { |
1199 | struct resource res; | 1199 | struct resource res; |
1200 | resource_size_t physaddr; | 1200 | resource_size_t physaddr; |
@@ -1226,7 +1226,7 @@ ace_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1226 | return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); | 1226 | return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | static int __devexit ace_of_remove(struct of_device *op) | 1229 | static int __devexit ace_of_remove(struct platform_device *op) |
1230 | { | 1230 | { |
1231 | ace_free(&op->dev); | 1231 | ace_free(&op->dev); |
1232 | return 0; | 1232 | return 0; |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7cfcc629a7fd..3d44ec724c17 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -1002,7 +1002,7 @@ config SCx200_GPIO | |||
1002 | 1002 | ||
1003 | config PC8736x_GPIO | 1003 | config PC8736x_GPIO |
1004 | tristate "NatSemi PC8736x GPIO Support" | 1004 | tristate "NatSemi PC8736x GPIO Support" |
1005 | depends on X86 | 1005 | depends on X86_32 |
1006 | default SCx200_GPIO # mostly N | 1006 | default SCx200_GPIO # mostly N |
1007 | select NSC_GPIO # needed for support routines | 1007 | select NSC_GPIO # needed for support routines |
1008 | help | 1008 | help |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 5a80ad68ef22..7b01bc609de3 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -1149,7 +1149,7 @@ out_err: | |||
1149 | * Note: If it is called early in the boot process, @val is stored and | 1149 | * Note: If it is called early in the boot process, @val is stored and |
1150 | * parsed later in hvc_iucv_init(). | 1150 | * parsed later in hvc_iucv_init(). |
1151 | */ | 1151 | */ |
1152 | static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | 1152 | static int param_set_vmidfilter(const char *val, const struct kernel_param *kp) |
1153 | { | 1153 | { |
1154 | int rc; | 1154 | int rc; |
1155 | 1155 | ||
@@ -1176,7 +1176,7 @@ static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | |||
1176 | * The function stores the filter as a comma-separated list of z/VM user IDs | 1176 | * The function stores the filter as a comma-separated list of z/VM user IDs |
1177 | * in @buffer. Typically, sysfs routines call this function for attr show. | 1177 | * in @buffer. Typically, sysfs routines call this function for attr show. |
1178 | */ | 1178 | */ |
1179 | static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | 1179 | static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp) |
1180 | { | 1180 | { |
1181 | int rc; | 1181 | int rc; |
1182 | size_t index, len; | 1182 | size_t index, len; |
@@ -1203,6 +1203,11 @@ static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | |||
1203 | 1203 | ||
1204 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) | 1204 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) |
1205 | 1205 | ||
1206 | static struct kernel_param_ops param_ops_vmidfilter = { | ||
1207 | .set = param_set_vmidfilter, | ||
1208 | .get = param_get_vmidfilter, | ||
1209 | }; | ||
1210 | |||
1206 | /** | 1211 | /** |
1207 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization | 1212 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
1208 | */ | 1213 | */ |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 7a4f080f8356..1acdb2509511 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -619,7 +619,7 @@ static void __devinit n2rng_driver_version(void) | |||
619 | pr_info("%s", version); | 619 | pr_info("%s", version); |
620 | } | 620 | } |
621 | 621 | ||
622 | static int __devinit n2rng_probe(struct of_device *op, | 622 | static int __devinit n2rng_probe(struct platform_device *op, |
623 | const struct of_device_id *match) | 623 | const struct of_device_id *match) |
624 | { | 624 | { |
625 | int victoria_falls = (match->data != NULL); | 625 | int victoria_falls = (match->data != NULL); |
@@ -714,7 +714,7 @@ out: | |||
714 | return err; | 714 | return err; |
715 | } | 715 | } |
716 | 716 | ||
717 | static int __devexit n2rng_remove(struct of_device *op) | 717 | static int __devexit n2rng_remove(struct platform_device *op) |
718 | { | 718 | { |
719 | struct n2rng *np = dev_get_drvdata(&op->dev); | 719 | struct n2rng *np = dev_get_drvdata(&op->dev); |
720 | 720 | ||
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h index a2b81e7bfc18..4bea07f30978 100644 --- a/drivers/char/hw_random/n2rng.h +++ b/drivers/char/hw_random/n2rng.h | |||
@@ -65,7 +65,7 @@ struct n2rng_unit { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct n2rng { | 67 | struct n2rng { |
68 | struct of_device *op; | 68 | struct platform_device *op; |
69 | 69 | ||
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ | 71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ |
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 261ba8f22b8b..a31c830ca8cd 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c | |||
@@ -94,7 +94,7 @@ static struct hwrng pasemi_rng = { | |||
94 | .data_read = pasemi_rng_data_read, | 94 | .data_read = pasemi_rng_data_read, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static int __devinit rng_probe(struct of_device *ofdev, | 97 | static int __devinit rng_probe(struct platform_device *ofdev, |
98 | const struct of_device_id *match) | 98 | const struct of_device_id *match) |
99 | { | 99 | { |
100 | void __iomem *rng_regs; | 100 | void __iomem *rng_regs; |
@@ -123,7 +123,7 @@ static int __devinit rng_probe(struct of_device *ofdev, | |||
123 | return err; | 123 | return err; |
124 | } | 124 | } |
125 | 125 | ||
126 | static int __devexit rng_remove(struct of_device *dev) | 126 | static int __devexit rng_remove(struct platform_device *dev) |
127 | { | 127 | { |
128 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; | 128 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; |
129 | 129 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index ff68e7c34ce7..3822b4f49c84 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1804,9 +1804,12 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1804 | info->irq_setup = std_irq_setup; | 1804 | info->irq_setup = std_irq_setup; |
1805 | info->slave_addr = ipmb; | 1805 | info->slave_addr = ipmb; |
1806 | 1806 | ||
1807 | if (!add_smi(info)) | 1807 | if (!add_smi(info)) { |
1808 | if (try_smi_init(info)) | 1808 | if (try_smi_init(info)) |
1809 | cleanup_one_si(info); | 1809 | cleanup_one_si(info); |
1810 | } else { | ||
1811 | kfree(info); | ||
1812 | } | ||
1810 | } else { | 1813 | } else { |
1811 | /* remove */ | 1814 | /* remove */ |
1812 | struct smi_info *e, *tmp_e; | 1815 | struct smi_info *e, *tmp_e; |
@@ -1890,9 +1893,12 @@ static __devinit void hardcode_find_bmc(void) | |||
1890 | info->irq_setup = std_irq_setup; | 1893 | info->irq_setup = std_irq_setup; |
1891 | info->slave_addr = slave_addrs[i]; | 1894 | info->slave_addr = slave_addrs[i]; |
1892 | 1895 | ||
1893 | if (!add_smi(info)) | 1896 | if (!add_smi(info)) { |
1894 | if (try_smi_init(info)) | 1897 | if (try_smi_init(info)) |
1895 | cleanup_one_si(info); | 1898 | cleanup_one_si(info); |
1899 | } else { | ||
1900 | kfree(info); | ||
1901 | } | ||
1896 | } | 1902 | } |
1897 | } | 1903 | } |
1898 | 1904 | ||
@@ -1965,8 +1971,8 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1965 | 1971 | ||
1966 | /* | 1972 | /* |
1967 | * Defined at | 1973 | * Defined at |
1968 | * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/ | 1974 | * http://h21007.www2.hp.com/portal/download/files |
1969 | * Docs/TechPapers/IA64/hpspmi.pdf | 1975 | * /unprot/hpspmi.pdf |
1970 | */ | 1976 | */ |
1971 | struct SPMITable { | 1977 | struct SPMITable { |
1972 | s8 Signature[4]; | 1978 | s8 Signature[4]; |
@@ -2013,18 +2019,12 @@ struct SPMITable { | |||
2013 | static __devinit int try_init_spmi(struct SPMITable *spmi) | 2019 | static __devinit int try_init_spmi(struct SPMITable *spmi) |
2014 | { | 2020 | { |
2015 | struct smi_info *info; | 2021 | struct smi_info *info; |
2016 | u8 addr_space; | ||
2017 | 2022 | ||
2018 | if (spmi->IPMIlegacy != 1) { | 2023 | if (spmi->IPMIlegacy != 1) { |
2019 | printk(KERN_INFO PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy); | 2024 | printk(KERN_INFO PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy); |
2020 | return -ENODEV; | 2025 | return -ENODEV; |
2021 | } | 2026 | } |
2022 | 2027 | ||
2023 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
2024 | addr_space = IPMI_MEM_ADDR_SPACE; | ||
2025 | else | ||
2026 | addr_space = IPMI_IO_ADDR_SPACE; | ||
2027 | |||
2028 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2028 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
2029 | if (!info) { | 2029 | if (!info) { |
2030 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); | 2030 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); |
@@ -2088,7 +2088,13 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2088 | } | 2088 | } |
2089 | info->io.addr_data = spmi->addr.address; | 2089 | info->io.addr_data = spmi->addr.address; |
2090 | 2090 | ||
2091 | add_smi(info); | 2091 | pr_info("ipmi_si: SPMI: %s %#lx regsize %d spacing %d irq %d\n", |
2092 | (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", | ||
2093 | info->io.addr_data, info->io.regsize, info->io.regspacing, | ||
2094 | info->irq); | ||
2095 | |||
2096 | if (add_smi(info)) | ||
2097 | kfree(info); | ||
2092 | 2098 | ||
2093 | return 0; | 2099 | return 0; |
2094 | } | 2100 | } |
@@ -2204,7 +2210,10 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2204 | res, info->io.regsize, info->io.regspacing, | 2210 | res, info->io.regsize, info->io.regspacing, |
2205 | info->irq); | 2211 | info->irq); |
2206 | 2212 | ||
2207 | return add_smi(info); | 2213 | if (add_smi(info)) |
2214 | goto err_free; | ||
2215 | |||
2216 | return 0; | ||
2208 | 2217 | ||
2209 | err_free: | 2218 | err_free: |
2210 | kfree(info); | 2219 | kfree(info); |
@@ -2362,7 +2371,13 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2362 | if (info->irq) | 2371 | if (info->irq) |
2363 | info->irq_setup = std_irq_setup; | 2372 | info->irq_setup = std_irq_setup; |
2364 | 2373 | ||
2365 | add_smi(info); | 2374 | pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n", |
2375 | (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", | ||
2376 | info->io.addr_data, info->io.regsize, info->io.regspacing, | ||
2377 | info->irq); | ||
2378 | |||
2379 | if (add_smi(info)) | ||
2380 | kfree(info); | ||
2366 | } | 2381 | } |
2367 | 2382 | ||
2368 | static void __devinit dmi_find_bmc(void) | 2383 | static void __devinit dmi_find_bmc(void) |
@@ -2468,7 +2483,10 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2468 | &pdev->resource[0], info->io.regsize, info->io.regspacing, | 2483 | &pdev->resource[0], info->io.regsize, info->io.regspacing, |
2469 | info->irq); | 2484 | info->irq); |
2470 | 2485 | ||
2471 | return add_smi(info); | 2486 | if (add_smi(info)) |
2487 | kfree(info); | ||
2488 | |||
2489 | return 0; | ||
2472 | } | 2490 | } |
2473 | 2491 | ||
2474 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) | 2492 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) |
@@ -2510,7 +2528,7 @@ static struct pci_driver ipmi_pci_driver = { | |||
2510 | 2528 | ||
2511 | 2529 | ||
2512 | #ifdef CONFIG_PPC_OF | 2530 | #ifdef CONFIG_PPC_OF |
2513 | static int __devinit ipmi_of_probe(struct of_device *dev, | 2531 | static int __devinit ipmi_of_probe(struct platform_device *dev, |
2514 | const struct of_device_id *match) | 2532 | const struct of_device_id *match) |
2515 | { | 2533 | { |
2516 | struct smi_info *info; | 2534 | struct smi_info *info; |
@@ -2581,10 +2599,15 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2581 | 2599 | ||
2582 | dev_set_drvdata(&dev->dev, info); | 2600 | dev_set_drvdata(&dev->dev, info); |
2583 | 2601 | ||
2584 | return add_smi(info); | 2602 | if (add_smi(info)) { |
2603 | kfree(info); | ||
2604 | return -EBUSY; | ||
2605 | } | ||
2606 | |||
2607 | return 0; | ||
2585 | } | 2608 | } |
2586 | 2609 | ||
2587 | static int __devexit ipmi_of_remove(struct of_device *dev) | 2610 | static int __devexit ipmi_of_remove(struct platform_device *dev) |
2588 | { | 2611 | { |
2589 | cleanup_one_si(dev_get_drvdata(&dev->dev)); | 2612 | cleanup_one_si(dev_get_drvdata(&dev->dev)); |
2590 | return 0; | 2613 | return 0; |
@@ -3014,6 +3037,8 @@ static __devinit void default_find_bmc(void) | |||
3014 | info->io.addr_data); | 3037 | info->io.addr_data); |
3015 | } else | 3038 | } else |
3016 | cleanup_one_si(info); | 3039 | cleanup_one_si(info); |
3040 | } else { | ||
3041 | kfree(info); | ||
3017 | } | 3042 | } |
3018 | } | 3043 | } |
3019 | } | 3044 | } |
@@ -3041,7 +3066,7 @@ static int add_smi(struct smi_info *new_smi) | |||
3041 | si_to_str[new_smi->si_type]); | 3066 | si_to_str[new_smi->si_type]); |
3042 | mutex_lock(&smi_infos_lock); | 3067 | mutex_lock(&smi_infos_lock); |
3043 | if (!is_new_interface(new_smi)) { | 3068 | if (!is_new_interface(new_smi)) { |
3044 | printk(KERN_CONT PFX "duplicate interface\n"); | 3069 | printk(KERN_CONT " duplicate interface\n"); |
3045 | rv = -EBUSY; | 3070 | rv = -EBUSY; |
3046 | goto out_err; | 3071 | goto out_err; |
3047 | } | 3072 | } |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 82bcdb262a3a..654d566ca57c 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -196,7 +196,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf); | |||
196 | */ | 196 | */ |
197 | static int start_now; | 197 | static int start_now; |
198 | 198 | ||
199 | static int set_param_int(const char *val, struct kernel_param *kp) | 199 | static int set_param_timeout(const char *val, const struct kernel_param *kp) |
200 | { | 200 | { |
201 | char *endp; | 201 | char *endp; |
202 | int l; | 202 | int l; |
@@ -215,10 +215,11 @@ static int set_param_int(const char *val, struct kernel_param *kp) | |||
215 | return rv; | 215 | return rv; |
216 | } | 216 | } |
217 | 217 | ||
218 | static int get_param_int(char *buffer, struct kernel_param *kp) | 218 | static struct kernel_param_ops param_ops_timeout = { |
219 | { | 219 | .set = set_param_timeout, |
220 | return sprintf(buffer, "%i", *((int *)kp->arg)); | 220 | .get = param_get_int, |
221 | } | 221 | }; |
222 | #define param_check_timeout param_check_int | ||
222 | 223 | ||
223 | typedef int (*action_fn)(const char *intval, char *outval); | 224 | typedef int (*action_fn)(const char *intval, char *outval); |
224 | 225 | ||
@@ -227,7 +228,7 @@ static int preaction_op(const char *inval, char *outval); | |||
227 | static int preop_op(const char *inval, char *outval); | 228 | static int preop_op(const char *inval, char *outval); |
228 | static void check_parms(void); | 229 | static void check_parms(void); |
229 | 230 | ||
230 | static int set_param_str(const char *val, struct kernel_param *kp) | 231 | static int set_param_str(const char *val, const struct kernel_param *kp) |
231 | { | 232 | { |
232 | action_fn fn = (action_fn) kp->arg; | 233 | action_fn fn = (action_fn) kp->arg; |
233 | int rv = 0; | 234 | int rv = 0; |
@@ -251,7 +252,7 @@ static int set_param_str(const char *val, struct kernel_param *kp) | |||
251 | return rv; | 252 | return rv; |
252 | } | 253 | } |
253 | 254 | ||
254 | static int get_param_str(char *buffer, struct kernel_param *kp) | 255 | static int get_param_str(char *buffer, const struct kernel_param *kp) |
255 | { | 256 | { |
256 | action_fn fn = (action_fn) kp->arg; | 257 | action_fn fn = (action_fn) kp->arg; |
257 | int rv; | 258 | int rv; |
@@ -263,7 +264,7 @@ static int get_param_str(char *buffer, struct kernel_param *kp) | |||
263 | } | 264 | } |
264 | 265 | ||
265 | 266 | ||
266 | static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | 267 | static int set_param_wdog_ifnum(const char *val, const struct kernel_param *kp) |
267 | { | 268 | { |
268 | int rv = param_set_int(val, kp); | 269 | int rv = param_set_int(val, kp); |
269 | if (rv) | 270 | if (rv) |
@@ -276,27 +277,38 @@ static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) | |||
276 | return 0; | 277 | return 0; |
277 | } | 278 | } |
278 | 279 | ||
279 | module_param_call(ifnum_to_use, set_param_wdog_ifnum, get_param_int, | 280 | static struct kernel_param_ops param_ops_wdog_ifnum = { |
280 | &ifnum_to_use, 0644); | 281 | .set = set_param_wdog_ifnum, |
282 | .get = param_get_int, | ||
283 | }; | ||
284 | |||
285 | #define param_check_wdog_ifnum param_check_int | ||
286 | |||
287 | static struct kernel_param_ops param_ops_str = { | ||
288 | .set = set_param_str, | ||
289 | .get = get_param_str, | ||
290 | }; | ||
291 | |||
292 | module_param(ifnum_to_use, wdog_ifnum, 0644); | ||
281 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " | 293 | MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " |
282 | "timer. Setting to -1 defaults to the first registered " | 294 | "timer. Setting to -1 defaults to the first registered " |
283 | "interface"); | 295 | "interface"); |
284 | 296 | ||
285 | module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644); | 297 | module_param(timeout, timeout, 0644); |
286 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); | 298 | MODULE_PARM_DESC(timeout, "Timeout value in seconds."); |
287 | 299 | ||
288 | module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644); | 300 | module_param(pretimeout, timeout, 0644); |
289 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); | 301 | MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); |
290 | 302 | ||
291 | module_param_call(action, set_param_str, get_param_str, action_op, 0644); | 303 | module_param_cb(action, ¶m_ops_str, action_op, 0644); |
292 | MODULE_PARM_DESC(action, "Timeout action. One of: " | 304 | MODULE_PARM_DESC(action, "Timeout action. One of: " |
293 | "reset, none, power_cycle, power_off."); | 305 | "reset, none, power_cycle, power_off."); |
294 | 306 | ||
295 | module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644); | 307 | module_param_cb(preaction, ¶m_ops_str, preaction_op, 0644); |
296 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " | 308 | MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " |
297 | "pre_none, pre_smi, pre_nmi, pre_int."); | 309 | "pre_none, pre_smi, pre_nmi, pre_int."); |
298 | 310 | ||
299 | module_param_call(preop, set_param_str, get_param_str, preop_op, 0644); | 311 | module_param_cb(preop, ¶m_ops_str, preop_op, 0644); |
300 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " | 312 | MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " |
301 | "preop_none, preop_panic, preop_give_data."); | 313 | "preop_none, preop_panic, preop_give_data."); |
302 | 314 | ||
diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c index 099105e0894e..04ef3ef0a422 100644 --- a/drivers/char/n_gsm.c +++ b/drivers/char/n_gsm.c | |||
@@ -919,7 +919,7 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) | |||
919 | else | 919 | else |
920 | len = gsm_dlci_data_output_framed(gsm, dlci); | 920 | len = gsm_dlci_data_output_framed(gsm, dlci); |
921 | if (len < 0) | 921 | if (len < 0) |
922 | return; | 922 | break; |
923 | /* DLCI empty - try the next */ | 923 | /* DLCI empty - try the next */ |
924 | if (len == 0) | 924 | if (len == 0) |
925 | i++; | 925 | i++; |
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 18af923093c3..817169cbb245 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -1743,8 +1743,7 @@ static int ntty_write_room(struct tty_struct *tty) | |||
1743 | if (dc) { | 1743 | if (dc) { |
1744 | mutex_lock(&port->tty_sem); | 1744 | mutex_lock(&port->tty_sem); |
1745 | if (port->port.count) | 1745 | if (port->port.count) |
1746 | room = port->fifo_ul.size - | 1746 | room = kfifo_avail(&port->fifo_ul); |
1747 | kfifo_len(&port->fifo_ul); | ||
1748 | mutex_unlock(&port->tty_sem); | 1747 | mutex_unlock(&port->tty_sem); |
1749 | } | 1748 | } |
1750 | return room; | 1749 | return room; |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 95acb8c880f4..dfa8b3062fda 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -961,7 +961,7 @@ static int __init rtc_init(void) | |||
961 | #endif | 961 | #endif |
962 | #ifdef CONFIG_SPARC32 | 962 | #ifdef CONFIG_SPARC32 |
963 | struct device_node *ebus_dp; | 963 | struct device_node *ebus_dp; |
964 | struct of_device *op; | 964 | struct platform_device *op; |
965 | #else | 965 | #else |
966 | void *r; | 966 | void *r; |
967 | #ifdef RTC_IRQ | 967 | #ifdef RTC_IRQ |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index ed8a9cec2a05..0ed763cd2e77 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -761,7 +761,7 @@ static struct platform_driver hwicap_platform_driver = { | |||
761 | 761 | ||
762 | #if defined(CONFIG_OF) | 762 | #if defined(CONFIG_OF) |
763 | static int __devinit | 763 | static int __devinit |
764 | hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | 764 | hwicap_of_probe(struct platform_device *op, const struct of_device_id *match) |
765 | { | 765 | { |
766 | struct resource res; | 766 | struct resource res; |
767 | const unsigned int *id; | 767 | const unsigned int *id; |
@@ -798,7 +798,7 @@ hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | |||
798 | regs); | 798 | regs); |
799 | } | 799 | } |
800 | 800 | ||
801 | static int __devexit hwicap_of_remove(struct of_device *op) | 801 | static int __devexit hwicap_of_remove(struct platform_device *op) |
802 | { | 802 | { |
803 | return hwicap_remove(&op->dev); | 803 | return hwicap_remove(&op->dev); |
804 | } | 804 | } |
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index fbf94cf496f0..ea0b3863ad0f 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -77,7 +77,7 @@ config ZCRYPT | |||
77 | 77 | ||
78 | config ZCRYPT_MONOLITHIC | 78 | config ZCRYPT_MONOLITHIC |
79 | bool "Monolithic zcrypt module" | 79 | bool "Monolithic zcrypt module" |
80 | depends on ZCRYPT="m" | 80 | depends on ZCRYPT |
81 | help | 81 | help |
82 | Select this option if you want to have a single module z90crypt, | 82 | Select this option if you want to have a single module z90crypt, |
83 | that contains all parts of the crypto device driver (ap bus, | 83 | that contains all parts of the crypto device driver (ap bus, |
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 983530ba04a7..2b1baee525bc 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c | |||
@@ -1150,7 +1150,7 @@ struct crypto4xx_alg_common crypto4xx_alg[] = { | |||
1150 | /** | 1150 | /** |
1151 | * Module Initialization Routine | 1151 | * Module Initialization Routine |
1152 | */ | 1152 | */ |
1153 | static int __init crypto4xx_probe(struct of_device *ofdev, | 1153 | static int __init crypto4xx_probe(struct platform_device *ofdev, |
1154 | const struct of_device_id *match) | 1154 | const struct of_device_id *match) |
1155 | { | 1155 | { |
1156 | int rc; | 1156 | int rc; |
@@ -1258,7 +1258,7 @@ err_alloc_dev: | |||
1258 | return rc; | 1258 | return rc; |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | static int __exit crypto4xx_remove(struct of_device *ofdev) | 1261 | static int __exit crypto4xx_remove(struct platform_device *ofdev) |
1262 | { | 1262 | { |
1263 | struct device *dev = &ofdev->dev; | 1263 | struct device *dev = &ofdev->dev; |
1264 | struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); | 1264 | struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); |
diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h index da9cbe3b9fc3..bac0bdeb4b5f 100644 --- a/drivers/crypto/amcc/crypto4xx_core.h +++ b/drivers/crypto/amcc/crypto4xx_core.h | |||
@@ -104,7 +104,7 @@ struct crypto4xx_device { | |||
104 | 104 | ||
105 | struct crypto4xx_core_device { | 105 | struct crypto4xx_core_device { |
106 | struct device *device; | 106 | struct device *device; |
107 | struct of_device *ofdev; | 107 | struct platform_device *ofdev; |
108 | struct crypto4xx_device *dev; | 108 | struct crypto4xx_device *dev; |
109 | u32 int_status; | 109 | u32 int_status; |
110 | u32 irq; | 110 | u32 irq; |
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index f17ddf37a1ed..0d662213c066 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c | |||
@@ -97,8 +97,13 @@ | |||
97 | 97 | ||
98 | struct buffer_desc { | 98 | struct buffer_desc { |
99 | u32 phys_next; | 99 | u32 phys_next; |
100 | #ifdef __ARMEB__ | ||
100 | u16 buf_len; | 101 | u16 buf_len; |
101 | u16 pkt_len; | 102 | u16 pkt_len; |
103 | #else | ||
104 | u16 pkt_len; | ||
105 | u16 buf_len; | ||
106 | #endif | ||
102 | u32 phys_addr; | 107 | u32 phys_addr; |
103 | u32 __reserved[4]; | 108 | u32 __reserved[4]; |
104 | struct buffer_desc *next; | 109 | struct buffer_desc *next; |
@@ -106,17 +111,30 @@ struct buffer_desc { | |||
106 | }; | 111 | }; |
107 | 112 | ||
108 | struct crypt_ctl { | 113 | struct crypt_ctl { |
114 | #ifdef __ARMEB__ | ||
109 | u8 mode; /* NPE_OP_* operation mode */ | 115 | u8 mode; /* NPE_OP_* operation mode */ |
110 | u8 init_len; | 116 | u8 init_len; |
111 | u16 reserved; | 117 | u16 reserved; |
118 | #else | ||
119 | u16 reserved; | ||
120 | u8 init_len; | ||
121 | u8 mode; /* NPE_OP_* operation mode */ | ||
122 | #endif | ||
112 | u8 iv[MAX_IVLEN]; /* IV for CBC mode or CTR IV for CTR mode */ | 123 | u8 iv[MAX_IVLEN]; /* IV for CBC mode or CTR IV for CTR mode */ |
113 | u32 icv_rev_aes; /* icv or rev aes */ | 124 | u32 icv_rev_aes; /* icv or rev aes */ |
114 | u32 src_buf; | 125 | u32 src_buf; |
115 | u32 dst_buf; | 126 | u32 dst_buf; |
127 | #ifdef __ARMEB__ | ||
116 | u16 auth_offs; /* Authentication start offset */ | 128 | u16 auth_offs; /* Authentication start offset */ |
117 | u16 auth_len; /* Authentication data length */ | 129 | u16 auth_len; /* Authentication data length */ |
118 | u16 crypt_offs; /* Cryption start offset */ | 130 | u16 crypt_offs; /* Cryption start offset */ |
119 | u16 crypt_len; /* Cryption data length */ | 131 | u16 crypt_len; /* Cryption data length */ |
132 | #else | ||
133 | u16 auth_len; /* Authentication data length */ | ||
134 | u16 auth_offs; /* Authentication start offset */ | ||
135 | u16 crypt_len; /* Cryption data length */ | ||
136 | u16 crypt_offs; /* Cryption start offset */ | ||
137 | #endif | ||
120 | u32 aadAddr; /* Additional Auth Data Addr for CCM mode */ | 138 | u32 aadAddr; /* Additional Auth Data Addr for CCM mode */ |
121 | u32 crypto_ctx; /* NPE Crypto Param structure address */ | 139 | u32 crypto_ctx; /* NPE Crypto Param structure address */ |
122 | 140 | ||
@@ -652,6 +670,9 @@ static int setup_auth(struct crypto_tfm *tfm, int encrypt, unsigned authsize, | |||
652 | 670 | ||
653 | /* write cfg word to cryptinfo */ | 671 | /* write cfg word to cryptinfo */ |
654 | cfgword = algo->cfgword | ( authsize << 6); /* (authsize/4) << 8 */ | 672 | cfgword = algo->cfgword | ( authsize << 6); /* (authsize/4) << 8 */ |
673 | #ifndef __ARMEB__ | ||
674 | cfgword ^= 0xAA000000; /* change the "byte swap" flags */ | ||
675 | #endif | ||
655 | *(u32*)cinfo = cpu_to_be32(cfgword); | 676 | *(u32*)cinfo = cpu_to_be32(cfgword); |
656 | cinfo += sizeof(cfgword); | 677 | cinfo += sizeof(cfgword); |
657 | 678 | ||
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 26af2dd5d831..88ee01510ec0 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c | |||
@@ -1552,7 +1552,7 @@ static void __exit n2_unregister_algs(void) | |||
1552 | 1552 | ||
1553 | /* To map CWQ queues to interrupt sources, the hypervisor API provides | 1553 | /* To map CWQ queues to interrupt sources, the hypervisor API provides |
1554 | * a devino. This isn't very useful to us because all of the | 1554 | * a devino. This isn't very useful to us because all of the |
1555 | * interrupts listed in the of_device node have been translated to | 1555 | * interrupts listed in the device_node have been translated to |
1556 | * Linux virtual IRQ cookie numbers. | 1556 | * Linux virtual IRQ cookie numbers. |
1557 | * | 1557 | * |
1558 | * So we have to back-translate, going through the 'intr' and 'ino' | 1558 | * So we have to back-translate, going through the 'intr' and 'ino' |
@@ -1560,7 +1560,7 @@ static void __exit n2_unregister_algs(void) | |||
1560 | * 'interrupts' property entries, in order to to figure out which | 1560 | * 'interrupts' property entries, in order to to figure out which |
1561 | * devino goes to which already-translated IRQ. | 1561 | * devino goes to which already-translated IRQ. |
1562 | */ | 1562 | */ |
1563 | static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, | 1563 | static int find_devino_index(struct platform_device *dev, struct spu_mdesc_info *ip, |
1564 | unsigned long dev_ino) | 1564 | unsigned long dev_ino) |
1565 | { | 1565 | { |
1566 | const unsigned int *dev_intrs; | 1566 | const unsigned int *dev_intrs; |
@@ -1580,7 +1580,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, | |||
1580 | if (!dev_intrs) | 1580 | if (!dev_intrs) |
1581 | return -ENODEV; | 1581 | return -ENODEV; |
1582 | 1582 | ||
1583 | for (i = 0; i < dev->num_irqs; i++) { | 1583 | for (i = 0; i < dev->archdata.num_irqs; i++) { |
1584 | if (dev_intrs[i] == intr) | 1584 | if (dev_intrs[i] == intr) |
1585 | return i; | 1585 | return i; |
1586 | } | 1586 | } |
@@ -1588,7 +1588,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, | |||
1588 | return -ENODEV; | 1588 | return -ENODEV; |
1589 | } | 1589 | } |
1590 | 1590 | ||
1591 | static int spu_map_ino(struct of_device *dev, struct spu_mdesc_info *ip, | 1591 | static int spu_map_ino(struct platform_device *dev, struct spu_mdesc_info *ip, |
1592 | const char *irq_name, struct spu_queue *p, | 1592 | const char *irq_name, struct spu_queue *p, |
1593 | irq_handler_t handler) | 1593 | irq_handler_t handler) |
1594 | { | 1594 | { |
@@ -1603,7 +1603,7 @@ static int spu_map_ino(struct of_device *dev, struct spu_mdesc_info *ip, | |||
1603 | if (index < 0) | 1603 | if (index < 0) |
1604 | return index; | 1604 | return index; |
1605 | 1605 | ||
1606 | p->irq = dev->irqs[index]; | 1606 | p->irq = dev->archdata.irqs[index]; |
1607 | 1607 | ||
1608 | sprintf(p->irq_name, "%s-%d", irq_name, index); | 1608 | sprintf(p->irq_name, "%s-%d", irq_name, index); |
1609 | 1609 | ||
@@ -1736,7 +1736,7 @@ static void spu_list_destroy(struct list_head *list) | |||
1736 | * gathering cpu membership information. | 1736 | * gathering cpu membership information. |
1737 | */ | 1737 | */ |
1738 | static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, | 1738 | static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, |
1739 | struct of_device *dev, | 1739 | struct platform_device *dev, |
1740 | u64 node, struct spu_queue *p, | 1740 | u64 node, struct spu_queue *p, |
1741 | struct spu_queue **table) | 1741 | struct spu_queue **table) |
1742 | { | 1742 | { |
@@ -1763,7 +1763,7 @@ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, | |||
1763 | 1763 | ||
1764 | /* Process an 'exec-unit' MDESC node of type 'cwq'. */ | 1764 | /* Process an 'exec-unit' MDESC node of type 'cwq'. */ |
1765 | static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, | 1765 | static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, |
1766 | struct of_device *dev, struct mdesc_handle *mdesc, | 1766 | struct platform_device *dev, struct mdesc_handle *mdesc, |
1767 | u64 node, const char *iname, unsigned long q_type, | 1767 | u64 node, const char *iname, unsigned long q_type, |
1768 | irq_handler_t handler, struct spu_queue **table) | 1768 | irq_handler_t handler, struct spu_queue **table) |
1769 | { | 1769 | { |
@@ -1794,7 +1794,7 @@ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, | |||
1794 | return spu_map_ino(dev, ip, iname, p, handler); | 1794 | return spu_map_ino(dev, ip, iname, p, handler); |
1795 | } | 1795 | } |
1796 | 1796 | ||
1797 | static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct of_device *dev, | 1797 | static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *dev, |
1798 | struct spu_mdesc_info *ip, struct list_head *list, | 1798 | struct spu_mdesc_info *ip, struct list_head *list, |
1799 | const char *exec_name, unsigned long q_type, | 1799 | const char *exec_name, unsigned long q_type, |
1800 | irq_handler_t handler, struct spu_queue **table) | 1800 | irq_handler_t handler, struct spu_queue **table) |
@@ -1855,7 +1855,7 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node, | |||
1855 | } | 1855 | } |
1856 | 1856 | ||
1857 | static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc, | 1857 | static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc, |
1858 | struct of_device *dev, | 1858 | struct platform_device *dev, |
1859 | struct spu_mdesc_info *ip, | 1859 | struct spu_mdesc_info *ip, |
1860 | const char *node_name) | 1860 | const char *node_name) |
1861 | { | 1861 | { |
@@ -2004,7 +2004,7 @@ static void __devinit n2_spu_driver_version(void) | |||
2004 | pr_info("%s", version); | 2004 | pr_info("%s", version); |
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | static int __devinit n2_crypto_probe(struct of_device *dev, | 2007 | static int __devinit n2_crypto_probe(struct platform_device *dev, |
2008 | const struct of_device_id *match) | 2008 | const struct of_device_id *match) |
2009 | { | 2009 | { |
2010 | struct mdesc_handle *mdesc; | 2010 | struct mdesc_handle *mdesc; |
@@ -2081,7 +2081,7 @@ out_free_n2cp: | |||
2081 | return err; | 2081 | return err; |
2082 | } | 2082 | } |
2083 | 2083 | ||
2084 | static int __devexit n2_crypto_remove(struct of_device *dev) | 2084 | static int __devexit n2_crypto_remove(struct platform_device *dev) |
2085 | { | 2085 | { |
2086 | struct n2_crypto *np = dev_get_drvdata(&dev->dev); | 2086 | struct n2_crypto *np = dev_get_drvdata(&dev->dev); |
2087 | 2087 | ||
@@ -2116,7 +2116,7 @@ static void free_ncp(struct n2_mau *mp) | |||
2116 | kfree(mp); | 2116 | kfree(mp); |
2117 | } | 2117 | } |
2118 | 2118 | ||
2119 | static int __devinit n2_mau_probe(struct of_device *dev, | 2119 | static int __devinit n2_mau_probe(struct platform_device *dev, |
2120 | const struct of_device_id *match) | 2120 | const struct of_device_id *match) |
2121 | { | 2121 | { |
2122 | struct mdesc_handle *mdesc; | 2122 | struct mdesc_handle *mdesc; |
@@ -2184,7 +2184,7 @@ out_free_ncp: | |||
2184 | return err; | 2184 | return err; |
2185 | } | 2185 | } |
2186 | 2186 | ||
2187 | static int __devexit n2_mau_remove(struct of_device *dev) | 2187 | static int __devexit n2_mau_remove(struct platform_device *dev) |
2188 | { | 2188 | { |
2189 | struct n2_mau *mp = dev_get_drvdata(&dev->dev); | 2189 | struct n2_mau *mp = dev_get_drvdata(&dev->dev); |
2190 | 2190 | ||
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 97f4af1d8a64..4bcd825b5739 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c | |||
@@ -118,7 +118,7 @@ struct talitos_channel { | |||
118 | 118 | ||
119 | struct talitos_private { | 119 | struct talitos_private { |
120 | struct device *dev; | 120 | struct device *dev; |
121 | struct of_device *ofdev; | 121 | struct platform_device *ofdev; |
122 | void __iomem *reg; | 122 | void __iomem *reg; |
123 | int irq; | 123 | int irq; |
124 | 124 | ||
@@ -2308,7 +2308,7 @@ static int hw_supports(struct device *dev, __be32 desc_hdr_template) | |||
2308 | return ret; | 2308 | return ret; |
2309 | } | 2309 | } |
2310 | 2310 | ||
2311 | static int talitos_remove(struct of_device *ofdev) | 2311 | static int talitos_remove(struct platform_device *ofdev) |
2312 | { | 2312 | { |
2313 | struct device *dev = &ofdev->dev; | 2313 | struct device *dev = &ofdev->dev; |
2314 | struct talitos_private *priv = dev_get_drvdata(dev); | 2314 | struct talitos_private *priv = dev_get_drvdata(dev); |
@@ -2401,7 +2401,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, | |||
2401 | return t_alg; | 2401 | return t_alg; |
2402 | } | 2402 | } |
2403 | 2403 | ||
2404 | static int talitos_probe(struct of_device *ofdev, | 2404 | static int talitos_probe(struct platform_device *ofdev, |
2405 | const struct of_device_id *match) | 2405 | const struct of_device_id *match) |
2406 | { | 2406 | { |
2407 | struct device *dev = &ofdev->dev; | 2407 | struct device *dev = &ofdev->dev; |
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index fed57634b6c1..9520cf02edc8 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -141,7 +141,7 @@ config TXX9_DMAC | |||
141 | 141 | ||
142 | config SH_DMAE | 142 | config SH_DMAE |
143 | tristate "Renesas SuperH DMAC support" | 143 | tristate "Renesas SuperH DMAC support" |
144 | depends on SUPERH && SH_DMA | 144 | depends on (SUPERH && SH_DMA) || (ARM && ARCH_SHMOBILE) |
145 | depends on !SH_DMA_API | 145 | depends on !SH_DMA_API |
146 | select DMA_ENGINE | 146 | select DMA_ENGINE |
147 | help | 147 | help |
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index f0fd6db6063c..cea08bed9cf9 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c | |||
@@ -1297,7 +1297,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan) | |||
1297 | kfree(chan); | 1297 | kfree(chan); |
1298 | } | 1298 | } |
1299 | 1299 | ||
1300 | static int __devinit fsldma_of_probe(struct of_device *op, | 1300 | static int __devinit fsldma_of_probe(struct platform_device *op, |
1301 | const struct of_device_id *match) | 1301 | const struct of_device_id *match) |
1302 | { | 1302 | { |
1303 | struct fsldma_device *fdev; | 1303 | struct fsldma_device *fdev; |
@@ -1382,7 +1382,7 @@ out_return: | |||
1382 | return err; | 1382 | return err; |
1383 | } | 1383 | } |
1384 | 1384 | ||
1385 | static int fsldma_of_remove(struct of_device *op) | 1385 | static int fsldma_of_remove(struct platform_device *op) |
1386 | { | 1386 | { |
1387 | struct fsldma_device *fdev; | 1387 | struct fsldma_device *fdev; |
1388 | unsigned int i; | 1388 | unsigned int i; |
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 14a8c0f1698e..4e9cbf300594 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c | |||
@@ -627,7 +627,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, | |||
627 | return &mdesc->desc; | 627 | return &mdesc->desc; |
628 | } | 628 | } |
629 | 629 | ||
630 | static int __devinit mpc_dma_probe(struct of_device *op, | 630 | static int __devinit mpc_dma_probe(struct platform_device *op, |
631 | const struct of_device_id *match) | 631 | const struct of_device_id *match) |
632 | { | 632 | { |
633 | struct device_node *dn = op->dev.of_node; | 633 | struct device_node *dn = op->dev.of_node; |
@@ -753,7 +753,7 @@ static int __devinit mpc_dma_probe(struct of_device *op, | |||
753 | return retval; | 753 | return retval; |
754 | } | 754 | } |
755 | 755 | ||
756 | static int __devexit mpc_dma_remove(struct of_device *op) | 756 | static int __devexit mpc_dma_remove(struct platform_device *op) |
757 | { | 757 | { |
758 | struct device *dev = &op->dev; | 758 | struct device *dev = &op->dev; |
759 | struct mpc_dma *mdma = dev_get_drvdata(dev); | 759 | struct mpc_dma *mdma = dev_get_drvdata(dev); |
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 7c3747902a37..0d58a4a4487f 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c | |||
@@ -4257,11 +4257,11 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev, | |||
4257 | struct ppc440spe_adma_chan *chan, | 4257 | struct ppc440spe_adma_chan *chan, |
4258 | int *initcode) | 4258 | int *initcode) |
4259 | { | 4259 | { |
4260 | struct of_device *ofdev; | 4260 | struct platform_device *ofdev; |
4261 | struct device_node *np; | 4261 | struct device_node *np; |
4262 | int ret; | 4262 | int ret; |
4263 | 4263 | ||
4264 | ofdev = container_of(adev->dev, struct of_device, dev); | 4264 | ofdev = container_of(adev->dev, struct platform_device, dev); |
4265 | np = ofdev->dev.of_node; | 4265 | np = ofdev->dev.of_node; |
4266 | if (adev->id != PPC440SPE_XOR_ID) { | 4266 | if (adev->id != PPC440SPE_XOR_ID) { |
4267 | adev->err_irq = irq_of_parse_and_map(np, 1); | 4267 | adev->err_irq = irq_of_parse_and_map(np, 1); |
@@ -4393,7 +4393,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev, | |||
4393 | /** | 4393 | /** |
4394 | * ppc440spe_adma_probe - probe the asynch device | 4394 | * ppc440spe_adma_probe - probe the asynch device |
4395 | */ | 4395 | */ |
4396 | static int __devinit ppc440spe_adma_probe(struct of_device *ofdev, | 4396 | static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev, |
4397 | const struct of_device_id *match) | 4397 | const struct of_device_id *match) |
4398 | { | 4398 | { |
4399 | struct device_node *np = ofdev->dev.of_node; | 4399 | struct device_node *np = ofdev->dev.of_node; |
@@ -4625,7 +4625,7 @@ out: | |||
4625 | /** | 4625 | /** |
4626 | * ppc440spe_adma_remove - remove the asynch device | 4626 | * ppc440spe_adma_remove - remove the asynch device |
4627 | */ | 4627 | */ |
4628 | static int __devexit ppc440spe_adma_remove(struct of_device *ofdev) | 4628 | static int __devexit ppc440spe_adma_remove(struct platform_device *ofdev) |
4629 | { | 4629 | { |
4630 | struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); | 4630 | struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); |
4631 | struct device_node *np = ofdev->dev.of_node; | 4631 | struct device_node *np = ofdev->dev.of_node; |
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index a2a519fd2a24..fb64cf36ba61 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -816,7 +816,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data) | |||
816 | return ret; | 816 | return ret; |
817 | } | 817 | } |
818 | 818 | ||
819 | #if defined(CONFIG_CPU_SH4) | 819 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) |
820 | static irqreturn_t sh_dmae_err(int irq, void *data) | 820 | static irqreturn_t sh_dmae_err(int irq, void *data) |
821 | { | 821 | { |
822 | struct sh_dmae_device *shdev = (struct sh_dmae_device *)data; | 822 | struct sh_dmae_device *shdev = (struct sh_dmae_device *)data; |
@@ -1057,7 +1057,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1057 | /* Default transfer size of 32 bytes requires 32-byte alignment */ | 1057 | /* Default transfer size of 32 bytes requires 32-byte alignment */ |
1058 | shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; | 1058 | shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; |
1059 | 1059 | ||
1060 | #if defined(CONFIG_CPU_SH4) | 1060 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) |
1061 | chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | 1061 | chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); |
1062 | 1062 | ||
1063 | if (!chanirq_res) | 1063 | if (!chanirq_res) |
@@ -1082,7 +1082,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1082 | 1082 | ||
1083 | #else | 1083 | #else |
1084 | chanirq_res = errirq_res; | 1084 | chanirq_res = errirq_res; |
1085 | #endif /* CONFIG_CPU_SH4 */ | 1085 | #endif /* CONFIG_CPU_SH4 || CONFIG_ARCH_SHMOBILE */ |
1086 | 1086 | ||
1087 | if (chanirq_res->start == chanirq_res->end && | 1087 | if (chanirq_res->start == chanirq_res->end && |
1088 | !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { | 1088 | !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { |
@@ -1129,7 +1129,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1129 | chan_probe_err: | 1129 | chan_probe_err: |
1130 | sh_dmae_chan_remove(shdev); | 1130 | sh_dmae_chan_remove(shdev); |
1131 | eirqres: | 1131 | eirqres: |
1132 | #if defined(CONFIG_CPU_SH4) | 1132 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) |
1133 | free_irq(errirq, shdev); | 1133 | free_irq(errirq, shdev); |
1134 | eirq_err: | 1134 | eirq_err: |
1135 | #endif | 1135 | #endif |
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 996c1bdb5a34..a5cefab8d65d 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
@@ -1482,7 +1482,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev, | |||
1482 | 1482 | ||
1483 | /* wake up device */ | 1483 | /* wake up device */ |
1484 | rc = pci_enable_device(pdev); | 1484 | rc = pci_enable_device(pdev); |
1485 | if (rc == -EIO) | 1485 | if (rc) |
1486 | return rc; | 1486 | return rc; |
1487 | 1487 | ||
1488 | /* now probe and enable the device */ | 1488 | /* now probe and enable the device */ |
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 010c1d6526f5..38a9be9e1c7c 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c | |||
@@ -1348,7 +1348,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev, | |||
1348 | 1348 | ||
1349 | /* wake up device */ | 1349 | /* wake up device */ |
1350 | rc = pci_enable_device(pdev); | 1350 | rc = pci_enable_device(pdev); |
1351 | if (rc == -EIO) | 1351 | if (rc) |
1352 | return rc; | 1352 | return rc; |
1353 | 1353 | ||
1354 | /* now probe and enable the device */ | 1354 | /* now probe and enable the device */ |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 1052340e6802..b123bb308a4a 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -43,7 +43,7 @@ static u32 orig_pci_err_en; | |||
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | static u32 orig_l2_err_disable; | 45 | static u32 orig_l2_err_disable; |
46 | #ifdef CONFIG_MPC85xx | 46 | #ifdef CONFIG_FSL_SOC_BOOKE |
47 | static u32 orig_hid1[2]; | 47 | static u32 orig_hid1[2]; |
48 | #endif | 48 | #endif |
49 | 49 | ||
@@ -200,7 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) | |||
200 | return IRQ_HANDLED; | 200 | return IRQ_HANDLED; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int __devinit mpc85xx_pci_err_probe(struct of_device *op, | 203 | static int __devinit mpc85xx_pci_err_probe(struct platform_device *op, |
204 | const struct of_device_id *match) | 204 | const struct of_device_id *match) |
205 | { | 205 | { |
206 | struct edac_pci_ctl_info *pci; | 206 | struct edac_pci_ctl_info *pci; |
@@ -305,7 +305,7 @@ err: | |||
305 | return res; | 305 | return res; |
306 | } | 306 | } |
307 | 307 | ||
308 | static int mpc85xx_pci_err_remove(struct of_device *op) | 308 | static int mpc85xx_pci_err_remove(struct platform_device *op) |
309 | { | 309 | { |
310 | struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); | 310 | struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); |
311 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; | 311 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; |
@@ -503,7 +503,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id) | |||
503 | return IRQ_HANDLED; | 503 | return IRQ_HANDLED; |
504 | } | 504 | } |
505 | 505 | ||
506 | static int __devinit mpc85xx_l2_err_probe(struct of_device *op, | 506 | static int __devinit mpc85xx_l2_err_probe(struct platform_device *op, |
507 | const struct of_device_id *match) | 507 | const struct of_device_id *match) |
508 | { | 508 | { |
509 | struct edac_device_ctl_info *edac_dev; | 509 | struct edac_device_ctl_info *edac_dev; |
@@ -613,7 +613,7 @@ err: | |||
613 | return res; | 613 | return res; |
614 | } | 614 | } |
615 | 615 | ||
616 | static int mpc85xx_l2_err_remove(struct of_device *op) | 616 | static int mpc85xx_l2_err_remove(struct platform_device *op) |
617 | { | 617 | { |
618 | struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); | 618 | struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); |
619 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | 619 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; |
@@ -647,7 +647,10 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = { | |||
647 | { .compatible = "fsl,mpc8555-l2-cache-controller", }, | 647 | { .compatible = "fsl,mpc8555-l2-cache-controller", }, |
648 | { .compatible = "fsl,mpc8560-l2-cache-controller", }, | 648 | { .compatible = "fsl,mpc8560-l2-cache-controller", }, |
649 | { .compatible = "fsl,mpc8568-l2-cache-controller", }, | 649 | { .compatible = "fsl,mpc8568-l2-cache-controller", }, |
650 | { .compatible = "fsl,mpc8569-l2-cache-controller", }, | ||
650 | { .compatible = "fsl,mpc8572-l2-cache-controller", }, | 651 | { .compatible = "fsl,mpc8572-l2-cache-controller", }, |
652 | { .compatible = "fsl,p1020-l2-cache-controller", }, | ||
653 | { .compatible = "fsl,p1021-l2-cache-controller", }, | ||
651 | { .compatible = "fsl,p2020-l2-cache-controller", }, | 654 | { .compatible = "fsl,p2020-l2-cache-controller", }, |
652 | {}, | 655 | {}, |
653 | }; | 656 | }; |
@@ -953,7 +956,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) | |||
953 | } | 956 | } |
954 | } | 957 | } |
955 | 958 | ||
956 | static int __devinit mpc85xx_mc_err_probe(struct of_device *op, | 959 | static int __devinit mpc85xx_mc_err_probe(struct platform_device *op, |
957 | const struct of_device_id *match) | 960 | const struct of_device_id *match) |
958 | { | 961 | { |
959 | struct mem_ctl_info *mci; | 962 | struct mem_ctl_info *mci; |
@@ -1085,7 +1088,7 @@ err: | |||
1085 | return res; | 1088 | return res; |
1086 | } | 1089 | } |
1087 | 1090 | ||
1088 | static int mpc85xx_mc_err_remove(struct of_device *op) | 1091 | static int mpc85xx_mc_err_remove(struct platform_device *op) |
1089 | { | 1092 | { |
1090 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); | 1093 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); |
1091 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | 1094 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; |
@@ -1125,7 +1128,10 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = { | |||
1125 | { .compatible = "fsl,mpc8569-memory-controller", }, | 1128 | { .compatible = "fsl,mpc8569-memory-controller", }, |
1126 | { .compatible = "fsl,mpc8572-memory-controller", }, | 1129 | { .compatible = "fsl,mpc8572-memory-controller", }, |
1127 | { .compatible = "fsl,mpc8349-memory-controller", }, | 1130 | { .compatible = "fsl,mpc8349-memory-controller", }, |
1131 | { .compatible = "fsl,p1020-memory-controller", }, | ||
1132 | { .compatible = "fsl,p1021-memory-controller", }, | ||
1128 | { .compatible = "fsl,p2020-memory-controller", }, | 1133 | { .compatible = "fsl,p2020-memory-controller", }, |
1134 | { .compatible = "fsl,p4080-memory-controller", }, | ||
1129 | {}, | 1135 | {}, |
1130 | }; | 1136 | }; |
1131 | MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match); | 1137 | MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match); |
@@ -1140,7 +1146,7 @@ static struct of_platform_driver mpc85xx_mc_err_driver = { | |||
1140 | }, | 1146 | }, |
1141 | }; | 1147 | }; |
1142 | 1148 | ||
1143 | #ifdef CONFIG_MPC85xx | 1149 | #ifdef CONFIG_FSL_SOC_BOOKE |
1144 | static void __init mpc85xx_mc_clear_rfxe(void *data) | 1150 | static void __init mpc85xx_mc_clear_rfxe(void *data) |
1145 | { | 1151 | { |
1146 | orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1); | 1152 | orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1); |
@@ -1179,7 +1185,7 @@ static int __init mpc85xx_mc_init(void) | |||
1179 | printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n"); | 1185 | printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n"); |
1180 | #endif | 1186 | #endif |
1181 | 1187 | ||
1182 | #ifdef CONFIG_MPC85xx | 1188 | #ifdef CONFIG_FSL_SOC_BOOKE |
1183 | /* | 1189 | /* |
1184 | * need to clear HID1[RFXE] to disable machine check int | 1190 | * need to clear HID1[RFXE] to disable machine check int |
1185 | * so we can catch it | 1191 | * so we can catch it |
@@ -1193,7 +1199,7 @@ static int __init mpc85xx_mc_init(void) | |||
1193 | 1199 | ||
1194 | module_init(mpc85xx_mc_init); | 1200 | module_init(mpc85xx_mc_init); |
1195 | 1201 | ||
1196 | #ifdef CONFIG_MPC85xx | 1202 | #ifdef CONFIG_FSL_SOC_BOOKE |
1197 | static void __exit mpc85xx_mc_restore_hid1(void *data) | 1203 | static void __exit mpc85xx_mc_restore_hid1(void *data) |
1198 | { | 1204 | { |
1199 | mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]); | 1205 | mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]); |
@@ -1202,7 +1208,7 @@ static void __exit mpc85xx_mc_restore_hid1(void *data) | |||
1202 | 1208 | ||
1203 | static void __exit mpc85xx_mc_exit(void) | 1209 | static void __exit mpc85xx_mc_exit(void) |
1204 | { | 1210 | { |
1205 | #ifdef CONFIG_MPC85xx | 1211 | #ifdef CONFIG_FSL_SOC_BOOKE |
1206 | on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0); | 1212 | on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0); |
1207 | #endif | 1213 | #endif |
1208 | #ifdef CONFIG_PCI | 1214 | #ifdef CONFIG_PCI |
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index e78839e89a06..070cea41b661 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c | |||
@@ -184,9 +184,9 @@ struct ppc4xx_ecc_status { | |||
184 | 184 | ||
185 | /* Function Prototypes */ | 185 | /* Function Prototypes */ |
186 | 186 | ||
187 | static int ppc4xx_edac_probe(struct of_device *device, | 187 | static int ppc4xx_edac_probe(struct platform_device *device, |
188 | const struct of_device_id *device_id); | 188 | const struct of_device_id *device_id); |
189 | static int ppc4xx_edac_remove(struct of_device *device); | 189 | static int ppc4xx_edac_remove(struct platform_device *device); |
190 | 190 | ||
191 | /* Global Variables */ | 191 | /* Global Variables */ |
192 | 192 | ||
@@ -1014,7 +1014,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) | |||
1014 | */ | 1014 | */ |
1015 | static int __devinit | 1015 | static int __devinit |
1016 | ppc4xx_edac_mc_init(struct mem_ctl_info *mci, | 1016 | ppc4xx_edac_mc_init(struct mem_ctl_info *mci, |
1017 | struct of_device *op, | 1017 | struct platform_device *op, |
1018 | const struct of_device_id *match, | 1018 | const struct of_device_id *match, |
1019 | const dcr_host_t *dcr_host, | 1019 | const dcr_host_t *dcr_host, |
1020 | u32 mcopt1) | 1020 | u32 mcopt1) |
@@ -1108,7 +1108,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, | |||
1108 | * mapped and assigned. | 1108 | * mapped and assigned. |
1109 | */ | 1109 | */ |
1110 | static int __devinit | 1110 | static int __devinit |
1111 | ppc4xx_edac_register_irq(struct of_device *op, struct mem_ctl_info *mci) | 1111 | ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci) |
1112 | { | 1112 | { |
1113 | int status = 0; | 1113 | int status = 0; |
1114 | int ded_irq, sec_irq; | 1114 | int ded_irq, sec_irq; |
@@ -1238,7 +1238,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) | |||
1238 | * driver; otherwise, < 0 on error. | 1238 | * driver; otherwise, < 0 on error. |
1239 | */ | 1239 | */ |
1240 | static int __devinit | 1240 | static int __devinit |
1241 | ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) | 1241 | ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match) |
1242 | { | 1242 | { |
1243 | int status = 0; | 1243 | int status = 0; |
1244 | u32 mcopt1, memcheck; | 1244 | u32 mcopt1, memcheck; |
@@ -1359,7 +1359,7 @@ ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) | |||
1359 | * Unconditionally returns 0. | 1359 | * Unconditionally returns 0. |
1360 | */ | 1360 | */ |
1361 | static int | 1361 | static int |
1362 | ppc4xx_edac_remove(struct of_device *op) | 1362 | ppc4xx_edac_remove(struct platform_device *op) |
1363 | { | 1363 | { |
1364 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); | 1364 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); |
1365 | struct ppc4xx_edac_pdata *pdata = mci->pvt_info; | 1365 | struct ppc4xx_edac_pdata *pdata = mci->pvt_info; |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7face915b963..510aa2054544 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -195,6 +195,24 @@ config GPIO_PCF857X | |||
195 | This driver provides an in-kernel interface to those GPIOs using | 195 | This driver provides an in-kernel interface to those GPIOs using |
196 | platform-neutral GPIO calls. | 196 | platform-neutral GPIO calls. |
197 | 197 | ||
198 | config GPIO_SX150X | ||
199 | bool "Semtech SX150x I2C GPIO expander" | ||
200 | depends on I2C=y | ||
201 | default n | ||
202 | help | ||
203 | Say yes here to provide support for Semtech SX150-series I2C | ||
204 | GPIO expanders. Compatible models include: | ||
205 | |||
206 | 8 bits: sx1508q | ||
207 | 16 bits: sx1509q | ||
208 | |||
209 | config GPIO_STMPE | ||
210 | bool "STMPE GPIOs" | ||
211 | depends on MFD_STMPE | ||
212 | help | ||
213 | This enables support for the GPIOs found on the STMPE I/O | ||
214 | Expanders. | ||
215 | |||
198 | config GPIO_TC35892 | 216 | config GPIO_TC35892 |
199 | bool "TC35892 GPIOs" | 217 | bool "TC35892 GPIOs" |
200 | depends on MFD_TC35892 | 218 | depends on MFD_TC35892 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index e53dcff49b4f..fc6019d93720 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | |||
20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
22 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 22 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
23 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o | ||
23 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o | 24 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o |
24 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o | 25 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o |
25 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 26 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
@@ -35,3 +36,4 @@ obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o | |||
35 | obj-$(CONFIG_GPIO_SCH) += sch_gpio.o | 36 | obj-$(CONFIG_GPIO_SCH) += sch_gpio.o |
36 | obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o | 37 | obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o |
37 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o | 38 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o |
39 | obj-$(CONFIG_GPIO_SX150X) += sx150x.o | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6a6bd569e1f8..21da9c19a0cb 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -57,9 +57,9 @@ struct gpio_desc { | |||
57 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ | 57 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ |
58 | #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ | 58 | #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ |
59 | 59 | ||
60 | #define PDESC_ID_SHIFT 16 /* add new flags before this one */ | 60 | #define ID_SHIFT 16 /* add new flags before this one */ |
61 | 61 | ||
62 | #define GPIO_FLAGS_MASK ((1 << PDESC_ID_SHIFT) - 1) | 62 | #define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1) |
63 | #define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) | 63 | #define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) |
64 | 64 | ||
65 | #ifdef CONFIG_DEBUG_FS | 65 | #ifdef CONFIG_DEBUG_FS |
@@ -69,12 +69,7 @@ struct gpio_desc { | |||
69 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; | 69 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; |
70 | 70 | ||
71 | #ifdef CONFIG_GPIO_SYSFS | 71 | #ifdef CONFIG_GPIO_SYSFS |
72 | struct poll_desc { | 72 | static DEFINE_IDR(dirent_idr); |
73 | struct work_struct work; | ||
74 | struct sysfs_dirent *value_sd; | ||
75 | }; | ||
76 | |||
77 | static struct idr pdesc_idr; | ||
78 | #endif | 73 | #endif |
79 | 74 | ||
80 | static inline void desc_set_label(struct gpio_desc *d, const char *label) | 75 | static inline void desc_set_label(struct gpio_desc *d, const char *label) |
@@ -325,24 +320,16 @@ static const DEVICE_ATTR(value, 0644, | |||
325 | 320 | ||
326 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) | 321 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) |
327 | { | 322 | { |
328 | struct work_struct *work = priv; | 323 | struct sysfs_dirent *value_sd = priv; |
329 | 324 | ||
330 | schedule_work(work); | 325 | sysfs_notify_dirent(value_sd); |
331 | return IRQ_HANDLED; | 326 | return IRQ_HANDLED; |
332 | } | 327 | } |
333 | 328 | ||
334 | static void gpio_notify_sysfs(struct work_struct *work) | ||
335 | { | ||
336 | struct poll_desc *pdesc; | ||
337 | |||
338 | pdesc = container_of(work, struct poll_desc, work); | ||
339 | sysfs_notify_dirent(pdesc->value_sd); | ||
340 | } | ||
341 | |||
342 | static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | 329 | static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, |
343 | unsigned long gpio_flags) | 330 | unsigned long gpio_flags) |
344 | { | 331 | { |
345 | struct poll_desc *pdesc; | 332 | struct sysfs_dirent *value_sd; |
346 | unsigned long irq_flags; | 333 | unsigned long irq_flags; |
347 | int ret, irq, id; | 334 | int ret, irq, id; |
348 | 335 | ||
@@ -353,18 +340,16 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | |||
353 | if (irq < 0) | 340 | if (irq < 0) |
354 | return -EIO; | 341 | return -EIO; |
355 | 342 | ||
356 | id = desc->flags >> PDESC_ID_SHIFT; | 343 | id = desc->flags >> ID_SHIFT; |
357 | pdesc = idr_find(&pdesc_idr, id); | 344 | value_sd = idr_find(&dirent_idr, id); |
358 | if (pdesc) { | 345 | if (value_sd) |
359 | free_irq(irq, &pdesc->work); | 346 | free_irq(irq, value_sd); |
360 | cancel_work_sync(&pdesc->work); | ||
361 | } | ||
362 | 347 | ||
363 | desc->flags &= ~GPIO_TRIGGER_MASK; | 348 | desc->flags &= ~GPIO_TRIGGER_MASK; |
364 | 349 | ||
365 | if (!gpio_flags) { | 350 | if (!gpio_flags) { |
366 | ret = 0; | 351 | ret = 0; |
367 | goto free_sd; | 352 | goto free_id; |
368 | } | 353 | } |
369 | 354 | ||
370 | irq_flags = IRQF_SHARED; | 355 | irq_flags = IRQF_SHARED; |
@@ -375,55 +360,46 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, | |||
375 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? | 360 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
376 | IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; | 361 | IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; |
377 | 362 | ||
378 | if (!pdesc) { | 363 | if (!value_sd) { |
379 | pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL); | 364 | value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); |
380 | if (!pdesc) { | 365 | if (!value_sd) { |
381 | ret = -ENOMEM; | 366 | ret = -ENODEV; |
382 | goto err_out; | 367 | goto err_out; |
383 | } | 368 | } |
384 | 369 | ||
385 | do { | 370 | do { |
386 | ret = -ENOMEM; | 371 | ret = -ENOMEM; |
387 | if (idr_pre_get(&pdesc_idr, GFP_KERNEL)) | 372 | if (idr_pre_get(&dirent_idr, GFP_KERNEL)) |
388 | ret = idr_get_new_above(&pdesc_idr, | 373 | ret = idr_get_new_above(&dirent_idr, value_sd, |
389 | pdesc, 1, &id); | 374 | 1, &id); |
390 | } while (ret == -EAGAIN); | 375 | } while (ret == -EAGAIN); |
391 | 376 | ||
392 | if (ret) | 377 | if (ret) |
393 | goto free_mem; | 378 | goto free_sd; |
394 | 379 | ||
395 | desc->flags &= GPIO_FLAGS_MASK; | 380 | desc->flags &= GPIO_FLAGS_MASK; |
396 | desc->flags |= (unsigned long)id << PDESC_ID_SHIFT; | 381 | desc->flags |= (unsigned long)id << ID_SHIFT; |
397 | 382 | ||
398 | if (desc->flags >> PDESC_ID_SHIFT != id) { | 383 | if (desc->flags >> ID_SHIFT != id) { |
399 | ret = -ERANGE; | 384 | ret = -ERANGE; |
400 | goto free_id; | 385 | goto free_id; |
401 | } | 386 | } |
402 | |||
403 | pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); | ||
404 | if (!pdesc->value_sd) { | ||
405 | ret = -ENODEV; | ||
406 | goto free_id; | ||
407 | } | ||
408 | INIT_WORK(&pdesc->work, gpio_notify_sysfs); | ||
409 | } | 387 | } |
410 | 388 | ||
411 | ret = request_irq(irq, gpio_sysfs_irq, irq_flags, | 389 | ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags, |
412 | "gpiolib", &pdesc->work); | 390 | "gpiolib", value_sd); |
413 | if (ret) | 391 | if (ret < 0) |
414 | goto free_sd; | 392 | goto free_id; |
415 | 393 | ||
416 | desc->flags |= gpio_flags; | 394 | desc->flags |= gpio_flags; |
417 | return 0; | 395 | return 0; |
418 | 396 | ||
419 | free_sd: | ||
420 | if (pdesc) | ||
421 | sysfs_put(pdesc->value_sd); | ||
422 | free_id: | 397 | free_id: |
423 | idr_remove(&pdesc_idr, id); | 398 | idr_remove(&dirent_idr, id); |
424 | desc->flags &= GPIO_FLAGS_MASK; | 399 | desc->flags &= GPIO_FLAGS_MASK; |
425 | free_mem: | 400 | free_sd: |
426 | kfree(pdesc); | 401 | if (value_sd) |
402 | sysfs_put(value_sd); | ||
427 | err_out: | 403 | err_out: |
428 | return ret; | 404 | return ret; |
429 | } | 405 | } |
@@ -994,8 +970,6 @@ static int __init gpiolib_sysfs_init(void) | |||
994 | unsigned long flags; | 970 | unsigned long flags; |
995 | unsigned gpio; | 971 | unsigned gpio; |
996 | 972 | ||
997 | idr_init(&pdesc_idr); | ||
998 | |||
999 | status = class_register(&gpio_class); | 973 | status = class_register(&gpio_class); |
1000 | if (status < 0) | 974 | if (status < 0) |
1001 | return status; | 975 | return status; |
@@ -1272,7 +1246,7 @@ void gpio_free(unsigned gpio) | |||
1272 | if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { | 1246 | if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { |
1273 | if (chip->free) { | 1247 | if (chip->free) { |
1274 | spin_unlock_irqrestore(&gpio_lock, flags); | 1248 | spin_unlock_irqrestore(&gpio_lock, flags); |
1275 | might_sleep_if(extra_checks && chip->can_sleep); | 1249 | might_sleep_if(chip->can_sleep); |
1276 | chip->free(chip, gpio - chip->base); | 1250 | chip->free(chip, gpio - chip->base); |
1277 | spin_lock_irqsave(&gpio_lock, flags); | 1251 | spin_lock_irqsave(&gpio_lock, flags); |
1278 | } | 1252 | } |
@@ -1410,7 +1384,7 @@ int gpio_direction_input(unsigned gpio) | |||
1410 | 1384 | ||
1411 | spin_unlock_irqrestore(&gpio_lock, flags); | 1385 | spin_unlock_irqrestore(&gpio_lock, flags); |
1412 | 1386 | ||
1413 | might_sleep_if(extra_checks && chip->can_sleep); | 1387 | might_sleep_if(chip->can_sleep); |
1414 | 1388 | ||
1415 | if (status) { | 1389 | if (status) { |
1416 | status = chip->request(chip, gpio); | 1390 | status = chip->request(chip, gpio); |
@@ -1463,7 +1437,7 @@ int gpio_direction_output(unsigned gpio, int value) | |||
1463 | 1437 | ||
1464 | spin_unlock_irqrestore(&gpio_lock, flags); | 1438 | spin_unlock_irqrestore(&gpio_lock, flags); |
1465 | 1439 | ||
1466 | might_sleep_if(extra_checks && chip->can_sleep); | 1440 | might_sleep_if(chip->can_sleep); |
1467 | 1441 | ||
1468 | if (status) { | 1442 | if (status) { |
1469 | status = chip->request(chip, gpio); | 1443 | status = chip->request(chip, gpio); |
@@ -1521,7 +1495,7 @@ int gpio_set_debounce(unsigned gpio, unsigned debounce) | |||
1521 | 1495 | ||
1522 | spin_unlock_irqrestore(&gpio_lock, flags); | 1496 | spin_unlock_irqrestore(&gpio_lock, flags); |
1523 | 1497 | ||
1524 | might_sleep_if(extra_checks && chip->can_sleep); | 1498 | might_sleep_if(chip->can_sleep); |
1525 | 1499 | ||
1526 | return chip->set_debounce(chip, gpio, debounce); | 1500 | return chip->set_debounce(chip, gpio, debounce); |
1527 | 1501 | ||
@@ -1571,7 +1545,7 @@ int __gpio_get_value(unsigned gpio) | |||
1571 | struct gpio_chip *chip; | 1545 | struct gpio_chip *chip; |
1572 | 1546 | ||
1573 | chip = gpio_to_chip(gpio); | 1547 | chip = gpio_to_chip(gpio); |
1574 | WARN_ON(extra_checks && chip->can_sleep); | 1548 | WARN_ON(chip->can_sleep); |
1575 | return chip->get ? chip->get(chip, gpio - chip->base) : 0; | 1549 | return chip->get ? chip->get(chip, gpio - chip->base) : 0; |
1576 | } | 1550 | } |
1577 | EXPORT_SYMBOL_GPL(__gpio_get_value); | 1551 | EXPORT_SYMBOL_GPL(__gpio_get_value); |
@@ -1590,7 +1564,7 @@ void __gpio_set_value(unsigned gpio, int value) | |||
1590 | struct gpio_chip *chip; | 1564 | struct gpio_chip *chip; |
1591 | 1565 | ||
1592 | chip = gpio_to_chip(gpio); | 1566 | chip = gpio_to_chip(gpio); |
1593 | WARN_ON(extra_checks && chip->can_sleep); | 1567 | WARN_ON(chip->can_sleep); |
1594 | chip->set(chip, gpio - chip->base, value); | 1568 | chip->set(chip, gpio - chip->base, value); |
1595 | } | 1569 | } |
1596 | EXPORT_SYMBOL_GPL(__gpio_set_value); | 1570 | EXPORT_SYMBOL_GPL(__gpio_set_value); |
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/max730x.c index 7696a5625d58..94ce773f95f8 100644 --- a/drivers/gpio/max730x.c +++ b/drivers/gpio/max730x.c | |||
@@ -54,7 +54,7 @@ static int max7301_direction_input(struct gpio_chip *chip, unsigned offset) | |||
54 | { | 54 | { |
55 | struct max7301 *ts = container_of(chip, struct max7301, chip); | 55 | struct max7301 *ts = container_of(chip, struct max7301, chip); |
56 | u8 *config; | 56 | u8 *config; |
57 | u8 offset_bits; | 57 | u8 offset_bits, pin_config; |
58 | int ret; | 58 | int ret; |
59 | 59 | ||
60 | /* First 4 pins are unused in the controller */ | 60 | /* First 4 pins are unused in the controller */ |
@@ -63,12 +63,15 @@ static int max7301_direction_input(struct gpio_chip *chip, unsigned offset) | |||
63 | 63 | ||
64 | config = &ts->port_config[offset >> 2]; | 64 | config = &ts->port_config[offset >> 2]; |
65 | 65 | ||
66 | if (ts->input_pullup_active & BIT(offset)) | ||
67 | pin_config = PIN_CONFIG_IN_PULLUP; | ||
68 | else | ||
69 | pin_config = PIN_CONFIG_IN_WO_PULLUP; | ||
70 | |||
66 | mutex_lock(&ts->lock); | 71 | mutex_lock(&ts->lock); |
67 | 72 | ||
68 | /* Standard GPIO API doesn't support pull-ups, has to be extended. | ||
69 | * Hard-coding no pollup for now. */ | ||
70 | *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) | 73 | *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) |
71 | | (PIN_CONFIG_IN_WO_PULLUP << offset_bits); | 74 | | (pin_config << offset_bits); |
72 | 75 | ||
73 | ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); | 76 | ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); |
74 | 77 | ||
@@ -177,6 +180,7 @@ int __devinit __max730x_probe(struct max7301 *ts) | |||
177 | /* Power up the chip and disable IRQ output */ | 180 | /* Power up the chip and disable IRQ output */ |
178 | ts->write(dev, 0x04, 0x01); | 181 | ts->write(dev, 0x04, 0x01); |
179 | 182 | ||
183 | ts->input_pullup_active = pdata->input_pullup_active; | ||
180 | ts->chip.label = dev->driver->name; | 184 | ts->chip.label = dev->driver->name; |
181 | 185 | ||
182 | ts->chip.direction_input = max7301_direction_input; | 186 | ts->chip.direction_input = max7301_direction_input; |
@@ -191,13 +195,17 @@ int __devinit __max730x_probe(struct max7301 *ts) | |||
191 | ts->chip.owner = THIS_MODULE; | 195 | ts->chip.owner = THIS_MODULE; |
192 | 196 | ||
193 | /* | 197 | /* |
194 | * tristate all pins in hardware and cache the | 198 | * initialize pullups according to platform data and cache the |
195 | * register values for later use. | 199 | * register values for later use. |
196 | */ | 200 | */ |
197 | for (i = 1; i < 8; i++) { | 201 | for (i = 1; i < 8; i++) { |
198 | int j; | 202 | int j; |
199 | /* 0xAA means input with internal pullup disabled */ | 203 | /* |
200 | ts->write(dev, 0x08 + i, 0xAA); | 204 | * initialize port_config with "0xAA", which means |
205 | * input with internal pullup disabled. This is needed | ||
206 | * to avoid writing zeros (in the inner for loop), | ||
207 | * which is not allowed according to the datasheet. | ||
208 | */ | ||
201 | ts->port_config[i] = 0xAA; | 209 | ts->port_config[i] = 0xAA; |
202 | for (j = 0; j < 4; j++) { | 210 | for (j = 0; j < 4; j++) { |
203 | int offset = (i - 1) * 4 + j; | 211 | int offset = (i - 1) * 4 + j; |
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index 29f19ce3e80f..879b473aab5a 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c | |||
@@ -190,7 +190,6 @@ static int pcf857x_probe(struct i2c_client *client, | |||
190 | pdata = client->dev.platform_data; | 190 | pdata = client->dev.platform_data; |
191 | if (!pdata) { | 191 | if (!pdata) { |
192 | dev_dbg(&client->dev, "no platform data\n"); | 192 | dev_dbg(&client->dev, "no platform data\n"); |
193 | return -EINVAL; | ||
194 | } | 193 | } |
195 | 194 | ||
196 | /* Allocate, initialize, and register this gpio_chip. */ | 195 | /* Allocate, initialize, and register this gpio_chip. */ |
@@ -200,7 +199,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
200 | 199 | ||
201 | mutex_init(&gpio->lock); | 200 | mutex_init(&gpio->lock); |
202 | 201 | ||
203 | gpio->chip.base = pdata->gpio_base; | 202 | gpio->chip.base = pdata ? pdata->gpio_base : -1; |
204 | gpio->chip.can_sleep = 1; | 203 | gpio->chip.can_sleep = 1; |
205 | gpio->chip.dev = &client->dev; | 204 | gpio->chip.dev = &client->dev; |
206 | gpio->chip.owner = THIS_MODULE; | 205 | gpio->chip.owner = THIS_MODULE; |
@@ -278,7 +277,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
278 | * to zero, our software copy of the "latch" then matches the chip's | 277 | * to zero, our software copy of the "latch" then matches the chip's |
279 | * all-ones reset state. Otherwise it flags pins to be driven low. | 278 | * all-ones reset state. Otherwise it flags pins to be driven low. |
280 | */ | 279 | */ |
281 | gpio->out = ~pdata->n_latch; | 280 | gpio->out = pdata ? ~pdata->n_latch : ~0; |
282 | 281 | ||
283 | status = gpiochip_add(&gpio->chip); | 282 | status = gpiochip_add(&gpio->chip); |
284 | if (status < 0) | 283 | if (status < 0) |
@@ -299,7 +298,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
299 | /* Let platform code set up the GPIOs and their users. | 298 | /* Let platform code set up the GPIOs and their users. |
300 | * Now is the first time anyone could use them. | 299 | * Now is the first time anyone could use them. |
301 | */ | 300 | */ |
302 | if (pdata->setup) { | 301 | if (pdata && pdata->setup) { |
303 | status = pdata->setup(client, | 302 | status = pdata->setup(client, |
304 | gpio->chip.base, gpio->chip.ngpio, | 303 | gpio->chip.base, gpio->chip.ngpio, |
305 | pdata->context); | 304 | pdata->context); |
@@ -322,7 +321,7 @@ static int pcf857x_remove(struct i2c_client *client) | |||
322 | struct pcf857x *gpio = i2c_get_clientdata(client); | 321 | struct pcf857x *gpio = i2c_get_clientdata(client); |
323 | int status = 0; | 322 | int status = 0; |
324 | 323 | ||
325 | if (pdata->teardown) { | 324 | if (pdata && pdata->teardown) { |
326 | status = pdata->teardown(client, | 325 | status = pdata->teardown(client, |
327 | gpio->chip.base, gpio->chip.ngpio, | 326 | gpio->chip.base, gpio->chip.ngpio, |
328 | pdata->context); | 327 | pdata->context); |
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c new file mode 100644 index 000000000000..4e1f1b9d5e67 --- /dev/null +++ b/drivers/gpio/stmpe-gpio.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | |||
17 | /* | ||
18 | * These registers are modified under the irq bus lock and cached to avoid | ||
19 | * unnecessary writes in bus_sync_unlock. | ||
20 | */ | ||
21 | enum { REG_RE, REG_FE, REG_IE }; | ||
22 | |||
23 | #define CACHE_NR_REGS 3 | ||
24 | #define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8) | ||
25 | |||
26 | struct stmpe_gpio { | ||
27 | struct gpio_chip chip; | ||
28 | struct stmpe *stmpe; | ||
29 | struct device *dev; | ||
30 | struct mutex irq_lock; | ||
31 | |||
32 | int irq_base; | ||
33 | |||
34 | /* Caches of interrupt control registers for bus_lock */ | ||
35 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
36 | u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
37 | }; | ||
38 | |||
39 | static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip) | ||
40 | { | ||
41 | return container_of(chip, struct stmpe_gpio, chip); | ||
42 | } | ||
43 | |||
44 | static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
45 | { | ||
46 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
47 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
48 | u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8); | ||
49 | u8 mask = 1 << (offset % 8); | ||
50 | int ret; | ||
51 | |||
52 | ret = stmpe_reg_read(stmpe, reg); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | return ret & mask; | ||
57 | } | ||
58 | |||
59 | static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
60 | { | ||
61 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
62 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
63 | int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB; | ||
64 | u8 reg = stmpe->regs[which] - (offset / 8); | ||
65 | u8 mask = 1 << (offset % 8); | ||
66 | |||
67 | stmpe_reg_write(stmpe, reg, mask); | ||
68 | } | ||
69 | |||
70 | static int stmpe_gpio_direction_output(struct gpio_chip *chip, | ||
71 | unsigned offset, int val) | ||
72 | { | ||
73 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
74 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
75 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
76 | u8 mask = 1 << (offset % 8); | ||
77 | |||
78 | stmpe_gpio_set(chip, offset, val); | ||
79 | |||
80 | return stmpe_set_bits(stmpe, reg, mask, mask); | ||
81 | } | ||
82 | |||
83 | static int stmpe_gpio_direction_input(struct gpio_chip *chip, | ||
84 | unsigned offset) | ||
85 | { | ||
86 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
87 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
88 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
89 | u8 mask = 1 << (offset % 8); | ||
90 | |||
91 | return stmpe_set_bits(stmpe, reg, mask, 0); | ||
92 | } | ||
93 | |||
94 | static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
95 | { | ||
96 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
97 | |||
98 | return stmpe_gpio->irq_base + offset; | ||
99 | } | ||
100 | |||
101 | static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
102 | { | ||
103 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip); | ||
104 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
105 | |||
106 | return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO); | ||
107 | } | ||
108 | |||
109 | static struct gpio_chip template_chip = { | ||
110 | .label = "stmpe", | ||
111 | .owner = THIS_MODULE, | ||
112 | .direction_input = stmpe_gpio_direction_input, | ||
113 | .get = stmpe_gpio_get, | ||
114 | .direction_output = stmpe_gpio_direction_output, | ||
115 | .set = stmpe_gpio_set, | ||
116 | .to_irq = stmpe_gpio_to_irq, | ||
117 | .request = stmpe_gpio_request, | ||
118 | .can_sleep = 1, | ||
119 | }; | ||
120 | |||
121 | static int stmpe_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
122 | { | ||
123 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
124 | int offset = irq - stmpe_gpio->irq_base; | ||
125 | int regoffset = offset / 8; | ||
126 | int mask = 1 << (offset % 8); | ||
127 | |||
128 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | ||
129 | return -EINVAL; | ||
130 | |||
131 | if (type == IRQ_TYPE_EDGE_RISING) | ||
132 | stmpe_gpio->regs[REG_RE][regoffset] |= mask; | ||
133 | else | ||
134 | stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; | ||
135 | |||
136 | if (type == IRQ_TYPE_EDGE_FALLING) | ||
137 | stmpe_gpio->regs[REG_FE][regoffset] |= mask; | ||
138 | else | ||
139 | stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void stmpe_gpio_irq_lock(unsigned int irq) | ||
145 | { | ||
146 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
147 | |||
148 | mutex_lock(&stmpe_gpio->irq_lock); | ||
149 | } | ||
150 | |||
151 | static void stmpe_gpio_irq_sync_unlock(unsigned int irq) | ||
152 | { | ||
153 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
154 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
155 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
156 | static const u8 regmap[] = { | ||
157 | [REG_RE] = STMPE_IDX_GPRER_LSB, | ||
158 | [REG_FE] = STMPE_IDX_GPFER_LSB, | ||
159 | [REG_IE] = STMPE_IDX_IEGPIOR_LSB, | ||
160 | }; | ||
161 | int i, j; | ||
162 | |||
163 | for (i = 0; i < CACHE_NR_REGS; i++) { | ||
164 | for (j = 0; j < num_banks; j++) { | ||
165 | u8 old = stmpe_gpio->oldregs[i][j]; | ||
166 | u8 new = stmpe_gpio->regs[i][j]; | ||
167 | |||
168 | if (new == old) | ||
169 | continue; | ||
170 | |||
171 | stmpe_gpio->oldregs[i][j] = new; | ||
172 | stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | mutex_unlock(&stmpe_gpio->irq_lock); | ||
177 | } | ||
178 | |||
179 | static void stmpe_gpio_irq_mask(unsigned int irq) | ||
180 | { | ||
181 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
182 | int offset = irq - stmpe_gpio->irq_base; | ||
183 | int regoffset = offset / 8; | ||
184 | int mask = 1 << (offset % 8); | ||
185 | |||
186 | stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; | ||
187 | } | ||
188 | |||
189 | static void stmpe_gpio_irq_unmask(unsigned int irq) | ||
190 | { | ||
191 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | ||
192 | int offset = irq - stmpe_gpio->irq_base; | ||
193 | int regoffset = offset / 8; | ||
194 | int mask = 1 << (offset % 8); | ||
195 | |||
196 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; | ||
197 | } | ||
198 | |||
199 | static struct irq_chip stmpe_gpio_irq_chip = { | ||
200 | .name = "stmpe-gpio", | ||
201 | .bus_lock = stmpe_gpio_irq_lock, | ||
202 | .bus_sync_unlock = stmpe_gpio_irq_sync_unlock, | ||
203 | .mask = stmpe_gpio_irq_mask, | ||
204 | .unmask = stmpe_gpio_irq_unmask, | ||
205 | .set_type = stmpe_gpio_irq_set_type, | ||
206 | }; | ||
207 | |||
208 | static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | ||
209 | { | ||
210 | struct stmpe_gpio *stmpe_gpio = dev; | ||
211 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
212 | u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; | ||
213 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
214 | u8 status[num_banks]; | ||
215 | int ret; | ||
216 | int i; | ||
217 | |||
218 | ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status); | ||
219 | if (ret < 0) | ||
220 | return IRQ_NONE; | ||
221 | |||
222 | for (i = 0; i < num_banks; i++) { | ||
223 | int bank = num_banks - i - 1; | ||
224 | unsigned int enabled = stmpe_gpio->regs[REG_IE][bank]; | ||
225 | unsigned int stat = status[i]; | ||
226 | |||
227 | stat &= enabled; | ||
228 | if (!stat) | ||
229 | continue; | ||
230 | |||
231 | while (stat) { | ||
232 | int bit = __ffs(stat); | ||
233 | int line = bank * 8 + bit; | ||
234 | |||
235 | handle_nested_irq(stmpe_gpio->irq_base + line); | ||
236 | stat &= ~(1 << bit); | ||
237 | } | ||
238 | |||
239 | stmpe_reg_write(stmpe, statmsbreg + i, status[i]); | ||
240 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i, | ||
241 | status[i]); | ||
242 | } | ||
243 | |||
244 | return IRQ_HANDLED; | ||
245 | } | ||
246 | |||
247 | static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio) | ||
248 | { | ||
249 | int base = stmpe_gpio->irq_base; | ||
250 | int irq; | ||
251 | |||
252 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
253 | set_irq_chip_data(irq, stmpe_gpio); | ||
254 | set_irq_chip_and_handler(irq, &stmpe_gpio_irq_chip, | ||
255 | handle_simple_irq); | ||
256 | set_irq_nested_thread(irq, 1); | ||
257 | #ifdef CONFIG_ARM | ||
258 | set_irq_flags(irq, IRQF_VALID); | ||
259 | #else | ||
260 | set_irq_noprobe(irq); | ||
261 | #endif | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio) | ||
268 | { | ||
269 | int base = stmpe_gpio->irq_base; | ||
270 | int irq; | ||
271 | |||
272 | for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) { | ||
273 | #ifdef CONFIG_ARM | ||
274 | set_irq_flags(irq, 0); | ||
275 | #endif | ||
276 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
277 | set_irq_chip_data(irq, NULL); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | static int __devinit stmpe_gpio_probe(struct platform_device *pdev) | ||
282 | { | ||
283 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
284 | struct stmpe_gpio_platform_data *pdata; | ||
285 | struct stmpe_gpio *stmpe_gpio; | ||
286 | int ret; | ||
287 | int irq; | ||
288 | |||
289 | pdata = stmpe->pdata->gpio; | ||
290 | if (!pdata) | ||
291 | return -ENODEV; | ||
292 | |||
293 | irq = platform_get_irq(pdev, 0); | ||
294 | if (irq < 0) | ||
295 | return irq; | ||
296 | |||
297 | stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL); | ||
298 | if (!stmpe_gpio) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | mutex_init(&stmpe_gpio->irq_lock); | ||
302 | |||
303 | stmpe_gpio->dev = &pdev->dev; | ||
304 | stmpe_gpio->stmpe = stmpe; | ||
305 | |||
306 | stmpe_gpio->chip = template_chip; | ||
307 | stmpe_gpio->chip.ngpio = stmpe->num_gpios; | ||
308 | stmpe_gpio->chip.dev = &pdev->dev; | ||
309 | stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; | ||
310 | |||
311 | stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); | ||
312 | |||
313 | ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
314 | if (ret) | ||
315 | return ret; | ||
316 | |||
317 | ret = stmpe_gpio_irq_init(stmpe_gpio); | ||
318 | if (ret) | ||
319 | goto out_free; | ||
320 | |||
321 | ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT, | ||
322 | "stmpe-gpio", stmpe_gpio); | ||
323 | if (ret) { | ||
324 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
325 | goto out_removeirq; | ||
326 | } | ||
327 | |||
328 | ret = gpiochip_add(&stmpe_gpio->chip); | ||
329 | if (ret) { | ||
330 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
331 | goto out_freeirq; | ||
332 | } | ||
333 | |||
334 | if (pdata && pdata->setup) | ||
335 | pdata->setup(stmpe, stmpe_gpio->chip.base); | ||
336 | |||
337 | platform_set_drvdata(pdev, stmpe_gpio); | ||
338 | |||
339 | return 0; | ||
340 | |||
341 | out_freeirq: | ||
342 | free_irq(irq, stmpe_gpio); | ||
343 | out_removeirq: | ||
344 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
345 | out_free: | ||
346 | kfree(stmpe_gpio); | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int __devexit stmpe_gpio_remove(struct platform_device *pdev) | ||
351 | { | ||
352 | struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev); | ||
353 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
354 | struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio; | ||
355 | int irq = platform_get_irq(pdev, 0); | ||
356 | int ret; | ||
357 | |||
358 | if (pdata && pdata->remove) | ||
359 | pdata->remove(stmpe, stmpe_gpio->chip.base); | ||
360 | |||
361 | ret = gpiochip_remove(&stmpe_gpio->chip); | ||
362 | if (ret < 0) { | ||
363 | dev_err(stmpe_gpio->dev, | ||
364 | "unable to remove gpiochip: %d\n", ret); | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | ||
369 | |||
370 | free_irq(irq, stmpe_gpio); | ||
371 | stmpe_gpio_irq_remove(stmpe_gpio); | ||
372 | platform_set_drvdata(pdev, NULL); | ||
373 | kfree(stmpe_gpio); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static struct platform_driver stmpe_gpio_driver = { | ||
379 | .driver.name = "stmpe-gpio", | ||
380 | .driver.owner = THIS_MODULE, | ||
381 | .probe = stmpe_gpio_probe, | ||
382 | .remove = __devexit_p(stmpe_gpio_remove), | ||
383 | }; | ||
384 | |||
385 | static int __init stmpe_gpio_init(void) | ||
386 | { | ||
387 | return platform_driver_register(&stmpe_gpio_driver); | ||
388 | } | ||
389 | subsys_initcall(stmpe_gpio_init); | ||
390 | |||
391 | static void __exit stmpe_gpio_exit(void) | ||
392 | { | ||
393 | platform_driver_unregister(&stmpe_gpio_driver); | ||
394 | } | ||
395 | module_exit(stmpe_gpio_exit); | ||
396 | |||
397 | MODULE_LICENSE("GPL v2"); | ||
398 | MODULE_DESCRIPTION("STMPExxxx GPIO driver"); | ||
399 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c new file mode 100644 index 000000000000..b42f42ca70c3 --- /dev/null +++ b/drivers/gpio/sx150x.c | |||
@@ -0,0 +1,645 @@ | |||
1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/workqueue.h> | ||
26 | #include <linux/i2c/sx150x.h> | ||
27 | |||
28 | struct sx150x_device_data { | ||
29 | u8 reg_pullup; | ||
30 | u8 reg_pulldn; | ||
31 | u8 reg_drain; | ||
32 | u8 reg_polarity; | ||
33 | u8 reg_dir; | ||
34 | u8 reg_data; | ||
35 | u8 reg_irq_mask; | ||
36 | u8 reg_irq_src; | ||
37 | u8 reg_sense; | ||
38 | u8 reg_clock; | ||
39 | u8 reg_misc; | ||
40 | u8 reg_reset; | ||
41 | u8 ngpios; | ||
42 | }; | ||
43 | |||
44 | struct sx150x_chip { | ||
45 | struct gpio_chip gpio_chip; | ||
46 | struct i2c_client *client; | ||
47 | const struct sx150x_device_data *dev_cfg; | ||
48 | int irq_summary; | ||
49 | int irq_base; | ||
50 | u32 irq_sense; | ||
51 | unsigned long irq_set_type_pending; | ||
52 | struct irq_chip irq_chip; | ||
53 | struct mutex lock; | ||
54 | }; | ||
55 | |||
56 | static const struct sx150x_device_data sx150x_devices[] = { | ||
57 | [0] = { /* sx1508q */ | ||
58 | .reg_pullup = 0x03, | ||
59 | .reg_pulldn = 0x04, | ||
60 | .reg_drain = 0x05, | ||
61 | .reg_polarity = 0x06, | ||
62 | .reg_dir = 0x07, | ||
63 | .reg_data = 0x08, | ||
64 | .reg_irq_mask = 0x09, | ||
65 | .reg_irq_src = 0x0c, | ||
66 | .reg_sense = 0x0b, | ||
67 | .reg_clock = 0x0f, | ||
68 | .reg_misc = 0x10, | ||
69 | .reg_reset = 0x7d, | ||
70 | .ngpios = 8 | ||
71 | }, | ||
72 | [1] = { /* sx1509q */ | ||
73 | .reg_pullup = 0x07, | ||
74 | .reg_pulldn = 0x09, | ||
75 | .reg_drain = 0x0b, | ||
76 | .reg_polarity = 0x0d, | ||
77 | .reg_dir = 0x0f, | ||
78 | .reg_data = 0x11, | ||
79 | .reg_irq_mask = 0x13, | ||
80 | .reg_irq_src = 0x19, | ||
81 | .reg_sense = 0x17, | ||
82 | .reg_clock = 0x1e, | ||
83 | .reg_misc = 0x1f, | ||
84 | .reg_reset = 0x7d, | ||
85 | .ngpios = 16 | ||
86 | }, | ||
87 | }; | ||
88 | |||
89 | static const struct i2c_device_id sx150x_id[] = { | ||
90 | {"sx1508q", 0}, | ||
91 | {"sx1509q", 1}, | ||
92 | {} | ||
93 | }; | ||
94 | MODULE_DEVICE_TABLE(i2c, sx150x_id); | ||
95 | |||
96 | static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) | ||
97 | { | ||
98 | s32 err = i2c_smbus_write_byte_data(client, reg, val); | ||
99 | |||
100 | if (err < 0) | ||
101 | dev_warn(&client->dev, | ||
102 | "i2c write fail: can't write %02x to %02x: %d\n", | ||
103 | val, reg, err); | ||
104 | return err; | ||
105 | } | ||
106 | |||
107 | static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) | ||
108 | { | ||
109 | s32 err = i2c_smbus_read_byte_data(client, reg); | ||
110 | |||
111 | if (err >= 0) | ||
112 | *val = err; | ||
113 | else | ||
114 | dev_warn(&client->dev, | ||
115 | "i2c read fail: can't read from %02x: %d\n", | ||
116 | reg, err); | ||
117 | return err; | ||
118 | } | ||
119 | |||
120 | static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset) | ||
121 | { | ||
122 | return (chip->dev_cfg->ngpios == offset); | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * These utility functions solve the common problem of locating and setting | ||
127 | * configuration bits. Configuration bits are grouped into registers | ||
128 | * whose indexes increase downwards. For example, with eight-bit registers, | ||
129 | * sixteen gpios would have their config bits grouped in the following order: | ||
130 | * REGISTER N-1 [ f e d c b a 9 8 ] | ||
131 | * N [ 7 6 5 4 3 2 1 0 ] | ||
132 | * | ||
133 | * For multi-bit configurations, the pattern gets wider: | ||
134 | * REGISTER N-3 [ f f e e d d c c ] | ||
135 | * N-2 [ b b a a 9 9 8 8 ] | ||
136 | * N-1 [ 7 7 6 6 5 5 4 4 ] | ||
137 | * N [ 3 3 2 2 1 1 0 0 ] | ||
138 | * | ||
139 | * Given the address of the starting register 'N', the index of the gpio | ||
140 | * whose configuration we seek to change, and the width in bits of that | ||
141 | * configuration, these functions allow us to locate the correct | ||
142 | * register and mask the correct bits. | ||
143 | */ | ||
144 | static inline void sx150x_find_cfg(u8 offset, u8 width, | ||
145 | u8 *reg, u8 *mask, u8 *shift) | ||
146 | { | ||
147 | *reg -= offset * width / 8; | ||
148 | *mask = (1 << width) - 1; | ||
149 | *shift = (offset * width) % 8; | ||
150 | *mask <<= *shift; | ||
151 | } | ||
152 | |||
153 | static s32 sx150x_write_cfg(struct sx150x_chip *chip, | ||
154 | u8 offset, u8 width, u8 reg, u8 val) | ||
155 | { | ||
156 | u8 mask; | ||
157 | u8 data; | ||
158 | u8 shift; | ||
159 | s32 err; | ||
160 | |||
161 | sx150x_find_cfg(offset, width, ®, &mask, &shift); | ||
162 | err = sx150x_i2c_read(chip->client, reg, &data); | ||
163 | if (err < 0) | ||
164 | return err; | ||
165 | |||
166 | data &= ~mask; | ||
167 | data |= (val << shift) & mask; | ||
168 | return sx150x_i2c_write(chip->client, reg, data); | ||
169 | } | ||
170 | |||
171 | static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset) | ||
172 | { | ||
173 | u8 reg = chip->dev_cfg->reg_data; | ||
174 | u8 mask; | ||
175 | u8 data; | ||
176 | u8 shift; | ||
177 | s32 err; | ||
178 | |||
179 | sx150x_find_cfg(offset, 1, ®, &mask, &shift); | ||
180 | err = sx150x_i2c_read(chip->client, reg, &data); | ||
181 | if (err >= 0) | ||
182 | err = (data & mask) != 0 ? 1 : 0; | ||
183 | |||
184 | return err; | ||
185 | } | ||
186 | |||
187 | static void sx150x_set_oscio(struct sx150x_chip *chip, int val) | ||
188 | { | ||
189 | sx150x_i2c_write(chip->client, | ||
190 | chip->dev_cfg->reg_clock, | ||
191 | (val ? 0x1f : 0x10)); | ||
192 | } | ||
193 | |||
194 | static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val) | ||
195 | { | ||
196 | sx150x_write_cfg(chip, | ||
197 | offset, | ||
198 | 1, | ||
199 | chip->dev_cfg->reg_data, | ||
200 | (val ? 1 : 0)); | ||
201 | } | ||
202 | |||
203 | static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset) | ||
204 | { | ||
205 | return sx150x_write_cfg(chip, | ||
206 | offset, | ||
207 | 1, | ||
208 | chip->dev_cfg->reg_dir, | ||
209 | 1); | ||
210 | } | ||
211 | |||
212 | static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val) | ||
213 | { | ||
214 | int err; | ||
215 | |||
216 | err = sx150x_write_cfg(chip, | ||
217 | offset, | ||
218 | 1, | ||
219 | chip->dev_cfg->reg_data, | ||
220 | (val ? 1 : 0)); | ||
221 | if (err >= 0) | ||
222 | err = sx150x_write_cfg(chip, | ||
223 | offset, | ||
224 | 1, | ||
225 | chip->dev_cfg->reg_dir, | ||
226 | 0); | ||
227 | return err; | ||
228 | } | ||
229 | |||
230 | static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
231 | { | ||
232 | struct sx150x_chip *chip; | ||
233 | int status = -EINVAL; | ||
234 | |||
235 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
236 | |||
237 | if (!offset_is_oscio(chip, offset)) { | ||
238 | mutex_lock(&chip->lock); | ||
239 | status = sx150x_get_io(chip, offset); | ||
240 | mutex_unlock(&chip->lock); | ||
241 | } | ||
242 | |||
243 | return status; | ||
244 | } | ||
245 | |||
246 | static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) | ||
247 | { | ||
248 | struct sx150x_chip *chip; | ||
249 | |||
250 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
251 | |||
252 | mutex_lock(&chip->lock); | ||
253 | if (offset_is_oscio(chip, offset)) | ||
254 | sx150x_set_oscio(chip, val); | ||
255 | else | ||
256 | sx150x_set_io(chip, offset, val); | ||
257 | mutex_unlock(&chip->lock); | ||
258 | } | ||
259 | |||
260 | static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | ||
261 | { | ||
262 | struct sx150x_chip *chip; | ||
263 | int status = -EINVAL; | ||
264 | |||
265 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
266 | |||
267 | if (!offset_is_oscio(chip, offset)) { | ||
268 | mutex_lock(&chip->lock); | ||
269 | status = sx150x_io_input(chip, offset); | ||
270 | mutex_unlock(&chip->lock); | ||
271 | } | ||
272 | return status; | ||
273 | } | ||
274 | |||
275 | static int sx150x_gpio_direction_output(struct gpio_chip *gc, | ||
276 | unsigned offset, | ||
277 | int val) | ||
278 | { | ||
279 | struct sx150x_chip *chip; | ||
280 | int status = 0; | ||
281 | |||
282 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
283 | |||
284 | if (!offset_is_oscio(chip, offset)) { | ||
285 | mutex_lock(&chip->lock); | ||
286 | status = sx150x_io_output(chip, offset, val); | ||
287 | mutex_unlock(&chip->lock); | ||
288 | } | ||
289 | return status; | ||
290 | } | ||
291 | |||
292 | static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
293 | { | ||
294 | struct sx150x_chip *chip; | ||
295 | |||
296 | chip = container_of(gc, struct sx150x_chip, gpio_chip); | ||
297 | |||
298 | if (offset >= chip->dev_cfg->ngpios) | ||
299 | return -EINVAL; | ||
300 | |||
301 | if (chip->irq_base < 0) | ||
302 | return -EINVAL; | ||
303 | |||
304 | return chip->irq_base + offset; | ||
305 | } | ||
306 | |||
307 | static void sx150x_irq_mask(unsigned int irq) | ||
308 | { | ||
309 | struct irq_chip *ic = get_irq_chip(irq); | ||
310 | struct sx150x_chip *chip; | ||
311 | unsigned n; | ||
312 | |||
313 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
314 | n = irq - chip->irq_base; | ||
315 | |||
316 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); | ||
317 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); | ||
318 | } | ||
319 | |||
320 | static void sx150x_irq_unmask(unsigned int irq) | ||
321 | { | ||
322 | struct irq_chip *ic = get_irq_chip(irq); | ||
323 | struct sx150x_chip *chip; | ||
324 | unsigned n; | ||
325 | |||
326 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
327 | n = irq - chip->irq_base; | ||
328 | |||
329 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); | ||
330 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, | ||
331 | chip->irq_sense >> (n * 2)); | ||
332 | } | ||
333 | |||
334 | static int sx150x_irq_set_type(unsigned int irq, unsigned int flow_type) | ||
335 | { | ||
336 | struct irq_chip *ic = get_irq_chip(irq); | ||
337 | struct sx150x_chip *chip; | ||
338 | unsigned n, val = 0; | ||
339 | |||
340 | if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) | ||
341 | return -EINVAL; | ||
342 | |||
343 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
344 | n = irq - chip->irq_base; | ||
345 | |||
346 | if (flow_type & IRQ_TYPE_EDGE_RISING) | ||
347 | val |= 0x1; | ||
348 | if (flow_type & IRQ_TYPE_EDGE_FALLING) | ||
349 | val |= 0x2; | ||
350 | |||
351 | chip->irq_sense &= ~(3UL << (n * 2)); | ||
352 | chip->irq_sense |= val << (n * 2); | ||
353 | chip->irq_set_type_pending |= BIT(n); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) | ||
358 | { | ||
359 | struct sx150x_chip *chip = (struct sx150x_chip *)dev_id; | ||
360 | unsigned nhandled = 0; | ||
361 | unsigned sub_irq; | ||
362 | unsigned n; | ||
363 | s32 err; | ||
364 | u8 val; | ||
365 | int i; | ||
366 | |||
367 | for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) { | ||
368 | err = sx150x_i2c_read(chip->client, | ||
369 | chip->dev_cfg->reg_irq_src - i, | ||
370 | &val); | ||
371 | if (err < 0) | ||
372 | continue; | ||
373 | |||
374 | sx150x_i2c_write(chip->client, | ||
375 | chip->dev_cfg->reg_irq_src - i, | ||
376 | val); | ||
377 | for (n = 0; n < 8; ++n) { | ||
378 | if (val & (1 << n)) { | ||
379 | sub_irq = chip->irq_base + (i * 8) + n; | ||
380 | handle_nested_irq(sub_irq); | ||
381 | ++nhandled; | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | |||
386 | return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); | ||
387 | } | ||
388 | |||
389 | static void sx150x_irq_bus_lock(unsigned int irq) | ||
390 | { | ||
391 | struct irq_chip *ic = get_irq_chip(irq); | ||
392 | struct sx150x_chip *chip; | ||
393 | |||
394 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
395 | |||
396 | mutex_lock(&chip->lock); | ||
397 | } | ||
398 | |||
399 | static void sx150x_irq_bus_sync_unlock(unsigned int irq) | ||
400 | { | ||
401 | struct irq_chip *ic = get_irq_chip(irq); | ||
402 | struct sx150x_chip *chip; | ||
403 | unsigned n; | ||
404 | |||
405 | chip = container_of(ic, struct sx150x_chip, irq_chip); | ||
406 | |||
407 | while (chip->irq_set_type_pending) { | ||
408 | n = __ffs(chip->irq_set_type_pending); | ||
409 | chip->irq_set_type_pending &= ~BIT(n); | ||
410 | if (!(irq_to_desc(n + chip->irq_base)->status & IRQ_MASKED)) | ||
411 | sx150x_write_cfg(chip, n, 2, | ||
412 | chip->dev_cfg->reg_sense, | ||
413 | chip->irq_sense >> (n * 2)); | ||
414 | } | ||
415 | |||
416 | mutex_unlock(&chip->lock); | ||
417 | } | ||
418 | |||
419 | static void sx150x_init_chip(struct sx150x_chip *chip, | ||
420 | struct i2c_client *client, | ||
421 | kernel_ulong_t driver_data, | ||
422 | struct sx150x_platform_data *pdata) | ||
423 | { | ||
424 | mutex_init(&chip->lock); | ||
425 | |||
426 | chip->client = client; | ||
427 | chip->dev_cfg = &sx150x_devices[driver_data]; | ||
428 | chip->gpio_chip.label = client->name; | ||
429 | chip->gpio_chip.direction_input = sx150x_gpio_direction_input; | ||
430 | chip->gpio_chip.direction_output = sx150x_gpio_direction_output; | ||
431 | chip->gpio_chip.get = sx150x_gpio_get; | ||
432 | chip->gpio_chip.set = sx150x_gpio_set; | ||
433 | chip->gpio_chip.to_irq = sx150x_gpio_to_irq; | ||
434 | chip->gpio_chip.base = pdata->gpio_base; | ||
435 | chip->gpio_chip.can_sleep = 1; | ||
436 | chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; | ||
437 | if (pdata->oscio_is_gpo) | ||
438 | ++chip->gpio_chip.ngpio; | ||
439 | |||
440 | chip->irq_chip.name = client->name; | ||
441 | chip->irq_chip.mask = sx150x_irq_mask; | ||
442 | chip->irq_chip.unmask = sx150x_irq_unmask; | ||
443 | chip->irq_chip.set_type = sx150x_irq_set_type; | ||
444 | chip->irq_chip.bus_lock = sx150x_irq_bus_lock; | ||
445 | chip->irq_chip.bus_sync_unlock = sx150x_irq_bus_sync_unlock; | ||
446 | chip->irq_summary = -1; | ||
447 | chip->irq_base = -1; | ||
448 | chip->irq_sense = 0; | ||
449 | chip->irq_set_type_pending = 0; | ||
450 | } | ||
451 | |||
452 | static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) | ||
453 | { | ||
454 | int err = 0; | ||
455 | unsigned n; | ||
456 | |||
457 | for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n) | ||
458 | err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8)); | ||
459 | return err; | ||
460 | } | ||
461 | |||
462 | static int sx150x_init_hw(struct sx150x_chip *chip, | ||
463 | struct sx150x_platform_data *pdata) | ||
464 | { | ||
465 | int err = 0; | ||
466 | |||
467 | err = i2c_smbus_write_word_data(chip->client, | ||
468 | chip->dev_cfg->reg_reset, | ||
469 | 0x3412); | ||
470 | if (err < 0) | ||
471 | return err; | ||
472 | |||
473 | err = sx150x_i2c_write(chip->client, | ||
474 | chip->dev_cfg->reg_misc, | ||
475 | 0x01); | ||
476 | if (err < 0) | ||
477 | return err; | ||
478 | |||
479 | err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup, | ||
480 | pdata->io_pullup_ena); | ||
481 | if (err < 0) | ||
482 | return err; | ||
483 | |||
484 | err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn, | ||
485 | pdata->io_pulldn_ena); | ||
486 | if (err < 0) | ||
487 | return err; | ||
488 | |||
489 | err = sx150x_init_io(chip, chip->dev_cfg->reg_drain, | ||
490 | pdata->io_open_drain_ena); | ||
491 | if (err < 0) | ||
492 | return err; | ||
493 | |||
494 | err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity, | ||
495 | pdata->io_polarity); | ||
496 | if (err < 0) | ||
497 | return err; | ||
498 | |||
499 | if (pdata->oscio_is_gpo) | ||
500 | sx150x_set_oscio(chip, 0); | ||
501 | |||
502 | return err; | ||
503 | } | ||
504 | |||
505 | static int sx150x_install_irq_chip(struct sx150x_chip *chip, | ||
506 | int irq_summary, | ||
507 | int irq_base) | ||
508 | { | ||
509 | int err; | ||
510 | unsigned n; | ||
511 | unsigned irq; | ||
512 | |||
513 | chip->irq_summary = irq_summary; | ||
514 | chip->irq_base = irq_base; | ||
515 | |||
516 | for (n = 0; n < chip->dev_cfg->ngpios; ++n) { | ||
517 | irq = irq_base + n; | ||
518 | set_irq_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq); | ||
519 | set_irq_nested_thread(irq, 1); | ||
520 | #ifdef CONFIG_ARM | ||
521 | set_irq_flags(irq, IRQF_VALID); | ||
522 | #else | ||
523 | set_irq_noprobe(irq); | ||
524 | #endif | ||
525 | } | ||
526 | |||
527 | err = request_threaded_irq(irq_summary, | ||
528 | NULL, | ||
529 | sx150x_irq_thread_fn, | ||
530 | IRQF_SHARED | IRQF_TRIGGER_FALLING, | ||
531 | chip->irq_chip.name, | ||
532 | chip); | ||
533 | if (err < 0) { | ||
534 | chip->irq_summary = -1; | ||
535 | chip->irq_base = -1; | ||
536 | } | ||
537 | |||
538 | return err; | ||
539 | } | ||
540 | |||
541 | static void sx150x_remove_irq_chip(struct sx150x_chip *chip) | ||
542 | { | ||
543 | unsigned n; | ||
544 | unsigned irq; | ||
545 | |||
546 | free_irq(chip->irq_summary, chip); | ||
547 | |||
548 | for (n = 0; n < chip->dev_cfg->ngpios; ++n) { | ||
549 | irq = chip->irq_base + n; | ||
550 | set_irq_handler(irq, NULL); | ||
551 | set_irq_chip(irq, NULL); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | static int __devinit sx150x_probe(struct i2c_client *client, | ||
556 | const struct i2c_device_id *id) | ||
557 | { | ||
558 | static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA | | ||
559 | I2C_FUNC_SMBUS_WRITE_WORD_DATA; | ||
560 | struct sx150x_platform_data *pdata; | ||
561 | struct sx150x_chip *chip; | ||
562 | int rc; | ||
563 | |||
564 | pdata = client->dev.platform_data; | ||
565 | if (!pdata) | ||
566 | return -EINVAL; | ||
567 | |||
568 | if (!i2c_check_functionality(client->adapter, i2c_funcs)) | ||
569 | return -ENOSYS; | ||
570 | |||
571 | chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL); | ||
572 | if (!chip) | ||
573 | return -ENOMEM; | ||
574 | |||
575 | sx150x_init_chip(chip, client, id->driver_data, pdata); | ||
576 | rc = sx150x_init_hw(chip, pdata); | ||
577 | if (rc < 0) | ||
578 | goto probe_fail_pre_gpiochip_add; | ||
579 | |||
580 | rc = gpiochip_add(&chip->gpio_chip); | ||
581 | if (rc < 0) | ||
582 | goto probe_fail_pre_gpiochip_add; | ||
583 | |||
584 | if (pdata->irq_summary >= 0) { | ||
585 | rc = sx150x_install_irq_chip(chip, | ||
586 | pdata->irq_summary, | ||
587 | pdata->irq_base); | ||
588 | if (rc < 0) | ||
589 | goto probe_fail_post_gpiochip_add; | ||
590 | } | ||
591 | |||
592 | i2c_set_clientdata(client, chip); | ||
593 | |||
594 | return 0; | ||
595 | probe_fail_post_gpiochip_add: | ||
596 | WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0); | ||
597 | probe_fail_pre_gpiochip_add: | ||
598 | kfree(chip); | ||
599 | return rc; | ||
600 | } | ||
601 | |||
602 | static int __devexit sx150x_remove(struct i2c_client *client) | ||
603 | { | ||
604 | struct sx150x_chip *chip; | ||
605 | int rc; | ||
606 | |||
607 | chip = i2c_get_clientdata(client); | ||
608 | rc = gpiochip_remove(&chip->gpio_chip); | ||
609 | if (rc < 0) | ||
610 | return rc; | ||
611 | |||
612 | if (chip->irq_summary >= 0) | ||
613 | sx150x_remove_irq_chip(chip); | ||
614 | |||
615 | kfree(chip); | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static struct i2c_driver sx150x_driver = { | ||
621 | .driver = { | ||
622 | .name = "sx150x", | ||
623 | .owner = THIS_MODULE | ||
624 | }, | ||
625 | .probe = sx150x_probe, | ||
626 | .remove = __devexit_p(sx150x_remove), | ||
627 | .id_table = sx150x_id, | ||
628 | }; | ||
629 | |||
630 | static int __init sx150x_init(void) | ||
631 | { | ||
632 | return i2c_add_driver(&sx150x_driver); | ||
633 | } | ||
634 | subsys_initcall(sx150x_init); | ||
635 | |||
636 | static void __exit sx150x_exit(void) | ||
637 | { | ||
638 | return i2c_del_driver(&sx150x_driver); | ||
639 | } | ||
640 | module_exit(sx150x_exit); | ||
641 | |||
642 | MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>"); | ||
643 | MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders"); | ||
644 | MODULE_LICENSE("GPL v2"); | ||
645 | MODULE_ALIAS("i2c:sx150x"); | ||
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c index 1fa449a1a4cb..309644cf4d9b 100644 --- a/drivers/gpio/wm831x-gpio.c +++ b/drivers/gpio/wm831x-gpio.c | |||
@@ -108,6 +108,37 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; | 108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, | ||
112 | unsigned debounce) | ||
113 | { | ||
114 | struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); | ||
115 | struct wm831x *wm831x = wm831x_gpio->wm831x; | ||
116 | int reg = WM831X_GPIO1_CONTROL + offset; | ||
117 | int ret, fn; | ||
118 | |||
119 | ret = wm831x_reg_read(wm831x, reg); | ||
120 | if (ret < 0) | ||
121 | return ret; | ||
122 | |||
123 | switch (ret & WM831X_GPN_FN_MASK) { | ||
124 | case 0: | ||
125 | case 1: | ||
126 | break; | ||
127 | default: | ||
128 | /* Not in GPIO mode */ | ||
129 | return -EBUSY; | ||
130 | } | ||
131 | |||
132 | if (debounce >= 32 && debounce <= 64) | ||
133 | fn = 0; | ||
134 | else if (debounce >= 4000 && debounce <= 8000) | ||
135 | fn = 1; | ||
136 | else | ||
137 | return -EINVAL; | ||
138 | |||
139 | return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); | ||
140 | } | ||
141 | |||
111 | #ifdef CONFIG_DEBUG_FS | 142 | #ifdef CONFIG_DEBUG_FS |
112 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 143 | static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
113 | { | 144 | { |
@@ -208,6 +239,7 @@ static struct gpio_chip template_chip = { | |||
208 | .direction_output = wm831x_gpio_direction_out, | 239 | .direction_output = wm831x_gpio_direction_out, |
209 | .set = wm831x_gpio_set, | 240 | .set = wm831x_gpio_set, |
210 | .to_irq = wm831x_gpio_to_irq, | 241 | .to_irq = wm831x_gpio_to_irq, |
242 | .set_debounce = wm831x_gpio_set_debounce, | ||
211 | .dbg_show = wm831x_gpio_dbg_show, | 243 | .dbg_show = wm831x_gpio_dbg_show, |
212 | .can_sleep = 1, | 244 | .can_sleep = 1, |
213 | }; | 245 | }; |
diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c index 17be051b7aa3..1c3649242208 100644 --- a/drivers/gpu/drm/ati_pcigart.c +++ b/drivers/gpu/drm/ati_pcigart.c | |||
@@ -152,7 +152,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga | |||
152 | /* we need to support large memory configurations */ | 152 | /* we need to support large memory configurations */ |
153 | entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], | 153 | entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], |
154 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 154 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
155 | if (entry->busaddr[i] == 0) { | 155 | if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) { |
156 | DRM_ERROR("unable to map PCIGART pages!\n"); | 156 | DRM_ERROR("unable to map PCIGART pages!\n"); |
157 | drm_ati_pcigart_cleanup(dev, gart_info); | 157 | drm_ati_pcigart_cleanup(dev, gart_info); |
158 | address = NULL; | 158 | address = NULL; |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index a5c9ce93bbcb..3e257a50bf56 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
@@ -328,14 +328,13 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, | |||
328 | return -EINVAL; | 328 | return -EINVAL; |
329 | } | 329 | } |
330 | 330 | ||
331 | list = kmalloc(sizeof(*list), GFP_KERNEL); | 331 | list = kzalloc(sizeof(*list), GFP_KERNEL); |
332 | if (!list) { | 332 | if (!list) { |
333 | if (map->type == _DRM_REGISTERS) | 333 | if (map->type == _DRM_REGISTERS) |
334 | iounmap(map->handle); | 334 | iounmap(map->handle); |
335 | kfree(map); | 335 | kfree(map); |
336 | return -EINVAL; | 336 | return -EINVAL; |
337 | } | 337 | } |
338 | memset(list, 0, sizeof(*list)); | ||
339 | list->map = map; | 338 | list->map = map; |
340 | 339 | ||
341 | mutex_lock(&dev->struct_mutex); | 340 | mutex_lock(&dev->struct_mutex); |
@@ -678,13 +677,12 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
678 | return -EINVAL; | 677 | return -EINVAL; |
679 | } | 678 | } |
680 | 679 | ||
681 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL); | 680 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL); |
682 | if (!entry->buflist) { | 681 | if (!entry->buflist) { |
683 | mutex_unlock(&dev->struct_mutex); | 682 | mutex_unlock(&dev->struct_mutex); |
684 | atomic_dec(&dev->buf_alloc); | 683 | atomic_dec(&dev->buf_alloc); |
685 | return -ENOMEM; | 684 | return -ENOMEM; |
686 | } | 685 | } |
687 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
688 | 686 | ||
689 | entry->buf_size = size; | 687 | entry->buf_size = size; |
690 | entry->page_order = page_order; | 688 | entry->page_order = page_order; |
@@ -708,7 +706,7 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
708 | buf->file_priv = NULL; | 706 | buf->file_priv = NULL; |
709 | 707 | ||
710 | buf->dev_priv_size = dev->driver->dev_priv_size; | 708 | buf->dev_priv_size = dev->driver->dev_priv_size; |
711 | buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL); | 709 | buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); |
712 | if (!buf->dev_private) { | 710 | if (!buf->dev_private) { |
713 | /* Set count correctly so we free the proper amount. */ | 711 | /* Set count correctly so we free the proper amount. */ |
714 | entry->buf_count = count; | 712 | entry->buf_count = count; |
@@ -717,7 +715,6 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
717 | atomic_dec(&dev->buf_alloc); | 715 | atomic_dec(&dev->buf_alloc); |
718 | return -ENOMEM; | 716 | return -ENOMEM; |
719 | } | 717 | } |
720 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
721 | 718 | ||
722 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); | 719 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); |
723 | 720 | ||
@@ -832,22 +829,20 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
832 | return -EINVAL; | 829 | return -EINVAL; |
833 | } | 830 | } |
834 | 831 | ||
835 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL); | 832 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL); |
836 | if (!entry->buflist) { | 833 | if (!entry->buflist) { |
837 | mutex_unlock(&dev->struct_mutex); | 834 | mutex_unlock(&dev->struct_mutex); |
838 | atomic_dec(&dev->buf_alloc); | 835 | atomic_dec(&dev->buf_alloc); |
839 | return -ENOMEM; | 836 | return -ENOMEM; |
840 | } | 837 | } |
841 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
842 | 838 | ||
843 | entry->seglist = kmalloc(count * sizeof(*entry->seglist), GFP_KERNEL); | 839 | entry->seglist = kzalloc(count * sizeof(*entry->seglist), GFP_KERNEL); |
844 | if (!entry->seglist) { | 840 | if (!entry->seglist) { |
845 | kfree(entry->buflist); | 841 | kfree(entry->buflist); |
846 | mutex_unlock(&dev->struct_mutex); | 842 | mutex_unlock(&dev->struct_mutex); |
847 | atomic_dec(&dev->buf_alloc); | 843 | atomic_dec(&dev->buf_alloc); |
848 | return -ENOMEM; | 844 | return -ENOMEM; |
849 | } | 845 | } |
850 | memset(entry->seglist, 0, count * sizeof(*entry->seglist)); | ||
851 | 846 | ||
852 | /* Keep the original pagelist until we know all the allocations | 847 | /* Keep the original pagelist until we know all the allocations |
853 | * have succeeded | 848 | * have succeeded |
@@ -911,8 +906,8 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
911 | buf->file_priv = NULL; | 906 | buf->file_priv = NULL; |
912 | 907 | ||
913 | buf->dev_priv_size = dev->driver->dev_priv_size; | 908 | buf->dev_priv_size = dev->driver->dev_priv_size; |
914 | buf->dev_private = kmalloc(buf->dev_priv_size, | 909 | buf->dev_private = kzalloc(buf->dev_priv_size, |
915 | GFP_KERNEL); | 910 | GFP_KERNEL); |
916 | if (!buf->dev_private) { | 911 | if (!buf->dev_private) { |
917 | /* Set count correctly so we free the proper amount. */ | 912 | /* Set count correctly so we free the proper amount. */ |
918 | entry->buf_count = count; | 913 | entry->buf_count = count; |
@@ -923,7 +918,6 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
923 | atomic_dec(&dev->buf_alloc); | 918 | atomic_dec(&dev->buf_alloc); |
924 | return -ENOMEM; | 919 | return -ENOMEM; |
925 | } | 920 | } |
926 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
927 | 921 | ||
928 | DRM_DEBUG("buffer %d @ %p\n", | 922 | DRM_DEBUG("buffer %d @ %p\n", |
929 | entry->buf_count, buf->address); | 923 | entry->buf_count, buf->address); |
@@ -1048,14 +1042,13 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
1048 | return -EINVAL; | 1042 | return -EINVAL; |
1049 | } | 1043 | } |
1050 | 1044 | ||
1051 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), | 1045 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), |
1052 | GFP_KERNEL); | 1046 | GFP_KERNEL); |
1053 | if (!entry->buflist) { | 1047 | if (!entry->buflist) { |
1054 | mutex_unlock(&dev->struct_mutex); | 1048 | mutex_unlock(&dev->struct_mutex); |
1055 | atomic_dec(&dev->buf_alloc); | 1049 | atomic_dec(&dev->buf_alloc); |
1056 | return -ENOMEM; | 1050 | return -ENOMEM; |
1057 | } | 1051 | } |
1058 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
1059 | 1052 | ||
1060 | entry->buf_size = size; | 1053 | entry->buf_size = size; |
1061 | entry->page_order = page_order; | 1054 | entry->page_order = page_order; |
@@ -1080,7 +1073,7 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
1080 | buf->file_priv = NULL; | 1073 | buf->file_priv = NULL; |
1081 | 1074 | ||
1082 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1075 | buf->dev_priv_size = dev->driver->dev_priv_size; |
1083 | buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL); | 1076 | buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); |
1084 | if (!buf->dev_private) { | 1077 | if (!buf->dev_private) { |
1085 | /* Set count correctly so we free the proper amount. */ | 1078 | /* Set count correctly so we free the proper amount. */ |
1086 | entry->buf_count = count; | 1079 | entry->buf_count = count; |
@@ -1090,8 +1083,6 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
1090 | return -ENOMEM; | 1083 | return -ENOMEM; |
1091 | } | 1084 | } |
1092 | 1085 | ||
1093 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
1094 | |||
1095 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); | 1086 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); |
1096 | 1087 | ||
1097 | offset += alignment; | 1088 | offset += alignment; |
@@ -1209,14 +1200,13 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
1209 | return -EINVAL; | 1200 | return -EINVAL; |
1210 | } | 1201 | } |
1211 | 1202 | ||
1212 | entry->buflist = kmalloc(count * sizeof(*entry->buflist), | 1203 | entry->buflist = kzalloc(count * sizeof(*entry->buflist), |
1213 | GFP_KERNEL); | 1204 | GFP_KERNEL); |
1214 | if (!entry->buflist) { | 1205 | if (!entry->buflist) { |
1215 | mutex_unlock(&dev->struct_mutex); | 1206 | mutex_unlock(&dev->struct_mutex); |
1216 | atomic_dec(&dev->buf_alloc); | 1207 | atomic_dec(&dev->buf_alloc); |
1217 | return -ENOMEM; | 1208 | return -ENOMEM; |
1218 | } | 1209 | } |
1219 | memset(entry->buflist, 0, count * sizeof(*entry->buflist)); | ||
1220 | 1210 | ||
1221 | entry->buf_size = size; | 1211 | entry->buf_size = size; |
1222 | entry->page_order = page_order; | 1212 | entry->page_order = page_order; |
@@ -1240,7 +1230,7 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
1240 | buf->file_priv = NULL; | 1230 | buf->file_priv = NULL; |
1241 | 1231 | ||
1242 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1232 | buf->dev_priv_size = dev->driver->dev_priv_size; |
1243 | buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL); | 1233 | buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); |
1244 | if (!buf->dev_private) { | 1234 | if (!buf->dev_private) { |
1245 | /* Set count correctly so we free the proper amount. */ | 1235 | /* Set count correctly so we free the proper amount. */ |
1246 | entry->buf_count = count; | 1236 | entry->buf_count = count; |
@@ -1249,7 +1239,6 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
1249 | atomic_dec(&dev->buf_alloc); | 1239 | atomic_dec(&dev->buf_alloc); |
1250 | return -ENOMEM; | 1240 | return -ENOMEM; |
1251 | } | 1241 | } |
1252 | memset(buf->dev_private, 0, buf->dev_priv_size); | ||
1253 | 1242 | ||
1254 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); | 1243 | DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); |
1255 | 1244 | ||
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4c68f76993d8..37e0b4fa482a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -1682,9 +1682,9 @@ int drm_mode_addfb(struct drm_device *dev, | |||
1682 | /* TODO setup destructor callback */ | 1682 | /* TODO setup destructor callback */ |
1683 | 1683 | ||
1684 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); | 1684 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
1685 | if (!fb) { | 1685 | if (IS_ERR(fb)) { |
1686 | DRM_ERROR("could not create framebuffer\n"); | 1686 | DRM_ERROR("could not create framebuffer\n"); |
1687 | ret = -EINVAL; | 1687 | ret = PTR_ERR(fb); |
1688 | goto out; | 1688 | goto out; |
1689 | } | 1689 | } |
1690 | 1690 | ||
@@ -2541,7 +2541,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
2541 | goto out; | 2541 | goto out; |
2542 | } | 2542 | } |
2543 | 2543 | ||
2544 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); | 2544 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); |
2545 | 2545 | ||
2546 | out: | 2546 | out: |
2547 | mutex_unlock(&dev->mode_config.mutex); | 2547 | mutex_unlock(&dev->mode_config.mutex); |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index b9e4dbfa0533..7e31d4348340 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -817,12 +817,12 @@ int drm_helper_resume_force_mode(struct drm_device *dev) | |||
817 | if (encoder_funcs->dpms) | 817 | if (encoder_funcs->dpms) |
818 | (*encoder_funcs->dpms) (encoder, | 818 | (*encoder_funcs->dpms) (encoder, |
819 | drm_helper_choose_encoder_dpms(encoder)); | 819 | drm_helper_choose_encoder_dpms(encoder)); |
820 | |||
821 | crtc_funcs = crtc->helper_private; | ||
822 | if (crtc_funcs->dpms) | ||
823 | (*crtc_funcs->dpms) (crtc, | ||
824 | drm_helper_choose_crtc_dpms(crtc)); | ||
825 | } | 820 | } |
821 | |||
822 | crtc_funcs = crtc->helper_private; | ||
823 | if (crtc_funcs->dpms) | ||
824 | (*crtc_funcs->dpms) (crtc, | ||
825 | drm_helper_choose_crtc_dpms(crtc)); | ||
826 | } | 826 | } |
827 | } | 827 | } |
828 | /* disable the unused connectors while restoring the modesetting */ | 828 | /* disable the unused connectors while restoring the modesetting */ |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index dce5c4a97f8d..96e963108225 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -33,6 +33,11 @@ | |||
33 | #include <linux/i2c-algo-bit.h> | 33 | #include <linux/i2c-algo-bit.h> |
34 | #include "drmP.h" | 34 | #include "drmP.h" |
35 | #include "drm_edid.h" | 35 | #include "drm_edid.h" |
36 | #include "drm_edid_modes.h" | ||
37 | |||
38 | #define version_greater(edid, maj, min) \ | ||
39 | (((edid)->version > (maj)) || \ | ||
40 | ((edid)->version == (maj) && (edid)->revision > (min))) | ||
36 | 41 | ||
37 | #define EDID_EST_TIMINGS 16 | 42 | #define EDID_EST_TIMINGS 16 |
38 | #define EDID_STD_TIMINGS 8 | 43 | #define EDID_STD_TIMINGS 8 |
@@ -62,6 +67,13 @@ | |||
62 | /* use +hsync +vsync for detailed mode */ | 67 | /* use +hsync +vsync for detailed mode */ |
63 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) | 68 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
64 | 69 | ||
70 | struct detailed_mode_closure { | ||
71 | struct drm_connector *connector; | ||
72 | struct edid *edid; | ||
73 | bool preferred; | ||
74 | u32 quirks; | ||
75 | int modes; | ||
76 | }; | ||
65 | 77 | ||
66 | #define LEVEL_DMT 0 | 78 | #define LEVEL_DMT 0 |
67 | #define LEVEL_GTF 1 | 79 | #define LEVEL_GTF 1 |
@@ -375,7 +387,6 @@ static u32 edid_get_quirks(struct edid *edid) | |||
375 | #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) | 387 | #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) |
376 | #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) | 388 | #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) |
377 | 389 | ||
378 | |||
379 | /** | 390 | /** |
380 | * edid_fixup_preferred - set preferred modes based on quirk list | 391 | * edid_fixup_preferred - set preferred modes based on quirk list |
381 | * @connector: has mode list to fix up | 392 | * @connector: has mode list to fix up |
@@ -422,245 +433,6 @@ static void edid_fixup_preferred(struct drm_connector *connector, | |||
422 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; | 433 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; |
423 | } | 434 | } |
424 | 435 | ||
425 | /* | ||
426 | * Add the Autogenerated from the DMT spec. | ||
427 | * This table is copied from xfree86/modes/xf86EdidModes.c. | ||
428 | * But the mode with Reduced blank feature is deleted. | ||
429 | */ | ||
430 | static struct drm_display_mode drm_dmt_modes[] = { | ||
431 | /* 640x350@85Hz */ | ||
432 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
433 | 736, 832, 0, 350, 382, 385, 445, 0, | ||
434 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
435 | /* 640x400@85Hz */ | ||
436 | { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
437 | 736, 832, 0, 400, 401, 404, 445, 0, | ||
438 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
439 | /* 720x400@85Hz */ | ||
440 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756, | ||
441 | 828, 936, 0, 400, 401, 404, 446, 0, | ||
442 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
443 | /* 640x480@60Hz */ | ||
444 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | ||
445 | 752, 800, 0, 480, 489, 492, 525, 0, | ||
446 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
447 | /* 640x480@72Hz */ | ||
448 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
449 | 704, 832, 0, 480, 489, 492, 520, 0, | ||
450 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
451 | /* 640x480@75Hz */ | ||
452 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
453 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
454 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
455 | /* 640x480@85Hz */ | ||
456 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696, | ||
457 | 752, 832, 0, 480, 481, 484, 509, 0, | ||
458 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
459 | /* 800x600@56Hz */ | ||
460 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
461 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
462 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
463 | /* 800x600@60Hz */ | ||
464 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
465 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
466 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
467 | /* 800x600@72Hz */ | ||
468 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
469 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
470 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
471 | /* 800x600@75Hz */ | ||
472 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
473 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
474 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
475 | /* 800x600@85Hz */ | ||
476 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832, | ||
477 | 896, 1048, 0, 600, 601, 604, 631, 0, | ||
478 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
479 | /* 848x480@60Hz */ | ||
480 | { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864, | ||
481 | 976, 1088, 0, 480, 486, 494, 517, 0, | ||
482 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
483 | /* 1024x768@43Hz, interlace */ | ||
484 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032, | ||
485 | 1208, 1264, 0, 768, 768, 772, 817, 0, | ||
486 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | | ||
487 | DRM_MODE_FLAG_INTERLACE) }, | ||
488 | /* 1024x768@60Hz */ | ||
489 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
490 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
491 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
492 | /* 1024x768@70Hz */ | ||
493 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
494 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
495 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
496 | /* 1024x768@75Hz */ | ||
497 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040, | ||
498 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
499 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
500 | /* 1024x768@85Hz */ | ||
501 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072, | ||
502 | 1168, 1376, 0, 768, 769, 772, 808, 0, | ||
503 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
504 | /* 1152x864@75Hz */ | ||
505 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
506 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
507 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
508 | /* 1280x768@60Hz */ | ||
509 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, | ||
510 | 1472, 1664, 0, 768, 771, 778, 798, 0, | ||
511 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
512 | /* 1280x768@75Hz */ | ||
513 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360, | ||
514 | 1488, 1696, 0, 768, 771, 778, 805, 0, | ||
515 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
516 | /* 1280x768@85Hz */ | ||
517 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360, | ||
518 | 1496, 1712, 0, 768, 771, 778, 809, 0, | ||
519 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
520 | /* 1280x800@60Hz */ | ||
521 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, | ||
522 | 1480, 1680, 0, 800, 803, 809, 831, 0, | ||
523 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
524 | /* 1280x800@75Hz */ | ||
525 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360, | ||
526 | 1488, 1696, 0, 800, 803, 809, 838, 0, | ||
527 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
528 | /* 1280x800@85Hz */ | ||
529 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360, | ||
530 | 1496, 1712, 0, 800, 803, 809, 843, 0, | ||
531 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
532 | /* 1280x960@60Hz */ | ||
533 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, | ||
534 | 1488, 1800, 0, 960, 961, 964, 1000, 0, | ||
535 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
536 | /* 1280x960@85Hz */ | ||
537 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344, | ||
538 | 1504, 1728, 0, 960, 961, 964, 1011, 0, | ||
539 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
540 | /* 1280x1024@60Hz */ | ||
541 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, | ||
542 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
543 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
544 | /* 1280x1024@75Hz */ | ||
545 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
546 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
547 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
548 | /* 1280x1024@85Hz */ | ||
549 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344, | ||
550 | 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, | ||
551 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
552 | /* 1360x768@60Hz */ | ||
553 | { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, | ||
554 | 1536, 1792, 0, 768, 771, 777, 795, 0, | ||
555 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
556 | /* 1440x1050@60Hz */ | ||
557 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, | ||
558 | 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, | ||
559 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
560 | /* 1440x1050@75Hz */ | ||
561 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504, | ||
562 | 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, | ||
563 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
564 | /* 1440x1050@85Hz */ | ||
565 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504, | ||
566 | 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, | ||
567 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
568 | /* 1440x900@60Hz */ | ||
569 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, | ||
570 | 1672, 1904, 0, 900, 903, 909, 934, 0, | ||
571 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
572 | /* 1440x900@75Hz */ | ||
573 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536, | ||
574 | 1688, 1936, 0, 900, 903, 909, 942, 0, | ||
575 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
576 | /* 1440x900@85Hz */ | ||
577 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544, | ||
578 | 1696, 1952, 0, 900, 903, 909, 948, 0, | ||
579 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
580 | /* 1600x1200@60Hz */ | ||
581 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, | ||
582 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
583 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
584 | /* 1600x1200@65Hz */ | ||
585 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664, | ||
586 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
587 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
588 | /* 1600x1200@70Hz */ | ||
589 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664, | ||
590 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
591 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
592 | /* 1600x1200@75Hz */ | ||
593 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 202500, 1600, 1664, | ||
594 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
595 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
596 | /* 1600x1200@85Hz */ | ||
597 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664, | ||
598 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
599 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
600 | /* 1680x1050@60Hz */ | ||
601 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, | ||
602 | 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, | ||
603 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
604 | /* 1680x1050@75Hz */ | ||
605 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800, | ||
606 | 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, | ||
607 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
608 | /* 1680x1050@85Hz */ | ||
609 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808, | ||
610 | 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, | ||
611 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
612 | /* 1792x1344@60Hz */ | ||
613 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, | ||
614 | 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, | ||
615 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
616 | /* 1729x1344@75Hz */ | ||
617 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888, | ||
618 | 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, | ||
619 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
620 | /* 1853x1392@60Hz */ | ||
621 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, | ||
622 | 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, | ||
623 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
624 | /* 1856x1392@75Hz */ | ||
625 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984, | ||
626 | 2208, 2560, 0, 1392, 1395, 1399, 1500, 0, | ||
627 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
628 | /* 1920x1200@60Hz */ | ||
629 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, | ||
630 | 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, | ||
631 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
632 | /* 1920x1200@75Hz */ | ||
633 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056, | ||
634 | 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, | ||
635 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
636 | /* 1920x1200@85Hz */ | ||
637 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064, | ||
638 | 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, | ||
639 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
640 | /* 1920x1440@60Hz */ | ||
641 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, | ||
642 | 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, | ||
643 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
644 | /* 1920x1440@75Hz */ | ||
645 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064, | ||
646 | 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, | ||
647 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
648 | /* 2560x1600@60Hz */ | ||
649 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, | ||
650 | 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, | ||
651 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
652 | /* 2560x1600@75HZ */ | ||
653 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768, | ||
654 | 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, | ||
655 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
656 | /* 2560x1600@85HZ */ | ||
657 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, | ||
658 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, | ||
659 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
660 | }; | ||
661 | static const int drm_num_dmt_modes = | ||
662 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | ||
663 | |||
664 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, | 436 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
665 | int hsize, int vsize, int fresh) | 437 | int hsize, int vsize, int fresh) |
666 | { | 438 | { |
@@ -685,6 +457,46 @@ EXPORT_SYMBOL(drm_mode_find_dmt); | |||
685 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); | 457 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); |
686 | 458 | ||
687 | static void | 459 | static void |
460 | cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) | ||
461 | { | ||
462 | int i, n = 0; | ||
463 | u8 rev = ext[0x01], d = ext[0x02]; | ||
464 | u8 *det_base = ext + d; | ||
465 | |||
466 | switch (rev) { | ||
467 | case 0: | ||
468 | /* can't happen */ | ||
469 | return; | ||
470 | case 1: | ||
471 | /* have to infer how many blocks we have, check pixel clock */ | ||
472 | for (i = 0; i < 6; i++) | ||
473 | if (det_base[18*i] || det_base[18*i+1]) | ||
474 | n++; | ||
475 | break; | ||
476 | default: | ||
477 | /* explicit count */ | ||
478 | n = min(ext[0x03] & 0x0f, 6); | ||
479 | break; | ||
480 | } | ||
481 | |||
482 | for (i = 0; i < n; i++) | ||
483 | cb((struct detailed_timing *)(det_base + 18 * i), closure); | ||
484 | } | ||
485 | |||
486 | static void | ||
487 | vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) | ||
488 | { | ||
489 | unsigned int i, n = min((int)ext[0x02], 6); | ||
490 | u8 *det_base = ext + 5; | ||
491 | |||
492 | if (ext[0x01] != 1) | ||
493 | return; /* unknown version */ | ||
494 | |||
495 | for (i = 0; i < n; i++) | ||
496 | cb((struct detailed_timing *)(det_base + 18 * i), closure); | ||
497 | } | ||
498 | |||
499 | static void | ||
688 | drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) | 500 | drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) |
689 | { | 501 | { |
690 | int i; | 502 | int i; |
@@ -696,7 +508,19 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) | |||
696 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) | 508 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) |
697 | cb(&(edid->detailed_timings[i]), closure); | 509 | cb(&(edid->detailed_timings[i]), closure); |
698 | 510 | ||
699 | /* XXX extension block walk */ | 511 | for (i = 1; i <= raw_edid[0x7e]; i++) { |
512 | u8 *ext = raw_edid + (i * EDID_LENGTH); | ||
513 | switch (*ext) { | ||
514 | case CEA_EXT: | ||
515 | cea_for_each_detailed_block(ext, cb, closure); | ||
516 | break; | ||
517 | case VTB_EXT: | ||
518 | vtb_for_each_detailed_block(ext, cb, closure); | ||
519 | break; | ||
520 | default: | ||
521 | break; | ||
522 | } | ||
523 | } | ||
700 | } | 524 | } |
701 | 525 | ||
702 | static void | 526 | static void |
@@ -1047,117 +871,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
1047 | return mode; | 871 | return mode; |
1048 | } | 872 | } |
1049 | 873 | ||
1050 | /* | ||
1051 | * Detailed mode info for the EDID "established modes" data to use. | ||
1052 | */ | ||
1053 | static struct drm_display_mode edid_est_modes[] = { | ||
1054 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
1055 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
1056 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ | ||
1057 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
1058 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
1059 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ | ||
1060 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
1061 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
1062 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ | ||
1063 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
1064 | 704, 832, 0, 480, 489, 491, 520, 0, | ||
1065 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ | ||
1066 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, | ||
1067 | 768, 864, 0, 480, 483, 486, 525, 0, | ||
1068 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ | ||
1069 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, | ||
1070 | 752, 800, 0, 480, 490, 492, 525, 0, | ||
1071 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ | ||
1072 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, | ||
1073 | 846, 900, 0, 400, 421, 423, 449, 0, | ||
1074 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ | ||
1075 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, | ||
1076 | 846, 900, 0, 400, 412, 414, 449, 0, | ||
1077 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ | ||
1078 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
1079 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
1080 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ | ||
1081 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, | ||
1082 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
1083 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ | ||
1084 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
1085 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
1086 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ | ||
1087 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
1088 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
1089 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ | ||
1090 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, | ||
1091 | 1208, 1264, 0, 768, 768, 776, 817, 0, | ||
1092 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ | ||
1093 | { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, | ||
1094 | 928, 1152, 0, 624, 625, 628, 667, 0, | ||
1095 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ | ||
1096 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
1097 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
1098 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ | ||
1099 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
1100 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
1101 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ | ||
1102 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
1103 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
1104 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ | ||
1105 | }; | ||
1106 | |||
1107 | /** | ||
1108 | * add_established_modes - get est. modes from EDID and add them | ||
1109 | * @edid: EDID block to scan | ||
1110 | * | ||
1111 | * Each EDID block contains a bitmap of the supported "established modes" list | ||
1112 | * (defined above). Tease them out and add them to the global modes list. | ||
1113 | */ | ||
1114 | static int add_established_modes(struct drm_connector *connector, struct edid *edid) | ||
1115 | { | ||
1116 | struct drm_device *dev = connector->dev; | ||
1117 | unsigned long est_bits = edid->established_timings.t1 | | ||
1118 | (edid->established_timings.t2 << 8) | | ||
1119 | ((edid->established_timings.mfg_rsvd & 0x80) << 9); | ||
1120 | int i, modes = 0; | ||
1121 | |||
1122 | for (i = 0; i <= EDID_EST_TIMINGS; i++) | ||
1123 | if (est_bits & (1<<i)) { | ||
1124 | struct drm_display_mode *newmode; | ||
1125 | newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); | ||
1126 | if (newmode) { | ||
1127 | drm_mode_probed_add(connector, newmode); | ||
1128 | modes++; | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1132 | return modes; | ||
1133 | } | ||
1134 | |||
1135 | /** | ||
1136 | * add_standard_modes - get std. modes from EDID and add them | ||
1137 | * @edid: EDID block to scan | ||
1138 | * | ||
1139 | * Standard modes can be calculated using the CVT standard. Grab them from | ||
1140 | * @edid, calculate them, and add them to the list. | ||
1141 | */ | ||
1142 | static int add_standard_modes(struct drm_connector *connector, struct edid *edid) | ||
1143 | { | ||
1144 | int i, modes = 0; | ||
1145 | |||
1146 | for (i = 0; i < EDID_STD_TIMINGS; i++) { | ||
1147 | struct drm_display_mode *newmode; | ||
1148 | |||
1149 | newmode = drm_mode_std(connector, edid, | ||
1150 | &edid->standard_timings[i], | ||
1151 | edid->revision); | ||
1152 | if (newmode) { | ||
1153 | drm_mode_probed_add(connector, newmode); | ||
1154 | modes++; | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | return modes; | ||
1159 | } | ||
1160 | |||
1161 | static bool | 874 | static bool |
1162 | mode_is_rb(struct drm_display_mode *mode) | 875 | mode_is_rb(struct drm_display_mode *mode) |
1163 | { | 876 | { |
@@ -1267,113 +980,33 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, | |||
1267 | return modes; | 980 | return modes; |
1268 | } | 981 | } |
1269 | 982 | ||
1270 | static int drm_cvt_modes(struct drm_connector *connector, | 983 | static void |
1271 | struct detailed_timing *timing) | 984 | do_inferred_modes(struct detailed_timing *timing, void *c) |
1272 | { | 985 | { |
1273 | int i, j, modes = 0; | 986 | struct detailed_mode_closure *closure = c; |
1274 | struct drm_display_mode *newmode; | 987 | struct detailed_non_pixel *data = &timing->data.other_data; |
1275 | struct drm_device *dev = connector->dev; | 988 | int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); |
1276 | struct cvt_timing *cvt; | ||
1277 | const int rates[] = { 60, 85, 75, 60, 50 }; | ||
1278 | const u8 empty[3] = { 0, 0, 0 }; | ||
1279 | |||
1280 | for (i = 0; i < 4; i++) { | ||
1281 | int uninitialized_var(width), height; | ||
1282 | cvt = &(timing->data.other_data.data.cvt[i]); | ||
1283 | 989 | ||
1284 | if (!memcmp(cvt->code, empty, 3)) | 990 | if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE) |
1285 | continue; | 991 | closure->modes += drm_gtf_modes_for_range(closure->connector, |
992 | closure->edid, | ||
993 | timing); | ||
994 | } | ||
1286 | 995 | ||
1287 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; | 996 | static int |
1288 | switch (cvt->code[1] & 0x0c) { | 997 | add_inferred_modes(struct drm_connector *connector, struct edid *edid) |
1289 | case 0x00: | 998 | { |
1290 | width = height * 4 / 3; | 999 | struct detailed_mode_closure closure = { |
1291 | break; | 1000 | connector, edid, 0, 0, 0 |
1292 | case 0x04: | 1001 | }; |
1293 | width = height * 16 / 9; | ||
1294 | break; | ||
1295 | case 0x08: | ||
1296 | width = height * 16 / 10; | ||
1297 | break; | ||
1298 | case 0x0c: | ||
1299 | width = height * 15 / 9; | ||
1300 | break; | ||
1301 | } | ||
1302 | 1002 | ||
1303 | for (j = 1; j < 5; j++) { | 1003 | if (version_greater(edid, 1, 0)) |
1304 | if (cvt->code[2] & (1 << j)) { | 1004 | drm_for_each_detailed_block((u8 *)edid, do_inferred_modes, |
1305 | newmode = drm_cvt_mode(dev, width, height, | 1005 | &closure); |
1306 | rates[j], j == 0, | ||
1307 | false, false); | ||
1308 | if (newmode) { | ||
1309 | drm_mode_probed_add(connector, newmode); | ||
1310 | modes++; | ||
1311 | } | ||
1312 | } | ||
1313 | } | ||
1314 | } | ||
1315 | 1006 | ||
1316 | return modes; | 1007 | return closure.modes; |
1317 | } | 1008 | } |
1318 | 1009 | ||
1319 | static const struct { | ||
1320 | short w; | ||
1321 | short h; | ||
1322 | short r; | ||
1323 | short rb; | ||
1324 | } est3_modes[] = { | ||
1325 | /* byte 6 */ | ||
1326 | { 640, 350, 85, 0 }, | ||
1327 | { 640, 400, 85, 0 }, | ||
1328 | { 720, 400, 85, 0 }, | ||
1329 | { 640, 480, 85, 0 }, | ||
1330 | { 848, 480, 60, 0 }, | ||
1331 | { 800, 600, 85, 0 }, | ||
1332 | { 1024, 768, 85, 0 }, | ||
1333 | { 1152, 864, 75, 0 }, | ||
1334 | /* byte 7 */ | ||
1335 | { 1280, 768, 60, 1 }, | ||
1336 | { 1280, 768, 60, 0 }, | ||
1337 | { 1280, 768, 75, 0 }, | ||
1338 | { 1280, 768, 85, 0 }, | ||
1339 | { 1280, 960, 60, 0 }, | ||
1340 | { 1280, 960, 85, 0 }, | ||
1341 | { 1280, 1024, 60, 0 }, | ||
1342 | { 1280, 1024, 85, 0 }, | ||
1343 | /* byte 8 */ | ||
1344 | { 1360, 768, 60, 0 }, | ||
1345 | { 1440, 900, 60, 1 }, | ||
1346 | { 1440, 900, 60, 0 }, | ||
1347 | { 1440, 900, 75, 0 }, | ||
1348 | { 1440, 900, 85, 0 }, | ||
1349 | { 1400, 1050, 60, 1 }, | ||
1350 | { 1400, 1050, 60, 0 }, | ||
1351 | { 1400, 1050, 75, 0 }, | ||
1352 | /* byte 9 */ | ||
1353 | { 1400, 1050, 85, 0 }, | ||
1354 | { 1680, 1050, 60, 1 }, | ||
1355 | { 1680, 1050, 60, 0 }, | ||
1356 | { 1680, 1050, 75, 0 }, | ||
1357 | { 1680, 1050, 85, 0 }, | ||
1358 | { 1600, 1200, 60, 0 }, | ||
1359 | { 1600, 1200, 65, 0 }, | ||
1360 | { 1600, 1200, 70, 0 }, | ||
1361 | /* byte 10 */ | ||
1362 | { 1600, 1200, 75, 0 }, | ||
1363 | { 1600, 1200, 85, 0 }, | ||
1364 | { 1792, 1344, 60, 0 }, | ||
1365 | { 1792, 1344, 85, 0 }, | ||
1366 | { 1856, 1392, 60, 0 }, | ||
1367 | { 1856, 1392, 75, 0 }, | ||
1368 | { 1920, 1200, 60, 1 }, | ||
1369 | { 1920, 1200, 60, 0 }, | ||
1370 | /* byte 11 */ | ||
1371 | { 1920, 1200, 75, 0 }, | ||
1372 | { 1920, 1200, 85, 0 }, | ||
1373 | { 1920, 1440, 60, 0 }, | ||
1374 | { 1920, 1440, 75, 0 }, | ||
1375 | }; | ||
1376 | |||
1377 | static int | 1010 | static int |
1378 | drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) | 1011 | drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) |
1379 | { | 1012 | { |
@@ -1403,37 +1036,63 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) | |||
1403 | return modes; | 1036 | return modes; |
1404 | } | 1037 | } |
1405 | 1038 | ||
1406 | static int add_detailed_modes(struct drm_connector *connector, | 1039 | static void |
1407 | struct detailed_timing *timing, | 1040 | do_established_modes(struct detailed_timing *timing, void *c) |
1408 | struct edid *edid, u32 quirks, int preferred) | ||
1409 | { | 1041 | { |
1410 | int i, modes = 0; | 1042 | struct detailed_mode_closure *closure = c; |
1411 | struct detailed_non_pixel *data = &timing->data.other_data; | 1043 | struct detailed_non_pixel *data = &timing->data.other_data; |
1412 | int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); | ||
1413 | struct drm_display_mode *newmode; | ||
1414 | struct drm_device *dev = connector->dev; | ||
1415 | 1044 | ||
1416 | if (timing->pixel_clock) { | 1045 | if (data->type == EDID_DETAIL_EST_TIMINGS) |
1417 | newmode = drm_mode_detailed(dev, edid, timing, quirks); | 1046 | closure->modes += drm_est3_modes(closure->connector, timing); |
1418 | if (!newmode) | 1047 | } |
1419 | return 0; | ||
1420 | 1048 | ||
1421 | if (preferred) | 1049 | /** |
1422 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | 1050 | * add_established_modes - get est. modes from EDID and add them |
1051 | * @edid: EDID block to scan | ||
1052 | * | ||
1053 | * Each EDID block contains a bitmap of the supported "established modes" list | ||
1054 | * (defined above). Tease them out and add them to the global modes list. | ||
1055 | */ | ||
1056 | static int | ||
1057 | add_established_modes(struct drm_connector *connector, struct edid *edid) | ||
1058 | { | ||
1059 | struct drm_device *dev = connector->dev; | ||
1060 | unsigned long est_bits = edid->established_timings.t1 | | ||
1061 | (edid->established_timings.t2 << 8) | | ||
1062 | ((edid->established_timings.mfg_rsvd & 0x80) << 9); | ||
1063 | int i, modes = 0; | ||
1064 | struct detailed_mode_closure closure = { | ||
1065 | connector, edid, 0, 0, 0 | ||
1066 | }; | ||
1423 | 1067 | ||
1424 | drm_mode_probed_add(connector, newmode); | 1068 | for (i = 0; i <= EDID_EST_TIMINGS; i++) { |
1425 | return 1; | 1069 | if (est_bits & (1<<i)) { |
1070 | struct drm_display_mode *newmode; | ||
1071 | newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); | ||
1072 | if (newmode) { | ||
1073 | drm_mode_probed_add(connector, newmode); | ||
1074 | modes++; | ||
1075 | } | ||
1076 | } | ||
1426 | } | 1077 | } |
1427 | 1078 | ||
1428 | /* other timing types */ | 1079 | if (version_greater(edid, 1, 0)) |
1429 | switch (data->type) { | 1080 | drm_for_each_detailed_block((u8 *)edid, |
1430 | case EDID_DETAIL_MONITOR_RANGE: | 1081 | do_established_modes, &closure); |
1431 | if (gtf) | 1082 | |
1432 | modes += drm_gtf_modes_for_range(connector, edid, | 1083 | return modes + closure.modes; |
1433 | timing); | 1084 | } |
1434 | break; | 1085 | |
1435 | case EDID_DETAIL_STD_MODES: | 1086 | static void |
1436 | /* Six modes per detailed section */ | 1087 | do_standard_modes(struct detailed_timing *timing, void *c) |
1088 | { | ||
1089 | struct detailed_mode_closure *closure = c; | ||
1090 | struct detailed_non_pixel *data = &timing->data.other_data; | ||
1091 | struct drm_connector *connector = closure->connector; | ||
1092 | struct edid *edid = closure->edid; | ||
1093 | |||
1094 | if (data->type == EDID_DETAIL_STD_MODES) { | ||
1095 | int i; | ||
1437 | for (i = 0; i < 6; i++) { | 1096 | for (i = 0; i < 6; i++) { |
1438 | struct std_timing *std; | 1097 | struct std_timing *std; |
1439 | struct drm_display_mode *newmode; | 1098 | struct drm_display_mode *newmode; |
@@ -1443,108 +1102,169 @@ static int add_detailed_modes(struct drm_connector *connector, | |||
1443 | edid->revision); | 1102 | edid->revision); |
1444 | if (newmode) { | 1103 | if (newmode) { |
1445 | drm_mode_probed_add(connector, newmode); | 1104 | drm_mode_probed_add(connector, newmode); |
1446 | modes++; | 1105 | closure->modes++; |
1447 | } | 1106 | } |
1448 | } | 1107 | } |
1449 | break; | ||
1450 | case EDID_DETAIL_CVT_3BYTE: | ||
1451 | modes += drm_cvt_modes(connector, timing); | ||
1452 | break; | ||
1453 | case EDID_DETAIL_EST_TIMINGS: | ||
1454 | modes += drm_est3_modes(connector, timing); | ||
1455 | break; | ||
1456 | default: | ||
1457 | break; | ||
1458 | } | 1108 | } |
1459 | |||
1460 | return modes; | ||
1461 | } | 1109 | } |
1462 | 1110 | ||
1463 | /** | 1111 | /** |
1464 | * add_detailed_info - get detailed mode info from EDID data | 1112 | * add_standard_modes - get std. modes from EDID and add them |
1465 | * @connector: attached connector | ||
1466 | * @edid: EDID block to scan | 1113 | * @edid: EDID block to scan |
1467 | * @quirks: quirks to apply | ||
1468 | * | 1114 | * |
1469 | * Some of the detailed timing sections may contain mode information. Grab | 1115 | * Standard modes can be calculated using the appropriate standard (DMT, |
1470 | * it and add it to the list. | 1116 | * GTF or CVT. Grab them from @edid and add them to the list. |
1471 | */ | 1117 | */ |
1472 | static int add_detailed_info(struct drm_connector *connector, | 1118 | static int |
1473 | struct edid *edid, u32 quirks) | 1119 | add_standard_modes(struct drm_connector *connector, struct edid *edid) |
1474 | { | 1120 | { |
1475 | int i, modes = 0; | 1121 | int i, modes = 0; |
1122 | struct detailed_mode_closure closure = { | ||
1123 | connector, edid, 0, 0, 0 | ||
1124 | }; | ||
1125 | |||
1126 | for (i = 0; i < EDID_STD_TIMINGS; i++) { | ||
1127 | struct drm_display_mode *newmode; | ||
1128 | |||
1129 | newmode = drm_mode_std(connector, edid, | ||
1130 | &edid->standard_timings[i], | ||
1131 | edid->revision); | ||
1132 | if (newmode) { | ||
1133 | drm_mode_probed_add(connector, newmode); | ||
1134 | modes++; | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | if (version_greater(edid, 1, 0)) | ||
1139 | drm_for_each_detailed_block((u8 *)edid, do_standard_modes, | ||
1140 | &closure); | ||
1141 | |||
1142 | /* XXX should also look for standard codes in VTB blocks */ | ||
1143 | |||
1144 | return modes + closure.modes; | ||
1145 | } | ||
1476 | 1146 | ||
1477 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { | 1147 | static int drm_cvt_modes(struct drm_connector *connector, |
1478 | struct detailed_timing *timing = &edid->detailed_timings[i]; | 1148 | struct detailed_timing *timing) |
1479 | int preferred = (i == 0); | 1149 | { |
1150 | int i, j, modes = 0; | ||
1151 | struct drm_display_mode *newmode; | ||
1152 | struct drm_device *dev = connector->dev; | ||
1153 | struct cvt_timing *cvt; | ||
1154 | const int rates[] = { 60, 85, 75, 60, 50 }; | ||
1155 | const u8 empty[3] = { 0, 0, 0 }; | ||
1480 | 1156 | ||
1481 | if (preferred && edid->version == 1 && edid->revision < 4) | 1157 | for (i = 0; i < 4; i++) { |
1482 | preferred = (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); | 1158 | int uninitialized_var(width), height; |
1159 | cvt = &(timing->data.other_data.data.cvt[i]); | ||
1483 | 1160 | ||
1484 | /* In 1.0, only timings are allowed */ | 1161 | if (!memcmp(cvt->code, empty, 3)) |
1485 | if (!timing->pixel_clock && edid->version == 1 && | ||
1486 | edid->revision == 0) | ||
1487 | continue; | 1162 | continue; |
1488 | 1163 | ||
1489 | modes += add_detailed_modes(connector, timing, edid, quirks, | 1164 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; |
1490 | preferred); | 1165 | switch (cvt->code[1] & 0x0c) { |
1166 | case 0x00: | ||
1167 | width = height * 4 / 3; | ||
1168 | break; | ||
1169 | case 0x04: | ||
1170 | width = height * 16 / 9; | ||
1171 | break; | ||
1172 | case 0x08: | ||
1173 | width = height * 16 / 10; | ||
1174 | break; | ||
1175 | case 0x0c: | ||
1176 | width = height * 15 / 9; | ||
1177 | break; | ||
1178 | } | ||
1179 | |||
1180 | for (j = 1; j < 5; j++) { | ||
1181 | if (cvt->code[2] & (1 << j)) { | ||
1182 | newmode = drm_cvt_mode(dev, width, height, | ||
1183 | rates[j], j == 0, | ||
1184 | false, false); | ||
1185 | if (newmode) { | ||
1186 | drm_mode_probed_add(connector, newmode); | ||
1187 | modes++; | ||
1188 | } | ||
1189 | } | ||
1190 | } | ||
1491 | } | 1191 | } |
1492 | 1192 | ||
1493 | return modes; | 1193 | return modes; |
1494 | } | 1194 | } |
1495 | 1195 | ||
1496 | /** | 1196 | static void |
1497 | * add_detailed_mode_eedid - get detailed mode info from addtional timing | 1197 | do_cvt_mode(struct detailed_timing *timing, void *c) |
1498 | * EDID block | ||
1499 | * @connector: attached connector | ||
1500 | * @edid: EDID block to scan(It is only to get addtional timing EDID block) | ||
1501 | * @quirks: quirks to apply | ||
1502 | * | ||
1503 | * Some of the detailed timing sections may contain mode information. Grab | ||
1504 | * it and add it to the list. | ||
1505 | */ | ||
1506 | static int add_detailed_info_eedid(struct drm_connector *connector, | ||
1507 | struct edid *edid, u32 quirks) | ||
1508 | { | 1198 | { |
1509 | int i, modes = 0; | 1199 | struct detailed_mode_closure *closure = c; |
1510 | char *edid_ext = NULL; | 1200 | struct detailed_non_pixel *data = &timing->data.other_data; |
1511 | struct detailed_timing *timing; | ||
1512 | int start_offset, end_offset; | ||
1513 | 1201 | ||
1514 | if (edid->version == 1 && edid->revision < 3) | 1202 | if (data->type == EDID_DETAIL_CVT_3BYTE) |
1515 | return 0; | 1203 | closure->modes += drm_cvt_modes(closure->connector, timing); |
1516 | if (!edid->extensions) | 1204 | } |
1517 | return 0; | ||
1518 | 1205 | ||
1519 | /* Find CEA extension */ | 1206 | static int |
1520 | for (i = 0; i < edid->extensions; i++) { | 1207 | add_cvt_modes(struct drm_connector *connector, struct edid *edid) |
1521 | edid_ext = (char *)edid + EDID_LENGTH * (i + 1); | 1208 | { |
1522 | if (edid_ext[0] == 0x02) | 1209 | struct detailed_mode_closure closure = { |
1523 | break; | 1210 | connector, edid, 0, 0, 0 |
1524 | } | 1211 | }; |
1525 | 1212 | ||
1526 | if (i == edid->extensions) | 1213 | if (version_greater(edid, 1, 2)) |
1527 | return 0; | 1214 | drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure); |
1528 | 1215 | ||
1529 | /* Get the start offset of detailed timing block */ | 1216 | /* XXX should also look for CVT codes in VTB blocks */ |
1530 | start_offset = edid_ext[2]; | ||
1531 | if (start_offset == 0) { | ||
1532 | /* If the start_offset is zero, it means that neither detailed | ||
1533 | * info nor data block exist. In such case it is also | ||
1534 | * unnecessary to parse the detailed timing info. | ||
1535 | */ | ||
1536 | return 0; | ||
1537 | } | ||
1538 | 1217 | ||
1539 | end_offset = EDID_LENGTH; | 1218 | return closure.modes; |
1540 | end_offset -= sizeof(struct detailed_timing); | 1219 | } |
1541 | for (i = start_offset; i < end_offset; | 1220 | |
1542 | i += sizeof(struct detailed_timing)) { | 1221 | static void |
1543 | timing = (struct detailed_timing *)(edid_ext + i); | 1222 | do_detailed_mode(struct detailed_timing *timing, void *c) |
1544 | modes += add_detailed_modes(connector, timing, edid, quirks, 0); | 1223 | { |
1224 | struct detailed_mode_closure *closure = c; | ||
1225 | struct drm_display_mode *newmode; | ||
1226 | |||
1227 | if (timing->pixel_clock) { | ||
1228 | newmode = drm_mode_detailed(closure->connector->dev, | ||
1229 | closure->edid, timing, | ||
1230 | closure->quirks); | ||
1231 | if (!newmode) | ||
1232 | return; | ||
1233 | |||
1234 | if (closure->preferred) | ||
1235 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | ||
1236 | |||
1237 | drm_mode_probed_add(closure->connector, newmode); | ||
1238 | closure->modes++; | ||
1239 | closure->preferred = 0; | ||
1545 | } | 1240 | } |
1241 | } | ||
1546 | 1242 | ||
1547 | return modes; | 1243 | /* |
1244 | * add_detailed_modes - Add modes from detailed timings | ||
1245 | * @connector: attached connector | ||
1246 | * @edid: EDID block to scan | ||
1247 | * @quirks: quirks to apply | ||
1248 | */ | ||
1249 | static int | ||
1250 | add_detailed_modes(struct drm_connector *connector, struct edid *edid, | ||
1251 | u32 quirks) | ||
1252 | { | ||
1253 | struct detailed_mode_closure closure = { | ||
1254 | connector, | ||
1255 | edid, | ||
1256 | 1, | ||
1257 | quirks, | ||
1258 | 0 | ||
1259 | }; | ||
1260 | |||
1261 | if (closure.preferred && !version_greater(edid, 1, 3)) | ||
1262 | closure.preferred = | ||
1263 | (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); | ||
1264 | |||
1265 | drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure); | ||
1266 | |||
1267 | return closure.modes; | ||
1548 | } | 1268 | } |
1549 | 1269 | ||
1550 | #define HDMI_IDENTIFIER 0x000C03 | 1270 | #define HDMI_IDENTIFIER 0x000C03 |
@@ -1640,35 +1360,21 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) | |||
1640 | * - established timing codes | 1360 | * - established timing codes |
1641 | * - modes inferred from GTF or CVT range information | 1361 | * - modes inferred from GTF or CVT range information |
1642 | * | 1362 | * |
1643 | * We don't quite implement this yet, but we're close. | 1363 | * We get this pretty much right. |
1644 | * | 1364 | * |
1645 | * XXX order for additional mode types in extension blocks? | 1365 | * XXX order for additional mode types in extension blocks? |
1646 | */ | 1366 | */ |
1647 | num_modes += add_detailed_info(connector, edid, quirks); | 1367 | num_modes += add_detailed_modes(connector, edid, quirks); |
1648 | num_modes += add_detailed_info_eedid(connector, edid, quirks); | 1368 | num_modes += add_cvt_modes(connector, edid); |
1649 | num_modes += add_standard_modes(connector, edid); | 1369 | num_modes += add_standard_modes(connector, edid); |
1650 | num_modes += add_established_modes(connector, edid); | 1370 | num_modes += add_established_modes(connector, edid); |
1371 | num_modes += add_inferred_modes(connector, edid); | ||
1651 | 1372 | ||
1652 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) | 1373 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
1653 | edid_fixup_preferred(connector, quirks); | 1374 | edid_fixup_preferred(connector, quirks); |
1654 | 1375 | ||
1655 | connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0; | ||
1656 | connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0; | ||
1657 | connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0; | ||
1658 | connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0; | ||
1659 | connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0; | ||
1660 | connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5; | ||
1661 | connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0; | ||
1662 | connector->display_info.width_mm = edid->width_cm * 10; | 1376 | connector->display_info.width_mm = edid->width_cm * 10; |
1663 | connector->display_info.height_mm = edid->height_cm * 10; | 1377 | connector->display_info.height_mm = edid->height_cm * 10; |
1664 | connector->display_info.gamma = edid->gamma; | ||
1665 | connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0; | ||
1666 | connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0; | ||
1667 | connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3; | ||
1668 | connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0; | ||
1669 | connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0; | ||
1670 | connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0; | ||
1671 | connector->display_info.gamma = edid->gamma; | ||
1672 | 1378 | ||
1673 | return num_modes; | 1379 | return num_modes; |
1674 | } | 1380 | } |
diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h new file mode 100644 index 000000000000..6eb7592e152f --- /dev/null +++ b/drivers/gpu/drm/drm_edid_modes.h | |||
@@ -0,0 +1,380 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007-2008 Intel Corporation | ||
3 | * Jesse Barnes <jesse.barnes@intel.com> | ||
4 | * Copyright 2010 Red Hat, Inc. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the | ||
14 | * next paragraph) shall be included in all copies or substantial portions | ||
15 | * of the Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
23 | * DEALINGS IN THE SOFTWARE. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include "drmP.h" | ||
28 | #include "drm_edid.h" | ||
29 | |||
30 | /* | ||
31 | * Autogenerated from the DMT spec. | ||
32 | * This table is copied from xfree86/modes/xf86EdidModes.c. | ||
33 | * But the mode with Reduced blank feature is deleted. | ||
34 | */ | ||
35 | static struct drm_display_mode drm_dmt_modes[] = { | ||
36 | /* 640x350@85Hz */ | ||
37 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
38 | 736, 832, 0, 350, 382, 385, 445, 0, | ||
39 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
40 | /* 640x400@85Hz */ | ||
41 | { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
42 | 736, 832, 0, 400, 401, 404, 445, 0, | ||
43 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
44 | /* 720x400@85Hz */ | ||
45 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756, | ||
46 | 828, 936, 0, 400, 401, 404, 446, 0, | ||
47 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
48 | /* 640x480@60Hz */ | ||
49 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | ||
50 | 752, 800, 0, 480, 489, 492, 525, 0, | ||
51 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
52 | /* 640x480@72Hz */ | ||
53 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
54 | 704, 832, 0, 480, 489, 492, 520, 0, | ||
55 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
56 | /* 640x480@75Hz */ | ||
57 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
58 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
59 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
60 | /* 640x480@85Hz */ | ||
61 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696, | ||
62 | 752, 832, 0, 480, 481, 484, 509, 0, | ||
63 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
64 | /* 800x600@56Hz */ | ||
65 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
66 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
67 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
68 | /* 800x600@60Hz */ | ||
69 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
70 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
71 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
72 | /* 800x600@72Hz */ | ||
73 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
74 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
75 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
76 | /* 800x600@75Hz */ | ||
77 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
78 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
79 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
80 | /* 800x600@85Hz */ | ||
81 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832, | ||
82 | 896, 1048, 0, 600, 601, 604, 631, 0, | ||
83 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
84 | /* 848x480@60Hz */ | ||
85 | { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864, | ||
86 | 976, 1088, 0, 480, 486, 494, 517, 0, | ||
87 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
88 | /* 1024x768@43Hz, interlace */ | ||
89 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032, | ||
90 | 1208, 1264, 0, 768, 768, 772, 817, 0, | ||
91 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | | ||
92 | DRM_MODE_FLAG_INTERLACE) }, | ||
93 | /* 1024x768@60Hz */ | ||
94 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
95 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
96 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
97 | /* 1024x768@70Hz */ | ||
98 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
99 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
100 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
101 | /* 1024x768@75Hz */ | ||
102 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040, | ||
103 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
104 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
105 | /* 1024x768@85Hz */ | ||
106 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072, | ||
107 | 1168, 1376, 0, 768, 769, 772, 808, 0, | ||
108 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
109 | /* 1152x864@75Hz */ | ||
110 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
111 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
112 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
113 | /* 1280x768@60Hz */ | ||
114 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, | ||
115 | 1472, 1664, 0, 768, 771, 778, 798, 0, | ||
116 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
117 | /* 1280x768@75Hz */ | ||
118 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360, | ||
119 | 1488, 1696, 0, 768, 771, 778, 805, 0, | ||
120 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
121 | /* 1280x768@85Hz */ | ||
122 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360, | ||
123 | 1496, 1712, 0, 768, 771, 778, 809, 0, | ||
124 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
125 | /* 1280x800@60Hz */ | ||
126 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, | ||
127 | 1480, 1680, 0, 800, 803, 809, 831, 0, | ||
128 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
129 | /* 1280x800@75Hz */ | ||
130 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360, | ||
131 | 1488, 1696, 0, 800, 803, 809, 838, 0, | ||
132 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
133 | /* 1280x800@85Hz */ | ||
134 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360, | ||
135 | 1496, 1712, 0, 800, 803, 809, 843, 0, | ||
136 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
137 | /* 1280x960@60Hz */ | ||
138 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, | ||
139 | 1488, 1800, 0, 960, 961, 964, 1000, 0, | ||
140 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
141 | /* 1280x960@85Hz */ | ||
142 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344, | ||
143 | 1504, 1728, 0, 960, 961, 964, 1011, 0, | ||
144 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
145 | /* 1280x1024@60Hz */ | ||
146 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, | ||
147 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
148 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
149 | /* 1280x1024@75Hz */ | ||
150 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
151 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
152 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
153 | /* 1280x1024@85Hz */ | ||
154 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344, | ||
155 | 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, | ||
156 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
157 | /* 1360x768@60Hz */ | ||
158 | { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, | ||
159 | 1536, 1792, 0, 768, 771, 777, 795, 0, | ||
160 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
161 | /* 1440x1050@60Hz */ | ||
162 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, | ||
163 | 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, | ||
164 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
165 | /* 1440x1050@75Hz */ | ||
166 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504, | ||
167 | 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, | ||
168 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
169 | /* 1440x1050@85Hz */ | ||
170 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504, | ||
171 | 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, | ||
172 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
173 | /* 1440x900@60Hz */ | ||
174 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, | ||
175 | 1672, 1904, 0, 900, 903, 909, 934, 0, | ||
176 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
177 | /* 1440x900@75Hz */ | ||
178 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536, | ||
179 | 1688, 1936, 0, 900, 903, 909, 942, 0, | ||
180 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
181 | /* 1440x900@85Hz */ | ||
182 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544, | ||
183 | 1696, 1952, 0, 900, 903, 909, 948, 0, | ||
184 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
185 | /* 1600x1200@60Hz */ | ||
186 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, | ||
187 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
188 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
189 | /* 1600x1200@65Hz */ | ||
190 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664, | ||
191 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
192 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
193 | /* 1600x1200@70Hz */ | ||
194 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664, | ||
195 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
196 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
197 | /* 1600x1200@75Hz */ | ||
198 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 202500, 1600, 1664, | ||
199 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
200 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
201 | /* 1600x1200@85Hz */ | ||
202 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664, | ||
203 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
204 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
205 | /* 1680x1050@60Hz */ | ||
206 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, | ||
207 | 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, | ||
208 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
209 | /* 1680x1050@75Hz */ | ||
210 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800, | ||
211 | 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, | ||
212 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
213 | /* 1680x1050@85Hz */ | ||
214 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808, | ||
215 | 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, | ||
216 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
217 | /* 1792x1344@60Hz */ | ||
218 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, | ||
219 | 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, | ||
220 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
221 | /* 1729x1344@75Hz */ | ||
222 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888, | ||
223 | 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, | ||
224 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
225 | /* 1853x1392@60Hz */ | ||
226 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, | ||
227 | 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, | ||
228 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
229 | /* 1856x1392@75Hz */ | ||
230 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984, | ||
231 | 2208, 2560, 0, 1392, 1395, 1399, 1500, 0, | ||
232 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
233 | /* 1920x1200@60Hz */ | ||
234 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, | ||
235 | 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, | ||
236 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
237 | /* 1920x1200@75Hz */ | ||
238 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056, | ||
239 | 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, | ||
240 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
241 | /* 1920x1200@85Hz */ | ||
242 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064, | ||
243 | 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, | ||
244 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
245 | /* 1920x1440@60Hz */ | ||
246 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, | ||
247 | 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, | ||
248 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
249 | /* 1920x1440@75Hz */ | ||
250 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064, | ||
251 | 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, | ||
252 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
253 | /* 2560x1600@60Hz */ | ||
254 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, | ||
255 | 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, | ||
256 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
257 | /* 2560x1600@75HZ */ | ||
258 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768, | ||
259 | 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, | ||
260 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
261 | /* 2560x1600@85HZ */ | ||
262 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, | ||
263 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, | ||
264 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
265 | }; | ||
266 | static const int drm_num_dmt_modes = | ||
267 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | ||
268 | |||
269 | static struct drm_display_mode edid_est_modes[] = { | ||
270 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
271 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
272 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ | ||
273 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
274 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
275 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ | ||
276 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
277 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
278 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ | ||
279 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
280 | 704, 832, 0, 480, 489, 491, 520, 0, | ||
281 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ | ||
282 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, | ||
283 | 768, 864, 0, 480, 483, 486, 525, 0, | ||
284 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ | ||
285 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, | ||
286 | 752, 800, 0, 480, 490, 492, 525, 0, | ||
287 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ | ||
288 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, | ||
289 | 846, 900, 0, 400, 421, 423, 449, 0, | ||
290 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ | ||
291 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, | ||
292 | 846, 900, 0, 400, 412, 414, 449, 0, | ||
293 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ | ||
294 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
295 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
296 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ | ||
297 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, | ||
298 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
299 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ | ||
300 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
301 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
302 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ | ||
303 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
304 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
305 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ | ||
306 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, | ||
307 | 1208, 1264, 0, 768, 768, 776, 817, 0, | ||
308 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ | ||
309 | { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, | ||
310 | 928, 1152, 0, 624, 625, 628, 667, 0, | ||
311 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ | ||
312 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
313 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
314 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ | ||
315 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
316 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
317 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ | ||
318 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
319 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
320 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ | ||
321 | }; | ||
322 | |||
323 | static const struct { | ||
324 | short w; | ||
325 | short h; | ||
326 | short r; | ||
327 | short rb; | ||
328 | } est3_modes[] = { | ||
329 | /* byte 6 */ | ||
330 | { 640, 350, 85, 0 }, | ||
331 | { 640, 400, 85, 0 }, | ||
332 | { 720, 400, 85, 0 }, | ||
333 | { 640, 480, 85, 0 }, | ||
334 | { 848, 480, 60, 0 }, | ||
335 | { 800, 600, 85, 0 }, | ||
336 | { 1024, 768, 85, 0 }, | ||
337 | { 1152, 864, 75, 0 }, | ||
338 | /* byte 7 */ | ||
339 | { 1280, 768, 60, 1 }, | ||
340 | { 1280, 768, 60, 0 }, | ||
341 | { 1280, 768, 75, 0 }, | ||
342 | { 1280, 768, 85, 0 }, | ||
343 | { 1280, 960, 60, 0 }, | ||
344 | { 1280, 960, 85, 0 }, | ||
345 | { 1280, 1024, 60, 0 }, | ||
346 | { 1280, 1024, 85, 0 }, | ||
347 | /* byte 8 */ | ||
348 | { 1360, 768, 60, 0 }, | ||
349 | { 1440, 900, 60, 1 }, | ||
350 | { 1440, 900, 60, 0 }, | ||
351 | { 1440, 900, 75, 0 }, | ||
352 | { 1440, 900, 85, 0 }, | ||
353 | { 1400, 1050, 60, 1 }, | ||
354 | { 1400, 1050, 60, 0 }, | ||
355 | { 1400, 1050, 75, 0 }, | ||
356 | /* byte 9 */ | ||
357 | { 1400, 1050, 85, 0 }, | ||
358 | { 1680, 1050, 60, 1 }, | ||
359 | { 1680, 1050, 60, 0 }, | ||
360 | { 1680, 1050, 75, 0 }, | ||
361 | { 1680, 1050, 85, 0 }, | ||
362 | { 1600, 1200, 60, 0 }, | ||
363 | { 1600, 1200, 65, 0 }, | ||
364 | { 1600, 1200, 70, 0 }, | ||
365 | /* byte 10 */ | ||
366 | { 1600, 1200, 75, 0 }, | ||
367 | { 1600, 1200, 85, 0 }, | ||
368 | { 1792, 1344, 60, 0 }, | ||
369 | { 1792, 1344, 85, 0 }, | ||
370 | { 1856, 1392, 60, 0 }, | ||
371 | { 1856, 1392, 75, 0 }, | ||
372 | { 1920, 1200, 60, 1 }, | ||
373 | { 1920, 1200, 60, 0 }, | ||
374 | /* byte 11 */ | ||
375 | { 1920, 1200, 75, 0 }, | ||
376 | { 1920, 1200, 85, 0 }, | ||
377 | { 1920, 1440, 60, 0 }, | ||
378 | { 1920, 1440, 75, 0 }, | ||
379 | }; | ||
380 | static const int num_est3_modes = sizeof(est3_modes) / sizeof(est3_modes[0]); | ||
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 2ca8df8b6102..3a652a65546f 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -135,15 +135,9 @@ int drm_open(struct inode *inode, struct file *filp) | |||
135 | retcode = drm_open_helper(inode, filp, dev); | 135 | retcode = drm_open_helper(inode, filp, dev); |
136 | if (!retcode) { | 136 | if (!retcode) { |
137 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); | 137 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); |
138 | spin_lock(&dev->count_lock); | 138 | if (!dev->open_count++) |
139 | if (!dev->open_count++) { | ||
140 | spin_unlock(&dev->count_lock); | ||
141 | retcode = drm_setup(dev); | 139 | retcode = drm_setup(dev); |
142 | goto out; | ||
143 | } | ||
144 | spin_unlock(&dev->count_lock); | ||
145 | } | 140 | } |
146 | out: | ||
147 | if (!retcode) { | 141 | if (!retcode) { |
148 | mutex_lock(&dev->struct_mutex); | 142 | mutex_lock(&dev->struct_mutex); |
149 | if (minor->type == DRM_MINOR_LEGACY) { | 143 | if (minor->type == DRM_MINOR_LEGACY) { |
@@ -570,18 +564,14 @@ int drm_release(struct inode *inode, struct file *filp) | |||
570 | */ | 564 | */ |
571 | 565 | ||
572 | atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); | 566 | atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); |
573 | spin_lock(&dev->count_lock); | ||
574 | if (!--dev->open_count) { | 567 | if (!--dev->open_count) { |
575 | if (atomic_read(&dev->ioctl_count)) { | 568 | if (atomic_read(&dev->ioctl_count)) { |
576 | DRM_ERROR("Device busy: %d\n", | 569 | DRM_ERROR("Device busy: %d\n", |
577 | atomic_read(&dev->ioctl_count)); | 570 | atomic_read(&dev->ioctl_count)); |
578 | retcode = -EBUSY; | 571 | retcode = -EBUSY; |
579 | goto out; | 572 | } else |
580 | } | 573 | retcode = drm_lastclose(dev); |
581 | retcode = drm_lastclose(dev); | ||
582 | } | 574 | } |
583 | out: | ||
584 | spin_unlock(&dev->count_lock); | ||
585 | mutex_unlock(&drm_global_mutex); | 575 | mutex_unlock(&drm_global_mutex); |
586 | 576 | ||
587 | return retcode; | 577 | return retcode; |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 4f1b86714489..bf92d07510df 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -322,7 +322,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, | |||
322 | 322 | ||
323 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 323 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
324 | if (obj == NULL) | 324 | if (obj == NULL) |
325 | return -EBADF; | 325 | return -ENOENT; |
326 | 326 | ||
327 | again: | 327 | again: |
328 | if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) { | 328 | if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) { |
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 7b03b197fc00..47db4df37a69 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c | |||
@@ -392,6 +392,7 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri | |||
392 | if (sv->drm_di_minor >= 1) { | 392 | if (sv->drm_di_minor >= 1) { |
393 | /* | 393 | /* |
394 | * Version 1.1 includes tying of DRM to specific device | 394 | * Version 1.1 includes tying of DRM to specific device |
395 | * Version 1.4 has proper PCI domain support | ||
395 | */ | 396 | */ |
396 | retcode = drm_set_busid(dev, file_priv); | 397 | retcode = drm_set_busid(dev, file_priv); |
397 | if (retcode) | 398 | if (retcode) |
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 833b35f44a77..08792a740f18 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c | |||
@@ -470,6 +470,7 @@ static int ch7006_encoder_init(struct i2c_client *client, | |||
470 | priv->hmargin = 50; | 470 | priv->hmargin = 50; |
471 | priv->vmargin = 50; | 471 | priv->vmargin = 50; |
472 | priv->last_dpms = -1; | 472 | priv->last_dpms = -1; |
473 | priv->chip_version = ch7006_read(client, CH7006_VERSION_ID); | ||
473 | 474 | ||
474 | if (ch7006_tv_norm) { | 475 | if (ch7006_tv_norm) { |
475 | for (i = 0; i < NUM_TV_NORMS; i++) { | 476 | for (i = 0; i < NUM_TV_NORMS; i++) { |
diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index e447dfb63890..c860f24a5afc 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c | |||
@@ -316,7 +316,10 @@ void ch7006_setup_power_state(struct drm_encoder *encoder) | |||
316 | } | 316 | } |
317 | 317 | ||
318 | } else { | 318 | } else { |
319 | *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF); | 319 | if (priv->chip_version >= 0x20) |
320 | *power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF); | ||
321 | else | ||
322 | *power |= bitfs(CH7006_POWER_LEVEL, POWER_OFF); | ||
320 | } | 323 | } |
321 | } | 324 | } |
322 | 325 | ||
diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index 1c6d2e3bd96f..17667b7d57e7 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h | |||
@@ -95,6 +95,7 @@ struct ch7006_priv { | |||
95 | int flicker; | 95 | int flicker; |
96 | int scale; | 96 | int scale; |
97 | 97 | ||
98 | int chip_version; | ||
98 | int last_dpms; | 99 | int last_dpms; |
99 | }; | 100 | }; |
100 | 101 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2a4ed7ca8b4e..0758c7802e6b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -456,7 +456,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
456 | 456 | ||
457 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 457 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
458 | if (obj == NULL) | 458 | if (obj == NULL) |
459 | return -EBADF; | 459 | return -ENOENT; |
460 | obj_priv = to_intel_bo(obj); | 460 | obj_priv = to_intel_bo(obj); |
461 | 461 | ||
462 | /* Bounds check source. | 462 | /* Bounds check source. |
@@ -919,7 +919,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
919 | 919 | ||
920 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 920 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
921 | if (obj == NULL) | 921 | if (obj == NULL) |
922 | return -EBADF; | 922 | return -ENOENT; |
923 | obj_priv = to_intel_bo(obj); | 923 | obj_priv = to_intel_bo(obj); |
924 | 924 | ||
925 | /* Bounds check destination. | 925 | /* Bounds check destination. |
@@ -1002,7 +1002,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1002 | 1002 | ||
1003 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1003 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1004 | if (obj == NULL) | 1004 | if (obj == NULL) |
1005 | return -EBADF; | 1005 | return -ENOENT; |
1006 | obj_priv = to_intel_bo(obj); | 1006 | obj_priv = to_intel_bo(obj); |
1007 | 1007 | ||
1008 | mutex_lock(&dev->struct_mutex); | 1008 | mutex_lock(&dev->struct_mutex); |
@@ -1060,7 +1060,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
1060 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1060 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1061 | if (obj == NULL) { | 1061 | if (obj == NULL) { |
1062 | mutex_unlock(&dev->struct_mutex); | 1062 | mutex_unlock(&dev->struct_mutex); |
1063 | return -EBADF; | 1063 | return -ENOENT; |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | #if WATCH_BUF | 1066 | #if WATCH_BUF |
@@ -1099,7 +1099,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
1099 | 1099 | ||
1100 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1100 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1101 | if (obj == NULL) | 1101 | if (obj == NULL) |
1102 | return -EBADF; | 1102 | return -ENOENT; |
1103 | 1103 | ||
1104 | offset = args->offset; | 1104 | offset = args->offset; |
1105 | 1105 | ||
@@ -1373,7 +1373,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1373 | 1373 | ||
1374 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1374 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1375 | if (obj == NULL) | 1375 | if (obj == NULL) |
1376 | return -EBADF; | 1376 | return -ENOENT; |
1377 | 1377 | ||
1378 | mutex_lock(&dev->struct_mutex); | 1378 | mutex_lock(&dev->struct_mutex); |
1379 | 1379 | ||
@@ -3364,7 +3364,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3364 | reloc->target_handle); | 3364 | reloc->target_handle); |
3365 | if (target_obj == NULL) { | 3365 | if (target_obj == NULL) { |
3366 | i915_gem_object_unpin(obj); | 3366 | i915_gem_object_unpin(obj); |
3367 | return -EBADF; | 3367 | return -ENOENT; |
3368 | } | 3368 | } |
3369 | target_obj_priv = to_intel_bo(target_obj); | 3369 | target_obj_priv = to_intel_bo(target_obj); |
3370 | 3370 | ||
@@ -3781,7 +3781,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3781 | exec_list[i].handle, i); | 3781 | exec_list[i].handle, i); |
3782 | /* prevent error path from reading uninitialized data */ | 3782 | /* prevent error path from reading uninitialized data */ |
3783 | args->buffer_count = i + 1; | 3783 | args->buffer_count = i + 1; |
3784 | ret = -EBADF; | 3784 | ret = -ENOENT; |
3785 | goto err; | 3785 | goto err; |
3786 | } | 3786 | } |
3787 | 3787 | ||
@@ -3791,7 +3791,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3791 | object_list[i]); | 3791 | object_list[i]); |
3792 | /* prevent error path from reading uninitialized data */ | 3792 | /* prevent error path from reading uninitialized data */ |
3793 | args->buffer_count = i + 1; | 3793 | args->buffer_count = i + 1; |
3794 | ret = -EBADF; | 3794 | ret = -EINVAL; |
3795 | goto err; | 3795 | goto err; |
3796 | } | 3796 | } |
3797 | obj_priv->in_execbuffer = true; | 3797 | obj_priv->in_execbuffer = true; |
@@ -4265,7 +4265,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
4265 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", | 4265 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", |
4266 | args->handle); | 4266 | args->handle); |
4267 | mutex_unlock(&dev->struct_mutex); | 4267 | mutex_unlock(&dev->struct_mutex); |
4268 | return -EBADF; | 4268 | return -ENOENT; |
4269 | } | 4269 | } |
4270 | obj_priv = to_intel_bo(obj); | 4270 | obj_priv = to_intel_bo(obj); |
4271 | 4271 | ||
@@ -4321,7 +4321,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, | |||
4321 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", | 4321 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", |
4322 | args->handle); | 4322 | args->handle); |
4323 | mutex_unlock(&dev->struct_mutex); | 4323 | mutex_unlock(&dev->struct_mutex); |
4324 | return -EBADF; | 4324 | return -ENOENT; |
4325 | } | 4325 | } |
4326 | 4326 | ||
4327 | obj_priv = to_intel_bo(obj); | 4327 | obj_priv = to_intel_bo(obj); |
@@ -4355,7 +4355,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4355 | if (obj == NULL) { | 4355 | if (obj == NULL) { |
4356 | DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", | 4356 | DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", |
4357 | args->handle); | 4357 | args->handle); |
4358 | return -EBADF; | 4358 | return -ENOENT; |
4359 | } | 4359 | } |
4360 | 4360 | ||
4361 | mutex_lock(&dev->struct_mutex); | 4361 | mutex_lock(&dev->struct_mutex); |
@@ -4408,7 +4408,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4408 | if (obj == NULL) { | 4408 | if (obj == NULL) { |
4409 | DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n", | 4409 | DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n", |
4410 | args->handle); | 4410 | args->handle); |
4411 | return -EBADF; | 4411 | return -ENOENT; |
4412 | } | 4412 | } |
4413 | 4413 | ||
4414 | mutex_lock(&dev->struct_mutex); | 4414 | mutex_lock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 155719e4d16f..710eca70b323 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
@@ -275,7 +275,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
275 | 275 | ||
276 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 276 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
277 | if (obj == NULL) | 277 | if (obj == NULL) |
278 | return -EINVAL; | 278 | return -ENOENT; |
279 | obj_priv = to_intel_bo(obj); | 279 | obj_priv = to_intel_bo(obj); |
280 | 280 | ||
281 | if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) { | 281 | if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) { |
@@ -362,7 +362,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
362 | 362 | ||
363 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 363 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
364 | if (obj == NULL) | 364 | if (obj == NULL) |
365 | return -EINVAL; | 365 | return -ENOENT; |
366 | obj_priv = to_intel_bo(obj); | 366 | obj_priv = to_intel_bo(obj); |
367 | 367 | ||
368 | mutex_lock(&dev->struct_mutex); | 368 | mutex_lock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1e5e0d379fa9..5ec10e02341b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4429,15 +4429,12 @@ void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
4429 | } | 4429 | } |
4430 | 4430 | ||
4431 | static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | 4431 | static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, |
4432 | u16 *blue, uint32_t size) | 4432 | u16 *blue, uint32_t start, uint32_t size) |
4433 | { | 4433 | { |
4434 | int end = (start + size > 256) ? 256 : start + size, i; | ||
4434 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4435 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4435 | int i; | ||
4436 | |||
4437 | if (size != 256) | ||
4438 | return; | ||
4439 | 4436 | ||
4440 | for (i = 0; i < 256; i++) { | 4437 | for (i = start; i < end; i++) { |
4441 | intel_crtc->lut_r[i] = red[i] >> 8; | 4438 | intel_crtc->lut_r[i] = red[i] >> 8; |
4442 | intel_crtc->lut_g[i] = green[i] >> 8; | 4439 | intel_crtc->lut_g[i] = green[i] >> 8; |
4443 | intel_crtc->lut_b[i] = blue[i] >> 8; | 4440 | intel_crtc->lut_b[i] = blue[i] >> 8; |
@@ -5412,18 +5409,18 @@ intel_user_framebuffer_create(struct drm_device *dev, | |||
5412 | 5409 | ||
5413 | obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); | 5410 | obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); |
5414 | if (!obj) | 5411 | if (!obj) |
5415 | return NULL; | 5412 | return ERR_PTR(-ENOENT); |
5416 | 5413 | ||
5417 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); | 5414 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); |
5418 | if (!intel_fb) | 5415 | if (!intel_fb) |
5419 | return NULL; | 5416 | return ERR_PTR(-ENOMEM); |
5420 | 5417 | ||
5421 | ret = intel_framebuffer_init(dev, intel_fb, | 5418 | ret = intel_framebuffer_init(dev, intel_fb, |
5422 | mode_cmd, obj); | 5419 | mode_cmd, obj); |
5423 | if (ret) { | 5420 | if (ret) { |
5424 | drm_gem_object_unreference_unlocked(obj); | 5421 | drm_gem_object_unreference_unlocked(obj); |
5425 | kfree(intel_fb); | 5422 | kfree(intel_fb); |
5426 | return NULL; | 5423 | return ERR_PTR(ret); |
5427 | } | 5424 | } |
5428 | 5425 | ||
5429 | return &intel_fb->base; | 5426 | return &intel_fb->base; |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index a79525f434a8..7bdc96256bf5 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -121,7 +121,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
121 | 121 | ||
122 | info->par = ifbdev; | 122 | info->par = ifbdev; |
123 | 123 | ||
124 | intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); | 124 | ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); |
125 | if (ret) | ||
126 | goto out_unpin; | ||
125 | 127 | ||
126 | fb = &ifbdev->ifb.base; | 128 | fb = &ifbdev->ifb.base; |
127 | 129 | ||
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 2405d5ef0ca7..e9b06e4ef2a2 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -12,12 +12,12 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
12 | nouveau_dp.o \ | 12 | nouveau_dp.o \ |
13 | nv04_timer.o \ | 13 | nv04_timer.o \ |
14 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 14 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \ | 15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ |
16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ | 16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \ |
17 | nv04_graph.o nv10_graph.o nv20_graph.o \ | 17 | nv04_graph.o nv10_graph.o nv20_graph.o \ |
18 | nv40_graph.o nv50_graph.o \ | 18 | nv40_graph.o nv50_graph.o nvc0_graph.o \ |
19 | nv40_grctx.o nv50_grctx.o \ | 19 | nv40_grctx.o nv50_grctx.o \ |
20 | nv04_instmem.o nv50_instmem.o \ | 20 | nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ |
21 | nv50_crtc.o nv50_dac.o nv50_sor.o \ | 21 | nv50_crtc.o nv50_dac.o nv50_sor.o \ |
22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ | 22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ |
23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ | 23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 7369b5e73649..0b69a9628c95 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -1928,6 +1928,31 @@ init_condition_time(struct nvbios *bios, uint16_t offset, | |||
1928 | } | 1928 | } |
1929 | 1929 | ||
1930 | static int | 1930 | static int |
1931 | init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
1932 | { | ||
1933 | /* | ||
1934 | * INIT_LTIME opcode: 0x57 ('V') | ||
1935 | * | ||
1936 | * offset (8 bit): opcode | ||
1937 | * offset + 1 (16 bit): time | ||
1938 | * | ||
1939 | * Sleep for "time" miliseconds. | ||
1940 | */ | ||
1941 | |||
1942 | unsigned time = ROM16(bios->data[offset + 1]); | ||
1943 | |||
1944 | if (!iexec->execute) | ||
1945 | return 3; | ||
1946 | |||
1947 | BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X miliseconds\n", | ||
1948 | offset, time); | ||
1949 | |||
1950 | msleep(time); | ||
1951 | |||
1952 | return 3; | ||
1953 | } | ||
1954 | |||
1955 | static int | ||
1931 | init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, | 1956 | init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, |
1932 | struct init_exec *iexec) | 1957 | struct init_exec *iexec) |
1933 | { | 1958 | { |
@@ -1995,6 +2020,64 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1995 | } | 2020 | } |
1996 | 2021 | ||
1997 | static int | 2022 | static int |
2023 | init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
2024 | { | ||
2025 | /* | ||
2026 | * INIT_I2C_IF opcode: 0x5E ('^') | ||
2027 | * | ||
2028 | * offset (8 bit): opcode | ||
2029 | * offset + 1 (8 bit): DCB I2C table entry index | ||
2030 | * offset + 2 (8 bit): I2C slave address | ||
2031 | * offset + 3 (8 bit): I2C register | ||
2032 | * offset + 4 (8 bit): mask | ||
2033 | * offset + 5 (8 bit): data | ||
2034 | * | ||
2035 | * Read the register given by "I2C register" on the device addressed | ||
2036 | * by "I2C slave address" on the I2C bus given by "DCB I2C table | ||
2037 | * entry index". Compare the result AND "mask" to "data". | ||
2038 | * If they're not equal, skip subsequent opcodes until condition is | ||
2039 | * inverted (INIT_NOT), or we hit INIT_RESUME | ||
2040 | */ | ||
2041 | |||
2042 | uint8_t i2c_index = bios->data[offset + 1]; | ||
2043 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | ||
2044 | uint8_t reg = bios->data[offset + 3]; | ||
2045 | uint8_t mask = bios->data[offset + 4]; | ||
2046 | uint8_t data = bios->data[offset + 5]; | ||
2047 | struct nouveau_i2c_chan *chan; | ||
2048 | union i2c_smbus_data val; | ||
2049 | int ret; | ||
2050 | |||
2051 | /* no execute check by design */ | ||
2052 | |||
2053 | BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", | ||
2054 | offset, i2c_index, i2c_address); | ||
2055 | |||
2056 | chan = init_i2c_device_find(bios->dev, i2c_index); | ||
2057 | if (!chan) | ||
2058 | return -ENODEV; | ||
2059 | |||
2060 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, | ||
2061 | I2C_SMBUS_READ, reg, | ||
2062 | I2C_SMBUS_BYTE_DATA, &val); | ||
2063 | if (ret < 0) { | ||
2064 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: [no device], " | ||
2065 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
2066 | offset, reg, mask, data); | ||
2067 | iexec->execute = 0; | ||
2068 | return 6; | ||
2069 | } | ||
2070 | |||
2071 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " | ||
2072 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
2073 | offset, reg, val.byte, mask, data); | ||
2074 | |||
2075 | iexec->execute = ((val.byte & mask) == data); | ||
2076 | |||
2077 | return 6; | ||
2078 | } | ||
2079 | |||
2080 | static int | ||
1998 | init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | 2081 | init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) |
1999 | { | 2082 | { |
2000 | /* | 2083 | /* |
@@ -2083,9 +2166,10 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2083 | uint32_t val = 0; | 2166 | uint32_t val = 0; |
2084 | 2167 | ||
2085 | if (off < pci_resource_len(dev->pdev, 1)) { | 2168 | if (off < pci_resource_len(dev->pdev, 1)) { |
2086 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | 2169 | uint32_t __iomem *p = |
2170 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | ||
2087 | 2171 | ||
2088 | val = ioread32(p); | 2172 | val = ioread32(p + (off & ~PAGE_MASK)); |
2089 | 2173 | ||
2090 | io_mapping_unmap_atomic(p, KM_USER0); | 2174 | io_mapping_unmap_atomic(p, KM_USER0); |
2091 | } | 2175 | } |
@@ -2098,9 +2182,10 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2098 | uint32_t off, uint32_t val) | 2182 | uint32_t off, uint32_t val) |
2099 | { | 2183 | { |
2100 | if (off < pci_resource_len(dev->pdev, 1)) { | 2184 | if (off < pci_resource_len(dev->pdev, 1)) { |
2101 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | 2185 | uint32_t __iomem *p = |
2186 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | ||
2102 | 2187 | ||
2103 | iowrite32(val, p); | 2188 | iowrite32(val, p + (off & ~PAGE_MASK)); |
2104 | wmb(); | 2189 | wmb(); |
2105 | 2190 | ||
2106 | io_mapping_unmap_atomic(p, KM_USER0); | 2191 | io_mapping_unmap_atomic(p, KM_USER0); |
@@ -2165,7 +2250,7 @@ nv04_init_compute_mem(struct nvbios *bios) | |||
2165 | NV04_PFB_BOOT_0_RAM_AMOUNT, | 2250 | NV04_PFB_BOOT_0_RAM_AMOUNT, |
2166 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); | 2251 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); |
2167 | 2252 | ||
2168 | } else if (peek_fb(dev, fb, 0) == patt) { | 2253 | } else if (peek_fb(dev, fb, 0) != patt) { |
2169 | if (read_back_fb(dev, fb, 0x800000, patt)) | 2254 | if (read_back_fb(dev, fb, 0x800000, patt)) |
2170 | bios_md32(bios, NV04_PFB_BOOT_0, | 2255 | bios_md32(bios, NV04_PFB_BOOT_0, |
2171 | NV04_PFB_BOOT_0_RAM_AMOUNT, | 2256 | NV04_PFB_BOOT_0_RAM_AMOUNT, |
@@ -2593,7 +2678,7 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset, | |||
2593 | /* no iexec->execute check by design */ | 2678 | /* no iexec->execute check by design */ |
2594 | 2679 | ||
2595 | uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); | 2680 | uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); |
2596 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); | 2681 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & 0x40) >> 6; |
2597 | 2682 | ||
2598 | if (bios->major_version > 2) | 2683 | if (bios->major_version > 2) |
2599 | return 0; | 2684 | return 0; |
@@ -3140,7 +3225,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
3140 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; | 3225 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; |
3141 | int i; | 3226 | int i; |
3142 | 3227 | ||
3143 | if (dev_priv->card_type != NV_50) { | 3228 | if (dev_priv->card_type < NV_50) { |
3144 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); | 3229 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); |
3145 | return 1; | 3230 | return 1; |
3146 | } | 3231 | } |
@@ -3490,6 +3575,69 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
3490 | return len; | 3575 | return len; |
3491 | } | 3576 | } |
3492 | 3577 | ||
3578 | static int | ||
3579 | init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
3580 | { | ||
3581 | /* | ||
3582 | * INIT_I2C_LONG_IF opcode: 0x9A ('') | ||
3583 | * | ||
3584 | * offset (8 bit): opcode | ||
3585 | * offset + 1 (8 bit): DCB I2C table entry index | ||
3586 | * offset + 2 (8 bit): I2C slave address | ||
3587 | * offset + 3 (16 bit): I2C register | ||
3588 | * offset + 5 (8 bit): mask | ||
3589 | * offset + 6 (8 bit): data | ||
3590 | * | ||
3591 | * Read the register given by "I2C register" on the device addressed | ||
3592 | * by "I2C slave address" on the I2C bus given by "DCB I2C table | ||
3593 | * entry index". Compare the result AND "mask" to "data". | ||
3594 | * If they're not equal, skip subsequent opcodes until condition is | ||
3595 | * inverted (INIT_NOT), or we hit INIT_RESUME | ||
3596 | */ | ||
3597 | |||
3598 | uint8_t i2c_index = bios->data[offset + 1]; | ||
3599 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | ||
3600 | uint8_t reglo = bios->data[offset + 3]; | ||
3601 | uint8_t reghi = bios->data[offset + 4]; | ||
3602 | uint8_t mask = bios->data[offset + 5]; | ||
3603 | uint8_t data = bios->data[offset + 6]; | ||
3604 | struct nouveau_i2c_chan *chan; | ||
3605 | uint8_t buf0[2] = { reghi, reglo }; | ||
3606 | uint8_t buf1[1]; | ||
3607 | struct i2c_msg msg[2] = { | ||
3608 | { i2c_address, 0, 1, buf0 }, | ||
3609 | { i2c_address, I2C_M_RD, 1, buf1 }, | ||
3610 | }; | ||
3611 | int ret; | ||
3612 | |||
3613 | /* no execute check by design */ | ||
3614 | |||
3615 | BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", | ||
3616 | offset, i2c_index, i2c_address); | ||
3617 | |||
3618 | chan = init_i2c_device_find(bios->dev, i2c_index); | ||
3619 | if (!chan) | ||
3620 | return -ENODEV; | ||
3621 | |||
3622 | |||
3623 | ret = i2c_transfer(&chan->adapter, msg, 2); | ||
3624 | if (ret < 0) { | ||
3625 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], " | ||
3626 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
3627 | offset, reghi, reglo, mask, data); | ||
3628 | iexec->execute = 0; | ||
3629 | return 7; | ||
3630 | } | ||
3631 | |||
3632 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: 0x%02X, " | ||
3633 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
3634 | offset, reghi, reglo, buf1[0], mask, data); | ||
3635 | |||
3636 | iexec->execute = ((buf1[0] & mask) == data); | ||
3637 | |||
3638 | return 7; | ||
3639 | } | ||
3640 | |||
3493 | static struct init_tbl_entry itbl_entry[] = { | 3641 | static struct init_tbl_entry itbl_entry[] = { |
3494 | /* command name , id , length , offset , mult , command handler */ | 3642 | /* command name , id , length , offset , mult , command handler */ |
3495 | /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ | 3643 | /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ |
@@ -3516,9 +3664,11 @@ static struct init_tbl_entry itbl_entry[] = { | |||
3516 | { "INIT_ZM_CR" , 0x53, init_zm_cr }, | 3664 | { "INIT_ZM_CR" , 0x53, init_zm_cr }, |
3517 | { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, | 3665 | { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, |
3518 | { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, | 3666 | { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, |
3667 | { "INIT_LTIME" , 0x57, init_ltime }, | ||
3519 | { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, | 3668 | { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, |
3520 | /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ | 3669 | /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ |
3521 | { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, | 3670 | { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, |
3671 | { "INIT_I2C_IF" , 0x5E, init_i2c_if }, | ||
3522 | { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, | 3672 | { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, |
3523 | { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, | 3673 | { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, |
3524 | { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, | 3674 | { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, |
@@ -3552,6 +3702,7 @@ static struct init_tbl_entry itbl_entry[] = { | |||
3552 | { "INIT_97" , 0x97, init_97 }, | 3702 | { "INIT_97" , 0x97, init_97 }, |
3553 | { "INIT_AUXCH" , 0x98, init_auxch }, | 3703 | { "INIT_AUXCH" , 0x98, init_auxch }, |
3554 | { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, | 3704 | { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, |
3705 | { "INIT_I2C_LONG_IF" , 0x9A, init_i2c_long_if }, | ||
3555 | { NULL , 0 , NULL } | 3706 | { NULL , 0 , NULL } |
3556 | }; | 3707 | }; |
3557 | 3708 | ||
@@ -4410,7 +4561,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
4410 | bios->display.script_table_ptr, | 4561 | bios->display.script_table_ptr, |
4411 | table[2], table[3], table[0] >= 0x21); | 4562 | table[2], table[3], table[0] >= 0x21); |
4412 | if (!otable) { | 4563 | if (!otable) { |
4413 | NV_ERROR(dev, "Couldn't find matching output script table\n"); | 4564 | NV_DEBUG_KMS(dev, "failed to match any output table\n"); |
4414 | return 1; | 4565 | return 1; |
4415 | } | 4566 | } |
4416 | 4567 | ||
@@ -4467,7 +4618,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
4467 | if (script) | 4618 | if (script) |
4468 | script = clkcmptable(bios, script, pxclk); | 4619 | script = clkcmptable(bios, script, pxclk); |
4469 | if (!script) { | 4620 | if (!script) { |
4470 | NV_ERROR(dev, "clock script 0 not found\n"); | 4621 | NV_DEBUG_KMS(dev, "clock script 0 not found\n"); |
4471 | return 1; | 4622 | return 1; |
4472 | } | 4623 | } |
4473 | 4624 | ||
@@ -4826,7 +4977,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4826 | pll_lim->min_p = record[12]; | 4977 | pll_lim->min_p = record[12]; |
4827 | pll_lim->max_p = record[13]; | 4978 | pll_lim->max_p = record[13]; |
4828 | /* where did this go to?? */ | 4979 | /* where did this go to?? */ |
4829 | if (limit_match == 0x00614100 || limit_match == 0x00614900) | 4980 | if ((entry[0] & 0xf0) == 0x80) |
4830 | pll_lim->refclk = 27000; | 4981 | pll_lim->refclk = 27000; |
4831 | else | 4982 | else |
4832 | pll_lim->refclk = 100000; | 4983 | pll_lim->refclk = 100000; |
@@ -5852,7 +6003,7 @@ static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) | |||
5852 | entry->i2c_index = i2c; | 6003 | entry->i2c_index = i2c; |
5853 | entry->heads = heads; | 6004 | entry->heads = heads; |
5854 | entry->location = DCB_LOC_ON_CHIP; | 6005 | entry->location = DCB_LOC_ON_CHIP; |
5855 | /* "or" mostly unused in early gen crt modesetting, 0 is fine */ | 6006 | entry->or = 1; |
5856 | } | 6007 | } |
5857 | 6008 | ||
5858 | static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) | 6009 | static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) |
@@ -5980,7 +6131,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | |||
5980 | } | 6131 | } |
5981 | break; | 6132 | break; |
5982 | case OUTPUT_TMDS: | 6133 | case OUTPUT_TMDS: |
5983 | entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; | 6134 | if (dcb->version >= 0x40) |
6135 | entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; | ||
6136 | else if (dcb->version >= 0x30) | ||
6137 | entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; | ||
6138 | else if (dcb->version >= 0x22) | ||
6139 | entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; | ||
6140 | |||
5984 | break; | 6141 | break; |
5985 | case 0xe: | 6142 | case 0xe: |
5986 | /* weird g80 mobile type that "nv" treats as a terminator */ | 6143 | /* weird g80 mobile type that "nv" treats as a terminator */ |
@@ -6270,6 +6427,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | |||
6270 | dcb->i2c_table = &bios->data[i2ctabptr]; | 6427 | dcb->i2c_table = &bios->data[i2ctabptr]; |
6271 | if (dcb->version >= 0x30) | 6428 | if (dcb->version >= 0x30) |
6272 | dcb->i2c_default_indices = dcb->i2c_table[4]; | 6429 | dcb->i2c_default_indices = dcb->i2c_table[4]; |
6430 | |||
6431 | /* | ||
6432 | * Parse the "management" I2C bus, used for hardware | ||
6433 | * monitoring and some external TMDS transmitters. | ||
6434 | */ | ||
6435 | if (dcb->version >= 0x22) { | ||
6436 | int idx = (dcb->version >= 0x40 ? | ||
6437 | dcb->i2c_default_indices & 0xf : | ||
6438 | 2); | ||
6439 | |||
6440 | read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, | ||
6441 | idx, &dcb->i2c[idx]); | ||
6442 | } | ||
6273 | } | 6443 | } |
6274 | 6444 | ||
6275 | if (entries > DCB_MAX_NUM_ENTRIES) | 6445 | if (entries > DCB_MAX_NUM_ENTRIES) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 024458a8d060..fd14dfd3d780 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -131,6 +131,7 @@ struct dcb_entry { | |||
131 | } dpconf; | 131 | } dpconf; |
132 | struct { | 132 | struct { |
133 | struct sor_conf sor; | 133 | struct sor_conf sor; |
134 | int slave_addr; | ||
134 | } tmdsconf; | 135 | } tmdsconf; |
135 | }; | 136 | }; |
136 | bool i2c_upper_default; | 137 | bool i2c_upper_default; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 3ca8343c15df..84f85183d041 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -51,9 +51,6 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) | |||
51 | if (nvbo->tile) | 51 | if (nvbo->tile) |
52 | nv10_mem_expire_tiling(dev, nvbo->tile, NULL); | 52 | nv10_mem_expire_tiling(dev, nvbo->tile, NULL); |
53 | 53 | ||
54 | spin_lock(&dev_priv->ttm.bo_list_lock); | ||
55 | list_del(&nvbo->head); | ||
56 | spin_unlock(&dev_priv->ttm.bo_list_lock); | ||
57 | kfree(nvbo); | 54 | kfree(nvbo); |
58 | } | 55 | } |
59 | 56 | ||
@@ -166,9 +163,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
166 | } | 163 | } |
167 | nvbo->channel = NULL; | 164 | nvbo->channel = NULL; |
168 | 165 | ||
169 | spin_lock(&dev_priv->ttm.bo_list_lock); | ||
170 | list_add_tail(&nvbo->head, &dev_priv->ttm.bo_list); | ||
171 | spin_unlock(&dev_priv->ttm.bo_list_lock); | ||
172 | *pnvbo = nvbo; | 166 | *pnvbo = nvbo; |
173 | return 0; | 167 | return 0; |
174 | } | 168 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 734e92635e83..b1b22baf1428 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -37,12 +37,6 @@ | |||
37 | #include "nouveau_connector.h" | 37 | #include "nouveau_connector.h" |
38 | #include "nouveau_hw.h" | 38 | #include "nouveau_hw.h" |
39 | 39 | ||
40 | static inline struct drm_encoder_slave_funcs * | ||
41 | get_slave_funcs(struct nouveau_encoder *enc) | ||
42 | { | ||
43 | return to_encoder_slave(to_drm_encoder(enc))->slave_funcs; | ||
44 | } | ||
45 | |||
46 | static struct nouveau_encoder * | 40 | static struct nouveau_encoder * |
47 | find_encoder_by_type(struct drm_connector *connector, int type) | 41 | find_encoder_by_type(struct drm_connector *connector, int type) |
48 | { | 42 | { |
@@ -360,6 +354,7 @@ nouveau_connector_set_property(struct drm_connector *connector, | |||
360 | { | 354 | { |
361 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 355 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
362 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 356 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
357 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
363 | struct drm_device *dev = connector->dev; | 358 | struct drm_device *dev = connector->dev; |
364 | int ret; | 359 | int ret; |
365 | 360 | ||
@@ -432,8 +427,8 @@ nouveau_connector_set_property(struct drm_connector *connector, | |||
432 | } | 427 | } |
433 | 428 | ||
434 | if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) | 429 | if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) |
435 | return get_slave_funcs(nv_encoder)-> | 430 | return get_slave_funcs(encoder)->set_property( |
436 | set_property(to_drm_encoder(nv_encoder), connector, property, value); | 431 | encoder, connector, property, value); |
437 | 432 | ||
438 | return -EINVAL; | 433 | return -EINVAL; |
439 | } | 434 | } |
@@ -545,6 +540,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
545 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 540 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
546 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 541 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
547 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 542 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
543 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
548 | int ret = 0; | 544 | int ret = 0; |
549 | 545 | ||
550 | /* destroy the native mode, the attached monitor could have changed. | 546 | /* destroy the native mode, the attached monitor could have changed. |
@@ -580,8 +576,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
580 | } | 576 | } |
581 | 577 | ||
582 | if (nv_encoder->dcb->type == OUTPUT_TV) | 578 | if (nv_encoder->dcb->type == OUTPUT_TV) |
583 | ret = get_slave_funcs(nv_encoder)-> | 579 | ret = get_slave_funcs(encoder)->get_modes(encoder, connector); |
584 | get_modes(to_drm_encoder(nv_encoder), connector); | ||
585 | 580 | ||
586 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || | 581 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || |
587 | nv_connector->dcb->type == DCB_CONNECTOR_eDP) | 582 | nv_connector->dcb->type == DCB_CONNECTOR_eDP) |
@@ -597,6 +592,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
597 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | 592 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; |
598 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 593 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
599 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 594 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
595 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
600 | unsigned min_clock = 25000, max_clock = min_clock; | 596 | unsigned min_clock = 25000, max_clock = min_clock; |
601 | unsigned clock = mode->clock; | 597 | unsigned clock = mode->clock; |
602 | 598 | ||
@@ -623,8 +619,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
623 | max_clock = 350000; | 619 | max_clock = 350000; |
624 | break; | 620 | break; |
625 | case OUTPUT_TV: | 621 | case OUTPUT_TV: |
626 | return get_slave_funcs(nv_encoder)-> | 622 | return get_slave_funcs(encoder)->mode_valid(encoder, mode); |
627 | mode_valid(to_drm_encoder(nv_encoder), mode); | ||
628 | case OUTPUT_DP: | 623 | case OUTPUT_DP: |
629 | if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) | 624 | if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) |
630 | max_clock = nv_encoder->dp.link_nr * 270000; | 625 | max_clock = nv_encoder->dp.link_nr * 270000; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 74e6b4ed12c0..2e11fd65b4dd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -84,16 +84,16 @@ nouveau_user_framebuffer_create(struct drm_device *dev, | |||
84 | 84 | ||
85 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); | 85 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); |
86 | if (!gem) | 86 | if (!gem) |
87 | return NULL; | 87 | return ERR_PTR(-ENOENT); |
88 | 88 | ||
89 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); | 89 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); |
90 | if (!nouveau_fb) | 90 | if (!nouveau_fb) |
91 | return NULL; | 91 | return ERR_PTR(-ENOMEM); |
92 | 92 | ||
93 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); | 93 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); |
94 | if (ret) { | 94 | if (ret) { |
95 | drm_gem_object_unreference(gem); | 95 | drm_gem_object_unreference(gem); |
96 | return NULL; | 96 | return ERR_PTR(ret); |
97 | } | 97 | } |
98 | 98 | ||
99 | return &nouveau_fb->base; | 99 | return &nouveau_fb->base; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 33742b11188b..8a1b188b4cd1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -572,47 +572,64 @@ out: | |||
572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); | 572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); |
573 | } | 573 | } |
574 | 574 | ||
575 | int | 575 | static int |
576 | nouveau_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | 576 | nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) |
577 | uint8_t write_byte, uint8_t *read_byte) | ||
578 | { | 577 | { |
579 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | 578 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; |
580 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adapter; | ||
581 | struct drm_device *dev = auxch->dev; | 579 | struct drm_device *dev = auxch->dev; |
582 | int ret = 0, cmd, addr = algo_data->address; | 580 | struct i2c_msg *msg = msgs; |
583 | uint8_t *buf; | 581 | int ret, mcnt = num; |
584 | |||
585 | if (mode == MODE_I2C_READ) { | ||
586 | cmd = AUX_I2C_READ; | ||
587 | buf = read_byte; | ||
588 | } else { | ||
589 | cmd = (mode & MODE_I2C_READ) ? AUX_I2C_READ : AUX_I2C_WRITE; | ||
590 | buf = &write_byte; | ||
591 | } | ||
592 | 582 | ||
593 | if (!(mode & MODE_I2C_STOP)) | 583 | while (mcnt--) { |
594 | cmd |= AUX_I2C_MOT; | 584 | u8 remaining = msg->len; |
585 | u8 *ptr = msg->buf; | ||
595 | 586 | ||
596 | if (mode & MODE_I2C_START) | 587 | while (remaining) { |
597 | return 1; | 588 | u8 cnt = (remaining > 16) ? 16 : remaining; |
589 | u8 cmd; | ||
598 | 590 | ||
599 | for (;;) { | 591 | if (msg->flags & I2C_M_RD) |
600 | ret = nouveau_dp_auxch(auxch, cmd, addr, buf, 1); | 592 | cmd = AUX_I2C_READ; |
601 | if (ret < 0) | 593 | else |
602 | return ret; | 594 | cmd = AUX_I2C_WRITE; |
603 | 595 | ||
604 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { | 596 | if (mcnt || remaining > 16) |
605 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: | 597 | cmd |= AUX_I2C_MOT; |
606 | return 1; | 598 | |
607 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: | 599 | ret = nouveau_dp_auxch(auxch, cmd, msg->addr, ptr, cnt); |
608 | return -EREMOTEIO; | 600 | if (ret < 0) |
609 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | 601 | return ret; |
610 | udelay(100); | 602 | |
611 | break; | 603 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { |
612 | default: | 604 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: |
613 | NV_ERROR(dev, "invalid auxch status: 0x%08x\n", ret); | 605 | break; |
614 | return -EREMOTEIO; | 606 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: |
607 | return -EREMOTEIO; | ||
608 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | ||
609 | udelay(100); | ||
610 | continue; | ||
611 | default: | ||
612 | NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret); | ||
613 | return -EREMOTEIO; | ||
614 | } | ||
615 | |||
616 | ptr += cnt; | ||
617 | remaining -= cnt; | ||
615 | } | 618 | } |
619 | |||
620 | msg++; | ||
616 | } | 621 | } |
622 | |||
623 | return num; | ||
624 | } | ||
625 | |||
626 | static u32 | ||
627 | nouveau_dp_i2c_func(struct i2c_adapter *adap) | ||
628 | { | ||
629 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
617 | } | 630 | } |
618 | 631 | ||
632 | const struct i2c_algorithm nouveau_dp_i2c_algo = { | ||
633 | .master_xfer = nouveau_dp_i2c_xfer, | ||
634 | .functionality = nouveau_dp_i2c_func | ||
635 | }; | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index e15db15dca77..e424bf74d706 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -410,7 +410,7 @@ enum nv04_fp_display_regs { | |||
410 | 410 | ||
411 | struct nv04_crtc_reg { | 411 | struct nv04_crtc_reg { |
412 | unsigned char MiscOutReg; /* */ | 412 | unsigned char MiscOutReg; /* */ |
413 | uint8_t CRTC[0x9f]; | 413 | uint8_t CRTC[0xa0]; |
414 | uint8_t CR58[0x10]; | 414 | uint8_t CR58[0x10]; |
415 | uint8_t Sequencer[5]; | 415 | uint8_t Sequencer[5]; |
416 | uint8_t Graphics[9]; | 416 | uint8_t Graphics[9]; |
@@ -509,6 +509,7 @@ enum nouveau_card_type { | |||
509 | NV_30 = 0x30, | 509 | NV_30 = 0x30, |
510 | NV_40 = 0x40, | 510 | NV_40 = 0x40, |
511 | NV_50 = 0x50, | 511 | NV_50 = 0x50, |
512 | NV_C0 = 0xc0, | ||
512 | }; | 513 | }; |
513 | 514 | ||
514 | struct drm_nouveau_private { | 515 | struct drm_nouveau_private { |
@@ -536,8 +537,6 @@ struct drm_nouveau_private { | |||
536 | struct drm_global_reference mem_global_ref; | 537 | struct drm_global_reference mem_global_ref; |
537 | struct ttm_bo_global_ref bo_global_ref; | 538 | struct ttm_bo_global_ref bo_global_ref; |
538 | struct ttm_bo_device bdev; | 539 | struct ttm_bo_device bdev; |
539 | spinlock_t bo_list_lock; | ||
540 | struct list_head bo_list; | ||
541 | atomic_t validate_sequence; | 540 | atomic_t validate_sequence; |
542 | } ttm; | 541 | } ttm; |
543 | 542 | ||
@@ -931,6 +930,10 @@ extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, | |||
931 | extern int nv50_fb_init(struct drm_device *); | 930 | extern int nv50_fb_init(struct drm_device *); |
932 | extern void nv50_fb_takedown(struct drm_device *); | 931 | extern void nv50_fb_takedown(struct drm_device *); |
933 | 932 | ||
933 | /* nvc0_fb.c */ | ||
934 | extern int nvc0_fb_init(struct drm_device *); | ||
935 | extern void nvc0_fb_takedown(struct drm_device *); | ||
936 | |||
934 | /* nv04_fifo.c */ | 937 | /* nv04_fifo.c */ |
935 | extern int nv04_fifo_init(struct drm_device *); | 938 | extern int nv04_fifo_init(struct drm_device *); |
936 | extern void nv04_fifo_disable(struct drm_device *); | 939 | extern void nv04_fifo_disable(struct drm_device *); |
@@ -968,6 +971,20 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *); | |||
968 | extern int nv50_fifo_load_context(struct nouveau_channel *); | 971 | extern int nv50_fifo_load_context(struct nouveau_channel *); |
969 | extern int nv50_fifo_unload_context(struct drm_device *); | 972 | extern int nv50_fifo_unload_context(struct drm_device *); |
970 | 973 | ||
974 | /* nvc0_fifo.c */ | ||
975 | extern int nvc0_fifo_init(struct drm_device *); | ||
976 | extern void nvc0_fifo_takedown(struct drm_device *); | ||
977 | extern void nvc0_fifo_disable(struct drm_device *); | ||
978 | extern void nvc0_fifo_enable(struct drm_device *); | ||
979 | extern bool nvc0_fifo_reassign(struct drm_device *, bool); | ||
980 | extern bool nvc0_fifo_cache_flush(struct drm_device *); | ||
981 | extern bool nvc0_fifo_cache_pull(struct drm_device *, bool); | ||
982 | extern int nvc0_fifo_channel_id(struct drm_device *); | ||
983 | extern int nvc0_fifo_create_context(struct nouveau_channel *); | ||
984 | extern void nvc0_fifo_destroy_context(struct nouveau_channel *); | ||
985 | extern int nvc0_fifo_load_context(struct nouveau_channel *); | ||
986 | extern int nvc0_fifo_unload_context(struct drm_device *); | ||
987 | |||
971 | /* nv04_graph.c */ | 988 | /* nv04_graph.c */ |
972 | extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; | 989 | extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; |
973 | extern int nv04_graph_init(struct drm_device *); | 990 | extern int nv04_graph_init(struct drm_device *); |
@@ -1032,6 +1049,16 @@ extern int nv50_graph_unload_context(struct drm_device *); | |||
1032 | extern void nv50_graph_context_switch(struct drm_device *); | 1049 | extern void nv50_graph_context_switch(struct drm_device *); |
1033 | extern int nv50_grctx_init(struct nouveau_grctx *); | 1050 | extern int nv50_grctx_init(struct nouveau_grctx *); |
1034 | 1051 | ||
1052 | /* nvc0_graph.c */ | ||
1053 | extern int nvc0_graph_init(struct drm_device *); | ||
1054 | extern void nvc0_graph_takedown(struct drm_device *); | ||
1055 | extern void nvc0_graph_fifo_access(struct drm_device *, bool); | ||
1056 | extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); | ||
1057 | extern int nvc0_graph_create_context(struct nouveau_channel *); | ||
1058 | extern void nvc0_graph_destroy_context(struct nouveau_channel *); | ||
1059 | extern int nvc0_graph_load_context(struct nouveau_channel *); | ||
1060 | extern int nvc0_graph_unload_context(struct drm_device *); | ||
1061 | |||
1035 | /* nv04_instmem.c */ | 1062 | /* nv04_instmem.c */ |
1036 | extern int nv04_instmem_init(struct drm_device *); | 1063 | extern int nv04_instmem_init(struct drm_device *); |
1037 | extern void nv04_instmem_takedown(struct drm_device *); | 1064 | extern void nv04_instmem_takedown(struct drm_device *); |
@@ -1058,6 +1085,18 @@ extern void nv50_instmem_flush(struct drm_device *); | |||
1058 | extern void nv84_instmem_flush(struct drm_device *); | 1085 | extern void nv84_instmem_flush(struct drm_device *); |
1059 | extern void nv50_vm_flush(struct drm_device *, int engine); | 1086 | extern void nv50_vm_flush(struct drm_device *, int engine); |
1060 | 1087 | ||
1088 | /* nvc0_instmem.c */ | ||
1089 | extern int nvc0_instmem_init(struct drm_device *); | ||
1090 | extern void nvc0_instmem_takedown(struct drm_device *); | ||
1091 | extern int nvc0_instmem_suspend(struct drm_device *); | ||
1092 | extern void nvc0_instmem_resume(struct drm_device *); | ||
1093 | extern int nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, | ||
1094 | uint32_t *size); | ||
1095 | extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); | ||
1096 | extern int nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); | ||
1097 | extern int nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); | ||
1098 | extern void nvc0_instmem_flush(struct drm_device *); | ||
1099 | |||
1061 | /* nv04_mc.c */ | 1100 | /* nv04_mc.c */ |
1062 | extern int nv04_mc_init(struct drm_device *); | 1101 | extern int nv04_mc_init(struct drm_device *); |
1063 | extern void nv04_mc_takedown(struct drm_device *); | 1102 | extern void nv04_mc_takedown(struct drm_device *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index a1a0d48ae70c..7c82d68bc155 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
@@ -71,6 +71,12 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) | |||
71 | return &enc->base.base; | 71 | return &enc->base.base; |
72 | } | 72 | } |
73 | 73 | ||
74 | static inline struct drm_encoder_slave_funcs * | ||
75 | get_slave_funcs(struct drm_encoder *enc) | ||
76 | { | ||
77 | return to_encoder_slave(enc)->slave_funcs; | ||
78 | } | ||
79 | |||
74 | struct nouveau_connector * | 80 | struct nouveau_connector * |
75 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); | 81 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); |
76 | int nv50_sor_create(struct drm_connector *, struct dcb_entry *); | 82 | int nv50_sor_create(struct drm_connector *, struct dcb_entry *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 099f637264aa..dbd30b2e43fd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -281,6 +281,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
281 | 281 | ||
282 | if (dev_priv->channel && !nouveau_nofbaccel) { | 282 | if (dev_priv->channel && !nouveau_nofbaccel) { |
283 | switch (dev_priv->card_type) { | 283 | switch (dev_priv->card_type) { |
284 | case NV_C0: | ||
285 | break; | ||
284 | case NV_50: | 286 | case NV_50: |
285 | nv50_fbcon_accel_init(info); | 287 | nv50_fbcon_accel_init(info); |
286 | info->fbops = &nv50_fbcon_ops; | 288 | info->fbops = &nv50_fbcon_ops; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 547f2c24c1e7..0f417ac1b696 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -284,7 +284,7 @@ retry: | |||
284 | if (!gem) { | 284 | if (!gem) { |
285 | NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); | 285 | NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); |
286 | validate_fini(op, NULL); | 286 | validate_fini(op, NULL); |
287 | return -EINVAL; | 287 | return -ENOENT; |
288 | } | 288 | } |
289 | nvbo = gem->driver_private; | 289 | nvbo = gem->driver_private; |
290 | 290 | ||
@@ -759,7 +759,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, | |||
759 | 759 | ||
760 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 760 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
761 | if (!gem) | 761 | if (!gem) |
762 | return ret; | 762 | return -ENOENT; |
763 | nvbo = nouveau_gem_object(gem); | 763 | nvbo = nouveau_gem_object(gem); |
764 | 764 | ||
765 | if (nvbo->cpu_filp) { | 765 | if (nvbo->cpu_filp) { |
@@ -797,7 +797,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, | |||
797 | 797 | ||
798 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 798 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
799 | if (!gem) | 799 | if (!gem) |
800 | return ret; | 800 | return -ENOENT; |
801 | nvbo = nouveau_gem_object(gem); | 801 | nvbo = nouveau_gem_object(gem); |
802 | 802 | ||
803 | if (nvbo->cpu_filp != file_priv) | 803 | if (nvbo->cpu_filp != file_priv) |
@@ -822,7 +822,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data, | |||
822 | 822 | ||
823 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 823 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
824 | if (!gem) | 824 | if (!gem) |
825 | return -EINVAL; | 825 | return -ENOENT; |
826 | 826 | ||
827 | ret = nouveau_gem_info(gem, req); | 827 | ret = nouveau_gem_info(gem, req); |
828 | drm_gem_object_unreference_unlocked(gem); | 828 | drm_gem_object_unreference_unlocked(gem); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index 7855b35effc3..7b613682e400 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c | |||
@@ -865,8 +865,12 @@ nv_save_state_ext(struct drm_device *dev, int head, | |||
865 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 865 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); |
866 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 866 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
867 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); | 867 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); |
868 | if (dev_priv->card_type >= NV_30) | 868 | |
869 | if (dev_priv->card_type >= NV_30) { | ||
869 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); | 870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); |
871 | rd_cio_state(dev, head, regp, 0x9f); | ||
872 | } | ||
873 | |||
870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); | 874 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); |
871 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 875 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
872 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); | 876 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); |
@@ -971,8 +975,11 @@ nv_load_state_ext(struct drm_device *dev, int head, | |||
971 | wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); | 975 | wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); |
972 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 976 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); |
973 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 977 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
974 | if (dev_priv->card_type >= NV_30) | 978 | |
979 | if (dev_priv->card_type >= NV_30) { | ||
975 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); | 980 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); |
981 | wr_cio_state(dev, head, regp, 0x9f); | ||
982 | } | ||
976 | 983 | ||
977 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); | 984 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); |
978 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 985 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index cb0cb34440c6..0bd407ca3d42 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
163 | if (entry->chan) | 163 | if (entry->chan) |
164 | return -EEXIST; | 164 | return -EEXIST; |
165 | 165 | ||
166 | if (dev_priv->card_type == NV_50 && entry->read >= NV50_I2C_PORTS) { | 166 | if (dev_priv->card_type == NV_C0 && entry->read >= NV50_I2C_PORTS) { |
167 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); | 167 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); |
168 | return -EINVAL; | 168 | return -EINVAL; |
169 | } | 169 | } |
@@ -174,26 +174,26 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
174 | 174 | ||
175 | switch (entry->port_type) { | 175 | switch (entry->port_type) { |
176 | case 0: | 176 | case 0: |
177 | i2c->algo.bit.setsda = nv04_i2c_setsda; | 177 | i2c->bit.setsda = nv04_i2c_setsda; |
178 | i2c->algo.bit.setscl = nv04_i2c_setscl; | 178 | i2c->bit.setscl = nv04_i2c_setscl; |
179 | i2c->algo.bit.getsda = nv04_i2c_getsda; | 179 | i2c->bit.getsda = nv04_i2c_getsda; |
180 | i2c->algo.bit.getscl = nv04_i2c_getscl; | 180 | i2c->bit.getscl = nv04_i2c_getscl; |
181 | i2c->rd = entry->read; | 181 | i2c->rd = entry->read; |
182 | i2c->wr = entry->write; | 182 | i2c->wr = entry->write; |
183 | break; | 183 | break; |
184 | case 4: | 184 | case 4: |
185 | i2c->algo.bit.setsda = nv4e_i2c_setsda; | 185 | i2c->bit.setsda = nv4e_i2c_setsda; |
186 | i2c->algo.bit.setscl = nv4e_i2c_setscl; | 186 | i2c->bit.setscl = nv4e_i2c_setscl; |
187 | i2c->algo.bit.getsda = nv4e_i2c_getsda; | 187 | i2c->bit.getsda = nv4e_i2c_getsda; |
188 | i2c->algo.bit.getscl = nv4e_i2c_getscl; | 188 | i2c->bit.getscl = nv4e_i2c_getscl; |
189 | i2c->rd = 0x600800 + entry->read; | 189 | i2c->rd = 0x600800 + entry->read; |
190 | i2c->wr = 0x600800 + entry->write; | 190 | i2c->wr = 0x600800 + entry->write; |
191 | break; | 191 | break; |
192 | case 5: | 192 | case 5: |
193 | i2c->algo.bit.setsda = nv50_i2c_setsda; | 193 | i2c->bit.setsda = nv50_i2c_setsda; |
194 | i2c->algo.bit.setscl = nv50_i2c_setscl; | 194 | i2c->bit.setscl = nv50_i2c_setscl; |
195 | i2c->algo.bit.getsda = nv50_i2c_getsda; | 195 | i2c->bit.getsda = nv50_i2c_getsda; |
196 | i2c->algo.bit.getscl = nv50_i2c_getscl; | 196 | i2c->bit.getscl = nv50_i2c_getscl; |
197 | i2c->rd = nv50_i2c_port[entry->read]; | 197 | i2c->rd = nv50_i2c_port[entry->read]; |
198 | i2c->wr = i2c->rd; | 198 | i2c->wr = i2c->rd; |
199 | break; | 199 | break; |
@@ -216,17 +216,14 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
216 | i2c_set_adapdata(&i2c->adapter, i2c); | 216 | i2c_set_adapdata(&i2c->adapter, i2c); |
217 | 217 | ||
218 | if (entry->port_type < 6) { | 218 | if (entry->port_type < 6) { |
219 | i2c->adapter.algo_data = &i2c->algo.bit; | 219 | i2c->adapter.algo_data = &i2c->bit; |
220 | i2c->algo.bit.udelay = 40; | 220 | i2c->bit.udelay = 40; |
221 | i2c->algo.bit.timeout = usecs_to_jiffies(5000); | 221 | i2c->bit.timeout = usecs_to_jiffies(5000); |
222 | i2c->algo.bit.data = i2c; | 222 | i2c->bit.data = i2c; |
223 | ret = i2c_bit_add_bus(&i2c->adapter); | 223 | ret = i2c_bit_add_bus(&i2c->adapter); |
224 | } else { | 224 | } else { |
225 | i2c->adapter.algo_data = &i2c->algo.dp; | 225 | i2c->adapter.algo = &nouveau_dp_i2c_algo; |
226 | i2c->algo.dp.running = false; | 226 | ret = i2c_add_adapter(&i2c->adapter); |
227 | i2c->algo.dp.address = 0; | ||
228 | i2c->algo.dp.aux_ch = nouveau_dp_i2c_aux_ch; | ||
229 | ret = i2c_dp_aux_add_bus(&i2c->adapter); | ||
230 | } | 227 | } |
231 | 228 | ||
232 | if (ret) { | 229 | if (ret) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index 6dd2f8713cd1..f71cb32f7571 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h | |||
@@ -33,10 +33,7 @@ struct dcb_i2c_entry; | |||
33 | struct nouveau_i2c_chan { | 33 | struct nouveau_i2c_chan { |
34 | struct i2c_adapter adapter; | 34 | struct i2c_adapter adapter; |
35 | struct drm_device *dev; | 35 | struct drm_device *dev; |
36 | union { | 36 | struct i2c_algo_bit_data bit; |
37 | struct i2c_algo_bit_data bit; | ||
38 | struct i2c_algo_dp_aux_data dp; | ||
39 | } algo; | ||
40 | unsigned rd; | 37 | unsigned rd; |
41 | unsigned wr; | 38 | unsigned wr; |
42 | unsigned data; | 39 | unsigned data; |
@@ -49,7 +46,6 @@ bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); | |||
49 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, | 46 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, |
50 | struct i2c_board_info *info, int index); | 47 | struct i2c_board_info *info, int index); |
51 | 48 | ||
52 | int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, | 49 | extern const struct i2c_algorithm nouveau_dp_i2c_algo; |
53 | uint8_t *read_byte); | ||
54 | 50 | ||
55 | #endif /* __NOUVEAU_I2C_H__ */ | 51 | #endif /* __NOUVEAU_I2C_H__ */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 53360f156063..794b0ee30cf6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -49,7 +49,7 @@ nouveau_irq_preinstall(struct drm_device *dev) | |||
49 | /* Master disable */ | 49 | /* Master disable */ |
50 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); | 50 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); |
51 | 51 | ||
52 | if (dev_priv->card_type == NV_50) { | 52 | if (dev_priv->card_type >= NV_50) { |
53 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); | 53 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); |
54 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); | 54 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); |
55 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); | 55 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); |
@@ -586,11 +586,11 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) | |||
586 | } | 586 | } |
587 | 587 | ||
588 | if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { | 588 | if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { |
589 | nouveau_pgraph_intr_context_switch(dev); | ||
590 | |||
591 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; | 589 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; |
592 | nv_wr32(dev, NV03_PGRAPH_INTR, | 590 | nv_wr32(dev, NV03_PGRAPH_INTR, |
593 | NV_PGRAPH_INTR_CONTEXT_SWITCH); | 591 | NV_PGRAPH_INTR_CONTEXT_SWITCH); |
592 | |||
593 | nouveau_pgraph_intr_context_switch(dev); | ||
594 | } | 594 | } |
595 | 595 | ||
596 | if (status) { | 596 | if (status) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index a9f36ab256b7..9689d4147686 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -320,7 +320,8 @@ nouveau_mem_detect(struct drm_device *dev) | |||
320 | if (dev_priv->card_type < NV_50) { | 320 | if (dev_priv->card_type < NV_50) { |
321 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | 321 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
322 | dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; | 322 | dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; |
323 | } else { | 323 | } else |
324 | if (dev_priv->card_type < NV_C0) { | ||
324 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | 325 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
325 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; | 326 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; |
326 | dev_priv->vram_size &= 0xffffffff00ll; | 327 | dev_priv->vram_size &= 0xffffffff00ll; |
@@ -328,6 +329,9 @@ nouveau_mem_detect(struct drm_device *dev) | |||
328 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); | 329 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); |
329 | dev_priv->vram_sys_base <<= 12; | 330 | dev_priv->vram_sys_base <<= 12; |
330 | } | 331 | } |
332 | } else { | ||
333 | dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; | ||
334 | dev_priv->vram_size *= nv_rd32(dev, 0x121c74); | ||
331 | } | 335 | } |
332 | 336 | ||
333 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); | 337 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); |
@@ -351,7 +355,7 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
351 | /* First of all, disable fast writes, otherwise if it's | 355 | /* First of all, disable fast writes, otherwise if it's |
352 | * already enabled in the AGP bridge and we disable the card's | 356 | * already enabled in the AGP bridge and we disable the card's |
353 | * AGP controller we might be locking ourselves out of it. */ | 357 | * AGP controller we might be locking ourselves out of it. */ |
354 | if (dev->agp->acquired) { | 358 | if (nv_rd32(dev, NV04_PBUS_PCI_NV_19) & PCI_AGP_COMMAND_FW) { |
355 | struct drm_agp_info info; | 359 | struct drm_agp_info info; |
356 | struct drm_agp_mode mode; | 360 | struct drm_agp_mode mode; |
357 | 361 | ||
@@ -359,7 +363,7 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
359 | if (ret) | 363 | if (ret) |
360 | return ret; | 364 | return ret; |
361 | 365 | ||
362 | mode.mode = info.mode & ~0x10; | 366 | mode.mode = info.mode & ~PCI_AGP_COMMAND_FW; |
363 | ret = drm_agp_enable(dev, mode); | 367 | ret = drm_agp_enable(dev, mode); |
364 | if (ret) | 368 | if (ret) |
365 | return ret; | 369 | return ret; |
@@ -405,6 +409,8 @@ nouveau_mem_init_agp(struct drm_device *dev) | |||
405 | } | 409 | } |
406 | } | 410 | } |
407 | 411 | ||
412 | nouveau_mem_reset_agp(dev); | ||
413 | |||
408 | ret = drm_agp_info(dev, &info); | 414 | ret = drm_agp_info(dev, &info); |
409 | if (ret) { | 415 | if (ret) { |
410 | NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); | 416 | NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); |
@@ -459,8 +465,6 @@ nouveau_mem_init(struct drm_device *dev) | |||
459 | return ret; | 465 | return ret; |
460 | } | 466 | } |
461 | 467 | ||
462 | INIT_LIST_HEAD(&dev_priv->ttm.bo_list); | ||
463 | spin_lock_init(&dev_priv->ttm.bo_list_lock); | ||
464 | spin_lock_init(&dev_priv->tile.lock); | 468 | spin_lock_init(&dev_priv->tile.lock); |
465 | 469 | ||
466 | dev_priv->fb_available_size = dev_priv->vram_size; | 470 | dev_priv->fb_available_size = dev_priv->vram_size; |
@@ -494,7 +498,6 @@ nouveau_mem_init(struct drm_device *dev) | |||
494 | /* GART */ | 498 | /* GART */ |
495 | #if !defined(__powerpc__) && !defined(__ia64__) | 499 | #if !defined(__powerpc__) && !defined(__ia64__) |
496 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { | 500 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { |
497 | nouveau_mem_reset_agp(dev); | ||
498 | ret = nouveau_mem_init_agp(dev); | 501 | ret = nouveau_mem_init_agp(dev); |
499 | if (ret) | 502 | if (ret) |
500 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); | 503 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index 9c1056cb8a90..21a6e453b975 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
@@ -220,28 +220,21 @@ | |||
220 | # define NV_PGRAPH_INTR_ERROR (1<<20) | 220 | # define NV_PGRAPH_INTR_ERROR (1<<20) |
221 | #define NV10_PGRAPH_CTX_CONTROL 0x00400144 | 221 | #define NV10_PGRAPH_CTX_CONTROL 0x00400144 |
222 | #define NV10_PGRAPH_CTX_USER 0x00400148 | 222 | #define NV10_PGRAPH_CTX_USER 0x00400148 |
223 | #define NV10_PGRAPH_CTX_SWITCH1 0x0040014C | 223 | #define NV10_PGRAPH_CTX_SWITCH(i) (0x0040014C + 0x4*(i)) |
224 | #define NV10_PGRAPH_CTX_SWITCH2 0x00400150 | ||
225 | #define NV10_PGRAPH_CTX_SWITCH3 0x00400154 | ||
226 | #define NV10_PGRAPH_CTX_SWITCH4 0x00400158 | ||
227 | #define NV10_PGRAPH_CTX_SWITCH5 0x0040015C | ||
228 | #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 | 224 | #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 |
229 | #define NV10_PGRAPH_CTX_CACHE1 0x00400160 | 225 | #define NV10_PGRAPH_CTX_CACHE(i, j) (0x00400160 \ |
226 | + 0x4*(i) + 0x20*(j)) | ||
230 | #define NV04_PGRAPH_CTX_SWITCH2 0x00400164 | 227 | #define NV04_PGRAPH_CTX_SWITCH2 0x00400164 |
231 | #define NV04_PGRAPH_CTX_SWITCH3 0x00400168 | 228 | #define NV04_PGRAPH_CTX_SWITCH3 0x00400168 |
232 | #define NV04_PGRAPH_CTX_SWITCH4 0x0040016C | 229 | #define NV04_PGRAPH_CTX_SWITCH4 0x0040016C |
233 | #define NV04_PGRAPH_CTX_CONTROL 0x00400170 | 230 | #define NV04_PGRAPH_CTX_CONTROL 0x00400170 |
234 | #define NV04_PGRAPH_CTX_USER 0x00400174 | 231 | #define NV04_PGRAPH_CTX_USER 0x00400174 |
235 | #define NV04_PGRAPH_CTX_CACHE1 0x00400180 | 232 | #define NV04_PGRAPH_CTX_CACHE1 0x00400180 |
236 | #define NV10_PGRAPH_CTX_CACHE2 0x00400180 | ||
237 | #define NV03_PGRAPH_CTX_CONTROL 0x00400190 | 233 | #define NV03_PGRAPH_CTX_CONTROL 0x00400190 |
238 | #define NV03_PGRAPH_CTX_USER 0x00400194 | 234 | #define NV03_PGRAPH_CTX_USER 0x00400194 |
239 | #define NV04_PGRAPH_CTX_CACHE2 0x004001A0 | 235 | #define NV04_PGRAPH_CTX_CACHE2 0x004001A0 |
240 | #define NV10_PGRAPH_CTX_CACHE3 0x004001A0 | ||
241 | #define NV04_PGRAPH_CTX_CACHE3 0x004001C0 | 236 | #define NV04_PGRAPH_CTX_CACHE3 0x004001C0 |
242 | #define NV10_PGRAPH_CTX_CACHE4 0x004001C0 | ||
243 | #define NV04_PGRAPH_CTX_CACHE4 0x004001E0 | 237 | #define NV04_PGRAPH_CTX_CACHE4 0x004001E0 |
244 | #define NV10_PGRAPH_CTX_CACHE5 0x004001E0 | ||
245 | #define NV40_PGRAPH_CTXCTL_0304 0x00400304 | 238 | #define NV40_PGRAPH_CTXCTL_0304 0x00400304 |
246 | #define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 | 239 | #define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 |
247 | #define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 | 240 | #define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 |
@@ -356,9 +349,12 @@ | |||
356 | #define NV04_PGRAPH_FFINTFC_ST2 0x00400754 | 349 | #define NV04_PGRAPH_FFINTFC_ST2 0x00400754 |
357 | #define NV10_PGRAPH_RDI_DATA 0x00400754 | 350 | #define NV10_PGRAPH_RDI_DATA 0x00400754 |
358 | #define NV04_PGRAPH_DMA_PITCH 0x00400760 | 351 | #define NV04_PGRAPH_DMA_PITCH 0x00400760 |
359 | #define NV10_PGRAPH_FFINTFC_ST2 0x00400764 | 352 | #define NV10_PGRAPH_FFINTFC_FIFO_PTR 0x00400760 |
360 | #define NV04_PGRAPH_DVD_COLORFMT 0x00400764 | 353 | #define NV04_PGRAPH_DVD_COLORFMT 0x00400764 |
354 | #define NV10_PGRAPH_FFINTFC_ST2 0x00400764 | ||
361 | #define NV04_PGRAPH_SCALED_FORMAT 0x00400768 | 355 | #define NV04_PGRAPH_SCALED_FORMAT 0x00400768 |
356 | #define NV10_PGRAPH_FFINTFC_ST2_DL 0x00400768 | ||
357 | #define NV10_PGRAPH_FFINTFC_ST2_DH 0x0040076c | ||
362 | #define NV10_PGRAPH_DMA_PITCH 0x00400770 | 358 | #define NV10_PGRAPH_DMA_PITCH 0x00400770 |
363 | #define NV10_PGRAPH_DVD_COLORFMT 0x00400774 | 359 | #define NV10_PGRAPH_DVD_COLORFMT 0x00400774 |
364 | #define NV10_PGRAPH_SCALED_FORMAT 0x00400778 | 360 | #define NV10_PGRAPH_SCALED_FORMAT 0x00400778 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index ee3729e7823b..989322be3728 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -359,6 +359,54 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
359 | engine->gpio.set = nv50_gpio_set; | 359 | engine->gpio.set = nv50_gpio_set; |
360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | 360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; |
361 | break; | 361 | break; |
362 | case 0xC0: | ||
363 | engine->instmem.init = nvc0_instmem_init; | ||
364 | engine->instmem.takedown = nvc0_instmem_takedown; | ||
365 | engine->instmem.suspend = nvc0_instmem_suspend; | ||
366 | engine->instmem.resume = nvc0_instmem_resume; | ||
367 | engine->instmem.populate = nvc0_instmem_populate; | ||
368 | engine->instmem.clear = nvc0_instmem_clear; | ||
369 | engine->instmem.bind = nvc0_instmem_bind; | ||
370 | engine->instmem.unbind = nvc0_instmem_unbind; | ||
371 | engine->instmem.flush = nvc0_instmem_flush; | ||
372 | engine->mc.init = nv50_mc_init; | ||
373 | engine->mc.takedown = nv50_mc_takedown; | ||
374 | engine->timer.init = nv04_timer_init; | ||
375 | engine->timer.read = nv04_timer_read; | ||
376 | engine->timer.takedown = nv04_timer_takedown; | ||
377 | engine->fb.init = nvc0_fb_init; | ||
378 | engine->fb.takedown = nvc0_fb_takedown; | ||
379 | engine->graph.grclass = NULL; //nvc0_graph_grclass; | ||
380 | engine->graph.init = nvc0_graph_init; | ||
381 | engine->graph.takedown = nvc0_graph_takedown; | ||
382 | engine->graph.fifo_access = nvc0_graph_fifo_access; | ||
383 | engine->graph.channel = nvc0_graph_channel; | ||
384 | engine->graph.create_context = nvc0_graph_create_context; | ||
385 | engine->graph.destroy_context = nvc0_graph_destroy_context; | ||
386 | engine->graph.load_context = nvc0_graph_load_context; | ||
387 | engine->graph.unload_context = nvc0_graph_unload_context; | ||
388 | engine->fifo.channels = 128; | ||
389 | engine->fifo.init = nvc0_fifo_init; | ||
390 | engine->fifo.takedown = nvc0_fifo_takedown; | ||
391 | engine->fifo.disable = nvc0_fifo_disable; | ||
392 | engine->fifo.enable = nvc0_fifo_enable; | ||
393 | engine->fifo.reassign = nvc0_fifo_reassign; | ||
394 | engine->fifo.channel_id = nvc0_fifo_channel_id; | ||
395 | engine->fifo.create_context = nvc0_fifo_create_context; | ||
396 | engine->fifo.destroy_context = nvc0_fifo_destroy_context; | ||
397 | engine->fifo.load_context = nvc0_fifo_load_context; | ||
398 | engine->fifo.unload_context = nvc0_fifo_unload_context; | ||
399 | engine->display.early_init = nv50_display_early_init; | ||
400 | engine->display.late_takedown = nv50_display_late_takedown; | ||
401 | engine->display.create = nv50_display_create; | ||
402 | engine->display.init = nv50_display_init; | ||
403 | engine->display.destroy = nv50_display_destroy; | ||
404 | engine->gpio.init = nv50_gpio_init; | ||
405 | engine->gpio.takedown = nouveau_stub_takedown; | ||
406 | engine->gpio.get = nv50_gpio_get; | ||
407 | engine->gpio.set = nv50_gpio_set; | ||
408 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | ||
409 | break; | ||
362 | default: | 410 | default: |
363 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); | 411 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); |
364 | return 1; | 412 | return 1; |
@@ -739,8 +787,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
739 | int ret; | 787 | int ret; |
740 | 788 | ||
741 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); | 789 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); |
742 | if (!dev_priv) | 790 | if (!dev_priv) { |
743 | return -ENOMEM; | 791 | ret = -ENOMEM; |
792 | goto err_out; | ||
793 | } | ||
744 | dev->dev_private = dev_priv; | 794 | dev->dev_private = dev_priv; |
745 | dev_priv->dev = dev; | 795 | dev_priv->dev = dev; |
746 | 796 | ||
@@ -750,8 +800,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
750 | dev->pci_vendor, dev->pci_device, dev->pdev->class); | 800 | dev->pci_vendor, dev->pci_device, dev->pdev->class); |
751 | 801 | ||
752 | dev_priv->wq = create_workqueue("nouveau"); | 802 | dev_priv->wq = create_workqueue("nouveau"); |
753 | if (!dev_priv->wq) | 803 | if (!dev_priv->wq) { |
754 | return -EINVAL; | 804 | ret = -EINVAL; |
805 | goto err_priv; | ||
806 | } | ||
755 | 807 | ||
756 | /* resource 0 is mmio regs */ | 808 | /* resource 0 is mmio regs */ |
757 | /* resource 1 is linear FB */ | 809 | /* resource 1 is linear FB */ |
@@ -764,7 +816,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
764 | if (!dev_priv->mmio) { | 816 | if (!dev_priv->mmio) { |
765 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " | 817 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " |
766 | "Please report your setup to " DRIVER_EMAIL "\n"); | 818 | "Please report your setup to " DRIVER_EMAIL "\n"); |
767 | return -EINVAL; | 819 | ret = -EINVAL; |
820 | goto err_wq; | ||
768 | } | 821 | } |
769 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", | 822 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", |
770 | (unsigned long long)mmio_start_offs); | 823 | (unsigned long long)mmio_start_offs); |
@@ -810,9 +863,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
810 | case 0xa0: | 863 | case 0xa0: |
811 | dev_priv->card_type = NV_50; | 864 | dev_priv->card_type = NV_50; |
812 | break; | 865 | break; |
866 | case 0xc0: | ||
867 | dev_priv->card_type = NV_C0; | ||
868 | break; | ||
813 | default: | 869 | default: |
814 | NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); | 870 | NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); |
815 | return -EINVAL; | 871 | ret = -EINVAL; |
872 | goto err_mmio; | ||
816 | } | 873 | } |
817 | 874 | ||
818 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", | 875 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", |
@@ -820,7 +877,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
820 | 877 | ||
821 | ret = nouveau_remove_conflicting_drivers(dev); | 878 | ret = nouveau_remove_conflicting_drivers(dev); |
822 | if (ret) | 879 | if (ret) |
823 | return ret; | 880 | goto err_mmio; |
824 | 881 | ||
825 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ | 882 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ |
826 | if (dev_priv->card_type >= NV_40) { | 883 | if (dev_priv->card_type >= NV_40) { |
@@ -834,7 +891,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
834 | dev_priv->ramin_size); | 891 | dev_priv->ramin_size); |
835 | if (!dev_priv->ramin) { | 892 | if (!dev_priv->ramin) { |
836 | NV_ERROR(dev, "Failed to PRAMIN BAR"); | 893 | NV_ERROR(dev, "Failed to PRAMIN BAR"); |
837 | return -ENOMEM; | 894 | ret = -ENOMEM; |
895 | goto err_mmio; | ||
838 | } | 896 | } |
839 | } else { | 897 | } else { |
840 | dev_priv->ramin_size = 1 * 1024 * 1024; | 898 | dev_priv->ramin_size = 1 * 1024 * 1024; |
@@ -842,7 +900,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
842 | dev_priv->ramin_size); | 900 | dev_priv->ramin_size); |
843 | if (!dev_priv->ramin) { | 901 | if (!dev_priv->ramin) { |
844 | NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); | 902 | NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); |
845 | return -ENOMEM; | 903 | ret = -ENOMEM; |
904 | goto err_mmio; | ||
846 | } | 905 | } |
847 | } | 906 | } |
848 | 907 | ||
@@ -857,9 +916,21 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
857 | /* For kernel modesetting, init card now and bring up fbcon */ | 916 | /* For kernel modesetting, init card now and bring up fbcon */ |
858 | ret = nouveau_card_init(dev); | 917 | ret = nouveau_card_init(dev); |
859 | if (ret) | 918 | if (ret) |
860 | return ret; | 919 | goto err_ramin; |
861 | 920 | ||
862 | return 0; | 921 | return 0; |
922 | |||
923 | err_ramin: | ||
924 | iounmap(dev_priv->ramin); | ||
925 | err_mmio: | ||
926 | iounmap(dev_priv->mmio); | ||
927 | err_wq: | ||
928 | destroy_workqueue(dev_priv->wq); | ||
929 | err_priv: | ||
930 | kfree(dev_priv); | ||
931 | dev->dev_private = NULL; | ||
932 | err_out: | ||
933 | return ret; | ||
863 | } | 934 | } |
864 | 935 | ||
865 | void nouveau_lastclose(struct drm_device *dev) | 936 | void nouveau_lastclose(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 1c20c08ce67c..497df8765f28 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -542,6 +542,9 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | |||
542 | * 1 << 30 on 0x60.830), for no apparent reason */ | 542 | * 1 << 30 on 0x60.830), for no apparent reason */ |
543 | regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; | 543 | regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; |
544 | 544 | ||
545 | if (dev_priv->card_type >= NV_30) | ||
546 | regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1; | ||
547 | |||
545 | regp->crtc_830 = mode->crtc_vdisplay - 3; | 548 | regp->crtc_830 = mode->crtc_vdisplay - 3; |
546 | regp->crtc_834 = mode->crtc_vdisplay - 1; | 549 | regp->crtc_834 = mode->crtc_vdisplay - 1; |
547 | 550 | ||
@@ -739,15 +742,13 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) | |||
739 | } | 742 | } |
740 | 743 | ||
741 | static void | 744 | static void |
742 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t size) | 745 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, |
746 | uint32_t size) | ||
743 | { | 747 | { |
748 | int end = (start + size > 256) ? 256 : start + size, i; | ||
744 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 749 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
745 | int i; | ||
746 | 750 | ||
747 | if (size != 256) | 751 | for (i = start; i < end; i++) { |
748 | return; | ||
749 | |||
750 | for (i = 0; i < 256; i++) { | ||
751 | nv_crtc->lut.r[i] = r[i]; | 752 | nv_crtc->lut.r[i] = r[i]; |
752 | nv_crtc->lut.g[i] = g[i]; | 753 | nv_crtc->lut.g[i] = g[i]; |
753 | nv_crtc->lut.b[i] = b[i]; | 754 | nv_crtc->lut.b[i] = b[i]; |
@@ -914,7 +915,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | |||
914 | 915 | ||
915 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); | 916 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); |
916 | if (!gem) | 917 | if (!gem) |
917 | return -EINVAL; | 918 | return -ENOENT; |
918 | cursor = nouveau_gem_object(gem); | 919 | cursor = nouveau_gem_object(gem); |
919 | 920 | ||
920 | ret = nouveau_bo_map(cursor); | 921 | ret = nouveau_bo_map(cursor); |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 3311f3a8c818..a5dcf7685800 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "nouveau_hw.h" | 34 | #include "nouveau_hw.h" |
35 | #include "nvreg.h" | 35 | #include "nvreg.h" |
36 | 36 | ||
37 | #include "i2c/sil164.h" | ||
38 | |||
37 | #define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ | 39 | #define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ |
38 | NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ | 40 | NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ |
39 | NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) | 41 | NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) |
@@ -144,6 +146,36 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) | |||
144 | } | 146 | } |
145 | } | 147 | } |
146 | 148 | ||
149 | static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) | ||
150 | { | ||
151 | struct drm_device *dev = encoder->dev; | ||
152 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | ||
153 | struct drm_encoder *slave; | ||
154 | |||
155 | if (dcb->type != OUTPUT_TMDS || dcb->location == DCB_LOC_ON_CHIP) | ||
156 | return NULL; | ||
157 | |||
158 | /* Some BIOSes (e.g. the one in a Quadro FX1000) report several | ||
159 | * TMDS transmitters at the same I2C address, in the same I2C | ||
160 | * bus. This can still work because in that case one of them is | ||
161 | * always hard-wired to a reasonable configuration using straps, | ||
162 | * and the other one needs to be programmed. | ||
163 | * | ||
164 | * I don't think there's a way to know which is which, even the | ||
165 | * blob programs the one exposed via I2C for *both* heads, so | ||
166 | * let's do the same. | ||
167 | */ | ||
168 | list_for_each_entry(slave, &dev->mode_config.encoder_list, head) { | ||
169 | struct dcb_entry *slave_dcb = nouveau_encoder(slave)->dcb; | ||
170 | |||
171 | if (slave_dcb->type == OUTPUT_TMDS && get_slave_funcs(slave) && | ||
172 | slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr) | ||
173 | return slave; | ||
174 | } | ||
175 | |||
176 | return NULL; | ||
177 | } | ||
178 | |||
147 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, | 179 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, |
148 | struct drm_display_mode *mode, | 180 | struct drm_display_mode *mode, |
149 | struct drm_display_mode *adjusted_mode) | 181 | struct drm_display_mode *adjusted_mode) |
@@ -429,6 +461,11 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) | |||
429 | else | 461 | else |
430 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); | 462 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); |
431 | 463 | ||
464 | /* Init external transmitters */ | ||
465 | if (get_tmds_slave(encoder)) | ||
466 | get_slave_funcs(get_tmds_slave(encoder))->mode_set( | ||
467 | encoder, &nv_encoder->mode, &nv_encoder->mode); | ||
468 | |||
432 | helper->dpms(encoder, DRM_MODE_DPMS_ON); | 469 | helper->dpms(encoder, DRM_MODE_DPMS_ON); |
433 | 470 | ||
434 | NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | 471 | NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", |
@@ -550,10 +587,42 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) | |||
550 | 587 | ||
551 | NV_DEBUG_KMS(encoder->dev, "\n"); | 588 | NV_DEBUG_KMS(encoder->dev, "\n"); |
552 | 589 | ||
590 | if (get_slave_funcs(encoder)) | ||
591 | get_slave_funcs(encoder)->destroy(encoder); | ||
592 | |||
553 | drm_encoder_cleanup(encoder); | 593 | drm_encoder_cleanup(encoder); |
554 | kfree(nv_encoder); | 594 | kfree(nv_encoder); |
555 | } | 595 | } |
556 | 596 | ||
597 | static void nv04_tmds_slave_init(struct drm_encoder *encoder) | ||
598 | { | ||
599 | struct drm_device *dev = encoder->dev; | ||
600 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | ||
601 | struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, 2); | ||
602 | struct i2c_board_info info[] = { | ||
603 | { | ||
604 | .type = "sil164", | ||
605 | .addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38), | ||
606 | .platform_data = &(struct sil164_encoder_params) { | ||
607 | SIL164_INPUT_EDGE_RISING | ||
608 | } | ||
609 | }, | ||
610 | { } | ||
611 | }; | ||
612 | int type; | ||
613 | |||
614 | if (!nv_gf4_disp_arch(dev) || !i2c || | ||
615 | get_tmds_slave(encoder)) | ||
616 | return; | ||
617 | |||
618 | type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2); | ||
619 | if (type < 0) | ||
620 | return; | ||
621 | |||
622 | drm_i2c_encoder_init(dev, to_encoder_slave(encoder), | ||
623 | &i2c->adapter, &info[type]); | ||
624 | } | ||
625 | |||
557 | static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { | 626 | static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { |
558 | .dpms = nv04_lvds_dpms, | 627 | .dpms = nv04_lvds_dpms, |
559 | .save = nv04_dfp_save, | 628 | .save = nv04_dfp_save, |
@@ -616,6 +685,10 @@ nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
616 | encoder->possible_crtcs = entry->heads; | 685 | encoder->possible_crtcs = entry->heads; |
617 | encoder->possible_clones = 0; | 686 | encoder->possible_clones = 0; |
618 | 687 | ||
688 | if (entry->type == OUTPUT_TMDS && | ||
689 | entry->location != DCB_LOC_ON_CHIP) | ||
690 | nv04_tmds_slave_init(encoder); | ||
691 | |||
619 | drm_mode_connector_attach_encoder(connector, encoder); | 692 | drm_mode_connector_attach_encoder(connector, encoder); |
620 | return 0; | 693 | return 0; |
621 | } | 694 | } |
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 94e299cef0b2..0b5d012d7c28 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c | |||
@@ -89,7 +89,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) | |||
89 | 89 | ||
90 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); | 90 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); |
91 | 91 | ||
92 | to_encoder_slave(encoder)->slave_funcs->dpms(encoder, mode); | 92 | get_slave_funcs(encoder)->dpms(encoder, mode); |
93 | } | 93 | } |
94 | 94 | ||
95 | static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) | 95 | static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) |
@@ -152,7 +152,7 @@ static void nv04_tv_mode_set(struct drm_encoder *encoder, | |||
152 | regp->tv_vskew = 1; | 152 | regp->tv_vskew = 1; |
153 | regp->tv_vsync_delay = 1; | 153 | regp->tv_vsync_delay = 1; |
154 | 154 | ||
155 | to_encoder_slave(encoder)->slave_funcs->mode_set(encoder, mode, adjusted_mode); | 155 | get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void nv04_tv_commit(struct drm_encoder *encoder) | 158 | static void nv04_tv_commit(struct drm_encoder *encoder) |
@@ -171,8 +171,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) | |||
171 | 171 | ||
172 | static void nv04_tv_destroy(struct drm_encoder *encoder) | 172 | static void nv04_tv_destroy(struct drm_encoder *encoder) |
173 | { | 173 | { |
174 | to_encoder_slave(encoder)->slave_funcs->destroy(encoder); | 174 | get_slave_funcs(encoder)->destroy(encoder); |
175 | |||
176 | drm_encoder_cleanup(encoder); | 175 | drm_encoder_cleanup(encoder); |
177 | 176 | ||
178 | kfree(encoder->helper_private); | 177 | kfree(encoder->helper_private); |
@@ -229,7 +228,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
229 | goto fail_cleanup; | 228 | goto fail_cleanup; |
230 | 229 | ||
231 | /* Fill the function pointers */ | 230 | /* Fill the function pointers */ |
232 | sfuncs = to_encoder_slave(encoder)->slave_funcs; | 231 | sfuncs = get_slave_funcs(encoder); |
233 | 232 | ||
234 | *hfuncs = (struct drm_encoder_helper_funcs) { | 233 | *hfuncs = (struct drm_encoder_helper_funcs) { |
235 | .dpms = nv04_tv_dpms, | 234 | .dpms = nv04_tv_dpms, |
@@ -243,7 +242,6 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
243 | }; | 242 | }; |
244 | 243 | ||
245 | /* Attach it to the specified connector. */ | 244 | /* Attach it to the specified connector. */ |
246 | sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data); | ||
247 | sfuncs->create_resources(encoder, connector); | 245 | sfuncs->create_resources(encoder, connector); |
248 | drm_mode_connector_attach_encoder(connector, encoder); | 246 | drm_mode_connector_attach_encoder(connector, encoder); |
249 | 247 | ||
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index fcf2cdd19493..b2f6a57c0cc5 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c | |||
@@ -43,51 +43,51 @@ struct pipe_state { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static int nv10_graph_ctx_regs[] = { | 45 | static int nv10_graph_ctx_regs[] = { |
46 | NV10_PGRAPH_CTX_SWITCH1, | 46 | NV10_PGRAPH_CTX_SWITCH(0), |
47 | NV10_PGRAPH_CTX_SWITCH2, | 47 | NV10_PGRAPH_CTX_SWITCH(1), |
48 | NV10_PGRAPH_CTX_SWITCH3, | 48 | NV10_PGRAPH_CTX_SWITCH(2), |
49 | NV10_PGRAPH_CTX_SWITCH4, | 49 | NV10_PGRAPH_CTX_SWITCH(3), |
50 | NV10_PGRAPH_CTX_SWITCH5, | 50 | NV10_PGRAPH_CTX_SWITCH(4), |
51 | NV10_PGRAPH_CTX_CACHE1, /* 8 values from 0x400160 to 0x40017c */ | 51 | NV10_PGRAPH_CTX_CACHE(0, 0), |
52 | NV10_PGRAPH_CTX_CACHE2, /* 8 values from 0x400180 to 0x40019c */ | 52 | NV10_PGRAPH_CTX_CACHE(0, 1), |
53 | NV10_PGRAPH_CTX_CACHE3, /* 8 values from 0x4001a0 to 0x4001bc */ | 53 | NV10_PGRAPH_CTX_CACHE(0, 2), |
54 | NV10_PGRAPH_CTX_CACHE4, /* 8 values from 0x4001c0 to 0x4001dc */ | 54 | NV10_PGRAPH_CTX_CACHE(0, 3), |
55 | NV10_PGRAPH_CTX_CACHE5, /* 8 values from 0x4001e0 to 0x4001fc */ | 55 | NV10_PGRAPH_CTX_CACHE(0, 4), |
56 | 0x00400164, | 56 | NV10_PGRAPH_CTX_CACHE(1, 0), |
57 | 0x00400184, | 57 | NV10_PGRAPH_CTX_CACHE(1, 1), |
58 | 0x004001a4, | 58 | NV10_PGRAPH_CTX_CACHE(1, 2), |
59 | 0x004001c4, | 59 | NV10_PGRAPH_CTX_CACHE(1, 3), |
60 | 0x004001e4, | 60 | NV10_PGRAPH_CTX_CACHE(1, 4), |
61 | 0x00400168, | 61 | NV10_PGRAPH_CTX_CACHE(2, 0), |
62 | 0x00400188, | 62 | NV10_PGRAPH_CTX_CACHE(2, 1), |
63 | 0x004001a8, | 63 | NV10_PGRAPH_CTX_CACHE(2, 2), |
64 | 0x004001c8, | 64 | NV10_PGRAPH_CTX_CACHE(2, 3), |
65 | 0x004001e8, | 65 | NV10_PGRAPH_CTX_CACHE(2, 4), |
66 | 0x0040016c, | 66 | NV10_PGRAPH_CTX_CACHE(3, 0), |
67 | 0x0040018c, | 67 | NV10_PGRAPH_CTX_CACHE(3, 1), |
68 | 0x004001ac, | 68 | NV10_PGRAPH_CTX_CACHE(3, 2), |
69 | 0x004001cc, | 69 | NV10_PGRAPH_CTX_CACHE(3, 3), |
70 | 0x004001ec, | 70 | NV10_PGRAPH_CTX_CACHE(3, 4), |
71 | 0x00400170, | 71 | NV10_PGRAPH_CTX_CACHE(4, 0), |
72 | 0x00400190, | 72 | NV10_PGRAPH_CTX_CACHE(4, 1), |
73 | 0x004001b0, | 73 | NV10_PGRAPH_CTX_CACHE(4, 2), |
74 | 0x004001d0, | 74 | NV10_PGRAPH_CTX_CACHE(4, 3), |
75 | 0x004001f0, | 75 | NV10_PGRAPH_CTX_CACHE(4, 4), |
76 | 0x00400174, | 76 | NV10_PGRAPH_CTX_CACHE(5, 0), |
77 | 0x00400194, | 77 | NV10_PGRAPH_CTX_CACHE(5, 1), |
78 | 0x004001b4, | 78 | NV10_PGRAPH_CTX_CACHE(5, 2), |
79 | 0x004001d4, | 79 | NV10_PGRAPH_CTX_CACHE(5, 3), |
80 | 0x004001f4, | 80 | NV10_PGRAPH_CTX_CACHE(5, 4), |
81 | 0x00400178, | 81 | NV10_PGRAPH_CTX_CACHE(6, 0), |
82 | 0x00400198, | 82 | NV10_PGRAPH_CTX_CACHE(6, 1), |
83 | 0x004001b8, | 83 | NV10_PGRAPH_CTX_CACHE(6, 2), |
84 | 0x004001d8, | 84 | NV10_PGRAPH_CTX_CACHE(6, 3), |
85 | 0x004001f8, | 85 | NV10_PGRAPH_CTX_CACHE(6, 4), |
86 | 0x0040017c, | 86 | NV10_PGRAPH_CTX_CACHE(7, 0), |
87 | 0x0040019c, | 87 | NV10_PGRAPH_CTX_CACHE(7, 1), |
88 | 0x004001bc, | 88 | NV10_PGRAPH_CTX_CACHE(7, 2), |
89 | 0x004001dc, | 89 | NV10_PGRAPH_CTX_CACHE(7, 3), |
90 | 0x004001fc, | 90 | NV10_PGRAPH_CTX_CACHE(7, 4), |
91 | NV10_PGRAPH_CTX_USER, | 91 | NV10_PGRAPH_CTX_USER, |
92 | NV04_PGRAPH_DMA_START_0, | 92 | NV04_PGRAPH_DMA_START_0, |
93 | NV04_PGRAPH_DMA_START_1, | 93 | NV04_PGRAPH_DMA_START_1, |
@@ -653,6 +653,78 @@ static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) | |||
653 | return -1; | 653 | return -1; |
654 | } | 654 | } |
655 | 655 | ||
656 | static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, | ||
657 | uint32_t inst) | ||
658 | { | ||
659 | struct drm_device *dev = chan->dev; | ||
660 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
661 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
662 | uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; | ||
663 | uint32_t ctx_user, ctx_switch[5]; | ||
664 | int i, subchan = -1; | ||
665 | |||
666 | /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state | ||
667 | * that cannot be restored via MMIO. Do it through the FIFO | ||
668 | * instead. | ||
669 | */ | ||
670 | |||
671 | /* Look for a celsius object */ | ||
672 | for (i = 0; i < 8; i++) { | ||
673 | int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; | ||
674 | |||
675 | if (class == 0x56 || class == 0x96 || class == 0x99) { | ||
676 | subchan = i; | ||
677 | break; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | if (subchan < 0 || !inst) | ||
682 | return; | ||
683 | |||
684 | /* Save the current ctx object */ | ||
685 | ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER); | ||
686 | for (i = 0; i < 5; i++) | ||
687 | ctx_switch[i] = nv_rd32(dev, NV10_PGRAPH_CTX_SWITCH(i)); | ||
688 | |||
689 | /* Save the FIFO state */ | ||
690 | st2 = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); | ||
691 | st2_dl = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DL); | ||
692 | st2_dh = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DH); | ||
693 | fifo_ptr = nv_rd32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR); | ||
694 | |||
695 | for (i = 0; i < ARRAY_SIZE(fifo); i++) | ||
696 | fifo[i] = nv_rd32(dev, 0x4007a0 + 4 * i); | ||
697 | |||
698 | /* Switch to the celsius subchannel */ | ||
699 | for (i = 0; i < 5; i++) | ||
700 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), | ||
701 | nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(subchan, i))); | ||
702 | nv_mask(dev, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); | ||
703 | |||
704 | /* Inject NV10TCL_DMA_VTXBUF */ | ||
705 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); | ||
706 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, | ||
707 | 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); | ||
708 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); | ||
709 | nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); | ||
710 | pgraph->fifo_access(dev, true); | ||
711 | pgraph->fifo_access(dev, false); | ||
712 | |||
713 | /* Restore the FIFO state */ | ||
714 | for (i = 0; i < ARRAY_SIZE(fifo); i++) | ||
715 | nv_wr32(dev, 0x4007a0 + 4 * i, fifo[i]); | ||
716 | |||
717 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); | ||
718 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, st2); | ||
719 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); | ||
720 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); | ||
721 | |||
722 | /* Restore the current ctx object */ | ||
723 | for (i = 0; i < 5; i++) | ||
724 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); | ||
725 | nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user); | ||
726 | } | ||
727 | |||
656 | int nv10_graph_load_context(struct nouveau_channel *chan) | 728 | int nv10_graph_load_context(struct nouveau_channel *chan) |
657 | { | 729 | { |
658 | struct drm_device *dev = chan->dev; | 730 | struct drm_device *dev = chan->dev; |
@@ -670,6 +742,8 @@ int nv10_graph_load_context(struct nouveau_channel *chan) | |||
670 | } | 742 | } |
671 | 743 | ||
672 | nv10_graph_load_pipe(chan); | 744 | nv10_graph_load_pipe(chan); |
745 | nv10_graph_load_dma_vtxbuf(chan, (nv_rd32(dev, NV10_PGRAPH_GLOBALSTATE1) | ||
746 | & 0xffff)); | ||
673 | 747 | ||
674 | nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); | 748 | nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); |
675 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); | 749 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); |
@@ -856,11 +930,12 @@ int nv10_graph_init(struct drm_device *dev) | |||
856 | for (i = 0; i < NV10_PFB_TILE__SIZE; i++) | 930 | for (i = 0; i < NV10_PFB_TILE__SIZE; i++) |
857 | nv10_graph_set_region_tiling(dev, i, 0, 0, 0); | 931 | nv10_graph_set_region_tiling(dev, i, 0, 0, 0); |
858 | 932 | ||
859 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000); | 933 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); |
860 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000); | 934 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); |
861 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH3, 0x00000000); | 935 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); |
862 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH4, 0x00000000); | 936 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); |
863 | nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); | 937 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); |
938 | nv_wr32(dev, NV10_PGRAPH_STATE, 0xFFFFFFFF); | ||
864 | 939 | ||
865 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; | 940 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; |
866 | tmp |= (dev_priv->engine.fifo.channels - 1) << 24; | 941 | tmp |= (dev_priv->engine.fifo.channels - 1) << 24; |
diff --git a/drivers/gpu/drm/nouveau/nv30_fb.c b/drivers/gpu/drm/nouveau/nv30_fb.c index 9d35c8b3b839..4a3f2f095128 100644 --- a/drivers/gpu/drm/nouveau/nv30_fb.c +++ b/drivers/gpu/drm/nouveau/nv30_fb.c | |||
@@ -30,15 +30,25 @@ | |||
30 | #include "nouveau_drm.h" | 30 | #include "nouveau_drm.h" |
31 | 31 | ||
32 | static int | 32 | static int |
33 | calc_ref(int b, int l, int i) | 33 | calc_bias(struct drm_device *dev, int k, int i, int j) |
34 | { | ||
35 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
36 | int b = (dev_priv->chipset > 0x30 ? | ||
37 | nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : | ||
38 | 0) & 0xf; | ||
39 | |||
40 | return 2 * (b & 0x8 ? b - 0x10 : b); | ||
41 | } | ||
42 | |||
43 | static int | ||
44 | calc_ref(struct drm_device *dev, int l, int k, int i) | ||
34 | { | 45 | { |
35 | int j, x = 0; | 46 | int j, x = 0; |
36 | 47 | ||
37 | for (j = 0; j < 4; j++) { | 48 | for (j = 0; j < 4; j++) { |
38 | int n = (b >> (8 * j) & 0xf); | 49 | int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j); |
39 | int m = (l >> (8 * i) & 0xff) + 2 * (n & 0x8 ? n - 0x10 : n); | ||
40 | 50 | ||
41 | x |= (0x80 | (m & 0x1f)) << (8 * j); | 51 | x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); |
42 | } | 52 | } |
43 | 53 | ||
44 | return x; | 54 | return x; |
@@ -63,18 +73,16 @@ nv30_fb_init(struct drm_device *dev) | |||
63 | dev_priv->chipset == 0x35) { | 73 | dev_priv->chipset == 0x35) { |
64 | /* Related to ROP count */ | 74 | /* Related to ROP count */ |
65 | int n = (dev_priv->chipset == 0x31 ? 2 : 4); | 75 | int n = (dev_priv->chipset == 0x31 ? 2 : 4); |
66 | int b = (dev_priv->chipset > 0x30 ? | ||
67 | nv_rd32(dev, 0x122c) & 0xf : 0); | ||
68 | int l = nv_rd32(dev, 0x1003d0); | 76 | int l = nv_rd32(dev, 0x1003d0); |
69 | 77 | ||
70 | for (i = 0; i < n; i++) { | 78 | for (i = 0; i < n; i++) { |
71 | for (j = 0; j < 3; j++) | 79 | for (j = 0; j < 3; j++) |
72 | nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, | 80 | nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, |
73 | calc_ref(b, l, j)); | 81 | calc_ref(dev, l, 0, j)); |
74 | 82 | ||
75 | for (j = 0; j < 2; j++) | 83 | for (j = 0; j < 2; j++) |
76 | nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, | 84 | nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, |
77 | calc_ref(b, l, j)); | 85 | calc_ref(dev, l, 1, j)); |
78 | } | 86 | } |
79 | } | 87 | } |
80 | 88 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 5d11ea101666..bfd4ca2fe7ef 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -264,11 +264,16 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) | |||
264 | int | 264 | int |
265 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | 265 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) |
266 | { | 266 | { |
267 | uint32_t reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); | 267 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
268 | struct pll_lims pll; | 268 | struct pll_lims pll; |
269 | uint32_t reg1, reg2; | 269 | uint32_t reg, reg1, reg2; |
270 | int ret, N1, M1, N2, M2, P; | 270 | int ret, N1, M1, N2, M2, P; |
271 | 271 | ||
272 | if (dev_priv->chipset < NV_C0) | ||
273 | reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); | ||
274 | else | ||
275 | reg = 0x614140 + (head * 0x800); | ||
276 | |||
272 | ret = get_pll_limits(dev, reg, &pll); | 277 | ret = get_pll_limits(dev, reg, &pll); |
273 | if (ret) | 278 | if (ret) |
274 | return ret; | 279 | return ret; |
@@ -286,7 +291,8 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
286 | nv_wr32(dev, reg, 0x10000611); | 291 | nv_wr32(dev, reg, 0x10000611); |
287 | nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); | 292 | nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); |
288 | nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); | 293 | nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); |
289 | } else { | 294 | } else |
295 | if (dev_priv->chipset < NV_C0) { | ||
290 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | 296 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); |
291 | if (ret <= 0) | 297 | if (ret <= 0) |
292 | return 0; | 298 | return 0; |
@@ -298,6 +304,17 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
298 | nv_wr32(dev, reg, 0x50000610); | 304 | nv_wr32(dev, reg, 0x50000610); |
299 | nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); | 305 | nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); |
300 | nv_wr32(dev, reg + 8, N2); | 306 | nv_wr32(dev, reg + 8, N2); |
307 | } else { | ||
308 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | ||
309 | if (ret <= 0) | ||
310 | return 0; | ||
311 | |||
312 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", | ||
313 | pclk, ret, N1, N2, M1, P); | ||
314 | |||
315 | nv_mask(dev, reg + 0x0c, 0x00000000, 0x00000100); | ||
316 | nv_wr32(dev, reg + 0x04, (P << 16) | (N1 << 8) | M1); | ||
317 | nv_wr32(dev, reg + 0x10, N2 << 16); | ||
301 | } | 318 | } |
302 | 319 | ||
303 | return 0; | 320 | return 0; |
@@ -348,7 +365,7 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | |||
348 | 365 | ||
349 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); | 366 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); |
350 | if (!gem) | 367 | if (!gem) |
351 | return -EINVAL; | 368 | return -ENOENT; |
352 | cursor = nouveau_gem_object(gem); | 369 | cursor = nouveau_gem_object(gem); |
353 | 370 | ||
354 | ret = nouveau_bo_map(cursor); | 371 | ret = nouveau_bo_map(cursor); |
@@ -381,15 +398,12 @@ nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | |||
381 | 398 | ||
382 | static void | 399 | static void |
383 | nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, | 400 | nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, |
384 | uint32_t size) | 401 | uint32_t start, uint32_t size) |
385 | { | 402 | { |
403 | int end = (start + size > 256) ? 256 : start + size, i; | ||
386 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 404 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
387 | int i; | ||
388 | |||
389 | if (size != 256) | ||
390 | return; | ||
391 | 405 | ||
392 | for (i = 0; i < 256; i++) { | 406 | for (i = start; i < end; i++) { |
393 | nv_crtc->lut.r[i] = r[i]; | 407 | nv_crtc->lut.r[i] = r[i]; |
394 | nv_crtc->lut.g[i] = g[i]; | 408 | nv_crtc->lut.g[i] = g[i]; |
395 | nv_crtc->lut.b[i] = b[i]; | 409 | nv_crtc->lut.b[i] = b[i]; |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index f13ad0de9c8f..612fa6d6a0cb 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -76,7 +76,10 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, | |||
76 | nv_wo32(dev, obj, 2, offset); | 76 | nv_wo32(dev, obj, 2, offset); |
77 | nv_wo32(dev, obj, 3, 0x00000000); | 77 | nv_wo32(dev, obj, 3, 0x00000000); |
78 | nv_wo32(dev, obj, 4, 0x00000000); | 78 | nv_wo32(dev, obj, 4, 0x00000000); |
79 | nv_wo32(dev, obj, 5, 0x00010000); | 79 | if (dev_priv->card_type < NV_C0) |
80 | nv_wo32(dev, obj, 5, 0x00010000); | ||
81 | else | ||
82 | nv_wo32(dev, obj, 5, 0x00020000); | ||
80 | dev_priv->engine.instmem.flush(dev); | 83 | dev_priv->engine.instmem.flush(dev); |
81 | 84 | ||
82 | return 0; | 85 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c new file mode 100644 index 000000000000..26a996025dd2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_fb.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | int | ||
30 | nvc0_fb_init(struct drm_device *dev) | ||
31 | { | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | void | ||
36 | nvc0_fb_takedown(struct drm_device *dev) | ||
37 | { | ||
38 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c new file mode 100644 index 000000000000..d64375871979 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | void | ||
30 | nvc0_fifo_disable(struct drm_device *dev) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | void | ||
35 | nvc0_fifo_enable(struct drm_device *dev) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | bool | ||
40 | nvc0_fifo_reassign(struct drm_device *dev, bool enable) | ||
41 | { | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | bool | ||
46 | nvc0_fifo_cache_flush(struct drm_device *dev) | ||
47 | { | ||
48 | return true; | ||
49 | } | ||
50 | |||
51 | bool | ||
52 | nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) | ||
53 | { | ||
54 | return false; | ||
55 | } | ||
56 | |||
57 | int | ||
58 | nvc0_fifo_channel_id(struct drm_device *dev) | ||
59 | { | ||
60 | return 127; | ||
61 | } | ||
62 | |||
63 | int | ||
64 | nvc0_fifo_create_context(struct nouveau_channel *chan) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void | ||
70 | nvc0_fifo_destroy_context(struct nouveau_channel *chan) | ||
71 | { | ||
72 | } | ||
73 | |||
74 | int | ||
75 | nvc0_fifo_load_context(struct nouveau_channel *chan) | ||
76 | { | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | int | ||
81 | nvc0_fifo_unload_context(struct drm_device *dev) | ||
82 | { | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | void | ||
87 | nvc0_fifo_takedown(struct drm_device *dev) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | int | ||
92 | nvc0_fifo_init(struct drm_device *dev) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c new file mode 100644 index 000000000000..717a5177a8d8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | void | ||
30 | nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | struct nouveau_channel * | ||
35 | nvc0_graph_channel(struct drm_device *dev) | ||
36 | { | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | int | ||
41 | nvc0_graph_create_context(struct nouveau_channel *chan) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | void | ||
47 | nvc0_graph_destroy_context(struct nouveau_channel *chan) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | int | ||
52 | nvc0_graph_load_context(struct nouveau_channel *chan) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int | ||
58 | nvc0_graph_unload_context(struct drm_device *dev) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | void | ||
64 | nvc0_graph_takedown(struct drm_device *dev) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | int | ||
69 | nvc0_graph_init(struct drm_device *dev) | ||
70 | { | ||
71 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
72 | dev_priv->engine.graph.accel_blocked = true; | ||
73 | return 0; | ||
74 | } | ||
75 | |||
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c new file mode 100644 index 000000000000..3ab3cdc42173 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | int | ||
30 | nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, | ||
31 | uint32_t *size) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | *size = ALIGN(*size, 4096); | ||
36 | if (*size == 0) | ||
37 | return -EINVAL; | ||
38 | |||
39 | ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, | ||
40 | true, false, &gpuobj->im_backing); | ||
41 | if (ret) { | ||
42 | NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); | ||
47 | if (ret) { | ||
48 | NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); | ||
49 | nouveau_bo_ref(NULL, &gpuobj->im_backing); | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; | ||
54 | gpuobj->im_backing_start <<= PAGE_SHIFT; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | void | ||
59 | nvc0_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
60 | { | ||
61 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
62 | |||
63 | if (gpuobj && gpuobj->im_backing) { | ||
64 | if (gpuobj->im_bound) | ||
65 | dev_priv->engine.instmem.unbind(dev, gpuobj); | ||
66 | nouveau_bo_unpin(gpuobj->im_backing); | ||
67 | nouveau_bo_ref(NULL, &gpuobj->im_backing); | ||
68 | gpuobj->im_backing = NULL; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | int | ||
73 | nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
74 | { | ||
75 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
76 | uint32_t pte, pte_end; | ||
77 | uint64_t vram; | ||
78 | |||
79 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) | ||
80 | return -EINVAL; | ||
81 | |||
82 | NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", | ||
83 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); | ||
84 | |||
85 | pte = gpuobj->im_pramin->start >> 12; | ||
86 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; | ||
87 | vram = gpuobj->im_backing_start; | ||
88 | |||
89 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", | ||
90 | gpuobj->im_pramin->start, pte, pte_end); | ||
91 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | ||
92 | |||
93 | while (pte < pte_end) { | ||
94 | nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); | ||
95 | nv_wr32(dev, 0x702004 + (pte * 8), 0); | ||
96 | vram += 4096; | ||
97 | pte++; | ||
98 | } | ||
99 | dev_priv->engine.instmem.flush(dev); | ||
100 | |||
101 | if (1) { | ||
102 | u32 chan = nv_rd32(dev, 0x1700) << 16; | ||
103 | nv_wr32(dev, 0x100cb8, (chan + 0x1000) >> 8); | ||
104 | nv_wr32(dev, 0x100cbc, 0x80000005); | ||
105 | } | ||
106 | |||
107 | gpuobj->im_bound = 1; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | int | ||
112 | nvc0_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
113 | { | ||
114 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
115 | uint32_t pte, pte_end; | ||
116 | |||
117 | if (gpuobj->im_bound == 0) | ||
118 | return -EINVAL; | ||
119 | |||
120 | pte = gpuobj->im_pramin->start >> 12; | ||
121 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; | ||
122 | while (pte < pte_end) { | ||
123 | nv_wr32(dev, 0x702000 + (pte * 8), 0); | ||
124 | nv_wr32(dev, 0x702004 + (pte * 8), 0); | ||
125 | pte++; | ||
126 | } | ||
127 | dev_priv->engine.instmem.flush(dev); | ||
128 | |||
129 | gpuobj->im_bound = 0; | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | void | ||
134 | nvc0_instmem_flush(struct drm_device *dev) | ||
135 | { | ||
136 | nv_wr32(dev, 0x070000, 1); | ||
137 | if (!nv_wait(0x070000, 0x00000002, 0x00000000)) | ||
138 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | ||
139 | } | ||
140 | |||
141 | int | ||
142 | nvc0_instmem_suspend(struct drm_device *dev) | ||
143 | { | ||
144 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
145 | int i; | ||
146 | |||
147 | dev_priv->susres.ramin_copy = vmalloc(65536); | ||
148 | if (!dev_priv->susres.ramin_copy) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | for (i = 0x700000; i < 0x710000; i += 4) | ||
152 | dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | void | ||
157 | nvc0_instmem_resume(struct drm_device *dev) | ||
158 | { | ||
159 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
160 | u64 chan; | ||
161 | int i; | ||
162 | |||
163 | chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; | ||
164 | nv_wr32(dev, 0x001700, chan >> 16); | ||
165 | |||
166 | for (i = 0x700000; i < 0x710000; i += 4) | ||
167 | nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]); | ||
168 | vfree(dev_priv->susres.ramin_copy); | ||
169 | dev_priv->susres.ramin_copy = NULL; | ||
170 | |||
171 | nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); | ||
172 | } | ||
173 | |||
174 | int | ||
175 | nvc0_instmem_init(struct drm_device *dev) | ||
176 | { | ||
177 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
178 | u64 chan, pgt3, imem, lim3 = dev_priv->ramin_size - 1; | ||
179 | int ret, i; | ||
180 | |||
181 | dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; | ||
182 | chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; | ||
183 | imem = 4096 + 4096 + 32768; | ||
184 | |||
185 | nv_wr32(dev, 0x001700, chan >> 16); | ||
186 | |||
187 | /* channel setup */ | ||
188 | nv_wr32(dev, 0x700200, lower_32_bits(chan + 0x1000)); | ||
189 | nv_wr32(dev, 0x700204, upper_32_bits(chan + 0x1000)); | ||
190 | nv_wr32(dev, 0x700208, lower_32_bits(lim3)); | ||
191 | nv_wr32(dev, 0x70020c, upper_32_bits(lim3)); | ||
192 | |||
193 | /* point pgd -> pgt */ | ||
194 | nv_wr32(dev, 0x701000, 0); | ||
195 | nv_wr32(dev, 0x701004, ((chan + 0x2000) >> 8) | 1); | ||
196 | |||
197 | /* point pgt -> physical vram for channel */ | ||
198 | pgt3 = 0x2000; | ||
199 | for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4096, pgt3 += 8) { | ||
200 | nv_wr32(dev, 0x700000 + pgt3, ((chan + i) >> 8) | 1); | ||
201 | nv_wr32(dev, 0x700004 + pgt3, 0); | ||
202 | } | ||
203 | |||
204 | /* clear rest of pgt */ | ||
205 | for (; i < dev_priv->ramin_size; i += 4096, pgt3 += 8) { | ||
206 | nv_wr32(dev, 0x700000 + pgt3, 0); | ||
207 | nv_wr32(dev, 0x700004 + pgt3, 0); | ||
208 | } | ||
209 | |||
210 | /* point bar3 at the channel */ | ||
211 | nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); | ||
212 | |||
213 | /* Global PRAMIN heap */ | ||
214 | ret = drm_mm_init(&dev_priv->ramin_heap, imem, | ||
215 | dev_priv->ramin_size - imem); | ||
216 | if (ret) { | ||
217 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | |||
221 | /*XXX: incorrect, but needed to make hash func "work" */ | ||
222 | dev_priv->ramht_offset = 0x10000; | ||
223 | dev_priv->ramht_bits = 9; | ||
224 | dev_priv->ramht_size = (1 << dev_priv->ramht_bits); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | void | ||
229 | nvc0_instmem_takedown(struct drm_device *dev) | ||
230 | { | ||
231 | } | ||
232 | |||
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index 68e6f4349309..4f4cd8b286d5 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c | |||
@@ -200,7 +200,7 @@ int r600_page_table_init(struct drm_device *dev) | |||
200 | entry->pagelist[i], 0, | 200 | entry->pagelist[i], 0, |
201 | PAGE_SIZE, | 201 | PAGE_SIZE, |
202 | PCI_DMA_BIDIRECTIONAL); | 202 | PCI_DMA_BIDIRECTIONAL); |
203 | if (entry->busaddr[i] == 0) { | 203 | if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) { |
204 | DRM_ERROR("unable to map PCIGART pages!\n"); | 204 | DRM_ERROR("unable to map PCIGART pages!\n"); |
205 | r600_page_table_cleanup(dev, gart_info); | 205 | r600_page_table_cleanup(dev, gart_info); |
206 | goto done; | 206 | goto done; |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index c3ea212e0c3c..d8864949e387 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -133,6 +133,7 @@ static inline int r600_bpe_from_format(u32 *bpe, u32 format) | |||
133 | case V_038004_FMT_GB_GR: | 133 | case V_038004_FMT_GB_GR: |
134 | case V_038004_FMT_BG_RG: | 134 | case V_038004_FMT_BG_RG: |
135 | case V_038004_COLOR_INVALID: | 135 | case V_038004_COLOR_INVALID: |
136 | default: | ||
136 | *bpe = 16; | 137 | *bpe = 16; |
137 | return -EINVAL; | 138 | return -EINVAL; |
138 | } | 139 | } |
@@ -174,7 +175,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | |||
174 | dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); | 175 | dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); |
175 | return -EINVAL; | 176 | return -EINVAL; |
176 | } | 177 | } |
177 | size = radeon_bo_size(track->cb_color_bo[i]); | 178 | size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; |
178 | if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) { | 179 | if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) { |
179 | dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", | 180 | dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", |
180 | __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]), | 181 | __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]), |
@@ -327,7 +328,6 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) | |||
327 | dev_warn(p->dev, "z/stencil buffer size not set\n"); | 328 | dev_warn(p->dev, "z/stencil buffer size not set\n"); |
328 | return -EINVAL; | 329 | return -EINVAL; |
329 | } | 330 | } |
330 | printk_once(KERN_WARNING "You have old & broken userspace please consider updating mesa\n"); | ||
331 | tmp = radeon_bo_size(track->db_bo) - track->db_offset; | 331 | tmp = radeon_bo_size(track->db_bo) - track->db_offset; |
332 | tmp = (tmp / bpe) >> 6; | 332 | tmp = (tmp / bpe) >> 6; |
333 | if (!tmp) { | 333 | if (!tmp) { |
@@ -882,8 +882,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
882 | return -EINVAL; | 882 | return -EINVAL; |
883 | } | 883 | } |
884 | ib[idx] = track->cb_color_base_last[tmp]; | 884 | ib[idx] = track->cb_color_base_last[tmp]; |
885 | printk_once(KERN_WARNING "You have old & broken userspace " | ||
886 | "please consider updating mesa & xf86-video-ati\n"); | ||
887 | track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; | 885 | track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; |
888 | } else { | 886 | } else { |
889 | r = r600_cs_packet_next_reloc(p, &reloc); | 887 | r = r600_cs_packet_next_reloc(p, &reloc); |
@@ -910,8 +908,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
910 | return -EINVAL; | 908 | return -EINVAL; |
911 | } | 909 | } |
912 | ib[idx] = track->cb_color_base_last[tmp]; | 910 | ib[idx] = track->cb_color_base_last[tmp]; |
913 | printk_once(KERN_WARNING "You have old & broken userspace " | ||
914 | "please consider updating mesa & xf86-video-ati\n"); | ||
915 | track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; | 911 | track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; |
916 | } else { | 912 | } else { |
917 | r = r600_cs_packet_next_reloc(p, &reloc); | 913 | r = r600_cs_packet_next_reloc(p, &reloc); |
@@ -938,7 +934,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
938 | return -EINVAL; | 934 | return -EINVAL; |
939 | } | 935 | } |
940 | tmp = (reg - CB_COLOR0_BASE) / 4; | 936 | tmp = (reg - CB_COLOR0_BASE) / 4; |
941 | track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); | 937 | track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; |
942 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 938 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
943 | track->cb_color_base_last[tmp] = ib[idx]; | 939 | track->cb_color_base_last[tmp] = ib[idx]; |
944 | track->cb_color_bo[tmp] = reloc->robj; | 940 | track->cb_color_bo[tmp] = reloc->robj; |
@@ -950,7 +946,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
950 | "0x%04X\n", reg); | 946 | "0x%04X\n", reg); |
951 | return -EINVAL; | 947 | return -EINVAL; |
952 | } | 948 | } |
953 | track->db_offset = radeon_get_ib_value(p, idx); | 949 | track->db_offset = radeon_get_ib_value(p, idx) << 8; |
954 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 950 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
955 | track->db_bo = reloc->robj; | 951 | track->db_bo = reloc->robj; |
956 | break; | 952 | break; |
@@ -1055,10 +1051,10 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels | |||
1055 | } | 1051 | } |
1056 | *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; | 1052 | *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; |
1057 | *mipmap_size = offset; | 1053 | *mipmap_size = offset; |
1058 | if (!blevel) | ||
1059 | *mipmap_size -= *l0_size; | ||
1060 | if (!nlevels) | 1054 | if (!nlevels) |
1061 | *mipmap_size = *l0_size; | 1055 | *mipmap_size = *l0_size; |
1056 | if (!blevel) | ||
1057 | *mipmap_size -= *l0_size; | ||
1062 | } | 1058 | } |
1063 | 1059 | ||
1064 | /** | 1060 | /** |
@@ -1165,14 +1161,14 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1165 | (pitch_align * bpe), | 1161 | (pitch_align * bpe), |
1166 | &l0_size, &mipmap_size); | 1162 | &l0_size, &mipmap_size); |
1167 | /* using get ib will give us the offset into the texture bo */ | 1163 | /* using get ib will give us the offset into the texture bo */ |
1168 | word0 = radeon_get_ib_value(p, idx + 2); | 1164 | word0 = radeon_get_ib_value(p, idx + 2) << 8; |
1169 | if ((l0_size + word0) > radeon_bo_size(texture)) { | 1165 | if ((l0_size + word0) > radeon_bo_size(texture)) { |
1170 | dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", | 1166 | dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", |
1171 | w0, h0, bpe, word0, l0_size, radeon_bo_size(texture)); | 1167 | w0, h0, bpe, word0, l0_size, radeon_bo_size(texture)); |
1172 | return -EINVAL; | 1168 | return -EINVAL; |
1173 | } | 1169 | } |
1174 | /* using get ib will give us the offset into the mipmap bo */ | 1170 | /* using get ib will give us the offset into the mipmap bo */ |
1175 | word0 = radeon_get_ib_value(p, idx + 3); | 1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; |
1176 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { | 1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { |
1177 | dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", | 1173 | dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", |
1178 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); | 1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); |
@@ -1366,7 +1362,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1366 | } | 1362 | } |
1367 | for (i = 0; i < (pkt->count / 7); i++) { | 1363 | for (i = 0; i < (pkt->count / 7); i++) { |
1368 | struct radeon_bo *texture, *mipmap; | 1364 | struct radeon_bo *texture, *mipmap; |
1369 | u32 size, offset; | 1365 | u32 size, offset, base_offset, mip_offset; |
1370 | 1366 | ||
1371 | switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) { | 1367 | switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) { |
1372 | case SQ_TEX_VTX_VALID_TEXTURE: | 1368 | case SQ_TEX_VTX_VALID_TEXTURE: |
@@ -1376,7 +1372,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1376 | DRM_ERROR("bad SET_RESOURCE\n"); | 1372 | DRM_ERROR("bad SET_RESOURCE\n"); |
1377 | return -EINVAL; | 1373 | return -EINVAL; |
1378 | } | 1374 | } |
1379 | ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 1375 | base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
1380 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | 1376 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) |
1381 | ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); | 1377 | ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); |
1382 | else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) | 1378 | else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) |
@@ -1388,12 +1384,14 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1388 | DRM_ERROR("bad SET_RESOURCE\n"); | 1384 | DRM_ERROR("bad SET_RESOURCE\n"); |
1389 | return -EINVAL; | 1385 | return -EINVAL; |
1390 | } | 1386 | } |
1391 | ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | 1387 | mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); |
1392 | mipmap = reloc->robj; | 1388 | mipmap = reloc->robj; |
1393 | r = r600_check_texture_resource(p, idx+(i*7)+1, | 1389 | r = r600_check_texture_resource(p, idx+(i*7)+1, |
1394 | texture, mipmap, reloc->lobj.tiling_flags); | 1390 | texture, mipmap, reloc->lobj.tiling_flags); |
1395 | if (r) | 1391 | if (r) |
1396 | return r; | 1392 | return r; |
1393 | ib[idx+1+(i*7)+2] += base_offset; | ||
1394 | ib[idx+1+(i*7)+3] += mip_offset; | ||
1397 | break; | 1395 | break; |
1398 | case SQ_TEX_VTX_VALID_BUFFER: | 1396 | case SQ_TEX_VTX_VALID_BUFFER: |
1399 | /* vtx base */ | 1397 | /* vtx base */ |
@@ -1403,10 +1401,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1403 | return -EINVAL; | 1401 | return -EINVAL; |
1404 | } | 1402 | } |
1405 | offset = radeon_get_ib_value(p, idx+1+(i*7)+0); | 1403 | offset = radeon_get_ib_value(p, idx+1+(i*7)+0); |
1406 | size = radeon_get_ib_value(p, idx+1+(i*7)+1); | 1404 | size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1; |
1407 | if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { | 1405 | if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { |
1408 | /* force size to size of the buffer */ | 1406 | /* force size to size of the buffer */ |
1409 | dev_warn(p->dev, "vbo resource seems too big for the bo\n"); | 1407 | dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n", |
1408 | size + offset, radeon_bo_size(reloc->robj)); | ||
1410 | ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj); | 1409 | ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj); |
1411 | } | 1410 | } |
1412 | ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); | 1411 | ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3cd1c470b777..3dfcfa3ca425 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1100,6 +1100,8 @@ struct radeon_device { | |||
1100 | struct notifier_block acpi_nb; | 1100 | struct notifier_block acpi_nb; |
1101 | /* only one userspace can use Hyperz features at a time */ | 1101 | /* only one userspace can use Hyperz features at a time */ |
1102 | struct drm_file *hyperz_filp; | 1102 | struct drm_file *hyperz_filp; |
1103 | /* i2c buses */ | ||
1104 | struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS]; | ||
1103 | }; | 1105 | }; |
1104 | 1106 | ||
1105 | int radeon_device_init(struct radeon_device *rdev, | 1107 | int radeon_device_init(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 3bc2bcdf5308..6d30868744ee 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -48,7 +48,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
48 | struct radeon_i2c_bus_rec *i2c_bus, | 48 | struct radeon_i2c_bus_rec *i2c_bus, |
49 | bool linkb, uint32_t igp_lane_info, | 49 | bool linkb, uint32_t igp_lane_info, |
50 | uint16_t connector_object_id, | 50 | uint16_t connector_object_id, |
51 | struct radeon_hpd *hpd); | 51 | struct radeon_hpd *hpd, |
52 | struct radeon_router *router); | ||
52 | 53 | ||
53 | /* from radeon_legacy_encoder.c */ | 54 | /* from radeon_legacy_encoder.c */ |
54 | extern void | 55 | extern void |
@@ -114,7 +115,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev | |||
114 | 115 | ||
115 | i2c.i2c_id = gpio->sucI2cId.ucAccess; | 116 | i2c.i2c_id = gpio->sucI2cId.ucAccess; |
116 | 117 | ||
117 | i2c.valid = true; | 118 | if (i2c.mask_clk_reg) |
119 | i2c.valid = true; | ||
118 | break; | 120 | break; |
119 | } | 121 | } |
120 | } | 122 | } |
@@ -123,6 +125,66 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev | |||
123 | return i2c; | 125 | return i2c; |
124 | } | 126 | } |
125 | 127 | ||
128 | void radeon_atombios_i2c_init(struct radeon_device *rdev) | ||
129 | { | ||
130 | struct atom_context *ctx = rdev->mode_info.atom_context; | ||
131 | ATOM_GPIO_I2C_ASSIGMENT *gpio; | ||
132 | struct radeon_i2c_bus_rec i2c; | ||
133 | int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); | ||
134 | struct _ATOM_GPIO_I2C_INFO *i2c_info; | ||
135 | uint16_t data_offset, size; | ||
136 | int i, num_indices; | ||
137 | char stmp[32]; | ||
138 | |||
139 | memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); | ||
140 | |||
141 | if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { | ||
142 | i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); | ||
143 | |||
144 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
145 | sizeof(ATOM_GPIO_I2C_ASSIGMENT); | ||
146 | |||
147 | for (i = 0; i < num_indices; i++) { | ||
148 | gpio = &i2c_info->asGPIO_Info[i]; | ||
149 | i2c.valid = false; | ||
150 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; | ||
151 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; | ||
152 | i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; | ||
153 | i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; | ||
154 | i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; | ||
155 | i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; | ||
156 | i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; | ||
157 | i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; | ||
158 | i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); | ||
159 | i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); | ||
160 | i2c.en_clk_mask = (1 << gpio->ucClkEnShift); | ||
161 | i2c.en_data_mask = (1 << gpio->ucDataEnShift); | ||
162 | i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); | ||
163 | i2c.y_data_mask = (1 << gpio->ucDataY_Shift); | ||
164 | i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); | ||
165 | i2c.a_data_mask = (1 << gpio->ucDataA_Shift); | ||
166 | |||
167 | if (gpio->sucI2cId.sbfAccess.bfHW_Capable) | ||
168 | i2c.hw_capable = true; | ||
169 | else | ||
170 | i2c.hw_capable = false; | ||
171 | |||
172 | if (gpio->sucI2cId.ucAccess == 0xa0) | ||
173 | i2c.mm_i2c = true; | ||
174 | else | ||
175 | i2c.mm_i2c = false; | ||
176 | |||
177 | i2c.i2c_id = gpio->sucI2cId.ucAccess; | ||
178 | |||
179 | if (i2c.mask_clk_reg) { | ||
180 | i2c.valid = true; | ||
181 | sprintf(stmp, "0x%x", i2c.i2c_id); | ||
182 | rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | |||
126 | static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, | 188 | static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, |
127 | u8 id) | 189 | u8 id) |
128 | { | 190 | { |
@@ -206,6 +268,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
206 | uint16_t *line_mux, | 268 | uint16_t *line_mux, |
207 | struct radeon_hpd *hpd) | 269 | struct radeon_hpd *hpd) |
208 | { | 270 | { |
271 | struct radeon_device *rdev = dev->dev_private; | ||
209 | 272 | ||
210 | /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ | 273 | /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ |
211 | if ((dev->pdev->device == 0x791e) && | 274 | if ((dev->pdev->device == 0x791e) && |
@@ -308,13 +371,22 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
308 | } | 371 | } |
309 | } | 372 | } |
310 | 373 | ||
311 | /* Acer laptop reports DVI-D as DVI-I */ | 374 | /* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */ |
312 | if ((dev->pdev->device == 0x95c4) && | 375 | if ((dev->pdev->device == 0x95c4) && |
313 | (dev->pdev->subsystem_vendor == 0x1025) && | 376 | (dev->pdev->subsystem_vendor == 0x1025) && |
314 | (dev->pdev->subsystem_device == 0x013c)) { | 377 | (dev->pdev->subsystem_device == 0x013c)) { |
378 | struct radeon_gpio_rec gpio; | ||
379 | |||
315 | if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && | 380 | if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && |
316 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) | 381 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { |
382 | gpio = radeon_lookup_gpio(rdev, 6); | ||
383 | *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); | ||
317 | *connector_type = DRM_MODE_CONNECTOR_DVID; | 384 | *connector_type = DRM_MODE_CONNECTOR_DVID; |
385 | } else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && | ||
386 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { | ||
387 | gpio = radeon_lookup_gpio(rdev, 7); | ||
388 | *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); | ||
389 | } | ||
318 | } | 390 | } |
319 | 391 | ||
320 | /* XFX Pine Group device rv730 reports no VGA DDC lines | 392 | /* XFX Pine Group device rv730 reports no VGA DDC lines |
@@ -399,13 +471,15 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
399 | u16 size, data_offset; | 471 | u16 size, data_offset; |
400 | u8 frev, crev; | 472 | u8 frev, crev; |
401 | ATOM_CONNECTOR_OBJECT_TABLE *con_obj; | 473 | ATOM_CONNECTOR_OBJECT_TABLE *con_obj; |
474 | ATOM_OBJECT_TABLE *router_obj; | ||
402 | ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; | 475 | ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; |
403 | ATOM_OBJECT_HEADER *obj_header; | 476 | ATOM_OBJECT_HEADER *obj_header; |
404 | int i, j, path_size, device_support; | 477 | int i, j, k, path_size, device_support; |
405 | int connector_type; | 478 | int connector_type; |
406 | u16 igp_lane_info, conn_id, connector_object_id; | 479 | u16 igp_lane_info, conn_id, connector_object_id; |
407 | bool linkb; | 480 | bool linkb; |
408 | struct radeon_i2c_bus_rec ddc_bus; | 481 | struct radeon_i2c_bus_rec ddc_bus; |
482 | struct radeon_router router; | ||
409 | struct radeon_gpio_rec gpio; | 483 | struct radeon_gpio_rec gpio; |
410 | struct radeon_hpd hpd; | 484 | struct radeon_hpd hpd; |
411 | 485 | ||
@@ -415,6 +489,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
415 | if (crev < 2) | 489 | if (crev < 2) |
416 | return false; | 490 | return false; |
417 | 491 | ||
492 | router.valid = false; | ||
493 | |||
418 | obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); | 494 | obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); |
419 | path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) | 495 | path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) |
420 | (ctx->bios + data_offset + | 496 | (ctx->bios + data_offset + |
@@ -422,6 +498,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
422 | con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) | 498 | con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) |
423 | (ctx->bios + data_offset + | 499 | (ctx->bios + data_offset + |
424 | le16_to_cpu(obj_header->usConnectorObjectTableOffset)); | 500 | le16_to_cpu(obj_header->usConnectorObjectTableOffset)); |
501 | router_obj = (ATOM_OBJECT_TABLE *) | ||
502 | (ctx->bios + data_offset + | ||
503 | le16_to_cpu(obj_header->usRouterObjectTableOffset)); | ||
425 | device_support = le16_to_cpu(obj_header->usDeviceSupport); | 504 | device_support = le16_to_cpu(obj_header->usDeviceSupport); |
426 | 505 | ||
427 | path_size = 0; | 506 | path_size = 0; |
@@ -508,33 +587,86 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
508 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) | 587 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
509 | continue; | 588 | continue; |
510 | 589 | ||
511 | for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); | 590 | for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { |
512 | j++) { | 591 | uint8_t grph_obj_id, grph_obj_num, grph_obj_type; |
513 | uint8_t enc_obj_id, enc_obj_num, enc_obj_type; | ||
514 | 592 | ||
515 | enc_obj_id = | 593 | grph_obj_id = |
516 | (le16_to_cpu(path->usGraphicObjIds[j]) & | 594 | (le16_to_cpu(path->usGraphicObjIds[j]) & |
517 | OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; | 595 | OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; |
518 | enc_obj_num = | 596 | grph_obj_num = |
519 | (le16_to_cpu(path->usGraphicObjIds[j]) & | 597 | (le16_to_cpu(path->usGraphicObjIds[j]) & |
520 | ENUM_ID_MASK) >> ENUM_ID_SHIFT; | 598 | ENUM_ID_MASK) >> ENUM_ID_SHIFT; |
521 | enc_obj_type = | 599 | grph_obj_type = |
522 | (le16_to_cpu(path->usGraphicObjIds[j]) & | 600 | (le16_to_cpu(path->usGraphicObjIds[j]) & |
523 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; | 601 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; |
524 | 602 | ||
525 | /* FIXME: add support for router objects */ | 603 | if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { |
526 | if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { | 604 | if (grph_obj_num == 2) |
527 | if (enc_obj_num == 2) | ||
528 | linkb = true; | 605 | linkb = true; |
529 | else | 606 | else |
530 | linkb = false; | 607 | linkb = false; |
531 | 608 | ||
532 | radeon_add_atom_encoder(dev, | 609 | radeon_add_atom_encoder(dev, |
533 | enc_obj_id, | 610 | grph_obj_id, |
534 | le16_to_cpu | 611 | le16_to_cpu |
535 | (path-> | 612 | (path-> |
536 | usDeviceTag)); | 613 | usDeviceTag)); |
537 | 614 | ||
615 | } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { | ||
616 | router.valid = false; | ||
617 | for (k = 0; k < router_obj->ucNumberOfObjects; k++) { | ||
618 | u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID); | ||
619 | if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { | ||
620 | ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) | ||
621 | (ctx->bios + data_offset + | ||
622 | le16_to_cpu(router_obj->asObjects[k].usRecordOffset)); | ||
623 | ATOM_I2C_RECORD *i2c_record; | ||
624 | ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; | ||
625 | ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; | ||
626 | ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = | ||
627 | (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) | ||
628 | (ctx->bios + data_offset + | ||
629 | le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); | ||
630 | int enum_id; | ||
631 | |||
632 | router.router_id = router_obj_id; | ||
633 | for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst; | ||
634 | enum_id++) { | ||
635 | if (le16_to_cpu(path->usConnObjectId) == | ||
636 | le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id])) | ||
637 | break; | ||
638 | } | ||
639 | |||
640 | while (record->ucRecordType > 0 && | ||
641 | record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { | ||
642 | switch (record->ucRecordType) { | ||
643 | case ATOM_I2C_RECORD_TYPE: | ||
644 | i2c_record = | ||
645 | (ATOM_I2C_RECORD *) | ||
646 | record; | ||
647 | i2c_config = | ||
648 | (ATOM_I2C_ID_CONFIG_ACCESS *) | ||
649 | &i2c_record->sucI2cId; | ||
650 | router.i2c_info = | ||
651 | radeon_lookup_i2c_gpio(rdev, | ||
652 | i2c_config-> | ||
653 | ucAccess); | ||
654 | router.i2c_addr = i2c_record->ucI2CAddr >> 1; | ||
655 | break; | ||
656 | case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: | ||
657 | ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) | ||
658 | record; | ||
659 | router.valid = true; | ||
660 | router.mux_type = ddc_path->ucMuxType; | ||
661 | router.mux_control_pin = ddc_path->ucMuxControlPin; | ||
662 | router.mux_state = ddc_path->ucMuxState[enum_id]; | ||
663 | break; | ||
664 | } | ||
665 | record = (ATOM_COMMON_RECORD_HEADER *) | ||
666 | ((char *)record + record->ucRecordSize); | ||
667 | } | ||
668 | } | ||
669 | } | ||
538 | } | 670 | } |
539 | } | 671 | } |
540 | 672 | ||
@@ -614,7 +746,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
614 | connector_type, &ddc_bus, | 746 | connector_type, &ddc_bus, |
615 | linkb, igp_lane_info, | 747 | linkb, igp_lane_info, |
616 | connector_object_id, | 748 | connector_object_id, |
617 | &hpd); | 749 | &hpd, |
750 | &router); | ||
618 | 751 | ||
619 | } | 752 | } |
620 | } | 753 | } |
@@ -691,6 +824,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
691 | int i, j, max_device; | 824 | int i, j, max_device; |
692 | struct bios_connector *bios_connectors; | 825 | struct bios_connector *bios_connectors; |
693 | size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; | 826 | size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; |
827 | struct radeon_router router; | ||
828 | |||
829 | router.valid = false; | ||
694 | 830 | ||
695 | bios_connectors = kzalloc(bc_size, GFP_KERNEL); | 831 | bios_connectors = kzalloc(bc_size, GFP_KERNEL); |
696 | if (!bios_connectors) | 832 | if (!bios_connectors) |
@@ -862,7 +998,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
862 | &bios_connectors[i].ddc_bus, | 998 | &bios_connectors[i].ddc_bus, |
863 | false, 0, | 999 | false, 0, |
864 | connector_object_id, | 1000 | connector_object_id, |
865 | &bios_connectors[i].hpd); | 1001 | &bios_connectors[i].hpd, |
1002 | &router); | ||
866 | } | 1003 | } |
867 | } | 1004 | } |
868 | 1005 | ||
@@ -1521,7 +1658,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1521 | thermal_controller_names[power_info->info.ucOverdriveThermalController], | 1658 | thermal_controller_names[power_info->info.ucOverdriveThermalController], |
1522 | power_info->info.ucOverdriveControllerAddress >> 1); | 1659 | power_info->info.ucOverdriveControllerAddress >> 1); |
1523 | i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); | 1660 | i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); |
1524 | rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal"); | 1661 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1525 | if (rdev->pm.i2c_bus) { | 1662 | if (rdev->pm.i2c_bus) { |
1526 | struct i2c_board_info info = { }; | 1663 | struct i2c_board_info info = { }; |
1527 | const char *name = thermal_controller_names[power_info->info. | 1664 | const char *name = thermal_controller_names[power_info->info. |
@@ -1814,7 +1951,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1814 | (controller->ucFanParameters & | 1951 | (controller->ucFanParameters & |
1815 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | 1952 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); |
1816 | i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); | 1953 | i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); |
1817 | rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal"); | 1954 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1818 | if (rdev->pm.i2c_bus) { | 1955 | if (rdev->pm.i2c_bus) { |
1819 | struct i2c_board_info info = { }; | 1956 | struct i2c_board_info info = { }; |
1820 | const char *name = pp_lib_thermal_controller_names[controller->ucType]; | 1957 | const char *name = pp_lib_thermal_controller_names[controller->ucType]; |
@@ -1927,6 +2064,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1927 | rdev->pm.power_state[state_index].type = | 2064 | rdev->pm.power_state[state_index].type = |
1928 | POWER_STATE_TYPE_PERFORMANCE; | 2065 | POWER_STATE_TYPE_PERFORMANCE; |
1929 | break; | 2066 | break; |
2067 | case ATOM_PPLIB_CLASSIFICATION_UI_NONE: | ||
2068 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) | ||
2069 | rdev->pm.power_state[state_index].type = | ||
2070 | POWER_STATE_TYPE_PERFORMANCE; | ||
2071 | break; | ||
1930 | } | 2072 | } |
1931 | rdev->pm.power_state[state_index].flags = 0; | 2073 | rdev->pm.power_state[state_index].flags = 0; |
1932 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) | 2074 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) |
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index f64936cc4dd9..14448a740ba6 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c | |||
@@ -91,6 +91,85 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) | |||
91 | return mclk; | 91 | return mclk; |
92 | } | 92 | } |
93 | 93 | ||
94 | #ifdef CONFIG_OF | ||
95 | /* | ||
96 | * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device | ||
97 | * tree. Hopefully, ATI OF driver is kind enough to fill these | ||
98 | */ | ||
99 | static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) | ||
100 | { | ||
101 | struct radeon_device *rdev = dev->dev_private; | ||
102 | struct device_node *dp = rdev->pdev->dev.of_node; | ||
103 | const u32 *val; | ||
104 | struct radeon_pll *p1pll = &rdev->clock.p1pll; | ||
105 | struct radeon_pll *p2pll = &rdev->clock.p2pll; | ||
106 | struct radeon_pll *spll = &rdev->clock.spll; | ||
107 | struct radeon_pll *mpll = &rdev->clock.mpll; | ||
108 | |||
109 | if (dp == NULL) | ||
110 | return false; | ||
111 | val = of_get_property(dp, "ATY,RefCLK", NULL); | ||
112 | if (!val || !*val) { | ||
113 | printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); | ||
114 | return false; | ||
115 | } | ||
116 | p1pll->reference_freq = p2pll->reference_freq = (*val) / 10; | ||
117 | p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; | ||
118 | if (p1pll->reference_div < 2) | ||
119 | p1pll->reference_div = 12; | ||
120 | p2pll->reference_div = p1pll->reference_div; | ||
121 | |||
122 | /* These aren't in the device-tree */ | ||
123 | if (rdev->family >= CHIP_R420) { | ||
124 | p1pll->pll_in_min = 100; | ||
125 | p1pll->pll_in_max = 1350; | ||
126 | p1pll->pll_out_min = 20000; | ||
127 | p1pll->pll_out_max = 50000; | ||
128 | p2pll->pll_in_min = 100; | ||
129 | p2pll->pll_in_max = 1350; | ||
130 | p2pll->pll_out_min = 20000; | ||
131 | p2pll->pll_out_max = 50000; | ||
132 | } else { | ||
133 | p1pll->pll_in_min = 40; | ||
134 | p1pll->pll_in_max = 500; | ||
135 | p1pll->pll_out_min = 12500; | ||
136 | p1pll->pll_out_max = 35000; | ||
137 | p2pll->pll_in_min = 40; | ||
138 | p2pll->pll_in_max = 500; | ||
139 | p2pll->pll_out_min = 12500; | ||
140 | p2pll->pll_out_max = 35000; | ||
141 | } | ||
142 | |||
143 | spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; | ||
144 | spll->reference_div = mpll->reference_div = | ||
145 | RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & | ||
146 | RADEON_M_SPLL_REF_DIV_MASK; | ||
147 | |||
148 | val = of_get_property(dp, "ATY,SCLK", NULL); | ||
149 | if (val && *val) | ||
150 | rdev->clock.default_sclk = (*val) / 10; | ||
151 | else | ||
152 | rdev->clock.default_sclk = | ||
153 | radeon_legacy_get_engine_clock(rdev); | ||
154 | |||
155 | val = of_get_property(dp, "ATY,MCLK", NULL); | ||
156 | if (val && *val) | ||
157 | rdev->clock.default_mclk = (*val) / 10; | ||
158 | else | ||
159 | rdev->clock.default_mclk = | ||
160 | radeon_legacy_get_memory_clock(rdev); | ||
161 | |||
162 | DRM_INFO("Using device-tree clock info\n"); | ||
163 | |||
164 | return true; | ||
165 | } | ||
166 | #else | ||
167 | static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) | ||
168 | { | ||
169 | return false; | ||
170 | } | ||
171 | #endif /* CONFIG_OF */ | ||
172 | |||
94 | void radeon_get_clock_info(struct drm_device *dev) | 173 | void radeon_get_clock_info(struct drm_device *dev) |
95 | { | 174 | { |
96 | struct radeon_device *rdev = dev->dev_private; | 175 | struct radeon_device *rdev = dev->dev_private; |
@@ -105,6 +184,8 @@ void radeon_get_clock_info(struct drm_device *dev) | |||
105 | ret = radeon_atom_get_clock_info(dev); | 184 | ret = radeon_atom_get_clock_info(dev); |
106 | else | 185 | else |
107 | ret = radeon_combios_get_clock_info(dev); | 186 | ret = radeon_combios_get_clock_info(dev); |
187 | if (!ret) | ||
188 | ret = radeon_read_clocks_OF(dev); | ||
108 | 189 | ||
109 | if (ret) { | 190 | if (ret) { |
110 | if (p1pll->reference_div < 2) { | 191 | if (p1pll->reference_div < 2) { |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 5e1474cde4b4..885dcfac1838 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -480,9 +480,66 @@ radeon_combios_get_hardcoded_edid(struct radeon_device *rdev) | |||
480 | } | 480 | } |
481 | 481 | ||
482 | static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, | 482 | static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, |
483 | int ddc_line) | 483 | enum radeon_combios_ddc ddc, |
484 | u32 clk_mask, | ||
485 | u32 data_mask) | ||
484 | { | 486 | { |
485 | struct radeon_i2c_bus_rec i2c; | 487 | struct radeon_i2c_bus_rec i2c; |
488 | int ddc_line = 0; | ||
489 | |||
490 | /* ddc id = mask reg | ||
491 | * DDC_NONE_DETECTED = none | ||
492 | * DDC_DVI = RADEON_GPIO_DVI_DDC | ||
493 | * DDC_VGA = RADEON_GPIO_VGA_DDC | ||
494 | * DDC_LCD = RADEON_GPIOPAD_MASK | ||
495 | * DDC_GPIO = RADEON_MDGPIO_MASK | ||
496 | * r1xx/r2xx | ||
497 | * DDC_MONID = RADEON_GPIO_MONID | ||
498 | * DDC_CRT2 = RADEON_GPIO_CRT2_DDC | ||
499 | * r3xx | ||
500 | * DDC_MONID = RADEON_GPIO_MONID | ||
501 | * DDC_CRT2 = RADEON_GPIO_DVI_DDC | ||
502 | * rs3xx/rs4xx | ||
503 | * DDC_MONID = RADEON_GPIOPAD_MASK | ||
504 | * DDC_CRT2 = RADEON_GPIO_MONID | ||
505 | */ | ||
506 | switch (ddc) { | ||
507 | case DDC_NONE_DETECTED: | ||
508 | default: | ||
509 | ddc_line = 0; | ||
510 | break; | ||
511 | case DDC_DVI: | ||
512 | ddc_line = RADEON_GPIO_DVI_DDC; | ||
513 | break; | ||
514 | case DDC_VGA: | ||
515 | ddc_line = RADEON_GPIO_VGA_DDC; | ||
516 | break; | ||
517 | case DDC_LCD: | ||
518 | ddc_line = RADEON_GPIOPAD_MASK; | ||
519 | break; | ||
520 | case DDC_GPIO: | ||
521 | ddc_line = RADEON_MDGPIO_MASK; | ||
522 | break; | ||
523 | case DDC_MONID: | ||
524 | if (rdev->family == CHIP_RS300 || | ||
525 | rdev->family == CHIP_RS400 || | ||
526 | rdev->family == CHIP_RS480) | ||
527 | ddc_line = RADEON_GPIOPAD_MASK; | ||
528 | else | ||
529 | ddc_line = RADEON_GPIO_MONID; | ||
530 | break; | ||
531 | case DDC_CRT2: | ||
532 | if (rdev->family == CHIP_RS300 || | ||
533 | rdev->family == CHIP_RS400 || | ||
534 | rdev->family == CHIP_RS480) | ||
535 | ddc_line = RADEON_GPIO_MONID; | ||
536 | else if (rdev->family >= CHIP_R300) { | ||
537 | ddc_line = RADEON_GPIO_DVI_DDC; | ||
538 | ddc = DDC_DVI; | ||
539 | } else | ||
540 | ddc_line = RADEON_GPIO_CRT2_DDC; | ||
541 | break; | ||
542 | } | ||
486 | 543 | ||
487 | if (ddc_line == RADEON_GPIOPAD_MASK) { | 544 | if (ddc_line == RADEON_GPIOPAD_MASK) { |
488 | i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; | 545 | i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; |
@@ -503,15 +560,6 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
503 | i2c.y_clk_reg = RADEON_MDGPIO_Y; | 560 | i2c.y_clk_reg = RADEON_MDGPIO_Y; |
504 | i2c.y_data_reg = RADEON_MDGPIO_Y; | 561 | i2c.y_data_reg = RADEON_MDGPIO_Y; |
505 | } else { | 562 | } else { |
506 | i2c.mask_clk_mask = RADEON_GPIO_EN_1; | ||
507 | i2c.mask_data_mask = RADEON_GPIO_EN_0; | ||
508 | i2c.a_clk_mask = RADEON_GPIO_A_1; | ||
509 | i2c.a_data_mask = RADEON_GPIO_A_0; | ||
510 | i2c.en_clk_mask = RADEON_GPIO_EN_1; | ||
511 | i2c.en_data_mask = RADEON_GPIO_EN_0; | ||
512 | i2c.y_clk_mask = RADEON_GPIO_Y_1; | ||
513 | i2c.y_data_mask = RADEON_GPIO_Y_0; | ||
514 | |||
515 | i2c.mask_clk_reg = ddc_line; | 563 | i2c.mask_clk_reg = ddc_line; |
516 | i2c.mask_data_reg = ddc_line; | 564 | i2c.mask_data_reg = ddc_line; |
517 | i2c.a_clk_reg = ddc_line; | 565 | i2c.a_clk_reg = ddc_line; |
@@ -522,6 +570,26 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
522 | i2c.y_data_reg = ddc_line; | 570 | i2c.y_data_reg = ddc_line; |
523 | } | 571 | } |
524 | 572 | ||
573 | if (clk_mask && data_mask) { | ||
574 | i2c.mask_clk_mask = clk_mask; | ||
575 | i2c.mask_data_mask = data_mask; | ||
576 | i2c.a_clk_mask = clk_mask; | ||
577 | i2c.a_data_mask = data_mask; | ||
578 | i2c.en_clk_mask = clk_mask; | ||
579 | i2c.en_data_mask = data_mask; | ||
580 | i2c.y_clk_mask = clk_mask; | ||
581 | i2c.y_data_mask = data_mask; | ||
582 | } else { | ||
583 | i2c.mask_clk_mask = RADEON_GPIO_EN_1; | ||
584 | i2c.mask_data_mask = RADEON_GPIO_EN_0; | ||
585 | i2c.a_clk_mask = RADEON_GPIO_A_1; | ||
586 | i2c.a_data_mask = RADEON_GPIO_A_0; | ||
587 | i2c.en_clk_mask = RADEON_GPIO_EN_1; | ||
588 | i2c.en_data_mask = RADEON_GPIO_EN_0; | ||
589 | i2c.y_clk_mask = RADEON_GPIO_Y_1; | ||
590 | i2c.y_data_mask = RADEON_GPIO_Y_0; | ||
591 | } | ||
592 | |||
525 | switch (rdev->family) { | 593 | switch (rdev->family) { |
526 | case CHIP_R100: | 594 | case CHIP_R100: |
527 | case CHIP_RV100: | 595 | case CHIP_RV100: |
@@ -599,7 +667,8 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
599 | break; | 667 | break; |
600 | } | 668 | } |
601 | i2c.mm_i2c = false; | 669 | i2c.mm_i2c = false; |
602 | i2c.i2c_id = 0; | 670 | |
671 | i2c.i2c_id = ddc; | ||
603 | i2c.hpd = RADEON_HPD_NONE; | 672 | i2c.hpd = RADEON_HPD_NONE; |
604 | 673 | ||
605 | if (ddc_line) | 674 | if (ddc_line) |
@@ -610,6 +679,62 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde | |||
610 | return i2c; | 679 | return i2c; |
611 | } | 680 | } |
612 | 681 | ||
682 | void radeon_combios_i2c_init(struct radeon_device *rdev) | ||
683 | { | ||
684 | struct drm_device *dev = rdev->ddev; | ||
685 | struct radeon_i2c_bus_rec i2c; | ||
686 | |||
687 | |||
688 | i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); | ||
689 | rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "DVI_DDC"); | ||
690 | |||
691 | i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); | ||
692 | rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "VGA_DDC"); | ||
693 | |||
694 | i2c.valid = true; | ||
695 | i2c.hw_capable = true; | ||
696 | i2c.mm_i2c = true; | ||
697 | i2c.i2c_id = 0xa0; | ||
698 | rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "MM_I2C"); | ||
699 | |||
700 | if (rdev->family == CHIP_RS300 || | ||
701 | rdev->family == CHIP_RS400 || | ||
702 | rdev->family == CHIP_RS480) { | ||
703 | u16 offset; | ||
704 | u8 id, blocks, clk, data; | ||
705 | int i; | ||
706 | |||
707 | i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); | ||
708 | rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); | ||
709 | |||
710 | offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); | ||
711 | if (offset) { | ||
712 | blocks = RBIOS8(offset + 2); | ||
713 | for (i = 0; i < blocks; i++) { | ||
714 | id = RBIOS8(offset + 3 + (i * 5) + 0); | ||
715 | if (id == 136) { | ||
716 | clk = RBIOS8(offset + 3 + (i * 5) + 3); | ||
717 | data = RBIOS8(offset + 3 + (i * 5) + 4); | ||
718 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, | ||
719 | clk, data); | ||
720 | rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); | ||
721 | break; | ||
722 | } | ||
723 | } | ||
724 | } | ||
725 | |||
726 | } else if (rdev->family >= CHIP_R300) { | ||
727 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); | ||
728 | rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); | ||
729 | } else { | ||
730 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); | ||
731 | rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); | ||
732 | |||
733 | i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); | ||
734 | rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "CRT2_DDC"); | ||
735 | } | ||
736 | } | ||
737 | |||
613 | bool radeon_combios_get_clock_info(struct drm_device *dev) | 738 | bool radeon_combios_get_clock_info(struct drm_device *dev) |
614 | { | 739 | { |
615 | struct radeon_device *rdev = dev->dev_private; | 740 | struct radeon_device *rdev = dev->dev_private; |
@@ -1247,8 +1372,8 @@ bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder, | |||
1247 | struct radeon_i2c_bus_rec i2c_bus; | 1372 | struct radeon_i2c_bus_rec i2c_bus; |
1248 | 1373 | ||
1249 | /* default for macs */ | 1374 | /* default for macs */ |
1250 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | 1375 | i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); |
1251 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | 1376 | tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1252 | 1377 | ||
1253 | /* XXX some macs have duallink chips */ | 1378 | /* XXX some macs have duallink chips */ |
1254 | switch (rdev->mode_info.connector_table) { | 1379 | switch (rdev->mode_info.connector_table) { |
@@ -1269,47 +1394,16 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder | |||
1269 | struct drm_device *dev = encoder->base.dev; | 1394 | struct drm_device *dev = encoder->base.dev; |
1270 | struct radeon_device *rdev = dev->dev_private; | 1395 | struct radeon_device *rdev = dev->dev_private; |
1271 | uint16_t offset; | 1396 | uint16_t offset; |
1272 | uint8_t ver, id, blocks, clk, data; | 1397 | uint8_t ver; |
1273 | int i; | ||
1274 | enum radeon_combios_ddc gpio; | 1398 | enum radeon_combios_ddc gpio; |
1275 | struct radeon_i2c_bus_rec i2c_bus; | 1399 | struct radeon_i2c_bus_rec i2c_bus; |
1276 | 1400 | ||
1277 | tmds->i2c_bus = NULL; | 1401 | tmds->i2c_bus = NULL; |
1278 | if (rdev->flags & RADEON_IS_IGP) { | 1402 | if (rdev->flags & RADEON_IS_IGP) { |
1279 | offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); | 1403 | i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); |
1280 | if (offset) { | 1404 | tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1281 | ver = RBIOS8(offset); | 1405 | tmds->dvo_chip = DVO_SIL164; |
1282 | DRM_INFO("GPIO Table revision: %d\n", ver); | 1406 | tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ |
1283 | blocks = RBIOS8(offset + 2); | ||
1284 | for (i = 0; i < blocks; i++) { | ||
1285 | id = RBIOS8(offset + 3 + (i * 5) + 0); | ||
1286 | if (id == 136) { | ||
1287 | clk = RBIOS8(offset + 3 + (i * 5) + 3); | ||
1288 | data = RBIOS8(offset + 3 + (i * 5) + 4); | ||
1289 | i2c_bus.valid = true; | ||
1290 | i2c_bus.mask_clk_mask = (1 << clk); | ||
1291 | i2c_bus.mask_data_mask = (1 << data); | ||
1292 | i2c_bus.a_clk_mask = (1 << clk); | ||
1293 | i2c_bus.a_data_mask = (1 << data); | ||
1294 | i2c_bus.en_clk_mask = (1 << clk); | ||
1295 | i2c_bus.en_data_mask = (1 << data); | ||
1296 | i2c_bus.y_clk_mask = (1 << clk); | ||
1297 | i2c_bus.y_data_mask = (1 << data); | ||
1298 | i2c_bus.mask_clk_reg = RADEON_GPIOPAD_MASK; | ||
1299 | i2c_bus.mask_data_reg = RADEON_GPIOPAD_MASK; | ||
1300 | i2c_bus.a_clk_reg = RADEON_GPIOPAD_A; | ||
1301 | i2c_bus.a_data_reg = RADEON_GPIOPAD_A; | ||
1302 | i2c_bus.en_clk_reg = RADEON_GPIOPAD_EN; | ||
1303 | i2c_bus.en_data_reg = RADEON_GPIOPAD_EN; | ||
1304 | i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y; | ||
1305 | i2c_bus.y_data_reg = RADEON_GPIOPAD_Y; | ||
1306 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1307 | tmds->dvo_chip = DVO_SIL164; | ||
1308 | tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ | ||
1309 | break; | ||
1310 | } | ||
1311 | } | ||
1312 | } | ||
1313 | } else { | 1407 | } else { |
1314 | offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); | 1408 | offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); |
1315 | if (offset) { | 1409 | if (offset) { |
@@ -1318,37 +1412,15 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder | |||
1318 | tmds->slave_addr = RBIOS8(offset + 4 + 2); | 1412 | tmds->slave_addr = RBIOS8(offset + 4 + 2); |
1319 | tmds->slave_addr >>= 1; /* 7 bit addressing */ | 1413 | tmds->slave_addr >>= 1; /* 7 bit addressing */ |
1320 | gpio = RBIOS8(offset + 4 + 3); | 1414 | gpio = RBIOS8(offset + 4 + 3); |
1321 | switch (gpio) { | 1415 | if (gpio == DDC_LCD) { |
1322 | case DDC_MONID: | 1416 | /* MM i2c */ |
1323 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
1324 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1325 | break; | ||
1326 | case DDC_DVI: | ||
1327 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | ||
1328 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1329 | break; | ||
1330 | case DDC_VGA: | ||
1331 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | ||
1332 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1333 | break; | ||
1334 | case DDC_CRT2: | ||
1335 | /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ | ||
1336 | if (rdev->family >= CHIP_R300) | ||
1337 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
1338 | else | ||
1339 | i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | ||
1340 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | ||
1341 | break; | ||
1342 | case DDC_LCD: /* MM i2c */ | ||
1343 | i2c_bus.valid = true; | 1417 | i2c_bus.valid = true; |
1344 | i2c_bus.hw_capable = true; | 1418 | i2c_bus.hw_capable = true; |
1345 | i2c_bus.mm_i2c = true; | 1419 | i2c_bus.mm_i2c = true; |
1346 | tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); | 1420 | i2c_bus.i2c_id = 0xa0; |
1347 | break; | 1421 | } else |
1348 | default: | 1422 | i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); |
1349 | DRM_ERROR("Unsupported gpio %d\n", gpio); | 1423 | tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1350 | break; | ||
1351 | } | ||
1352 | } | 1424 | } |
1353 | } | 1425 | } |
1354 | 1426 | ||
@@ -1430,7 +1502,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1430 | /* these are the most common settings */ | 1502 | /* these are the most common settings */ |
1431 | if (rdev->flags & RADEON_SINGLE_CRTC) { | 1503 | if (rdev->flags & RADEON_SINGLE_CRTC) { |
1432 | /* VGA - primary dac */ | 1504 | /* VGA - primary dac */ |
1433 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1505 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1434 | hpd.hpd = RADEON_HPD_NONE; | 1506 | hpd.hpd = RADEON_HPD_NONE; |
1435 | radeon_add_legacy_encoder(dev, | 1507 | radeon_add_legacy_encoder(dev, |
1436 | radeon_get_encoder_id(dev, | 1508 | radeon_get_encoder_id(dev, |
@@ -1445,7 +1517,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1445 | &hpd); | 1517 | &hpd); |
1446 | } else if (rdev->flags & RADEON_IS_MOBILITY) { | 1518 | } else if (rdev->flags & RADEON_IS_MOBILITY) { |
1447 | /* LVDS */ | 1519 | /* LVDS */ |
1448 | ddc_i2c = combios_setup_i2c_bus(rdev, 0); | 1520 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0); |
1449 | hpd.hpd = RADEON_HPD_NONE; | 1521 | hpd.hpd = RADEON_HPD_NONE; |
1450 | radeon_add_legacy_encoder(dev, | 1522 | radeon_add_legacy_encoder(dev, |
1451 | radeon_get_encoder_id(dev, | 1523 | radeon_get_encoder_id(dev, |
@@ -1460,7 +1532,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1460 | &hpd); | 1532 | &hpd); |
1461 | 1533 | ||
1462 | /* VGA - primary dac */ | 1534 | /* VGA - primary dac */ |
1463 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1535 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1464 | hpd.hpd = RADEON_HPD_NONE; | 1536 | hpd.hpd = RADEON_HPD_NONE; |
1465 | radeon_add_legacy_encoder(dev, | 1537 | radeon_add_legacy_encoder(dev, |
1466 | radeon_get_encoder_id(dev, | 1538 | radeon_get_encoder_id(dev, |
@@ -1475,7 +1547,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1475 | &hpd); | 1547 | &hpd); |
1476 | } else { | 1548 | } else { |
1477 | /* DVI-I - tv dac, int tmds */ | 1549 | /* DVI-I - tv dac, int tmds */ |
1478 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1550 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1479 | hpd.hpd = RADEON_HPD_1; | 1551 | hpd.hpd = RADEON_HPD_1; |
1480 | radeon_add_legacy_encoder(dev, | 1552 | radeon_add_legacy_encoder(dev, |
1481 | radeon_get_encoder_id(dev, | 1553 | radeon_get_encoder_id(dev, |
@@ -1496,7 +1568,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1496 | &hpd); | 1568 | &hpd); |
1497 | 1569 | ||
1498 | /* VGA - primary dac */ | 1570 | /* VGA - primary dac */ |
1499 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1571 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1500 | hpd.hpd = RADEON_HPD_NONE; | 1572 | hpd.hpd = RADEON_HPD_NONE; |
1501 | radeon_add_legacy_encoder(dev, | 1573 | radeon_add_legacy_encoder(dev, |
1502 | radeon_get_encoder_id(dev, | 1574 | radeon_get_encoder_id(dev, |
@@ -1532,7 +1604,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1532 | DRM_INFO("Connector Table: %d (ibook)\n", | 1604 | DRM_INFO("Connector Table: %d (ibook)\n", |
1533 | rdev->mode_info.connector_table); | 1605 | rdev->mode_info.connector_table); |
1534 | /* LVDS */ | 1606 | /* LVDS */ |
1535 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1607 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1536 | hpd.hpd = RADEON_HPD_NONE; | 1608 | hpd.hpd = RADEON_HPD_NONE; |
1537 | radeon_add_legacy_encoder(dev, | 1609 | radeon_add_legacy_encoder(dev, |
1538 | radeon_get_encoder_id(dev, | 1610 | radeon_get_encoder_id(dev, |
@@ -1544,7 +1616,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1544 | CONNECTOR_OBJECT_ID_LVDS, | 1616 | CONNECTOR_OBJECT_ID_LVDS, |
1545 | &hpd); | 1617 | &hpd); |
1546 | /* VGA - TV DAC */ | 1618 | /* VGA - TV DAC */ |
1547 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1619 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1548 | hpd.hpd = RADEON_HPD_NONE; | 1620 | hpd.hpd = RADEON_HPD_NONE; |
1549 | radeon_add_legacy_encoder(dev, | 1621 | radeon_add_legacy_encoder(dev, |
1550 | radeon_get_encoder_id(dev, | 1622 | radeon_get_encoder_id(dev, |
@@ -1573,7 +1645,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1573 | DRM_INFO("Connector Table: %d (powerbook external tmds)\n", | 1645 | DRM_INFO("Connector Table: %d (powerbook external tmds)\n", |
1574 | rdev->mode_info.connector_table); | 1646 | rdev->mode_info.connector_table); |
1575 | /* LVDS */ | 1647 | /* LVDS */ |
1576 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1648 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1577 | hpd.hpd = RADEON_HPD_NONE; | 1649 | hpd.hpd = RADEON_HPD_NONE; |
1578 | radeon_add_legacy_encoder(dev, | 1650 | radeon_add_legacy_encoder(dev, |
1579 | radeon_get_encoder_id(dev, | 1651 | radeon_get_encoder_id(dev, |
@@ -1585,7 +1657,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1585 | CONNECTOR_OBJECT_ID_LVDS, | 1657 | CONNECTOR_OBJECT_ID_LVDS, |
1586 | &hpd); | 1658 | &hpd); |
1587 | /* DVI-I - primary dac, ext tmds */ | 1659 | /* DVI-I - primary dac, ext tmds */ |
1588 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1660 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1589 | hpd.hpd = RADEON_HPD_2; /* ??? */ | 1661 | hpd.hpd = RADEON_HPD_2; /* ??? */ |
1590 | radeon_add_legacy_encoder(dev, | 1662 | radeon_add_legacy_encoder(dev, |
1591 | radeon_get_encoder_id(dev, | 1663 | radeon_get_encoder_id(dev, |
@@ -1622,7 +1694,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1622 | DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", | 1694 | DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", |
1623 | rdev->mode_info.connector_table); | 1695 | rdev->mode_info.connector_table); |
1624 | /* LVDS */ | 1696 | /* LVDS */ |
1625 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1697 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1626 | hpd.hpd = RADEON_HPD_NONE; | 1698 | hpd.hpd = RADEON_HPD_NONE; |
1627 | radeon_add_legacy_encoder(dev, | 1699 | radeon_add_legacy_encoder(dev, |
1628 | radeon_get_encoder_id(dev, | 1700 | radeon_get_encoder_id(dev, |
@@ -1634,7 +1706,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1634 | CONNECTOR_OBJECT_ID_LVDS, | 1706 | CONNECTOR_OBJECT_ID_LVDS, |
1635 | &hpd); | 1707 | &hpd); |
1636 | /* DVI-I - primary dac, int tmds */ | 1708 | /* DVI-I - primary dac, int tmds */ |
1637 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1709 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1638 | hpd.hpd = RADEON_HPD_1; /* ??? */ | 1710 | hpd.hpd = RADEON_HPD_1; /* ??? */ |
1639 | radeon_add_legacy_encoder(dev, | 1711 | radeon_add_legacy_encoder(dev, |
1640 | radeon_get_encoder_id(dev, | 1712 | radeon_get_encoder_id(dev, |
@@ -1670,7 +1742,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1670 | DRM_INFO("Connector Table: %d (powerbook vga)\n", | 1742 | DRM_INFO("Connector Table: %d (powerbook vga)\n", |
1671 | rdev->mode_info.connector_table); | 1743 | rdev->mode_info.connector_table); |
1672 | /* LVDS */ | 1744 | /* LVDS */ |
1673 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1745 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1674 | hpd.hpd = RADEON_HPD_NONE; | 1746 | hpd.hpd = RADEON_HPD_NONE; |
1675 | radeon_add_legacy_encoder(dev, | 1747 | radeon_add_legacy_encoder(dev, |
1676 | radeon_get_encoder_id(dev, | 1748 | radeon_get_encoder_id(dev, |
@@ -1682,7 +1754,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1682 | CONNECTOR_OBJECT_ID_LVDS, | 1754 | CONNECTOR_OBJECT_ID_LVDS, |
1683 | &hpd); | 1755 | &hpd); |
1684 | /* VGA - primary dac */ | 1756 | /* VGA - primary dac */ |
1685 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1757 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1686 | hpd.hpd = RADEON_HPD_NONE; | 1758 | hpd.hpd = RADEON_HPD_NONE; |
1687 | radeon_add_legacy_encoder(dev, | 1759 | radeon_add_legacy_encoder(dev, |
1688 | radeon_get_encoder_id(dev, | 1760 | radeon_get_encoder_id(dev, |
@@ -1711,7 +1783,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1711 | DRM_INFO("Connector Table: %d (mini external tmds)\n", | 1783 | DRM_INFO("Connector Table: %d (mini external tmds)\n", |
1712 | rdev->mode_info.connector_table); | 1784 | rdev->mode_info.connector_table); |
1713 | /* DVI-I - tv dac, ext tmds */ | 1785 | /* DVI-I - tv dac, ext tmds */ |
1714 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1786 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1715 | hpd.hpd = RADEON_HPD_2; /* ??? */ | 1787 | hpd.hpd = RADEON_HPD_2; /* ??? */ |
1716 | radeon_add_legacy_encoder(dev, | 1788 | radeon_add_legacy_encoder(dev, |
1717 | radeon_get_encoder_id(dev, | 1789 | radeon_get_encoder_id(dev, |
@@ -1748,7 +1820,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1748 | DRM_INFO("Connector Table: %d (mini internal tmds)\n", | 1820 | DRM_INFO("Connector Table: %d (mini internal tmds)\n", |
1749 | rdev->mode_info.connector_table); | 1821 | rdev->mode_info.connector_table); |
1750 | /* DVI-I - tv dac, int tmds */ | 1822 | /* DVI-I - tv dac, int tmds */ |
1751 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1823 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1752 | hpd.hpd = RADEON_HPD_1; /* ??? */ | 1824 | hpd.hpd = RADEON_HPD_1; /* ??? */ |
1753 | radeon_add_legacy_encoder(dev, | 1825 | radeon_add_legacy_encoder(dev, |
1754 | radeon_get_encoder_id(dev, | 1826 | radeon_get_encoder_id(dev, |
@@ -1784,7 +1856,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1784 | DRM_INFO("Connector Table: %d (imac g5 isight)\n", | 1856 | DRM_INFO("Connector Table: %d (imac g5 isight)\n", |
1785 | rdev->mode_info.connector_table); | 1857 | rdev->mode_info.connector_table); |
1786 | /* DVI-D - int tmds */ | 1858 | /* DVI-D - int tmds */ |
1787 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | 1859 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); |
1788 | hpd.hpd = RADEON_HPD_1; /* ??? */ | 1860 | hpd.hpd = RADEON_HPD_1; /* ??? */ |
1789 | radeon_add_legacy_encoder(dev, | 1861 | radeon_add_legacy_encoder(dev, |
1790 | radeon_get_encoder_id(dev, | 1862 | radeon_get_encoder_id(dev, |
@@ -1796,7 +1868,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1796 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, | 1868 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, |
1797 | &hpd); | 1869 | &hpd); |
1798 | /* VGA - tv dac */ | 1870 | /* VGA - tv dac */ |
1799 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 1871 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
1800 | hpd.hpd = RADEON_HPD_NONE; | 1872 | hpd.hpd = RADEON_HPD_NONE; |
1801 | radeon_add_legacy_encoder(dev, | 1873 | radeon_add_legacy_encoder(dev, |
1802 | radeon_get_encoder_id(dev, | 1874 | radeon_get_encoder_id(dev, |
@@ -1825,7 +1897,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1825 | DRM_INFO("Connector Table: %d (emac)\n", | 1897 | DRM_INFO("Connector Table: %d (emac)\n", |
1826 | rdev->mode_info.connector_table); | 1898 | rdev->mode_info.connector_table); |
1827 | /* VGA - primary dac */ | 1899 | /* VGA - primary dac */ |
1828 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1900 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1829 | hpd.hpd = RADEON_HPD_NONE; | 1901 | hpd.hpd = RADEON_HPD_NONE; |
1830 | radeon_add_legacy_encoder(dev, | 1902 | radeon_add_legacy_encoder(dev, |
1831 | radeon_get_encoder_id(dev, | 1903 | radeon_get_encoder_id(dev, |
@@ -1837,7 +1909,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1837 | CONNECTOR_OBJECT_ID_VGA, | 1909 | CONNECTOR_OBJECT_ID_VGA, |
1838 | &hpd); | 1910 | &hpd); |
1839 | /* VGA - tv dac */ | 1911 | /* VGA - tv dac */ |
1840 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1912 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1841 | hpd.hpd = RADEON_HPD_NONE; | 1913 | hpd.hpd = RADEON_HPD_NONE; |
1842 | radeon_add_legacy_encoder(dev, | 1914 | radeon_add_legacy_encoder(dev, |
1843 | radeon_get_encoder_id(dev, | 1915 | radeon_get_encoder_id(dev, |
@@ -1866,7 +1938,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1866 | DRM_INFO("Connector Table: %d (rn50-power)\n", | 1938 | DRM_INFO("Connector Table: %d (rn50-power)\n", |
1867 | rdev->mode_info.connector_table); | 1939 | rdev->mode_info.connector_table); |
1868 | /* VGA - primary dac */ | 1940 | /* VGA - primary dac */ |
1869 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 1941 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
1870 | hpd.hpd = RADEON_HPD_NONE; | 1942 | hpd.hpd = RADEON_HPD_NONE; |
1871 | radeon_add_legacy_encoder(dev, | 1943 | radeon_add_legacy_encoder(dev, |
1872 | radeon_get_encoder_id(dev, | 1944 | radeon_get_encoder_id(dev, |
@@ -1877,7 +1949,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
1877 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c, | 1949 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c, |
1878 | CONNECTOR_OBJECT_ID_VGA, | 1950 | CONNECTOR_OBJECT_ID_VGA, |
1879 | &hpd); | 1951 | &hpd); |
1880 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | 1952 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
1881 | hpd.hpd = RADEON_HPD_NONE; | 1953 | hpd.hpd = RADEON_HPD_NONE; |
1882 | radeon_add_legacy_encoder(dev, | 1954 | radeon_add_legacy_encoder(dev, |
1883 | radeon_get_encoder_id(dev, | 1955 | radeon_get_encoder_id(dev, |
@@ -1907,31 +1979,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev, | |||
1907 | struct radeon_i2c_bus_rec *ddc_i2c, | 1979 | struct radeon_i2c_bus_rec *ddc_i2c, |
1908 | struct radeon_hpd *hpd) | 1980 | struct radeon_hpd *hpd) |
1909 | { | 1981 | { |
1910 | struct radeon_device *rdev = dev->dev_private; | ||
1911 | |||
1912 | /* XPRESS DDC quirks */ | ||
1913 | if ((rdev->family == CHIP_RS400 || | ||
1914 | rdev->family == CHIP_RS480) && | ||
1915 | ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) | ||
1916 | *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
1917 | else if ((rdev->family == CHIP_RS400 || | ||
1918 | rdev->family == CHIP_RS480) && | ||
1919 | ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) { | ||
1920 | *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIOPAD_MASK); | ||
1921 | ddc_i2c->mask_clk_mask = (0x20 << 8); | ||
1922 | ddc_i2c->mask_data_mask = 0x80; | ||
1923 | ddc_i2c->a_clk_mask = (0x20 << 8); | ||
1924 | ddc_i2c->a_data_mask = 0x80; | ||
1925 | ddc_i2c->en_clk_mask = (0x20 << 8); | ||
1926 | ddc_i2c->en_data_mask = 0x80; | ||
1927 | ddc_i2c->y_clk_mask = (0x20 << 8); | ||
1928 | ddc_i2c->y_data_mask = 0x80; | ||
1929 | } | ||
1930 | |||
1931 | /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ | ||
1932 | if ((rdev->family >= CHIP_R300) && | ||
1933 | ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) | ||
1934 | *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | ||
1935 | 1982 | ||
1936 | /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, | 1983 | /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, |
1937 | one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ | 1984 | one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ |
@@ -2035,27 +2082,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2035 | connector = (tmp >> 12) & 0xf; | 2082 | connector = (tmp >> 12) & 0xf; |
2036 | 2083 | ||
2037 | ddc_type = (tmp >> 8) & 0xf; | 2084 | ddc_type = (tmp >> 8) & 0xf; |
2038 | switch (ddc_type) { | 2085 | ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); |
2039 | case DDC_MONID: | ||
2040 | ddc_i2c = | ||
2041 | combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); | ||
2042 | break; | ||
2043 | case DDC_DVI: | ||
2044 | ddc_i2c = | ||
2045 | combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | ||
2046 | break; | ||
2047 | case DDC_VGA: | ||
2048 | ddc_i2c = | ||
2049 | combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | ||
2050 | break; | ||
2051 | case DDC_CRT2: | ||
2052 | ddc_i2c = | ||
2053 | combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); | ||
2054 | break; | ||
2055 | default: | ||
2056 | ddc_i2c.valid = false; | ||
2057 | break; | ||
2058 | } | ||
2059 | 2086 | ||
2060 | switch (connector) { | 2087 | switch (connector) { |
2061 | case CONNECTOR_PROPRIETARY_LEGACY: | 2088 | case CONNECTOR_PROPRIETARY_LEGACY: |
@@ -2225,7 +2252,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2225 | 0), | 2252 | 0), |
2226 | ATOM_DEVICE_DFP1_SUPPORT); | 2253 | ATOM_DEVICE_DFP1_SUPPORT); |
2227 | 2254 | ||
2228 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); | 2255 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
2229 | hpd.hpd = RADEON_HPD_1; | 2256 | hpd.hpd = RADEON_HPD_1; |
2230 | radeon_add_legacy_connector(dev, | 2257 | radeon_add_legacy_connector(dev, |
2231 | 0, | 2258 | 0, |
@@ -2245,7 +2272,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2245 | ATOM_DEVICE_CRT1_SUPPORT, | 2272 | ATOM_DEVICE_CRT1_SUPPORT, |
2246 | 1), | 2273 | 1), |
2247 | ATOM_DEVICE_CRT1_SUPPORT); | 2274 | ATOM_DEVICE_CRT1_SUPPORT); |
2248 | ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); | 2275 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
2249 | hpd.hpd = RADEON_HPD_NONE; | 2276 | hpd.hpd = RADEON_HPD_NONE; |
2250 | radeon_add_legacy_connector(dev, | 2277 | radeon_add_legacy_connector(dev, |
2251 | 0, | 2278 | 0, |
@@ -2278,70 +2305,25 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2278 | if (lcd_ddc_info) { | 2305 | if (lcd_ddc_info) { |
2279 | ddc_type = RBIOS8(lcd_ddc_info + 2); | 2306 | ddc_type = RBIOS8(lcd_ddc_info + 2); |
2280 | switch (ddc_type) { | 2307 | switch (ddc_type) { |
2281 | case DDC_MONID: | ||
2282 | ddc_i2c = | ||
2283 | combios_setup_i2c_bus | ||
2284 | (rdev, RADEON_GPIO_MONID); | ||
2285 | break; | ||
2286 | case DDC_DVI: | ||
2287 | ddc_i2c = | ||
2288 | combios_setup_i2c_bus | ||
2289 | (rdev, RADEON_GPIO_DVI_DDC); | ||
2290 | break; | ||
2291 | case DDC_VGA: | ||
2292 | ddc_i2c = | ||
2293 | combios_setup_i2c_bus | ||
2294 | (rdev, RADEON_GPIO_VGA_DDC); | ||
2295 | break; | ||
2296 | case DDC_CRT2: | ||
2297 | ddc_i2c = | ||
2298 | combios_setup_i2c_bus | ||
2299 | (rdev, RADEON_GPIO_CRT2_DDC); | ||
2300 | break; | ||
2301 | case DDC_LCD: | 2308 | case DDC_LCD: |
2302 | ddc_i2c = | 2309 | ddc_i2c = |
2303 | combios_setup_i2c_bus | 2310 | combios_setup_i2c_bus(rdev, |
2304 | (rdev, RADEON_GPIOPAD_MASK); | 2311 | DDC_LCD, |
2305 | ddc_i2c.mask_clk_mask = | 2312 | RBIOS32(lcd_ddc_info + 3), |
2306 | RBIOS32(lcd_ddc_info + 3); | 2313 | RBIOS32(lcd_ddc_info + 7)); |
2307 | ddc_i2c.mask_data_mask = | 2314 | radeon_i2c_add(rdev, &ddc_i2c, "LCD"); |
2308 | RBIOS32(lcd_ddc_info + 7); | ||
2309 | ddc_i2c.a_clk_mask = | ||
2310 | RBIOS32(lcd_ddc_info + 3); | ||
2311 | ddc_i2c.a_data_mask = | ||
2312 | RBIOS32(lcd_ddc_info + 7); | ||
2313 | ddc_i2c.en_clk_mask = | ||
2314 | RBIOS32(lcd_ddc_info + 3); | ||
2315 | ddc_i2c.en_data_mask = | ||
2316 | RBIOS32(lcd_ddc_info + 7); | ||
2317 | ddc_i2c.y_clk_mask = | ||
2318 | RBIOS32(lcd_ddc_info + 3); | ||
2319 | ddc_i2c.y_data_mask = | ||
2320 | RBIOS32(lcd_ddc_info + 7); | ||
2321 | break; | 2315 | break; |
2322 | case DDC_GPIO: | 2316 | case DDC_GPIO: |
2323 | ddc_i2c = | 2317 | ddc_i2c = |
2324 | combios_setup_i2c_bus | 2318 | combios_setup_i2c_bus(rdev, |
2325 | (rdev, RADEON_MDGPIO_MASK); | 2319 | DDC_GPIO, |
2326 | ddc_i2c.mask_clk_mask = | 2320 | RBIOS32(lcd_ddc_info + 3), |
2327 | RBIOS32(lcd_ddc_info + 3); | 2321 | RBIOS32(lcd_ddc_info + 7)); |
2328 | ddc_i2c.mask_data_mask = | 2322 | radeon_i2c_add(rdev, &ddc_i2c, "LCD"); |
2329 | RBIOS32(lcd_ddc_info + 7); | ||
2330 | ddc_i2c.a_clk_mask = | ||
2331 | RBIOS32(lcd_ddc_info + 3); | ||
2332 | ddc_i2c.a_data_mask = | ||
2333 | RBIOS32(lcd_ddc_info + 7); | ||
2334 | ddc_i2c.en_clk_mask = | ||
2335 | RBIOS32(lcd_ddc_info + 3); | ||
2336 | ddc_i2c.en_data_mask = | ||
2337 | RBIOS32(lcd_ddc_info + 7); | ||
2338 | ddc_i2c.y_clk_mask = | ||
2339 | RBIOS32(lcd_ddc_info + 3); | ||
2340 | ddc_i2c.y_data_mask = | ||
2341 | RBIOS32(lcd_ddc_info + 7); | ||
2342 | break; | 2323 | break; |
2343 | default: | 2324 | default: |
2344 | ddc_i2c.valid = false; | 2325 | ddc_i2c = |
2326 | combios_setup_i2c_bus(rdev, ddc_type, 0, 0); | ||
2345 | break; | 2327 | break; |
2346 | } | 2328 | } |
2347 | DRM_DEBUG_KMS("LCD DDC Info Table found!\n"); | 2329 | DRM_DEBUG_KMS("LCD DDC Info Table found!\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2395c8600cf4..47c4b276d30c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -518,8 +518,6 @@ static void radeon_connector_destroy(struct drm_connector *connector) | |||
518 | { | 518 | { |
519 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 519 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
520 | 520 | ||
521 | if (radeon_connector->ddc_bus) | ||
522 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
523 | if (radeon_connector->edid) | 521 | if (radeon_connector->edid) |
524 | kfree(radeon_connector->edid); | 522 | kfree(radeon_connector->edid); |
525 | kfree(radeon_connector->con_priv); | 523 | kfree(radeon_connector->con_priv); |
@@ -955,8 +953,6 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector) | |||
955 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 953 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
956 | struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; | 954 | struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; |
957 | 955 | ||
958 | if (radeon_connector->ddc_bus) | ||
959 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
960 | if (radeon_connector->edid) | 956 | if (radeon_connector->edid) |
961 | kfree(radeon_connector->edid); | 957 | kfree(radeon_connector->edid); |
962 | if (radeon_dig_connector->dp_i2c_bus) | 958 | if (radeon_dig_connector->dp_i2c_bus) |
@@ -1044,7 +1040,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1044 | bool linkb, | 1040 | bool linkb, |
1045 | uint32_t igp_lane_info, | 1041 | uint32_t igp_lane_info, |
1046 | uint16_t connector_object_id, | 1042 | uint16_t connector_object_id, |
1047 | struct radeon_hpd *hpd) | 1043 | struct radeon_hpd *hpd, |
1044 | struct radeon_router *router) | ||
1048 | { | 1045 | { |
1049 | struct radeon_device *rdev = dev->dev_private; | 1046 | struct radeon_device *rdev = dev->dev_private; |
1050 | struct drm_connector *connector; | 1047 | struct drm_connector *connector; |
@@ -1069,6 +1066,11 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1069 | radeon_connector->shared_ddc = true; | 1066 | radeon_connector->shared_ddc = true; |
1070 | shared_ddc = true; | 1067 | shared_ddc = true; |
1071 | } | 1068 | } |
1069 | if (radeon_connector->router_bus && router->valid && | ||
1070 | (radeon_connector->router.router_id == router->router_id)) { | ||
1071 | radeon_connector->shared_ddc = false; | ||
1072 | shared_ddc = false; | ||
1073 | } | ||
1072 | } | 1074 | } |
1073 | } | 1075 | } |
1074 | 1076 | ||
@@ -1083,12 +1085,18 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1083 | radeon_connector->shared_ddc = shared_ddc; | 1085 | radeon_connector->shared_ddc = shared_ddc; |
1084 | radeon_connector->connector_object_id = connector_object_id; | 1086 | radeon_connector->connector_object_id = connector_object_id; |
1085 | radeon_connector->hpd = *hpd; | 1087 | radeon_connector->hpd = *hpd; |
1088 | radeon_connector->router = *router; | ||
1089 | if (router->valid) { | ||
1090 | radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); | ||
1091 | if (!radeon_connector->router_bus) | ||
1092 | goto failed; | ||
1093 | } | ||
1086 | switch (connector_type) { | 1094 | switch (connector_type) { |
1087 | case DRM_MODE_CONNECTOR_VGA: | 1095 | case DRM_MODE_CONNECTOR_VGA: |
1088 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1096 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1089 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1097 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1090 | if (i2c_bus->valid) { | 1098 | if (i2c_bus->valid) { |
1091 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); | 1099 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1092 | if (!radeon_connector->ddc_bus) | 1100 | if (!radeon_connector->ddc_bus) |
1093 | goto failed; | 1101 | goto failed; |
1094 | } | 1102 | } |
@@ -1104,7 +1112,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1104 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1112 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1105 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1113 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1106 | if (i2c_bus->valid) { | 1114 | if (i2c_bus->valid) { |
1107 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1115 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1108 | if (!radeon_connector->ddc_bus) | 1116 | if (!radeon_connector->ddc_bus) |
1109 | goto failed; | 1117 | goto failed; |
1110 | } | 1118 | } |
@@ -1126,7 +1134,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1126 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | 1134 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1127 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | 1135 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1128 | if (i2c_bus->valid) { | 1136 | if (i2c_bus->valid) { |
1129 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1137 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1130 | if (!radeon_connector->ddc_bus) | 1138 | if (!radeon_connector->ddc_bus) |
1131 | goto failed; | 1139 | goto failed; |
1132 | } | 1140 | } |
@@ -1156,7 +1164,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1156 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | 1164 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1157 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | 1165 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1158 | if (i2c_bus->valid) { | 1166 | if (i2c_bus->valid) { |
1159 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); | 1167 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1160 | if (!radeon_connector->ddc_bus) | 1168 | if (!radeon_connector->ddc_bus) |
1161 | goto failed; | 1169 | goto failed; |
1162 | } | 1170 | } |
@@ -1187,10 +1195,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1187 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); | 1195 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); |
1188 | if (!radeon_dig_connector->dp_i2c_bus) | 1196 | if (!radeon_dig_connector->dp_i2c_bus) |
1189 | goto failed; | 1197 | goto failed; |
1190 | if (connector_type == DRM_MODE_CONNECTOR_eDP) | 1198 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1191 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP"); | ||
1192 | else | ||
1193 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); | ||
1194 | if (!radeon_connector->ddc_bus) | 1199 | if (!radeon_connector->ddc_bus) |
1195 | goto failed; | 1200 | goto failed; |
1196 | } | 1201 | } |
@@ -1230,7 +1235,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1230 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); | 1235 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
1231 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); | 1236 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
1232 | if (i2c_bus->valid) { | 1237 | if (i2c_bus->valid) { |
1233 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); | 1238 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1234 | if (!radeon_connector->ddc_bus) | 1239 | if (!radeon_connector->ddc_bus) |
1235 | goto failed; | 1240 | goto failed; |
1236 | } | 1241 | } |
@@ -1252,8 +1257,6 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1252 | return; | 1257 | return; |
1253 | 1258 | ||
1254 | failed: | 1259 | failed: |
1255 | if (radeon_connector->ddc_bus) | ||
1256 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
1257 | drm_connector_cleanup(connector); | 1260 | drm_connector_cleanup(connector); |
1258 | kfree(connector); | 1261 | kfree(connector); |
1259 | } | 1262 | } |
@@ -1300,7 +1303,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1300 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1303 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1301 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1304 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1302 | if (i2c_bus->valid) { | 1305 | if (i2c_bus->valid) { |
1303 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); | 1306 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1304 | if (!radeon_connector->ddc_bus) | 1307 | if (!radeon_connector->ddc_bus) |
1305 | goto failed; | 1308 | goto failed; |
1306 | } | 1309 | } |
@@ -1316,7 +1319,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1316 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1319 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
1317 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | 1320 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
1318 | if (i2c_bus->valid) { | 1321 | if (i2c_bus->valid) { |
1319 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1322 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1320 | if (!radeon_connector->ddc_bus) | 1323 | if (!radeon_connector->ddc_bus) |
1321 | goto failed; | 1324 | goto failed; |
1322 | } | 1325 | } |
@@ -1332,7 +1335,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1332 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | 1335 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
1333 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | 1336 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
1334 | if (i2c_bus->valid) { | 1337 | if (i2c_bus->valid) { |
1335 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | 1338 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1336 | if (!radeon_connector->ddc_bus) | 1339 | if (!radeon_connector->ddc_bus) |
1337 | goto failed; | 1340 | goto failed; |
1338 | } | 1341 | } |
@@ -1372,7 +1375,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1372 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); | 1375 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
1373 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); | 1376 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
1374 | if (i2c_bus->valid) { | 1377 | if (i2c_bus->valid) { |
1375 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); | 1378 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
1376 | if (!radeon_connector->ddc_bus) | 1379 | if (!radeon_connector->ddc_bus) |
1377 | goto failed; | 1380 | goto failed; |
1378 | } | 1381 | } |
@@ -1393,8 +1396,6 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1393 | return; | 1396 | return; |
1394 | 1397 | ||
1395 | failed: | 1398 | failed: |
1396 | if (radeon_connector->ddc_bus) | ||
1397 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
1398 | drm_connector_cleanup(connector); | 1399 | drm_connector_cleanup(connector); |
1399 | kfree(connector); | 1400 | kfree(connector); |
1400 | } | 1401 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index ae0fb7356e62..fcc79b5d22d1 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -72,7 +72,7 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
72 | if (p->relocs[i].gobj == NULL) { | 72 | if (p->relocs[i].gobj == NULL) { |
73 | DRM_ERROR("gem object lookup failed 0x%x\n", | 73 | DRM_ERROR("gem object lookup failed 0x%x\n", |
74 | r->handle); | 74 | r->handle); |
75 | return -EINVAL; | 75 | return -ENOENT; |
76 | } | 76 | } |
77 | p->relocs_ptr[i] = &p->relocs[i]; | 77 | p->relocs_ptr[i] = &p->relocs[i]; |
78 | p->relocs[i].robj = p->relocs[i].gobj->driver_private; | 78 | p->relocs[i].robj = p->relocs[i].gobj->driver_private; |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 4eb67c0e0996..5731fc9b1ae3 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
@@ -170,7 +170,7 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, | |||
170 | obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); | 170 | obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); |
171 | if (!obj) { | 171 | if (!obj) { |
172 | DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); | 172 | DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); |
173 | return -EINVAL; | 173 | return -ENOENT; |
174 | } | 174 | } |
175 | 175 | ||
176 | ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); | 176 | ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a64811a94519..4f7a170d1566 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -347,7 +347,8 @@ int radeon_dummy_page_init(struct radeon_device *rdev) | |||
347 | return -ENOMEM; | 347 | return -ENOMEM; |
348 | rdev->dummy_page.addr = pci_map_page(rdev->pdev, rdev->dummy_page.page, | 348 | rdev->dummy_page.addr = pci_map_page(rdev->pdev, rdev->dummy_page.page, |
349 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 349 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
350 | if (!rdev->dummy_page.addr) { | 350 | if (pci_dma_mapping_error(rdev->pdev, rdev->dummy_page.addr)) { |
351 | dev_err(&rdev->pdev->dev, "Failed to DMA MAP the dummy page\n"); | ||
351 | __free_page(rdev->dummy_page.page); | 352 | __free_page(rdev->dummy_page.page); |
352 | rdev->dummy_page.page = NULL; | 353 | rdev->dummy_page.page = NULL; |
353 | return -ENOMEM; | 354 | return -ENOMEM; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 74dac9635d70..5764f4d3b4f1 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -161,17 +161,13 @@ void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
161 | } | 161 | } |
162 | 162 | ||
163 | static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | 163 | static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, |
164 | u16 *blue, uint32_t size) | 164 | u16 *blue, uint32_t start, uint32_t size) |
165 | { | 165 | { |
166 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 166 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
167 | int i; | 167 | int end = (start + size > 256) ? 256 : start + size, i; |
168 | |||
169 | if (size != 256) { | ||
170 | return; | ||
171 | } | ||
172 | 168 | ||
173 | /* userspace palettes are always correct as is */ | 169 | /* userspace palettes are always correct as is */ |
174 | for (i = 0; i < 256; i++) { | 170 | for (i = start; i < end; i++) { |
175 | radeon_crtc->lut_r[i] = red[i] >> 6; | 171 | radeon_crtc->lut_r[i] = red[i] >> 6; |
176 | radeon_crtc->lut_g[i] = green[i] >> 6; | 172 | radeon_crtc->lut_g[i] = green[i] >> 6; |
177 | radeon_crtc->lut_b[i] = blue[i] >> 6; | 173 | radeon_crtc->lut_b[i] = blue[i] >> 6; |
@@ -319,6 +315,10 @@ static void radeon_print_display_setup(struct drm_device *dev) | |||
319 | radeon_connector->ddc_bus->rec.en_data_reg, | 315 | radeon_connector->ddc_bus->rec.en_data_reg, |
320 | radeon_connector->ddc_bus->rec.y_clk_reg, | 316 | radeon_connector->ddc_bus->rec.y_clk_reg, |
321 | radeon_connector->ddc_bus->rec.y_data_reg); | 317 | radeon_connector->ddc_bus->rec.y_data_reg); |
318 | if (radeon_connector->router_bus) | ||
319 | DRM_INFO(" DDC Router 0x%x/0x%x\n", | ||
320 | radeon_connector->router.mux_control_pin, | ||
321 | radeon_connector->router.mux_state); | ||
322 | } else { | 322 | } else { |
323 | if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || | 323 | if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || |
324 | connector->connector_type == DRM_MODE_CONNECTOR_DVII || | 324 | connector->connector_type == DRM_MODE_CONNECTOR_DVII || |
@@ -395,6 +395,10 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
395 | struct radeon_device *rdev = dev->dev_private; | 395 | struct radeon_device *rdev = dev->dev_private; |
396 | int ret = 0; | 396 | int ret = 0; |
397 | 397 | ||
398 | /* on hw with routers, select right port */ | ||
399 | if (radeon_connector->router.valid) | ||
400 | radeon_router_select_port(radeon_connector); | ||
401 | |||
398 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || | 402 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || |
399 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { | 403 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { |
400 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | 404 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
@@ -425,6 +429,10 @@ static int radeon_ddc_dump(struct drm_connector *connector) | |||
425 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 429 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
426 | int ret = 0; | 430 | int ret = 0; |
427 | 431 | ||
432 | /* on hw with routers, select right port */ | ||
433 | if (radeon_connector->router.valid) | ||
434 | radeon_router_select_port(radeon_connector); | ||
435 | |||
428 | if (!radeon_connector->ddc_bus) | 436 | if (!radeon_connector->ddc_bus) |
429 | return -1; | 437 | return -1; |
430 | edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); | 438 | edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); |
@@ -876,13 +884,12 @@ radeon_user_framebuffer_create(struct drm_device *dev, | |||
876 | if (obj == NULL) { | 884 | if (obj == NULL) { |
877 | dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, " | 885 | dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, " |
878 | "can't create framebuffer\n", mode_cmd->handle); | 886 | "can't create framebuffer\n", mode_cmd->handle); |
879 | return NULL; | 887 | return ERR_PTR(-ENOENT); |
880 | } | 888 | } |
881 | 889 | ||
882 | radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); | 890 | radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); |
883 | if (radeon_fb == NULL) { | 891 | if (radeon_fb == NULL) |
884 | return NULL; | 892 | return ERR_PTR(-ENOMEM); |
885 | } | ||
886 | 893 | ||
887 | radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); | 894 | radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); |
888 | 895 | ||
@@ -1040,6 +1047,9 @@ int radeon_modeset_init(struct radeon_device *rdev) | |||
1040 | return ret; | 1047 | return ret; |
1041 | } | 1048 | } |
1042 | 1049 | ||
1050 | /* init i2c buses */ | ||
1051 | radeon_i2c_init(rdev); | ||
1052 | |||
1043 | /* check combios for a valid hardcoded EDID - Sun servers */ | 1053 | /* check combios for a valid hardcoded EDID - Sun servers */ |
1044 | if (!rdev->is_atom_bios) { | 1054 | if (!rdev->is_atom_bios) { |
1045 | /* check for hardcoded EDID in BIOS */ | 1055 | /* check for hardcoded EDID in BIOS */ |
@@ -1080,6 +1090,8 @@ void radeon_modeset_fini(struct radeon_device *rdev) | |||
1080 | drm_mode_config_cleanup(rdev->ddev); | 1090 | drm_mode_config_cleanup(rdev->ddev); |
1081 | rdev->mode_info.mode_config_initialized = false; | 1091 | rdev->mode_info.mode_config_initialized = false; |
1082 | } | 1092 | } |
1093 | /* free i2c buses */ | ||
1094 | radeon_i2c_fini(rdev); | ||
1083 | } | 1095 | } |
1084 | 1096 | ||
1085 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | 1097 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index a72a3ee5d69b..c578f265b24c 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
@@ -226,7 +226,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
226 | /* just do a BO wait for now */ | 226 | /* just do a BO wait for now */ |
227 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 227 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
228 | if (gobj == NULL) { | 228 | if (gobj == NULL) { |
229 | return -EINVAL; | 229 | return -ENOENT; |
230 | } | 230 | } |
231 | robj = gobj->driver_private; | 231 | robj = gobj->driver_private; |
232 | 232 | ||
@@ -245,7 +245,7 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
245 | 245 | ||
246 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 246 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
247 | if (gobj == NULL) { | 247 | if (gobj == NULL) { |
248 | return -EINVAL; | 248 | return -ENOENT; |
249 | } | 249 | } |
250 | robj = gobj->driver_private; | 250 | robj = gobj->driver_private; |
251 | args->addr_ptr = radeon_bo_mmap_offset(robj); | 251 | args->addr_ptr = radeon_bo_mmap_offset(robj); |
@@ -264,7 +264,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
264 | 264 | ||
265 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 265 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
266 | if (gobj == NULL) { | 266 | if (gobj == NULL) { |
267 | return -EINVAL; | 267 | return -ENOENT; |
268 | } | 268 | } |
269 | robj = gobj->driver_private; | 269 | robj = gobj->driver_private; |
270 | r = radeon_bo_wait(robj, &cur_placement, true); | 270 | r = radeon_bo_wait(robj, &cur_placement, true); |
@@ -294,7 +294,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | |||
294 | 294 | ||
295 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 295 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
296 | if (gobj == NULL) { | 296 | if (gobj == NULL) { |
297 | return -EINVAL; | 297 | return -ENOENT; |
298 | } | 298 | } |
299 | robj = gobj->driver_private; | 299 | robj = gobj->driver_private; |
300 | r = radeon_bo_wait(robj, NULL, false); | 300 | r = radeon_bo_wait(robj, NULL, false); |
@@ -316,7 +316,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, | |||
316 | DRM_DEBUG("%d \n", args->handle); | 316 | DRM_DEBUG("%d \n", args->handle); |
317 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 317 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
318 | if (gobj == NULL) | 318 | if (gobj == NULL) |
319 | return -EINVAL; | 319 | return -ENOENT; |
320 | robj = gobj->driver_private; | 320 | robj = gobj->driver_private; |
321 | r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); | 321 | r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); |
322 | drm_gem_object_unreference_unlocked(gobj); | 322 | drm_gem_object_unreference_unlocked(gobj); |
@@ -334,7 +334,7 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, | |||
334 | DRM_DEBUG("\n"); | 334 | DRM_DEBUG("\n"); |
335 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 335 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
336 | if (gobj == NULL) | 336 | if (gobj == NULL) |
337 | return -EINVAL; | 337 | return -ENOENT; |
338 | rbo = gobj->driver_private; | 338 | rbo = gobj->driver_private; |
339 | r = radeon_bo_reserve(rbo, false); | 339 | r = radeon_bo_reserve(rbo, false); |
340 | if (unlikely(r != 0)) | 340 | if (unlikely(r != 0)) |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 5def6f5dff38..bfd2ce5f5372 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
@@ -52,6 +52,10 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) | |||
52 | } | 52 | } |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* on hw with routers, select right port */ | ||
56 | if (radeon_connector->router.valid) | ||
57 | radeon_router_select_port(radeon_connector); | ||
58 | |||
55 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); | 59 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); |
56 | if (ret == 2) | 60 | if (ret == 2) |
57 | return true; | 61 | return true; |
@@ -960,6 +964,59 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) | |||
960 | kfree(i2c); | 964 | kfree(i2c); |
961 | } | 965 | } |
962 | 966 | ||
967 | /* Add the default buses */ | ||
968 | void radeon_i2c_init(struct radeon_device *rdev) | ||
969 | { | ||
970 | if (rdev->is_atom_bios) | ||
971 | radeon_atombios_i2c_init(rdev); | ||
972 | else | ||
973 | radeon_combios_i2c_init(rdev); | ||
974 | } | ||
975 | |||
976 | /* remove all the buses */ | ||
977 | void radeon_i2c_fini(struct radeon_device *rdev) | ||
978 | { | ||
979 | int i; | ||
980 | |||
981 | for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { | ||
982 | if (rdev->i2c_bus[i]) { | ||
983 | radeon_i2c_destroy(rdev->i2c_bus[i]); | ||
984 | rdev->i2c_bus[i] = NULL; | ||
985 | } | ||
986 | } | ||
987 | } | ||
988 | |||
989 | /* Add additional buses */ | ||
990 | void radeon_i2c_add(struct radeon_device *rdev, | ||
991 | struct radeon_i2c_bus_rec *rec, | ||
992 | const char *name) | ||
993 | { | ||
994 | struct drm_device *dev = rdev->ddev; | ||
995 | int i; | ||
996 | |||
997 | for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { | ||
998 | if (!rdev->i2c_bus[i]) { | ||
999 | rdev->i2c_bus[i] = radeon_i2c_create(dev, rec, name); | ||
1000 | return; | ||
1001 | } | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | /* looks up bus based on id */ | ||
1006 | struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, | ||
1007 | struct radeon_i2c_bus_rec *i2c_bus) | ||
1008 | { | ||
1009 | int i; | ||
1010 | |||
1011 | for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { | ||
1012 | if (rdev->i2c_bus[i] && | ||
1013 | (rdev->i2c_bus[i]->rec.i2c_id == i2c_bus->i2c_id)) { | ||
1014 | return rdev->i2c_bus[i]; | ||
1015 | } | ||
1016 | } | ||
1017 | return NULL; | ||
1018 | } | ||
1019 | |||
963 | struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) | 1020 | struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) |
964 | { | 1021 | { |
965 | return NULL; | 1022 | return NULL; |
@@ -1020,3 +1077,28 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, | |||
1020 | addr, val); | 1077 | addr, val); |
1021 | } | 1078 | } |
1022 | 1079 | ||
1080 | /* router switching */ | ||
1081 | void radeon_router_select_port(struct radeon_connector *radeon_connector) | ||
1082 | { | ||
1083 | u8 val; | ||
1084 | |||
1085 | if (!radeon_connector->router.valid) | ||
1086 | return; | ||
1087 | |||
1088 | radeon_i2c_get_byte(radeon_connector->router_bus, | ||
1089 | radeon_connector->router.i2c_addr, | ||
1090 | 0x3, &val); | ||
1091 | val &= radeon_connector->router.mux_control_pin; | ||
1092 | radeon_i2c_put_byte(radeon_connector->router_bus, | ||
1093 | radeon_connector->router.i2c_addr, | ||
1094 | 0x3, val); | ||
1095 | radeon_i2c_get_byte(radeon_connector->router_bus, | ||
1096 | radeon_connector->router.i2c_addr, | ||
1097 | 0x1, &val); | ||
1098 | val &= radeon_connector->router.mux_control_pin; | ||
1099 | val |= radeon_connector->router.mux_state; | ||
1100 | radeon_i2c_put_byte(radeon_connector->router_bus, | ||
1101 | radeon_connector->router.i2c_addr, | ||
1102 | 0x1, val); | ||
1103 | } | ||
1104 | |||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index ddcd3b13f151..b1c8ace5f080 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -112,7 +112,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
112 | 112 | ||
113 | info = data; | 113 | info = data; |
114 | value_ptr = (uint32_t *)((unsigned long)info->value); | 114 | value_ptr = (uint32_t *)((unsigned long)info->value); |
115 | value = *value_ptr; | 115 | if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) |
116 | return -EFAULT; | ||
117 | |||
116 | switch (info->request) { | 118 | switch (info->request) { |
117 | case RADEON_INFO_DEVICE_ID: | 119 | case RADEON_INFO_DEVICE_ID: |
118 | value = dev->pci_device; | 120 | value = dev->pci_device; |
@@ -160,13 +162,27 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
160 | return -EINVAL; | 162 | return -EINVAL; |
161 | } | 163 | } |
162 | case RADEON_INFO_WANT_HYPERZ: | 164 | case RADEON_INFO_WANT_HYPERZ: |
165 | /* The "value" here is both an input and output parameter. | ||
166 | * If the input value is 1, filp requests hyper-z access. | ||
167 | * If the input value is 0, filp revokes its hyper-z access. | ||
168 | * | ||
169 | * When returning, the value is 1 if filp owns hyper-z access, | ||
170 | * 0 otherwise. */ | ||
171 | if (value >= 2) { | ||
172 | DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); | ||
173 | return -EINVAL; | ||
174 | } | ||
163 | mutex_lock(&dev->struct_mutex); | 175 | mutex_lock(&dev->struct_mutex); |
164 | if (rdev->hyperz_filp) | 176 | if (value == 1) { |
165 | value = 0; | 177 | /* wants hyper-z */ |
166 | else { | 178 | if (!rdev->hyperz_filp) |
167 | rdev->hyperz_filp = filp; | 179 | rdev->hyperz_filp = filp; |
168 | value = 1; | 180 | } else if (value == 0) { |
181 | /* revokes hyper-z */ | ||
182 | if (rdev->hyperz_filp == filp) | ||
183 | rdev->hyperz_filp = NULL; | ||
169 | } | 184 | } |
185 | value = rdev->hyperz_filp == filp ? 1 : 0; | ||
170 | mutex_unlock(&dev->struct_mutex); | 186 | mutex_unlock(&dev->struct_mutex); |
171 | break; | 187 | break; |
172 | default: | 188 | default: |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 71aea4037e90..5bbc086b9267 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -82,6 +82,8 @@ enum radeon_hpd_id { | |||
82 | RADEON_HPD_NONE = 0xff, | 82 | RADEON_HPD_NONE = 0xff, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define RADEON_MAX_I2C_BUS 16 | ||
86 | |||
85 | /* radeon gpio-based i2c | 87 | /* radeon gpio-based i2c |
86 | * 1. "mask" reg and bits | 88 | * 1. "mask" reg and bits |
87 | * grabs the gpio pins for software use | 89 | * grabs the gpio pins for software use |
@@ -398,6 +400,16 @@ struct radeon_hpd { | |||
398 | struct radeon_gpio_rec gpio; | 400 | struct radeon_gpio_rec gpio; |
399 | }; | 401 | }; |
400 | 402 | ||
403 | struct radeon_router { | ||
404 | bool valid; | ||
405 | u32 router_id; | ||
406 | struct radeon_i2c_bus_rec i2c_info; | ||
407 | u8 i2c_addr; | ||
408 | u8 mux_type; | ||
409 | u8 mux_control_pin; | ||
410 | u8 mux_state; | ||
411 | }; | ||
412 | |||
401 | struct radeon_connector { | 413 | struct radeon_connector { |
402 | struct drm_connector base; | 414 | struct drm_connector base; |
403 | uint32_t connector_id; | 415 | uint32_t connector_id; |
@@ -413,6 +425,8 @@ struct radeon_connector { | |||
413 | bool dac_load_detect; | 425 | bool dac_load_detect; |
414 | uint16_t connector_object_id; | 426 | uint16_t connector_object_id; |
415 | struct radeon_hpd hpd; | 427 | struct radeon_hpd hpd; |
428 | struct radeon_router router; | ||
429 | struct radeon_i2c_chan *router_bus; | ||
416 | }; | 430 | }; |
417 | 431 | ||
418 | struct radeon_framebuffer { | 432 | struct radeon_framebuffer { |
@@ -445,6 +459,15 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, | |||
445 | extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | 459 | extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, |
446 | uint8_t write_byte, uint8_t *read_byte); | 460 | uint8_t write_byte, uint8_t *read_byte); |
447 | 461 | ||
462 | extern void radeon_i2c_init(struct radeon_device *rdev); | ||
463 | extern void radeon_i2c_fini(struct radeon_device *rdev); | ||
464 | extern void radeon_combios_i2c_init(struct radeon_device *rdev); | ||
465 | extern void radeon_atombios_i2c_init(struct radeon_device *rdev); | ||
466 | extern void radeon_i2c_add(struct radeon_device *rdev, | ||
467 | struct radeon_i2c_bus_rec *rec, | ||
468 | const char *name); | ||
469 | extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, | ||
470 | struct radeon_i2c_bus_rec *i2c_bus); | ||
448 | extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, | 471 | extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, |
449 | struct radeon_i2c_bus_rec *rec, | 472 | struct radeon_i2c_bus_rec *rec, |
450 | const char *name); | 473 | const char *name); |
@@ -460,6 +483,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, | |||
460 | u8 slave_addr, | 483 | u8 slave_addr, |
461 | u8 addr, | 484 | u8 addr, |
462 | u8 val); | 485 | u8 val); |
486 | extern void radeon_router_select_port(struct radeon_connector *radeon_connector); | ||
463 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); | 487 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); |
464 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); | 488 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); |
465 | 489 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 95f8b3a3c43d..58038f5cab38 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -472,9 +472,9 @@ static const struct attribute_group hwmon_attrgroup = { | |||
472 | .attrs = hwmon_attributes, | 472 | .attrs = hwmon_attributes, |
473 | }; | 473 | }; |
474 | 474 | ||
475 | static void radeon_hwmon_init(struct radeon_device *rdev) | 475 | static int radeon_hwmon_init(struct radeon_device *rdev) |
476 | { | 476 | { |
477 | int err; | 477 | int err = 0; |
478 | 478 | ||
479 | rdev->pm.int_hwmon_dev = NULL; | 479 | rdev->pm.int_hwmon_dev = NULL; |
480 | 480 | ||
@@ -483,15 +483,26 @@ static void radeon_hwmon_init(struct radeon_device *rdev) | |||
483 | case THERMAL_TYPE_RV770: | 483 | case THERMAL_TYPE_RV770: |
484 | case THERMAL_TYPE_EVERGREEN: | 484 | case THERMAL_TYPE_EVERGREEN: |
485 | rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); | 485 | rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); |
486 | if (IS_ERR(rdev->pm.int_hwmon_dev)) { | ||
487 | err = PTR_ERR(rdev->pm.int_hwmon_dev); | ||
488 | dev_err(rdev->dev, | ||
489 | "Unable to register hwmon device: %d\n", err); | ||
490 | break; | ||
491 | } | ||
486 | dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev); | 492 | dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev); |
487 | err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj, | 493 | err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj, |
488 | &hwmon_attrgroup); | 494 | &hwmon_attrgroup); |
489 | if (err) | 495 | if (err) { |
490 | DRM_ERROR("Unable to create hwmon sysfs file: %d\n", err); | 496 | dev_err(rdev->dev, |
497 | "Unable to create hwmon sysfs file: %d\n", err); | ||
498 | hwmon_device_unregister(rdev->dev); | ||
499 | } | ||
491 | break; | 500 | break; |
492 | default: | 501 | default: |
493 | break; | 502 | break; |
494 | } | 503 | } |
504 | |||
505 | return err; | ||
495 | } | 506 | } |
496 | 507 | ||
497 | static void radeon_hwmon_fini(struct radeon_device *rdev) | 508 | static void radeon_hwmon_fini(struct radeon_device *rdev) |
@@ -540,6 +551,7 @@ void radeon_pm_resume(struct radeon_device *rdev) | |||
540 | int radeon_pm_init(struct radeon_device *rdev) | 551 | int radeon_pm_init(struct radeon_device *rdev) |
541 | { | 552 | { |
542 | int ret; | 553 | int ret; |
554 | |||
543 | /* default to profile method */ | 555 | /* default to profile method */ |
544 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 556 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
545 | rdev->pm.profile = PM_PROFILE_DEFAULT; | 557 | rdev->pm.profile = PM_PROFILE_DEFAULT; |
@@ -561,7 +573,9 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
561 | } | 573 | } |
562 | 574 | ||
563 | /* set up the internal thermal sensor if applicable */ | 575 | /* set up the internal thermal sensor if applicable */ |
564 | radeon_hwmon_init(rdev); | 576 | ret = radeon_hwmon_init(rdev); |
577 | if (ret) | ||
578 | return ret; | ||
565 | if (rdev->pm.num_power_states > 1) { | 579 | if (rdev->pm.num_power_states > 1) { |
566 | /* where's the best place to put these? */ | 580 | /* where's the best place to put these? */ |
567 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); | 581 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); |
diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 8293855f5f0d..b3f9f1d92005 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 | |||
@@ -316,6 +316,7 @@ rv515 0x6d40 | |||
316 | 0x4BD0 FG_FOG_COLOR_B | 316 | 0x4BD0 FG_FOG_COLOR_B |
317 | 0x4BD4 FG_ALPHA_FUNC | 317 | 0x4BD4 FG_ALPHA_FUNC |
318 | 0x4BD8 FG_DEPTH_SRC | 318 | 0x4BD8 FG_DEPTH_SRC |
319 | 0x4BE0 FG_ALPHA_VALUE | ||
319 | 0x4C00 US_ALU_CONST_R_0 | 320 | 0x4C00 US_ALU_CONST_R_0 |
320 | 0x4C04 US_ALU_CONST_G_0 | 321 | 0x4C04 US_ALU_CONST_G_0 |
321 | 0x4C08 US_ALU_CONST_B_0 | 322 | 0x4C08 US_ALU_CONST_B_0 |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 437ac786277a..64d7f47df868 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -737,7 +737,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, | |||
737 | 737 | ||
738 | if (ret) { | 738 | if (ret) { |
739 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); | 739 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); |
740 | return NULL; | 740 | return ERR_PTR(ret); |
741 | } | 741 | } |
742 | return &vfb->base; | 742 | return &vfb->base; |
743 | 743 | ||
@@ -747,7 +747,7 @@ try_dmabuf: | |||
747 | ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo); | 747 | ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo); |
748 | if (ret) { | 748 | if (ret) { |
749 | DRM_ERROR("failed to find buffer: %i\n", ret); | 749 | DRM_ERROR("failed to find buffer: %i\n", ret); |
750 | return NULL; | 750 | return ERR_PTR(-ENOENT); |
751 | } | 751 | } |
752 | 752 | ||
753 | ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, | 753 | ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, |
@@ -758,7 +758,7 @@ try_dmabuf: | |||
758 | 758 | ||
759 | if (ret) { | 759 | if (ret) { |
760 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); | 760 | DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); |
761 | return NULL; | 761 | return ERR_PTR(ret); |
762 | } | 762 | } |
763 | 763 | ||
764 | return &vfb->base; | 764 | return &vfb->base; |
@@ -768,7 +768,7 @@ err_not_scanout: | |||
768 | /* vmw_user_surface_lookup takes one ref */ | 768 | /* vmw_user_surface_lookup takes one ref */ |
769 | vmw_surface_unreference(&surface); | 769 | vmw_surface_unreference(&surface); |
770 | 770 | ||
771 | return NULL; | 771 | return ERR_PTR(-EINVAL); |
772 | } | 772 | } |
773 | 773 | ||
774 | static struct drm_mode_config_funcs vmw_kms_funcs = { | 774 | static struct drm_mode_config_funcs vmw_kms_funcs = { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index cfaf690a5b2f..2ff5cf78235f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -79,7 +79,7 @@ static void vmw_ldu_crtc_restore(struct drm_crtc *crtc) | |||
79 | 79 | ||
80 | static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc, | 80 | static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc, |
81 | u16 *r, u16 *g, u16 *b, | 81 | u16 *r, u16 *g, u16 *b, |
82 | uint32_t size) | 82 | uint32_t start, uint32_t size) |
83 | { | 83 | { |
84 | } | 84 | } |
85 | 85 | ||
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h index b28d7e27a031..90f094d45450 100644 --- a/drivers/hwmon/ams/ams.h +++ b/drivers/hwmon/ams/ams.h | |||
@@ -23,7 +23,7 @@ struct ams { | |||
23 | 23 | ||
24 | /* General properties */ | 24 | /* General properties */ |
25 | struct device_node *of_node; | 25 | struct device_node *of_node; |
26 | struct of_device *of_dev; | 26 | struct platform_device *of_dev; |
27 | char has_device; | 27 | char has_device; |
28 | char vflag; | 28 | char vflag; |
29 | u32 orient1; | 29 | u32 orient1; |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index a92e28a35767..c070c9714cbe 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -501,13 +501,10 @@ static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, | |||
501 | 501 | ||
502 | switch (action) { | 502 | switch (action) { |
503 | case CPU_ONLINE: | 503 | case CPU_ONLINE: |
504 | case CPU_ONLINE_FROZEN: | ||
505 | case CPU_DOWN_FAILED: | 504 | case CPU_DOWN_FAILED: |
506 | case CPU_DOWN_FAILED_FROZEN: | ||
507 | coretemp_device_add(cpu); | 505 | coretemp_device_add(cpu); |
508 | break; | 506 | break; |
509 | case CPU_DOWN_PREPARE: | 507 | case CPU_DOWN_PREPARE: |
510 | case CPU_DOWN_PREPARE_FROZEN: | ||
511 | coretemp_device_remove(cpu); | 508 | coretemp_device_remove(cpu); |
512 | break; | 509 | break; |
513 | } | 510 | } |
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c index ce3c7bc81814..d5226c9e1201 100644 --- a/drivers/hwmon/mc13783-adc.c +++ b/drivers/hwmon/mc13783-adc.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/mfd/mc13783-private.h> | 21 | #include <linux/mfd/mc13783.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/hwmon-sysfs.h> | 23 | #include <linux/hwmon-sysfs.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
@@ -144,6 +144,14 @@ static const struct attribute_group mc13783_group_ts = { | |||
144 | .attrs = mc13783_attr_ts, | 144 | .attrs = mc13783_attr_ts, |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static int mc13783_adc_use_touchscreen(struct platform_device *pdev) | ||
148 | { | ||
149 | struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); | ||
150 | unsigned flags = mc13783_get_flags(priv->mc13783); | ||
151 | |||
152 | return flags & MC13783_USE_TOUCHSCREEN; | ||
153 | } | ||
154 | |||
147 | static int __init mc13783_adc_probe(struct platform_device *pdev) | 155 | static int __init mc13783_adc_probe(struct platform_device *pdev) |
148 | { | 156 | { |
149 | struct mc13783_adc_priv *priv; | 157 | struct mc13783_adc_priv *priv; |
@@ -162,10 +170,11 @@ static int __init mc13783_adc_probe(struct platform_device *pdev) | |||
162 | if (ret) | 170 | if (ret) |
163 | goto out_err_create1; | 171 | goto out_err_create1; |
164 | 172 | ||
165 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 173 | if (!mc13783_adc_use_touchscreen(pdev)) { |
166 | ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); | 174 | ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); |
167 | if (ret) | 175 | if (ret) |
168 | goto out_err_create2; | 176 | goto out_err_create2; |
177 | } | ||
169 | 178 | ||
170 | priv->hwmon_dev = hwmon_device_register(&pdev->dev); | 179 | priv->hwmon_dev = hwmon_device_register(&pdev->dev); |
171 | if (IS_ERR(priv->hwmon_dev)) { | 180 | if (IS_ERR(priv->hwmon_dev)) { |
@@ -180,7 +189,7 @@ static int __init mc13783_adc_probe(struct platform_device *pdev) | |||
180 | 189 | ||
181 | out_err_register: | 190 | out_err_register: |
182 | 191 | ||
183 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 192 | if (!mc13783_adc_use_touchscreen(pdev)) |
184 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); | 193 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); |
185 | out_err_create2: | 194 | out_err_create2: |
186 | 195 | ||
@@ -199,7 +208,7 @@ static int __devexit mc13783_adc_remove(struct platform_device *pdev) | |||
199 | 208 | ||
200 | hwmon_device_unregister(priv->hwmon_dev); | 209 | hwmon_device_unregister(priv->hwmon_dev); |
201 | 210 | ||
202 | if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)) | 211 | if (!mc13783_adc_use_touchscreen(pdev)) |
203 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); | 212 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); |
204 | 213 | ||
205 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); | 214 | sysfs_remove_group(&pdev->dev.kobj, &mc13783_group); |
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index 89643261ccdb..d863e13a50b8 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c | |||
@@ -234,7 +234,7 @@ static const struct attribute_group env_group = { | |||
234 | .attrs = env_attributes, | 234 | .attrs = env_attributes, |
235 | }; | 235 | }; |
236 | 236 | ||
237 | static int __devinit env_probe(struct of_device *op, | 237 | static int __devinit env_probe(struct platform_device *op, |
238 | const struct of_device_id *match) | 238 | const struct of_device_id *match) |
239 | { | 239 | { |
240 | struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); | 240 | struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); |
@@ -276,7 +276,7 @@ out_free: | |||
276 | goto out; | 276 | goto out; |
277 | } | 277 | } |
278 | 278 | ||
279 | static int __devexit env_remove(struct of_device *op) | 279 | static int __devexit env_remove(struct platform_device *op) |
280 | { | 280 | { |
281 | struct env *p = dev_get_drvdata(&op->dev); | 281 | struct env *p = dev_get_drvdata(&op->dev); |
282 | 282 | ||
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index d06083fdffbb..30f06e956bfb 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig | |||
@@ -47,6 +47,19 @@ config I2C_CHARDEV | |||
47 | This support is also available as a module. If so, the module | 47 | This support is also available as a module. If so, the module |
48 | will be called i2c-dev. | 48 | will be called i2c-dev. |
49 | 49 | ||
50 | config I2C_MUX | ||
51 | tristate "I2C bus multiplexing support" | ||
52 | depends on EXPERIMENTAL | ||
53 | help | ||
54 | Say Y here if you want the I2C core to support the ability to | ||
55 | handle multiplexed I2C bus topologies, by presenting each | ||
56 | multiplexed segment as a I2C adapter. | ||
57 | |||
58 | This support is also available as a module. If so, the module | ||
59 | will be called i2c-mux. | ||
60 | |||
61 | source drivers/i2c/muxes/Kconfig | ||
62 | |||
50 | config I2C_HELPER_AUTO | 63 | config I2C_HELPER_AUTO |
51 | bool "Autoselect pertinent helper modules" | 64 | bool "Autoselect pertinent helper modules" |
52 | default y | 65 | default y |
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index a7d9b4be9bb3..c00fd66388f5 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile | |||
@@ -6,7 +6,8 @@ obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o | |||
6 | obj-$(CONFIG_I2C) += i2c-core.o | 6 | obj-$(CONFIG_I2C) += i2c-core.o |
7 | obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o | 7 | obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o |
8 | obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o | 8 | obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o |
9 | obj-y += algos/ busses/ | 9 | obj-$(CONFIG_I2C_MUX) += i2c-mux.o |
10 | obj-y += algos/ busses/ muxes/ | ||
10 | 11 | ||
11 | ifeq ($(CONFIG_I2C_DEBUG_CORE),y) | 12 | ifeq ($(CONFIG_I2C_DEBUG_CORE),y) |
12 | EXTRA_CFLAGS += -DDEBUG | 13 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index bceafbfa7268..15a9702e2941 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -521,12 +521,19 @@ config I2C_PXA_SLAVE | |||
521 | is necessary for systems where the PXA may be a target on the | 521 | is necessary for systems where the PXA may be a target on the |
522 | I2C bus. | 522 | I2C bus. |
523 | 523 | ||
524 | config HAVE_S3C2410_I2C | ||
525 | bool | ||
526 | help | ||
527 | This will include I2C support for Samsung SoCs. If you want to | ||
528 | include I2C support for any machine, kindly select this in the | ||
529 | respective Kconfig file. | ||
530 | |||
524 | config I2C_S3C2410 | 531 | config I2C_S3C2410 |
525 | tristate "S3C2410 I2C Driver" | 532 | tristate "S3C2410 I2C Driver" |
526 | depends on ARCH_S3C2410 || ARCH_S3C64XX | 533 | depends on HAVE_S3C2410_I2C |
527 | help | 534 | help |
528 | Say Y here to include support for I2C controller in the | 535 | Say Y here to include support for I2C controller in the |
529 | Samsung S3C2410 based System-on-Chip devices. | 536 | Samsung SoCs. |
530 | 537 | ||
531 | config I2C_S6000 | 538 | config I2C_S6000 |
532 | tristate "S6000 I2C support" | 539 | tristate "S6000 I2C support" |
@@ -549,7 +556,7 @@ config I2C_SH7760 | |||
549 | 556 | ||
550 | config I2C_SH_MOBILE | 557 | config I2C_SH_MOBILE |
551 | tristate "SuperH Mobile I2C Controller" | 558 | tristate "SuperH Mobile I2C Controller" |
552 | depends on SUPERH | 559 | depends on SUPERH || ARCH_SHMOBILE |
553 | help | 560 | help |
554 | If you say yes to this option, support will be included for the | 561 | If you say yes to this option, support will be included for the |
555 | built-in I2C interface on the Renesas SH-Mobile processor. | 562 | built-in I2C interface on the Renesas SH-Mobile processor. |
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index e591de1bc704..f7bd2613cecc 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c | |||
@@ -105,7 +105,7 @@ struct i2c_reg { | |||
105 | 105 | ||
106 | struct cpm_i2c { | 106 | struct cpm_i2c { |
107 | char *base; | 107 | char *base; |
108 | struct of_device *ofdev; | 108 | struct platform_device *ofdev; |
109 | struct i2c_adapter adap; | 109 | struct i2c_adapter adap; |
110 | uint dp_addr; | 110 | uint dp_addr; |
111 | int version; /* CPM1=1, CPM2=2 */ | 111 | int version; /* CPM1=1, CPM2=2 */ |
@@ -428,7 +428,7 @@ static const struct i2c_adapter cpm_ops = { | |||
428 | 428 | ||
429 | static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) | 429 | static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) |
430 | { | 430 | { |
431 | struct of_device *ofdev = cpm->ofdev; | 431 | struct platform_device *ofdev = cpm->ofdev; |
432 | const u32 *data; | 432 | const u32 *data; |
433 | int len, ret, i; | 433 | int len, ret, i; |
434 | void __iomem *i2c_base; | 434 | void __iomem *i2c_base; |
@@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm) | |||
634 | cpm_muram_free(cpm->i2c_addr); | 634 | cpm_muram_free(cpm->i2c_addr); |
635 | } | 635 | } |
636 | 636 | ||
637 | static int __devinit cpm_i2c_probe(struct of_device *ofdev, | 637 | static int __devinit cpm_i2c_probe(struct platform_device *ofdev, |
638 | const struct of_device_id *match) | 638 | const struct of_device_id *match) |
639 | { | 639 | { |
640 | int result, len; | 640 | int result, len; |
@@ -687,7 +687,7 @@ out_free: | |||
687 | return result; | 687 | return result; |
688 | } | 688 | } |
689 | 689 | ||
690 | static int __devexit cpm_i2c_remove(struct of_device *ofdev) | 690 | static int __devexit cpm_i2c_remove(struct platform_device *ofdev) |
691 | { | 691 | { |
692 | struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); | 692 | struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); |
693 | 693 | ||
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 1168d61418c9..43ca32fddde2 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c | |||
@@ -661,7 +661,7 @@ static inline u8 iic_clckdiv(unsigned int opb) | |||
661 | return (u8)((opb + 9) / 10 - 1); | 661 | return (u8)((opb + 9) / 10 - 1); |
662 | } | 662 | } |
663 | 663 | ||
664 | static int __devinit iic_request_irq(struct of_device *ofdev, | 664 | static int __devinit iic_request_irq(struct platform_device *ofdev, |
665 | struct ibm_iic_private *dev) | 665 | struct ibm_iic_private *dev) |
666 | { | 666 | { |
667 | struct device_node *np = ofdev->dev.of_node; | 667 | struct device_node *np = ofdev->dev.of_node; |
@@ -692,7 +692,7 @@ static int __devinit iic_request_irq(struct of_device *ofdev, | |||
692 | /* | 692 | /* |
693 | * Register single IIC interface | 693 | * Register single IIC interface |
694 | */ | 694 | */ |
695 | static int __devinit iic_probe(struct of_device *ofdev, | 695 | static int __devinit iic_probe(struct platform_device *ofdev, |
696 | const struct of_device_id *match) | 696 | const struct of_device_id *match) |
697 | { | 697 | { |
698 | struct device_node *np = ofdev->dev.of_node; | 698 | struct device_node *np = ofdev->dev.of_node; |
@@ -780,7 +780,7 @@ error_cleanup: | |||
780 | /* | 780 | /* |
781 | * Cleanup initialized IIC interface | 781 | * Cleanup initialized IIC interface |
782 | */ | 782 | */ |
783 | static int __devexit iic_remove(struct of_device *ofdev) | 783 | static int __devexit iic_remove(struct platform_device *ofdev) |
784 | { | 784 | { |
785 | struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); | 785 | struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); |
786 | 786 | ||
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 6545d1c99b61..a1c419a716af 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c | |||
@@ -560,7 +560,7 @@ static struct i2c_adapter mpc_ops = { | |||
560 | .timeout = HZ, | 560 | .timeout = HZ, |
561 | }; | 561 | }; |
562 | 562 | ||
563 | static int __devinit fsl_i2c_probe(struct of_device *op, | 563 | static int __devinit fsl_i2c_probe(struct platform_device *op, |
564 | const struct of_device_id *match) | 564 | const struct of_device_id *match) |
565 | { | 565 | { |
566 | struct mpc_i2c *i2c; | 566 | struct mpc_i2c *i2c; |
@@ -646,7 +646,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op, | |||
646 | return result; | 646 | return result; |
647 | }; | 647 | }; |
648 | 648 | ||
649 | static int __devexit fsl_i2c_remove(struct of_device *op) | 649 | static int __devexit fsl_i2c_remove(struct platform_device *op) |
650 | { | 650 | { |
651 | struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); | 651 | struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); |
652 | 652 | ||
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ffb405d7c6f2..598c49acaeb5 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
@@ -119,8 +119,10 @@ struct sh_mobile_i2c_data { | |||
119 | struct i2c_adapter adap; | 119 | struct i2c_adapter adap; |
120 | 120 | ||
121 | struct clk *clk; | 121 | struct clk *clk; |
122 | u_int8_t icic; | ||
122 | u_int8_t iccl; | 123 | u_int8_t iccl; |
123 | u_int8_t icch; | 124 | u_int8_t icch; |
125 | u_int8_t flags; | ||
124 | 126 | ||
125 | spinlock_t lock; | 127 | spinlock_t lock; |
126 | wait_queue_head_t wait; | 128 | wait_queue_head_t wait; |
@@ -129,15 +131,17 @@ struct sh_mobile_i2c_data { | |||
129 | int sr; | 131 | int sr; |
130 | }; | 132 | }; |
131 | 133 | ||
134 | #define IIC_FLAG_HAS_ICIC67 (1 << 0) | ||
135 | |||
132 | #define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ | 136 | #define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ |
133 | 137 | ||
134 | /* Register offsets */ | 138 | /* Register offsets */ |
135 | #define ICDR(pd) (pd->reg + 0x00) | 139 | #define ICDR 0x00 |
136 | #define ICCR(pd) (pd->reg + 0x04) | 140 | #define ICCR 0x04 |
137 | #define ICSR(pd) (pd->reg + 0x08) | 141 | #define ICSR 0x08 |
138 | #define ICIC(pd) (pd->reg + 0x0c) | 142 | #define ICIC 0x0c |
139 | #define ICCL(pd) (pd->reg + 0x10) | 143 | #define ICCL 0x10 |
140 | #define ICCH(pd) (pd->reg + 0x14) | 144 | #define ICCH 0x14 |
141 | 145 | ||
142 | /* Register bits */ | 146 | /* Register bits */ |
143 | #define ICCR_ICE 0x80 | 147 | #define ICCR_ICE 0x80 |
@@ -155,11 +159,32 @@ struct sh_mobile_i2c_data { | |||
155 | #define ICSR_WAIT 0x02 | 159 | #define ICSR_WAIT 0x02 |
156 | #define ICSR_DTE 0x01 | 160 | #define ICSR_DTE 0x01 |
157 | 161 | ||
162 | #define ICIC_ICCLB8 0x80 | ||
163 | #define ICIC_ICCHB8 0x40 | ||
158 | #define ICIC_ALE 0x08 | 164 | #define ICIC_ALE 0x08 |
159 | #define ICIC_TACKE 0x04 | 165 | #define ICIC_TACKE 0x04 |
160 | #define ICIC_WAITE 0x02 | 166 | #define ICIC_WAITE 0x02 |
161 | #define ICIC_DTEE 0x01 | 167 | #define ICIC_DTEE 0x01 |
162 | 168 | ||
169 | static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) | ||
170 | { | ||
171 | if (offs == ICIC) | ||
172 | data |= pd->icic; | ||
173 | |||
174 | iowrite8(data, pd->reg + offs); | ||
175 | } | ||
176 | |||
177 | static unsigned char iic_rd(struct sh_mobile_i2c_data *pd, int offs) | ||
178 | { | ||
179 | return ioread8(pd->reg + offs); | ||
180 | } | ||
181 | |||
182 | static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, | ||
183 | unsigned char set, unsigned char clr) | ||
184 | { | ||
185 | iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); | ||
186 | } | ||
187 | |||
163 | static void activate_ch(struct sh_mobile_i2c_data *pd) | 188 | static void activate_ch(struct sh_mobile_i2c_data *pd) |
164 | { | 189 | { |
165 | unsigned long i2c_clk; | 190 | unsigned long i2c_clk; |
@@ -187,6 +212,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) | |||
187 | else | 212 | else |
188 | pd->iccl = (u_int8_t)(num/denom); | 213 | pd->iccl = (u_int8_t)(num/denom); |
189 | 214 | ||
215 | /* one more bit of ICCL in ICIC */ | ||
216 | if (pd->flags & IIC_FLAG_HAS_ICIC67) { | ||
217 | if ((num/denom) > 0xff) | ||
218 | pd->icic |= ICIC_ICCLB8; | ||
219 | else | ||
220 | pd->icic &= ~ICIC_ICCLB8; | ||
221 | } | ||
222 | |||
190 | /* Calculate the value for icch. From the data sheet: | 223 | /* Calculate the value for icch. From the data sheet: |
191 | icch = (p clock / transfer rate) * (H / (L + H)) */ | 224 | icch = (p clock / transfer rate) * (H / (L + H)) */ |
192 | num = i2c_clk * 4; | 225 | num = i2c_clk * 4; |
@@ -196,25 +229,33 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) | |||
196 | else | 229 | else |
197 | pd->icch = (u_int8_t)(num/denom); | 230 | pd->icch = (u_int8_t)(num/denom); |
198 | 231 | ||
232 | /* one more bit of ICCH in ICIC */ | ||
233 | if (pd->flags & IIC_FLAG_HAS_ICIC67) { | ||
234 | if ((num/denom) > 0xff) | ||
235 | pd->icic |= ICIC_ICCHB8; | ||
236 | else | ||
237 | pd->icic &= ~ICIC_ICCHB8; | ||
238 | } | ||
239 | |||
199 | /* Enable channel and configure rx ack */ | 240 | /* Enable channel and configure rx ack */ |
200 | iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); | 241 | iic_set_clr(pd, ICCR, ICCR_ICE, 0); |
201 | 242 | ||
202 | /* Mask all interrupts */ | 243 | /* Mask all interrupts */ |
203 | iowrite8(0, ICIC(pd)); | 244 | iic_wr(pd, ICIC, 0); |
204 | 245 | ||
205 | /* Set the clock */ | 246 | /* Set the clock */ |
206 | iowrite8(pd->iccl, ICCL(pd)); | 247 | iic_wr(pd, ICCL, pd->iccl); |
207 | iowrite8(pd->icch, ICCH(pd)); | 248 | iic_wr(pd, ICCH, pd->icch); |
208 | } | 249 | } |
209 | 250 | ||
210 | static void deactivate_ch(struct sh_mobile_i2c_data *pd) | 251 | static void deactivate_ch(struct sh_mobile_i2c_data *pd) |
211 | { | 252 | { |
212 | /* Clear/disable interrupts */ | 253 | /* Clear/disable interrupts */ |
213 | iowrite8(0, ICSR(pd)); | 254 | iic_wr(pd, ICSR, 0); |
214 | iowrite8(0, ICIC(pd)); | 255 | iic_wr(pd, ICIC, 0); |
215 | 256 | ||
216 | /* Disable channel */ | 257 | /* Disable channel */ |
217 | iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); | 258 | iic_set_clr(pd, ICCR, 0, ICCR_ICE); |
218 | 259 | ||
219 | /* Disable clock and mark device as idle */ | 260 | /* Disable clock and mark device as idle */ |
220 | clk_disable(pd->clk); | 261 | clk_disable(pd->clk); |
@@ -233,35 +274,35 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, | |||
233 | 274 | ||
234 | switch (op) { | 275 | switch (op) { |
235 | case OP_START: /* issue start and trigger DTE interrupt */ | 276 | case OP_START: /* issue start and trigger DTE interrupt */ |
236 | iowrite8(0x94, ICCR(pd)); | 277 | iic_wr(pd, ICCR, 0x94); |
237 | break; | 278 | break; |
238 | case OP_TX_FIRST: /* disable DTE interrupt and write data */ | 279 | case OP_TX_FIRST: /* disable DTE interrupt and write data */ |
239 | iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd)); | 280 | iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
240 | iowrite8(data, ICDR(pd)); | 281 | iic_wr(pd, ICDR, data); |
241 | break; | 282 | break; |
242 | case OP_TX: /* write data */ | 283 | case OP_TX: /* write data */ |
243 | iowrite8(data, ICDR(pd)); | 284 | iic_wr(pd, ICDR, data); |
244 | break; | 285 | break; |
245 | case OP_TX_STOP: /* write data and issue a stop afterwards */ | 286 | case OP_TX_STOP: /* write data and issue a stop afterwards */ |
246 | iowrite8(data, ICDR(pd)); | 287 | iic_wr(pd, ICDR, data); |
247 | iowrite8(0x90, ICCR(pd)); | 288 | iic_wr(pd, ICCR, 0x90); |
248 | break; | 289 | break; |
249 | case OP_TX_TO_RX: /* select read mode */ | 290 | case OP_TX_TO_RX: /* select read mode */ |
250 | iowrite8(0x81, ICCR(pd)); | 291 | iic_wr(pd, ICCR, 0x81); |
251 | break; | 292 | break; |
252 | case OP_RX: /* just read data */ | 293 | case OP_RX: /* just read data */ |
253 | ret = ioread8(ICDR(pd)); | 294 | ret = iic_rd(pd, ICDR); |
254 | break; | 295 | break; |
255 | case OP_RX_STOP: /* enable DTE interrupt, issue stop */ | 296 | case OP_RX_STOP: /* enable DTE interrupt, issue stop */ |
256 | iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, | 297 | iic_wr(pd, ICIC, |
257 | ICIC(pd)); | 298 | ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
258 | iowrite8(0xc0, ICCR(pd)); | 299 | iic_wr(pd, ICCR, 0xc0); |
259 | break; | 300 | break; |
260 | case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ | 301 | case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ |
261 | iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, | 302 | iic_wr(pd, ICIC, |
262 | ICIC(pd)); | 303 | ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
263 | ret = ioread8(ICDR(pd)); | 304 | ret = iic_rd(pd, ICDR); |
264 | iowrite8(0xc0, ICCR(pd)); | 305 | iic_wr(pd, ICCR, 0xc0); |
265 | break; | 306 | break; |
266 | } | 307 | } |
267 | 308 | ||
@@ -367,7 +408,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) | |||
367 | unsigned char sr; | 408 | unsigned char sr; |
368 | int wakeup; | 409 | int wakeup; |
369 | 410 | ||
370 | sr = ioread8(ICSR(pd)); | 411 | sr = iic_rd(pd, ICSR); |
371 | pd->sr |= sr; /* remember state */ | 412 | pd->sr |= sr; /* remember state */ |
372 | 413 | ||
373 | dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, | 414 | dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, |
@@ -376,7 +417,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) | |||
376 | 417 | ||
377 | if (sr & (ICSR_AL | ICSR_TACK)) { | 418 | if (sr & (ICSR_AL | ICSR_TACK)) { |
378 | /* don't interrupt transaction - continue to issue stop */ | 419 | /* don't interrupt transaction - continue to issue stop */ |
379 | iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd)); | 420 | iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK)); |
380 | wakeup = 0; | 421 | wakeup = 0; |
381 | } else if (pd->msg->flags & I2C_M_RD) | 422 | } else if (pd->msg->flags & I2C_M_RD) |
382 | wakeup = sh_mobile_i2c_isr_rx(pd); | 423 | wakeup = sh_mobile_i2c_isr_rx(pd); |
@@ -384,7 +425,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) | |||
384 | wakeup = sh_mobile_i2c_isr_tx(pd); | 425 | wakeup = sh_mobile_i2c_isr_tx(pd); |
385 | 426 | ||
386 | if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ | 427 | if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ |
387 | iowrite8(sr & ~ICSR_WAIT, ICSR(pd)); | 428 | iic_wr(pd, ICSR, sr & ~ICSR_WAIT); |
388 | 429 | ||
389 | if (wakeup) { | 430 | if (wakeup) { |
390 | pd->sr |= SW_DONE; | 431 | pd->sr |= SW_DONE; |
@@ -402,21 +443,21 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) | |||
402 | } | 443 | } |
403 | 444 | ||
404 | /* Initialize channel registers */ | 445 | /* Initialize channel registers */ |
405 | iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); | 446 | iic_set_clr(pd, ICCR, 0, ICCR_ICE); |
406 | 447 | ||
407 | /* Enable channel and configure rx ack */ | 448 | /* Enable channel and configure rx ack */ |
408 | iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); | 449 | iic_set_clr(pd, ICCR, ICCR_ICE, 0); |
409 | 450 | ||
410 | /* Set the clock */ | 451 | /* Set the clock */ |
411 | iowrite8(pd->iccl, ICCL(pd)); | 452 | iic_wr(pd, ICCL, pd->iccl); |
412 | iowrite8(pd->icch, ICCH(pd)); | 453 | iic_wr(pd, ICCH, pd->icch); |
413 | 454 | ||
414 | pd->msg = usr_msg; | 455 | pd->msg = usr_msg; |
415 | pd->pos = -1; | 456 | pd->pos = -1; |
416 | pd->sr = 0; | 457 | pd->sr = 0; |
417 | 458 | ||
418 | /* Enable all interrupts to begin with */ | 459 | /* Enable all interrupts to begin with */ |
419 | iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd)); | 460 | iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
420 | return 0; | 461 | return 0; |
421 | } | 462 | } |
422 | 463 | ||
@@ -451,7 +492,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, | |||
451 | 492 | ||
452 | retry_count = 1000; | 493 | retry_count = 1000; |
453 | again: | 494 | again: |
454 | val = ioread8(ICSR(pd)); | 495 | val = iic_rd(pd, ICSR); |
455 | 496 | ||
456 | dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); | 497 | dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); |
457 | 498 | ||
@@ -576,6 +617,12 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
576 | goto err_irq; | 617 | goto err_irq; |
577 | } | 618 | } |
578 | 619 | ||
620 | /* The IIC blocks on SH-Mobile ARM processors | ||
621 | * come with two new bits in ICIC. | ||
622 | */ | ||
623 | if (size > 0x17) | ||
624 | pd->flags |= IIC_FLAG_HAS_ICIC67; | ||
625 | |||
579 | /* Enable Runtime PM for this device. | 626 | /* Enable Runtime PM for this device. |
580 | * | 627 | * |
581 | * Also tell the Runtime PM core to ignore children | 628 | * Also tell the Runtime PM core to ignore children |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index df937df845eb..6649176de940 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -20,7 +20,9 @@ | |||
20 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. | 20 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. |
21 | All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> | 21 | All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> |
22 | SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and | 22 | SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and |
23 | Jean Delvare <khali@linux-fr.org> */ | 23 | Jean Delvare <khali@linux-fr.org> |
24 | Mux support by Rodolfo Giometti <giometti@enneenne.com> and | ||
25 | Michael Lawnick <michael.lawnick.ext@nsn.com> */ | ||
24 | 26 | ||
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
@@ -423,11 +425,87 @@ static int __i2c_check_addr_busy(struct device *dev, void *addrp) | |||
423 | return 0; | 425 | return 0; |
424 | } | 426 | } |
425 | 427 | ||
428 | /* walk up mux tree */ | ||
429 | static int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr) | ||
430 | { | ||
431 | int result; | ||
432 | |||
433 | result = device_for_each_child(&adapter->dev, &addr, | ||
434 | __i2c_check_addr_busy); | ||
435 | |||
436 | if (!result && i2c_parent_is_i2c_adapter(adapter)) | ||
437 | result = i2c_check_mux_parents( | ||
438 | to_i2c_adapter(adapter->dev.parent), addr); | ||
439 | |||
440 | return result; | ||
441 | } | ||
442 | |||
443 | /* recurse down mux tree */ | ||
444 | static int i2c_check_mux_children(struct device *dev, void *addrp) | ||
445 | { | ||
446 | int result; | ||
447 | |||
448 | if (dev->type == &i2c_adapter_type) | ||
449 | result = device_for_each_child(dev, addrp, | ||
450 | i2c_check_mux_children); | ||
451 | else | ||
452 | result = __i2c_check_addr_busy(dev, addrp); | ||
453 | |||
454 | return result; | ||
455 | } | ||
456 | |||
426 | static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) | 457 | static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) |
427 | { | 458 | { |
428 | return device_for_each_child(&adapter->dev, &addr, | 459 | int result = 0; |
429 | __i2c_check_addr_busy); | 460 | |
461 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
462 | result = i2c_check_mux_parents( | ||
463 | to_i2c_adapter(adapter->dev.parent), addr); | ||
464 | |||
465 | if (!result) | ||
466 | result = device_for_each_child(&adapter->dev, &addr, | ||
467 | i2c_check_mux_children); | ||
468 | |||
469 | return result; | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * i2c_lock_adapter - Get exclusive access to an I2C bus segment | ||
474 | * @adapter: Target I2C bus segment | ||
475 | */ | ||
476 | void i2c_lock_adapter(struct i2c_adapter *adapter) | ||
477 | { | ||
478 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
479 | i2c_lock_adapter(to_i2c_adapter(adapter->dev.parent)); | ||
480 | else | ||
481 | rt_mutex_lock(&adapter->bus_lock); | ||
482 | } | ||
483 | EXPORT_SYMBOL_GPL(i2c_lock_adapter); | ||
484 | |||
485 | /** | ||
486 | * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment | ||
487 | * @adapter: Target I2C bus segment | ||
488 | */ | ||
489 | static int i2c_trylock_adapter(struct i2c_adapter *adapter) | ||
490 | { | ||
491 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
492 | return i2c_trylock_adapter(to_i2c_adapter(adapter->dev.parent)); | ||
493 | else | ||
494 | return rt_mutex_trylock(&adapter->bus_lock); | ||
495 | } | ||
496 | |||
497 | /** | ||
498 | * i2c_unlock_adapter - Release exclusive access to an I2C bus segment | ||
499 | * @adapter: Target I2C bus segment | ||
500 | */ | ||
501 | void i2c_unlock_adapter(struct i2c_adapter *adapter) | ||
502 | { | ||
503 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
504 | i2c_unlock_adapter(to_i2c_adapter(adapter->dev.parent)); | ||
505 | else | ||
506 | rt_mutex_unlock(&adapter->bus_lock); | ||
430 | } | 507 | } |
508 | EXPORT_SYMBOL_GPL(i2c_unlock_adapter); | ||
431 | 509 | ||
432 | /** | 510 | /** |
433 | * i2c_new_device - instantiate an i2c device | 511 | * i2c_new_device - instantiate an i2c device |
@@ -633,9 +711,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, | |||
633 | return -EINVAL; | 711 | return -EINVAL; |
634 | 712 | ||
635 | /* Keep track of the added device */ | 713 | /* Keep track of the added device */ |
636 | i2c_lock_adapter(adap); | 714 | mutex_lock(&adap->userspace_clients_lock); |
637 | list_add_tail(&client->detected, &adap->userspace_clients); | 715 | list_add_tail(&client->detected, &adap->userspace_clients); |
638 | i2c_unlock_adapter(adap); | 716 | mutex_unlock(&adap->userspace_clients_lock); |
639 | dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", | 717 | dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", |
640 | info.type, info.addr); | 718 | info.type, info.addr); |
641 | 719 | ||
@@ -674,7 +752,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, | |||
674 | 752 | ||
675 | /* Make sure the device was added through sysfs */ | 753 | /* Make sure the device was added through sysfs */ |
676 | res = -ENOENT; | 754 | res = -ENOENT; |
677 | i2c_lock_adapter(adap); | 755 | mutex_lock(&adap->userspace_clients_lock); |
678 | list_for_each_entry_safe(client, next, &adap->userspace_clients, | 756 | list_for_each_entry_safe(client, next, &adap->userspace_clients, |
679 | detected) { | 757 | detected) { |
680 | if (client->addr == addr) { | 758 | if (client->addr == addr) { |
@@ -687,7 +765,7 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, | |||
687 | break; | 765 | break; |
688 | } | 766 | } |
689 | } | 767 | } |
690 | i2c_unlock_adapter(adap); | 768 | mutex_unlock(&adap->userspace_clients_lock); |
691 | 769 | ||
692 | if (res < 0) | 770 | if (res < 0) |
693 | dev_err(dev, "%s: Can't find device in list\n", | 771 | dev_err(dev, "%s: Can't find device in list\n", |
@@ -714,10 +792,11 @@ static const struct attribute_group *i2c_adapter_attr_groups[] = { | |||
714 | NULL | 792 | NULL |
715 | }; | 793 | }; |
716 | 794 | ||
717 | static struct device_type i2c_adapter_type = { | 795 | struct device_type i2c_adapter_type = { |
718 | .groups = i2c_adapter_attr_groups, | 796 | .groups = i2c_adapter_attr_groups, |
719 | .release = i2c_adapter_dev_release, | 797 | .release = i2c_adapter_dev_release, |
720 | }; | 798 | }; |
799 | EXPORT_SYMBOL_GPL(i2c_adapter_type); | ||
721 | 800 | ||
722 | #ifdef CONFIG_I2C_COMPAT | 801 | #ifdef CONFIG_I2C_COMPAT |
723 | static struct class_compat *i2c_adapter_compat_class; | 802 | static struct class_compat *i2c_adapter_compat_class; |
@@ -760,7 +839,7 @@ static int __process_new_adapter(struct device_driver *d, void *data) | |||
760 | 839 | ||
761 | static int i2c_register_adapter(struct i2c_adapter *adap) | 840 | static int i2c_register_adapter(struct i2c_adapter *adap) |
762 | { | 841 | { |
763 | int res = 0, dummy; | 842 | int res = 0; |
764 | 843 | ||
765 | /* Can't register until after driver model init */ | 844 | /* Can't register until after driver model init */ |
766 | if (unlikely(WARN_ON(!i2c_bus_type.p))) { | 845 | if (unlikely(WARN_ON(!i2c_bus_type.p))) { |
@@ -769,6 +848,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
769 | } | 848 | } |
770 | 849 | ||
771 | rt_mutex_init(&adap->bus_lock); | 850 | rt_mutex_init(&adap->bus_lock); |
851 | mutex_init(&adap->userspace_clients_lock); | ||
772 | INIT_LIST_HEAD(&adap->userspace_clients); | 852 | INIT_LIST_HEAD(&adap->userspace_clients); |
773 | 853 | ||
774 | /* Set default timeout to 1 second if not already set */ | 854 | /* Set default timeout to 1 second if not already set */ |
@@ -801,8 +881,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
801 | 881 | ||
802 | /* Notify drivers */ | 882 | /* Notify drivers */ |
803 | mutex_lock(&core_lock); | 883 | mutex_lock(&core_lock); |
804 | dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, | 884 | bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); |
805 | __process_new_adapter); | ||
806 | mutex_unlock(&core_lock); | 885 | mutex_unlock(&core_lock); |
807 | 886 | ||
808 | return 0; | 887 | return 0; |
@@ -975,7 +1054,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
975 | return res; | 1054 | return res; |
976 | 1055 | ||
977 | /* Remove devices instantiated from sysfs */ | 1056 | /* Remove devices instantiated from sysfs */ |
978 | i2c_lock_adapter(adap); | 1057 | mutex_lock(&adap->userspace_clients_lock); |
979 | list_for_each_entry_safe(client, next, &adap->userspace_clients, | 1058 | list_for_each_entry_safe(client, next, &adap->userspace_clients, |
980 | detected) { | 1059 | detected) { |
981 | dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, | 1060 | dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, |
@@ -983,7 +1062,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
983 | list_del(&client->detected); | 1062 | list_del(&client->detected); |
984 | i2c_unregister_device(client); | 1063 | i2c_unregister_device(client); |
985 | } | 1064 | } |
986 | i2c_unlock_adapter(adap); | 1065 | mutex_unlock(&adap->userspace_clients_lock); |
987 | 1066 | ||
988 | /* Detach any active clients. This can't fail, thus we do not | 1067 | /* Detach any active clients. This can't fail, thus we do not |
989 | checking the returned value. */ | 1068 | checking the returned value. */ |
@@ -1238,12 +1317,12 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
1238 | #endif | 1317 | #endif |
1239 | 1318 | ||
1240 | if (in_atomic() || irqs_disabled()) { | 1319 | if (in_atomic() || irqs_disabled()) { |
1241 | ret = rt_mutex_trylock(&adap->bus_lock); | 1320 | ret = i2c_trylock_adapter(adap); |
1242 | if (!ret) | 1321 | if (!ret) |
1243 | /* I2C activity is ongoing. */ | 1322 | /* I2C activity is ongoing. */ |
1244 | return -EAGAIN; | 1323 | return -EAGAIN; |
1245 | } else { | 1324 | } else { |
1246 | rt_mutex_lock(&adap->bus_lock); | 1325 | i2c_lock_adapter(adap); |
1247 | } | 1326 | } |
1248 | 1327 | ||
1249 | /* Retry automatically on arbitration loss */ | 1328 | /* Retry automatically on arbitration loss */ |
@@ -1255,7 +1334,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
1255 | if (time_after(jiffies, orig_jiffies + adap->timeout)) | 1334 | if (time_after(jiffies, orig_jiffies + adap->timeout)) |
1256 | break; | 1335 | break; |
1257 | } | 1336 | } |
1258 | rt_mutex_unlock(&adap->bus_lock); | 1337 | i2c_unlock_adapter(adap); |
1259 | 1338 | ||
1260 | return ret; | 1339 | return ret; |
1261 | } else { | 1340 | } else { |
@@ -1350,13 +1429,17 @@ static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr) | |||
1350 | I2C_SMBUS_BYTE_DATA, &dummy); | 1429 | I2C_SMBUS_BYTE_DATA, &dummy); |
1351 | else | 1430 | else |
1352 | #endif | 1431 | #endif |
1353 | if ((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50 | 1432 | if (!((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50) |
1354 | || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) | 1433 | && i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) |
1355 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, | ||
1356 | I2C_SMBUS_BYTE, &dummy); | ||
1357 | else | ||
1358 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0, | 1434 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0, |
1359 | I2C_SMBUS_QUICK, NULL); | 1435 | I2C_SMBUS_QUICK, NULL); |
1436 | else if (i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) | ||
1437 | err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, | ||
1438 | I2C_SMBUS_BYTE, &dummy); | ||
1439 | else { | ||
1440 | dev_warn(&adap->dev, "No suitable probing method supported\n"); | ||
1441 | err = -EOPNOTSUPP; | ||
1442 | } | ||
1360 | 1443 | ||
1361 | return err >= 0; | 1444 | return err >= 0; |
1362 | } | 1445 | } |
@@ -1437,16 +1520,6 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | |||
1437 | if (!(adapter->class & driver->class)) | 1520 | if (!(adapter->class & driver->class)) |
1438 | goto exit_free; | 1521 | goto exit_free; |
1439 | 1522 | ||
1440 | /* Stop here if the bus doesn't support probing */ | ||
1441 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE)) { | ||
1442 | if (address_list[0] == I2C_CLIENT_END) | ||
1443 | goto exit_free; | ||
1444 | |||
1445 | dev_warn(&adapter->dev, "Probing not supported\n"); | ||
1446 | err = -EOPNOTSUPP; | ||
1447 | goto exit_free; | ||
1448 | } | ||
1449 | |||
1450 | for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { | 1523 | for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { |
1451 | dev_dbg(&adapter->dev, "found normal entry for adapter %d, " | 1524 | dev_dbg(&adapter->dev, "found normal entry for adapter %d, " |
1452 | "addr 0x%02x\n", adap_id, address_list[i]); | 1525 | "addr 0x%02x\n", adap_id, address_list[i]); |
@@ -1461,18 +1534,23 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | |||
1461 | return err; | 1534 | return err; |
1462 | } | 1535 | } |
1463 | 1536 | ||
1537 | int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) | ||
1538 | { | ||
1539 | return i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, | ||
1540 | I2C_SMBUS_QUICK, NULL) >= 0; | ||
1541 | } | ||
1542 | EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); | ||
1543 | |||
1464 | struct i2c_client * | 1544 | struct i2c_client * |
1465 | i2c_new_probed_device(struct i2c_adapter *adap, | 1545 | i2c_new_probed_device(struct i2c_adapter *adap, |
1466 | struct i2c_board_info *info, | 1546 | struct i2c_board_info *info, |
1467 | unsigned short const *addr_list) | 1547 | unsigned short const *addr_list, |
1548 | int (*probe)(struct i2c_adapter *, unsigned short addr)) | ||
1468 | { | 1549 | { |
1469 | int i; | 1550 | int i; |
1470 | 1551 | ||
1471 | /* Stop here if the bus doesn't support probing */ | 1552 | if (!probe) |
1472 | if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) { | 1553 | probe = i2c_default_probe; |
1473 | dev_err(&adap->dev, "Probing not supported\n"); | ||
1474 | return NULL; | ||
1475 | } | ||
1476 | 1554 | ||
1477 | for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { | 1555 | for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { |
1478 | /* Check address validity */ | 1556 | /* Check address validity */ |
@@ -1490,7 +1568,7 @@ i2c_new_probed_device(struct i2c_adapter *adap, | |||
1490 | } | 1568 | } |
1491 | 1569 | ||
1492 | /* Test address responsiveness */ | 1570 | /* Test address responsiveness */ |
1493 | if (i2c_default_probe(adap, addr_list[i])) | 1571 | if (probe(adap, addr_list[i])) |
1494 | break; | 1572 | break; |
1495 | } | 1573 | } |
1496 | 1574 | ||
@@ -2002,7 +2080,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, | |||
2002 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; | 2080 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; |
2003 | 2081 | ||
2004 | if (adapter->algo->smbus_xfer) { | 2082 | if (adapter->algo->smbus_xfer) { |
2005 | rt_mutex_lock(&adapter->bus_lock); | 2083 | i2c_lock_adapter(adapter); |
2006 | 2084 | ||
2007 | /* Retry automatically on arbitration loss */ | 2085 | /* Retry automatically on arbitration loss */ |
2008 | orig_jiffies = jiffies; | 2086 | orig_jiffies = jiffies; |
@@ -2016,7 +2094,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, | |||
2016 | orig_jiffies + adapter->timeout)) | 2094 | orig_jiffies + adapter->timeout)) |
2017 | break; | 2095 | break; |
2018 | } | 2096 | } |
2019 | rt_mutex_unlock(&adapter->bus_lock); | 2097 | i2c_unlock_adapter(adapter); |
2020 | } else | 2098 | } else |
2021 | res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, | 2099 | res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, |
2022 | command, protocol, data); | 2100 | command, protocol, data); |
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index e0694e4d86c7..5f3a52d517c3 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -167,13 +167,9 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf, | |||
167 | if (count > 8192) | 167 | if (count > 8192) |
168 | count = 8192; | 168 | count = 8192; |
169 | 169 | ||
170 | tmp = kmalloc(count, GFP_KERNEL); | 170 | tmp = memdup_user(buf, count); |
171 | if (tmp == NULL) | 171 | if (IS_ERR(tmp)) |
172 | return -ENOMEM; | 172 | return PTR_ERR(tmp); |
173 | if (copy_from_user(tmp, buf, count)) { | ||
174 | kfree(tmp); | ||
175 | return -EFAULT; | ||
176 | } | ||
177 | 173 | ||
178 | pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", | 174 | pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", |
179 | iminor(file->f_path.dentry->d_inode), count); | 175 | iminor(file->f_path.dentry->d_inode), count); |
@@ -193,12 +189,50 @@ static int i2cdev_check(struct device *dev, void *addrp) | |||
193 | return dev->driver ? -EBUSY : 0; | 189 | return dev->driver ? -EBUSY : 0; |
194 | } | 190 | } |
195 | 191 | ||
192 | /* walk up mux tree */ | ||
193 | static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) | ||
194 | { | ||
195 | int result; | ||
196 | |||
197 | result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); | ||
198 | |||
199 | if (!result && i2c_parent_is_i2c_adapter(adapter)) | ||
200 | result = i2cdev_check_mux_parents( | ||
201 | to_i2c_adapter(adapter->dev.parent), addr); | ||
202 | |||
203 | return result; | ||
204 | } | ||
205 | |||
206 | /* recurse down mux tree */ | ||
207 | static int i2cdev_check_mux_children(struct device *dev, void *addrp) | ||
208 | { | ||
209 | int result; | ||
210 | |||
211 | if (dev->type == &i2c_adapter_type) | ||
212 | result = device_for_each_child(dev, addrp, | ||
213 | i2cdev_check_mux_children); | ||
214 | else | ||
215 | result = i2cdev_check(dev, addrp); | ||
216 | |||
217 | return result; | ||
218 | } | ||
219 | |||
196 | /* This address checking function differs from the one in i2c-core | 220 | /* This address checking function differs from the one in i2c-core |
197 | in that it considers an address with a registered device, but no | 221 | in that it considers an address with a registered device, but no |
198 | driver bound to it, as NOT busy. */ | 222 | driver bound to it, as NOT busy. */ |
199 | static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) | 223 | static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) |
200 | { | 224 | { |
201 | return device_for_each_child(&adapter->dev, &addr, i2cdev_check); | 225 | int result = 0; |
226 | |||
227 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
228 | result = i2cdev_check_mux_parents( | ||
229 | to_i2c_adapter(adapter->dev.parent), addr); | ||
230 | |||
231 | if (!result) | ||
232 | result = device_for_each_child(&adapter->dev, &addr, | ||
233 | i2cdev_check_mux_children); | ||
234 | |||
235 | return result; | ||
202 | } | 236 | } |
203 | 237 | ||
204 | static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | 238 | static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, |
@@ -219,9 +253,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | |||
219 | if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) | 253 | if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) |
220 | return -EINVAL; | 254 | return -EINVAL; |
221 | 255 | ||
222 | rdwr_pa = (struct i2c_msg *) | 256 | rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL); |
223 | kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), | ||
224 | GFP_KERNEL); | ||
225 | if (!rdwr_pa) | 257 | if (!rdwr_pa) |
226 | return -ENOMEM; | 258 | return -ENOMEM; |
227 | 259 | ||
@@ -247,15 +279,9 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | |||
247 | break; | 279 | break; |
248 | } | 280 | } |
249 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; | 281 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; |
250 | rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); | 282 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); |
251 | if (rdwr_pa[i].buf == NULL) { | 283 | if (IS_ERR(rdwr_pa[i].buf)) { |
252 | res = -ENOMEM; | 284 | res = PTR_ERR(rdwr_pa[i].buf); |
253 | break; | ||
254 | } | ||
255 | if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i], | ||
256 | rdwr_pa[i].len)) { | ||
257 | ++i; /* Needs to be kfreed too */ | ||
258 | res = -EFAULT; | ||
259 | break; | 285 | break; |
260 | } | 286 | } |
261 | } | 287 | } |
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c new file mode 100644 index 000000000000..d32a4843fc3a --- /dev/null +++ b/drivers/i2c/i2c-mux.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Multiplexed I2C bus driver. | ||
3 | * | ||
4 | * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * Copyright (c) 2009-2010 NSN GmbH & Co KG <michael.lawnick.ext@nsn.com> | ||
7 | * | ||
8 | * Simplifies access to complex multiplexed I2C bus topologies, by presenting | ||
9 | * each multiplexed bus segment as an additional I2C adapter. | ||
10 | * Supports multi-level mux'ing (mux behind a mux). | ||
11 | * | ||
12 | * Based on: | ||
13 | * i2c-virt.c from Kumar Gala <galak@kernel.crashing.org> | ||
14 | * i2c-virtual.c from Ken Harrenstien, Copyright (c) 2004 Google, Inc. | ||
15 | * i2c-virtual.c from Brian Kuschak <bkuschak@yahoo.com> | ||
16 | * | ||
17 | * This file is licensed under the terms of the GNU General Public | ||
18 | * License version 2. This program is licensed "as is" without any | ||
19 | * warranty of any kind, whether express or implied. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/i2c-mux.h> | ||
27 | |||
28 | /* multiplexer per channel data */ | ||
29 | struct i2c_mux_priv { | ||
30 | struct i2c_adapter adap; | ||
31 | struct i2c_algorithm algo; | ||
32 | |||
33 | struct i2c_adapter *parent; | ||
34 | void *mux_dev; /* the mux chip/device */ | ||
35 | u32 chan_id; /* the channel id */ | ||
36 | |||
37 | int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); | ||
38 | int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); | ||
39 | }; | ||
40 | |||
41 | static int i2c_mux_master_xfer(struct i2c_adapter *adap, | ||
42 | struct i2c_msg msgs[], int num) | ||
43 | { | ||
44 | struct i2c_mux_priv *priv = adap->algo_data; | ||
45 | struct i2c_adapter *parent = priv->parent; | ||
46 | int ret; | ||
47 | |||
48 | /* Switch to the right mux port and perform the transfer. */ | ||
49 | |||
50 | ret = priv->select(parent, priv->mux_dev, priv->chan_id); | ||
51 | if (ret >= 0) | ||
52 | ret = parent->algo->master_xfer(parent, msgs, num); | ||
53 | if (priv->deselect) | ||
54 | priv->deselect(parent, priv->mux_dev, priv->chan_id); | ||
55 | |||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, | ||
60 | u16 addr, unsigned short flags, | ||
61 | char read_write, u8 command, | ||
62 | int size, union i2c_smbus_data *data) | ||
63 | { | ||
64 | struct i2c_mux_priv *priv = adap->algo_data; | ||
65 | struct i2c_adapter *parent = priv->parent; | ||
66 | int ret; | ||
67 | |||
68 | /* Select the right mux port and perform the transfer. */ | ||
69 | |||
70 | ret = priv->select(parent, priv->mux_dev, priv->chan_id); | ||
71 | if (ret >= 0) | ||
72 | ret = parent->algo->smbus_xfer(parent, addr, flags, | ||
73 | read_write, command, size, data); | ||
74 | if (priv->deselect) | ||
75 | priv->deselect(parent, priv->mux_dev, priv->chan_id); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | /* Return the parent's functionality */ | ||
81 | static u32 i2c_mux_functionality(struct i2c_adapter *adap) | ||
82 | { | ||
83 | struct i2c_mux_priv *priv = adap->algo_data; | ||
84 | struct i2c_adapter *parent = priv->parent; | ||
85 | |||
86 | return parent->algo->functionality(parent); | ||
87 | } | ||
88 | |||
89 | struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, | ||
90 | void *mux_dev, u32 force_nr, u32 chan_id, | ||
91 | int (*select) (struct i2c_adapter *, | ||
92 | void *, u32), | ||
93 | int (*deselect) (struct i2c_adapter *, | ||
94 | void *, u32)) | ||
95 | { | ||
96 | struct i2c_mux_priv *priv; | ||
97 | int ret; | ||
98 | |||
99 | priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL); | ||
100 | if (!priv) | ||
101 | return NULL; | ||
102 | |||
103 | /* Set up private adapter data */ | ||
104 | priv->parent = parent; | ||
105 | priv->mux_dev = mux_dev; | ||
106 | priv->chan_id = chan_id; | ||
107 | priv->select = select; | ||
108 | priv->deselect = deselect; | ||
109 | |||
110 | /* Need to do algo dynamically because we don't know ahead | ||
111 | * of time what sort of physical adapter we'll be dealing with. | ||
112 | */ | ||
113 | if (parent->algo->master_xfer) | ||
114 | priv->algo.master_xfer = i2c_mux_master_xfer; | ||
115 | if (parent->algo->smbus_xfer) | ||
116 | priv->algo.smbus_xfer = i2c_mux_smbus_xfer; | ||
117 | priv->algo.functionality = i2c_mux_functionality; | ||
118 | |||
119 | /* Now fill out new adapter structure */ | ||
120 | snprintf(priv->adap.name, sizeof(priv->adap.name), | ||
121 | "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id); | ||
122 | priv->adap.owner = THIS_MODULE; | ||
123 | priv->adap.id = parent->id; | ||
124 | priv->adap.algo = &priv->algo; | ||
125 | priv->adap.algo_data = priv; | ||
126 | priv->adap.dev.parent = &parent->dev; | ||
127 | |||
128 | if (force_nr) { | ||
129 | priv->adap.nr = force_nr; | ||
130 | ret = i2c_add_numbered_adapter(&priv->adap); | ||
131 | } else { | ||
132 | ret = i2c_add_adapter(&priv->adap); | ||
133 | } | ||
134 | if (ret < 0) { | ||
135 | dev_err(&parent->dev, | ||
136 | "failed to add mux-adapter (error=%d)\n", | ||
137 | ret); | ||
138 | kfree(priv); | ||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", | ||
143 | i2c_adapter_id(&priv->adap)); | ||
144 | |||
145 | return &priv->adap; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); | ||
148 | |||
149 | int i2c_del_mux_adapter(struct i2c_adapter *adap) | ||
150 | { | ||
151 | struct i2c_mux_priv *priv = adap->algo_data; | ||
152 | int ret; | ||
153 | |||
154 | ret = i2c_del_adapter(adap); | ||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | kfree(priv); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(i2c_del_mux_adapter); | ||
162 | |||
163 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
164 | MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses"); | ||
165 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig new file mode 100644 index 000000000000..4c9a99c4fcb0 --- /dev/null +++ b/drivers/i2c/muxes/Kconfig | |||
@@ -0,0 +1,18 @@ | |||
1 | # | ||
2 | # Multiplexer I2C chip drivers configuration | ||
3 | # | ||
4 | |||
5 | menu "Multiplexer I2C Chip support" | ||
6 | depends on I2C_MUX | ||
7 | |||
8 | config I2C_MUX_PCA954x | ||
9 | tristate "Philips PCA954x I2C Mux/switches" | ||
10 | depends on EXPERIMENTAL | ||
11 | help | ||
12 | If you say yes here you get support for the Philips PCA954x | ||
13 | I2C mux/switch devices. | ||
14 | |||
15 | This driver can also be built as a module. If so, the module | ||
16 | will be called pca954x. | ||
17 | |||
18 | endmenu | ||
diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile new file mode 100644 index 000000000000..bd83b5274815 --- /dev/null +++ b/drivers/i2c/muxes/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for multiplexer I2C chip drivers. | ||
3 | |||
4 | obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o | ||
5 | |||
6 | ifeq ($(CONFIG_I2C_DEBUG_BUS),y) | ||
7 | EXTRA_CFLAGS += -DDEBUG | ||
8 | endif | ||
diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c new file mode 100644 index 000000000000..6f9accf3189d --- /dev/null +++ b/drivers/i2c/muxes/pca954x.c | |||
@@ -0,0 +1,301 @@ | |||
1 | /* | ||
2 | * I2C multiplexer | ||
3 | * | ||
4 | * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * | ||
7 | * This module supports the PCA954x series of I2C multiplexer/switch chips | ||
8 | * made by Philips Semiconductors. | ||
9 | * This includes the: | ||
10 | * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 | ||
11 | * and PCA9548. | ||
12 | * | ||
13 | * These chips are all controlled via the I2C bus itself, and all have a | ||
14 | * single 8-bit register. The upstream "parent" bus fans out to two, | ||
15 | * four, or eight downstream busses or channels; which of these | ||
16 | * are selected is determined by the chip type and register contents. A | ||
17 | * mux can select only one sub-bus at a time; a switch can select any | ||
18 | * combination simultaneously. | ||
19 | * | ||
20 | * Based on: | ||
21 | * pca954x.c from Kumar Gala <galak@kernel.crashing.org> | ||
22 | * Copyright (C) 2006 | ||
23 | * | ||
24 | * Based on: | ||
25 | * pca954x.c from Ken Harrenstien | ||
26 | * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) | ||
27 | * | ||
28 | * Based on: | ||
29 | * i2c-virtual_cb.c from Brian Kuschak <bkuschak@yahoo.com> | ||
30 | * and | ||
31 | * pca9540.c from Jean Delvare <khali@linux-fr.org>. | ||
32 | * | ||
33 | * This file is licensed under the terms of the GNU General Public | ||
34 | * License version 2. This program is licensed "as is" without any | ||
35 | * warranty of any kind, whether express or implied. | ||
36 | */ | ||
37 | |||
38 | #include <linux/module.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/device.h> | ||
42 | #include <linux/i2c.h> | ||
43 | #include <linux/i2c-mux.h> | ||
44 | |||
45 | #include <linux/i2c/pca954x.h> | ||
46 | |||
47 | #define PCA954X_MAX_NCHANS 8 | ||
48 | |||
49 | enum pca_type { | ||
50 | pca_9540, | ||
51 | pca_9542, | ||
52 | pca_9543, | ||
53 | pca_9544, | ||
54 | pca_9545, | ||
55 | pca_9546, | ||
56 | pca_9547, | ||
57 | pca_9548, | ||
58 | }; | ||
59 | |||
60 | struct pca954x { | ||
61 | enum pca_type type; | ||
62 | struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; | ||
63 | |||
64 | u8 last_chan; /* last register value */ | ||
65 | }; | ||
66 | |||
67 | struct chip_desc { | ||
68 | u8 nchans; | ||
69 | u8 enable; /* used for muxes only */ | ||
70 | enum muxtype { | ||
71 | pca954x_ismux = 0, | ||
72 | pca954x_isswi | ||
73 | } muxtype; | ||
74 | }; | ||
75 | |||
76 | /* Provide specs for the PCA954x types we know about */ | ||
77 | static const struct chip_desc chips[] = { | ||
78 | [pca_9540] = { | ||
79 | .nchans = 2, | ||
80 | .enable = 0x4, | ||
81 | .muxtype = pca954x_ismux, | ||
82 | }, | ||
83 | [pca_9543] = { | ||
84 | .nchans = 2, | ||
85 | .muxtype = pca954x_isswi, | ||
86 | }, | ||
87 | [pca_9544] = { | ||
88 | .nchans = 4, | ||
89 | .enable = 0x4, | ||
90 | .muxtype = pca954x_ismux, | ||
91 | }, | ||
92 | [pca_9545] = { | ||
93 | .nchans = 4, | ||
94 | .muxtype = pca954x_isswi, | ||
95 | }, | ||
96 | [pca_9547] = { | ||
97 | .nchans = 8, | ||
98 | .enable = 0x8, | ||
99 | .muxtype = pca954x_ismux, | ||
100 | }, | ||
101 | [pca_9548] = { | ||
102 | .nchans = 8, | ||
103 | .muxtype = pca954x_isswi, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | static const struct i2c_device_id pca954x_id[] = { | ||
108 | { "pca9540", pca_9540 }, | ||
109 | { "pca9542", pca_9540 }, | ||
110 | { "pca9543", pca_9543 }, | ||
111 | { "pca9544", pca_9544 }, | ||
112 | { "pca9545", pca_9545 }, | ||
113 | { "pca9546", pca_9545 }, | ||
114 | { "pca9547", pca_9547 }, | ||
115 | { "pca9548", pca_9548 }, | ||
116 | { } | ||
117 | }; | ||
118 | MODULE_DEVICE_TABLE(i2c, pca954x_id); | ||
119 | |||
120 | /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() | ||
121 | for this as they will try to lock adapter a second time */ | ||
122 | static int pca954x_reg_write(struct i2c_adapter *adap, | ||
123 | struct i2c_client *client, u8 val) | ||
124 | { | ||
125 | int ret = -ENODEV; | ||
126 | |||
127 | if (adap->algo->master_xfer) { | ||
128 | struct i2c_msg msg; | ||
129 | char buf[1]; | ||
130 | |||
131 | msg.addr = client->addr; | ||
132 | msg.flags = 0; | ||
133 | msg.len = 1; | ||
134 | buf[0] = val; | ||
135 | msg.buf = buf; | ||
136 | ret = adap->algo->master_xfer(adap, &msg, 1); | ||
137 | } else { | ||
138 | union i2c_smbus_data data; | ||
139 | ret = adap->algo->smbus_xfer(adap, client->addr, | ||
140 | client->flags, | ||
141 | I2C_SMBUS_WRITE, | ||
142 | val, I2C_SMBUS_BYTE, &data); | ||
143 | } | ||
144 | |||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static int pca954x_select_chan(struct i2c_adapter *adap, | ||
149 | void *client, u32 chan) | ||
150 | { | ||
151 | struct pca954x *data = i2c_get_clientdata(client); | ||
152 | const struct chip_desc *chip = &chips[data->type]; | ||
153 | u8 regval; | ||
154 | int ret = 0; | ||
155 | |||
156 | /* we make switches look like muxes, not sure how to be smarter */ | ||
157 | if (chip->muxtype == pca954x_ismux) | ||
158 | regval = chan | chip->enable; | ||
159 | else | ||
160 | regval = 1 << chan; | ||
161 | |||
162 | /* Only select the channel if its different from the last channel */ | ||
163 | if (data->last_chan != regval) { | ||
164 | ret = pca954x_reg_write(adap, client, regval); | ||
165 | data->last_chan = regval; | ||
166 | } | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static int pca954x_deselect_mux(struct i2c_adapter *adap, | ||
172 | void *client, u32 chan) | ||
173 | { | ||
174 | struct pca954x *data = i2c_get_clientdata(client); | ||
175 | |||
176 | /* Deselect active channel */ | ||
177 | data->last_chan = 0; | ||
178 | return pca954x_reg_write(adap, client, data->last_chan); | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * I2C init/probing/exit functions | ||
183 | */ | ||
184 | static int __devinit pca954x_probe(struct i2c_client *client, | ||
185 | const struct i2c_device_id *id) | ||
186 | { | ||
187 | struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); | ||
188 | struct pca954x_platform_data *pdata = client->dev.platform_data; | ||
189 | int num, force; | ||
190 | struct pca954x *data; | ||
191 | int ret = -ENODEV; | ||
192 | |||
193 | if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) | ||
194 | goto err; | ||
195 | |||
196 | data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); | ||
197 | if (!data) { | ||
198 | ret = -ENOMEM; | ||
199 | goto err; | ||
200 | } | ||
201 | |||
202 | i2c_set_clientdata(client, data); | ||
203 | |||
204 | /* Read the mux register at addr to verify | ||
205 | * that the mux is in fact present. | ||
206 | */ | ||
207 | if (i2c_smbus_read_byte(client) < 0) { | ||
208 | dev_warn(&client->dev, "probe failed\n"); | ||
209 | goto exit_free; | ||
210 | } | ||
211 | |||
212 | data->type = id->driver_data; | ||
213 | data->last_chan = 0; /* force the first selection */ | ||
214 | |||
215 | /* Now create an adapter for each channel */ | ||
216 | for (num = 0; num < chips[data->type].nchans; num++) { | ||
217 | force = 0; /* dynamic adap number */ | ||
218 | if (pdata) { | ||
219 | if (num < pdata->num_modes) | ||
220 | /* force static number */ | ||
221 | force = pdata->modes[num].adap_id; | ||
222 | else | ||
223 | /* discard unconfigured channels */ | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | data->virt_adaps[num] = | ||
228 | i2c_add_mux_adapter(adap, client, | ||
229 | force, num, pca954x_select_chan, | ||
230 | (pdata && pdata->modes[num].deselect_on_exit) | ||
231 | ? pca954x_deselect_mux : NULL); | ||
232 | |||
233 | if (data->virt_adaps[num] == NULL) { | ||
234 | ret = -ENODEV; | ||
235 | dev_err(&client->dev, | ||
236 | "failed to register multiplexed adapter" | ||
237 | " %d as bus %d\n", num, force); | ||
238 | goto virt_reg_failed; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | dev_info(&client->dev, | ||
243 | "registered %d multiplexed busses for I2C %s %s\n", | ||
244 | num, chips[data->type].muxtype == pca954x_ismux | ||
245 | ? "mux" : "switch", client->name); | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | virt_reg_failed: | ||
250 | for (num--; num >= 0; num--) | ||
251 | i2c_del_mux_adapter(data->virt_adaps[num]); | ||
252 | exit_free: | ||
253 | kfree(data); | ||
254 | err: | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static int __devexit pca954x_remove(struct i2c_client *client) | ||
259 | { | ||
260 | struct pca954x *data = i2c_get_clientdata(client); | ||
261 | const struct chip_desc *chip = &chips[data->type]; | ||
262 | int i, err; | ||
263 | |||
264 | for (i = 0; i < chip->nchans; ++i) | ||
265 | if (data->virt_adaps[i]) { | ||
266 | err = i2c_del_mux_adapter(data->virt_adaps[i]); | ||
267 | if (err) | ||
268 | return err; | ||
269 | data->virt_adaps[i] = NULL; | ||
270 | } | ||
271 | |||
272 | kfree(data); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static struct i2c_driver pca954x_driver = { | ||
277 | .driver = { | ||
278 | .name = "pca954x", | ||
279 | .owner = THIS_MODULE, | ||
280 | }, | ||
281 | .probe = pca954x_probe, | ||
282 | .remove = __devexit_p(pca954x_remove), | ||
283 | .id_table = pca954x_id, | ||
284 | }; | ||
285 | |||
286 | static int __init pca954x_init(void) | ||
287 | { | ||
288 | return i2c_add_driver(&pca954x_driver); | ||
289 | } | ||
290 | |||
291 | static void __exit pca954x_exit(void) | ||
292 | { | ||
293 | i2c_del_driver(&pca954x_driver); | ||
294 | } | ||
295 | |||
296 | module_init(pca954x_init); | ||
297 | module_exit(pca954x_exit); | ||
298 | |||
299 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
300 | MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); | ||
301 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3cb9c4e056ff..fa896210ed7b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -177,7 +177,7 @@ EXPORT_SYMBOL_GPL(ide_pci_clk); | |||
177 | module_param_named(pci_clock, ide_pci_clk, int, 0); | 177 | module_param_named(pci_clock, ide_pci_clk, int, 0); |
178 | MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); | 178 | MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); |
179 | 179 | ||
180 | static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | 180 | static int ide_set_dev_param_mask(const char *s, const struct kernel_param *kp) |
181 | { | 181 | { |
182 | int a, b, i, j = 1; | 182 | int a, b, i, j = 1; |
183 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; | 183 | unsigned int *dev_param_mask = (unsigned int *)kp->arg; |
@@ -200,34 +200,40 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) | |||
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
203 | static struct kernel_param_ops param_ops_ide_dev_mask = { | ||
204 | .set = ide_set_dev_param_mask | ||
205 | }; | ||
206 | |||
207 | #define param_check_ide_dev_mask(name, p) param_check_uint(name, p) | ||
208 | |||
203 | static unsigned int ide_nodma; | 209 | static unsigned int ide_nodma; |
204 | 210 | ||
205 | module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0); | 211 | module_param_named(nodma, ide_nodma, ide_dev_mask, 0); |
206 | MODULE_PARM_DESC(nodma, "disallow DMA for a device"); | 212 | MODULE_PARM_DESC(nodma, "disallow DMA for a device"); |
207 | 213 | ||
208 | static unsigned int ide_noflush; | 214 | static unsigned int ide_noflush; |
209 | 215 | ||
210 | module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); | 216 | module_param_named(noflush, ide_noflush, ide_dev_mask, 0); |
211 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); | 217 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); |
212 | 218 | ||
213 | static unsigned int ide_nohpa; | 219 | static unsigned int ide_nohpa; |
214 | 220 | ||
215 | module_param_call(nohpa, ide_set_dev_param_mask, NULL, &ide_nohpa, 0); | 221 | module_param_named(nohpa, ide_nohpa, ide_dev_mask, 0); |
216 | MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); | 222 | MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); |
217 | 223 | ||
218 | static unsigned int ide_noprobe; | 224 | static unsigned int ide_noprobe; |
219 | 225 | ||
220 | module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); | 226 | module_param_named(noprobe, ide_noprobe, ide_dev_mask, 0); |
221 | MODULE_PARM_DESC(noprobe, "skip probing for a device"); | 227 | MODULE_PARM_DESC(noprobe, "skip probing for a device"); |
222 | 228 | ||
223 | static unsigned int ide_nowerr; | 229 | static unsigned int ide_nowerr; |
224 | 230 | ||
225 | module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); | 231 | module_param_named(nowerr, ide_nowerr, ide_dev_mask, 0); |
226 | MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); | 232 | MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); |
227 | 233 | ||
228 | static unsigned int ide_cdroms; | 234 | static unsigned int ide_cdroms; |
229 | 235 | ||
230 | module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0); | 236 | module_param_named(cdrom, ide_cdroms, ide_dev_mask, 0); |
231 | MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); | 237 | MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); |
232 | 238 | ||
233 | struct chs_geom { | 239 | struct chs_geom { |
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 0136abd50dd4..aaf6023a4835 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -112,7 +112,7 @@ struct ehca_sport { | |||
112 | 112 | ||
113 | struct ehca_shca { | 113 | struct ehca_shca { |
114 | struct ib_device ib_device; | 114 | struct ib_device ib_device; |
115 | struct of_device *ofdev; | 115 | struct platform_device *ofdev; |
116 | u8 num_ports; | 116 | u8 num_ports; |
117 | int hw_level; | 117 | int hw_level; |
118 | struct list_head shca_list; | 118 | struct list_head shca_list; |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index cfc4de7a5da4..c240e9972cb0 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -713,7 +713,7 @@ static struct attribute_group ehca_dev_attr_grp = { | |||
713 | .attrs = ehca_dev_attrs | 713 | .attrs = ehca_dev_attrs |
714 | }; | 714 | }; |
715 | 715 | ||
716 | static int __devinit ehca_probe(struct of_device *dev, | 716 | static int __devinit ehca_probe(struct platform_device *dev, |
717 | const struct of_device_id *id) | 717 | const struct of_device_id *id) |
718 | { | 718 | { |
719 | struct ehca_shca *shca; | 719 | struct ehca_shca *shca; |
@@ -879,7 +879,7 @@ probe1: | |||
879 | return -EINVAL; | 879 | return -EINVAL; |
880 | } | 880 | } |
881 | 881 | ||
882 | static int __devexit ehca_remove(struct of_device *dev) | 882 | static int __devexit ehca_remove(struct platform_device *dev) |
883 | { | 883 | { |
884 | struct ehca_shca *shca = dev_get_drvdata(&dev->dev); | 884 | struct ehca_shca *shca = dev_get_drvdata(&dev->dev); |
885 | unsigned long flags; | 885 | unsigned long flags; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b171f63fe4d7..9cc488d21490 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -395,6 +395,16 @@ config KEYBOARD_SH_KEYSC | |||
395 | To compile this driver as a module, choose M here: the | 395 | To compile this driver as a module, choose M here: the |
396 | module will be called sh_keysc. | 396 | module will be called sh_keysc. |
397 | 397 | ||
398 | config KEYBOARD_STMPE | ||
399 | tristate "STMPE keypad support" | ||
400 | depends on MFD_STMPE | ||
401 | help | ||
402 | Say Y here if you want to use the keypad controller on STMPE I/O | ||
403 | expanders. | ||
404 | |||
405 | To compile this driver as a module, choose M here: the module will be | ||
406 | called stmpe-keypad. | ||
407 | |||
398 | config KEYBOARD_DAVINCI | 408 | config KEYBOARD_DAVINCI |
399 | tristate "TI DaVinci Key Scan" | 409 | tristate "TI DaVinci Key Scan" |
400 | depends on ARCH_DAVINCI_DM365 | 410 | depends on ARCH_DAVINCI_DM365 |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 1a66d5f1ca8b..504b591be0cd 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -35,6 +35,7 @@ obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | |||
35 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | 35 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o |
36 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o | 36 | obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o |
37 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 37 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
38 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o | ||
38 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 39 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
39 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 40 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
40 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 41 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c new file mode 100644 index 000000000000..ab7610ca10eb --- /dev/null +++ b/drivers/input/keyboard/stmpe-keypad.c | |||
@@ -0,0 +1,386 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/input.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/input/matrix_keypad.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | |||
17 | /* These are at the same addresses in all STMPE variants */ | ||
18 | #define STMPE_KPC_COL 0x60 | ||
19 | #define STMPE_KPC_ROW_MSB 0x61 | ||
20 | #define STMPE_KPC_ROW_LSB 0x62 | ||
21 | #define STMPE_KPC_CTRL_MSB 0x63 | ||
22 | #define STMPE_KPC_CTRL_LSB 0x64 | ||
23 | #define STMPE_KPC_COMBI_KEY_0 0x65 | ||
24 | #define STMPE_KPC_COMBI_KEY_1 0x66 | ||
25 | #define STMPE_KPC_COMBI_KEY_2 0x67 | ||
26 | #define STMPE_KPC_DATA_BYTE0 0x68 | ||
27 | #define STMPE_KPC_DATA_BYTE1 0x69 | ||
28 | #define STMPE_KPC_DATA_BYTE2 0x6a | ||
29 | #define STMPE_KPC_DATA_BYTE3 0x6b | ||
30 | #define STMPE_KPC_DATA_BYTE4 0x6c | ||
31 | |||
32 | #define STMPE_KPC_CTRL_LSB_SCAN (0x1 << 0) | ||
33 | #define STMPE_KPC_CTRL_LSB_DEBOUNCE (0x7f << 1) | ||
34 | #define STMPE_KPC_CTRL_MSB_SCAN_COUNT (0xf << 4) | ||
35 | |||
36 | #define STMPE_KPC_ROW_MSB_ROWS 0xff | ||
37 | |||
38 | #define STMPE_KPC_DATA_UP (0x1 << 7) | ||
39 | #define STMPE_KPC_DATA_ROW (0xf << 3) | ||
40 | #define STMPE_KPC_DATA_COL (0x7 << 0) | ||
41 | #define STMPE_KPC_DATA_NOKEY_MASK 0x78 | ||
42 | |||
43 | #define STMPE_KEYPAD_MAX_DEBOUNCE 127 | ||
44 | #define STMPE_KEYPAD_MAX_SCAN_COUNT 15 | ||
45 | |||
46 | #define STMPE_KEYPAD_MAX_ROWS 8 | ||
47 | #define STMPE_KEYPAD_MAX_COLS 8 | ||
48 | #define STMPE_KEYPAD_ROW_SHIFT 3 | ||
49 | #define STMPE_KEYPAD_KEYMAP_SIZE \ | ||
50 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) | ||
51 | |||
52 | /** | ||
53 | * struct stmpe_keypad_variant - model-specific attributes | ||
54 | * @auto_increment: whether the KPC_DATA_BYTE register address | ||
55 | * auto-increments on multiple read | ||
56 | * @num_data: number of data bytes | ||
57 | * @num_normal_data: number of normal keys' data bytes | ||
58 | * @max_cols: maximum number of columns supported | ||
59 | * @max_rows: maximum number of rows supported | ||
60 | * @col_gpios: bitmask of gpios which can be used for columns | ||
61 | * @row_gpios: bitmask of gpios which can be used for rows | ||
62 | */ | ||
63 | struct stmpe_keypad_variant { | ||
64 | bool auto_increment; | ||
65 | int num_data; | ||
66 | int num_normal_data; | ||
67 | int max_cols; | ||
68 | int max_rows; | ||
69 | unsigned int col_gpios; | ||
70 | unsigned int row_gpios; | ||
71 | }; | ||
72 | |||
73 | static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | ||
74 | [STMPE1601] = { | ||
75 | .auto_increment = true, | ||
76 | .num_data = 5, | ||
77 | .num_normal_data = 3, | ||
78 | .max_cols = 8, | ||
79 | .max_rows = 8, | ||
80 | .col_gpios = 0x000ff, /* GPIO 0 - 7 */ | ||
81 | .row_gpios = 0x0ff00, /* GPIO 8 - 15 */ | ||
82 | }, | ||
83 | [STMPE2401] = { | ||
84 | .auto_increment = false, | ||
85 | .num_data = 3, | ||
86 | .num_normal_data = 2, | ||
87 | .max_cols = 8, | ||
88 | .max_rows = 12, | ||
89 | .col_gpios = 0x0000ff, /* GPIO 0 - 7*/ | ||
90 | .row_gpios = 0x1fef00, /* GPIO 8-14, 16-20 */ | ||
91 | }, | ||
92 | [STMPE2403] = { | ||
93 | .auto_increment = true, | ||
94 | .num_data = 5, | ||
95 | .num_normal_data = 3, | ||
96 | .max_cols = 8, | ||
97 | .max_rows = 12, | ||
98 | .col_gpios = 0x0000ff, /* GPIO 0 - 7*/ | ||
99 | .row_gpios = 0x1fef00, /* GPIO 8-14, 16-20 */ | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | struct stmpe_keypad { | ||
104 | struct stmpe *stmpe; | ||
105 | struct input_dev *input; | ||
106 | const struct stmpe_keypad_variant *variant; | ||
107 | const struct stmpe_keypad_platform_data *plat; | ||
108 | |||
109 | unsigned int rows; | ||
110 | unsigned int cols; | ||
111 | |||
112 | unsigned short keymap[STMPE_KEYPAD_KEYMAP_SIZE]; | ||
113 | }; | ||
114 | |||
115 | static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data) | ||
116 | { | ||
117 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
118 | struct stmpe *stmpe = keypad->stmpe; | ||
119 | int ret; | ||
120 | int i; | ||
121 | |||
122 | if (variant->auto_increment) | ||
123 | return stmpe_block_read(stmpe, STMPE_KPC_DATA_BYTE0, | ||
124 | variant->num_data, data); | ||
125 | |||
126 | for (i = 0; i < variant->num_data; i++) { | ||
127 | ret = stmpe_reg_read(stmpe, STMPE_KPC_DATA_BYTE0 + i); | ||
128 | if (ret < 0) | ||
129 | return ret; | ||
130 | |||
131 | data[i] = ret; | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static irqreturn_t stmpe_keypad_irq(int irq, void *dev) | ||
138 | { | ||
139 | struct stmpe_keypad *keypad = dev; | ||
140 | struct input_dev *input = keypad->input; | ||
141 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
142 | u8 fifo[variant->num_data]; | ||
143 | int ret; | ||
144 | int i; | ||
145 | |||
146 | ret = stmpe_keypad_read_data(keypad, fifo); | ||
147 | if (ret < 0) | ||
148 | return IRQ_NONE; | ||
149 | |||
150 | for (i = 0; i < variant->num_normal_data; i++) { | ||
151 | u8 data = fifo[i]; | ||
152 | int row = (data & STMPE_KPC_DATA_ROW) >> 3; | ||
153 | int col = data & STMPE_KPC_DATA_COL; | ||
154 | int code = MATRIX_SCAN_CODE(row, col, STMPE_KEYPAD_ROW_SHIFT); | ||
155 | bool up = data & STMPE_KPC_DATA_UP; | ||
156 | |||
157 | if ((data & STMPE_KPC_DATA_NOKEY_MASK) | ||
158 | == STMPE_KPC_DATA_NOKEY_MASK) | ||
159 | continue; | ||
160 | |||
161 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
162 | input_report_key(input, keypad->keymap[code], !up); | ||
163 | input_sync(input); | ||
164 | } | ||
165 | |||
166 | return IRQ_HANDLED; | ||
167 | } | ||
168 | |||
169 | static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) | ||
170 | { | ||
171 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
172 | unsigned int col_gpios = variant->col_gpios; | ||
173 | unsigned int row_gpios = variant->row_gpios; | ||
174 | struct stmpe *stmpe = keypad->stmpe; | ||
175 | unsigned int pins = 0; | ||
176 | int i; | ||
177 | |||
178 | /* | ||
179 | * Figure out which pins need to be set to the keypad alternate | ||
180 | * function. | ||
181 | * | ||
182 | * {cols,rows}_gpios are bitmasks of which pins on the chip can be used | ||
183 | * for the keypad. | ||
184 | * | ||
185 | * keypad->{cols,rows} are a bitmask of which pins (of the ones useable | ||
186 | * for the keypad) are used on the board. | ||
187 | */ | ||
188 | |||
189 | for (i = 0; i < variant->max_cols; i++) { | ||
190 | int num = __ffs(col_gpios); | ||
191 | |||
192 | if (keypad->cols & (1 << i)) | ||
193 | pins |= 1 << num; | ||
194 | |||
195 | col_gpios &= ~(1 << num); | ||
196 | } | ||
197 | |||
198 | for (i = 0; i < variant->max_rows; i++) { | ||
199 | int num = __ffs(row_gpios); | ||
200 | |||
201 | if (keypad->rows & (1 << i)) | ||
202 | pins |= 1 << num; | ||
203 | |||
204 | row_gpios &= ~(1 << num); | ||
205 | } | ||
206 | |||
207 | return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD); | ||
208 | } | ||
209 | |||
210 | static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad) | ||
211 | { | ||
212 | const struct stmpe_keypad_platform_data *plat = keypad->plat; | ||
213 | const struct stmpe_keypad_variant *variant = keypad->variant; | ||
214 | struct stmpe *stmpe = keypad->stmpe; | ||
215 | int ret; | ||
216 | |||
217 | if (plat->debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE) | ||
218 | return -EINVAL; | ||
219 | |||
220 | if (plat->scan_count > STMPE_KEYPAD_MAX_SCAN_COUNT) | ||
221 | return -EINVAL; | ||
222 | |||
223 | ret = stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD); | ||
224 | if (ret < 0) | ||
225 | return ret; | ||
226 | |||
227 | ret = stmpe_keypad_altfunc_init(keypad); | ||
228 | if (ret < 0) | ||
229 | return ret; | ||
230 | |||
231 | ret = stmpe_reg_write(stmpe, STMPE_KPC_COL, keypad->cols); | ||
232 | if (ret < 0) | ||
233 | return ret; | ||
234 | |||
235 | ret = stmpe_reg_write(stmpe, STMPE_KPC_ROW_LSB, keypad->rows); | ||
236 | if (ret < 0) | ||
237 | return ret; | ||
238 | |||
239 | if (variant->max_rows > 8) { | ||
240 | ret = stmpe_set_bits(stmpe, STMPE_KPC_ROW_MSB, | ||
241 | STMPE_KPC_ROW_MSB_ROWS, | ||
242 | keypad->rows >> 8); | ||
243 | if (ret < 0) | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | ret = stmpe_set_bits(stmpe, STMPE_KPC_CTRL_MSB, | ||
248 | STMPE_KPC_CTRL_MSB_SCAN_COUNT, | ||
249 | plat->scan_count << 4); | ||
250 | if (ret < 0) | ||
251 | return ret; | ||
252 | |||
253 | return stmpe_set_bits(stmpe, STMPE_KPC_CTRL_LSB, | ||
254 | STMPE_KPC_CTRL_LSB_SCAN | | ||
255 | STMPE_KPC_CTRL_LSB_DEBOUNCE, | ||
256 | STMPE_KPC_CTRL_LSB_SCAN | | ||
257 | (plat->debounce_ms << 1)); | ||
258 | } | ||
259 | |||
260 | static int __devinit stmpe_keypad_probe(struct platform_device *pdev) | ||
261 | { | ||
262 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
263 | struct stmpe_keypad_platform_data *plat; | ||
264 | struct stmpe_keypad *keypad; | ||
265 | struct input_dev *input; | ||
266 | int ret; | ||
267 | int irq; | ||
268 | int i; | ||
269 | |||
270 | plat = stmpe->pdata->keypad; | ||
271 | if (!plat) | ||
272 | return -ENODEV; | ||
273 | |||
274 | irq = platform_get_irq(pdev, 0); | ||
275 | if (irq < 0) | ||
276 | return irq; | ||
277 | |||
278 | keypad = kzalloc(sizeof(struct stmpe_keypad), GFP_KERNEL); | ||
279 | if (!keypad) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | input = input_allocate_device(); | ||
283 | if (!input) { | ||
284 | ret = -ENOMEM; | ||
285 | goto out_freekeypad; | ||
286 | } | ||
287 | |||
288 | input->name = "STMPE keypad"; | ||
289 | input->id.bustype = BUS_I2C; | ||
290 | input->dev.parent = &pdev->dev; | ||
291 | |||
292 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
293 | |||
294 | __set_bit(EV_KEY, input->evbit); | ||
295 | if (!plat->no_autorepeat) | ||
296 | __set_bit(EV_REP, input->evbit); | ||
297 | |||
298 | input->keycode = keypad->keymap; | ||
299 | input->keycodesize = sizeof(keypad->keymap[0]); | ||
300 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
301 | |||
302 | matrix_keypad_build_keymap(plat->keymap_data, STMPE_KEYPAD_ROW_SHIFT, | ||
303 | input->keycode, input->keybit); | ||
304 | |||
305 | for (i = 0; i < plat->keymap_data->keymap_size; i++) { | ||
306 | unsigned int key = plat->keymap_data->keymap[i]; | ||
307 | |||
308 | keypad->cols |= 1 << KEY_COL(key); | ||
309 | keypad->rows |= 1 << KEY_ROW(key); | ||
310 | } | ||
311 | |||
312 | keypad->stmpe = stmpe; | ||
313 | keypad->plat = plat; | ||
314 | keypad->input = input; | ||
315 | keypad->variant = &stmpe_keypad_variants[stmpe->partnum]; | ||
316 | |||
317 | ret = stmpe_keypad_chip_init(keypad); | ||
318 | if (ret < 0) | ||
319 | goto out_freeinput; | ||
320 | |||
321 | ret = input_register_device(input); | ||
322 | if (ret) { | ||
323 | dev_err(&pdev->dev, | ||
324 | "unable to register input device: %d\n", ret); | ||
325 | goto out_freeinput; | ||
326 | } | ||
327 | |||
328 | ret = request_threaded_irq(irq, NULL, stmpe_keypad_irq, IRQF_ONESHOT, | ||
329 | "stmpe-keypad", keypad); | ||
330 | if (ret) { | ||
331 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
332 | goto out_unregisterinput; | ||
333 | } | ||
334 | |||
335 | platform_set_drvdata(pdev, keypad); | ||
336 | |||
337 | return 0; | ||
338 | |||
339 | out_unregisterinput: | ||
340 | input_unregister_device(input); | ||
341 | input = NULL; | ||
342 | out_freeinput: | ||
343 | input_free_device(input); | ||
344 | out_freekeypad: | ||
345 | kfree(keypad); | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit stmpe_keypad_remove(struct platform_device *pdev) | ||
350 | { | ||
351 | struct stmpe_keypad *keypad = platform_get_drvdata(pdev); | ||
352 | struct stmpe *stmpe = keypad->stmpe; | ||
353 | int irq = platform_get_irq(pdev, 0); | ||
354 | |||
355 | stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD); | ||
356 | |||
357 | free_irq(irq, keypad); | ||
358 | input_unregister_device(keypad->input); | ||
359 | platform_set_drvdata(pdev, NULL); | ||
360 | kfree(keypad); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static struct platform_driver stmpe_keypad_driver = { | ||
366 | .driver.name = "stmpe-keypad", | ||
367 | .driver.owner = THIS_MODULE, | ||
368 | .probe = stmpe_keypad_probe, | ||
369 | .remove = __devexit_p(stmpe_keypad_remove), | ||
370 | }; | ||
371 | |||
372 | static int __init stmpe_keypad_init(void) | ||
373 | { | ||
374 | return platform_driver_register(&stmpe_keypad_driver); | ||
375 | } | ||
376 | module_init(stmpe_keypad_init); | ||
377 | |||
378 | static void __exit stmpe_keypad_exit(void) | ||
379 | { | ||
380 | platform_driver_unregister(&stmpe_keypad_driver); | ||
381 | } | ||
382 | module_exit(stmpe_keypad_exit); | ||
383 | |||
384 | MODULE_LICENSE("GPL v2"); | ||
385 | MODULE_DESCRIPTION("STMPExxxx keypad driver"); | ||
386 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index e148749b5851..23257652b8e8 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -38,7 +38,8 @@ enum { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | static int ati_remote2_set_mask(const char *val, | 40 | static int ati_remote2_set_mask(const char *val, |
41 | struct kernel_param *kp, unsigned int max) | 41 | const struct kernel_param *kp, |
42 | unsigned int max) | ||
42 | { | 43 | { |
43 | unsigned long mask; | 44 | unsigned long mask; |
44 | int ret; | 45 | int ret; |
@@ -59,28 +60,31 @@ static int ati_remote2_set_mask(const char *val, | |||
59 | } | 60 | } |
60 | 61 | ||
61 | static int ati_remote2_set_channel_mask(const char *val, | 62 | static int ati_remote2_set_channel_mask(const char *val, |
62 | struct kernel_param *kp) | 63 | const struct kernel_param *kp) |
63 | { | 64 | { |
64 | pr_debug("%s()\n", __func__); | 65 | pr_debug("%s()\n", __func__); |
65 | 66 | ||
66 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); | 67 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); |
67 | } | 68 | } |
68 | 69 | ||
69 | static int ati_remote2_get_channel_mask(char *buffer, struct kernel_param *kp) | 70 | static int ati_remote2_get_channel_mask(char *buffer, |
71 | const struct kernel_param *kp) | ||
70 | { | 72 | { |
71 | pr_debug("%s()\n", __func__); | 73 | pr_debug("%s()\n", __func__); |
72 | 74 | ||
73 | return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); | 75 | return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); |
74 | } | 76 | } |
75 | 77 | ||
76 | static int ati_remote2_set_mode_mask(const char *val, struct kernel_param *kp) | 78 | static int ati_remote2_set_mode_mask(const char *val, |
79 | const struct kernel_param *kp) | ||
77 | { | 80 | { |
78 | pr_debug("%s()\n", __func__); | 81 | pr_debug("%s()\n", __func__); |
79 | 82 | ||
80 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); | 83 | return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); |
81 | } | 84 | } |
82 | 85 | ||
83 | static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) | 86 | static int ati_remote2_get_mode_mask(char *buffer, |
87 | const struct kernel_param *kp) | ||
84 | { | 88 | { |
85 | pr_debug("%s()\n", __func__); | 89 | pr_debug("%s()\n", __func__); |
86 | 90 | ||
@@ -89,15 +93,19 @@ static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) | |||
89 | 93 | ||
90 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; | 94 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; |
91 | #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) | 95 | #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) |
92 | #define param_set_channel_mask ati_remote2_set_channel_mask | 96 | static struct kernel_param_ops param_ops_channel_mask = { |
93 | #define param_get_channel_mask ati_remote2_get_channel_mask | 97 | .set = ati_remote2_set_channel_mask, |
98 | .get = ati_remote2_get_channel_mask, | ||
99 | }; | ||
94 | module_param(channel_mask, channel_mask, 0644); | 100 | module_param(channel_mask, channel_mask, 0644); |
95 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | 101 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); |
96 | 102 | ||
97 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; | 103 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; |
98 | #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) | 104 | #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) |
99 | #define param_set_mode_mask ati_remote2_set_mode_mask | 105 | static struct kernel_param_ops param_ops_mode_mask = { |
100 | #define param_get_mode_mask ati_remote2_get_mode_mask | 106 | .set = ati_remote2_set_mode_mask, |
107 | .get = ati_remote2_get_mode_mask, | ||
108 | }; | ||
101 | module_param(mode_mask, mode_mask, 0644); | 109 | module_param(mode_mask, mode_mask, 0644); |
102 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | 110 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); |
103 | 111 | ||
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index f3bb92e9755f..8e130bf7d32b 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c | |||
@@ -173,7 +173,7 @@ static int __devinit sparcspkr_probe(struct device *dev) | |||
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | static int sparcspkr_shutdown(struct of_device *dev) | 176 | static int sparcspkr_shutdown(struct platform_device *dev) |
177 | { | 177 | { |
178 | struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); | 178 | struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); |
179 | struct input_dev *input_dev = state->input_dev; | 179 | struct input_dev *input_dev = state->input_dev; |
@@ -184,7 +184,7 @@ static int sparcspkr_shutdown(struct of_device *dev) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int __devinit bbc_beep_probe(struct of_device *op, const struct of_device_id *match) | 187 | static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match) |
188 | { | 188 | { |
189 | struct sparcspkr_state *state; | 189 | struct sparcspkr_state *state; |
190 | struct bbc_beep_info *info; | 190 | struct bbc_beep_info *info; |
@@ -231,7 +231,7 @@ out_err: | |||
231 | return err; | 231 | return err; |
232 | } | 232 | } |
233 | 233 | ||
234 | static int __devexit bbc_remove(struct of_device *op) | 234 | static int __devexit bbc_remove(struct platform_device *op) |
235 | { | 235 | { |
236 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); | 236 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); |
237 | struct input_dev *input_dev = state->input_dev; | 237 | struct input_dev *input_dev = state->input_dev; |
@@ -269,7 +269,7 @@ static struct of_platform_driver bbc_beep_driver = { | |||
269 | .shutdown = sparcspkr_shutdown, | 269 | .shutdown = sparcspkr_shutdown, |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static int __devinit grover_beep_probe(struct of_device *op, const struct of_device_id *match) | 272 | static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match) |
273 | { | 273 | { |
274 | struct sparcspkr_state *state; | 274 | struct sparcspkr_state *state; |
275 | struct grover_beep_info *info; | 275 | struct grover_beep_info *info; |
@@ -312,7 +312,7 @@ out_err: | |||
312 | return err; | 312 | return err; |
313 | } | 313 | } |
314 | 314 | ||
315 | static int __devexit grover_remove(struct of_device *op) | 315 | static int __devexit grover_remove(struct platform_device *op) |
316 | { | 316 | { |
317 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); | 317 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); |
318 | struct grover_beep_info *info = &state->u.grover; | 318 | struct grover_beep_info *info = &state->u.grover; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 979c50215282..73a7af2542a8 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -39,11 +39,13 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | 40 | ||
41 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; | 41 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; |
42 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); | 42 | static int psmouse_set_maxproto(const char *val, const struct kernel_param *); |
43 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); | 43 | static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp); |
44 | static struct kernel_param_ops param_ops_proto_abbrev = { | ||
45 | .set = psmouse_set_maxproto, | ||
46 | .get = psmouse_get_maxproto, | ||
47 | }; | ||
44 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) | 48 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) |
45 | #define param_set_proto_abbrev psmouse_set_maxproto | ||
46 | #define param_get_proto_abbrev psmouse_get_maxproto | ||
47 | module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); | 49 | module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644); |
48 | MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); | 50 | MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches."); |
49 | 51 | ||
@@ -1679,7 +1681,7 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, | |||
1679 | } | 1681 | } |
1680 | 1682 | ||
1681 | 1683 | ||
1682 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | 1684 | static int psmouse_set_maxproto(const char *val, const struct kernel_param *kp) |
1683 | { | 1685 | { |
1684 | const struct psmouse_protocol *proto; | 1686 | const struct psmouse_protocol *proto; |
1685 | 1687 | ||
@@ -1696,7 +1698,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | |||
1696 | return 0; | 1698 | return 0; |
1697 | } | 1699 | } |
1698 | 1700 | ||
1699 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | 1701 | static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp) |
1700 | { | 1702 | { |
1701 | int type = *((unsigned int *)kp->arg); | 1703 | int type = *((unsigned int *)kp->arg); |
1702 | 1704 | ||
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index cb2a24b94746..c5cc4508d6df 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
@@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) | |||
49 | #define OBP_PS2MS_NAME1 "kdmouse" | 49 | #define OBP_PS2MS_NAME1 "kdmouse" |
50 | #define OBP_PS2MS_NAME2 "mouse" | 50 | #define OBP_PS2MS_NAME2 "mouse" |
51 | 51 | ||
52 | static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_device_id *match) | 52 | static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match) |
53 | { | 53 | { |
54 | struct device_node *dp = op->dev.of_node; | 54 | struct device_node *dp = op->dev.of_node; |
55 | 55 | ||
@@ -57,7 +57,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev | |||
57 | while (dp) { | 57 | while (dp) { |
58 | if (!strcmp(dp->name, OBP_PS2KBD_NAME1) || | 58 | if (!strcmp(dp->name, OBP_PS2KBD_NAME1) || |
59 | !strcmp(dp->name, OBP_PS2KBD_NAME2)) { | 59 | !strcmp(dp->name, OBP_PS2KBD_NAME2)) { |
60 | struct of_device *kbd = of_find_device_by_node(dp); | 60 | struct platform_device *kbd = of_find_device_by_node(dp); |
61 | unsigned int irq = kbd->archdata.irqs[0]; | 61 | unsigned int irq = kbd->archdata.irqs[0]; |
62 | if (irq == 0xffffffff) | 62 | if (irq == 0xffffffff) |
63 | irq = op->archdata.irqs[0]; | 63 | irq = op->archdata.irqs[0]; |
@@ -67,7 +67,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev | |||
67 | kbd_res = &kbd->resource[0]; | 67 | kbd_res = &kbd->resource[0]; |
68 | } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) || | 68 | } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) || |
69 | !strcmp(dp->name, OBP_PS2MS_NAME2)) { | 69 | !strcmp(dp->name, OBP_PS2MS_NAME2)) { |
70 | struct of_device *ms = of_find_device_by_node(dp); | 70 | struct platform_device *ms = of_find_device_by_node(dp); |
71 | unsigned int irq = ms->archdata.irqs[0]; | 71 | unsigned int irq = ms->archdata.irqs[0]; |
72 | if (irq == 0xffffffff) | 72 | if (irq == 0xffffffff) |
73 | irq = op->archdata.irqs[0]; | 73 | irq = op->archdata.irqs[0]; |
@@ -80,7 +80,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev | |||
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | static int __devexit sparc_i8042_remove(struct of_device *op) | 83 | static int __devexit sparc_i8042_remove(struct platform_device *op) |
84 | { | 84 | { |
85 | of_iounmap(kbd_res, kbd_iobase, 8); | 85 | of_iounmap(kbd_res, kbd_iobase, 8); |
86 | 86 | ||
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 258b98b9d7c2..46e4ba0b9246 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -61,10 +61,6 @@ static bool i8042_noloop; | |||
61 | module_param_named(noloop, i8042_noloop, bool, 0); | 61 | module_param_named(noloop, i8042_noloop, bool, 0); |
62 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); | 62 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); |
63 | 63 | ||
64 | static unsigned int i8042_blink_frequency = 500; | ||
65 | module_param_named(panicblink, i8042_blink_frequency, uint, 0600); | ||
66 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); | ||
67 | |||
68 | #ifdef CONFIG_X86 | 64 | #ifdef CONFIG_X86 |
69 | static bool i8042_dritek; | 65 | static bool i8042_dritek; |
70 | module_param_named(dritek, i8042_dritek, bool, 0); | 66 | module_param_named(dritek, i8042_dritek, bool, 0); |
@@ -1030,8 +1026,8 @@ static void i8042_controller_reset(void) | |||
1030 | 1026 | ||
1031 | 1027 | ||
1032 | /* | 1028 | /* |
1033 | * i8042_panic_blink() will flash the keyboard LEDs and is called when | 1029 | * i8042_panic_blink() will turn the keyboard LEDs on or off and is called |
1034 | * kernel panics. Flashing LEDs is useful for users running X who may | 1030 | * when kernel panics. Flashing LEDs is useful for users running X who may |
1035 | * not see the console and will help distingushing panics from "real" | 1031 | * not see the console and will help distingushing panics from "real" |
1036 | * lockups. | 1032 | * lockups. |
1037 | * | 1033 | * |
@@ -1041,22 +1037,12 @@ static void i8042_controller_reset(void) | |||
1041 | 1037 | ||
1042 | #define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) | 1038 | #define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) |
1043 | 1039 | ||
1044 | static long i8042_panic_blink(long count) | 1040 | static long i8042_panic_blink(int state) |
1045 | { | 1041 | { |
1046 | long delay = 0; | 1042 | long delay = 0; |
1047 | static long last_blink; | 1043 | char led; |
1048 | static char led; | ||
1049 | |||
1050 | /* | ||
1051 | * We expect frequency to be about 1/2s. KDB uses about 1s. | ||
1052 | * Make sure they are different. | ||
1053 | */ | ||
1054 | if (!i8042_blink_frequency) | ||
1055 | return 0; | ||
1056 | if (count - last_blink < i8042_blink_frequency) | ||
1057 | return 0; | ||
1058 | 1044 | ||
1059 | led ^= 0x01 | 0x04; | 1045 | led = (state) ? 0x01 | 0x04 : 0; |
1060 | while (i8042_read_status() & I8042_STR_IBF) | 1046 | while (i8042_read_status() & I8042_STR_IBF) |
1061 | DELAY; | 1047 | DELAY; |
1062 | dbg("%02x -> i8042 (panic blink)", 0xed); | 1048 | dbg("%02x -> i8042 (panic blink)", 0xed); |
@@ -1069,7 +1055,6 @@ static long i8042_panic_blink(long count) | |||
1069 | dbg("%02x -> i8042 (panic blink)", led); | 1055 | dbg("%02x -> i8042 (panic blink)", led); |
1070 | i8042_write_data(led); | 1056 | i8042_write_data(led); |
1071 | DELAY; | 1057 | DELAY; |
1072 | last_blink = count; | ||
1073 | return delay; | 1058 | return delay; |
1074 | } | 1059 | } |
1075 | 1060 | ||
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index e2c028d2638f..bb14449fb022 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -232,7 +232,7 @@ static void sxps2_close(struct serio *pserio) | |||
232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative | 232 | * It returns 0, if the driver is bound to the PS/2 device, or a negative |
233 | * value if there is an error. | 233 | * value if there is an error. |
234 | */ | 234 | */ |
235 | static int __devinit xps2_of_probe(struct of_device *ofdev, | 235 | static int __devinit xps2_of_probe(struct platform_device *ofdev, |
236 | const struct of_device_id *match) | 236 | const struct of_device_id *match) |
237 | { | 237 | { |
238 | struct resource r_irq; /* Interrupt resources */ | 238 | struct resource r_irq; /* Interrupt resources */ |
@@ -332,7 +332,7 @@ failed1: | |||
332 | * if the driver module is being unloaded. It frees any resources allocated to | 332 | * if the driver module is being unloaded. It frees any resources allocated to |
333 | * the device. | 333 | * the device. |
334 | */ | 334 | */ |
335 | static int __devexit xps2_of_remove(struct of_device *of_dev) | 335 | static int __devexit xps2_of_remove(struct platform_device *of_dev) |
336 | { | 336 | { |
337 | struct device *dev = &of_dev->dev; | 337 | struct device *dev = &of_dev->dev; |
338 | struct xps2data *drvdata = dev_get_drvdata(dev); | 338 | struct xps2data *drvdata = dev_get_drvdata(dev); |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 61f35184f76c..0069d9703fda 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -628,4 +628,14 @@ config TOUCHSCREEN_TPS6507X | |||
628 | To compile this driver as a module, choose M here: the | 628 | To compile this driver as a module, choose M here: the |
629 | module will be called tps6507x_ts. | 629 | module will be called tps6507x_ts. |
630 | 630 | ||
631 | config TOUCHSCREEN_STMPE | ||
632 | tristate "STMicroelectronics STMPE touchscreens" | ||
633 | depends on MFD_STMPE | ||
634 | help | ||
635 | Say Y here if you want support for STMicroelectronics | ||
636 | STMPE touchscreen controllers. | ||
637 | |||
638 | To compile this driver as a module, choose M here: the | ||
639 | module will be called stmpe-ts. | ||
640 | |||
631 | endif | 641 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index bd6f30b4ff70..28217e1dcafd 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | |||
36 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 36 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
37 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o | 37 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o |
38 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 38 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
39 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | ||
39 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 40 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
40 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 41 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
41 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 42 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c new file mode 100644 index 000000000000..656148ec0027 --- /dev/null +++ b/drivers/input/touchscreen/stmpe-ts.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* STMicroelectronics STMPE811 Touchscreen Driver | ||
2 | * | ||
3 | * (C) 2010 Luotao Fu <l.fu@pengutronix.de> | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #include <linux/mfd/stmpe.h> | ||
27 | |||
28 | /* Register layouts and functionalities are identical on all stmpexxx variants | ||
29 | * with touchscreen controller | ||
30 | */ | ||
31 | #define STMPE_REG_INT_STA 0x0B | ||
32 | #define STMPE_REG_ADC_CTRL1 0x20 | ||
33 | #define STMPE_REG_ADC_CTRL2 0x21 | ||
34 | #define STMPE_REG_TSC_CTRL 0x40 | ||
35 | #define STMPE_REG_TSC_CFG 0x41 | ||
36 | #define STMPE_REG_FIFO_TH 0x4A | ||
37 | #define STMPE_REG_FIFO_STA 0x4B | ||
38 | #define STMPE_REG_FIFO_SIZE 0x4C | ||
39 | #define STMPE_REG_TSC_DATA_XYZ 0x52 | ||
40 | #define STMPE_REG_TSC_FRACTION_Z 0x56 | ||
41 | #define STMPE_REG_TSC_I_DRIVE 0x58 | ||
42 | |||
43 | #define OP_MOD_XYZ 0 | ||
44 | |||
45 | #define STMPE_TSC_CTRL_TSC_EN (1<<0) | ||
46 | |||
47 | #define STMPE_FIFO_STA_RESET (1<<0) | ||
48 | |||
49 | #define STMPE_IRQ_TOUCH_DET 0 | ||
50 | |||
51 | #define SAMPLE_TIME(x) ((x & 0xf) << 4) | ||
52 | #define MOD_12B(x) ((x & 0x1) << 3) | ||
53 | #define REF_SEL(x) ((x & 0x1) << 1) | ||
54 | #define ADC_FREQ(x) (x & 0x3) | ||
55 | #define AVE_CTRL(x) ((x & 0x3) << 6) | ||
56 | #define DET_DELAY(x) ((x & 0x7) << 3) | ||
57 | #define SETTLING(x) (x & 0x7) | ||
58 | #define FRACTION_Z(x) (x & 0x7) | ||
59 | #define I_DRIVE(x) (x & 0x1) | ||
60 | #define OP_MODE(x) ((x & 0x7) << 1) | ||
61 | |||
62 | #define STMPE_TS_NAME "stmpe-ts" | ||
63 | #define XY_MASK 0xfff | ||
64 | |||
65 | struct stmpe_touch { | ||
66 | struct stmpe *stmpe; | ||
67 | struct input_dev *idev; | ||
68 | struct delayed_work work; | ||
69 | struct device *dev; | ||
70 | u8 sample_time; | ||
71 | u8 mod_12b; | ||
72 | u8 ref_sel; | ||
73 | u8 adc_freq; | ||
74 | u8 ave_ctrl; | ||
75 | u8 touch_det_delay; | ||
76 | u8 settling; | ||
77 | u8 fraction_z; | ||
78 | u8 i_drive; | ||
79 | }; | ||
80 | |||
81 | static int __stmpe_reset_fifo(struct stmpe *stmpe) | ||
82 | { | ||
83 | int ret; | ||
84 | |||
85 | ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, | ||
86 | STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET); | ||
87 | if (ret) | ||
88 | return ret; | ||
89 | |||
90 | return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA, | ||
91 | STMPE_FIFO_STA_RESET, 0); | ||
92 | } | ||
93 | |||
94 | static void stmpe_work(struct work_struct *work) | ||
95 | { | ||
96 | int int_sta; | ||
97 | u32 timeout = 40; | ||
98 | |||
99 | struct stmpe_touch *ts = | ||
100 | container_of(work, struct stmpe_touch, work.work); | ||
101 | |||
102 | int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); | ||
103 | |||
104 | /* | ||
105 | * touch_det sometimes get desasserted or just get stuck. This appears | ||
106 | * to be a silicon bug, We still have to clearify this with the | ||
107 | * manufacture. As a workaround We release the key anyway if the | ||
108 | * touch_det keeps coming in after 4ms, while the FIFO contains no value | ||
109 | * during the whole time. | ||
110 | */ | ||
111 | while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) { | ||
112 | timeout--; | ||
113 | int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA); | ||
114 | udelay(100); | ||
115 | } | ||
116 | |||
117 | /* reset the FIFO before we report release event */ | ||
118 | __stmpe_reset_fifo(ts->stmpe); | ||
119 | |||
120 | input_report_abs(ts->idev, ABS_PRESSURE, 0); | ||
121 | input_sync(ts->idev); | ||
122 | } | ||
123 | |||
124 | static irqreturn_t stmpe_ts_handler(int irq, void *data) | ||
125 | { | ||
126 | u8 data_set[4]; | ||
127 | int x, y, z; | ||
128 | struct stmpe_touch *ts = data; | ||
129 | |||
130 | /* | ||
131 | * Cancel scheduled polling for release if we have new value | ||
132 | * available. Wait if the polling is already running. | ||
133 | */ | ||
134 | cancel_delayed_work_sync(&ts->work); | ||
135 | |||
136 | /* | ||
137 | * The FIFO sometimes just crashes and stops generating interrupts. This | ||
138 | * appears to be a silicon bug. We still have to clearify this with | ||
139 | * the manufacture. As a workaround we disable the TSC while we are | ||
140 | * collecting data and flush the FIFO after reading | ||
141 | */ | ||
142 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
143 | STMPE_TSC_CTRL_TSC_EN, 0); | ||
144 | |||
145 | stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set); | ||
146 | |||
147 | x = (data_set[0] << 4) | (data_set[1] >> 4); | ||
148 | y = ((data_set[1] & 0xf) << 8) | data_set[2]; | ||
149 | z = data_set[3]; | ||
150 | |||
151 | input_report_abs(ts->idev, ABS_X, x); | ||
152 | input_report_abs(ts->idev, ABS_Y, y); | ||
153 | input_report_abs(ts->idev, ABS_PRESSURE, z); | ||
154 | input_sync(ts->idev); | ||
155 | |||
156 | /* flush the FIFO after we have read out our values. */ | ||
157 | __stmpe_reset_fifo(ts->stmpe); | ||
158 | |||
159 | /* reenable the tsc */ | ||
160 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
161 | STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); | ||
162 | |||
163 | /* start polling for touch_det to detect release */ | ||
164 | schedule_delayed_work(&ts->work, HZ / 50); | ||
165 | |||
166 | return IRQ_HANDLED; | ||
167 | } | ||
168 | |||
169 | static int __devinit stmpe_init_hw(struct stmpe_touch *ts) | ||
170 | { | ||
171 | int ret; | ||
172 | u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; | ||
173 | struct stmpe *stmpe = ts->stmpe; | ||
174 | struct device *dev = ts->dev; | ||
175 | |||
176 | ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC); | ||
177 | if (ret) { | ||
178 | dev_err(dev, "Could not enable clock for ADC and TS\n"); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) | | ||
183 | REF_SEL(ts->ref_sel); | ||
184 | adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff); | ||
185 | |||
186 | ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1, | ||
187 | adc_ctrl1_mask, adc_ctrl1); | ||
188 | if (ret) { | ||
189 | dev_err(dev, "Could not setup ADC\n"); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2, | ||
194 | ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq)); | ||
195 | if (ret) { | ||
196 | dev_err(dev, "Could not setup ADC\n"); | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) | | ||
201 | SETTLING(ts->settling); | ||
202 | tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff); | ||
203 | |||
204 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg); | ||
205 | if (ret) { | ||
206 | dev_err(dev, "Could not config touch\n"); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z, | ||
211 | FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z)); | ||
212 | if (ret) { | ||
213 | dev_err(dev, "Could not config touch\n"); | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE, | ||
218 | I_DRIVE(0xff), I_DRIVE(ts->i_drive)); | ||
219 | if (ret) { | ||
220 | dev_err(dev, "Could not config touch\n"); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | /* set FIFO to 1 for single point reading */ | ||
225 | ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1); | ||
226 | if (ret) { | ||
227 | dev_err(dev, "Could not set FIFO\n"); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL, | ||
232 | OP_MODE(0xff), OP_MODE(OP_MOD_XYZ)); | ||
233 | if (ret) { | ||
234 | dev_err(dev, "Could not set mode\n"); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int stmpe_ts_open(struct input_dev *dev) | ||
242 | { | ||
243 | struct stmpe_touch *ts = input_get_drvdata(dev); | ||
244 | int ret = 0; | ||
245 | |||
246 | ret = __stmpe_reset_fifo(ts->stmpe); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
251 | STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); | ||
252 | } | ||
253 | |||
254 | static void stmpe_ts_close(struct input_dev *dev) | ||
255 | { | ||
256 | struct stmpe_touch *ts = input_get_drvdata(dev); | ||
257 | |||
258 | cancel_delayed_work_sync(&ts->work); | ||
259 | |||
260 | stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL, | ||
261 | STMPE_TSC_CTRL_TSC_EN, 0); | ||
262 | } | ||
263 | |||
264 | static int __devinit stmpe_input_probe(struct platform_device *pdev) | ||
265 | { | ||
266 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | ||
267 | struct stmpe_platform_data *pdata = stmpe->pdata; | ||
268 | struct stmpe_touch *ts; | ||
269 | struct input_dev *idev; | ||
270 | struct stmpe_ts_platform_data *ts_pdata = NULL; | ||
271 | int ret = 0; | ||
272 | int ts_irq; | ||
273 | |||
274 | ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
275 | if (ts_irq < 0) | ||
276 | return ts_irq; | ||
277 | |||
278 | ts = kzalloc(sizeof(*ts), GFP_KERNEL); | ||
279 | if (!ts) | ||
280 | goto err_out; | ||
281 | |||
282 | idev = input_allocate_device(); | ||
283 | if (!idev) | ||
284 | goto err_free_ts; | ||
285 | |||
286 | platform_set_drvdata(pdev, ts); | ||
287 | ts->stmpe = stmpe; | ||
288 | ts->idev = idev; | ||
289 | ts->dev = &pdev->dev; | ||
290 | |||
291 | if (pdata) | ||
292 | ts_pdata = pdata->ts; | ||
293 | |||
294 | if (ts_pdata) { | ||
295 | ts->sample_time = ts_pdata->sample_time; | ||
296 | ts->mod_12b = ts_pdata->mod_12b; | ||
297 | ts->ref_sel = ts_pdata->ref_sel; | ||
298 | ts->adc_freq = ts_pdata->adc_freq; | ||
299 | ts->ave_ctrl = ts_pdata->ave_ctrl; | ||
300 | ts->touch_det_delay = ts_pdata->touch_det_delay; | ||
301 | ts->settling = ts_pdata->settling; | ||
302 | ts->fraction_z = ts_pdata->fraction_z; | ||
303 | ts->i_drive = ts_pdata->i_drive; | ||
304 | } | ||
305 | |||
306 | INIT_DELAYED_WORK(&ts->work, stmpe_work); | ||
307 | |||
308 | ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler, | ||
309 | IRQF_ONESHOT, STMPE_TS_NAME, ts); | ||
310 | if (ret) { | ||
311 | dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq); | ||
312 | goto err_free_input; | ||
313 | } | ||
314 | |||
315 | ret = stmpe_init_hw(ts); | ||
316 | if (ret) | ||
317 | goto err_free_irq; | ||
318 | |||
319 | idev->name = STMPE_TS_NAME; | ||
320 | idev->id.bustype = BUS_I2C; | ||
321 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
322 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
323 | |||
324 | idev->open = stmpe_ts_open; | ||
325 | idev->close = stmpe_ts_close; | ||
326 | |||
327 | input_set_drvdata(idev, ts); | ||
328 | |||
329 | input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0); | ||
330 | input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); | ||
331 | input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); | ||
332 | |||
333 | ret = input_register_device(idev); | ||
334 | if (ret) { | ||
335 | dev_err(&pdev->dev, "Could not register input device\n"); | ||
336 | goto err_free_irq; | ||
337 | } | ||
338 | |||
339 | return ret; | ||
340 | |||
341 | err_free_irq: | ||
342 | free_irq(ts_irq, ts); | ||
343 | err_free_input: | ||
344 | input_free_device(idev); | ||
345 | platform_set_drvdata(pdev, NULL); | ||
346 | err_free_ts: | ||
347 | kfree(ts); | ||
348 | err_out: | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static int __devexit stmpe_ts_remove(struct platform_device *pdev) | ||
353 | { | ||
354 | struct stmpe_touch *ts = platform_get_drvdata(pdev); | ||
355 | unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
356 | |||
357 | stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN); | ||
358 | |||
359 | free_irq(ts_irq, ts); | ||
360 | |||
361 | platform_set_drvdata(pdev, NULL); | ||
362 | |||
363 | input_unregister_device(ts->idev); | ||
364 | input_free_device(ts->idev); | ||
365 | |||
366 | kfree(ts); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static struct platform_driver stmpe_ts_driver = { | ||
372 | .driver = { | ||
373 | .name = STMPE_TS_NAME, | ||
374 | .owner = THIS_MODULE, | ||
375 | }, | ||
376 | .probe = stmpe_input_probe, | ||
377 | .remove = __devexit_p(stmpe_ts_remove), | ||
378 | }; | ||
379 | |||
380 | static int __init stmpe_ts_init(void) | ||
381 | { | ||
382 | return platform_driver_register(&stmpe_ts_driver); | ||
383 | } | ||
384 | |||
385 | module_init(stmpe_ts_init); | ||
386 | |||
387 | static void __exit stmpe_ts_exit(void) | ||
388 | { | ||
389 | platform_driver_unregister(&stmpe_ts_driver); | ||
390 | } | ||
391 | |||
392 | module_exit(stmpe_ts_exit); | ||
393 | |||
394 | MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); | ||
395 | MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); | ||
396 | MODULE_LICENSE("GPL"); | ||
397 | MODULE_ALIAS("platform:" STMPE_TS_NAME); | ||
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index 7715d3242ec8..d3530f6e8115 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c | |||
@@ -1273,6 +1273,7 @@ static int __devinit c4_probe(struct pci_dev *dev, | |||
1273 | if (retval != 0) { | 1273 | if (retval != 0) { |
1274 | printk(KERN_ERR "c4: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n", | 1274 | printk(KERN_ERR "c4: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n", |
1275 | nr, param.port, param.irq, param.membase); | 1275 | nr, param.port, param.irq, param.membase); |
1276 | pci_disable_device(dev); | ||
1276 | return -ENODEV; | 1277 | return -ENODEV; |
1277 | } | 1278 | } |
1278 | return 0; | 1279 | return 0; |
diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c index 5a3f83098018..a79eb5afb92d 100644 --- a/drivers/isdn/hardware/avm/t1pci.c +++ b/drivers/isdn/hardware/avm/t1pci.c | |||
@@ -210,6 +210,7 @@ static int __devinit t1pci_probe(struct pci_dev *dev, | |||
210 | if (retval != 0) { | 210 | if (retval != 0) { |
211 | printk(KERN_ERR "t1pci: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", | 211 | printk(KERN_ERR "t1pci: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", |
212 | param.port, param.irq, param.membase); | 212 | param.port, param.irq, param.membase); |
213 | pci_disable_device(dev); | ||
213 | return -ENODEV; | 214 | return -ENODEV; |
214 | } | 215 | } |
215 | return 0; | 216 | return 0; |
diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index d2dd61d65d51..af25e1f3efd4 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c | |||
@@ -1094,6 +1094,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1094 | pr_info("mISDN: do not have informations about adapter at %s\n", | 1094 | pr_info("mISDN: do not have informations about adapter at %s\n", |
1095 | pci_name(pdev)); | 1095 | pci_name(pdev)); |
1096 | kfree(card); | 1096 | kfree(card); |
1097 | pci_disable_device(pdev); | ||
1097 | return -EINVAL; | 1098 | return -EINVAL; |
1098 | } else | 1099 | } else |
1099 | pr_notice("mISDN: found adapter %s at %s\n", | 1100 | pr_notice("mISDN: found adapter %s at %s\n", |
@@ -1103,7 +1104,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1103 | pci_set_drvdata(pdev, card); | 1104 | pci_set_drvdata(pdev, card); |
1104 | err = setup_instance(card); | 1105 | err = setup_instance(card); |
1105 | if (err) { | 1106 | if (err) { |
1106 | pci_disable_device(card->pdev); | 1107 | pci_disable_device(pdev); |
1107 | kfree(card); | 1108 | kfree(card); |
1108 | pci_set_drvdata(pdev, NULL); | 1109 | pci_set_drvdata(pdev, NULL); |
1109 | } else if (ent->driver_data == INF_SCT_1) { | 1110 | } else if (ent->driver_data == INF_SCT_1) { |
@@ -1114,6 +1115,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1114 | sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL); | 1115 | sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL); |
1115 | if (!sc) { | 1116 | if (!sc) { |
1116 | release_card(card); | 1117 | release_card(card); |
1118 | pci_disable_device(pdev); | ||
1117 | return -ENOMEM; | 1119 | return -ENOMEM; |
1118 | } | 1120 | } |
1119 | sc->irq = card->irq; | 1121 | sc->irq = card->irq; |
@@ -1121,6 +1123,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1121 | sc->ci = card->ci + i; | 1123 | sc->ci = card->ci + i; |
1122 | err = setup_instance(sc); | 1124 | err = setup_instance(sc); |
1123 | if (err) { | 1125 | if (err) { |
1126 | pci_disable_device(pdev); | ||
1124 | kfree(sc); | 1127 | kfree(sc); |
1125 | release_card(card); | 1128 | release_card(card); |
1126 | break; | 1129 | break; |
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index cc22eeefa10b..ea57e05d08f3 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -224,7 +224,7 @@ struct gpio_led_of_platform_data { | |||
224 | struct gpio_led_data led_data[]; | 224 | struct gpio_led_data led_data[]; |
225 | }; | 225 | }; |
226 | 226 | ||
227 | static int __devinit of_gpio_leds_probe(struct of_device *ofdev, | 227 | static int __devinit of_gpio_leds_probe(struct platform_device *ofdev, |
228 | const struct of_device_id *match) | 228 | const struct of_device_id *match) |
229 | { | 229 | { |
230 | struct device_node *np = ofdev->dev.of_node, *child; | 230 | struct device_node *np = ofdev->dev.of_node, *child; |
@@ -283,7 +283,7 @@ err: | |||
283 | return ret; | 283 | return ret; |
284 | } | 284 | } |
285 | 285 | ||
286 | static int __devexit of_gpio_leds_remove(struct of_device *ofdev) | 286 | static int __devexit of_gpio_leds_remove(struct platform_device *ofdev) |
287 | { | 287 | { |
288 | struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev); | 288 | struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev); |
289 | int i; | 289 | int i; |
diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 6024038a5b9d..8eb40afbd0f5 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c | |||
@@ -15,7 +15,7 @@ field##_show (struct device *dev, struct device_attribute *attr, \ | |||
15 | static ssize_t | 15 | static ssize_t |
16 | compatible_show (struct device *dev, struct device_attribute *attr, char *buf) | 16 | compatible_show (struct device *dev, struct device_attribute *attr, char *buf) |
17 | { | 17 | { |
18 | struct of_device *of; | 18 | struct platform_device *of; |
19 | const char *compat; | 19 | const char *compat; |
20 | int cplen; | 20 | int cplen; |
21 | int length = 0; | 21 | int length = 0; |
@@ -52,9 +52,9 @@ static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, | |||
52 | static ssize_t devspec_show(struct device *dev, | 52 | static ssize_t devspec_show(struct device *dev, |
53 | struct device_attribute *attr, char *buf) | 53 | struct device_attribute *attr, char *buf) |
54 | { | 54 | { |
55 | struct of_device *ofdev; | 55 | struct platform_device *ofdev; |
56 | 56 | ||
57 | ofdev = to_of_device(dev); | 57 | ofdev = to_platform_device(dev); |
58 | return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); | 58 | return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); |
59 | } | 59 | } |
60 | 60 | ||
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 2506c957712e..e58c3d33e035 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c | |||
@@ -75,7 +75,7 @@ struct smu_cmd_buf { | |||
75 | struct smu_device { | 75 | struct smu_device { |
76 | spinlock_t lock; | 76 | spinlock_t lock; |
77 | struct device_node *of_node; | 77 | struct device_node *of_node; |
78 | struct of_device *of_dev; | 78 | struct platform_device *of_dev; |
79 | int doorbell; /* doorbell gpio */ | 79 | int doorbell; /* doorbell gpio */ |
80 | u32 __iomem *db_buf; /* doorbell buffer */ | 80 | u32 __iomem *db_buf; /* doorbell buffer */ |
81 | struct device_node *db_node; | 81 | struct device_node *db_node; |
@@ -645,7 +645,7 @@ static void smu_expose_childs(struct work_struct *unused) | |||
645 | 645 | ||
646 | static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); | 646 | static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); |
647 | 647 | ||
648 | static int smu_platform_probe(struct of_device* dev, | 648 | static int smu_platform_probe(struct platform_device* dev, |
649 | const struct of_device_id *match) | 649 | const struct of_device_id *match) |
650 | { | 650 | { |
651 | if (!smu) | 651 | if (!smu) |
@@ -695,7 +695,7 @@ static int __init smu_init_sysfs(void) | |||
695 | 695 | ||
696 | device_initcall(smu_init_sysfs); | 696 | device_initcall(smu_init_sysfs); |
697 | 697 | ||
698 | struct of_device *smu_get_ofdev(void) | 698 | struct platform_device *smu_get_ofdev(void) |
699 | { | 699 | { |
700 | if (!smu) | 700 | if (!smu) |
701 | return NULL; | 701 | return NULL; |
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index c42eeb43042d..d0d221332db0 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c | |||
@@ -84,7 +84,7 @@ struct thermostat { | |||
84 | 84 | ||
85 | static enum {ADT7460, ADT7467} therm_type; | 85 | static enum {ADT7460, ADT7467} therm_type; |
86 | static int therm_bus, therm_address; | 86 | static int therm_bus, therm_address; |
87 | static struct of_device * of_dev; | 87 | static struct platform_device * of_dev; |
88 | static struct thermostat* thermostat; | 88 | static struct thermostat* thermostat; |
89 | static struct task_struct *thread_therm = NULL; | 89 | static struct task_struct *thread_therm = NULL; |
90 | 90 | ||
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index e60605bd0ea9..44549272333c 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c | |||
@@ -148,7 +148,7 @@ | |||
148 | * Driver statics | 148 | * Driver statics |
149 | */ | 149 | */ |
150 | 150 | ||
151 | static struct of_device * of_dev; | 151 | static struct platform_device * of_dev; |
152 | static struct i2c_adapter * u3_0; | 152 | static struct i2c_adapter * u3_0; |
153 | static struct i2c_adapter * u3_1; | 153 | static struct i2c_adapter * u3_1; |
154 | static struct i2c_adapter * k2; | 154 | static struct i2c_adapter * k2; |
@@ -2210,7 +2210,7 @@ static void fcu_lookup_fans(struct device_node *fcu_node) | |||
2210 | } | 2210 | } |
2211 | } | 2211 | } |
2212 | 2212 | ||
2213 | static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) | 2213 | static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match) |
2214 | { | 2214 | { |
2215 | state = state_detached; | 2215 | state = state_detached; |
2216 | 2216 | ||
@@ -2221,7 +2221,7 @@ static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) | |||
2221 | return i2c_add_driver(&therm_pm72_driver); | 2221 | return i2c_add_driver(&therm_pm72_driver); |
2222 | } | 2222 | } |
2223 | 2223 | ||
2224 | static int fcu_of_remove(struct of_device* dev) | 2224 | static int fcu_of_remove(struct platform_device* dev) |
2225 | { | 2225 | { |
2226 | i2c_del_driver(&therm_pm72_driver); | 2226 | i2c_del_driver(&therm_pm72_driver); |
2227 | 2227 | ||
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 5c9367acf0cf..c89f396e4c53 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c | |||
@@ -52,7 +52,7 @@ static struct { | |||
52 | struct task_struct *poll_task; | 52 | struct task_struct *poll_task; |
53 | 53 | ||
54 | struct mutex lock; | 54 | struct mutex lock; |
55 | struct of_device *of_dev; | 55 | struct platform_device *of_dev; |
56 | 56 | ||
57 | struct i2c_client *thermostat; | 57 | struct i2c_client *thermostat; |
58 | struct i2c_client *fan; | 58 | struct i2c_client *fan; |
@@ -322,10 +322,10 @@ do_attach( struct i2c_adapter *adapter ) | |||
322 | 322 | ||
323 | memset(&info, 0, sizeof(struct i2c_board_info)); | 323 | memset(&info, 0, sizeof(struct i2c_board_info)); |
324 | strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE); | 324 | strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE); |
325 | i2c_new_probed_device(adapter, &info, scan_ds1775); | 325 | i2c_new_probed_device(adapter, &info, scan_ds1775, NULL); |
326 | 326 | ||
327 | strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE); | 327 | strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE); |
328 | i2c_new_probed_device(adapter, &info, scan_adm1030); | 328 | i2c_new_probed_device(adapter, &info, scan_adm1030, NULL); |
329 | 329 | ||
330 | if( x.thermostat && x.fan ) { | 330 | if( x.thermostat && x.fan ) { |
331 | x.running = 1; | 331 | x.running = 1; |
@@ -444,13 +444,13 @@ static struct i2c_driver g4fan_driver = { | |||
444 | /************************************************************************/ | 444 | /************************************************************************/ |
445 | 445 | ||
446 | static int | 446 | static int |
447 | therm_of_probe( struct of_device *dev, const struct of_device_id *match ) | 447 | therm_of_probe( struct platform_device *dev, const struct of_device_id *match ) |
448 | { | 448 | { |
449 | return i2c_add_driver( &g4fan_driver ); | 449 | return i2c_add_driver( &g4fan_driver ); |
450 | } | 450 | } |
451 | 451 | ||
452 | static int | 452 | static int |
453 | therm_of_remove( struct of_device *dev ) | 453 | therm_of_remove( struct platform_device *dev ) |
454 | { | 454 | { |
455 | i2c_del_driver( &g4fan_driver ); | 455 | i2c_del_driver( &g4fan_driver ); |
456 | return 0; | 456 | return 0; |
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 3bdbb6115702..368e8e98f705 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -107,11 +107,10 @@ struct crypt_config { | |||
107 | struct workqueue_struct *io_queue; | 107 | struct workqueue_struct *io_queue; |
108 | struct workqueue_struct *crypt_queue; | 108 | struct workqueue_struct *crypt_queue; |
109 | 109 | ||
110 | /* | 110 | char *cipher; |
111 | * crypto related data | 111 | char *cipher_mode; |
112 | */ | 112 | |
113 | struct crypt_iv_operations *iv_gen_ops; | 113 | struct crypt_iv_operations *iv_gen_ops; |
114 | char *iv_mode; | ||
115 | union { | 114 | union { |
116 | struct iv_essiv_private essiv; | 115 | struct iv_essiv_private essiv; |
117 | struct iv_benbi_private benbi; | 116 | struct iv_benbi_private benbi; |
@@ -135,8 +134,6 @@ struct crypt_config { | |||
135 | unsigned int dmreq_start; | 134 | unsigned int dmreq_start; |
136 | struct ablkcipher_request *req; | 135 | struct ablkcipher_request *req; |
137 | 136 | ||
138 | char cipher[CRYPTO_MAX_ALG_NAME]; | ||
139 | char chainmode[CRYPTO_MAX_ALG_NAME]; | ||
140 | struct crypto_ablkcipher *tfm; | 137 | struct crypto_ablkcipher *tfm; |
141 | unsigned long flags; | 138 | unsigned long flags; |
142 | unsigned int key_size; | 139 | unsigned int key_size; |
@@ -999,82 +996,135 @@ static int crypt_wipe_key(struct crypt_config *cc) | |||
999 | return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size); | 996 | return crypto_ablkcipher_setkey(cc->tfm, cc->key, cc->key_size); |
1000 | } | 997 | } |
1001 | 998 | ||
1002 | /* | 999 | static void crypt_dtr(struct dm_target *ti) |
1003 | * Construct an encryption mapping: | ||
1004 | * <cipher> <key> <iv_offset> <dev_path> <start> | ||
1005 | */ | ||
1006 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | ||
1007 | { | 1000 | { |
1008 | struct crypt_config *cc; | 1001 | struct crypt_config *cc = ti->private; |
1009 | struct crypto_ablkcipher *tfm; | ||
1010 | char *tmp; | ||
1011 | char *cipher; | ||
1012 | char *chainmode; | ||
1013 | char *ivmode; | ||
1014 | char *ivopts; | ||
1015 | unsigned int key_size; | ||
1016 | unsigned long long tmpll; | ||
1017 | 1002 | ||
1018 | if (argc != 5) { | 1003 | ti->private = NULL; |
1019 | ti->error = "Not enough arguments"; | 1004 | |
1005 | if (!cc) | ||
1006 | return; | ||
1007 | |||
1008 | if (cc->io_queue) | ||
1009 | destroy_workqueue(cc->io_queue); | ||
1010 | if (cc->crypt_queue) | ||
1011 | destroy_workqueue(cc->crypt_queue); | ||
1012 | |||
1013 | if (cc->bs) | ||
1014 | bioset_free(cc->bs); | ||
1015 | |||
1016 | if (cc->page_pool) | ||
1017 | mempool_destroy(cc->page_pool); | ||
1018 | if (cc->req_pool) | ||
1019 | mempool_destroy(cc->req_pool); | ||
1020 | if (cc->io_pool) | ||
1021 | mempool_destroy(cc->io_pool); | ||
1022 | |||
1023 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | ||
1024 | cc->iv_gen_ops->dtr(cc); | ||
1025 | |||
1026 | if (cc->tfm && !IS_ERR(cc->tfm)) | ||
1027 | crypto_free_ablkcipher(cc->tfm); | ||
1028 | |||
1029 | if (cc->dev) | ||
1030 | dm_put_device(ti, cc->dev); | ||
1031 | |||
1032 | kzfree(cc->cipher); | ||
1033 | kzfree(cc->cipher_mode); | ||
1034 | |||
1035 | /* Must zero key material before freeing */ | ||
1036 | kzfree(cc); | ||
1037 | } | ||
1038 | |||
1039 | static int crypt_ctr_cipher(struct dm_target *ti, | ||
1040 | char *cipher_in, char *key) | ||
1041 | { | ||
1042 | struct crypt_config *cc = ti->private; | ||
1043 | char *tmp, *cipher, *chainmode, *ivmode, *ivopts; | ||
1044 | char *cipher_api = NULL; | ||
1045 | int ret = -EINVAL; | ||
1046 | |||
1047 | /* Convert to crypto api definition? */ | ||
1048 | if (strchr(cipher_in, '(')) { | ||
1049 | ti->error = "Bad cipher specification"; | ||
1020 | return -EINVAL; | 1050 | return -EINVAL; |
1021 | } | 1051 | } |
1022 | 1052 | ||
1023 | tmp = argv[0]; | 1053 | /* |
1054 | * Legacy dm-crypt cipher specification | ||
1055 | * cipher-mode-iv:ivopts | ||
1056 | */ | ||
1057 | tmp = cipher_in; | ||
1024 | cipher = strsep(&tmp, "-"); | 1058 | cipher = strsep(&tmp, "-"); |
1059 | |||
1060 | cc->cipher = kstrdup(cipher, GFP_KERNEL); | ||
1061 | if (!cc->cipher) | ||
1062 | goto bad_mem; | ||
1063 | |||
1064 | if (tmp) { | ||
1065 | cc->cipher_mode = kstrdup(tmp, GFP_KERNEL); | ||
1066 | if (!cc->cipher_mode) | ||
1067 | goto bad_mem; | ||
1068 | } | ||
1069 | |||
1025 | chainmode = strsep(&tmp, "-"); | 1070 | chainmode = strsep(&tmp, "-"); |
1026 | ivopts = strsep(&tmp, "-"); | 1071 | ivopts = strsep(&tmp, "-"); |
1027 | ivmode = strsep(&ivopts, ":"); | 1072 | ivmode = strsep(&ivopts, ":"); |
1028 | 1073 | ||
1029 | if (tmp) | 1074 | if (tmp) |
1030 | DMWARN("Unexpected additional cipher options"); | 1075 | DMWARN("Ignoring unexpected additional cipher options"); |
1031 | |||
1032 | key_size = strlen(argv[1]) >> 1; | ||
1033 | |||
1034 | cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); | ||
1035 | if (cc == NULL) { | ||
1036 | ti->error = | ||
1037 | "Cannot allocate transparent encryption context"; | ||
1038 | return -ENOMEM; | ||
1039 | } | ||
1040 | 1076 | ||
1041 | /* Compatibility mode for old dm-crypt cipher strings */ | 1077 | /* Compatibility mode for old dm-crypt mappings */ |
1042 | if (!chainmode || (strcmp(chainmode, "plain") == 0 && !ivmode)) { | 1078 | if (!chainmode || (!strcmp(chainmode, "plain") && !ivmode)) { |
1079 | kfree(cc->cipher_mode); | ||
1080 | cc->cipher_mode = kstrdup("cbc-plain", GFP_KERNEL); | ||
1043 | chainmode = "cbc"; | 1081 | chainmode = "cbc"; |
1044 | ivmode = "plain"; | 1082 | ivmode = "plain"; |
1045 | } | 1083 | } |
1046 | 1084 | ||
1047 | if (strcmp(chainmode, "ecb") && !ivmode) { | 1085 | if (strcmp(chainmode, "ecb") && !ivmode) { |
1048 | ti->error = "This chaining mode requires an IV mechanism"; | 1086 | ti->error = "IV mechanism required"; |
1049 | goto bad_cipher; | 1087 | return -EINVAL; |
1050 | } | 1088 | } |
1051 | 1089 | ||
1052 | if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", | 1090 | cipher_api = kmalloc(CRYPTO_MAX_ALG_NAME, GFP_KERNEL); |
1053 | chainmode, cipher) >= CRYPTO_MAX_ALG_NAME) { | 1091 | if (!cipher_api) |
1054 | ti->error = "Chain mode + cipher name is too long"; | 1092 | goto bad_mem; |
1055 | goto bad_cipher; | 1093 | |
1094 | ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME, | ||
1095 | "%s(%s)", chainmode, cipher); | ||
1096 | if (ret < 0) { | ||
1097 | kfree(cipher_api); | ||
1098 | goto bad_mem; | ||
1056 | } | 1099 | } |
1057 | 1100 | ||
1058 | tfm = crypto_alloc_ablkcipher(cc->cipher, 0, 0); | 1101 | /* Allocate cipher */ |
1059 | if (IS_ERR(tfm)) { | 1102 | cc->tfm = crypto_alloc_ablkcipher(cipher_api, 0, 0); |
1103 | if (IS_ERR(cc->tfm)) { | ||
1104 | ret = PTR_ERR(cc->tfm); | ||
1060 | ti->error = "Error allocating crypto tfm"; | 1105 | ti->error = "Error allocating crypto tfm"; |
1061 | goto bad_cipher; | 1106 | goto bad; |
1062 | } | 1107 | } |
1063 | 1108 | ||
1064 | strcpy(cc->cipher, cipher); | 1109 | /* Initialize and set key */ |
1065 | strcpy(cc->chainmode, chainmode); | 1110 | ret = crypt_set_key(cc, key); |
1066 | cc->tfm = tfm; | 1111 | if (ret < 0) { |
1067 | |||
1068 | if (crypt_set_key(cc, argv[1]) < 0) { | ||
1069 | ti->error = "Error decoding and setting key"; | 1112 | ti->error = "Error decoding and setting key"; |
1070 | goto bad_ivmode; | 1113 | goto bad; |
1071 | } | 1114 | } |
1072 | 1115 | ||
1073 | /* | 1116 | /* Initialize IV */ |
1074 | * Choose ivmode. Valid modes: "plain", "essiv:<esshash>", "benbi". | 1117 | cc->iv_size = crypto_ablkcipher_ivsize(cc->tfm); |
1075 | * See comments at iv code | 1118 | if (cc->iv_size) |
1076 | */ | 1119 | /* at least a 64 bit sector number should fit in our buffer */ |
1120 | cc->iv_size = max(cc->iv_size, | ||
1121 | (unsigned int)(sizeof(u64) / sizeof(u8))); | ||
1122 | else if (ivmode) { | ||
1123 | DMWARN("Selected cipher does not support IVs"); | ||
1124 | ivmode = NULL; | ||
1125 | } | ||
1077 | 1126 | ||
1127 | /* Choose ivmode, see comments at iv code. */ | ||
1078 | if (ivmode == NULL) | 1128 | if (ivmode == NULL) |
1079 | cc->iv_gen_ops = NULL; | 1129 | cc->iv_gen_ops = NULL; |
1080 | else if (strcmp(ivmode, "plain") == 0) | 1130 | else if (strcmp(ivmode, "plain") == 0) |
@@ -1088,159 +1138,138 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1088 | else if (strcmp(ivmode, "null") == 0) | 1138 | else if (strcmp(ivmode, "null") == 0) |
1089 | cc->iv_gen_ops = &crypt_iv_null_ops; | 1139 | cc->iv_gen_ops = &crypt_iv_null_ops; |
1090 | else { | 1140 | else { |
1141 | ret = -EINVAL; | ||
1091 | ti->error = "Invalid IV mode"; | 1142 | ti->error = "Invalid IV mode"; |
1092 | goto bad_ivmode; | 1143 | goto bad; |
1093 | } | 1144 | } |
1094 | 1145 | ||
1095 | if (cc->iv_gen_ops && cc->iv_gen_ops->ctr && | 1146 | /* Allocate IV */ |
1096 | cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) | 1147 | if (cc->iv_gen_ops && cc->iv_gen_ops->ctr) { |
1097 | goto bad_ivmode; | 1148 | ret = cc->iv_gen_ops->ctr(cc, ti, ivopts); |
1098 | 1149 | if (ret < 0) { | |
1099 | if (cc->iv_gen_ops && cc->iv_gen_ops->init && | 1150 | ti->error = "Error creating IV"; |
1100 | cc->iv_gen_ops->init(cc) < 0) { | 1151 | goto bad; |
1101 | ti->error = "Error initialising IV"; | 1152 | } |
1102 | goto bad_slab_pool; | ||
1103 | } | 1153 | } |
1104 | 1154 | ||
1105 | cc->iv_size = crypto_ablkcipher_ivsize(tfm); | 1155 | /* Initialize IV (set keys for ESSIV etc) */ |
1106 | if (cc->iv_size) | 1156 | if (cc->iv_gen_ops && cc->iv_gen_ops->init) { |
1107 | /* at least a 64 bit sector number should fit in our buffer */ | 1157 | ret = cc->iv_gen_ops->init(cc); |
1108 | cc->iv_size = max(cc->iv_size, | 1158 | if (ret < 0) { |
1109 | (unsigned int)(sizeof(u64) / sizeof(u8))); | 1159 | ti->error = "Error initialising IV"; |
1110 | else { | 1160 | goto bad; |
1111 | if (cc->iv_gen_ops) { | ||
1112 | DMWARN("Selected cipher does not support IVs"); | ||
1113 | if (cc->iv_gen_ops->dtr) | ||
1114 | cc->iv_gen_ops->dtr(cc); | ||
1115 | cc->iv_gen_ops = NULL; | ||
1116 | } | 1161 | } |
1117 | } | 1162 | } |
1118 | 1163 | ||
1164 | ret = 0; | ||
1165 | bad: | ||
1166 | kfree(cipher_api); | ||
1167 | return ret; | ||
1168 | |||
1169 | bad_mem: | ||
1170 | ti->error = "Cannot allocate cipher strings"; | ||
1171 | return -ENOMEM; | ||
1172 | } | ||
1173 | |||
1174 | /* | ||
1175 | * Construct an encryption mapping: | ||
1176 | * <cipher> <key> <iv_offset> <dev_path> <start> | ||
1177 | */ | ||
1178 | static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | ||
1179 | { | ||
1180 | struct crypt_config *cc; | ||
1181 | unsigned int key_size; | ||
1182 | unsigned long long tmpll; | ||
1183 | int ret; | ||
1184 | |||
1185 | if (argc != 5) { | ||
1186 | ti->error = "Not enough arguments"; | ||
1187 | return -EINVAL; | ||
1188 | } | ||
1189 | |||
1190 | key_size = strlen(argv[1]) >> 1; | ||
1191 | |||
1192 | cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); | ||
1193 | if (!cc) { | ||
1194 | ti->error = "Cannot allocate encryption context"; | ||
1195 | return -ENOMEM; | ||
1196 | } | ||
1197 | |||
1198 | ti->private = cc; | ||
1199 | ret = crypt_ctr_cipher(ti, argv[0], argv[1]); | ||
1200 | if (ret < 0) | ||
1201 | goto bad; | ||
1202 | |||
1203 | ret = -ENOMEM; | ||
1119 | cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); | 1204 | cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); |
1120 | if (!cc->io_pool) { | 1205 | if (!cc->io_pool) { |
1121 | ti->error = "Cannot allocate crypt io mempool"; | 1206 | ti->error = "Cannot allocate crypt io mempool"; |
1122 | goto bad_slab_pool; | 1207 | goto bad; |
1123 | } | 1208 | } |
1124 | 1209 | ||
1125 | cc->dmreq_start = sizeof(struct ablkcipher_request); | 1210 | cc->dmreq_start = sizeof(struct ablkcipher_request); |
1126 | cc->dmreq_start += crypto_ablkcipher_reqsize(tfm); | 1211 | cc->dmreq_start += crypto_ablkcipher_reqsize(cc->tfm); |
1127 | cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); | 1212 | cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); |
1128 | cc->dmreq_start += crypto_ablkcipher_alignmask(tfm) & | 1213 | cc->dmreq_start += crypto_ablkcipher_alignmask(cc->tfm) & |
1129 | ~(crypto_tfm_ctx_alignment() - 1); | 1214 | ~(crypto_tfm_ctx_alignment() - 1); |
1130 | 1215 | ||
1131 | cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + | 1216 | cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + |
1132 | sizeof(struct dm_crypt_request) + cc->iv_size); | 1217 | sizeof(struct dm_crypt_request) + cc->iv_size); |
1133 | if (!cc->req_pool) { | 1218 | if (!cc->req_pool) { |
1134 | ti->error = "Cannot allocate crypt request mempool"; | 1219 | ti->error = "Cannot allocate crypt request mempool"; |
1135 | goto bad_req_pool; | 1220 | goto bad; |
1136 | } | 1221 | } |
1137 | cc->req = NULL; | 1222 | cc->req = NULL; |
1138 | 1223 | ||
1139 | cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); | 1224 | cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); |
1140 | if (!cc->page_pool) { | 1225 | if (!cc->page_pool) { |
1141 | ti->error = "Cannot allocate page mempool"; | 1226 | ti->error = "Cannot allocate page mempool"; |
1142 | goto bad_page_pool; | 1227 | goto bad; |
1143 | } | 1228 | } |
1144 | 1229 | ||
1145 | cc->bs = bioset_create(MIN_IOS, 0); | 1230 | cc->bs = bioset_create(MIN_IOS, 0); |
1146 | if (!cc->bs) { | 1231 | if (!cc->bs) { |
1147 | ti->error = "Cannot allocate crypt bioset"; | 1232 | ti->error = "Cannot allocate crypt bioset"; |
1148 | goto bad_bs; | 1233 | goto bad; |
1149 | } | 1234 | } |
1150 | 1235 | ||
1236 | ret = -EINVAL; | ||
1151 | if (sscanf(argv[2], "%llu", &tmpll) != 1) { | 1237 | if (sscanf(argv[2], "%llu", &tmpll) != 1) { |
1152 | ti->error = "Invalid iv_offset sector"; | 1238 | ti->error = "Invalid iv_offset sector"; |
1153 | goto bad_device; | 1239 | goto bad; |
1154 | } | 1240 | } |
1155 | cc->iv_offset = tmpll; | 1241 | cc->iv_offset = tmpll; |
1156 | 1242 | ||
1157 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { | ||
1158 | ti->error = "Invalid device sector"; | ||
1159 | goto bad_device; | ||
1160 | } | ||
1161 | cc->start = tmpll; | ||
1162 | |||
1163 | if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) { | 1243 | if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) { |
1164 | ti->error = "Device lookup failed"; | 1244 | ti->error = "Device lookup failed"; |
1165 | goto bad_device; | 1245 | goto bad; |
1166 | } | 1246 | } |
1167 | 1247 | ||
1168 | if (ivmode && cc->iv_gen_ops) { | 1248 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { |
1169 | if (ivopts) | 1249 | ti->error = "Invalid device sector"; |
1170 | *(ivopts - 1) = ':'; | 1250 | goto bad; |
1171 | cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL); | 1251 | } |
1172 | if (!cc->iv_mode) { | 1252 | cc->start = tmpll; |
1173 | ti->error = "Error kmallocing iv_mode string"; | ||
1174 | goto bad_ivmode_string; | ||
1175 | } | ||
1176 | strcpy(cc->iv_mode, ivmode); | ||
1177 | } else | ||
1178 | cc->iv_mode = NULL; | ||
1179 | 1253 | ||
1254 | ret = -ENOMEM; | ||
1180 | cc->io_queue = create_singlethread_workqueue("kcryptd_io"); | 1255 | cc->io_queue = create_singlethread_workqueue("kcryptd_io"); |
1181 | if (!cc->io_queue) { | 1256 | if (!cc->io_queue) { |
1182 | ti->error = "Couldn't create kcryptd io queue"; | 1257 | ti->error = "Couldn't create kcryptd io queue"; |
1183 | goto bad_io_queue; | 1258 | goto bad; |
1184 | } | 1259 | } |
1185 | 1260 | ||
1186 | cc->crypt_queue = create_singlethread_workqueue("kcryptd"); | 1261 | cc->crypt_queue = create_singlethread_workqueue("kcryptd"); |
1187 | if (!cc->crypt_queue) { | 1262 | if (!cc->crypt_queue) { |
1188 | ti->error = "Couldn't create kcryptd queue"; | 1263 | ti->error = "Couldn't create kcryptd queue"; |
1189 | goto bad_crypt_queue; | 1264 | goto bad; |
1190 | } | 1265 | } |
1191 | 1266 | ||
1192 | ti->num_flush_requests = 1; | 1267 | ti->num_flush_requests = 1; |
1193 | ti->private = cc; | ||
1194 | return 0; | 1268 | return 0; |
1195 | 1269 | ||
1196 | bad_crypt_queue: | 1270 | bad: |
1197 | destroy_workqueue(cc->io_queue); | 1271 | crypt_dtr(ti); |
1198 | bad_io_queue: | 1272 | return ret; |
1199 | kfree(cc->iv_mode); | ||
1200 | bad_ivmode_string: | ||
1201 | dm_put_device(ti, cc->dev); | ||
1202 | bad_device: | ||
1203 | bioset_free(cc->bs); | ||
1204 | bad_bs: | ||
1205 | mempool_destroy(cc->page_pool); | ||
1206 | bad_page_pool: | ||
1207 | mempool_destroy(cc->req_pool); | ||
1208 | bad_req_pool: | ||
1209 | mempool_destroy(cc->io_pool); | ||
1210 | bad_slab_pool: | ||
1211 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | ||
1212 | cc->iv_gen_ops->dtr(cc); | ||
1213 | bad_ivmode: | ||
1214 | crypto_free_ablkcipher(tfm); | ||
1215 | bad_cipher: | ||
1216 | /* Must zero key material before freeing */ | ||
1217 | kzfree(cc); | ||
1218 | return -EINVAL; | ||
1219 | } | ||
1220 | |||
1221 | static void crypt_dtr(struct dm_target *ti) | ||
1222 | { | ||
1223 | struct crypt_config *cc = (struct crypt_config *) ti->private; | ||
1224 | |||
1225 | destroy_workqueue(cc->io_queue); | ||
1226 | destroy_workqueue(cc->crypt_queue); | ||
1227 | |||
1228 | if (cc->req) | ||
1229 | mempool_free(cc->req, cc->req_pool); | ||
1230 | |||
1231 | bioset_free(cc->bs); | ||
1232 | mempool_destroy(cc->page_pool); | ||
1233 | mempool_destroy(cc->req_pool); | ||
1234 | mempool_destroy(cc->io_pool); | ||
1235 | |||
1236 | kfree(cc->iv_mode); | ||
1237 | if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) | ||
1238 | cc->iv_gen_ops->dtr(cc); | ||
1239 | crypto_free_ablkcipher(cc->tfm); | ||
1240 | dm_put_device(ti, cc->dev); | ||
1241 | |||
1242 | /* Must zero key material before freeing */ | ||
1243 | kzfree(cc); | ||
1244 | } | 1273 | } |
1245 | 1274 | ||
1246 | static int crypt_map(struct dm_target *ti, struct bio *bio, | 1275 | static int crypt_map(struct dm_target *ti, struct bio *bio, |
@@ -1255,7 +1284,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, | |||
1255 | return DM_MAPIO_REMAPPED; | 1284 | return DM_MAPIO_REMAPPED; |
1256 | } | 1285 | } |
1257 | 1286 | ||
1258 | io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin); | 1287 | io = crypt_io_alloc(ti, bio, dm_target_offset(ti, bio->bi_sector)); |
1259 | 1288 | ||
1260 | if (bio_data_dir(io->base_bio) == READ) | 1289 | if (bio_data_dir(io->base_bio) == READ) |
1261 | kcryptd_queue_io(io); | 1290 | kcryptd_queue_io(io); |
@@ -1268,7 +1297,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, | |||
1268 | static int crypt_status(struct dm_target *ti, status_type_t type, | 1297 | static int crypt_status(struct dm_target *ti, status_type_t type, |
1269 | char *result, unsigned int maxlen) | 1298 | char *result, unsigned int maxlen) |
1270 | { | 1299 | { |
1271 | struct crypt_config *cc = (struct crypt_config *) ti->private; | 1300 | struct crypt_config *cc = ti->private; |
1272 | unsigned int sz = 0; | 1301 | unsigned int sz = 0; |
1273 | 1302 | ||
1274 | switch (type) { | 1303 | switch (type) { |
@@ -1277,11 +1306,10 @@ static int crypt_status(struct dm_target *ti, status_type_t type, | |||
1277 | break; | 1306 | break; |
1278 | 1307 | ||
1279 | case STATUSTYPE_TABLE: | 1308 | case STATUSTYPE_TABLE: |
1280 | if (cc->iv_mode) | 1309 | if (cc->cipher_mode) |
1281 | DMEMIT("%s-%s-%s ", cc->cipher, cc->chainmode, | 1310 | DMEMIT("%s-%s ", cc->cipher, cc->cipher_mode); |
1282 | cc->iv_mode); | ||
1283 | else | 1311 | else |
1284 | DMEMIT("%s-%s ", cc->cipher, cc->chainmode); | 1312 | DMEMIT("%s ", cc->cipher); |
1285 | 1313 | ||
1286 | if (cc->key_size > 0) { | 1314 | if (cc->key_size > 0) { |
1287 | if ((maxlen - sz) < ((cc->key_size << 1) + 1)) | 1315 | if ((maxlen - sz) < ((cc->key_size << 1) + 1)) |
@@ -1378,7 +1406,7 @@ static int crypt_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | |||
1378 | return max_size; | 1406 | return max_size; |
1379 | 1407 | ||
1380 | bvm->bi_bdev = cc->dev->bdev; | 1408 | bvm->bi_bdev = cc->dev->bdev; |
1381 | bvm->bi_sector = cc->start + bvm->bi_sector - ti->begin; | 1409 | bvm->bi_sector = cc->start + dm_target_offset(ti, bvm->bi_sector); |
1382 | 1410 | ||
1383 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | 1411 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); |
1384 | } | 1412 | } |
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 852052880d7a..baa11912cc94 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c | |||
@@ -198,6 +198,7 @@ out: | |||
198 | atomic_set(&dc->may_delay, 1); | 198 | atomic_set(&dc->may_delay, 1); |
199 | 199 | ||
200 | ti->num_flush_requests = 1; | 200 | ti->num_flush_requests = 1; |
201 | ti->num_discard_requests = 1; | ||
201 | ti->private = dc; | 202 | ti->private = dc; |
202 | return 0; | 203 | return 0; |
203 | 204 | ||
@@ -281,14 +282,13 @@ static int delay_map(struct dm_target *ti, struct bio *bio, | |||
281 | bio->bi_bdev = dc->dev_write->bdev; | 282 | bio->bi_bdev = dc->dev_write->bdev; |
282 | if (bio_sectors(bio)) | 283 | if (bio_sectors(bio)) |
283 | bio->bi_sector = dc->start_write + | 284 | bio->bi_sector = dc->start_write + |
284 | (bio->bi_sector - ti->begin); | 285 | dm_target_offset(ti, bio->bi_sector); |
285 | 286 | ||
286 | return delay_bio(dc, dc->write_delay, bio); | 287 | return delay_bio(dc, dc->write_delay, bio); |
287 | } | 288 | } |
288 | 289 | ||
289 | bio->bi_bdev = dc->dev_read->bdev; | 290 | bio->bi_bdev = dc->dev_read->bdev; |
290 | bio->bi_sector = dc->start_read + | 291 | bio->bi_sector = dc->start_read + dm_target_offset(ti, bio->bi_sector); |
291 | (bio->bi_sector - ti->begin); | ||
292 | 292 | ||
293 | return delay_bio(dc, dc->read_delay, bio); | 293 | return delay_bio(dc, dc->read_delay, bio); |
294 | } | 294 | } |
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 2b7907b6dd09..0bdb201c2c2a 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c | |||
@@ -173,7 +173,9 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store, | |||
173 | 173 | ||
174 | /* Validate the chunk size against the device block size */ | 174 | /* Validate the chunk size against the device block size */ |
175 | if (chunk_size % | 175 | if (chunk_size % |
176 | (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9)) { | 176 | (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) || |
177 | chunk_size % | ||
178 | (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) { | ||
177 | *error = "Chunk size is not a multiple of device blocksize"; | 179 | *error = "Chunk size is not a multiple of device blocksize"; |
178 | return -EINVAL; | 180 | return -EINVAL; |
179 | } | 181 | } |
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h index e8dfa06af3ba..0b2536247cf5 100644 --- a/drivers/md/dm-exception-store.h +++ b/drivers/md/dm-exception-store.h | |||
@@ -126,8 +126,9 @@ struct dm_exception_store { | |||
126 | }; | 126 | }; |
127 | 127 | ||
128 | /* | 128 | /* |
129 | * Obtain the cow device used by a given snapshot. | 129 | * Obtain the origin or cow device used by a given snapshot. |
130 | */ | 130 | */ |
131 | struct dm_dev *dm_snap_origin(struct dm_snapshot *snap); | ||
131 | struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); | 132 | struct dm_dev *dm_snap_cow(struct dm_snapshot *snap); |
132 | 133 | ||
133 | /* | 134 | /* |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index d7500e1c26f2..3e39193e5036 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -249,55 +249,66 @@ static void __hash_remove(struct hash_cell *hc) | |||
249 | 249 | ||
250 | static void dm_hash_remove_all(int keep_open_devices) | 250 | static void dm_hash_remove_all(int keep_open_devices) |
251 | { | 251 | { |
252 | int i, dev_skipped, dev_removed; | 252 | int i, dev_skipped; |
253 | struct hash_cell *hc; | 253 | struct hash_cell *hc; |
254 | struct list_head *tmp, *n; | 254 | struct mapped_device *md; |
255 | |||
256 | retry: | ||
257 | dev_skipped = 0; | ||
255 | 258 | ||
256 | down_write(&_hash_lock); | 259 | down_write(&_hash_lock); |
257 | 260 | ||
258 | retry: | ||
259 | dev_skipped = dev_removed = 0; | ||
260 | for (i = 0; i < NUM_BUCKETS; i++) { | 261 | for (i = 0; i < NUM_BUCKETS; i++) { |
261 | list_for_each_safe (tmp, n, _name_buckets + i) { | 262 | list_for_each_entry(hc, _name_buckets + i, name_list) { |
262 | hc = list_entry(tmp, struct hash_cell, name_list); | 263 | md = hc->md; |
264 | dm_get(md); | ||
263 | 265 | ||
264 | if (keep_open_devices && | 266 | if (keep_open_devices && dm_lock_for_deletion(md)) { |
265 | dm_lock_for_deletion(hc->md)) { | 267 | dm_put(md); |
266 | dev_skipped++; | 268 | dev_skipped++; |
267 | continue; | 269 | continue; |
268 | } | 270 | } |
271 | |||
269 | __hash_remove(hc); | 272 | __hash_remove(hc); |
270 | dev_removed = 1; | ||
271 | } | ||
272 | } | ||
273 | 273 | ||
274 | /* | 274 | up_write(&_hash_lock); |
275 | * Some mapped devices may be using other mapped devices, so if any | ||
276 | * still exist, repeat until we make no further progress. | ||
277 | */ | ||
278 | if (dev_skipped) { | ||
279 | if (dev_removed) | ||
280 | goto retry; | ||
281 | 275 | ||
282 | DMWARN("remove_all left %d open device(s)", dev_skipped); | 276 | dm_put(md); |
277 | if (likely(keep_open_devices)) | ||
278 | dm_destroy(md); | ||
279 | else | ||
280 | dm_destroy_immediate(md); | ||
281 | |||
282 | /* | ||
283 | * Some mapped devices may be using other mapped | ||
284 | * devices, so repeat until we make no further | ||
285 | * progress. If a new mapped device is created | ||
286 | * here it will also get removed. | ||
287 | */ | ||
288 | goto retry; | ||
289 | } | ||
283 | } | 290 | } |
284 | 291 | ||
285 | up_write(&_hash_lock); | 292 | up_write(&_hash_lock); |
293 | |||
294 | if (dev_skipped) | ||
295 | DMWARN("remove_all left %d open device(s)", dev_skipped); | ||
286 | } | 296 | } |
287 | 297 | ||
288 | static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old, | 298 | static struct mapped_device *dm_hash_rename(struct dm_ioctl *param, |
289 | const char *new) | 299 | const char *new) |
290 | { | 300 | { |
291 | char *new_name, *old_name; | 301 | char *new_name, *old_name; |
292 | struct hash_cell *hc; | 302 | struct hash_cell *hc; |
293 | struct dm_table *table; | 303 | struct dm_table *table; |
304 | struct mapped_device *md; | ||
294 | 305 | ||
295 | /* | 306 | /* |
296 | * duplicate new. | 307 | * duplicate new. |
297 | */ | 308 | */ |
298 | new_name = kstrdup(new, GFP_KERNEL); | 309 | new_name = kstrdup(new, GFP_KERNEL); |
299 | if (!new_name) | 310 | if (!new_name) |
300 | return -ENOMEM; | 311 | return ERR_PTR(-ENOMEM); |
301 | 312 | ||
302 | down_write(&_hash_lock); | 313 | down_write(&_hash_lock); |
303 | 314 | ||
@@ -306,24 +317,24 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old, | |||
306 | */ | 317 | */ |
307 | hc = __get_name_cell(new); | 318 | hc = __get_name_cell(new); |
308 | if (hc) { | 319 | if (hc) { |
309 | DMWARN("asked to rename to an already existing name %s -> %s", | 320 | DMWARN("asked to rename to an already-existing name %s -> %s", |
310 | old, new); | 321 | param->name, new); |
311 | dm_put(hc->md); | 322 | dm_put(hc->md); |
312 | up_write(&_hash_lock); | 323 | up_write(&_hash_lock); |
313 | kfree(new_name); | 324 | kfree(new_name); |
314 | return -EBUSY; | 325 | return ERR_PTR(-EBUSY); |
315 | } | 326 | } |
316 | 327 | ||
317 | /* | 328 | /* |
318 | * Is there such a device as 'old' ? | 329 | * Is there such a device as 'old' ? |
319 | */ | 330 | */ |
320 | hc = __get_name_cell(old); | 331 | hc = __get_name_cell(param->name); |
321 | if (!hc) { | 332 | if (!hc) { |
322 | DMWARN("asked to rename a non existent device %s -> %s", | 333 | DMWARN("asked to rename a non-existent device %s -> %s", |
323 | old, new); | 334 | param->name, new); |
324 | up_write(&_hash_lock); | 335 | up_write(&_hash_lock); |
325 | kfree(new_name); | 336 | kfree(new_name); |
326 | return -ENXIO; | 337 | return ERR_PTR(-ENXIO); |
327 | } | 338 | } |
328 | 339 | ||
329 | /* | 340 | /* |
@@ -345,13 +356,14 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old, | |||
345 | dm_table_put(table); | 356 | dm_table_put(table); |
346 | } | 357 | } |
347 | 358 | ||
348 | if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie)) | 359 | if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, param->event_nr)) |
349 | *flags |= DM_UEVENT_GENERATED_FLAG; | 360 | param->flags |= DM_UEVENT_GENERATED_FLAG; |
350 | 361 | ||
351 | dm_put(hc->md); | 362 | md = hc->md; |
352 | up_write(&_hash_lock); | 363 | up_write(&_hash_lock); |
353 | kfree(old_name); | 364 | kfree(old_name); |
354 | return 0; | 365 | |
366 | return md; | ||
355 | } | 367 | } |
356 | 368 | ||
357 | /*----------------------------------------------------------------- | 369 | /*----------------------------------------------------------------- |
@@ -573,7 +585,7 @@ static struct dm_table *dm_get_live_or_inactive_table(struct mapped_device *md, | |||
573 | * Fills in a dm_ioctl structure, ready for sending back to | 585 | * Fills in a dm_ioctl structure, ready for sending back to |
574 | * userland. | 586 | * userland. |
575 | */ | 587 | */ |
576 | static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) | 588 | static void __dev_status(struct mapped_device *md, struct dm_ioctl *param) |
577 | { | 589 | { |
578 | struct gendisk *disk = dm_disk(md); | 590 | struct gendisk *disk = dm_disk(md); |
579 | struct dm_table *table; | 591 | struct dm_table *table; |
@@ -617,8 +629,6 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) | |||
617 | dm_table_put(table); | 629 | dm_table_put(table); |
618 | } | 630 | } |
619 | } | 631 | } |
620 | |||
621 | return 0; | ||
622 | } | 632 | } |
623 | 633 | ||
624 | static int dev_create(struct dm_ioctl *param, size_t param_size) | 634 | static int dev_create(struct dm_ioctl *param, size_t param_size) |
@@ -640,15 +650,17 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) | |||
640 | r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); | 650 | r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); |
641 | if (r) { | 651 | if (r) { |
642 | dm_put(md); | 652 | dm_put(md); |
653 | dm_destroy(md); | ||
643 | return r; | 654 | return r; |
644 | } | 655 | } |
645 | 656 | ||
646 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; | 657 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; |
647 | 658 | ||
648 | r = __dev_status(md, param); | 659 | __dev_status(md, param); |
660 | |||
649 | dm_put(md); | 661 | dm_put(md); |
650 | 662 | ||
651 | return r; | 663 | return 0; |
652 | } | 664 | } |
653 | 665 | ||
654 | /* | 666 | /* |
@@ -742,6 +754,7 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size) | |||
742 | param->flags |= DM_UEVENT_GENERATED_FLAG; | 754 | param->flags |= DM_UEVENT_GENERATED_FLAG; |
743 | 755 | ||
744 | dm_put(md); | 756 | dm_put(md); |
757 | dm_destroy(md); | ||
745 | return 0; | 758 | return 0; |
746 | } | 759 | } |
747 | 760 | ||
@@ -762,6 +775,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) | |||
762 | { | 775 | { |
763 | int r; | 776 | int r; |
764 | char *new_name = (char *) param + param->data_start; | 777 | char *new_name = (char *) param + param->data_start; |
778 | struct mapped_device *md; | ||
765 | 779 | ||
766 | if (new_name < param->data || | 780 | if (new_name < param->data || |
767 | invalid_str(new_name, (void *) param + param_size) || | 781 | invalid_str(new_name, (void *) param + param_size) || |
@@ -774,10 +788,14 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) | |||
774 | if (r) | 788 | if (r) |
775 | return r; | 789 | return r; |
776 | 790 | ||
777 | param->data_size = 0; | 791 | md = dm_hash_rename(param, new_name); |
792 | if (IS_ERR(md)) | ||
793 | return PTR_ERR(md); | ||
794 | |||
795 | __dev_status(md, param); | ||
796 | dm_put(md); | ||
778 | 797 | ||
779 | return dm_hash_rename(param->event_nr, ¶m->flags, param->name, | 798 | return 0; |
780 | new_name); | ||
781 | } | 799 | } |
782 | 800 | ||
783 | static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) | 801 | static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) |
@@ -818,8 +836,6 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) | |||
818 | geometry.start = indata[3]; | 836 | geometry.start = indata[3]; |
819 | 837 | ||
820 | r = dm_set_geometry(md, &geometry); | 838 | r = dm_set_geometry(md, &geometry); |
821 | if (!r) | ||
822 | r = __dev_status(md, param); | ||
823 | 839 | ||
824 | param->data_size = 0; | 840 | param->data_size = 0; |
825 | 841 | ||
@@ -843,13 +859,17 @@ static int do_suspend(struct dm_ioctl *param) | |||
843 | if (param->flags & DM_NOFLUSH_FLAG) | 859 | if (param->flags & DM_NOFLUSH_FLAG) |
844 | suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; | 860 | suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; |
845 | 861 | ||
846 | if (!dm_suspended_md(md)) | 862 | if (!dm_suspended_md(md)) { |
847 | r = dm_suspend(md, suspend_flags); | 863 | r = dm_suspend(md, suspend_flags); |
864 | if (r) | ||
865 | goto out; | ||
866 | } | ||
848 | 867 | ||
849 | if (!r) | 868 | __dev_status(md, param); |
850 | r = __dev_status(md, param); | ||
851 | 869 | ||
870 | out: | ||
852 | dm_put(md); | 871 | dm_put(md); |
872 | |||
853 | return r; | 873 | return r; |
854 | } | 874 | } |
855 | 875 | ||
@@ -911,7 +931,7 @@ static int do_resume(struct dm_ioctl *param) | |||
911 | dm_table_destroy(old_map); | 931 | dm_table_destroy(old_map); |
912 | 932 | ||
913 | if (!r) | 933 | if (!r) |
914 | r = __dev_status(md, param); | 934 | __dev_status(md, param); |
915 | 935 | ||
916 | dm_put(md); | 936 | dm_put(md); |
917 | return r; | 937 | return r; |
@@ -935,16 +955,16 @@ static int dev_suspend(struct dm_ioctl *param, size_t param_size) | |||
935 | */ | 955 | */ |
936 | static int dev_status(struct dm_ioctl *param, size_t param_size) | 956 | static int dev_status(struct dm_ioctl *param, size_t param_size) |
937 | { | 957 | { |
938 | int r; | ||
939 | struct mapped_device *md; | 958 | struct mapped_device *md; |
940 | 959 | ||
941 | md = find_device(param); | 960 | md = find_device(param); |
942 | if (!md) | 961 | if (!md) |
943 | return -ENXIO; | 962 | return -ENXIO; |
944 | 963 | ||
945 | r = __dev_status(md, param); | 964 | __dev_status(md, param); |
946 | dm_put(md); | 965 | dm_put(md); |
947 | return r; | 966 | |
967 | return 0; | ||
948 | } | 968 | } |
949 | 969 | ||
950 | /* | 970 | /* |
@@ -1019,7 +1039,7 @@ static void retrieve_status(struct dm_table *table, | |||
1019 | */ | 1039 | */ |
1020 | static int dev_wait(struct dm_ioctl *param, size_t param_size) | 1040 | static int dev_wait(struct dm_ioctl *param, size_t param_size) |
1021 | { | 1041 | { |
1022 | int r; | 1042 | int r = 0; |
1023 | struct mapped_device *md; | 1043 | struct mapped_device *md; |
1024 | struct dm_table *table; | 1044 | struct dm_table *table; |
1025 | 1045 | ||
@@ -1040,9 +1060,7 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size) | |||
1040 | * changed to trigger the event, so we may as well tell | 1060 | * changed to trigger the event, so we may as well tell |
1041 | * him and save an ioctl. | 1061 | * him and save an ioctl. |
1042 | */ | 1062 | */ |
1043 | r = __dev_status(md, param); | 1063 | __dev_status(md, param); |
1044 | if (r) | ||
1045 | goto out; | ||
1046 | 1064 | ||
1047 | table = dm_get_live_or_inactive_table(md, param); | 1065 | table = dm_get_live_or_inactive_table(md, param); |
1048 | if (table) { | 1066 | if (table) { |
@@ -1050,8 +1068,9 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size) | |||
1050 | dm_table_put(table); | 1068 | dm_table_put(table); |
1051 | } | 1069 | } |
1052 | 1070 | ||
1053 | out: | 1071 | out: |
1054 | dm_put(md); | 1072 | dm_put(md); |
1073 | |||
1055 | return r; | 1074 | return r; |
1056 | } | 1075 | } |
1057 | 1076 | ||
@@ -1112,28 +1131,9 @@ static int populate_table(struct dm_table *table, | |||
1112 | next = spec->next; | 1131 | next = spec->next; |
1113 | } | 1132 | } |
1114 | 1133 | ||
1115 | r = dm_table_set_type(table); | ||
1116 | if (r) { | ||
1117 | DMWARN("unable to set table type"); | ||
1118 | return r; | ||
1119 | } | ||
1120 | |||
1121 | return dm_table_complete(table); | 1134 | return dm_table_complete(table); |
1122 | } | 1135 | } |
1123 | 1136 | ||
1124 | static int table_prealloc_integrity(struct dm_table *t, | ||
1125 | struct mapped_device *md) | ||
1126 | { | ||
1127 | struct list_head *devices = dm_table_get_devices(t); | ||
1128 | struct dm_dev_internal *dd; | ||
1129 | |||
1130 | list_for_each_entry(dd, devices, list) | ||
1131 | if (bdev_get_integrity(dd->dm_dev.bdev)) | ||
1132 | return blk_integrity_register(dm_disk(md), NULL); | ||
1133 | |||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | static int table_load(struct dm_ioctl *param, size_t param_size) | 1137 | static int table_load(struct dm_ioctl *param, size_t param_size) |
1138 | { | 1138 | { |
1139 | int r; | 1139 | int r; |
@@ -1155,21 +1155,30 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
1155 | goto out; | 1155 | goto out; |
1156 | } | 1156 | } |
1157 | 1157 | ||
1158 | r = table_prealloc_integrity(t, md); | 1158 | /* Protect md->type and md->queue against concurrent table loads. */ |
1159 | if (r) { | 1159 | dm_lock_md_type(md); |
1160 | DMERR("%s: could not register integrity profile.", | 1160 | if (dm_get_md_type(md) == DM_TYPE_NONE) |
1161 | dm_device_name(md)); | 1161 | /* Initial table load: acquire type of table. */ |
1162 | dm_set_md_type(md, dm_table_get_type(t)); | ||
1163 | else if (dm_get_md_type(md) != dm_table_get_type(t)) { | ||
1164 | DMWARN("can't change device type after initial table load."); | ||
1162 | dm_table_destroy(t); | 1165 | dm_table_destroy(t); |
1166 | dm_unlock_md_type(md); | ||
1167 | r = -EINVAL; | ||
1163 | goto out; | 1168 | goto out; |
1164 | } | 1169 | } |
1165 | 1170 | ||
1166 | r = dm_table_alloc_md_mempools(t); | 1171 | /* setup md->queue to reflect md's type (may block) */ |
1172 | r = dm_setup_md_queue(md); | ||
1167 | if (r) { | 1173 | if (r) { |
1168 | DMWARN("unable to allocate mempools for this table"); | 1174 | DMWARN("unable to set up device queue for new table."); |
1169 | dm_table_destroy(t); | 1175 | dm_table_destroy(t); |
1176 | dm_unlock_md_type(md); | ||
1170 | goto out; | 1177 | goto out; |
1171 | } | 1178 | } |
1179 | dm_unlock_md_type(md); | ||
1172 | 1180 | ||
1181 | /* stage inactive table */ | ||
1173 | down_write(&_hash_lock); | 1182 | down_write(&_hash_lock); |
1174 | hc = dm_get_mdptr(md); | 1183 | hc = dm_get_mdptr(md); |
1175 | if (!hc || hc->md != md) { | 1184 | if (!hc || hc->md != md) { |
@@ -1186,7 +1195,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
1186 | up_write(&_hash_lock); | 1195 | up_write(&_hash_lock); |
1187 | 1196 | ||
1188 | param->flags |= DM_INACTIVE_PRESENT_FLAG; | 1197 | param->flags |= DM_INACTIVE_PRESENT_FLAG; |
1189 | r = __dev_status(md, param); | 1198 | __dev_status(md, param); |
1190 | 1199 | ||
1191 | out: | 1200 | out: |
1192 | dm_put(md); | 1201 | dm_put(md); |
@@ -1196,7 +1205,6 @@ out: | |||
1196 | 1205 | ||
1197 | static int table_clear(struct dm_ioctl *param, size_t param_size) | 1206 | static int table_clear(struct dm_ioctl *param, size_t param_size) |
1198 | { | 1207 | { |
1199 | int r; | ||
1200 | struct hash_cell *hc; | 1208 | struct hash_cell *hc; |
1201 | struct mapped_device *md; | 1209 | struct mapped_device *md; |
1202 | 1210 | ||
@@ -1216,11 +1224,12 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) | |||
1216 | 1224 | ||
1217 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; | 1225 | param->flags &= ~DM_INACTIVE_PRESENT_FLAG; |
1218 | 1226 | ||
1219 | r = __dev_status(hc->md, param); | 1227 | __dev_status(hc->md, param); |
1220 | md = hc->md; | 1228 | md = hc->md; |
1221 | up_write(&_hash_lock); | 1229 | up_write(&_hash_lock); |
1222 | dm_put(md); | 1230 | dm_put(md); |
1223 | return r; | 1231 | |
1232 | return 0; | ||
1224 | } | 1233 | } |
1225 | 1234 | ||
1226 | /* | 1235 | /* |
@@ -1265,7 +1274,6 @@ static void retrieve_deps(struct dm_table *table, | |||
1265 | 1274 | ||
1266 | static int table_deps(struct dm_ioctl *param, size_t param_size) | 1275 | static int table_deps(struct dm_ioctl *param, size_t param_size) |
1267 | { | 1276 | { |
1268 | int r = 0; | ||
1269 | struct mapped_device *md; | 1277 | struct mapped_device *md; |
1270 | struct dm_table *table; | 1278 | struct dm_table *table; |
1271 | 1279 | ||
@@ -1273,9 +1281,7 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) | |||
1273 | if (!md) | 1281 | if (!md) |
1274 | return -ENXIO; | 1282 | return -ENXIO; |
1275 | 1283 | ||
1276 | r = __dev_status(md, param); | 1284 | __dev_status(md, param); |
1277 | if (r) | ||
1278 | goto out; | ||
1279 | 1285 | ||
1280 | table = dm_get_live_or_inactive_table(md, param); | 1286 | table = dm_get_live_or_inactive_table(md, param); |
1281 | if (table) { | 1287 | if (table) { |
@@ -1283,9 +1289,9 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) | |||
1283 | dm_table_put(table); | 1289 | dm_table_put(table); |
1284 | } | 1290 | } |
1285 | 1291 | ||
1286 | out: | ||
1287 | dm_put(md); | 1292 | dm_put(md); |
1288 | return r; | 1293 | |
1294 | return 0; | ||
1289 | } | 1295 | } |
1290 | 1296 | ||
1291 | /* | 1297 | /* |
@@ -1294,7 +1300,6 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) | |||
1294 | */ | 1300 | */ |
1295 | static int table_status(struct dm_ioctl *param, size_t param_size) | 1301 | static int table_status(struct dm_ioctl *param, size_t param_size) |
1296 | { | 1302 | { |
1297 | int r; | ||
1298 | struct mapped_device *md; | 1303 | struct mapped_device *md; |
1299 | struct dm_table *table; | 1304 | struct dm_table *table; |
1300 | 1305 | ||
@@ -1302,9 +1307,7 @@ static int table_status(struct dm_ioctl *param, size_t param_size) | |||
1302 | if (!md) | 1307 | if (!md) |
1303 | return -ENXIO; | 1308 | return -ENXIO; |
1304 | 1309 | ||
1305 | r = __dev_status(md, param); | 1310 | __dev_status(md, param); |
1306 | if (r) | ||
1307 | goto out; | ||
1308 | 1311 | ||
1309 | table = dm_get_live_or_inactive_table(md, param); | 1312 | table = dm_get_live_or_inactive_table(md, param); |
1310 | if (table) { | 1313 | if (table) { |
@@ -1312,9 +1315,9 @@ static int table_status(struct dm_ioctl *param, size_t param_size) | |||
1312 | dm_table_put(table); | 1315 | dm_table_put(table); |
1313 | } | 1316 | } |
1314 | 1317 | ||
1315 | out: | ||
1316 | dm_put(md); | 1318 | dm_put(md); |
1317 | return r; | 1319 | |
1320 | return 0; | ||
1318 | } | 1321 | } |
1319 | 1322 | ||
1320 | /* | 1323 | /* |
@@ -1333,10 +1336,6 @@ static int target_message(struct dm_ioctl *param, size_t param_size) | |||
1333 | if (!md) | 1336 | if (!md) |
1334 | return -ENXIO; | 1337 | return -ENXIO; |
1335 | 1338 | ||
1336 | r = __dev_status(md, param); | ||
1337 | if (r) | ||
1338 | goto out; | ||
1339 | |||
1340 | if (tmsg < (struct dm_target_msg *) param->data || | 1339 | if (tmsg < (struct dm_target_msg *) param->data || |
1341 | invalid_str(tmsg->message, (void *) param + param_size)) { | 1340 | invalid_str(tmsg->message, (void *) param + param_size)) { |
1342 | DMWARN("Invalid target message parameters."); | 1341 | DMWARN("Invalid target message parameters."); |
@@ -1593,18 +1592,22 @@ static long dm_compat_ctl_ioctl(struct file *file, uint command, ulong u) | |||
1593 | #endif | 1592 | #endif |
1594 | 1593 | ||
1595 | static const struct file_operations _ctl_fops = { | 1594 | static const struct file_operations _ctl_fops = { |
1595 | .open = nonseekable_open, | ||
1596 | .unlocked_ioctl = dm_ctl_ioctl, | 1596 | .unlocked_ioctl = dm_ctl_ioctl, |
1597 | .compat_ioctl = dm_compat_ctl_ioctl, | 1597 | .compat_ioctl = dm_compat_ctl_ioctl, |
1598 | .owner = THIS_MODULE, | 1598 | .owner = THIS_MODULE, |
1599 | }; | 1599 | }; |
1600 | 1600 | ||
1601 | static struct miscdevice _dm_misc = { | 1601 | static struct miscdevice _dm_misc = { |
1602 | .minor = MISC_DYNAMIC_MINOR, | 1602 | .minor = MAPPER_CTRL_MINOR, |
1603 | .name = DM_NAME, | 1603 | .name = DM_NAME, |
1604 | .nodename = "mapper/control", | 1604 | .nodename = DM_DIR "/" DM_CONTROL_NODE, |
1605 | .fops = &_ctl_fops | 1605 | .fops = &_ctl_fops |
1606 | }; | 1606 | }; |
1607 | 1607 | ||
1608 | MODULE_ALIAS_MISCDEV(MAPPER_CTRL_MINOR); | ||
1609 | MODULE_ALIAS("devname:" DM_DIR "/" DM_CONTROL_NODE); | ||
1610 | |||
1608 | /* | 1611 | /* |
1609 | * Create misc character device and link to DM_DIR/control. | 1612 | * Create misc character device and link to DM_DIR/control. |
1610 | */ | 1613 | */ |
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 9200dbf2391a..3921e3bb43c1 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c | |||
@@ -53,6 +53,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | ti->num_flush_requests = 1; | 55 | ti->num_flush_requests = 1; |
56 | ti->num_discard_requests = 1; | ||
56 | ti->private = lc; | 57 | ti->private = lc; |
57 | return 0; | 58 | return 0; |
58 | 59 | ||
@@ -73,7 +74,7 @@ static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector) | |||
73 | { | 74 | { |
74 | struct linear_c *lc = ti->private; | 75 | struct linear_c *lc = ti->private; |
75 | 76 | ||
76 | return lc->start + (bi_sector - ti->begin); | 77 | return lc->start + dm_target_offset(ti, bi_sector); |
77 | } | 78 | } |
78 | 79 | ||
79 | static void linear_map_bio(struct dm_target *ti, struct bio *bio) | 80 | static void linear_map_bio(struct dm_target *ti, struct bio *bio) |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 826bce7343b3..487ecda90ad4 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -706,6 +706,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as, | |||
706 | 706 | ||
707 | if (as->argc < nr_params) { | 707 | if (as->argc < nr_params) { |
708 | ti->error = "not enough path parameters"; | 708 | ti->error = "not enough path parameters"; |
709 | r = -EINVAL; | ||
709 | goto bad; | 710 | goto bad; |
710 | } | 711 | } |
711 | 712 | ||
@@ -892,6 +893,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, | |||
892 | } | 893 | } |
893 | 894 | ||
894 | ti->num_flush_requests = 1; | 895 | ti->num_flush_requests = 1; |
896 | ti->num_discard_requests = 1; | ||
895 | 897 | ||
896 | return 0; | 898 | return 0; |
897 | 899 | ||
@@ -1271,6 +1273,15 @@ static int do_end_io(struct multipath *m, struct request *clone, | |||
1271 | if (error == -EOPNOTSUPP) | 1273 | if (error == -EOPNOTSUPP) |
1272 | return error; | 1274 | return error; |
1273 | 1275 | ||
1276 | if (clone->cmd_flags & REQ_DISCARD) | ||
1277 | /* | ||
1278 | * Pass all discard request failures up. | ||
1279 | * FIXME: only fail_path if the discard failed due to a | ||
1280 | * transport problem. This requires precise understanding | ||
1281 | * of the underlying failure (e.g. the SCSI sense). | ||
1282 | */ | ||
1283 | return error; | ||
1284 | |||
1274 | if (mpio->pgpath) | 1285 | if (mpio->pgpath) |
1275 | fail_path(mpio->pgpath); | 1286 | fail_path(mpio->pgpath); |
1276 | 1287 | ||
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 74136262d654..7c081bcbc3cf 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -445,7 +445,7 @@ static sector_t map_sector(struct mirror *m, struct bio *bio) | |||
445 | { | 445 | { |
446 | if (unlikely(!bio->bi_size)) | 446 | if (unlikely(!bio->bi_size)) |
447 | return 0; | 447 | return 0; |
448 | return m->offset + (bio->bi_sector - m->ms->ti->begin); | 448 | return m->offset + dm_target_offset(m->ms->ti, bio->bi_sector); |
449 | } | 449 | } |
450 | 450 | ||
451 | static void map_bio(struct mirror *m, struct bio *bio) | 451 | static void map_bio(struct mirror *m, struct bio *bio) |
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index c097d8a4823d..cc2bdb83f9ad 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c | |||
@@ -266,7 +266,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, | |||
266 | */ | 266 | */ |
267 | static chunk_t area_location(struct pstore *ps, chunk_t area) | 267 | static chunk_t area_location(struct pstore *ps, chunk_t area) |
268 | { | 268 | { |
269 | return 1 + ((ps->exceptions_per_area + 1) * area); | 269 | return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area); |
270 | } | 270 | } |
271 | 271 | ||
272 | /* | 272 | /* |
@@ -780,8 +780,8 @@ static int persistent_commit_merge(struct dm_exception_store *store, | |||
780 | * ps->current_area does not get reduced by prepare_merge() until | 780 | * ps->current_area does not get reduced by prepare_merge() until |
781 | * after commit_merge() has removed the nr_merged previous exceptions. | 781 | * after commit_merge() has removed the nr_merged previous exceptions. |
782 | */ | 782 | */ |
783 | ps->next_free = (area_location(ps, ps->current_area) - 1) + | 783 | ps->next_free = area_location(ps, ps->current_area) + |
784 | (ps->current_committed + 1) + NUM_SNAPSHOT_HDR_CHUNKS; | 784 | ps->current_committed + 1; |
785 | 785 | ||
786 | return 0; | 786 | return 0; |
787 | } | 787 | } |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 54853773510c..5974d3094d97 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -148,6 +148,12 @@ struct dm_snapshot { | |||
148 | #define RUNNING_MERGE 0 | 148 | #define RUNNING_MERGE 0 |
149 | #define SHUTDOWN_MERGE 1 | 149 | #define SHUTDOWN_MERGE 1 |
150 | 150 | ||
151 | struct dm_dev *dm_snap_origin(struct dm_snapshot *s) | ||
152 | { | ||
153 | return s->origin; | ||
154 | } | ||
155 | EXPORT_SYMBOL(dm_snap_origin); | ||
156 | |||
151 | struct dm_dev *dm_snap_cow(struct dm_snapshot *s) | 157 | struct dm_dev *dm_snap_cow(struct dm_snapshot *s) |
152 | { | 158 | { |
153 | return s->cow; | 159 | return s->cow; |
@@ -1065,10 +1071,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1065 | origin_mode = FMODE_WRITE; | 1071 | origin_mode = FMODE_WRITE; |
1066 | } | 1072 | } |
1067 | 1073 | ||
1068 | origin_path = argv[0]; | ||
1069 | argv++; | ||
1070 | argc--; | ||
1071 | |||
1072 | s = kmalloc(sizeof(*s), GFP_KERNEL); | 1074 | s = kmalloc(sizeof(*s), GFP_KERNEL); |
1073 | if (!s) { | 1075 | if (!s) { |
1074 | ti->error = "Cannot allocate snapshot context private " | 1076 | ti->error = "Cannot allocate snapshot context private " |
@@ -1077,6 +1079,16 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1077 | goto bad; | 1079 | goto bad; |
1078 | } | 1080 | } |
1079 | 1081 | ||
1082 | origin_path = argv[0]; | ||
1083 | argv++; | ||
1084 | argc--; | ||
1085 | |||
1086 | r = dm_get_device(ti, origin_path, origin_mode, &s->origin); | ||
1087 | if (r) { | ||
1088 | ti->error = "Cannot get origin device"; | ||
1089 | goto bad_origin; | ||
1090 | } | ||
1091 | |||
1080 | cow_path = argv[0]; | 1092 | cow_path = argv[0]; |
1081 | argv++; | 1093 | argv++; |
1082 | argc--; | 1094 | argc--; |
@@ -1097,12 +1109,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1097 | argv += args_used; | 1109 | argv += args_used; |
1098 | argc -= args_used; | 1110 | argc -= args_used; |
1099 | 1111 | ||
1100 | r = dm_get_device(ti, origin_path, origin_mode, &s->origin); | ||
1101 | if (r) { | ||
1102 | ti->error = "Cannot get origin device"; | ||
1103 | goto bad_origin; | ||
1104 | } | ||
1105 | |||
1106 | s->ti = ti; | 1112 | s->ti = ti; |
1107 | s->valid = 1; | 1113 | s->valid = 1; |
1108 | s->active = 0; | 1114 | s->active = 0; |
@@ -1212,15 +1218,15 @@ bad_kcopyd: | |||
1212 | dm_exception_table_exit(&s->complete, exception_cache); | 1218 | dm_exception_table_exit(&s->complete, exception_cache); |
1213 | 1219 | ||
1214 | bad_hash_tables: | 1220 | bad_hash_tables: |
1215 | dm_put_device(ti, s->origin); | ||
1216 | |||
1217 | bad_origin: | ||
1218 | dm_exception_store_destroy(s->store); | 1221 | dm_exception_store_destroy(s->store); |
1219 | 1222 | ||
1220 | bad_store: | 1223 | bad_store: |
1221 | dm_put_device(ti, s->cow); | 1224 | dm_put_device(ti, s->cow); |
1222 | 1225 | ||
1223 | bad_cow: | 1226 | bad_cow: |
1227 | dm_put_device(ti, s->origin); | ||
1228 | |||
1229 | bad_origin: | ||
1224 | kfree(s); | 1230 | kfree(s); |
1225 | 1231 | ||
1226 | bad: | 1232 | bad: |
@@ -1314,12 +1320,12 @@ static void snapshot_dtr(struct dm_target *ti) | |||
1314 | 1320 | ||
1315 | mempool_destroy(s->pending_pool); | 1321 | mempool_destroy(s->pending_pool); |
1316 | 1322 | ||
1317 | dm_put_device(ti, s->origin); | ||
1318 | |||
1319 | dm_exception_store_destroy(s->store); | 1323 | dm_exception_store_destroy(s->store); |
1320 | 1324 | ||
1321 | dm_put_device(ti, s->cow); | 1325 | dm_put_device(ti, s->cow); |
1322 | 1326 | ||
1327 | dm_put_device(ti, s->origin); | ||
1328 | |||
1323 | kfree(s); | 1329 | kfree(s); |
1324 | } | 1330 | } |
1325 | 1331 | ||
@@ -1686,7 +1692,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio, | |||
1686 | chunk_t chunk; | 1692 | chunk_t chunk; |
1687 | 1693 | ||
1688 | if (unlikely(bio_empty_barrier(bio))) { | 1694 | if (unlikely(bio_empty_barrier(bio))) { |
1689 | if (!map_context->flush_request) | 1695 | if (!map_context->target_request_nr) |
1690 | bio->bi_bdev = s->origin->bdev; | 1696 | bio->bi_bdev = s->origin->bdev; |
1691 | else | 1697 | else |
1692 | bio->bi_bdev = s->cow->bdev; | 1698 | bio->bi_bdev = s->cow->bdev; |
@@ -1899,8 +1905,14 @@ static int snapshot_iterate_devices(struct dm_target *ti, | |||
1899 | iterate_devices_callout_fn fn, void *data) | 1905 | iterate_devices_callout_fn fn, void *data) |
1900 | { | 1906 | { |
1901 | struct dm_snapshot *snap = ti->private; | 1907 | struct dm_snapshot *snap = ti->private; |
1908 | int r; | ||
1909 | |||
1910 | r = fn(ti, snap->origin, 0, ti->len, data); | ||
1911 | |||
1912 | if (!r) | ||
1913 | r = fn(ti, snap->cow, 0, get_dev_size(snap->cow->bdev), data); | ||
1902 | 1914 | ||
1903 | return fn(ti, snap->origin, 0, ti->len, data); | 1915 | return r; |
1904 | } | 1916 | } |
1905 | 1917 | ||
1906 | 1918 | ||
@@ -2159,6 +2171,21 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, | |||
2159 | return 0; | 2171 | return 0; |
2160 | } | 2172 | } |
2161 | 2173 | ||
2174 | static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | ||
2175 | struct bio_vec *biovec, int max_size) | ||
2176 | { | ||
2177 | struct dm_dev *dev = ti->private; | ||
2178 | struct request_queue *q = bdev_get_queue(dev->bdev); | ||
2179 | |||
2180 | if (!q->merge_bvec_fn) | ||
2181 | return max_size; | ||
2182 | |||
2183 | bvm->bi_bdev = dev->bdev; | ||
2184 | bvm->bi_sector = bvm->bi_sector; | ||
2185 | |||
2186 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | ||
2187 | } | ||
2188 | |||
2162 | static int origin_iterate_devices(struct dm_target *ti, | 2189 | static int origin_iterate_devices(struct dm_target *ti, |
2163 | iterate_devices_callout_fn fn, void *data) | 2190 | iterate_devices_callout_fn fn, void *data) |
2164 | { | 2191 | { |
@@ -2176,6 +2203,7 @@ static struct target_type origin_target = { | |||
2176 | .map = origin_map, | 2203 | .map = origin_map, |
2177 | .resume = origin_resume, | 2204 | .resume = origin_resume, |
2178 | .status = origin_status, | 2205 | .status = origin_status, |
2206 | .merge = origin_merge, | ||
2179 | .iterate_devices = origin_iterate_devices, | 2207 | .iterate_devices = origin_iterate_devices, |
2180 | }; | 2208 | }; |
2181 | 2209 | ||
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index d6e28d732b4d..c297f6da91ea 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -25,6 +25,8 @@ struct stripe { | |||
25 | 25 | ||
26 | struct stripe_c { | 26 | struct stripe_c { |
27 | uint32_t stripes; | 27 | uint32_t stripes; |
28 | int stripes_shift; | ||
29 | sector_t stripes_mask; | ||
28 | 30 | ||
29 | /* The size of this target / num. stripes */ | 31 | /* The size of this target / num. stripes */ |
30 | sector_t stripe_width; | 32 | sector_t stripe_width; |
@@ -162,16 +164,22 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
162 | 164 | ||
163 | /* Set pointer to dm target; used in trigger_event */ | 165 | /* Set pointer to dm target; used in trigger_event */ |
164 | sc->ti = ti; | 166 | sc->ti = ti; |
165 | |||
166 | sc->stripes = stripes; | 167 | sc->stripes = stripes; |
167 | sc->stripe_width = width; | 168 | sc->stripe_width = width; |
169 | |||
170 | if (stripes & (stripes - 1)) | ||
171 | sc->stripes_shift = -1; | ||
172 | else { | ||
173 | sc->stripes_shift = ffs(stripes) - 1; | ||
174 | sc->stripes_mask = ((sector_t) stripes) - 1; | ||
175 | } | ||
176 | |||
168 | ti->split_io = chunk_size; | 177 | ti->split_io = chunk_size; |
169 | ti->num_flush_requests = stripes; | 178 | ti->num_flush_requests = stripes; |
179 | ti->num_discard_requests = stripes; | ||
170 | 180 | ||
181 | sc->chunk_shift = ffs(chunk_size) - 1; | ||
171 | sc->chunk_mask = ((sector_t) chunk_size) - 1; | 182 | sc->chunk_mask = ((sector_t) chunk_size) - 1; |
172 | for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++) | ||
173 | chunk_size >>= 1; | ||
174 | sc->chunk_shift--; | ||
175 | 183 | ||
176 | /* | 184 | /* |
177 | * Get the stripe destinations. | 185 | * Get the stripe destinations. |
@@ -207,26 +215,79 @@ static void stripe_dtr(struct dm_target *ti) | |||
207 | kfree(sc); | 215 | kfree(sc); |
208 | } | 216 | } |
209 | 217 | ||
218 | static void stripe_map_sector(struct stripe_c *sc, sector_t sector, | ||
219 | uint32_t *stripe, sector_t *result) | ||
220 | { | ||
221 | sector_t offset = dm_target_offset(sc->ti, sector); | ||
222 | sector_t chunk = offset >> sc->chunk_shift; | ||
223 | |||
224 | if (sc->stripes_shift < 0) | ||
225 | *stripe = sector_div(chunk, sc->stripes); | ||
226 | else { | ||
227 | *stripe = chunk & sc->stripes_mask; | ||
228 | chunk >>= sc->stripes_shift; | ||
229 | } | ||
230 | |||
231 | *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask); | ||
232 | } | ||
233 | |||
234 | static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, | ||
235 | uint32_t target_stripe, sector_t *result) | ||
236 | { | ||
237 | uint32_t stripe; | ||
238 | |||
239 | stripe_map_sector(sc, sector, &stripe, result); | ||
240 | if (stripe == target_stripe) | ||
241 | return; | ||
242 | *result &= ~sc->chunk_mask; /* round down */ | ||
243 | if (target_stripe < stripe) | ||
244 | *result += sc->chunk_mask + 1; /* next chunk */ | ||
245 | } | ||
246 | |||
247 | static int stripe_map_discard(struct stripe_c *sc, struct bio *bio, | ||
248 | uint32_t target_stripe) | ||
249 | { | ||
250 | sector_t begin, end; | ||
251 | |||
252 | stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin); | ||
253 | stripe_map_range_sector(sc, bio->bi_sector + bio_sectors(bio), | ||
254 | target_stripe, &end); | ||
255 | if (begin < end) { | ||
256 | bio->bi_bdev = sc->stripe[target_stripe].dev->bdev; | ||
257 | bio->bi_sector = begin + sc->stripe[target_stripe].physical_start; | ||
258 | bio->bi_size = to_bytes(end - begin); | ||
259 | return DM_MAPIO_REMAPPED; | ||
260 | } else { | ||
261 | /* The range doesn't map to the target stripe */ | ||
262 | bio_endio(bio, 0); | ||
263 | return DM_MAPIO_SUBMITTED; | ||
264 | } | ||
265 | } | ||
266 | |||
210 | static int stripe_map(struct dm_target *ti, struct bio *bio, | 267 | static int stripe_map(struct dm_target *ti, struct bio *bio, |
211 | union map_info *map_context) | 268 | union map_info *map_context) |
212 | { | 269 | { |
213 | struct stripe_c *sc = (struct stripe_c *) ti->private; | 270 | struct stripe_c *sc = ti->private; |
214 | sector_t offset, chunk; | ||
215 | uint32_t stripe; | 271 | uint32_t stripe; |
272 | unsigned target_request_nr; | ||
216 | 273 | ||
217 | if (unlikely(bio_empty_barrier(bio))) { | 274 | if (unlikely(bio_empty_barrier(bio))) { |
218 | BUG_ON(map_context->flush_request >= sc->stripes); | 275 | target_request_nr = map_context->target_request_nr; |
219 | bio->bi_bdev = sc->stripe[map_context->flush_request].dev->bdev; | 276 | BUG_ON(target_request_nr >= sc->stripes); |
277 | bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; | ||
220 | return DM_MAPIO_REMAPPED; | 278 | return DM_MAPIO_REMAPPED; |
221 | } | 279 | } |
280 | if (unlikely(bio->bi_rw & REQ_DISCARD)) { | ||
281 | target_request_nr = map_context->target_request_nr; | ||
282 | BUG_ON(target_request_nr >= sc->stripes); | ||
283 | return stripe_map_discard(sc, bio, target_request_nr); | ||
284 | } | ||
222 | 285 | ||
223 | offset = bio->bi_sector - ti->begin; | 286 | stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector); |
224 | chunk = offset >> sc->chunk_shift; | ||
225 | stripe = sector_div(chunk, sc->stripes); | ||
226 | 287 | ||
288 | bio->bi_sector += sc->stripe[stripe].physical_start; | ||
227 | bio->bi_bdev = sc->stripe[stripe].dev->bdev; | 289 | bio->bi_bdev = sc->stripe[stripe].dev->bdev; |
228 | bio->bi_sector = sc->stripe[stripe].physical_start + | 290 | |
229 | (chunk << sc->chunk_shift) + (offset & sc->chunk_mask); | ||
230 | return DM_MAPIO_REMAPPED; | 291 | return DM_MAPIO_REMAPPED; |
231 | } | 292 | } |
232 | 293 | ||
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 9924ea23032d..f9fc07d7a4b9 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -54,6 +54,8 @@ struct dm_table { | |||
54 | sector_t *highs; | 54 | sector_t *highs; |
55 | struct dm_target *targets; | 55 | struct dm_target *targets; |
56 | 56 | ||
57 | unsigned discards_supported:1; | ||
58 | |||
57 | /* | 59 | /* |
58 | * Indicates the rw permissions for the new logical | 60 | * Indicates the rw permissions for the new logical |
59 | * device. This should be a combination of FMODE_READ | 61 | * device. This should be a combination of FMODE_READ |
@@ -203,6 +205,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode, | |||
203 | 205 | ||
204 | INIT_LIST_HEAD(&t->devices); | 206 | INIT_LIST_HEAD(&t->devices); |
205 | atomic_set(&t->holders, 0); | 207 | atomic_set(&t->holders, 0); |
208 | t->discards_supported = 1; | ||
206 | 209 | ||
207 | if (!num_targets) | 210 | if (!num_targets) |
208 | num_targets = KEYS_PER_NODE; | 211 | num_targets = KEYS_PER_NODE; |
@@ -245,7 +248,7 @@ void dm_table_destroy(struct dm_table *t) | |||
245 | msleep(1); | 248 | msleep(1); |
246 | smp_mb(); | 249 | smp_mb(); |
247 | 250 | ||
248 | /* free the indexes (see dm_table_complete) */ | 251 | /* free the indexes */ |
249 | if (t->depth >= 2) | 252 | if (t->depth >= 2) |
250 | vfree(t->index[t->depth - 2]); | 253 | vfree(t->index[t->depth - 2]); |
251 | 254 | ||
@@ -770,6 +773,9 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
770 | 773 | ||
771 | t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; | 774 | t->highs[t->num_targets++] = tgt->begin + tgt->len - 1; |
772 | 775 | ||
776 | if (!tgt->num_discard_requests) | ||
777 | t->discards_supported = 0; | ||
778 | |||
773 | return 0; | 779 | return 0; |
774 | 780 | ||
775 | bad: | 781 | bad: |
@@ -778,7 +784,7 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
778 | return r; | 784 | return r; |
779 | } | 785 | } |
780 | 786 | ||
781 | int dm_table_set_type(struct dm_table *t) | 787 | static int dm_table_set_type(struct dm_table *t) |
782 | { | 788 | { |
783 | unsigned i; | 789 | unsigned i; |
784 | unsigned bio_based = 0, request_based = 0; | 790 | unsigned bio_based = 0, request_based = 0; |
@@ -900,7 +906,7 @@ static int setup_indexes(struct dm_table *t) | |||
900 | /* | 906 | /* |
901 | * Builds the btree to index the map. | 907 | * Builds the btree to index the map. |
902 | */ | 908 | */ |
903 | int dm_table_complete(struct dm_table *t) | 909 | static int dm_table_build_index(struct dm_table *t) |
904 | { | 910 | { |
905 | int r = 0; | 911 | int r = 0; |
906 | unsigned int leaf_nodes; | 912 | unsigned int leaf_nodes; |
@@ -919,6 +925,55 @@ int dm_table_complete(struct dm_table *t) | |||
919 | return r; | 925 | return r; |
920 | } | 926 | } |
921 | 927 | ||
928 | /* | ||
929 | * Register the mapped device for blk_integrity support if | ||
930 | * the underlying devices support it. | ||
931 | */ | ||
932 | static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md) | ||
933 | { | ||
934 | struct list_head *devices = dm_table_get_devices(t); | ||
935 | struct dm_dev_internal *dd; | ||
936 | |||
937 | list_for_each_entry(dd, devices, list) | ||
938 | if (bdev_get_integrity(dd->dm_dev.bdev)) | ||
939 | return blk_integrity_register(dm_disk(md), NULL); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * Prepares the table for use by building the indices, | ||
946 | * setting the type, and allocating mempools. | ||
947 | */ | ||
948 | int dm_table_complete(struct dm_table *t) | ||
949 | { | ||
950 | int r; | ||
951 | |||
952 | r = dm_table_set_type(t); | ||
953 | if (r) { | ||
954 | DMERR("unable to set table type"); | ||
955 | return r; | ||
956 | } | ||
957 | |||
958 | r = dm_table_build_index(t); | ||
959 | if (r) { | ||
960 | DMERR("unable to build btrees"); | ||
961 | return r; | ||
962 | } | ||
963 | |||
964 | r = dm_table_prealloc_integrity(t, t->md); | ||
965 | if (r) { | ||
966 | DMERR("could not register integrity profile."); | ||
967 | return r; | ||
968 | } | ||
969 | |||
970 | r = dm_table_alloc_md_mempools(t); | ||
971 | if (r) | ||
972 | DMERR("unable to allocate mempools"); | ||
973 | |||
974 | return r; | ||
975 | } | ||
976 | |||
922 | static DEFINE_MUTEX(_event_lock); | 977 | static DEFINE_MUTEX(_event_lock); |
923 | void dm_table_event_callback(struct dm_table *t, | 978 | void dm_table_event_callback(struct dm_table *t, |
924 | void (*fn)(void *), void *context) | 979 | void (*fn)(void *), void *context) |
@@ -1086,6 +1141,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | |||
1086 | else | 1141 | else |
1087 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); | 1142 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); |
1088 | 1143 | ||
1144 | if (!dm_table_supports_discards(t)) | ||
1145 | queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1146 | else | ||
1147 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); | ||
1148 | |||
1089 | dm_table_set_integrity(t); | 1149 | dm_table_set_integrity(t); |
1090 | 1150 | ||
1091 | /* | 1151 | /* |
@@ -1232,6 +1292,39 @@ struct mapped_device *dm_table_get_md(struct dm_table *t) | |||
1232 | return t->md; | 1292 | return t->md; |
1233 | } | 1293 | } |
1234 | 1294 | ||
1295 | static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev, | ||
1296 | sector_t start, sector_t len, void *data) | ||
1297 | { | ||
1298 | struct request_queue *q = bdev_get_queue(dev->bdev); | ||
1299 | |||
1300 | return q && blk_queue_discard(q); | ||
1301 | } | ||
1302 | |||
1303 | bool dm_table_supports_discards(struct dm_table *t) | ||
1304 | { | ||
1305 | struct dm_target *ti; | ||
1306 | unsigned i = 0; | ||
1307 | |||
1308 | if (!t->discards_supported) | ||
1309 | return 0; | ||
1310 | |||
1311 | /* | ||
1312 | * Ensure that at least one underlying device supports discards. | ||
1313 | * t->devices includes internal dm devices such as mirror logs | ||
1314 | * so we need to use iterate_devices here, which targets | ||
1315 | * supporting discard must provide. | ||
1316 | */ | ||
1317 | while (i < dm_table_get_num_targets(t)) { | ||
1318 | ti = dm_table_get_target(t, i++); | ||
1319 | |||
1320 | if (ti->type->iterate_devices && | ||
1321 | ti->type->iterate_devices(ti, device_discard_capable, NULL)) | ||
1322 | return 1; | ||
1323 | } | ||
1324 | |||
1325 | return 0; | ||
1326 | } | ||
1327 | |||
1235 | EXPORT_SYMBOL(dm_vcalloc); | 1328 | EXPORT_SYMBOL(dm_vcalloc); |
1236 | EXPORT_SYMBOL(dm_get_device); | 1329 | EXPORT_SYMBOL(dm_get_device); |
1237 | EXPORT_SYMBOL(dm_put_device); | 1330 | EXPORT_SYMBOL(dm_put_device); |
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 11dea11dc0b6..8da366cf381c 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c | |||
@@ -113,6 +113,11 @@ void dm_unregister_target(struct target_type *tt) | |||
113 | */ | 113 | */ |
114 | static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args) | 114 | static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args) |
115 | { | 115 | { |
116 | /* | ||
117 | * Return error for discards instead of -EOPNOTSUPP | ||
118 | */ | ||
119 | tt->num_discard_requests = 1; | ||
120 | |||
116 | return 0; | 121 | return 0; |
117 | } | 122 | } |
118 | 123 | ||
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index bbc97030c0c2..cc2b3cb81946 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c | |||
@@ -22,6 +22,11 @@ static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
22 | return -EINVAL; | 22 | return -EINVAL; |
23 | } | 23 | } |
24 | 24 | ||
25 | /* | ||
26 | * Silently drop discards, avoiding -EOPNOTSUPP. | ||
27 | */ | ||
28 | ti->num_discard_requests = 1; | ||
29 | |||
25 | return 0; | 30 | return 0; |
26 | } | 31 | } |
27 | 32 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a3f21dc02bd8..ac384b2a6a33 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/idr.h> | 21 | #include <linux/idr.h> |
22 | #include <linux/hdreg.h> | 22 | #include <linux/hdreg.h> |
23 | #include <linux/delay.h> | ||
23 | 24 | ||
24 | #include <trace/events/block.h> | 25 | #include <trace/events/block.h> |
25 | 26 | ||
@@ -124,6 +125,10 @@ struct mapped_device { | |||
124 | unsigned long flags; | 125 | unsigned long flags; |
125 | 126 | ||
126 | struct request_queue *queue; | 127 | struct request_queue *queue; |
128 | unsigned type; | ||
129 | /* Protect queue and type against concurrent access. */ | ||
130 | struct mutex type_lock; | ||
131 | |||
127 | struct gendisk *disk; | 132 | struct gendisk *disk; |
128 | char name[16]; | 133 | char name[16]; |
129 | 134 | ||
@@ -638,8 +643,14 @@ static void dec_pending(struct dm_io *io, int error) | |||
638 | * There can be just one barrier request so we use | 643 | * There can be just one barrier request so we use |
639 | * a per-device variable for error reporting. | 644 | * a per-device variable for error reporting. |
640 | * Note that you can't touch the bio after end_io_acct | 645 | * Note that you can't touch the bio after end_io_acct |
646 | * | ||
647 | * We ignore -EOPNOTSUPP for empty flush reported by | ||
648 | * underlying devices. We assume that if the device | ||
649 | * doesn't support empty barriers, it doesn't need | ||
650 | * cache flushing commands. | ||
641 | */ | 651 | */ |
642 | if (!md->barrier_error && io_error != -EOPNOTSUPP) | 652 | if (!md->barrier_error && |
653 | !(bio_empty_barrier(bio) && io_error == -EOPNOTSUPP)) | ||
643 | md->barrier_error = io_error; | 654 | md->barrier_error = io_error; |
644 | end_io_acct(io); | 655 | end_io_acct(io); |
645 | free_io(md, io); | 656 | free_io(md, io); |
@@ -1019,17 +1030,27 @@ static void end_clone_request(struct request *clone, int error) | |||
1019 | dm_complete_request(clone, error); | 1030 | dm_complete_request(clone, error); |
1020 | } | 1031 | } |
1021 | 1032 | ||
1022 | static sector_t max_io_len(struct mapped_device *md, | 1033 | /* |
1023 | sector_t sector, struct dm_target *ti) | 1034 | * Return maximum size of I/O possible at the supplied sector up to the current |
1035 | * target boundary. | ||
1036 | */ | ||
1037 | static sector_t max_io_len_target_boundary(sector_t sector, struct dm_target *ti) | ||
1038 | { | ||
1039 | sector_t target_offset = dm_target_offset(ti, sector); | ||
1040 | |||
1041 | return ti->len - target_offset; | ||
1042 | } | ||
1043 | |||
1044 | static sector_t max_io_len(sector_t sector, struct dm_target *ti) | ||
1024 | { | 1045 | { |
1025 | sector_t offset = sector - ti->begin; | 1046 | sector_t len = max_io_len_target_boundary(sector, ti); |
1026 | sector_t len = ti->len - offset; | ||
1027 | 1047 | ||
1028 | /* | 1048 | /* |
1029 | * Does the target need to split even further ? | 1049 | * Does the target need to split even further ? |
1030 | */ | 1050 | */ |
1031 | if (ti->split_io) { | 1051 | if (ti->split_io) { |
1032 | sector_t boundary; | 1052 | sector_t boundary; |
1053 | sector_t offset = dm_target_offset(ti, sector); | ||
1033 | boundary = ((offset + ti->split_io) & ~(ti->split_io - 1)) | 1054 | boundary = ((offset + ti->split_io) & ~(ti->split_io - 1)) |
1034 | - offset; | 1055 | - offset; |
1035 | if (len > boundary) | 1056 | if (len > boundary) |
@@ -1171,36 +1192,96 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci, | |||
1171 | return tio; | 1192 | return tio; |
1172 | } | 1193 | } |
1173 | 1194 | ||
1174 | static void __flush_target(struct clone_info *ci, struct dm_target *ti, | 1195 | static void __issue_target_request(struct clone_info *ci, struct dm_target *ti, |
1175 | unsigned flush_nr) | 1196 | unsigned request_nr, sector_t len) |
1176 | { | 1197 | { |
1177 | struct dm_target_io *tio = alloc_tio(ci, ti); | 1198 | struct dm_target_io *tio = alloc_tio(ci, ti); |
1178 | struct bio *clone; | 1199 | struct bio *clone; |
1179 | 1200 | ||
1180 | tio->info.flush_request = flush_nr; | 1201 | tio->info.target_request_nr = request_nr; |
1181 | 1202 | ||
1182 | clone = bio_alloc_bioset(GFP_NOIO, 0, ci->md->bs); | 1203 | /* |
1204 | * Discard requests require the bio's inline iovecs be initialized. | ||
1205 | * ci->bio->bi_max_vecs is BIO_INLINE_VECS anyway, for both flush | ||
1206 | * and discard, so no need for concern about wasted bvec allocations. | ||
1207 | */ | ||
1208 | clone = bio_alloc_bioset(GFP_NOIO, ci->bio->bi_max_vecs, ci->md->bs); | ||
1183 | __bio_clone(clone, ci->bio); | 1209 | __bio_clone(clone, ci->bio); |
1184 | clone->bi_destructor = dm_bio_destructor; | 1210 | clone->bi_destructor = dm_bio_destructor; |
1211 | if (len) { | ||
1212 | clone->bi_sector = ci->sector; | ||
1213 | clone->bi_size = to_bytes(len); | ||
1214 | } | ||
1185 | 1215 | ||
1186 | __map_bio(ti, clone, tio); | 1216 | __map_bio(ti, clone, tio); |
1187 | } | 1217 | } |
1188 | 1218 | ||
1219 | static void __issue_target_requests(struct clone_info *ci, struct dm_target *ti, | ||
1220 | unsigned num_requests, sector_t len) | ||
1221 | { | ||
1222 | unsigned request_nr; | ||
1223 | |||
1224 | for (request_nr = 0; request_nr < num_requests; request_nr++) | ||
1225 | __issue_target_request(ci, ti, request_nr, len); | ||
1226 | } | ||
1227 | |||
1189 | static int __clone_and_map_empty_barrier(struct clone_info *ci) | 1228 | static int __clone_and_map_empty_barrier(struct clone_info *ci) |
1190 | { | 1229 | { |
1191 | unsigned target_nr = 0, flush_nr; | 1230 | unsigned target_nr = 0; |
1192 | struct dm_target *ti; | 1231 | struct dm_target *ti; |
1193 | 1232 | ||
1194 | while ((ti = dm_table_get_target(ci->map, target_nr++))) | 1233 | while ((ti = dm_table_get_target(ci->map, target_nr++))) |
1195 | for (flush_nr = 0; flush_nr < ti->num_flush_requests; | 1234 | __issue_target_requests(ci, ti, ti->num_flush_requests, 0); |
1196 | flush_nr++) | ||
1197 | __flush_target(ci, ti, flush_nr); | ||
1198 | 1235 | ||
1199 | ci->sector_count = 0; | 1236 | ci->sector_count = 0; |
1200 | 1237 | ||
1201 | return 0; | 1238 | return 0; |
1202 | } | 1239 | } |
1203 | 1240 | ||
1241 | /* | ||
1242 | * Perform all io with a single clone. | ||
1243 | */ | ||
1244 | static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti) | ||
1245 | { | ||
1246 | struct bio *clone, *bio = ci->bio; | ||
1247 | struct dm_target_io *tio; | ||
1248 | |||
1249 | tio = alloc_tio(ci, ti); | ||
1250 | clone = clone_bio(bio, ci->sector, ci->idx, | ||
1251 | bio->bi_vcnt - ci->idx, ci->sector_count, | ||
1252 | ci->md->bs); | ||
1253 | __map_bio(ti, clone, tio); | ||
1254 | ci->sector_count = 0; | ||
1255 | } | ||
1256 | |||
1257 | static int __clone_and_map_discard(struct clone_info *ci) | ||
1258 | { | ||
1259 | struct dm_target *ti; | ||
1260 | sector_t len; | ||
1261 | |||
1262 | do { | ||
1263 | ti = dm_table_find_target(ci->map, ci->sector); | ||
1264 | if (!dm_target_is_valid(ti)) | ||
1265 | return -EIO; | ||
1266 | |||
1267 | /* | ||
1268 | * Even though the device advertised discard support, | ||
1269 | * reconfiguration might have changed that since the | ||
1270 | * check was performed. | ||
1271 | */ | ||
1272 | if (!ti->num_discard_requests) | ||
1273 | return -EOPNOTSUPP; | ||
1274 | |||
1275 | len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); | ||
1276 | |||
1277 | __issue_target_requests(ci, ti, ti->num_discard_requests, len); | ||
1278 | |||
1279 | ci->sector += len; | ||
1280 | } while (ci->sector_count -= len); | ||
1281 | |||
1282 | return 0; | ||
1283 | } | ||
1284 | |||
1204 | static int __clone_and_map(struct clone_info *ci) | 1285 | static int __clone_and_map(struct clone_info *ci) |
1205 | { | 1286 | { |
1206 | struct bio *clone, *bio = ci->bio; | 1287 | struct bio *clone, *bio = ci->bio; |
@@ -1211,27 +1292,21 @@ static int __clone_and_map(struct clone_info *ci) | |||
1211 | if (unlikely(bio_empty_barrier(bio))) | 1292 | if (unlikely(bio_empty_barrier(bio))) |
1212 | return __clone_and_map_empty_barrier(ci); | 1293 | return __clone_and_map_empty_barrier(ci); |
1213 | 1294 | ||
1295 | if (unlikely(bio->bi_rw & REQ_DISCARD)) | ||
1296 | return __clone_and_map_discard(ci); | ||
1297 | |||
1214 | ti = dm_table_find_target(ci->map, ci->sector); | 1298 | ti = dm_table_find_target(ci->map, ci->sector); |
1215 | if (!dm_target_is_valid(ti)) | 1299 | if (!dm_target_is_valid(ti)) |
1216 | return -EIO; | 1300 | return -EIO; |
1217 | 1301 | ||
1218 | max = max_io_len(ci->md, ci->sector, ti); | 1302 | max = max_io_len(ci->sector, ti); |
1219 | |||
1220 | /* | ||
1221 | * Allocate a target io object. | ||
1222 | */ | ||
1223 | tio = alloc_tio(ci, ti); | ||
1224 | 1303 | ||
1225 | if (ci->sector_count <= max) { | 1304 | if (ci->sector_count <= max) { |
1226 | /* | 1305 | /* |
1227 | * Optimise for the simple case where we can do all of | 1306 | * Optimise for the simple case where we can do all of |
1228 | * the remaining io with a single clone. | 1307 | * the remaining io with a single clone. |
1229 | */ | 1308 | */ |
1230 | clone = clone_bio(bio, ci->sector, ci->idx, | 1309 | __clone_and_map_simple(ci, ti); |
1231 | bio->bi_vcnt - ci->idx, ci->sector_count, | ||
1232 | ci->md->bs); | ||
1233 | __map_bio(ti, clone, tio); | ||
1234 | ci->sector_count = 0; | ||
1235 | 1310 | ||
1236 | } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { | 1311 | } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { |
1237 | /* | 1312 | /* |
@@ -1252,6 +1327,7 @@ static int __clone_and_map(struct clone_info *ci) | |||
1252 | len += bv_len; | 1327 | len += bv_len; |
1253 | } | 1328 | } |
1254 | 1329 | ||
1330 | tio = alloc_tio(ci, ti); | ||
1255 | clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len, | 1331 | clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len, |
1256 | ci->md->bs); | 1332 | ci->md->bs); |
1257 | __map_bio(ti, clone, tio); | 1333 | __map_bio(ti, clone, tio); |
@@ -1274,13 +1350,12 @@ static int __clone_and_map(struct clone_info *ci) | |||
1274 | if (!dm_target_is_valid(ti)) | 1350 | if (!dm_target_is_valid(ti)) |
1275 | return -EIO; | 1351 | return -EIO; |
1276 | 1352 | ||
1277 | max = max_io_len(ci->md, ci->sector, ti); | 1353 | max = max_io_len(ci->sector, ti); |
1278 | |||
1279 | tio = alloc_tio(ci, ti); | ||
1280 | } | 1354 | } |
1281 | 1355 | ||
1282 | len = min(remaining, max); | 1356 | len = min(remaining, max); |
1283 | 1357 | ||
1358 | tio = alloc_tio(ci, ti); | ||
1284 | clone = split_bvec(bio, ci->sector, ci->idx, | 1359 | clone = split_bvec(bio, ci->sector, ci->idx, |
1285 | bv->bv_offset + offset, len, | 1360 | bv->bv_offset + offset, len, |
1286 | ci->md->bs); | 1361 | ci->md->bs); |
@@ -1362,7 +1437,7 @@ static int dm_merge_bvec(struct request_queue *q, | |||
1362 | /* | 1437 | /* |
1363 | * Find maximum amount of I/O that won't need splitting | 1438 | * Find maximum amount of I/O that won't need splitting |
1364 | */ | 1439 | */ |
1365 | max_sectors = min(max_io_len(md, bvm->bi_sector, ti), | 1440 | max_sectors = min(max_io_len(bvm->bi_sector, ti), |
1366 | (sector_t) BIO_MAX_SECTORS); | 1441 | (sector_t) BIO_MAX_SECTORS); |
1367 | max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size; | 1442 | max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size; |
1368 | if (max_size < 0) | 1443 | if (max_size < 0) |
@@ -1845,6 +1920,28 @@ static const struct block_device_operations dm_blk_dops; | |||
1845 | static void dm_wq_work(struct work_struct *work); | 1920 | static void dm_wq_work(struct work_struct *work); |
1846 | static void dm_rq_barrier_work(struct work_struct *work); | 1921 | static void dm_rq_barrier_work(struct work_struct *work); |
1847 | 1922 | ||
1923 | static void dm_init_md_queue(struct mapped_device *md) | ||
1924 | { | ||
1925 | /* | ||
1926 | * Request-based dm devices cannot be stacked on top of bio-based dm | ||
1927 | * devices. The type of this dm device has not been decided yet. | ||
1928 | * The type is decided at the first table loading time. | ||
1929 | * To prevent problematic device stacking, clear the queue flag | ||
1930 | * for request stacking support until then. | ||
1931 | * | ||
1932 | * This queue is new, so no concurrency on the queue_flags. | ||
1933 | */ | ||
1934 | queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue); | ||
1935 | |||
1936 | md->queue->queuedata = md; | ||
1937 | md->queue->backing_dev_info.congested_fn = dm_any_congested; | ||
1938 | md->queue->backing_dev_info.congested_data = md; | ||
1939 | blk_queue_make_request(md->queue, dm_request); | ||
1940 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); | ||
1941 | md->queue->unplug_fn = dm_unplug_all; | ||
1942 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); | ||
1943 | } | ||
1944 | |||
1848 | /* | 1945 | /* |
1849 | * Allocate and initialise a blank device with a given minor. | 1946 | * Allocate and initialise a blank device with a given minor. |
1850 | */ | 1947 | */ |
@@ -1870,8 +1967,10 @@ static struct mapped_device *alloc_dev(int minor) | |||
1870 | if (r < 0) | 1967 | if (r < 0) |
1871 | goto bad_minor; | 1968 | goto bad_minor; |
1872 | 1969 | ||
1970 | md->type = DM_TYPE_NONE; | ||
1873 | init_rwsem(&md->io_lock); | 1971 | init_rwsem(&md->io_lock); |
1874 | mutex_init(&md->suspend_lock); | 1972 | mutex_init(&md->suspend_lock); |
1973 | mutex_init(&md->type_lock); | ||
1875 | spin_lock_init(&md->deferred_lock); | 1974 | spin_lock_init(&md->deferred_lock); |
1876 | spin_lock_init(&md->barrier_error_lock); | 1975 | spin_lock_init(&md->barrier_error_lock); |
1877 | rwlock_init(&md->map_lock); | 1976 | rwlock_init(&md->map_lock); |
@@ -1882,33 +1981,11 @@ static struct mapped_device *alloc_dev(int minor) | |||
1882 | INIT_LIST_HEAD(&md->uevent_list); | 1981 | INIT_LIST_HEAD(&md->uevent_list); |
1883 | spin_lock_init(&md->uevent_lock); | 1982 | spin_lock_init(&md->uevent_lock); |
1884 | 1983 | ||
1885 | md->queue = blk_init_queue(dm_request_fn, NULL); | 1984 | md->queue = blk_alloc_queue(GFP_KERNEL); |
1886 | if (!md->queue) | 1985 | if (!md->queue) |
1887 | goto bad_queue; | 1986 | goto bad_queue; |
1888 | 1987 | ||
1889 | /* | 1988 | dm_init_md_queue(md); |
1890 | * Request-based dm devices cannot be stacked on top of bio-based dm | ||
1891 | * devices. The type of this dm device has not been decided yet, | ||
1892 | * although we initialized the queue using blk_init_queue(). | ||
1893 | * The type is decided at the first table loading time. | ||
1894 | * To prevent problematic device stacking, clear the queue flag | ||
1895 | * for request stacking support until then. | ||
1896 | * | ||
1897 | * This queue is new, so no concurrency on the queue_flags. | ||
1898 | */ | ||
1899 | queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue); | ||
1900 | md->saved_make_request_fn = md->queue->make_request_fn; | ||
1901 | md->queue->queuedata = md; | ||
1902 | md->queue->backing_dev_info.congested_fn = dm_any_congested; | ||
1903 | md->queue->backing_dev_info.congested_data = md; | ||
1904 | blk_queue_make_request(md->queue, dm_request); | ||
1905 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); | ||
1906 | md->queue->unplug_fn = dm_unplug_all; | ||
1907 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); | ||
1908 | blk_queue_softirq_done(md->queue, dm_softirq_done); | ||
1909 | blk_queue_prep_rq(md->queue, dm_prep_fn); | ||
1910 | blk_queue_lld_busy(md->queue, dm_lld_busy); | ||
1911 | blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH); | ||
1912 | 1989 | ||
1913 | md->disk = alloc_disk(1); | 1990 | md->disk = alloc_disk(1); |
1914 | if (!md->disk) | 1991 | if (!md->disk) |
@@ -2123,6 +2200,72 @@ int dm_create(int minor, struct mapped_device **result) | |||
2123 | return 0; | 2200 | return 0; |
2124 | } | 2201 | } |
2125 | 2202 | ||
2203 | /* | ||
2204 | * Functions to manage md->type. | ||
2205 | * All are required to hold md->type_lock. | ||
2206 | */ | ||
2207 | void dm_lock_md_type(struct mapped_device *md) | ||
2208 | { | ||
2209 | mutex_lock(&md->type_lock); | ||
2210 | } | ||
2211 | |||
2212 | void dm_unlock_md_type(struct mapped_device *md) | ||
2213 | { | ||
2214 | mutex_unlock(&md->type_lock); | ||
2215 | } | ||
2216 | |||
2217 | void dm_set_md_type(struct mapped_device *md, unsigned type) | ||
2218 | { | ||
2219 | md->type = type; | ||
2220 | } | ||
2221 | |||
2222 | unsigned dm_get_md_type(struct mapped_device *md) | ||
2223 | { | ||
2224 | return md->type; | ||
2225 | } | ||
2226 | |||
2227 | /* | ||
2228 | * Fully initialize a request-based queue (->elevator, ->request_fn, etc). | ||
2229 | */ | ||
2230 | static int dm_init_request_based_queue(struct mapped_device *md) | ||
2231 | { | ||
2232 | struct request_queue *q = NULL; | ||
2233 | |||
2234 | if (md->queue->elevator) | ||
2235 | return 1; | ||
2236 | |||
2237 | /* Fully initialize the queue */ | ||
2238 | q = blk_init_allocated_queue(md->queue, dm_request_fn, NULL); | ||
2239 | if (!q) | ||
2240 | return 0; | ||
2241 | |||
2242 | md->queue = q; | ||
2243 | md->saved_make_request_fn = md->queue->make_request_fn; | ||
2244 | dm_init_md_queue(md); | ||
2245 | blk_queue_softirq_done(md->queue, dm_softirq_done); | ||
2246 | blk_queue_prep_rq(md->queue, dm_prep_fn); | ||
2247 | blk_queue_lld_busy(md->queue, dm_lld_busy); | ||
2248 | blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH); | ||
2249 | |||
2250 | elv_register_queue(md->queue); | ||
2251 | |||
2252 | return 1; | ||
2253 | } | ||
2254 | |||
2255 | /* | ||
2256 | * Setup the DM device's queue based on md's type | ||
2257 | */ | ||
2258 | int dm_setup_md_queue(struct mapped_device *md) | ||
2259 | { | ||
2260 | if ((dm_get_md_type(md) == DM_TYPE_REQUEST_BASED) && | ||
2261 | !dm_init_request_based_queue(md)) { | ||
2262 | DMWARN("Cannot initialize queue for request-based mapped device"); | ||
2263 | return -EINVAL; | ||
2264 | } | ||
2265 | |||
2266 | return 0; | ||
2267 | } | ||
2268 | |||
2126 | static struct mapped_device *dm_find_md(dev_t dev) | 2269 | static struct mapped_device *dm_find_md(dev_t dev) |
2127 | { | 2270 | { |
2128 | struct mapped_device *md; | 2271 | struct mapped_device *md; |
@@ -2136,6 +2279,7 @@ static struct mapped_device *dm_find_md(dev_t dev) | |||
2136 | md = idr_find(&_minor_idr, minor); | 2279 | md = idr_find(&_minor_idr, minor); |
2137 | if (md && (md == MINOR_ALLOCED || | 2280 | if (md && (md == MINOR_ALLOCED || |
2138 | (MINOR(disk_devt(dm_disk(md))) != minor) || | 2281 | (MINOR(disk_devt(dm_disk(md))) != minor) || |
2282 | dm_deleting_md(md) || | ||
2139 | test_bit(DMF_FREEING, &md->flags))) { | 2283 | test_bit(DMF_FREEING, &md->flags))) { |
2140 | md = NULL; | 2284 | md = NULL; |
2141 | goto out; | 2285 | goto out; |
@@ -2170,6 +2314,7 @@ void dm_set_mdptr(struct mapped_device *md, void *ptr) | |||
2170 | void dm_get(struct mapped_device *md) | 2314 | void dm_get(struct mapped_device *md) |
2171 | { | 2315 | { |
2172 | atomic_inc(&md->holders); | 2316 | atomic_inc(&md->holders); |
2317 | BUG_ON(test_bit(DMF_FREEING, &md->flags)); | ||
2173 | } | 2318 | } |
2174 | 2319 | ||
2175 | const char *dm_device_name(struct mapped_device *md) | 2320 | const char *dm_device_name(struct mapped_device *md) |
@@ -2178,27 +2323,55 @@ const char *dm_device_name(struct mapped_device *md) | |||
2178 | } | 2323 | } |
2179 | EXPORT_SYMBOL_GPL(dm_device_name); | 2324 | EXPORT_SYMBOL_GPL(dm_device_name); |
2180 | 2325 | ||
2181 | void dm_put(struct mapped_device *md) | 2326 | static void __dm_destroy(struct mapped_device *md, bool wait) |
2182 | { | 2327 | { |
2183 | struct dm_table *map; | 2328 | struct dm_table *map; |
2184 | 2329 | ||
2185 | BUG_ON(test_bit(DMF_FREEING, &md->flags)); | 2330 | might_sleep(); |
2186 | 2331 | ||
2187 | if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { | 2332 | spin_lock(&_minor_lock); |
2188 | map = dm_get_live_table(md); | 2333 | map = dm_get_live_table(md); |
2189 | idr_replace(&_minor_idr, MINOR_ALLOCED, | 2334 | idr_replace(&_minor_idr, MINOR_ALLOCED, MINOR(disk_devt(dm_disk(md)))); |
2190 | MINOR(disk_devt(dm_disk(md)))); | 2335 | set_bit(DMF_FREEING, &md->flags); |
2191 | set_bit(DMF_FREEING, &md->flags); | 2336 | spin_unlock(&_minor_lock); |
2192 | spin_unlock(&_minor_lock); | 2337 | |
2193 | if (!dm_suspended_md(md)) { | 2338 | if (!dm_suspended_md(md)) { |
2194 | dm_table_presuspend_targets(map); | 2339 | dm_table_presuspend_targets(map); |
2195 | dm_table_postsuspend_targets(map); | 2340 | dm_table_postsuspend_targets(map); |
2196 | } | ||
2197 | dm_sysfs_exit(md); | ||
2198 | dm_table_put(map); | ||
2199 | dm_table_destroy(__unbind(md)); | ||
2200 | free_dev(md); | ||
2201 | } | 2341 | } |
2342 | |||
2343 | /* | ||
2344 | * Rare, but there may be I/O requests still going to complete, | ||
2345 | * for example. Wait for all references to disappear. | ||
2346 | * No one should increment the reference count of the mapped_device, | ||
2347 | * after the mapped_device state becomes DMF_FREEING. | ||
2348 | */ | ||
2349 | if (wait) | ||
2350 | while (atomic_read(&md->holders)) | ||
2351 | msleep(1); | ||
2352 | else if (atomic_read(&md->holders)) | ||
2353 | DMWARN("%s: Forcibly removing mapped_device still in use! (%d users)", | ||
2354 | dm_device_name(md), atomic_read(&md->holders)); | ||
2355 | |||
2356 | dm_sysfs_exit(md); | ||
2357 | dm_table_put(map); | ||
2358 | dm_table_destroy(__unbind(md)); | ||
2359 | free_dev(md); | ||
2360 | } | ||
2361 | |||
2362 | void dm_destroy(struct mapped_device *md) | ||
2363 | { | ||
2364 | __dm_destroy(md, true); | ||
2365 | } | ||
2366 | |||
2367 | void dm_destroy_immediate(struct mapped_device *md) | ||
2368 | { | ||
2369 | __dm_destroy(md, false); | ||
2370 | } | ||
2371 | |||
2372 | void dm_put(struct mapped_device *md) | ||
2373 | { | ||
2374 | atomic_dec(&md->holders); | ||
2202 | } | 2375 | } |
2203 | EXPORT_SYMBOL_GPL(dm_put); | 2376 | EXPORT_SYMBOL_GPL(dm_put); |
2204 | 2377 | ||
@@ -2253,7 +2426,12 @@ static void process_barrier(struct mapped_device *md, struct bio *bio) | |||
2253 | 2426 | ||
2254 | if (!bio_empty_barrier(bio)) { | 2427 | if (!bio_empty_barrier(bio)) { |
2255 | __split_and_process_bio(md, bio); | 2428 | __split_and_process_bio(md, bio); |
2256 | dm_flush(md); | 2429 | /* |
2430 | * If the request isn't supported, don't waste time with | ||
2431 | * the second flush. | ||
2432 | */ | ||
2433 | if (md->barrier_error != -EOPNOTSUPP) | ||
2434 | dm_flush(md); | ||
2257 | } | 2435 | } |
2258 | 2436 | ||
2259 | if (md->barrier_error != DM_ENDIO_REQUEUE) | 2437 | if (md->barrier_error != DM_ENDIO_REQUEUE) |
@@ -2310,11 +2488,11 @@ static void dm_queue_flush(struct mapped_device *md) | |||
2310 | queue_work(md->wq, &md->work); | 2488 | queue_work(md->wq, &md->work); |
2311 | } | 2489 | } |
2312 | 2490 | ||
2313 | static void dm_rq_set_flush_nr(struct request *clone, unsigned flush_nr) | 2491 | static void dm_rq_set_target_request_nr(struct request *clone, unsigned request_nr) |
2314 | { | 2492 | { |
2315 | struct dm_rq_target_io *tio = clone->end_io_data; | 2493 | struct dm_rq_target_io *tio = clone->end_io_data; |
2316 | 2494 | ||
2317 | tio->info.flush_request = flush_nr; | 2495 | tio->info.target_request_nr = request_nr; |
2318 | } | 2496 | } |
2319 | 2497 | ||
2320 | /* Issue barrier requests to targets and wait for their completion. */ | 2498 | /* Issue barrier requests to targets and wait for their completion. */ |
@@ -2332,7 +2510,7 @@ static int dm_rq_barrier(struct mapped_device *md) | |||
2332 | ti = dm_table_get_target(map, i); | 2510 | ti = dm_table_get_target(map, i); |
2333 | for (j = 0; j < ti->num_flush_requests; j++) { | 2511 | for (j = 0; j < ti->num_flush_requests; j++) { |
2334 | clone = clone_rq(md->flush_request, md, GFP_NOIO); | 2512 | clone = clone_rq(md->flush_request, md, GFP_NOIO); |
2335 | dm_rq_set_flush_nr(clone, j); | 2513 | dm_rq_set_target_request_nr(clone, j); |
2336 | atomic_inc(&md->pending[rq_data_dir(clone)]); | 2514 | atomic_inc(&md->pending[rq_data_dir(clone)]); |
2337 | map_request(ti, clone, md); | 2515 | map_request(ti, clone, md); |
2338 | } | 2516 | } |
@@ -2398,13 +2576,6 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) | |||
2398 | goto out; | 2576 | goto out; |
2399 | } | 2577 | } |
2400 | 2578 | ||
2401 | /* cannot change the device type, once a table is bound */ | ||
2402 | if (md->map && | ||
2403 | (dm_table_get_type(md->map) != dm_table_get_type(table))) { | ||
2404 | DMWARN("can't change the device type after a table is bound"); | ||
2405 | goto out; | ||
2406 | } | ||
2407 | |||
2408 | map = __bind(md, table, &limits); | 2579 | map = __bind(md, table, &limits); |
2409 | 2580 | ||
2410 | out: | 2581 | out: |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index bad1724d4869..0c2dd5f4af76 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
@@ -59,13 +59,20 @@ void dm_table_postsuspend_targets(struct dm_table *t); | |||
59 | int dm_table_resume_targets(struct dm_table *t); | 59 | int dm_table_resume_targets(struct dm_table *t); |
60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); | 60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); |
61 | int dm_table_any_busy_target(struct dm_table *t); | 61 | int dm_table_any_busy_target(struct dm_table *t); |
62 | int dm_table_set_type(struct dm_table *t); | ||
63 | unsigned dm_table_get_type(struct dm_table *t); | 62 | unsigned dm_table_get_type(struct dm_table *t); |
64 | bool dm_table_request_based(struct dm_table *t); | 63 | bool dm_table_request_based(struct dm_table *t); |
64 | bool dm_table_supports_discards(struct dm_table *t); | ||
65 | int dm_table_alloc_md_mempools(struct dm_table *t); | 65 | int dm_table_alloc_md_mempools(struct dm_table *t); |
66 | void dm_table_free_md_mempools(struct dm_table *t); | 66 | void dm_table_free_md_mempools(struct dm_table *t); |
67 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); | 67 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); |
68 | 68 | ||
69 | void dm_lock_md_type(struct mapped_device *md); | ||
70 | void dm_unlock_md_type(struct mapped_device *md); | ||
71 | void dm_set_md_type(struct mapped_device *md, unsigned type); | ||
72 | unsigned dm_get_md_type(struct mapped_device *md); | ||
73 | |||
74 | int dm_setup_md_queue(struct mapped_device *md); | ||
75 | |||
69 | /* | 76 | /* |
70 | * To check the return value from dm_table_find_target(). | 77 | * To check the return value from dm_table_find_target(). |
71 | */ | 78 | */ |
@@ -122,6 +129,11 @@ void dm_linear_exit(void); | |||
122 | int dm_stripe_init(void); | 129 | int dm_stripe_init(void); |
123 | void dm_stripe_exit(void); | 130 | void dm_stripe_exit(void); |
124 | 131 | ||
132 | /* | ||
133 | * mapped_device operations | ||
134 | */ | ||
135 | void dm_destroy(struct mapped_device *md); | ||
136 | void dm_destroy_immediate(struct mapped_device *md); | ||
125 | int dm_open_count(struct mapped_device *md); | 137 | int dm_open_count(struct mapped_device *md); |
126 | int dm_lock_for_deletion(struct mapped_device *md); | 138 | int dm_lock_for_deletion(struct mapped_device *md); |
127 | 139 | ||
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 30e04915a256..490c57cc4cfe 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig | |||
@@ -2,14 +2,21 @@ menuconfig IR_CORE | |||
2 | tristate "Infrared remote controller adapters" | 2 | tristate "Infrared remote controller adapters" |
3 | depends on INPUT | 3 | depends on INPUT |
4 | default INPUT | 4 | default INPUT |
5 | ---help--- | ||
6 | Enable support for Remote Controllers on Linux. This is | ||
7 | needed in order to support several video capture adapters. | ||
5 | 8 | ||
6 | if IR_CORE | 9 | Enable this option if you have a video capture board even |
10 | if you don't need IR, as otherwise, you may not be able to | ||
11 | compile the driver for your adapter. | ||
7 | 12 | ||
8 | config VIDEO_IR | 13 | config VIDEO_IR |
9 | tristate | 14 | tristate |
10 | depends on IR_CORE | 15 | depends on IR_CORE |
11 | default IR_CORE | 16 | default IR_CORE |
12 | 17 | ||
18 | if IR_CORE | ||
19 | |||
13 | config LIRC | 20 | config LIRC |
14 | tristate | 21 | tristate |
15 | default y | 22 | default y |
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index 695239227cb7..a6ceb08f1183 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig | |||
@@ -9,7 +9,7 @@ config DVB_DM1105 | |||
9 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | 9 | select DVB_CX24116 if !DVB_FE_CUSTOMISE |
10 | select DVB_SI21XX if !DVB_FE_CUSTOMISE | 10 | select DVB_SI21XX if !DVB_FE_CUSTOMISE |
11 | select DVB_DS3000 if !DVB_FE_CUSTOMISE | 11 | select DVB_DS3000 if !DVB_FE_CUSTOMISE |
12 | select VIDEO_IR | 12 | depends on VIDEO_IR |
13 | help | 13 | help |
14 | Support for cards based on the SDMC DM1105 PCI chip like | 14 | Support for cards based on the SDMC DM1105 PCI chip like |
15 | DvbWorld 2002 | 15 | DvbWorld 2002 |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 553b48ac1919..fdc19bba2128 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config DVB_USB | 1 | config DVB_USB |
2 | tristate "Support for various USB DVB devices" | 2 | tristate "Support for various USB DVB devices" |
3 | depends on DVB_CORE && USB && I2C && INPUT | 3 | depends on DVB_CORE && USB && I2C && IR_CORE |
4 | help | 4 | help |
5 | By enabling this you will be able to choose the various supported | 5 | By enabling this you will be able to choose the various supported |
6 | USB1.1 and USB2.0 DVB devices. | 6 | USB1.1 and USB2.0 DVB devices. |
diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig index 85a222c4eaa0..e520bceee0af 100644 --- a/drivers/media/dvb/siano/Kconfig +++ b/drivers/media/dvb/siano/Kconfig | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | config SMS_SIANO_MDTV | 5 | config SMS_SIANO_MDTV |
6 | tristate "Siano SMS1xxx based MDTV receiver" | 6 | tristate "Siano SMS1xxx based MDTV receiver" |
7 | depends on DVB_CORE && INPUT && HAS_DMA | 7 | depends on DVB_CORE && IR_CORE && HAS_DMA |
8 | ---help--- | 8 | ---help--- |
9 | Choose Y or M here if you have MDTV receiver with a Siano chipset. | 9 | Choose Y or M here if you have MDTV receiver with a Siano chipset. |
10 | 10 | ||
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 32a7ec65ec42..debea8d1d31c 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
@@ -98,7 +98,7 @@ config DVB_BUDGET_CI | |||
98 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 98 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
99 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | 99 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE |
100 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE | 100 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE |
101 | select VIDEO_IR | 101 | depends on VIDEO_IR |
102 | help | 102 | help |
103 | Support for simple SAA7146 based DVB cards | 103 | Support for simple SAA7146 based DVB cards |
104 | (so called Budget- or Nova-PCI cards) without onboard | 104 | (so called Budget- or Nova-PCI cards) without onboard |
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 3077c45015f5..1a4a89fdf767 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig | |||
@@ -4,7 +4,7 @@ config VIDEO_BT848 | |||
4 | select I2C_ALGOBIT | 4 | select I2C_ALGOBIT |
5 | select VIDEO_BTCX | 5 | select VIDEO_BTCX |
6 | select VIDEOBUF_DMA_SG | 6 | select VIDEOBUF_DMA_SG |
7 | select VIDEO_IR | 7 | depends on VIDEO_IR |
8 | select VIDEO_TUNER | 8 | select VIDEO_TUNER |
9 | select VIDEO_TVEEPROM | 9 | select VIDEO_TVEEPROM |
10 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO | 10 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO |
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index 407fa61e4cda..685d6597ee79 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c | |||
@@ -411,7 +411,7 @@ void __devinit init_bttv_i2c_ir(struct bttv *btv) | |||
411 | 411 | ||
412 | memset(&info, 0, sizeof(struct i2c_board_info)); | 412 | memset(&info, 0, sizeof(struct i2c_board_info)); |
413 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 413 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
414 | i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list); | 414 | i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL); |
415 | } | 415 | } |
416 | } | 416 | } |
417 | 417 | ||
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index baf7e91ee0f5..76c054d1eef9 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
@@ -3,7 +3,7 @@ config VIDEO_CX18 | |||
3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL | 3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL |
4 | depends on INPUT # due to VIDEO_IR | 4 | depends on INPUT # due to VIDEO_IR |
5 | select I2C_ALGOBIT | 5 | select I2C_ALGOBIT |
6 | select VIDEO_IR | 6 | depends on VIDEO_IR |
7 | select VIDEO_TUNER | 7 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 8 | select VIDEO_TVEEPROM |
9 | select VIDEO_CX2341X | 9 | select VIDEO_CX2341X |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 809f7d37129c..73ce90c2f577 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -117,7 +117,8 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, | |||
117 | break; | 117 | break; |
118 | } | 118 | } |
119 | 119 | ||
120 | return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; | 120 | return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? |
121 | -1 : 0; | ||
121 | } | 122 | } |
122 | 123 | ||
123 | int cx18_i2c_register(struct cx18 *cx, unsigned idx) | 124 | int cx18_i2c_register(struct cx18 *cx, unsigned idx) |
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index 477d4ab5e9ac..5ac7eceececa 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig | |||
@@ -3,7 +3,7 @@ config VIDEO_CX231XX | |||
3 | depends on VIDEO_DEV && I2C && INPUT | 3 | depends on VIDEO_DEV && I2C && INPUT |
4 | select VIDEO_TUNER | 4 | select VIDEO_TUNER |
5 | select VIDEO_TVEEPROM | 5 | select VIDEO_TVEEPROM |
6 | select VIDEO_IR | 6 | depends on VIDEO_IR |
7 | select VIDEOBUF_VMALLOC | 7 | select VIDEOBUF_VMALLOC |
8 | select VIDEO_CX25840 | 8 | select VIDEO_CX25840 |
9 | 9 | ||
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 768f000e4b21..e1367b35647a 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig | |||
@@ -5,7 +5,7 @@ config VIDEO_CX23885 | |||
5 | select VIDEO_BTCX | 5 | select VIDEO_BTCX |
6 | select VIDEO_TUNER | 6 | select VIDEO_TUNER |
7 | select VIDEO_TVEEPROM | 7 | select VIDEO_TVEEPROM |
8 | select IR_CORE | 8 | depends on IR_CORE |
9 | select VIDEOBUF_DVB | 9 | select VIDEOBUF_DVB |
10 | select VIDEOBUF_DMA_SG | 10 | select VIDEOBUF_DMA_SG |
11 | select VIDEO_CX25840 | 11 | select VIDEO_CX25840 |
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 1a391486e551..ed3d8f55029b 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c | |||
@@ -364,17 +364,10 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) | |||
364 | 364 | ||
365 | memset(&info, 0, sizeof(struct i2c_board_info)); | 365 | memset(&info, 0, sizeof(struct i2c_board_info)); |
366 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 366 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
367 | /* | 367 | /* Use quick read command for probe, some IR chips don't |
368 | * We can't call i2c_new_probed_device() because it uses | 368 | * support writes */ |
369 | * quick writes for probing and the IR receiver device only | 369 | i2c_new_probed_device(&bus->i2c_adap, &info, addr_list, |
370 | * replies to reads. | 370 | i2c_probe_func_quick_read); |
371 | */ | ||
372 | if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0, | ||
373 | I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK, | ||
374 | NULL) >= 0) { | ||
375 | info.addr = addr_list[0]; | ||
376 | i2c_new_device(&bus->i2c_adap, &info); | ||
377 | } | ||
378 | } | 371 | } |
379 | 372 | ||
380 | return bus->i2c_rc; | 373 | return bus->i2c_rc; |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index c7e5851d3486..99dbae117591 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -6,7 +6,7 @@ config VIDEO_CX88 | |||
6 | select VIDEOBUF_DMA_SG | 6 | select VIDEOBUF_DMA_SG |
7 | select VIDEO_TUNER | 7 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 8 | select VIDEO_TVEEPROM |
9 | select VIDEO_IR | 9 | depends on VIDEO_IR |
10 | select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO | 10 | select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO |
11 | ---help--- | 11 | ---help--- |
12 | This is a video4linux driver for Conexant 2388x based | 12 | This is a video4linux driver for Conexant 2388x based |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 375ad53f7961..82db555b22dd 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -193,24 +193,13 @@ void cx88_i2c_init_ir(struct cx88_core *core) | |||
193 | 0x18, 0x6b, 0x71, | 193 | 0x18, 0x6b, 0x71, |
194 | I2C_CLIENT_END | 194 | I2C_CLIENT_END |
195 | }; | 195 | }; |
196 | const unsigned short *addrp; | ||
197 | 196 | ||
198 | memset(&info, 0, sizeof(struct i2c_board_info)); | 197 | memset(&info, 0, sizeof(struct i2c_board_info)); |
199 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 198 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
200 | /* | 199 | /* Use quick read command for probe, some IR chips don't |
201 | * We can't call i2c_new_probed_device() because it uses | 200 | * support writes */ |
202 | * quick writes for probing and at least some R receiver | 201 | i2c_new_probed_device(&core->i2c_adap, &info, addr_list, |
203 | * devices only reply to reads. | 202 | i2c_probe_func_quick_read); |
204 | */ | ||
205 | for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) { | ||
206 | if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0, | ||
207 | I2C_SMBUS_READ, 0, | ||
208 | I2C_SMBUS_QUICK, NULL) >= 0) { | ||
209 | info.addr = *addrp; | ||
210 | i2c_new_device(&core->i2c_adap, &info); | ||
211 | break; | ||
212 | } | ||
213 | } | ||
214 | } | 203 | } |
215 | } | 204 | } |
216 | 205 | ||
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index c7be0e097828..66aefd6eef55 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig | |||
@@ -3,7 +3,7 @@ config VIDEO_EM28XX | |||
3 | depends on VIDEO_DEV && I2C && INPUT | 3 | depends on VIDEO_DEV && I2C && INPUT |
4 | select VIDEO_TUNER | 4 | select VIDEO_TUNER |
5 | select VIDEO_TVEEPROM | 5 | select VIDEO_TVEEPROM |
6 | select VIDEO_IR | 6 | depends on VIDEO_IR |
7 | select VIDEOBUF_VMALLOC | 7 | select VIDEOBUF_VMALLOC |
8 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | 8 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO |
9 | select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO | 9 | select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ffbe544e30f4..e7efb4bffabd 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -2385,7 +2385,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2385 | 2385 | ||
2386 | if (dev->init_data.name) | 2386 | if (dev->init_data.name) |
2387 | info.platform_data = &dev->init_data; | 2387 | info.platform_data = &dev->init_data; |
2388 | i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); | 2388 | i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL); |
2389 | } | 2389 | } |
2390 | 2390 | ||
2391 | void em28xx_card_setup(struct em28xx *dev) | 2391 | void em28xx_card_setup(struct em28xx *dev) |
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 8f1c94f7e00c..43d208f1f586 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c | |||
@@ -1418,7 +1418,7 @@ static struct video_device viu_template = { | |||
1418 | .current_norm = V4L2_STD_NTSC_M, | 1418 | .current_norm = V4L2_STD_NTSC_M, |
1419 | }; | 1419 | }; |
1420 | 1420 | ||
1421 | static int __devinit viu_of_probe(struct of_device *op, | 1421 | static int __devinit viu_of_probe(struct platform_device *op, |
1422 | const struct of_device_id *match) | 1422 | const struct of_device_id *match) |
1423 | { | 1423 | { |
1424 | struct viu_dev *viu_dev; | 1424 | struct viu_dev *viu_dev; |
@@ -1549,7 +1549,7 @@ err: | |||
1549 | return ret; | 1549 | return ret; |
1550 | } | 1550 | } |
1551 | 1551 | ||
1552 | static int __devexit viu_of_remove(struct of_device *op) | 1552 | static int __devexit viu_of_remove(struct platform_device *op) |
1553 | { | 1553 | { |
1554 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | 1554 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); |
1555 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | 1555 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); |
@@ -1570,7 +1570,7 @@ static int __devexit viu_of_remove(struct of_device *op) | |||
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | #ifdef CONFIG_PM | 1572 | #ifdef CONFIG_PM |
1573 | static int viu_suspend(struct of_device *op, pm_message_t state) | 1573 | static int viu_suspend(struct platform_device *op, pm_message_t state) |
1574 | { | 1574 | { |
1575 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | 1575 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); |
1576 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | 1576 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); |
@@ -1579,7 +1579,7 @@ static int viu_suspend(struct of_device *op, pm_message_t state) | |||
1579 | return 0; | 1579 | return 0; |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | static int viu_resume(struct of_device *op) | 1582 | static int viu_resume(struct platform_device *op) |
1583 | { | 1583 | { |
1584 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | 1584 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); |
1585 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | 1585 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); |
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index c46bfb1569e3..be4af1fa557e 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig | |||
@@ -3,7 +3,7 @@ config VIDEO_IVTV | |||
3 | depends on VIDEO_V4L2 && PCI && I2C | 3 | depends on VIDEO_V4L2 && PCI && I2C |
4 | depends on INPUT # due to VIDEO_IR | 4 | depends on INPUT # due to VIDEO_IR |
5 | select I2C_ALGOBIT | 5 | select I2C_ALGOBIT |
6 | select VIDEO_IR | 6 | depends on VIDEO_IR |
7 | select VIDEO_TUNER | 7 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 8 | select VIDEO_TVEEPROM |
9 | select VIDEO_CX2341X | 9 | select VIDEO_CX2341X |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index d391bbdb0b8a..a74fa099c565 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -183,8 +183,8 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) | |||
183 | return -1; | 183 | return -1; |
184 | memset(&info, 0, sizeof(struct i2c_board_info)); | 184 | memset(&info, 0, sizeof(struct i2c_board_info)); |
185 | strlcpy(info.type, type, I2C_NAME_SIZE); | 185 | strlcpy(info.type, type, I2C_NAME_SIZE); |
186 | return i2c_new_probed_device(adap, &info, addr_list) == NULL | 186 | return i2c_new_probed_device(adap, &info, addr_list, NULL) |
187 | ? -1 : 0; | 187 | == NULL ? -1 : 0; |
188 | } | 188 | } |
189 | 189 | ||
190 | /* Only allow one IR receiver to be registered per board */ | 190 | /* Only allow one IR receiver to be registered per board */ |
@@ -221,7 +221,8 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) | |||
221 | info.platform_data = init_data; | 221 | info.platform_data = init_data; |
222 | strlcpy(info.type, type, I2C_NAME_SIZE); | 222 | strlcpy(info.type, type, I2C_NAME_SIZE); |
223 | 223 | ||
224 | return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; | 224 | return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? |
225 | -1 : 0; | ||
225 | } | 226 | } |
226 | 227 | ||
227 | /* Instantiate the IR receiver device using probing -- undesirable */ | 228 | /* Instantiate the IR receiver device using probing -- undesirable */ |
@@ -249,7 +250,7 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) | |||
249 | 250 | ||
250 | memset(&info, 0, sizeof(struct i2c_board_info)); | 251 | memset(&info, 0, sizeof(struct i2c_board_info)); |
251 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 252 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
252 | return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); | 253 | return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL); |
253 | } | 254 | } |
254 | 255 | ||
255 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) | 256 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) |
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 22bfd62c9551..fda005e01670 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig | |||
@@ -2,7 +2,7 @@ config VIDEO_SAA7134 | |||
2 | tristate "Philips SAA7134 support" | 2 | tristate "Philips SAA7134 support" |
3 | depends on VIDEO_DEV && PCI && I2C && INPUT | 3 | depends on VIDEO_DEV && PCI && I2C && INPUT |
4 | select VIDEOBUF_DMA_SG | 4 | select VIDEOBUF_DMA_SG |
5 | select VIDEO_IR | 5 | depends on VIDEO_IR |
6 | select VIDEO_TUNER | 6 | select VIDEO_TUNER |
7 | select VIDEO_TVEEPROM | 7 | select VIDEO_TVEEPROM |
8 | select CRC32 | 8 | select CRC32 |
diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig index 2c29ec659b4e..1686ebfa6951 100644 --- a/drivers/media/video/tlg2300/Kconfig +++ b/drivers/media/video/tlg2300/Kconfig | |||
@@ -3,7 +3,7 @@ config VIDEO_TLG2300 | |||
3 | depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE | 3 | depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE |
4 | select VIDEO_TUNER | 4 | select VIDEO_TUNER |
5 | select VIDEO_TVEEPROM | 5 | select VIDEO_TVEEPROM |
6 | select VIDEO_IR | 6 | depends on VIDEO_IR |
7 | select VIDEOBUF_VMALLOC | 7 | select VIDEOBUF_VMALLOC |
8 | select SND_PCM | 8 | select SND_PCM |
9 | select VIDEOBUF_DVB | 9 | select VIDEOBUF_DVB |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 3ce7c64e5789..8ee1179be926 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -381,7 +381,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, | |||
381 | 381 | ||
382 | /* Create the i2c client */ | 382 | /* Create the i2c client */ |
383 | if (info->addr == 0 && probe_addrs) | 383 | if (info->addr == 0 && probe_addrs) |
384 | client = i2c_new_probed_device(adapter, info, probe_addrs); | 384 | client = i2c_new_probed_device(adapter, info, probe_addrs, |
385 | NULL); | ||
385 | else | 386 | else |
386 | client = i2c_new_device(adapter, info); | 387 | client = i2c_new_device(adapter, info); |
387 | 388 | ||
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 84c1a53a727a..ea8d32cd425d 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
22 | #include <linux/slab.h> | ||
22 | #include <media/v4l2-ioctl.h> | 23 | #include <media/v4l2-ioctl.h> |
23 | #include <media/v4l2-device.h> | 24 | #include <media/v4l2-device.h> |
24 | #include <media/v4l2-ctrls.h> | 25 | #include <media/v4l2-ctrls.h> |
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index eef78a068fd1..d3f1a087eced 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
@@ -1048,6 +1048,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) | |||
1048 | snprintf(s_attr->name, sizeof(s_attr->name), | 1048 | snprintf(s_attr->name, sizeof(s_attr->name), |
1049 | "attr_x%02x", attr->entries[cnt].id); | 1049 | "attr_x%02x", attr->entries[cnt].id); |
1050 | 1050 | ||
1051 | sysfs_attr_init(&s_attr->dev_attr.attr); | ||
1051 | s_attr->dev_attr.attr.name = s_attr->name; | 1052 | s_attr->dev_attr.attr.name = s_attr->name; |
1052 | s_attr->dev_attr.attr.mode = S_IRUGO; | 1053 | s_attr->dev_attr.attr.mode = S_IRUGO; |
1053 | s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); | 1054 | s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); |
@@ -1338,13 +1339,14 @@ static void mspro_block_remove(struct memstick_dev *card) | |||
1338 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 1339 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
1339 | unsigned long flags; | 1340 | unsigned long flags; |
1340 | 1341 | ||
1341 | del_gendisk(msb->disk); | ||
1342 | dev_dbg(&card->dev, "mspro block remove\n"); | ||
1343 | spin_lock_irqsave(&msb->q_lock, flags); | 1342 | spin_lock_irqsave(&msb->q_lock, flags); |
1344 | msb->eject = 1; | 1343 | msb->eject = 1; |
1345 | blk_start_queue(msb->queue); | 1344 | blk_start_queue(msb->queue); |
1346 | spin_unlock_irqrestore(&msb->q_lock, flags); | 1345 | spin_unlock_irqrestore(&msb->q_lock, flags); |
1347 | 1346 | ||
1347 | del_gendisk(msb->disk); | ||
1348 | dev_dbg(&card->dev, "mspro block remove\n"); | ||
1349 | |||
1348 | blk_cleanup_queue(msb->queue); | 1350 | blk_cleanup_queue(msb->queue); |
1349 | msb->queue = NULL; | 1351 | msb->queue = NULL; |
1350 | 1352 | ||
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index b88a244a1edd..b8f1719d7c02 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/module.h> | 50 | #include <linux/module.h> |
51 | #include <linux/errno.h> | 51 | #include <linux/errno.h> |
52 | #include <linux/init.h> | 52 | #include <linux/init.h> |
53 | #include <linux/seq_file.h> | ||
53 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
54 | #include <linux/types.h> | 55 | #include <linux/types.h> |
55 | #include <linux/pci.h> | 56 | #include <linux/pci.h> |
@@ -109,8 +110,7 @@ MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \ | |||
109 | 110 | ||
110 | int mpt_fwfault_debug; | 111 | int mpt_fwfault_debug; |
111 | EXPORT_SYMBOL(mpt_fwfault_debug); | 112 | EXPORT_SYMBOL(mpt_fwfault_debug); |
112 | module_param_call(mpt_fwfault_debug, param_set_int, param_get_int, | 113 | module_param(mpt_fwfault_debug, int, 0600); |
113 | &mpt_fwfault_debug, 0600); | ||
114 | MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" | 114 | MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault" |
115 | " and halt Firmware on fault - (default=0)"); | 115 | " and halt Firmware on fault - (default=0)"); |
116 | 116 | ||
@@ -200,12 +200,9 @@ static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_valu | |||
200 | static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); | 200 | static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); |
201 | 201 | ||
202 | #ifdef CONFIG_PROC_FS | 202 | #ifdef CONFIG_PROC_FS |
203 | static int procmpt_summary_read(char *buf, char **start, off_t offset, | 203 | static const struct file_operations mpt_summary_proc_fops; |
204 | int request, int *eof, void *data); | 204 | static const struct file_operations mpt_version_proc_fops; |
205 | static int procmpt_version_read(char *buf, char **start, off_t offset, | 205 | static const struct file_operations mpt_iocinfo_proc_fops; |
206 | int request, int *eof, void *data); | ||
207 | static int procmpt_iocinfo_read(char *buf, char **start, off_t offset, | ||
208 | int request, int *eof, void *data); | ||
209 | #endif | 206 | #endif |
210 | static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); | 207 | static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); |
211 | 208 | ||
@@ -1725,7 +1722,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1725 | u8 pcixcmd; | 1722 | u8 pcixcmd; |
1726 | static int mpt_ids = 0; | 1723 | static int mpt_ids = 0; |
1727 | #ifdef CONFIG_PROC_FS | 1724 | #ifdef CONFIG_PROC_FS |
1728 | struct proc_dir_entry *dent, *ent; | 1725 | struct proc_dir_entry *dent; |
1729 | #endif | 1726 | #endif |
1730 | 1727 | ||
1731 | ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); | 1728 | ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); |
@@ -1980,16 +1977,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1980 | */ | 1977 | */ |
1981 | dent = proc_mkdir(ioc->name, mpt_proc_root_dir); | 1978 | dent = proc_mkdir(ioc->name, mpt_proc_root_dir); |
1982 | if (dent) { | 1979 | if (dent) { |
1983 | ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent); | 1980 | proc_create_data("info", S_IRUGO, dent, &mpt_iocinfo_proc_fops, ioc); |
1984 | if (ent) { | 1981 | proc_create_data("summary", S_IRUGO, dent, &mpt_summary_proc_fops, ioc); |
1985 | ent->read_proc = procmpt_iocinfo_read; | ||
1986 | ent->data = ioc; | ||
1987 | } | ||
1988 | ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent); | ||
1989 | if (ent) { | ||
1990 | ent->read_proc = procmpt_summary_read; | ||
1991 | ent->data = ioc; | ||
1992 | } | ||
1993 | } | 1982 | } |
1994 | #endif | 1983 | #endif |
1995 | 1984 | ||
@@ -6546,20 +6535,12 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
6546 | static int | 6535 | static int |
6547 | procmpt_create(void) | 6536 | procmpt_create(void) |
6548 | { | 6537 | { |
6549 | struct proc_dir_entry *ent; | ||
6550 | |||
6551 | mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL); | 6538 | mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL); |
6552 | if (mpt_proc_root_dir == NULL) | 6539 | if (mpt_proc_root_dir == NULL) |
6553 | return -ENOTDIR; | 6540 | return -ENOTDIR; |
6554 | 6541 | ||
6555 | ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir); | 6542 | proc_create("summary", S_IRUGO, mpt_proc_root_dir, &mpt_summary_proc_fops); |
6556 | if (ent) | 6543 | proc_create("version", S_IRUGO, mpt_proc_root_dir, &mpt_version_proc_fops); |
6557 | ent->read_proc = procmpt_summary_read; | ||
6558 | |||
6559 | ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir); | ||
6560 | if (ent) | ||
6561 | ent->read_proc = procmpt_version_read; | ||
6562 | |||
6563 | return 0; | 6544 | return 0; |
6564 | } | 6545 | } |
6565 | 6546 | ||
@@ -6579,70 +6560,46 @@ procmpt_destroy(void) | |||
6579 | 6560 | ||
6580 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6561 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
6581 | /** | 6562 | /** |
6582 | * procmpt_summary_read - Handle read request of a summary file | ||
6583 | * @buf: Pointer to area to write information | ||
6584 | * @start: Pointer to start pointer | ||
6585 | * @offset: Offset to start writing | ||
6586 | * @request: Amount of read data requested | ||
6587 | * @eof: Pointer to EOF integer | ||
6588 | * @data: Pointer | ||
6589 | * | ||
6590 | * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. | 6563 | * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. |
6591 | * Returns number of characters written to process performing the read. | ||
6592 | */ | 6564 | */ |
6593 | static int | 6565 | static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan); |
6594 | procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) | ||
6595 | { | ||
6596 | MPT_ADAPTER *ioc; | ||
6597 | char *out = buf; | ||
6598 | int len; | ||
6599 | 6566 | ||
6600 | if (data) { | 6567 | static int mpt_summary_proc_show(struct seq_file *m, void *v) |
6601 | int more = 0; | 6568 | { |
6602 | 6569 | MPT_ADAPTER *ioc = m->private; | |
6603 | ioc = data; | ||
6604 | mpt_print_ioc_summary(ioc, out, &more, 0, 1); | ||
6605 | 6570 | ||
6606 | out += more; | 6571 | if (ioc) { |
6572 | seq_mpt_print_ioc_summary(ioc, m, 1); | ||
6607 | } else { | 6573 | } else { |
6608 | list_for_each_entry(ioc, &ioc_list, list) { | 6574 | list_for_each_entry(ioc, &ioc_list, list) { |
6609 | int more = 0; | 6575 | seq_mpt_print_ioc_summary(ioc, m, 1); |
6610 | |||
6611 | mpt_print_ioc_summary(ioc, out, &more, 0, 1); | ||
6612 | |||
6613 | out += more; | ||
6614 | if ((out-buf) >= request) | ||
6615 | break; | ||
6616 | } | 6576 | } |
6617 | } | 6577 | } |
6618 | 6578 | ||
6619 | len = out - buf; | 6579 | return 0; |
6580 | } | ||
6620 | 6581 | ||
6621 | MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); | 6582 | static int mpt_summary_proc_open(struct inode *inode, struct file *file) |
6583 | { | ||
6584 | return single_open(file, mpt_summary_proc_show, PDE(inode)->data); | ||
6622 | } | 6585 | } |
6623 | 6586 | ||
6624 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6587 | static const struct file_operations mpt_summary_proc_fops = { |
6625 | /** | 6588 | .owner = THIS_MODULE, |
6626 | * procmpt_version_read - Handle read request from /proc/mpt/version. | 6589 | .open = mpt_summary_proc_open, |
6627 | * @buf: Pointer to area to write information | 6590 | .read = seq_read, |
6628 | * @start: Pointer to start pointer | 6591 | .llseek = seq_lseek, |
6629 | * @offset: Offset to start writing | 6592 | .release = single_release, |
6630 | * @request: Amount of read data requested | 6593 | }; |
6631 | * @eof: Pointer to EOF integer | 6594 | |
6632 | * @data: Pointer | 6595 | static int mpt_version_proc_show(struct seq_file *m, void *v) |
6633 | * | ||
6634 | * Returns number of characters written to process performing the read. | ||
6635 | */ | ||
6636 | static int | ||
6637 | procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) | ||
6638 | { | 6596 | { |
6639 | u8 cb_idx; | 6597 | u8 cb_idx; |
6640 | int scsi, fc, sas, lan, ctl, targ, dmp; | 6598 | int scsi, fc, sas, lan, ctl, targ, dmp; |
6641 | char *drvname; | 6599 | char *drvname; |
6642 | int len; | ||
6643 | 6600 | ||
6644 | len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON); | 6601 | seq_printf(m, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON); |
6645 | len += sprintf(buf+len, " Fusion MPT base driver\n"); | 6602 | seq_printf(m, " Fusion MPT base driver\n"); |
6646 | 6603 | ||
6647 | scsi = fc = sas = lan = ctl = targ = dmp = 0; | 6604 | scsi = fc = sas = lan = ctl = targ = dmp = 0; |
6648 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { | 6605 | for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { |
@@ -6670,98 +6627,97 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo | |||
6670 | } | 6627 | } |
6671 | 6628 | ||
6672 | if (drvname) | 6629 | if (drvname) |
6673 | len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname); | 6630 | seq_printf(m, " Fusion MPT %s driver\n", drvname); |
6674 | } | 6631 | } |
6675 | } | 6632 | } |
6676 | 6633 | ||
6677 | MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); | 6634 | return 0; |
6678 | } | 6635 | } |
6679 | 6636 | ||
6680 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6637 | static int mpt_version_proc_open(struct inode *inode, struct file *file) |
6681 | /** | 6638 | { |
6682 | * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info. | 6639 | return single_open(file, mpt_version_proc_show, NULL); |
6683 | * @buf: Pointer to area to write information | 6640 | } |
6684 | * @start: Pointer to start pointer | 6641 | |
6685 | * @offset: Offset to start writing | 6642 | static const struct file_operations mpt_version_proc_fops = { |
6686 | * @request: Amount of read data requested | 6643 | .owner = THIS_MODULE, |
6687 | * @eof: Pointer to EOF integer | 6644 | .open = mpt_version_proc_open, |
6688 | * @data: Pointer | 6645 | .read = seq_read, |
6689 | * | 6646 | .llseek = seq_lseek, |
6690 | * Returns number of characters written to process performing the read. | 6647 | .release = single_release, |
6691 | */ | 6648 | }; |
6692 | static int | 6649 | |
6693 | procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) | 6650 | static int mpt_iocinfo_proc_show(struct seq_file *m, void *v) |
6694 | { | 6651 | { |
6695 | MPT_ADAPTER *ioc = data; | 6652 | MPT_ADAPTER *ioc = m->private; |
6696 | int len; | ||
6697 | char expVer[32]; | 6653 | char expVer[32]; |
6698 | int sz; | 6654 | int sz; |
6699 | int p; | 6655 | int p; |
6700 | 6656 | ||
6701 | mpt_get_fw_exp_ver(expVer, ioc); | 6657 | mpt_get_fw_exp_ver(expVer, ioc); |
6702 | 6658 | ||
6703 | len = sprintf(buf, "%s:", ioc->name); | 6659 | seq_printf(m, "%s:", ioc->name); |
6704 | if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) | 6660 | if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) |
6705 | len += sprintf(buf+len, " (f/w download boot flag set)"); | 6661 | seq_printf(m, " (f/w download boot flag set)"); |
6706 | // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL) | 6662 | // if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL) |
6707 | // len += sprintf(buf+len, " CONFIG_CHECKSUM_FAIL!"); | 6663 | // seq_printf(m, " CONFIG_CHECKSUM_FAIL!"); |
6708 | 6664 | ||
6709 | len += sprintf(buf+len, "\n ProductID = 0x%04x (%s)\n", | 6665 | seq_printf(m, "\n ProductID = 0x%04x (%s)\n", |
6710 | ioc->facts.ProductID, | 6666 | ioc->facts.ProductID, |
6711 | ioc->prod_name); | 6667 | ioc->prod_name); |
6712 | len += sprintf(buf+len, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer); | 6668 | seq_printf(m, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer); |
6713 | if (ioc->facts.FWImageSize) | 6669 | if (ioc->facts.FWImageSize) |
6714 | len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize); | 6670 | seq_printf(m, " (fw_size=%d)", ioc->facts.FWImageSize); |
6715 | len += sprintf(buf+len, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion); | 6671 | seq_printf(m, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion); |
6716 | len += sprintf(buf+len, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit); | 6672 | seq_printf(m, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit); |
6717 | len += sprintf(buf+len, " EventState = 0x%02x\n", ioc->facts.EventState); | 6673 | seq_printf(m, " EventState = 0x%02x\n", ioc->facts.EventState); |
6718 | 6674 | ||
6719 | len += sprintf(buf+len, " CurrentHostMfaHighAddr = 0x%08x\n", | 6675 | seq_printf(m, " CurrentHostMfaHighAddr = 0x%08x\n", |
6720 | ioc->facts.CurrentHostMfaHighAddr); | 6676 | ioc->facts.CurrentHostMfaHighAddr); |
6721 | len += sprintf(buf+len, " CurrentSenseBufferHighAddr = 0x%08x\n", | 6677 | seq_printf(m, " CurrentSenseBufferHighAddr = 0x%08x\n", |
6722 | ioc->facts.CurrentSenseBufferHighAddr); | 6678 | ioc->facts.CurrentSenseBufferHighAddr); |
6723 | 6679 | ||
6724 | len += sprintf(buf+len, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); | 6680 | seq_printf(m, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); |
6725 | len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); | 6681 | seq_printf(m, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); |
6726 | 6682 | ||
6727 | len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", | 6683 | seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", |
6728 | (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma); | 6684 | (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma); |
6729 | /* | 6685 | /* |
6730 | * Rounding UP to nearest 4-kB boundary here... | 6686 | * Rounding UP to nearest 4-kB boundary here... |
6731 | */ | 6687 | */ |
6732 | sz = (ioc->req_sz * ioc->req_depth) + 128; | 6688 | sz = (ioc->req_sz * ioc->req_depth) + 128; |
6733 | sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; | 6689 | sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; |
6734 | len += sprintf(buf+len, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n", | 6690 | seq_printf(m, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n", |
6735 | ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz); | 6691 | ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz); |
6736 | len += sprintf(buf+len, " {MaxReqSz=%d} {MaxReqDepth=%d}\n", | 6692 | seq_printf(m, " {MaxReqSz=%d} {MaxReqDepth=%d}\n", |
6737 | 4*ioc->facts.RequestFrameSize, | 6693 | 4*ioc->facts.RequestFrameSize, |
6738 | ioc->facts.GlobalCredits); | 6694 | ioc->facts.GlobalCredits); |
6739 | 6695 | ||
6740 | len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n", | 6696 | seq_printf(m, " Frames @ 0x%p (Dma @ 0x%p)\n", |
6741 | (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma); | 6697 | (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma); |
6742 | sz = (ioc->reply_sz * ioc->reply_depth) + 128; | 6698 | sz = (ioc->reply_sz * ioc->reply_depth) + 128; |
6743 | len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", | 6699 | seq_printf(m, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", |
6744 | ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); | 6700 | ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); |
6745 | len += sprintf(buf+len, " {MaxRepSz=%d} {MaxRepDepth=%d}\n", | 6701 | seq_printf(m, " {MaxRepSz=%d} {MaxRepDepth=%d}\n", |
6746 | ioc->facts.CurReplyFrameSize, | 6702 | ioc->facts.CurReplyFrameSize, |
6747 | ioc->facts.ReplyQueueDepth); | 6703 | ioc->facts.ReplyQueueDepth); |
6748 | 6704 | ||
6749 | len += sprintf(buf+len, " MaxDevices = %d\n", | 6705 | seq_printf(m, " MaxDevices = %d\n", |
6750 | (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices); | 6706 | (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices); |
6751 | len += sprintf(buf+len, " MaxBuses = %d\n", ioc->facts.MaxBuses); | 6707 | seq_printf(m, " MaxBuses = %d\n", ioc->facts.MaxBuses); |
6752 | 6708 | ||
6753 | /* per-port info */ | 6709 | /* per-port info */ |
6754 | for (p=0; p < ioc->facts.NumberOfPorts; p++) { | 6710 | for (p=0; p < ioc->facts.NumberOfPorts; p++) { |
6755 | len += sprintf(buf+len, " PortNumber = %d (of %d)\n", | 6711 | seq_printf(m, " PortNumber = %d (of %d)\n", |
6756 | p+1, | 6712 | p+1, |
6757 | ioc->facts.NumberOfPorts); | 6713 | ioc->facts.NumberOfPorts); |
6758 | if (ioc->bus_type == FC) { | 6714 | if (ioc->bus_type == FC) { |
6759 | if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { | 6715 | if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { |
6760 | u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; | 6716 | u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; |
6761 | len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", | 6717 | seq_printf(m, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", |
6762 | a[5], a[4], a[3], a[2], a[1], a[0]); | 6718 | a[5], a[4], a[3], a[2], a[1], a[0]); |
6763 | } | 6719 | } |
6764 | len += sprintf(buf+len, " WWN = %08X%08X:%08X%08X\n", | 6720 | seq_printf(m, " WWN = %08X%08X:%08X%08X\n", |
6765 | ioc->fc_port_page0[p].WWNN.High, | 6721 | ioc->fc_port_page0[p].WWNN.High, |
6766 | ioc->fc_port_page0[p].WWNN.Low, | 6722 | ioc->fc_port_page0[p].WWNN.Low, |
6767 | ioc->fc_port_page0[p].WWPN.High, | 6723 | ioc->fc_port_page0[p].WWPN.High, |
@@ -6769,9 +6725,21 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo | |||
6769 | } | 6725 | } |
6770 | } | 6726 | } |
6771 | 6727 | ||
6772 | MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len); | 6728 | return 0; |
6773 | } | 6729 | } |
6774 | 6730 | ||
6731 | static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file) | ||
6732 | { | ||
6733 | return single_open(file, mpt_iocinfo_proc_show, PDE(inode)->data); | ||
6734 | } | ||
6735 | |||
6736 | static const struct file_operations mpt_iocinfo_proc_fops = { | ||
6737 | .owner = THIS_MODULE, | ||
6738 | .open = mpt_iocinfo_proc_open, | ||
6739 | .read = seq_read, | ||
6740 | .llseek = seq_lseek, | ||
6741 | .release = single_release, | ||
6742 | }; | ||
6775 | #endif /* CONFIG_PROC_FS } */ | 6743 | #endif /* CONFIG_PROC_FS } */ |
6776 | 6744 | ||
6777 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6745 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -6837,6 +6805,39 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh | |||
6837 | 6805 | ||
6838 | *size = y; | 6806 | *size = y; |
6839 | } | 6807 | } |
6808 | |||
6809 | static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan) | ||
6810 | { | ||
6811 | char expVer[32]; | ||
6812 | |||
6813 | mpt_get_fw_exp_ver(expVer, ioc); | ||
6814 | |||
6815 | /* | ||
6816 | * Shorter summary of attached ioc's... | ||
6817 | */ | ||
6818 | seq_printf(m, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d", | ||
6819 | ioc->name, | ||
6820 | ioc->prod_name, | ||
6821 | MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */ | ||
6822 | ioc->facts.FWVersion.Word, | ||
6823 | expVer, | ||
6824 | ioc->facts.NumberOfPorts, | ||
6825 | ioc->req_depth); | ||
6826 | |||
6827 | if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { | ||
6828 | u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; | ||
6829 | seq_printf(m, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X", | ||
6830 | a[5], a[4], a[3], a[2], a[1], a[0]); | ||
6831 | } | ||
6832 | |||
6833 | seq_printf(m, ", IRQ=%d", ioc->pci_irq); | ||
6834 | |||
6835 | if (!ioc->active) | ||
6836 | seq_printf(m, " (disabled)"); | ||
6837 | |||
6838 | seq_putc(m, '\n'); | ||
6839 | } | ||
6840 | |||
6840 | /** | 6841 | /** |
6841 | * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management | 6842 | * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management |
6842 | * @ioc: Pointer to MPT_ADAPTER structure | 6843 | * @ioc: Pointer to MPT_ADAPTER structure |
@@ -6922,7 +6923,6 @@ EXPORT_SYMBOL(mpt_halt_firmware); | |||
6922 | * mpt_SoftResetHandler - Issues a less expensive reset | 6923 | * mpt_SoftResetHandler - Issues a less expensive reset |
6923 | * @ioc: Pointer to MPT_ADAPTER structure | 6924 | * @ioc: Pointer to MPT_ADAPTER structure |
6924 | * @sleepFlag: Indicates if sleep or schedule must be called. | 6925 | * @sleepFlag: Indicates if sleep or schedule must be called. |
6925 | |||
6926 | * | 6926 | * |
6927 | * Returns 0 for SUCCESS or -1 if FAILED. | 6927 | * Returns 0 for SUCCESS or -1 if FAILED. |
6928 | * | 6928 | * |
@@ -7067,7 +7067,6 @@ mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | |||
7067 | * mpt_Soft_Hard_ResetHandler - Try less expensive reset | 7067 | * mpt_Soft_Hard_ResetHandler - Try less expensive reset |
7068 | * @ioc: Pointer to MPT_ADAPTER structure | 7068 | * @ioc: Pointer to MPT_ADAPTER structure |
7069 | * @sleepFlag: Indicates if sleep or schedule must be called. | 7069 | * @sleepFlag: Indicates if sleep or schedule must be called. |
7070 | |||
7071 | * | 7070 | * |
7072 | * Returns 0 for SUCCESS or -1 if FAILED. | 7071 | * Returns 0 for SUCCESS or -1 if FAILED. |
7073 | * Try for softreset first, only if it fails go for expensive | 7072 | * Try for softreset first, only if it fails go for expensive |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 23ed3dec72a5..f71f22948477 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -420,31 +420,6 @@ typedef struct _VirtDevice { | |||
420 | #define MPT_TARGET_FLAGS_LED_ON 0x80 | 420 | #define MPT_TARGET_FLAGS_LED_ON 0x80 |
421 | 421 | ||
422 | /* | 422 | /* |
423 | * /proc/mpt interface | ||
424 | */ | ||
425 | typedef struct { | ||
426 | const char *name; | ||
427 | mode_t mode; | ||
428 | int pad; | ||
429 | read_proc_t *read_proc; | ||
430 | write_proc_t *write_proc; | ||
431 | } mpt_proc_entry_t; | ||
432 | |||
433 | #define MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len) \ | ||
434 | do { \ | ||
435 | len -= offset; \ | ||
436 | if (len < request) { \ | ||
437 | *eof = 1; \ | ||
438 | if (len <= 0) \ | ||
439 | return 0; \ | ||
440 | } else \ | ||
441 | len = request; \ | ||
442 | *start = buf + offset; \ | ||
443 | return len; \ | ||
444 | } while (0) | ||
445 | |||
446 | |||
447 | /* | ||
448 | * IOCTL structure and associated defines | 423 | * IOCTL structure and associated defines |
449 | */ | 424 | */ |
450 | 425 | ||
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 06c655c55587..a3970e56ae53 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
@@ -389,12 +389,16 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) | |||
389 | dev = &c->pdev->dev; | 389 | dev = &c->pdev->dev; |
390 | 390 | ||
391 | if (i2o_dma_realloc(dev, &c->dlct, | 391 | if (i2o_dma_realloc(dev, &c->dlct, |
392 | le32_to_cpu(sb->expected_lct_size))) | 392 | le32_to_cpu(sb->expected_lct_size))) { |
393 | mutex_unlock(&c->lct_lock); | ||
393 | return -ENOMEM; | 394 | return -ENOMEM; |
395 | } | ||
394 | 396 | ||
395 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | 397 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
396 | if (IS_ERR(msg)) | 398 | if (IS_ERR(msg)) { |
399 | mutex_unlock(&c->lct_lock); | ||
397 | return PTR_ERR(msg); | 400 | return PTR_ERR(msg); |
401 | } | ||
398 | 402 | ||
399 | msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); | 403 | msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); |
400 | msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | | 404 | msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | |
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index e6733bc99724..f0f1e667000f 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c | |||
@@ -727,7 +727,7 @@ static int i2o_block_transfer(struct request *req) | |||
727 | { | 727 | { |
728 | struct i2o_block_device *dev = req->rq_disk->private_data; | 728 | struct i2o_block_device *dev = req->rq_disk->private_data; |
729 | struct i2o_controller *c; | 729 | struct i2o_controller *c; |
730 | u32 tid = dev->i2o_dev->lct_data.tid; | 730 | u32 tid; |
731 | struct i2o_message *msg; | 731 | struct i2o_message *msg; |
732 | u32 *mptr; | 732 | u32 *mptr; |
733 | struct i2o_block_request *ireq = req->special; | 733 | struct i2o_block_request *ireq = req->special; |
@@ -743,6 +743,7 @@ static int i2o_block_transfer(struct request *req) | |||
743 | goto exit; | 743 | goto exit; |
744 | } | 744 | } |
745 | 745 | ||
746 | tid = dev->i2o_dev->lct_data.tid; | ||
746 | c = dev->i2o_dev->iop; | 747 | c = dev->i2o_dev->iop; |
747 | 748 | ||
748 | msg = i2o_msg_get(c); | 749 | msg = i2o_msg_get(c); |
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index c4b117f5fb70..068ba0785bb4 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
@@ -111,11 +111,11 @@ static int i2o_cfg_gethrt(unsigned long arg) | |||
111 | 111 | ||
112 | len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); | 112 | len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); |
113 | 113 | ||
114 | /* We did a get user...so assuming mem is ok...is this bad? */ | 114 | if (put_user(len, kcmd.reslen)) |
115 | put_user(len, kcmd.reslen); | 115 | ret = -EFAULT; |
116 | if (len > reslen) | 116 | else if (len > reslen) |
117 | ret = -ENOBUFS; | 117 | ret = -ENOBUFS; |
118 | if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) | 118 | else if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) |
119 | ret = -EFAULT; | 119 | ret = -EFAULT; |
120 | 120 | ||
121 | return ret; | 121 | return ret; |
@@ -147,8 +147,9 @@ static int i2o_cfg_getlct(unsigned long arg) | |||
147 | lct = (i2o_lct *) c->lct; | 147 | lct = (i2o_lct *) c->lct; |
148 | 148 | ||
149 | len = (unsigned int)lct->table_size << 2; | 149 | len = (unsigned int)lct->table_size << 2; |
150 | put_user(len, kcmd.reslen); | 150 | if (put_user(len, kcmd.reslen)) |
151 | if (len > reslen) | 151 | ret = -EFAULT; |
152 | else if (len > reslen) | ||
152 | ret = -ENOBUFS; | 153 | ret = -ENOBUFS; |
153 | else if (copy_to_user(kcmd.resbuf, lct, len)) | 154 | else if (copy_to_user(kcmd.resbuf, lct, len)) |
154 | ret = -EFAULT; | 155 | ret = -EFAULT; |
@@ -208,8 +209,9 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) | |||
208 | return -EAGAIN; | 209 | return -EAGAIN; |
209 | } | 210 | } |
210 | 211 | ||
211 | put_user(len, kcmd.reslen); | 212 | if (put_user(len, kcmd.reslen)) |
212 | if (len > reslen) | 213 | ret = -EFAULT; |
214 | else if (len > reslen) | ||
213 | ret = -ENOBUFS; | 215 | ret = -ENOBUFS; |
214 | else if (copy_to_user(kcmd.resbuf, res, len)) | 216 | else if (copy_to_user(kcmd.resbuf, res, len)) |
215 | ret = -EFAULT; | 217 | ret = -EFAULT; |
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 3d45817e6dcd..ea6b2197da8a 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c | |||
@@ -528,7 +528,6 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
528 | * Do the incoming paperwork | 528 | * Do the incoming paperwork |
529 | */ | 529 | */ |
530 | i2o_dev = SCpnt->device->hostdata; | 530 | i2o_dev = SCpnt->device->hostdata; |
531 | c = i2o_dev->iop; | ||
532 | 531 | ||
533 | SCpnt->scsi_done = done; | 532 | SCpnt->scsi_done = done; |
534 | 533 | ||
@@ -538,7 +537,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
538 | done(SCpnt); | 537 | done(SCpnt); |
539 | goto exit; | 538 | goto exit; |
540 | } | 539 | } |
541 | 540 | c = i2o_dev->iop; | |
542 | tid = i2o_dev->lct_data.tid; | 541 | tid = i2o_dev->lct_data.tid; |
543 | 542 | ||
544 | osm_debug("qcmd: Tid = %03x\n", tid); | 543 | osm_debug("qcmd: Tid = %03x\n", tid); |
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 2c65a2c57294..07933f3f7e4c 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -74,12 +74,12 @@ static struct mfd_cell backlight_devs[] = { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | static struct resource led_resources[] = { | 76 | static struct resource led_resources[] = { |
77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB2B), | 77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B), |
78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB2C), | 78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C), |
79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB2D), | 79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D), |
80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB1B), | 80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B), |
81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB1C), | 81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C), |
82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB1D), | 82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D), |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define PM8606_LED_DEVS(_i) \ | 85 | #define PM8606_LED_DEVS(_i) \ |
@@ -428,52 +428,44 @@ static int __devinit device_gpadc_init(struct pm860x_chip *chip, | |||
428 | { | 428 | { |
429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | 429 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ |
430 | : chip->companion; | 430 | : chip->companion; |
431 | int use_gpadc = 0, data, ret; | 431 | int data; |
432 | int ret; | ||
432 | 433 | ||
433 | /* initialize GPADC without activating it */ | 434 | /* initialize GPADC without activating it */ |
434 | 435 | ||
435 | if (pdata && pdata->touch) { | 436 | if (!pdata || !pdata->touch) |
436 | /* set GPADC MISC1 register */ | 437 | return -EINVAL; |
437 | data = 0; | ||
438 | data |= (pdata->touch->gpadc_prebias << 1) | ||
439 | & PM8607_GPADC_PREBIAS_MASK; | ||
440 | data |= (pdata->touch->slot_cycle << 3) | ||
441 | & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
442 | data |= (pdata->touch->off_scale << 5) | ||
443 | & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) | ||
445 | & PM8607_GPADC_SW_CAL_MASK; | ||
446 | if (data) { | ||
447 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
448 | if (ret < 0) | ||
449 | goto out; | ||
450 | } | ||
451 | /* set tsi prebias time */ | ||
452 | if (pdata->touch->tsi_prebias) { | ||
453 | data = pdata->touch->tsi_prebias; | ||
454 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); | ||
455 | if (ret < 0) | ||
456 | goto out; | ||
457 | } | ||
458 | /* set prebias & prechg time of pen detect */ | ||
459 | data = 0; | ||
460 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
461 | data |= (pdata->touch->pen_prechg << 5) | ||
462 | & PM8607_PD_PRECHG_MASK; | ||
463 | if (data) { | ||
464 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
465 | if (ret < 0) | ||
466 | goto out; | ||
467 | } | ||
468 | 438 | ||
469 | use_gpadc = 1; | 439 | /* set GPADC MISC1 register */ |
440 | data = 0; | ||
441 | data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; | ||
442 | data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
443 | data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; | ||
444 | data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; | ||
445 | if (data) { | ||
446 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
447 | if (ret < 0) | ||
448 | goto out; | ||
470 | } | 449 | } |
471 | 450 | /* set tsi prebias time */ | |
472 | /* turn on GPADC */ | 451 | if (pdata->touch->tsi_prebias) { |
473 | if (use_gpadc) { | 452 | data = pdata->touch->tsi_prebias; |
474 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | 453 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); |
475 | PM8607_GPADC_EN, PM8607_GPADC_EN); | 454 | if (ret < 0) |
455 | goto out; | ||
476 | } | 456 | } |
457 | /* set prebias & prechg time of pen detect */ | ||
458 | data = 0; | ||
459 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | ||
460 | data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; | ||
461 | if (data) { | ||
462 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
463 | if (ret < 0) | ||
464 | goto out; | ||
465 | } | ||
466 | |||
467 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | ||
468 | PM8607_GPADC_EN, PM8607_GPADC_EN); | ||
477 | out: | 469 | out: |
478 | return ret; | 470 | return ret; |
479 | } | 471 | } |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9da0e504bbe9..db51ea1c6082 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -7,7 +7,16 @@ menuconfig MFD_SUPPORT | |||
7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | default y | 8 | default y |
9 | help | 9 | help |
10 | Configure MFD device drivers. | 10 | Multifunction devices embed several functions (e.g. GPIOs, |
11 | touchscreens, keyboards, current regulators, power management chips, | ||
12 | etc...) in one single integrated circuit. They usually talk to the | ||
13 | main CPU through one or more IRQ lines and low speed data busses (SPI, | ||
14 | I2C, etc..). They appear as one single device to the main system | ||
15 | through the data bus and the MFD framework allows for sub devices | ||
16 | (a.k.a. functions) to appear as discrete platform devices. | ||
17 | MFDs are typically found on embedded platforms. | ||
18 | |||
19 | This option alone does not add any kernel code. | ||
11 | 20 | ||
12 | if MFD_SUPPORT | 21 | if MFD_SUPPORT |
13 | 22 | ||
@@ -177,6 +186,38 @@ config TWL4030_CODEC | |||
177 | select MFD_CORE | 186 | select MFD_CORE |
178 | default n | 187 | default n |
179 | 188 | ||
189 | config TWL6030_PWM | ||
190 | tristate "TWL6030 PWM (Pulse Width Modulator) Support" | ||
191 | depends on TWL4030_CORE | ||
192 | select HAVE_PWM | ||
193 | default n | ||
194 | help | ||
195 | Say yes here if you want support for TWL6030 PWM. | ||
196 | This is used to control charging LED brightness. | ||
197 | |||
198 | config MFD_STMPE | ||
199 | bool "Support STMicroelectronics STMPE" | ||
200 | depends on I2C=y && GENERIC_HARDIRQS | ||
201 | select MFD_CORE | ||
202 | help | ||
203 | Support for the STMPE family of I/O Expanders from | ||
204 | STMicroelectronics. | ||
205 | |||
206 | Currently supported devices are: | ||
207 | |||
208 | STMPE811: GPIO, Touchscreen | ||
209 | STMPE1601: GPIO, Keypad | ||
210 | STMPE2401: GPIO, Keypad | ||
211 | STMPE2403: GPIO, Keypad | ||
212 | |||
213 | This driver provides common support for accessing the device, | ||
214 | additional drivers must be enabled in order to use the functionality | ||
215 | of the device. Currently available sub drivers are: | ||
216 | |||
217 | GPIO: stmpe-gpio | ||
218 | Keypad: stmpe-keypad | ||
219 | Touchscreen: stmpe-ts | ||
220 | |||
180 | config MFD_TC35892 | 221 | config MFD_TC35892 |
181 | bool "Support Toshiba TC35892" | 222 | bool "Support Toshiba TC35892" |
182 | depends on I2C=y && GENERIC_HARDIRQS | 223 | depends on I2C=y && GENERIC_HARDIRQS |
@@ -252,6 +293,16 @@ config MFD_MAX8925 | |||
252 | accessing the device, additional drivers must be enabled in order | 293 | accessing the device, additional drivers must be enabled in order |
253 | to use the functionality of the device. | 294 | to use the functionality of the device. |
254 | 295 | ||
296 | config MFD_MAX8998 | ||
297 | bool "Maxim Semiconductor MAX8998 PMIC Support" | ||
298 | depends on I2C=y | ||
299 | select MFD_CORE | ||
300 | help | ||
301 | Say yes here to support for Maxim Semiconductor MAX8998. This is | ||
302 | a Power Management IC. This driver provies common support for | ||
303 | accessing the device, additional drivers must be enabled in order | ||
304 | to use the functionality of the device. | ||
305 | |||
255 | config MFD_WM8400 | 306 | config MFD_WM8400 |
256 | tristate "Support Wolfson Microelectronics WM8400" | 307 | tristate "Support Wolfson Microelectronics WM8400" |
257 | select MFD_CORE | 308 | select MFD_CORE |
@@ -482,6 +533,28 @@ config MFD_JANZ_CMODIO | |||
482 | host many different types of MODULbus daughterboards, including | 533 | host many different types of MODULbus daughterboards, including |
483 | CAN and GPIO controllers. | 534 | CAN and GPIO controllers. |
484 | 535 | ||
536 | config MFD_JZ4740_ADC | ||
537 | tristate "Support for the JZ4740 SoC ADC core" | ||
538 | select MFD_CORE | ||
539 | depends on MACH_JZ4740 | ||
540 | help | ||
541 | Say yes here if you want support for the ADC unit in the JZ4740 SoC. | ||
542 | This driver is necessary for jz4740-battery and jz4740-hwmon driver. | ||
543 | |||
544 | config MFD_TPS6586X | ||
545 | tristate "TPS6586x Power Management chips" | ||
546 | depends on I2C && GPIOLIB | ||
547 | select MFD_CORE | ||
548 | help | ||
549 | If you say yes here you get support for the TPS6586X series of | ||
550 | Power Management chips. | ||
551 | This driver provides common support for accessing the device, | ||
552 | additional drivers must be enabled in order to use the | ||
553 | functionality of the device. | ||
554 | |||
555 | This driver can also be built as a module. If so, the module | ||
556 | will be called tps6586x. | ||
557 | |||
485 | endif # MFD_SUPPORT | 558 | endif # MFD_SUPPORT |
486 | 559 | ||
487 | menu "Multimedia Capabilities Port drivers" | 560 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index fb503e77dc60..feaeeaeeddb7 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o | |||
15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o | 15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o |
16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o | 16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o |
17 | 17 | ||
18 | obj-$(CONFIG_MFD_STMPE) += stmpe.o | ||
18 | obj-$(CONFIG_MFD_TC35892) += tc35892.o | 19 | obj-$(CONFIG_MFD_TC35892) += tc35892.o |
19 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o | 20 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o |
20 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o | 21 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o |
@@ -36,6 +37,7 @@ obj-$(CONFIG_MENELAUS) += menelaus.o | |||
36 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o | 37 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o |
37 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o | 38 | obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o |
38 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o | 39 | obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o |
40 | obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o | ||
39 | 41 | ||
40 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o | 42 | obj-$(CONFIG_MFD_MC13783) += mc13783-core.o |
41 | 43 | ||
@@ -56,6 +58,7 @@ obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o | |||
56 | obj-$(CONFIG_PMIC_DA903X) += da903x.o | 58 | obj-$(CONFIG_PMIC_DA903X) += da903x.o |
57 | max8925-objs := max8925-core.o max8925-i2c.o | 59 | max8925-objs := max8925-core.o max8925-i2c.o |
58 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 60 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
61 | obj-$(CONFIG_MFD_MAX8998) += max8998.o | ||
59 | 62 | ||
60 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o | 63 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o |
61 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o | 64 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o |
@@ -71,3 +74,5 @@ obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | |||
71 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o | 74 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o |
72 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o | 75 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o |
73 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o | 76 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o |
77 | obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o | ||
78 | obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o | ||
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index 63d2b727ddbb..8440010eb2b8 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c | |||
@@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
199 | 199 | ||
200 | err = ab3100_otp_read(otp); | 200 | err = ab3100_otp_read(otp); |
201 | if (err) | 201 | if (err) |
202 | return err; | 202 | goto err_otp_read; |
203 | 203 | ||
204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); | 204 | dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); |
205 | 205 | ||
@@ -208,21 +208,21 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
208 | err = device_create_file(&pdev->dev, | 208 | err = device_create_file(&pdev->dev, |
209 | &ab3100_otp_attrs[i]); | 209 | &ab3100_otp_attrs[i]); |
210 | if (err) | 210 | if (err) |
211 | goto out_no_sysfs; | 211 | goto err_create_file; |
212 | } | 212 | } |
213 | 213 | ||
214 | /* debugfs entries */ | 214 | /* debugfs entries */ |
215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); | 215 | err = ab3100_otp_init_debugfs(&pdev->dev, otp); |
216 | if (err) | 216 | if (err) |
217 | goto out_no_debugfs; | 217 | goto err_init_debugfs; |
218 | 218 | ||
219 | return 0; | 219 | return 0; |
220 | 220 | ||
221 | out_no_sysfs: | 221 | err_init_debugfs: |
222 | for (i = 0; i < ARRAY_SIZE(ab3100_otp_attrs); i++) | 222 | err_create_file: |
223 | device_remove_file(&pdev->dev, | 223 | while (--i >= 0) |
224 | &ab3100_otp_attrs[i]); | 224 | device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); |
225 | out_no_debugfs: | 225 | err_otp_read: |
226 | kfree(otp); | 226 | kfree(otp); |
227 | return err; | 227 | return err; |
228 | } | 228 | } |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index f54ab62e7bc6..8a98739e6d9c 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c | |||
@@ -589,16 +589,16 @@ static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | |||
589 | } | 589 | } |
590 | 590 | ||
591 | /* | 591 | /* |
592 | * The exported register access functionality. | 592 | * The register access functionality. |
593 | */ | 593 | */ |
594 | int ab3550_get_chip_id(struct device *dev) | 594 | static int ab3550_get_chip_id(struct device *dev) |
595 | { | 595 | { |
596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); | 596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); |
597 | return (int)ab->chip_id; | 597 | return (int)ab->chip_id; |
598 | } | 598 | } |
599 | 599 | ||
600 | int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | 600 | static int ab3550_mask_and_set_register_interruptible(struct device *dev, |
601 | u8 reg, u8 bitmask, u8 bitvalues) | 601 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) |
602 | { | 602 | { |
603 | struct ab3550 *ab; | 603 | struct ab3550 *ab; |
604 | struct platform_device *pdev = to_platform_device(dev); | 604 | struct platform_device *pdev = to_platform_device(dev); |
@@ -612,15 +612,15 @@ int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | |||
612 | bitmask, bitvalues); | 612 | bitmask, bitvalues); |
613 | } | 613 | } |
614 | 614 | ||
615 | int ab3550_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | 615 | static int ab3550_set_register_interruptible(struct device *dev, u8 bank, |
616 | u8 value) | 616 | u8 reg, u8 value) |
617 | { | 617 | { |
618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | 618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, |
619 | value); | 619 | value); |
620 | } | 620 | } |
621 | 621 | ||
622 | int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | 622 | static int ab3550_get_register_interruptible(struct device *dev, u8 bank, |
623 | u8 *value) | 623 | u8 reg, u8 *value) |
624 | { | 624 | { |
625 | struct ab3550 *ab; | 625 | struct ab3550 *ab; |
626 | struct platform_device *pdev = to_platform_device(dev); | 626 | struct platform_device *pdev = to_platform_device(dev); |
@@ -633,7 +633,7 @@ int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | |||
633 | return get_register_interruptible(ab, bank, reg, value); | 633 | return get_register_interruptible(ab, bank, reg, value); |
634 | } | 634 | } |
635 | 635 | ||
636 | int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | 636 | static int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, |
637 | u8 first_reg, u8 *regvals, u8 numregs) | 637 | u8 first_reg, u8 *regvals, u8 numregs) |
638 | { | 638 | { |
639 | struct ab3550 *ab; | 639 | struct ab3550 *ab; |
@@ -649,7 +649,8 @@ int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | |||
649 | numregs); | 649 | numregs); |
650 | } | 650 | } |
651 | 651 | ||
652 | int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | 652 | static int ab3550_event_registers_startup_state_get(struct device *dev, |
653 | u8 *event) | ||
653 | { | 654 | { |
654 | struct ab3550 *ab; | 655 | struct ab3550 *ab; |
655 | 656 | ||
@@ -661,7 +662,7 @@ int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | |||
661 | return 0; | 662 | return 0; |
662 | } | 663 | } |
663 | 664 | ||
664 | int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) | 665 | static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) |
665 | { | 666 | { |
666 | struct ab3550 *ab; | 667 | struct ab3550 *ab; |
667 | struct ab3550_platform_data *plf_data; | 668 | struct ab3550_platform_data *plf_data; |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index f3d26fa9c34d..defa786dee34 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/mfd/core.h> | 17 | #include <linux/mfd/core.h> |
18 | #include <linux/mfd/ab8500.h> | 18 | #include <linux/mfd/ab8500.h> |
19 | #include <linux/regulator/ab8500.h> | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * Interrupt register offsets | 22 | * Interrupt register offsets |
@@ -352,6 +353,7 @@ static struct mfd_cell ab8500_devs[] = { | |||
352 | { .name = "ab8500-audio", }, | 353 | { .name = "ab8500-audio", }, |
353 | { .name = "ab8500-usb", }, | 354 | { .name = "ab8500-usb", }, |
354 | { .name = "ab8500-pwm", }, | 355 | { .name = "ab8500-pwm", }, |
356 | { .name = "ab8500-regulator", }, | ||
355 | }; | 357 | }; |
356 | 358 | ||
357 | int __devinit ab8500_init(struct ab8500 *ab8500) | 359 | int __devinit ab8500_init(struct ab8500 *ab8500) |
@@ -411,7 +413,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
411 | goto out_removeirq; | 413 | goto out_removeirq; |
412 | } | 414 | } |
413 | 415 | ||
414 | ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs, | 416 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, |
415 | ARRAY_SIZE(ab8500_devs), NULL, | 417 | ARRAY_SIZE(ab8500_devs), NULL, |
416 | ab8500->irq_base); | 418 | ab8500->irq_base); |
417 | if (ret) | 419 | if (ret) |
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c index b81d4f768ef6..e1c8b62b086d 100644 --- a/drivers/mfd/ab8500-spi.c +++ b/drivers/mfd/ab8500-spi.c | |||
@@ -68,7 +68,12 @@ static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr) | |||
68 | 68 | ||
69 | ret = spi_sync(spi, &msg); | 69 | ret = spi_sync(spi, &msg); |
70 | if (!ret) | 70 | if (!ret) |
71 | ret = ab8500->rx_buf[0]; | 71 | /* |
72 | * Only the 8 lowermost bytes are | ||
73 | * defined with value, the rest may | ||
74 | * vary depending on chip/board noise. | ||
75 | */ | ||
76 | ret = ab8500->rx_buf[0] & 0xFFU; | ||
72 | 77 | ||
73 | return ret; | 78 | return ret; |
74 | } | 79 | } |
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 3b3b97ec32a7..f12720dbe126 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c | |||
@@ -36,7 +36,7 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops) | |||
36 | struct abx500_device_entry *dev_entry; | 36 | struct abx500_device_entry *dev_entry; |
37 | 37 | ||
38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); | 38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); |
39 | if (IS_ERR(dev_entry)) { | 39 | if (!dev_entry) { |
40 | dev_err(dev, "register_ops kzalloc failed"); | 40 | dev_err(dev, "register_ops kzalloc failed"); |
41 | return -ENOMEM; | 41 | return -ENOMEM; |
42 | } | 42 | } |
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 3e75f02e4778..33c923d215c7 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c | |||
@@ -94,7 +94,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 94 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
95 | if (!res) { | 95 | if (!res) { |
96 | dev_err(&pdev->dev, "no DMA resource\n"); | 96 | dev_err(&pdev->dev, "no DMA resource\n"); |
97 | return -ENXIO; | 97 | ret = -ENXIO; |
98 | goto fail4; | ||
98 | } | 99 | } |
99 | 100 | ||
100 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; | 101 | davinci_vc->davinci_vcif.dma_tx_channel = res->start; |
@@ -104,7 +105,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) | |||
104 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 105 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
105 | if (!res) { | 106 | if (!res) { |
106 | dev_err(&pdev->dev, "no DMA resource\n"); | 107 | dev_err(&pdev->dev, "no DMA resource\n"); |
107 | return -ENXIO; | 108 | ret = -ENXIO; |
109 | goto fail4; | ||
108 | } | 110 | } |
109 | 111 | ||
110 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; | 112 | davinci_vc->davinci_vcif.dma_rx_channel = res->start; |
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 9ed630799acc..36a166bcdb08 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/mfd/core.h> | 22 | #include <linux/mfd/core.h> |
22 | 23 | ||
23 | #include <linux/mfd/janz.h> | 24 | #include <linux/mfd/janz.h> |
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c new file mode 100644 index 000000000000..3ad492cb6c41 --- /dev/null +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -0,0 +1,394 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 SoC ADC driver | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | * This driver synchronizes access to the JZ4740 ADC core between the | ||
15 | * JZ4740 battery and hwmon drivers. | ||
16 | */ | ||
17 | |||
18 | #include <linux/err.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | |||
27 | #include <linux/clk.h> | ||
28 | #include <linux/mfd/core.h> | ||
29 | |||
30 | #include <linux/jz4740-adc.h> | ||
31 | |||
32 | |||
33 | #define JZ_REG_ADC_ENABLE 0x00 | ||
34 | #define JZ_REG_ADC_CFG 0x04 | ||
35 | #define JZ_REG_ADC_CTRL 0x08 | ||
36 | #define JZ_REG_ADC_STATUS 0x0c | ||
37 | |||
38 | #define JZ_REG_ADC_TOUCHSCREEN_BASE 0x10 | ||
39 | #define JZ_REG_ADC_BATTERY_BASE 0x1c | ||
40 | #define JZ_REG_ADC_HWMON_BASE 0x20 | ||
41 | |||
42 | #define JZ_ADC_ENABLE_TOUCH BIT(2) | ||
43 | #define JZ_ADC_ENABLE_BATTERY BIT(1) | ||
44 | #define JZ_ADC_ENABLE_ADCIN BIT(0) | ||
45 | |||
46 | enum { | ||
47 | JZ_ADC_IRQ_ADCIN = 0, | ||
48 | JZ_ADC_IRQ_BATTERY, | ||
49 | JZ_ADC_IRQ_TOUCH, | ||
50 | JZ_ADC_IRQ_PENUP, | ||
51 | JZ_ADC_IRQ_PENDOWN, | ||
52 | }; | ||
53 | |||
54 | struct jz4740_adc { | ||
55 | struct resource *mem; | ||
56 | void __iomem *base; | ||
57 | |||
58 | int irq; | ||
59 | int irq_base; | ||
60 | |||
61 | struct clk *clk; | ||
62 | atomic_t clk_ref; | ||
63 | |||
64 | spinlock_t lock; | ||
65 | }; | ||
66 | |||
67 | static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq, | ||
68 | bool masked) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | uint8_t val; | ||
72 | |||
73 | irq -= adc->irq_base; | ||
74 | |||
75 | spin_lock_irqsave(&adc->lock, flags); | ||
76 | |||
77 | val = readb(adc->base + JZ_REG_ADC_CTRL); | ||
78 | if (masked) | ||
79 | val |= BIT(irq); | ||
80 | else | ||
81 | val &= ~BIT(irq); | ||
82 | writeb(val, adc->base + JZ_REG_ADC_CTRL); | ||
83 | |||
84 | spin_unlock_irqrestore(&adc->lock, flags); | ||
85 | } | ||
86 | |||
87 | static void jz4740_adc_irq_mask(unsigned int irq) | ||
88 | { | ||
89 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
90 | jz4740_adc_irq_set_masked(adc, irq, true); | ||
91 | } | ||
92 | |||
93 | static void jz4740_adc_irq_unmask(unsigned int irq) | ||
94 | { | ||
95 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
96 | jz4740_adc_irq_set_masked(adc, irq, false); | ||
97 | } | ||
98 | |||
99 | static void jz4740_adc_irq_ack(unsigned int irq) | ||
100 | { | ||
101 | struct jz4740_adc *adc = get_irq_chip_data(irq); | ||
102 | |||
103 | irq -= adc->irq_base; | ||
104 | writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS); | ||
105 | } | ||
106 | |||
107 | static struct irq_chip jz4740_adc_irq_chip = { | ||
108 | .name = "jz4740-adc", | ||
109 | .mask = jz4740_adc_irq_mask, | ||
110 | .unmask = jz4740_adc_irq_unmask, | ||
111 | .ack = jz4740_adc_irq_ack, | ||
112 | }; | ||
113 | |||
114 | static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
115 | { | ||
116 | struct jz4740_adc *adc = get_irq_desc_data(desc); | ||
117 | uint8_t status; | ||
118 | unsigned int i; | ||
119 | |||
120 | status = readb(adc->base + JZ_REG_ADC_STATUS); | ||
121 | |||
122 | for (i = 0; i < 5; ++i) { | ||
123 | if (status & BIT(i)) | ||
124 | generic_handle_irq(adc->irq_base + i); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | |||
129 | /* Refcounting for the ADC clock is done in here instead of in the clock | ||
130 | * framework, because it is the only clock which is shared between multiple | ||
131 | * devices and thus is the only clock which needs refcounting */ | ||
132 | static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc) | ||
133 | { | ||
134 | if (atomic_inc_return(&adc->clk_ref) == 1) | ||
135 | clk_enable(adc->clk); | ||
136 | } | ||
137 | |||
138 | static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc) | ||
139 | { | ||
140 | if (atomic_dec_return(&adc->clk_ref) == 0) | ||
141 | clk_disable(adc->clk); | ||
142 | } | ||
143 | |||
144 | static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine, | ||
145 | bool enabled) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | uint8_t val; | ||
149 | |||
150 | spin_lock_irqsave(&adc->lock, flags); | ||
151 | |||
152 | val = readb(adc->base + JZ_REG_ADC_ENABLE); | ||
153 | if (enabled) | ||
154 | val |= BIT(engine); | ||
155 | else | ||
156 | val &= BIT(engine); | ||
157 | writeb(val, adc->base + JZ_REG_ADC_ENABLE); | ||
158 | |||
159 | spin_unlock_irqrestore(&adc->lock, flags); | ||
160 | } | ||
161 | |||
162 | static int jz4740_adc_cell_enable(struct platform_device *pdev) | ||
163 | { | ||
164 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
165 | |||
166 | jz4740_adc_clk_enable(adc); | ||
167 | jz4740_adc_set_enabled(adc, pdev->id, true); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int jz4740_adc_cell_disable(struct platform_device *pdev) | ||
173 | { | ||
174 | struct jz4740_adc *adc = dev_get_drvdata(pdev->dev.parent); | ||
175 | |||
176 | jz4740_adc_set_enabled(adc, pdev->id, false); | ||
177 | jz4740_adc_clk_disable(adc); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int jz4740_adc_set_config(struct device *dev, uint32_t mask, uint32_t val) | ||
183 | { | ||
184 | struct jz4740_adc *adc = dev_get_drvdata(dev); | ||
185 | unsigned long flags; | ||
186 | uint32_t cfg; | ||
187 | |||
188 | if (!adc) | ||
189 | return -ENODEV; | ||
190 | |||
191 | spin_lock_irqsave(&adc->lock, flags); | ||
192 | |||
193 | cfg = readl(adc->base + JZ_REG_ADC_CFG); | ||
194 | |||
195 | cfg &= ~mask; | ||
196 | cfg |= val; | ||
197 | |||
198 | writel(cfg, adc->base + JZ_REG_ADC_CFG); | ||
199 | |||
200 | spin_unlock_irqrestore(&adc->lock, flags); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(jz4740_adc_set_config); | ||
205 | |||
206 | static struct resource jz4740_hwmon_resources[] = { | ||
207 | { | ||
208 | .start = JZ_ADC_IRQ_ADCIN, | ||
209 | .flags = IORESOURCE_IRQ, | ||
210 | }, | ||
211 | { | ||
212 | .start = JZ_REG_ADC_HWMON_BASE, | ||
213 | .end = JZ_REG_ADC_HWMON_BASE + 3, | ||
214 | .flags = IORESOURCE_MEM, | ||
215 | }, | ||
216 | }; | ||
217 | |||
218 | static struct resource jz4740_battery_resources[] = { | ||
219 | { | ||
220 | .start = JZ_ADC_IRQ_BATTERY, | ||
221 | .flags = IORESOURCE_IRQ, | ||
222 | }, | ||
223 | { | ||
224 | .start = JZ_REG_ADC_BATTERY_BASE, | ||
225 | .end = JZ_REG_ADC_BATTERY_BASE + 3, | ||
226 | .flags = IORESOURCE_MEM, | ||
227 | }, | ||
228 | }; | ||
229 | |||
230 | const struct mfd_cell jz4740_adc_cells[] = { | ||
231 | { | ||
232 | .id = 0, | ||
233 | .name = "jz4740-hwmon", | ||
234 | .num_resources = ARRAY_SIZE(jz4740_hwmon_resources), | ||
235 | .resources = jz4740_hwmon_resources, | ||
236 | .platform_data = (void *)&jz4740_adc_cells[0], | ||
237 | .data_size = sizeof(struct mfd_cell), | ||
238 | |||
239 | .enable = jz4740_adc_cell_enable, | ||
240 | .disable = jz4740_adc_cell_disable, | ||
241 | }, | ||
242 | { | ||
243 | .id = 1, | ||
244 | .name = "jz4740-battery", | ||
245 | .num_resources = ARRAY_SIZE(jz4740_battery_resources), | ||
246 | .resources = jz4740_battery_resources, | ||
247 | .platform_data = (void *)&jz4740_adc_cells[1], | ||
248 | .data_size = sizeof(struct mfd_cell), | ||
249 | |||
250 | .enable = jz4740_adc_cell_enable, | ||
251 | .disable = jz4740_adc_cell_disable, | ||
252 | }, | ||
253 | }; | ||
254 | |||
255 | static int __devinit jz4740_adc_probe(struct platform_device *pdev) | ||
256 | { | ||
257 | int ret; | ||
258 | struct jz4740_adc *adc; | ||
259 | struct resource *mem_base; | ||
260 | int irq; | ||
261 | |||
262 | adc = kmalloc(sizeof(*adc), GFP_KERNEL); | ||
263 | if (!adc) { | ||
264 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | adc->irq = platform_get_irq(pdev, 0); | ||
269 | if (adc->irq < 0) { | ||
270 | ret = adc->irq; | ||
271 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); | ||
272 | goto err_free; | ||
273 | } | ||
274 | |||
275 | adc->irq_base = platform_get_irq(pdev, 1); | ||
276 | if (adc->irq_base < 0) { | ||
277 | ret = adc->irq_base; | ||
278 | dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret); | ||
279 | goto err_free; | ||
280 | } | ||
281 | |||
282 | mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
283 | if (!mem_base) { | ||
284 | ret = -ENOENT; | ||
285 | dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); | ||
286 | goto err_free; | ||
287 | } | ||
288 | |||
289 | /* Only request the shared registers for the MFD driver */ | ||
290 | adc->mem = request_mem_region(mem_base->start, JZ_REG_ADC_STATUS, | ||
291 | pdev->name); | ||
292 | if (!adc->mem) { | ||
293 | ret = -EBUSY; | ||
294 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
295 | goto err_free; | ||
296 | } | ||
297 | |||
298 | adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem)); | ||
299 | if (!adc->base) { | ||
300 | ret = -EBUSY; | ||
301 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
302 | goto err_release_mem_region; | ||
303 | } | ||
304 | |||
305 | adc->clk = clk_get(&pdev->dev, "adc"); | ||
306 | if (IS_ERR(adc->clk)) { | ||
307 | ret = PTR_ERR(adc->clk); | ||
308 | dev_err(&pdev->dev, "Failed to get clock: %d\n", ret); | ||
309 | goto err_iounmap; | ||
310 | } | ||
311 | |||
312 | spin_lock_init(&adc->lock); | ||
313 | atomic_set(&adc->clk_ref, 0); | ||
314 | |||
315 | platform_set_drvdata(pdev, adc); | ||
316 | |||
317 | for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) { | ||
318 | set_irq_chip_data(irq, adc); | ||
319 | set_irq_chip_and_handler(irq, &jz4740_adc_irq_chip, | ||
320 | handle_level_irq); | ||
321 | } | ||
322 | |||
323 | set_irq_data(adc->irq, adc); | ||
324 | set_irq_chained_handler(adc->irq, jz4740_adc_irq_demux); | ||
325 | |||
326 | writeb(0x00, adc->base + JZ_REG_ADC_ENABLE); | ||
327 | writeb(0xff, adc->base + JZ_REG_ADC_CTRL); | ||
328 | |||
329 | ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, | ||
330 | ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base); | ||
331 | if (ret < 0) | ||
332 | goto err_clk_put; | ||
333 | |||
334 | return 0; | ||
335 | |||
336 | err_clk_put: | ||
337 | clk_put(adc->clk); | ||
338 | err_iounmap: | ||
339 | platform_set_drvdata(pdev, NULL); | ||
340 | iounmap(adc->base); | ||
341 | err_release_mem_region: | ||
342 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
343 | err_free: | ||
344 | kfree(adc); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit jz4740_adc_remove(struct platform_device *pdev) | ||
350 | { | ||
351 | struct jz4740_adc *adc = platform_get_drvdata(pdev); | ||
352 | |||
353 | mfd_remove_devices(&pdev->dev); | ||
354 | |||
355 | set_irq_data(adc->irq, NULL); | ||
356 | set_irq_chained_handler(adc->irq, NULL); | ||
357 | |||
358 | iounmap(adc->base); | ||
359 | release_mem_region(adc->mem->start, resource_size(adc->mem)); | ||
360 | |||
361 | clk_put(adc->clk); | ||
362 | |||
363 | platform_set_drvdata(pdev, NULL); | ||
364 | |||
365 | kfree(adc); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | struct platform_driver jz4740_adc_driver = { | ||
371 | .probe = jz4740_adc_probe, | ||
372 | .remove = __devexit_p(jz4740_adc_remove), | ||
373 | .driver = { | ||
374 | .name = "jz4740-adc", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | }; | ||
378 | |||
379 | static int __init jz4740_adc_init(void) | ||
380 | { | ||
381 | return platform_driver_register(&jz4740_adc_driver); | ||
382 | } | ||
383 | module_init(jz4740_adc_init); | ||
384 | |||
385 | static void __exit jz4740_adc_exit(void) | ||
386 | { | ||
387 | platform_driver_unregister(&jz4740_adc_driver); | ||
388 | } | ||
389 | module_exit(jz4740_adc_exit); | ||
390 | |||
391 | MODULE_DESCRIPTION("JZ4740 SoC ADC driver"); | ||
392 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_ALIAS("platform:jz4740-adc"); | ||
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index f621bcea3d02..04028a9ee082 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -90,6 +90,24 @@ static struct mfd_cell rtc_devs[] = { | |||
90 | }, | 90 | }, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static struct resource onkey_resources[] = { | ||
94 | { | ||
95 | .name = "max8925-onkey", | ||
96 | .start = MAX8925_IRQ_GPM_SW_3SEC, | ||
97 | .end = MAX8925_IRQ_GPM_SW_3SEC, | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static struct mfd_cell onkey_devs[] = { | ||
103 | { | ||
104 | .name = "max8925-onkey", | ||
105 | .num_resources = 1, | ||
106 | .resources = &onkey_resources[0], | ||
107 | .id = -1, | ||
108 | }, | ||
109 | }; | ||
110 | |||
93 | #define MAX8925_REG_RESOURCE(_start, _end) \ | 111 | #define MAX8925_REG_RESOURCE(_start, _end) \ |
94 | { \ | 112 | { \ |
95 | .start = MAX8925_##_start, \ | 113 | .start = MAX8925_##_start, \ |
@@ -596,6 +614,15 @@ int __devinit max8925_device_init(struct max8925_chip *chip, | |||
596 | dev_err(chip->dev, "Failed to add rtc subdev\n"); | 614 | dev_err(chip->dev, "Failed to add rtc subdev\n"); |
597 | goto out; | 615 | goto out; |
598 | } | 616 | } |
617 | |||
618 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
619 | ARRAY_SIZE(onkey_devs), | ||
620 | &onkey_resources[0], 0); | ||
621 | if (ret < 0) { | ||
622 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
623 | goto out_dev; | ||
624 | } | ||
625 | |||
599 | if (pdata && pdata->regulator[0]) { | 626 | if (pdata && pdata->regulator[0]) { |
600 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], | 627 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], |
601 | ARRAY_SIZE(regulator_devs), | 628 | ARRAY_SIZE(regulator_devs), |
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c new file mode 100644 index 000000000000..73e6f5c4efc9 --- /dev/null +++ b/drivers/mfd/max8998.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * max8698.c - mfd core driver for the Maxim 8998 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electronics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * Marek Szyprowski <m.szyprowski@samsung.com> | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/mfd/core.h> | ||
30 | #include <linux/mfd/max8998.h> | ||
31 | #include <linux/mfd/max8998-private.h> | ||
32 | |||
33 | static struct mfd_cell max8998_devs[] = { | ||
34 | { | ||
35 | .name = "max8998-pmic", | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | static int max8998_i2c_device_read(struct max8998_dev *max8998, u8 reg, u8 *dest) | ||
40 | { | ||
41 | struct i2c_client *client = max8998->i2c_client; | ||
42 | int ret; | ||
43 | |||
44 | mutex_lock(&max8998->iolock); | ||
45 | ret = i2c_smbus_read_byte_data(client, reg); | ||
46 | mutex_unlock(&max8998->iolock); | ||
47 | if (ret < 0) | ||
48 | return ret; | ||
49 | |||
50 | ret &= 0xff; | ||
51 | *dest = ret; | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int max8998_i2c_device_write(struct max8998_dev *max8998, u8 reg, u8 value) | ||
56 | { | ||
57 | struct i2c_client *client = max8998->i2c_client; | ||
58 | int ret; | ||
59 | |||
60 | mutex_lock(&max8998->iolock); | ||
61 | ret = i2c_smbus_write_byte_data(client, reg, value); | ||
62 | mutex_unlock(&max8998->iolock); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | static int max8998_i2c_device_update(struct max8998_dev *max8998, u8 reg, | ||
67 | u8 val, u8 mask) | ||
68 | { | ||
69 | struct i2c_client *client = max8998->i2c_client; | ||
70 | int ret; | ||
71 | |||
72 | mutex_lock(&max8998->iolock); | ||
73 | ret = i2c_smbus_read_byte_data(client, reg); | ||
74 | if (ret >= 0) { | ||
75 | u8 old_val = ret & 0xff; | ||
76 | u8 new_val = (val & mask) | (old_val & (~mask)); | ||
77 | ret = i2c_smbus_write_byte_data(client, reg, new_val); | ||
78 | if (ret >= 0) | ||
79 | ret = 0; | ||
80 | } | ||
81 | mutex_unlock(&max8998->iolock); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int max8998_i2c_probe(struct i2c_client *i2c, | ||
86 | const struct i2c_device_id *id) | ||
87 | { | ||
88 | struct max8998_dev *max8998; | ||
89 | int ret = 0; | ||
90 | |||
91 | max8998 = kzalloc(sizeof(struct max8998_dev), GFP_KERNEL); | ||
92 | if (max8998 == NULL) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | i2c_set_clientdata(i2c, max8998); | ||
96 | max8998->dev = &i2c->dev; | ||
97 | max8998->i2c_client = i2c; | ||
98 | max8998->dev_read = max8998_i2c_device_read; | ||
99 | max8998->dev_write = max8998_i2c_device_write; | ||
100 | max8998->dev_update = max8998_i2c_device_update; | ||
101 | mutex_init(&max8998->iolock); | ||
102 | |||
103 | ret = mfd_add_devices(max8998->dev, -1, | ||
104 | max8998_devs, ARRAY_SIZE(max8998_devs), | ||
105 | NULL, 0); | ||
106 | if (ret < 0) | ||
107 | goto err; | ||
108 | |||
109 | return ret; | ||
110 | |||
111 | err: | ||
112 | mfd_remove_devices(max8998->dev); | ||
113 | kfree(max8998); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int max8998_i2c_remove(struct i2c_client *i2c) | ||
118 | { | ||
119 | struct max8998_dev *max8998 = i2c_get_clientdata(i2c); | ||
120 | |||
121 | mfd_remove_devices(max8998->dev); | ||
122 | kfree(max8998); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static const struct i2c_device_id max8998_i2c_id[] = { | ||
128 | { "max8998", 0 }, | ||
129 | { } | ||
130 | }; | ||
131 | MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); | ||
132 | |||
133 | static struct i2c_driver max8998_i2c_driver = { | ||
134 | .driver = { | ||
135 | .name = "max8998", | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | .probe = max8998_i2c_probe, | ||
139 | .remove = max8998_i2c_remove, | ||
140 | .id_table = max8998_i2c_id, | ||
141 | }; | ||
142 | |||
143 | static int __init max8998_i2c_init(void) | ||
144 | { | ||
145 | return i2c_add_driver(&max8998_i2c_driver); | ||
146 | } | ||
147 | /* init early so consumer devices can complete system boot */ | ||
148 | subsys_initcall(max8998_i2c_init); | ||
149 | |||
150 | static void __exit max8998_i2c_exit(void) | ||
151 | { | ||
152 | i2c_del_driver(&max8998_i2c_driver); | ||
153 | } | ||
154 | module_exit(max8998_i2c_exit); | ||
155 | |||
156 | MODULE_DESCRIPTION("MAXIM 8998 multi-function core driver"); | ||
157 | MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); | ||
158 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index fecf38a4f025..6df34989c1f6 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
@@ -11,9 +11,31 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/interrupt.h> | ||
14 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
15 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
16 | #include <linux/mfd/mc13783-private.h> | 19 | #include <linux/mfd/mc13783.h> |
20 | |||
21 | struct mc13783 { | ||
22 | struct spi_device *spidev; | ||
23 | struct mutex lock; | ||
24 | int irq; | ||
25 | int flags; | ||
26 | |||
27 | irq_handler_t irqhandler[MC13783_NUM_IRQ]; | ||
28 | void *irqdata[MC13783_NUM_IRQ]; | ||
29 | |||
30 | /* XXX these should go as platformdata to the regulator subdevice */ | ||
31 | struct mc13783_regulator_init_data *regulators; | ||
32 | int num_regulators; | ||
33 | }; | ||
34 | |||
35 | #define MC13783_REG_REVISION 7 | ||
36 | #define MC13783_REG_ADC_0 43 | ||
37 | #define MC13783_REG_ADC_1 44 | ||
38 | #define MC13783_REG_ADC_2 45 | ||
17 | 39 | ||
18 | #define MC13783_IRQSTAT0 0 | 40 | #define MC13783_IRQSTAT0 0 |
19 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) | 41 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) |
@@ -226,6 +248,12 @@ int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | |||
226 | } | 248 | } |
227 | EXPORT_SYMBOL(mc13783_reg_rmw); | 249 | EXPORT_SYMBOL(mc13783_reg_rmw); |
228 | 250 | ||
251 | int mc13783_get_flags(struct mc13783 *mc13783) | ||
252 | { | ||
253 | return mc13783->flags; | ||
254 | } | ||
255 | EXPORT_SYMBOL(mc13783_get_flags); | ||
256 | |||
229 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) | 257 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) |
230 | { | 258 | { |
231 | int ret; | 259 | int ret; |
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index a3fb4bcb9889..4ba85bbdb4c1 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c | |||
@@ -128,6 +128,39 @@ | |||
128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ | 128 | #define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ |
129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ | 129 | #define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ |
130 | 130 | ||
131 | /* VCORE_CTRL1 register */ | ||
132 | #define VCORE_CTRL1_BYP_COMP (1 << 5) | ||
133 | #define VCORE_CTRL1_HW_NSW (1 << 7) | ||
134 | |||
135 | /* GPIO_CTRL register */ | ||
136 | #define GPIO_CTRL_SLOTSELEN (1 << 5) | ||
137 | #define GPIO_CTRL_SLPCTLEN (1 << 6) | ||
138 | #define GPIO1_DIR_INPUT (1 << 0) | ||
139 | #define GPIO2_DIR_INPUT (1 << 1) | ||
140 | #define GPIO3_DIR_INPUT (1 << 2) | ||
141 | |||
142 | /* MCT_CTRL1 register */ | ||
143 | #define MCT_CTRL1_S1_CMD_OD (1 << 2) | ||
144 | #define MCT_CTRL1_S2_CMD_OD (1 << 3) | ||
145 | |||
146 | /* MCT_CTRL2 register */ | ||
147 | #define MCT_CTRL2_VS2_SEL_D0 (1 << 0) | ||
148 | #define MCT_CTRL2_VS2_SEL_D1 (1 << 1) | ||
149 | #define MCT_CTRL2_S1CD_BUFEN (1 << 4) | ||
150 | #define MCT_CTRL2_S2CD_BUFEN (1 << 5) | ||
151 | #define MCT_CTRL2_S1CD_DBEN (1 << 6) | ||
152 | #define MCT_CTRL2_S2CD_BEN (1 << 7) | ||
153 | |||
154 | /* MCT_CTRL3 register */ | ||
155 | #define MCT_CTRL3_SLOT1_EN (1 << 0) | ||
156 | #define MCT_CTRL3_SLOT2_EN (1 << 1) | ||
157 | #define MCT_CTRL3_S1_AUTO_EN (1 << 2) | ||
158 | #define MCT_CTRL3_S2_AUTO_EN (1 << 3) | ||
159 | |||
160 | /* MCT_PIN_ST register */ | ||
161 | #define MCT_PIN_ST_S1_CD_ST (1 << 0) | ||
162 | #define MCT_PIN_ST_S2_CD_ST (1 << 1) | ||
163 | |||
131 | static void menelaus_work(struct work_struct *_menelaus); | 164 | static void menelaus_work(struct work_struct *_menelaus); |
132 | 165 | ||
133 | struct menelaus_chip { | 166 | struct menelaus_chip { |
@@ -249,10 +282,10 @@ static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw) | |||
249 | return; | 282 | return; |
250 | 283 | ||
251 | if (!(reg & 0x1)) | 284 | if (!(reg & 0x1)) |
252 | card_mask |= (1 << 0); | 285 | card_mask |= MCT_PIN_ST_S1_CD_ST; |
253 | 286 | ||
254 | if (!(reg & 0x2)) | 287 | if (!(reg & 0x2)) |
255 | card_mask |= (1 << 1); | 288 | card_mask |= MCT_PIN_ST_S2_CD_ST; |
256 | 289 | ||
257 | if (menelaus_hw->mmc_callback) | 290 | if (menelaus_hw->mmc_callback) |
258 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, | 291 | menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, |
@@ -277,14 +310,14 @@ int menelaus_set_mmc_opendrain(int slot, int enable) | |||
277 | val = ret; | 310 | val = ret; |
278 | if (slot == 1) { | 311 | if (slot == 1) { |
279 | if (enable) | 312 | if (enable) |
280 | val |= 1 << 2; | 313 | val |= MCT_CTRL1_S1_CMD_OD; |
281 | else | 314 | else |
282 | val &= ~(1 << 2); | 315 | val &= ~MCT_CTRL1_S1_CMD_OD; |
283 | } else { | 316 | } else { |
284 | if (enable) | 317 | if (enable) |
285 | val |= 1 << 3; | 318 | val |= MCT_CTRL1_S2_CMD_OD; |
286 | else | 319 | else |
287 | val &= ~(1 << 3); | 320 | val &= ~MCT_CTRL1_S2_CMD_OD; |
288 | } | 321 | } |
289 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); | 322 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); |
290 | mutex_unlock(&the_menelaus->lock); | 323 | mutex_unlock(&the_menelaus->lock); |
@@ -301,11 +334,11 @@ int menelaus_set_slot_sel(int enable) | |||
301 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 334 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
302 | if (ret < 0) | 335 | if (ret < 0) |
303 | goto out; | 336 | goto out; |
304 | ret |= 0x02; | 337 | ret |= GPIO2_DIR_INPUT; |
305 | if (enable) | 338 | if (enable) |
306 | ret |= 1 << 5; | 339 | ret |= GPIO_CTRL_SLOTSELEN; |
307 | else | 340 | else |
308 | ret &= ~(1 << 5); | 341 | ret &= ~GPIO_CTRL_SLOTSELEN; |
309 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); | 342 | ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); |
310 | out: | 343 | out: |
311 | mutex_unlock(&the_menelaus->lock); | 344 | mutex_unlock(&the_menelaus->lock); |
@@ -330,14 +363,14 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
330 | val = ret; | 363 | val = ret; |
331 | if (slot == 1) { | 364 | if (slot == 1) { |
332 | if (cd_en) | 365 | if (cd_en) |
333 | val |= (1 << 4) | (1 << 6); | 366 | val |= MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN; |
334 | else | 367 | else |
335 | val &= ~((1 << 4) | (1 << 6)); | 368 | val &= ~(MCT_CTRL2_S1CD_BUFEN | MCT_CTRL2_S1CD_DBEN); |
336 | } else { | 369 | } else { |
337 | if (cd_en) | 370 | if (cd_en) |
338 | val |= (1 << 5) | (1 << 7); | 371 | val |= MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN; |
339 | else | 372 | else |
340 | val &= ~((1 << 5) | (1 << 7)); | 373 | val &= ~(MCT_CTRL2_S2CD_BUFEN | MCT_CTRL2_S2CD_BEN); |
341 | } | 374 | } |
342 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); | 375 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); |
343 | if (ret < 0) | 376 | if (ret < 0) |
@@ -349,25 +382,25 @@ int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) | |||
349 | val = ret; | 382 | val = ret; |
350 | if (slot == 1) { | 383 | if (slot == 1) { |
351 | if (enable) | 384 | if (enable) |
352 | val |= 1 << 0; | 385 | val |= MCT_CTRL3_SLOT1_EN; |
353 | else | 386 | else |
354 | val &= ~(1 << 0); | 387 | val &= ~MCT_CTRL3_SLOT1_EN; |
355 | } else { | 388 | } else { |
356 | int b; | 389 | int b; |
357 | 390 | ||
358 | if (enable) | 391 | if (enable) |
359 | ret |= 1 << 1; | 392 | val |= MCT_CTRL3_SLOT2_EN; |
360 | else | 393 | else |
361 | ret &= ~(1 << 1); | 394 | val &= ~MCT_CTRL3_SLOT2_EN; |
362 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); | 395 | b = menelaus_read_reg(MENELAUS_MCT_CTRL2); |
363 | b &= ~0x03; | 396 | b &= ~(MCT_CTRL2_VS2_SEL_D0 | MCT_CTRL2_VS2_SEL_D1); |
364 | b |= power; | 397 | b |= power; |
365 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); | 398 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); |
366 | if (ret < 0) | 399 | if (ret < 0) |
367 | goto out; | 400 | goto out; |
368 | } | 401 | } |
369 | /* Disable autonomous shutdown */ | 402 | /* Disable autonomous shutdown */ |
370 | val &= ~(0x03 << 2); | 403 | val &= ~(MCT_CTRL3_S1_AUTO_EN | MCT_CTRL3_S2_AUTO_EN); |
371 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); | 404 | ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); |
372 | out: | 405 | out: |
373 | mutex_unlock(&the_menelaus->lock); | 406 | mutex_unlock(&the_menelaus->lock); |
@@ -552,7 +585,7 @@ int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV) | |||
552 | if (!the_menelaus->vcore_hw_mode) { | 585 | if (!the_menelaus->vcore_hw_mode) { |
553 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); | 586 | val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); |
554 | /* HW mode, turn OFF byte comparator */ | 587 | /* HW mode, turn OFF byte comparator */ |
555 | val |= ((1 << 7) | (1 << 5)); | 588 | val |= (VCORE_CTRL1_HW_NSW | VCORE_CTRL1_BYP_COMP); |
556 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); | 589 | ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); |
557 | the_menelaus->vcore_hw_mode = 1; | 590 | the_menelaus->vcore_hw_mode = 1; |
558 | } | 591 | } |
@@ -749,7 +782,7 @@ int menelaus_set_regulator_sleep(int enable, u32 val) | |||
749 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); | 782 | ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); |
750 | if (ret < 0) | 783 | if (ret < 0) |
751 | goto out; | 784 | goto out; |
752 | t = ((1 << 6) | 0x04); | 785 | t = (GPIO_CTRL_SLPCTLEN | GPIO3_DIR_INPUT); |
753 | if (enable) | 786 | if (enable) |
754 | ret |= t; | 787 | ret |= t; |
755 | else | 788 | else |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 7dd76bceaae8..1823a57b7d8f 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -70,7 +70,9 @@ static int mfd_add_device(struct device *parent, int id, | |||
70 | goto fail_res; | 70 | goto fail_res; |
71 | } | 71 | } |
72 | 72 | ||
73 | platform_device_add_resources(pdev, res, cell->num_resources); | 73 | ret = platform_device_add_resources(pdev, res, cell->num_resources); |
74 | if (ret) | ||
75 | goto fail_res; | ||
74 | 76 | ||
75 | ret = platform_device_add(pdev); | 77 | ret = platform_device_add(pdev); |
76 | if (ret) | 78 | if (ret) |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c new file mode 100644 index 000000000000..0754c5e91995 --- /dev/null +++ b/drivers/mfd/stmpe.c | |||
@@ -0,0 +1,985 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mfd/core.h> | ||
15 | #include <linux/mfd/stmpe.h> | ||
16 | #include "stmpe.h" | ||
17 | |||
18 | static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
19 | { | ||
20 | return stmpe->variant->enable(stmpe, blocks, true); | ||
21 | } | ||
22 | |||
23 | static int __stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
24 | { | ||
25 | return stmpe->variant->enable(stmpe, blocks, false); | ||
26 | } | ||
27 | |||
28 | static int __stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
29 | { | ||
30 | int ret; | ||
31 | |||
32 | ret = i2c_smbus_read_byte_data(stmpe->i2c, reg); | ||
33 | if (ret < 0) | ||
34 | dev_err(stmpe->dev, "failed to read reg %#x: %d\n", | ||
35 | reg, ret); | ||
36 | |||
37 | dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret); | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
43 | { | ||
44 | int ret; | ||
45 | |||
46 | dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val); | ||
47 | |||
48 | ret = i2c_smbus_write_byte_data(stmpe->i2c, reg, val); | ||
49 | if (ret < 0) | ||
50 | dev_err(stmpe->dev, "failed to write reg %#x: %d\n", | ||
51 | reg, ret); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | static int __stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
57 | { | ||
58 | int ret; | ||
59 | |||
60 | ret = __stmpe_reg_read(stmpe, reg); | ||
61 | if (ret < 0) | ||
62 | return ret; | ||
63 | |||
64 | ret &= ~mask; | ||
65 | ret |= val; | ||
66 | |||
67 | return __stmpe_reg_write(stmpe, reg, ret); | ||
68 | } | ||
69 | |||
70 | static int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, | ||
71 | u8 *values) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = i2c_smbus_read_i2c_block_data(stmpe->i2c, reg, length, values); | ||
76 | if (ret < 0) | ||
77 | dev_err(stmpe->dev, "failed to read regs %#x: %d\n", | ||
78 | reg, ret); | ||
79 | |||
80 | dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret); | ||
81 | stmpe_dump_bytes("stmpe rd: ", values, length); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
87 | const u8 *values) | ||
88 | { | ||
89 | int ret; | ||
90 | |||
91 | dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length); | ||
92 | stmpe_dump_bytes("stmpe wr: ", values, length); | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(stmpe->i2c, reg, length, | ||
95 | values); | ||
96 | if (ret < 0) | ||
97 | dev_err(stmpe->dev, "failed to write regs %#x: %d\n", | ||
98 | reg, ret); | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * stmpe_enable - enable blocks on an STMPE device | ||
105 | * @stmpe: Device to work on | ||
106 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
107 | */ | ||
108 | int stmpe_enable(struct stmpe *stmpe, unsigned int blocks) | ||
109 | { | ||
110 | int ret; | ||
111 | |||
112 | mutex_lock(&stmpe->lock); | ||
113 | ret = __stmpe_enable(stmpe, blocks); | ||
114 | mutex_unlock(&stmpe->lock); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | EXPORT_SYMBOL_GPL(stmpe_enable); | ||
119 | |||
120 | /** | ||
121 | * stmpe_disable - disable blocks on an STMPE device | ||
122 | * @stmpe: Device to work on | ||
123 | * @blocks: Mask of blocks (enum stmpe_block values) to enable | ||
124 | */ | ||
125 | int stmpe_disable(struct stmpe *stmpe, unsigned int blocks) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | mutex_lock(&stmpe->lock); | ||
130 | ret = __stmpe_disable(stmpe, blocks); | ||
131 | mutex_unlock(&stmpe->lock); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(stmpe_disable); | ||
136 | |||
137 | /** | ||
138 | * stmpe_reg_read() - read a single STMPE register | ||
139 | * @stmpe: Device to read from | ||
140 | * @reg: Register to read | ||
141 | */ | ||
142 | int stmpe_reg_read(struct stmpe *stmpe, u8 reg) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | mutex_lock(&stmpe->lock); | ||
147 | ret = __stmpe_reg_read(stmpe, reg); | ||
148 | mutex_unlock(&stmpe->lock); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | EXPORT_SYMBOL_GPL(stmpe_reg_read); | ||
153 | |||
154 | /** | ||
155 | * stmpe_reg_write() - write a single STMPE register | ||
156 | * @stmpe: Device to write to | ||
157 | * @reg: Register to write | ||
158 | * @val: Value to write | ||
159 | */ | ||
160 | int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | mutex_lock(&stmpe->lock); | ||
165 | ret = __stmpe_reg_write(stmpe, reg, val); | ||
166 | mutex_unlock(&stmpe->lock); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(stmpe_reg_write); | ||
171 | |||
172 | /** | ||
173 | * stmpe_set_bits() - set the value of a bitfield in a STMPE register | ||
174 | * @stmpe: Device to write to | ||
175 | * @reg: Register to write | ||
176 | * @mask: Mask of bits to set | ||
177 | * @val: Value to set | ||
178 | */ | ||
179 | int stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) | ||
180 | { | ||
181 | int ret; | ||
182 | |||
183 | mutex_lock(&stmpe->lock); | ||
184 | ret = __stmpe_set_bits(stmpe, reg, mask, val); | ||
185 | mutex_unlock(&stmpe->lock); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(stmpe_set_bits); | ||
190 | |||
191 | /** | ||
192 | * stmpe_block_read() - read multiple STMPE registers | ||
193 | * @stmpe: Device to read from | ||
194 | * @reg: First register | ||
195 | * @length: Number of registers | ||
196 | * @values: Buffer to write to | ||
197 | */ | ||
198 | int stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values) | ||
199 | { | ||
200 | int ret; | ||
201 | |||
202 | mutex_lock(&stmpe->lock); | ||
203 | ret = __stmpe_block_read(stmpe, reg, length, values); | ||
204 | mutex_unlock(&stmpe->lock); | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(stmpe_block_read); | ||
209 | |||
210 | /** | ||
211 | * stmpe_block_write() - write multiple STMPE registers | ||
212 | * @stmpe: Device to write to | ||
213 | * @reg: First register | ||
214 | * @length: Number of registers | ||
215 | * @values: Values to write | ||
216 | */ | ||
217 | int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, | ||
218 | const u8 *values) | ||
219 | { | ||
220 | int ret; | ||
221 | |||
222 | mutex_lock(&stmpe->lock); | ||
223 | ret = __stmpe_block_write(stmpe, reg, length, values); | ||
224 | mutex_unlock(&stmpe->lock); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(stmpe_block_write); | ||
229 | |||
230 | /** | ||
231 | * stmpe_set_altfunc: set the alternate function for STMPE pins | ||
232 | * @stmpe: Device to configure | ||
233 | * @pins: Bitmask of pins to affect | ||
234 | * @block: block to enable alternate functions for | ||
235 | * | ||
236 | * @pins is assumed to have a bit set for each of the bits whose alternate | ||
237 | * function is to be changed, numbered according to the GPIOXY numbers. | ||
238 | * | ||
239 | * If the GPIO module is not enabled, this function automatically enables it in | ||
240 | * order to perform the change. | ||
241 | */ | ||
242 | int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block) | ||
243 | { | ||
244 | struct stmpe_variant_info *variant = stmpe->variant; | ||
245 | u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; | ||
246 | int af_bits = variant->af_bits; | ||
247 | int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); | ||
248 | int afperreg = 8 / af_bits; | ||
249 | int mask = (1 << af_bits) - 1; | ||
250 | u8 regs[numregs]; | ||
251 | int af; | ||
252 | int ret; | ||
253 | |||
254 | mutex_lock(&stmpe->lock); | ||
255 | |||
256 | ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); | ||
257 | if (ret < 0) | ||
258 | goto out; | ||
259 | |||
260 | ret = __stmpe_block_read(stmpe, regaddr, numregs, regs); | ||
261 | if (ret < 0) | ||
262 | goto out; | ||
263 | |||
264 | af = variant->get_altfunc(stmpe, block); | ||
265 | |||
266 | while (pins) { | ||
267 | int pin = __ffs(pins); | ||
268 | int regoffset = numregs - (pin / afperreg) - 1; | ||
269 | int pos = (pin % afperreg) * (8 / afperreg); | ||
270 | |||
271 | regs[regoffset] &= ~(mask << pos); | ||
272 | regs[regoffset] |= af << pos; | ||
273 | |||
274 | pins &= ~(1 << pin); | ||
275 | } | ||
276 | |||
277 | ret = __stmpe_block_write(stmpe, regaddr, numregs, regs); | ||
278 | |||
279 | out: | ||
280 | mutex_unlock(&stmpe->lock); | ||
281 | return ret; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(stmpe_set_altfunc); | ||
284 | |||
285 | /* | ||
286 | * GPIO (all variants) | ||
287 | */ | ||
288 | |||
289 | static struct resource stmpe_gpio_resources[] = { | ||
290 | /* Start and end filled dynamically */ | ||
291 | { | ||
292 | .flags = IORESOURCE_IRQ, | ||
293 | }, | ||
294 | }; | ||
295 | |||
296 | static struct mfd_cell stmpe_gpio_cell = { | ||
297 | .name = "stmpe-gpio", | ||
298 | .resources = stmpe_gpio_resources, | ||
299 | .num_resources = ARRAY_SIZE(stmpe_gpio_resources), | ||
300 | }; | ||
301 | |||
302 | /* | ||
303 | * Keypad (1601, 2401, 2403) | ||
304 | */ | ||
305 | |||
306 | static struct resource stmpe_keypad_resources[] = { | ||
307 | { | ||
308 | .name = "KEYPAD", | ||
309 | .start = 0, | ||
310 | .end = 0, | ||
311 | .flags = IORESOURCE_IRQ, | ||
312 | }, | ||
313 | { | ||
314 | .name = "KEYPAD_OVER", | ||
315 | .start = 1, | ||
316 | .end = 1, | ||
317 | .flags = IORESOURCE_IRQ, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static struct mfd_cell stmpe_keypad_cell = { | ||
322 | .name = "stmpe-keypad", | ||
323 | .resources = stmpe_keypad_resources, | ||
324 | .num_resources = ARRAY_SIZE(stmpe_keypad_resources), | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | * Touchscreen (STMPE811) | ||
329 | */ | ||
330 | |||
331 | static struct resource stmpe_ts_resources[] = { | ||
332 | { | ||
333 | .name = "TOUCH_DET", | ||
334 | .start = 0, | ||
335 | .end = 0, | ||
336 | .flags = IORESOURCE_IRQ, | ||
337 | }, | ||
338 | { | ||
339 | .name = "FIFO_TH", | ||
340 | .start = 1, | ||
341 | .end = 1, | ||
342 | .flags = IORESOURCE_IRQ, | ||
343 | }, | ||
344 | }; | ||
345 | |||
346 | static struct mfd_cell stmpe_ts_cell = { | ||
347 | .name = "stmpe-ts", | ||
348 | .resources = stmpe_ts_resources, | ||
349 | .num_resources = ARRAY_SIZE(stmpe_ts_resources), | ||
350 | }; | ||
351 | |||
352 | /* | ||
353 | * STMPE811 | ||
354 | */ | ||
355 | |||
356 | static const u8 stmpe811_regs[] = { | ||
357 | [STMPE_IDX_CHIP_ID] = STMPE811_REG_CHIP_ID, | ||
358 | [STMPE_IDX_ICR_LSB] = STMPE811_REG_INT_CTRL, | ||
359 | [STMPE_IDX_IER_LSB] = STMPE811_REG_INT_EN, | ||
360 | [STMPE_IDX_ISR_MSB] = STMPE811_REG_INT_STA, | ||
361 | [STMPE_IDX_GPMR_LSB] = STMPE811_REG_GPIO_MP_STA, | ||
362 | [STMPE_IDX_GPSR_LSB] = STMPE811_REG_GPIO_SET_PIN, | ||
363 | [STMPE_IDX_GPCR_LSB] = STMPE811_REG_GPIO_CLR_PIN, | ||
364 | [STMPE_IDX_GPDR_LSB] = STMPE811_REG_GPIO_DIR, | ||
365 | [STMPE_IDX_GPRER_LSB] = STMPE811_REG_GPIO_RE, | ||
366 | [STMPE_IDX_GPFER_LSB] = STMPE811_REG_GPIO_FE, | ||
367 | [STMPE_IDX_GPAFR_U_MSB] = STMPE811_REG_GPIO_AF, | ||
368 | [STMPE_IDX_IEGPIOR_LSB] = STMPE811_REG_GPIO_INT_EN, | ||
369 | [STMPE_IDX_ISGPIOR_MSB] = STMPE811_REG_GPIO_INT_STA, | ||
370 | [STMPE_IDX_GPEDR_MSB] = STMPE811_REG_GPIO_ED, | ||
371 | }; | ||
372 | |||
373 | static struct stmpe_variant_block stmpe811_blocks[] = { | ||
374 | { | ||
375 | .cell = &stmpe_gpio_cell, | ||
376 | .irq = STMPE811_IRQ_GPIOC, | ||
377 | .block = STMPE_BLOCK_GPIO, | ||
378 | }, | ||
379 | { | ||
380 | .cell = &stmpe_ts_cell, | ||
381 | .irq = STMPE811_IRQ_TOUCH_DET, | ||
382 | .block = STMPE_BLOCK_TOUCHSCREEN, | ||
383 | }, | ||
384 | }; | ||
385 | |||
386 | static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, | ||
387 | bool enable) | ||
388 | { | ||
389 | unsigned int mask = 0; | ||
390 | |||
391 | if (blocks & STMPE_BLOCK_GPIO) | ||
392 | mask |= STMPE811_SYS_CTRL2_GPIO_OFF; | ||
393 | |||
394 | if (blocks & STMPE_BLOCK_ADC) | ||
395 | mask |= STMPE811_SYS_CTRL2_ADC_OFF; | ||
396 | |||
397 | if (blocks & STMPE_BLOCK_TOUCHSCREEN) | ||
398 | mask |= STMPE811_SYS_CTRL2_TSC_OFF; | ||
399 | |||
400 | return __stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask, | ||
401 | enable ? 0 : mask); | ||
402 | } | ||
403 | |||
404 | static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
405 | { | ||
406 | /* 0 for touchscreen, 1 for GPIO */ | ||
407 | return block != STMPE_BLOCK_TOUCHSCREEN; | ||
408 | } | ||
409 | |||
410 | static struct stmpe_variant_info stmpe811 = { | ||
411 | .name = "stmpe811", | ||
412 | .id_val = 0x0811, | ||
413 | .id_mask = 0xffff, | ||
414 | .num_gpios = 8, | ||
415 | .af_bits = 1, | ||
416 | .regs = stmpe811_regs, | ||
417 | .blocks = stmpe811_blocks, | ||
418 | .num_blocks = ARRAY_SIZE(stmpe811_blocks), | ||
419 | .num_irqs = STMPE811_NR_INTERNAL_IRQS, | ||
420 | .enable = stmpe811_enable, | ||
421 | .get_altfunc = stmpe811_get_altfunc, | ||
422 | }; | ||
423 | |||
424 | /* | ||
425 | * STMPE1601 | ||
426 | */ | ||
427 | |||
428 | static const u8 stmpe1601_regs[] = { | ||
429 | [STMPE_IDX_CHIP_ID] = STMPE1601_REG_CHIP_ID, | ||
430 | [STMPE_IDX_ICR_LSB] = STMPE1601_REG_ICR_LSB, | ||
431 | [STMPE_IDX_IER_LSB] = STMPE1601_REG_IER_LSB, | ||
432 | [STMPE_IDX_ISR_MSB] = STMPE1601_REG_ISR_MSB, | ||
433 | [STMPE_IDX_GPMR_LSB] = STMPE1601_REG_GPIO_MP_LSB, | ||
434 | [STMPE_IDX_GPSR_LSB] = STMPE1601_REG_GPIO_SET_LSB, | ||
435 | [STMPE_IDX_GPCR_LSB] = STMPE1601_REG_GPIO_CLR_LSB, | ||
436 | [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, | ||
437 | [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, | ||
438 | [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, | ||
439 | [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, | ||
440 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, | ||
441 | [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, | ||
442 | [STMPE_IDX_GPEDR_MSB] = STMPE1601_REG_GPIO_ED_MSB, | ||
443 | }; | ||
444 | |||
445 | static struct stmpe_variant_block stmpe1601_blocks[] = { | ||
446 | { | ||
447 | .cell = &stmpe_gpio_cell, | ||
448 | .irq = STMPE24XX_IRQ_GPIOC, | ||
449 | .block = STMPE_BLOCK_GPIO, | ||
450 | }, | ||
451 | { | ||
452 | .cell = &stmpe_keypad_cell, | ||
453 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
454 | .block = STMPE_BLOCK_KEYPAD, | ||
455 | }, | ||
456 | }; | ||
457 | |||
458 | /* supported autosleep timeout delay (in msecs) */ | ||
459 | static const int stmpe_autosleep_delay[] = { | ||
460 | 4, 16, 32, 64, 128, 256, 512, 1024, | ||
461 | }; | ||
462 | |||
463 | static int stmpe_round_timeout(int timeout) | ||
464 | { | ||
465 | int i; | ||
466 | |||
467 | for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) { | ||
468 | if (stmpe_autosleep_delay[i] >= timeout) | ||
469 | return i; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * requests for delays longer than supported should not return the | ||
474 | * longest supported delay | ||
475 | */ | ||
476 | return -EINVAL; | ||
477 | } | ||
478 | |||
479 | static int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | if (!stmpe->variant->enable_autosleep) | ||
484 | return -ENOSYS; | ||
485 | |||
486 | mutex_lock(&stmpe->lock); | ||
487 | ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout); | ||
488 | mutex_unlock(&stmpe->lock); | ||
489 | |||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * Both stmpe 1601/2403 support same layout for autosleep | ||
495 | */ | ||
496 | static int stmpe1601_autosleep(struct stmpe *stmpe, | ||
497 | int autosleep_timeout) | ||
498 | { | ||
499 | int ret, timeout; | ||
500 | |||
501 | /* choose the best available timeout */ | ||
502 | timeout = stmpe_round_timeout(autosleep_timeout); | ||
503 | if (timeout < 0) { | ||
504 | dev_err(stmpe->dev, "invalid timeout\n"); | ||
505 | return timeout; | ||
506 | } | ||
507 | |||
508 | ret = __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
509 | STMPE1601_AUTOSLEEP_TIMEOUT_MASK, | ||
510 | timeout); | ||
511 | if (ret < 0) | ||
512 | return ret; | ||
513 | |||
514 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL2, | ||
515 | STPME1601_AUTOSLEEP_ENABLE, | ||
516 | STPME1601_AUTOSLEEP_ENABLE); | ||
517 | } | ||
518 | |||
519 | static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks, | ||
520 | bool enable) | ||
521 | { | ||
522 | unsigned int mask = 0; | ||
523 | |||
524 | if (blocks & STMPE_BLOCK_GPIO) | ||
525 | mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO; | ||
526 | |||
527 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
528 | mask |= STMPE1601_SYS_CTRL_ENABLE_KPC; | ||
529 | |||
530 | return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask, | ||
531 | enable ? mask : 0); | ||
532 | } | ||
533 | |||
534 | static int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
535 | { | ||
536 | switch (block) { | ||
537 | case STMPE_BLOCK_PWM: | ||
538 | return 2; | ||
539 | |||
540 | case STMPE_BLOCK_KEYPAD: | ||
541 | return 1; | ||
542 | |||
543 | case STMPE_BLOCK_GPIO: | ||
544 | default: | ||
545 | return 0; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static struct stmpe_variant_info stmpe1601 = { | ||
550 | .name = "stmpe1601", | ||
551 | .id_val = 0x0210, | ||
552 | .id_mask = 0xfff0, /* at least 0x0210 and 0x0212 */ | ||
553 | .num_gpios = 16, | ||
554 | .af_bits = 2, | ||
555 | .regs = stmpe1601_regs, | ||
556 | .blocks = stmpe1601_blocks, | ||
557 | .num_blocks = ARRAY_SIZE(stmpe1601_blocks), | ||
558 | .num_irqs = STMPE1601_NR_INTERNAL_IRQS, | ||
559 | .enable = stmpe1601_enable, | ||
560 | .get_altfunc = stmpe1601_get_altfunc, | ||
561 | .enable_autosleep = stmpe1601_autosleep, | ||
562 | }; | ||
563 | |||
564 | /* | ||
565 | * STMPE24XX | ||
566 | */ | ||
567 | |||
568 | static const u8 stmpe24xx_regs[] = { | ||
569 | [STMPE_IDX_CHIP_ID] = STMPE24XX_REG_CHIP_ID, | ||
570 | [STMPE_IDX_ICR_LSB] = STMPE24XX_REG_ICR_LSB, | ||
571 | [STMPE_IDX_IER_LSB] = STMPE24XX_REG_IER_LSB, | ||
572 | [STMPE_IDX_ISR_MSB] = STMPE24XX_REG_ISR_MSB, | ||
573 | [STMPE_IDX_GPMR_LSB] = STMPE24XX_REG_GPMR_LSB, | ||
574 | [STMPE_IDX_GPSR_LSB] = STMPE24XX_REG_GPSR_LSB, | ||
575 | [STMPE_IDX_GPCR_LSB] = STMPE24XX_REG_GPCR_LSB, | ||
576 | [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, | ||
577 | [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, | ||
578 | [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, | ||
579 | [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, | ||
580 | [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, | ||
581 | [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, | ||
582 | [STMPE_IDX_GPEDR_MSB] = STMPE24XX_REG_GPEDR_MSB, | ||
583 | }; | ||
584 | |||
585 | static struct stmpe_variant_block stmpe24xx_blocks[] = { | ||
586 | { | ||
587 | .cell = &stmpe_gpio_cell, | ||
588 | .irq = STMPE24XX_IRQ_GPIOC, | ||
589 | .block = STMPE_BLOCK_GPIO, | ||
590 | }, | ||
591 | { | ||
592 | .cell = &stmpe_keypad_cell, | ||
593 | .irq = STMPE24XX_IRQ_KEYPAD, | ||
594 | .block = STMPE_BLOCK_KEYPAD, | ||
595 | }, | ||
596 | }; | ||
597 | |||
598 | static int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks, | ||
599 | bool enable) | ||
600 | { | ||
601 | unsigned int mask = 0; | ||
602 | |||
603 | if (blocks & STMPE_BLOCK_GPIO) | ||
604 | mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO; | ||
605 | |||
606 | if (blocks & STMPE_BLOCK_KEYPAD) | ||
607 | mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC; | ||
608 | |||
609 | return __stmpe_set_bits(stmpe, STMPE24XX_REG_SYS_CTRL, mask, | ||
610 | enable ? mask : 0); | ||
611 | } | ||
612 | |||
613 | static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) | ||
614 | { | ||
615 | switch (block) { | ||
616 | case STMPE_BLOCK_ROTATOR: | ||
617 | return 2; | ||
618 | |||
619 | case STMPE_BLOCK_KEYPAD: | ||
620 | return 1; | ||
621 | |||
622 | case STMPE_BLOCK_GPIO: | ||
623 | default: | ||
624 | return 0; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | static struct stmpe_variant_info stmpe2401 = { | ||
629 | .name = "stmpe2401", | ||
630 | .id_val = 0x0101, | ||
631 | .id_mask = 0xffff, | ||
632 | .num_gpios = 24, | ||
633 | .af_bits = 2, | ||
634 | .regs = stmpe24xx_regs, | ||
635 | .blocks = stmpe24xx_blocks, | ||
636 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
637 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
638 | .enable = stmpe24xx_enable, | ||
639 | .get_altfunc = stmpe24xx_get_altfunc, | ||
640 | }; | ||
641 | |||
642 | static struct stmpe_variant_info stmpe2403 = { | ||
643 | .name = "stmpe2403", | ||
644 | .id_val = 0x0120, | ||
645 | .id_mask = 0xffff, | ||
646 | .num_gpios = 24, | ||
647 | .af_bits = 2, | ||
648 | .regs = stmpe24xx_regs, | ||
649 | .blocks = stmpe24xx_blocks, | ||
650 | .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), | ||
651 | .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, | ||
652 | .enable = stmpe24xx_enable, | ||
653 | .get_altfunc = stmpe24xx_get_altfunc, | ||
654 | .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ | ||
655 | }; | ||
656 | |||
657 | static struct stmpe_variant_info *stmpe_variant_info[] = { | ||
658 | [STMPE811] = &stmpe811, | ||
659 | [STMPE1601] = &stmpe1601, | ||
660 | [STMPE2401] = &stmpe2401, | ||
661 | [STMPE2403] = &stmpe2403, | ||
662 | }; | ||
663 | |||
664 | static irqreturn_t stmpe_irq(int irq, void *data) | ||
665 | { | ||
666 | struct stmpe *stmpe = data; | ||
667 | struct stmpe_variant_info *variant = stmpe->variant; | ||
668 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
669 | u8 israddr = stmpe->regs[STMPE_IDX_ISR_MSB]; | ||
670 | u8 isr[num]; | ||
671 | int ret; | ||
672 | int i; | ||
673 | |||
674 | ret = stmpe_block_read(stmpe, israddr, num, isr); | ||
675 | if (ret < 0) | ||
676 | return IRQ_NONE; | ||
677 | |||
678 | for (i = 0; i < num; i++) { | ||
679 | int bank = num - i - 1; | ||
680 | u8 status = isr[i]; | ||
681 | u8 clear; | ||
682 | |||
683 | status &= stmpe->ier[bank]; | ||
684 | if (!status) | ||
685 | continue; | ||
686 | |||
687 | clear = status; | ||
688 | while (status) { | ||
689 | int bit = __ffs(status); | ||
690 | int line = bank * 8 + bit; | ||
691 | |||
692 | handle_nested_irq(stmpe->irq_base + line); | ||
693 | status &= ~(1 << bit); | ||
694 | } | ||
695 | |||
696 | stmpe_reg_write(stmpe, israddr + i, clear); | ||
697 | } | ||
698 | |||
699 | return IRQ_HANDLED; | ||
700 | } | ||
701 | |||
702 | static void stmpe_irq_lock(unsigned int irq) | ||
703 | { | ||
704 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
705 | |||
706 | mutex_lock(&stmpe->irq_lock); | ||
707 | } | ||
708 | |||
709 | static void stmpe_irq_sync_unlock(unsigned int irq) | ||
710 | { | ||
711 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
712 | struct stmpe_variant_info *variant = stmpe->variant; | ||
713 | int num = DIV_ROUND_UP(variant->num_irqs, 8); | ||
714 | int i; | ||
715 | |||
716 | for (i = 0; i < num; i++) { | ||
717 | u8 new = stmpe->ier[i]; | ||
718 | u8 old = stmpe->oldier[i]; | ||
719 | |||
720 | if (new == old) | ||
721 | continue; | ||
722 | |||
723 | stmpe->oldier[i] = new; | ||
724 | stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB] - i, new); | ||
725 | } | ||
726 | |||
727 | mutex_unlock(&stmpe->irq_lock); | ||
728 | } | ||
729 | |||
730 | static void stmpe_irq_mask(unsigned int irq) | ||
731 | { | ||
732 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
733 | int offset = irq - stmpe->irq_base; | ||
734 | int regoffset = offset / 8; | ||
735 | int mask = 1 << (offset % 8); | ||
736 | |||
737 | stmpe->ier[regoffset] &= ~mask; | ||
738 | } | ||
739 | |||
740 | static void stmpe_irq_unmask(unsigned int irq) | ||
741 | { | ||
742 | struct stmpe *stmpe = get_irq_chip_data(irq); | ||
743 | int offset = irq - stmpe->irq_base; | ||
744 | int regoffset = offset / 8; | ||
745 | int mask = 1 << (offset % 8); | ||
746 | |||
747 | stmpe->ier[regoffset] |= mask; | ||
748 | } | ||
749 | |||
750 | static struct irq_chip stmpe_irq_chip = { | ||
751 | .name = "stmpe", | ||
752 | .bus_lock = stmpe_irq_lock, | ||
753 | .bus_sync_unlock = stmpe_irq_sync_unlock, | ||
754 | .mask = stmpe_irq_mask, | ||
755 | .unmask = stmpe_irq_unmask, | ||
756 | }; | ||
757 | |||
758 | static int __devinit stmpe_irq_init(struct stmpe *stmpe) | ||
759 | { | ||
760 | int num_irqs = stmpe->variant->num_irqs; | ||
761 | int base = stmpe->irq_base; | ||
762 | int irq; | ||
763 | |||
764 | for (irq = base; irq < base + num_irqs; irq++) { | ||
765 | set_irq_chip_data(irq, stmpe); | ||
766 | set_irq_chip_and_handler(irq, &stmpe_irq_chip, | ||
767 | handle_edge_irq); | ||
768 | set_irq_nested_thread(irq, 1); | ||
769 | #ifdef CONFIG_ARM | ||
770 | set_irq_flags(irq, IRQF_VALID); | ||
771 | #else | ||
772 | set_irq_noprobe(irq); | ||
773 | #endif | ||
774 | } | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static void stmpe_irq_remove(struct stmpe *stmpe) | ||
780 | { | ||
781 | int num_irqs = stmpe->variant->num_irqs; | ||
782 | int base = stmpe->irq_base; | ||
783 | int irq; | ||
784 | |||
785 | for (irq = base; irq < base + num_irqs; irq++) { | ||
786 | #ifdef CONFIG_ARM | ||
787 | set_irq_flags(irq, 0); | ||
788 | #endif | ||
789 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
790 | set_irq_chip_data(irq, NULL); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | static int __devinit stmpe_chip_init(struct stmpe *stmpe) | ||
795 | { | ||
796 | unsigned int irq_trigger = stmpe->pdata->irq_trigger; | ||
797 | int autosleep_timeout = stmpe->pdata->autosleep_timeout; | ||
798 | struct stmpe_variant_info *variant = stmpe->variant; | ||
799 | u8 icr = STMPE_ICR_LSB_GIM; | ||
800 | unsigned int id; | ||
801 | u8 data[2]; | ||
802 | int ret; | ||
803 | |||
804 | ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID], | ||
805 | ARRAY_SIZE(data), data); | ||
806 | if (ret < 0) | ||
807 | return ret; | ||
808 | |||
809 | id = (data[0] << 8) | data[1]; | ||
810 | if ((id & variant->id_mask) != variant->id_val) { | ||
811 | dev_err(stmpe->dev, "unknown chip id: %#x\n", id); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id); | ||
816 | |||
817 | /* Disable all modules -- subdrivers should enable what they need. */ | ||
818 | ret = stmpe_disable(stmpe, ~0); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
822 | if (irq_trigger == IRQF_TRIGGER_FALLING || | ||
823 | irq_trigger == IRQF_TRIGGER_RISING) | ||
824 | icr |= STMPE_ICR_LSB_EDGE; | ||
825 | |||
826 | if (irq_trigger == IRQF_TRIGGER_RISING || | ||
827 | irq_trigger == IRQF_TRIGGER_HIGH) | ||
828 | icr |= STMPE_ICR_LSB_HIGH; | ||
829 | |||
830 | if (stmpe->pdata->irq_invert_polarity) | ||
831 | icr ^= STMPE_ICR_LSB_HIGH; | ||
832 | |||
833 | if (stmpe->pdata->autosleep) { | ||
834 | ret = stmpe_autosleep(stmpe, autosleep_timeout); | ||
835 | if (ret) | ||
836 | return ret; | ||
837 | } | ||
838 | |||
839 | return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); | ||
840 | } | ||
841 | |||
842 | static int __devinit stmpe_add_device(struct stmpe *stmpe, | ||
843 | struct mfd_cell *cell, int irq) | ||
844 | { | ||
845 | return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, | ||
846 | NULL, stmpe->irq_base + irq); | ||
847 | } | ||
848 | |||
849 | static int __devinit stmpe_devices_init(struct stmpe *stmpe) | ||
850 | { | ||
851 | struct stmpe_variant_info *variant = stmpe->variant; | ||
852 | unsigned int platform_blocks = stmpe->pdata->blocks; | ||
853 | int ret = -EINVAL; | ||
854 | int i; | ||
855 | |||
856 | for (i = 0; i < variant->num_blocks; i++) { | ||
857 | struct stmpe_variant_block *block = &variant->blocks[i]; | ||
858 | |||
859 | if (!(platform_blocks & block->block)) | ||
860 | continue; | ||
861 | |||
862 | platform_blocks &= ~block->block; | ||
863 | ret = stmpe_add_device(stmpe, block->cell, block->irq); | ||
864 | if (ret) | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | if (platform_blocks) | ||
869 | dev_warn(stmpe->dev, | ||
870 | "platform wants blocks (%#x) not present on variant", | ||
871 | platform_blocks); | ||
872 | |||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | static int __devinit stmpe_probe(struct i2c_client *i2c, | ||
877 | const struct i2c_device_id *id) | ||
878 | { | ||
879 | struct stmpe_platform_data *pdata = i2c->dev.platform_data; | ||
880 | struct stmpe *stmpe; | ||
881 | int ret; | ||
882 | |||
883 | if (!pdata) | ||
884 | return -EINVAL; | ||
885 | |||
886 | stmpe = kzalloc(sizeof(struct stmpe), GFP_KERNEL); | ||
887 | if (!stmpe) | ||
888 | return -ENOMEM; | ||
889 | |||
890 | mutex_init(&stmpe->irq_lock); | ||
891 | mutex_init(&stmpe->lock); | ||
892 | |||
893 | stmpe->dev = &i2c->dev; | ||
894 | stmpe->i2c = i2c; | ||
895 | |||
896 | stmpe->pdata = pdata; | ||
897 | stmpe->irq_base = pdata->irq_base; | ||
898 | |||
899 | stmpe->partnum = id->driver_data; | ||
900 | stmpe->variant = stmpe_variant_info[stmpe->partnum]; | ||
901 | stmpe->regs = stmpe->variant->regs; | ||
902 | stmpe->num_gpios = stmpe->variant->num_gpios; | ||
903 | |||
904 | i2c_set_clientdata(i2c, stmpe); | ||
905 | |||
906 | ret = stmpe_chip_init(stmpe); | ||
907 | if (ret) | ||
908 | goto out_free; | ||
909 | |||
910 | ret = stmpe_irq_init(stmpe); | ||
911 | if (ret) | ||
912 | goto out_free; | ||
913 | |||
914 | ret = request_threaded_irq(stmpe->i2c->irq, NULL, stmpe_irq, | ||
915 | pdata->irq_trigger | IRQF_ONESHOT, | ||
916 | "stmpe", stmpe); | ||
917 | if (ret) { | ||
918 | dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret); | ||
919 | goto out_removeirq; | ||
920 | } | ||
921 | |||
922 | ret = stmpe_devices_init(stmpe); | ||
923 | if (ret) { | ||
924 | dev_err(stmpe->dev, "failed to add children\n"); | ||
925 | goto out_removedevs; | ||
926 | } | ||
927 | |||
928 | return 0; | ||
929 | |||
930 | out_removedevs: | ||
931 | mfd_remove_devices(stmpe->dev); | ||
932 | free_irq(stmpe->i2c->irq, stmpe); | ||
933 | out_removeirq: | ||
934 | stmpe_irq_remove(stmpe); | ||
935 | out_free: | ||
936 | kfree(stmpe); | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int __devexit stmpe_remove(struct i2c_client *client) | ||
941 | { | ||
942 | struct stmpe *stmpe = i2c_get_clientdata(client); | ||
943 | |||
944 | mfd_remove_devices(stmpe->dev); | ||
945 | |||
946 | free_irq(stmpe->i2c->irq, stmpe); | ||
947 | stmpe_irq_remove(stmpe); | ||
948 | |||
949 | kfree(stmpe); | ||
950 | |||
951 | return 0; | ||
952 | } | ||
953 | |||
954 | static const struct i2c_device_id stmpe_id[] = { | ||
955 | { "stmpe811", STMPE811 }, | ||
956 | { "stmpe1601", STMPE1601 }, | ||
957 | { "stmpe2401", STMPE2401 }, | ||
958 | { "stmpe2403", STMPE2403 }, | ||
959 | { } | ||
960 | }; | ||
961 | MODULE_DEVICE_TABLE(i2c, stmpe_id); | ||
962 | |||
963 | static struct i2c_driver stmpe_driver = { | ||
964 | .driver.name = "stmpe", | ||
965 | .driver.owner = THIS_MODULE, | ||
966 | .probe = stmpe_probe, | ||
967 | .remove = __devexit_p(stmpe_remove), | ||
968 | .id_table = stmpe_id, | ||
969 | }; | ||
970 | |||
971 | static int __init stmpe_init(void) | ||
972 | { | ||
973 | return i2c_add_driver(&stmpe_driver); | ||
974 | } | ||
975 | subsys_initcall(stmpe_init); | ||
976 | |||
977 | static void __exit stmpe_exit(void) | ||
978 | { | ||
979 | i2c_del_driver(&stmpe_driver); | ||
980 | } | ||
981 | module_exit(stmpe_exit); | ||
982 | |||
983 | MODULE_LICENSE("GPL v2"); | ||
984 | MODULE_DESCRIPTION("STMPE MFD core driver"); | ||
985 | MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>"); | ||
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h new file mode 100644 index 000000000000..0dbdc4e8cd77 --- /dev/null +++ b/drivers/mfd/stmpe.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
6 | */ | ||
7 | |||
8 | #ifndef __STMPE_H | ||
9 | #define __STMPE_H | ||
10 | |||
11 | #ifdef STMPE_DUMP_BYTES | ||
12 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
13 | size_t len) | ||
14 | { | ||
15 | print_hex_dump_bytes(str, DUMP_PREFIX_OFFSET, buf, len); | ||
16 | } | ||
17 | #else | ||
18 | static inline void stmpe_dump_bytes(const char *str, const void *buf, | ||
19 | size_t len) | ||
20 | { | ||
21 | } | ||
22 | #endif | ||
23 | |||
24 | /** | ||
25 | * struct stmpe_variant_block - information about block | ||
26 | * @cell: base mfd cell | ||
27 | * @irq: interrupt number to be added to each IORESOURCE_IRQ | ||
28 | * in the cell | ||
29 | * @block: block id; used for identification with platform data and for | ||
30 | * enable and altfunc callbacks | ||
31 | */ | ||
32 | struct stmpe_variant_block { | ||
33 | struct mfd_cell *cell; | ||
34 | int irq; | ||
35 | enum stmpe_block block; | ||
36 | }; | ||
37 | |||
38 | /** | ||
39 | * struct stmpe_variant_info - variant-specific information | ||
40 | * @name: part name | ||
41 | * @id_val: content of CHIPID register | ||
42 | * @id_mask: bits valid in CHIPID register for comparison with id_val | ||
43 | * @num_gpios: number of GPIOS | ||
44 | * @af_bits: number of bits used to specify the alternate function | ||
45 | * @blocks: list of blocks present on this device | ||
46 | * @num_blocks: number of blocks present on this device | ||
47 | * @num_irqs: number of internal IRQs available on this device | ||
48 | * @enable: callback to enable the specified blocks. | ||
49 | * Called with the I/O lock held. | ||
50 | * @get_altfunc: callback to get the alternate function number for the | ||
51 | * specific block | ||
52 | * @enable_autosleep: callback to configure autosleep with specified timeout | ||
53 | */ | ||
54 | struct stmpe_variant_info { | ||
55 | const char *name; | ||
56 | u16 id_val; | ||
57 | u16 id_mask; | ||
58 | int num_gpios; | ||
59 | int af_bits; | ||
60 | const u8 *regs; | ||
61 | struct stmpe_variant_block *blocks; | ||
62 | int num_blocks; | ||
63 | int num_irqs; | ||
64 | int (*enable)(struct stmpe *stmpe, unsigned int blocks, bool enable); | ||
65 | int (*get_altfunc)(struct stmpe *stmpe, enum stmpe_block block); | ||
66 | int (*enable_autosleep)(struct stmpe *stmpe, int autosleep_timeout); | ||
67 | }; | ||
68 | |||
69 | #define STMPE_ICR_LSB_HIGH (1 << 2) | ||
70 | #define STMPE_ICR_LSB_EDGE (1 << 1) | ||
71 | #define STMPE_ICR_LSB_GIM (1 << 0) | ||
72 | |||
73 | /* | ||
74 | * STMPE811 | ||
75 | */ | ||
76 | |||
77 | #define STMPE811_IRQ_TOUCH_DET 0 | ||
78 | #define STMPE811_IRQ_FIFO_TH 1 | ||
79 | #define STMPE811_IRQ_FIFO_OFLOW 2 | ||
80 | #define STMPE811_IRQ_FIFO_FULL 3 | ||
81 | #define STMPE811_IRQ_FIFO_EMPTY 4 | ||
82 | #define STMPE811_IRQ_TEMP_SENS 5 | ||
83 | #define STMPE811_IRQ_ADC 6 | ||
84 | #define STMPE811_IRQ_GPIOC 7 | ||
85 | #define STMPE811_NR_INTERNAL_IRQS 8 | ||
86 | |||
87 | #define STMPE811_REG_CHIP_ID 0x00 | ||
88 | #define STMPE811_REG_SYS_CTRL2 0x04 | ||
89 | #define STMPE811_REG_INT_CTRL 0x09 | ||
90 | #define STMPE811_REG_INT_EN 0x0A | ||
91 | #define STMPE811_REG_INT_STA 0x0B | ||
92 | #define STMPE811_REG_GPIO_INT_EN 0x0C | ||
93 | #define STMPE811_REG_GPIO_INT_STA 0x0D | ||
94 | #define STMPE811_REG_GPIO_SET_PIN 0x10 | ||
95 | #define STMPE811_REG_GPIO_CLR_PIN 0x11 | ||
96 | #define STMPE811_REG_GPIO_MP_STA 0x12 | ||
97 | #define STMPE811_REG_GPIO_DIR 0x13 | ||
98 | #define STMPE811_REG_GPIO_ED 0x14 | ||
99 | #define STMPE811_REG_GPIO_RE 0x15 | ||
100 | #define STMPE811_REG_GPIO_FE 0x16 | ||
101 | #define STMPE811_REG_GPIO_AF 0x17 | ||
102 | |||
103 | #define STMPE811_SYS_CTRL2_ADC_OFF (1 << 0) | ||
104 | #define STMPE811_SYS_CTRL2_TSC_OFF (1 << 1) | ||
105 | #define STMPE811_SYS_CTRL2_GPIO_OFF (1 << 2) | ||
106 | #define STMPE811_SYS_CTRL2_TS_OFF (1 << 3) | ||
107 | |||
108 | /* | ||
109 | * STMPE1601 | ||
110 | */ | ||
111 | |||
112 | #define STMPE1601_IRQ_GPIOC 8 | ||
113 | #define STMPE1601_IRQ_PWM3 7 | ||
114 | #define STMPE1601_IRQ_PWM2 6 | ||
115 | #define STMPE1601_IRQ_PWM1 5 | ||
116 | #define STMPE1601_IRQ_PWM0 4 | ||
117 | #define STMPE1601_IRQ_KEYPAD_OVER 2 | ||
118 | #define STMPE1601_IRQ_KEYPAD 1 | ||
119 | #define STMPE1601_IRQ_WAKEUP 0 | ||
120 | #define STMPE1601_NR_INTERNAL_IRQS 9 | ||
121 | |||
122 | #define STMPE1601_REG_SYS_CTRL 0x02 | ||
123 | #define STMPE1601_REG_SYS_CTRL2 0x03 | ||
124 | #define STMPE1601_REG_ICR_LSB 0x11 | ||
125 | #define STMPE1601_REG_IER_LSB 0x13 | ||
126 | #define STMPE1601_REG_ISR_MSB 0x14 | ||
127 | #define STMPE1601_REG_CHIP_ID 0x80 | ||
128 | #define STMPE1601_REG_INT_EN_GPIO_MASK_LSB 0x17 | ||
129 | #define STMPE1601_REG_INT_STA_GPIO_MSB 0x18 | ||
130 | #define STMPE1601_REG_GPIO_MP_LSB 0x87 | ||
131 | #define STMPE1601_REG_GPIO_SET_LSB 0x83 | ||
132 | #define STMPE1601_REG_GPIO_CLR_LSB 0x85 | ||
133 | #define STMPE1601_REG_GPIO_SET_DIR_LSB 0x89 | ||
134 | #define STMPE1601_REG_GPIO_ED_MSB 0x8A | ||
135 | #define STMPE1601_REG_GPIO_RE_LSB 0x8D | ||
136 | #define STMPE1601_REG_GPIO_FE_LSB 0x8F | ||
137 | #define STMPE1601_REG_GPIO_AF_U_MSB 0x92 | ||
138 | |||
139 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
140 | #define STMPE1601_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
141 | #define STMPE1601_SYSCON_ENABLE_SPWM (1 << 0) | ||
142 | |||
143 | /* The 1601/2403 share the same masks */ | ||
144 | #define STMPE1601_AUTOSLEEP_TIMEOUT_MASK (0x7) | ||
145 | #define STPME1601_AUTOSLEEP_ENABLE (1 << 3) | ||
146 | |||
147 | /* | ||
148 | * STMPE24xx | ||
149 | */ | ||
150 | |||
151 | #define STMPE24XX_IRQ_GPIOC 8 | ||
152 | #define STMPE24XX_IRQ_PWM2 7 | ||
153 | #define STMPE24XX_IRQ_PWM1 6 | ||
154 | #define STMPE24XX_IRQ_PWM0 5 | ||
155 | #define STMPE24XX_IRQ_ROT_OVER 4 | ||
156 | #define STMPE24XX_IRQ_ROT 3 | ||
157 | #define STMPE24XX_IRQ_KEYPAD_OVER 2 | ||
158 | #define STMPE24XX_IRQ_KEYPAD 1 | ||
159 | #define STMPE24XX_IRQ_WAKEUP 0 | ||
160 | #define STMPE24XX_NR_INTERNAL_IRQS 9 | ||
161 | |||
162 | #define STMPE24XX_REG_SYS_CTRL 0x02 | ||
163 | #define STMPE24XX_REG_ICR_LSB 0x11 | ||
164 | #define STMPE24XX_REG_IER_LSB 0x13 | ||
165 | #define STMPE24XX_REG_ISR_MSB 0x14 | ||
166 | #define STMPE24XX_REG_CHIP_ID 0x80 | ||
167 | #define STMPE24XX_REG_IEGPIOR_LSB 0x18 | ||
168 | #define STMPE24XX_REG_ISGPIOR_MSB 0x19 | ||
169 | #define STMPE24XX_REG_GPMR_LSB 0xA5 | ||
170 | #define STMPE24XX_REG_GPSR_LSB 0x85 | ||
171 | #define STMPE24XX_REG_GPCR_LSB 0x88 | ||
172 | #define STMPE24XX_REG_GPDR_LSB 0x8B | ||
173 | #define STMPE24XX_REG_GPEDR_MSB 0x8C | ||
174 | #define STMPE24XX_REG_GPRER_LSB 0x91 | ||
175 | #define STMPE24XX_REG_GPFER_LSB 0x94 | ||
176 | #define STMPE24XX_REG_GPAFR_U_MSB 0x9B | ||
177 | |||
178 | #define STMPE24XX_SYS_CTRL_ENABLE_GPIO (1 << 3) | ||
179 | #define STMPE24XX_SYSCON_ENABLE_PWM (1 << 2) | ||
180 | #define STMPE24XX_SYS_CTRL_ENABLE_KPC (1 << 1) | ||
181 | #define STMPE24XX_SYSCON_ENABLE_ROT (1 << 0) | ||
182 | |||
183 | #endif | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 5041d33adf0b..006c121f3f0d 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -350,7 +350,6 @@ static int t7l66xb_probe(struct platform_device *dev) | |||
350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); | 350 | t7l66xb->clk48m = clk_get(&dev->dev, "CLK_CK48M"); |
351 | if (IS_ERR(t7l66xb->clk48m)) { | 351 | if (IS_ERR(t7l66xb->clk48m)) { |
352 | ret = PTR_ERR(t7l66xb->clk48m); | 352 | ret = PTR_ERR(t7l66xb->clk48m); |
353 | clk_put(t7l66xb->clk32k); | ||
354 | goto err_clk48m_get; | 353 | goto err_clk48m_get; |
355 | } | 354 | } |
356 | 355 | ||
@@ -425,6 +424,8 @@ static int t7l66xb_remove(struct platform_device *dev) | |||
425 | ret = pdata->disable(dev); | 424 | ret = pdata->disable(dev); |
426 | clk_disable(t7l66xb->clk48m); | 425 | clk_disable(t7l66xb->clk48m); |
427 | clk_put(t7l66xb->clk48m); | 426 | clk_put(t7l66xb->clk48m); |
427 | clk_disable(t7l66xb->clk32k); | ||
428 | clk_put(t7l66xb->clk32k); | ||
428 | t7l66xb_detach_irq(dev); | 429 | t7l66xb_detach_irq(dev); |
429 | iounmap(t7l66xb->scr); | 430 | iounmap(t7l66xb->scr); |
430 | release_resource(&t7l66xb->rscr); | 431 | release_resource(&t7l66xb->rscr); |
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 517f9bcdeaac..6315f63f017d 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
@@ -137,7 +137,7 @@ static struct mfd_cell tc6387xb_cells[] = { | |||
137 | }, | 137 | }, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static int tc6387xb_probe(struct platform_device *dev) | 140 | static int __devinit tc6387xb_probe(struct platform_device *dev) |
141 | { | 141 | { |
142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; | 142 | struct tc6387xb_platform_data *pdata = dev->dev.platform_data; |
143 | struct resource *iomem, *rscr; | 143 | struct resource *iomem, *rscr; |
@@ -201,6 +201,7 @@ static int tc6387xb_probe(struct platform_device *dev) | |||
201 | if (!ret) | 201 | if (!ret) |
202 | return 0; | 202 | return 0; |
203 | 203 | ||
204 | iounmap(tc6387xb->scr); | ||
204 | err_ioremap: | 205 | err_ioremap: |
205 | release_resource(&tc6387xb->rscr); | 206 | release_resource(&tc6387xb->rscr); |
206 | err_resource: | 207 | err_resource: |
@@ -211,14 +212,17 @@ err_no_irq: | |||
211 | return ret; | 212 | return ret; |
212 | } | 213 | } |
213 | 214 | ||
214 | static int tc6387xb_remove(struct platform_device *dev) | 215 | static int __devexit tc6387xb_remove(struct platform_device *dev) |
215 | { | 216 | { |
216 | struct clk *clk32k = platform_get_drvdata(dev); | 217 | struct tc6387xb *tc6387xb = platform_get_drvdata(dev); |
217 | 218 | ||
218 | mfd_remove_devices(&dev->dev); | 219 | mfd_remove_devices(&dev->dev); |
219 | clk_disable(clk32k); | 220 | iounmap(tc6387xb->scr); |
220 | clk_put(clk32k); | 221 | release_resource(&tc6387xb->rscr); |
222 | clk_disable(tc6387xb->clk32k); | ||
223 | clk_put(tc6387xb->clk32k); | ||
221 | platform_set_drvdata(dev, NULL); | 224 | platform_set_drvdata(dev, NULL); |
225 | kfree(tc6387xb); | ||
222 | 226 | ||
223 | return 0; | 227 | return 0; |
224 | } | 228 | } |
@@ -229,7 +233,7 @@ static struct platform_driver tc6387xb_platform_driver = { | |||
229 | .name = "tc6387xb", | 233 | .name = "tc6387xb", |
230 | }, | 234 | }, |
231 | .probe = tc6387xb_probe, | 235 | .probe = tc6387xb_probe, |
232 | .remove = tc6387xb_remove, | 236 | .remove = __devexit_p(tc6387xb_remove), |
233 | .suspend = tc6387xb_suspend, | 237 | .suspend = tc6387xb_suspend, |
234 | .resume = tc6387xb_resume, | 238 | .resume = tc6387xb_resume, |
235 | }; | 239 | }; |
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index fcf9068810fb..ef6c42c8917a 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
@@ -732,9 +732,9 @@ err_gpio_add: | |||
732 | if (tc6393xb->gpio.base != -1) | 732 | if (tc6393xb->gpio.base != -1) |
733 | temp = gpiochip_remove(&tc6393xb->gpio); | 733 | temp = gpiochip_remove(&tc6393xb->gpio); |
734 | tcpd->disable(dev); | 734 | tcpd->disable(dev); |
735 | err_clk_enable: | ||
736 | clk_disable(tc6393xb->clk); | ||
737 | err_enable: | 735 | err_enable: |
736 | clk_disable(tc6393xb->clk); | ||
737 | err_clk_enable: | ||
738 | iounmap(tc6393xb->scr); | 738 | iounmap(tc6393xb->scr); |
739 | err_ioremap: | 739 | err_ioremap: |
740 | release_resource(&tc6393xb->rscr); | 740 | release_resource(&tc6393xb->rscr); |
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index d859dffed39f..fc0197649281 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c | |||
@@ -89,10 +89,8 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, | |||
89 | int ret = 0; | 89 | int ret = 0; |
90 | 90 | ||
91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); | 91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); |
92 | if (tps6507x == NULL) { | 92 | if (tps6507x == NULL) |
93 | kfree(i2c); | ||
94 | return -ENOMEM; | 93 | return -ENOMEM; |
95 | } | ||
96 | 94 | ||
97 | i2c_set_clientdata(i2c, tps6507x); | 95 | i2c_set_clientdata(i2c, tps6507x); |
98 | tps6507x->dev = &i2c->dev; | 96 | tps6507x->dev = &i2c->dev; |
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c new file mode 100644 index 000000000000..4cde31e6a252 --- /dev/null +++ b/drivers/mfd/tps6586x.c | |||
@@ -0,0 +1,375 @@ | |||
1 | /* | ||
2 | * Core driver for TI TPS6586x PMIC family | ||
3 | * | ||
4 | * Copyright (c) 2010 CompuLab Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on da903x.c. | ||
8 | * Copyright (C) 2008 Compulab, Ltd. | ||
9 | * Mike Rapoport <mike@compulab.co.il> | ||
10 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
11 | * Eric Miao <eric.miao@marvell.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/i2c.h> | ||
24 | |||
25 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/tps6586x.h> | ||
27 | |||
28 | /* GPIO control registers */ | ||
29 | #define TPS6586X_GPIOSET1 0x5d | ||
30 | #define TPS6586X_GPIOSET2 0x5e | ||
31 | |||
32 | /* device id */ | ||
33 | #define TPS6586X_VERSIONCRC 0xcd | ||
34 | #define TPS658621A_VERSIONCRC 0x15 | ||
35 | |||
36 | struct tps6586x { | ||
37 | struct mutex lock; | ||
38 | struct device *dev; | ||
39 | struct i2c_client *client; | ||
40 | |||
41 | struct gpio_chip gpio; | ||
42 | }; | ||
43 | |||
44 | static inline int __tps6586x_read(struct i2c_client *client, | ||
45 | int reg, uint8_t *val) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | ret = i2c_smbus_read_byte_data(client, reg); | ||
50 | if (ret < 0) { | ||
51 | dev_err(&client->dev, "failed reading at 0x%02x\n", reg); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | *val = (uint8_t)ret; | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static inline int __tps6586x_reads(struct i2c_client *client, int reg, | ||
61 | int len, uint8_t *val) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); | ||
66 | if (ret < 0) { | ||
67 | dev_err(&client->dev, "failed reading from 0x%02x\n", reg); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static inline int __tps6586x_write(struct i2c_client *client, | ||
75 | int reg, uint8_t val) | ||
76 | { | ||
77 | int ret; | ||
78 | |||
79 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
80 | if (ret < 0) { | ||
81 | dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", | ||
82 | val, reg); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static inline int __tps6586x_writes(struct i2c_client *client, int reg, | ||
90 | int len, uint8_t *val) | ||
91 | { | ||
92 | int ret; | ||
93 | |||
94 | ret = i2c_smbus_write_i2c_block_data(client, reg, len, val); | ||
95 | if (ret < 0) { | ||
96 | dev_err(&client->dev, "failed writings to 0x%02x\n", reg); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int tps6586x_write(struct device *dev, int reg, uint8_t val) | ||
104 | { | ||
105 | return __tps6586x_write(to_i2c_client(dev), reg, val); | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(tps6586x_write); | ||
108 | |||
109 | int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) | ||
110 | { | ||
111 | return __tps6586x_writes(to_i2c_client(dev), reg, len, val); | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(tps6586x_writes); | ||
114 | |||
115 | int tps6586x_read(struct device *dev, int reg, uint8_t *val) | ||
116 | { | ||
117 | return __tps6586x_read(to_i2c_client(dev), reg, val); | ||
118 | } | ||
119 | EXPORT_SYMBOL_GPL(tps6586x_read); | ||
120 | |||
121 | int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) | ||
122 | { | ||
123 | return __tps6586x_reads(to_i2c_client(dev), reg, len, val); | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(tps6586x_reads); | ||
126 | |||
127 | int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
128 | { | ||
129 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
130 | uint8_t reg_val; | ||
131 | int ret = 0; | ||
132 | |||
133 | mutex_lock(&tps6586x->lock); | ||
134 | |||
135 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
136 | if (ret) | ||
137 | goto out; | ||
138 | |||
139 | if ((reg_val & bit_mask) == 0) { | ||
140 | reg_val |= bit_mask; | ||
141 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
142 | } | ||
143 | out: | ||
144 | mutex_unlock(&tps6586x->lock); | ||
145 | return ret; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(tps6586x_set_bits); | ||
148 | |||
149 | int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) | ||
150 | { | ||
151 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
152 | uint8_t reg_val; | ||
153 | int ret = 0; | ||
154 | |||
155 | mutex_lock(&tps6586x->lock); | ||
156 | |||
157 | ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); | ||
158 | if (ret) | ||
159 | goto out; | ||
160 | |||
161 | if (reg_val & bit_mask) { | ||
162 | reg_val &= ~bit_mask; | ||
163 | ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); | ||
164 | } | ||
165 | out: | ||
166 | mutex_unlock(&tps6586x->lock); | ||
167 | return ret; | ||
168 | } | ||
169 | EXPORT_SYMBOL_GPL(tps6586x_clr_bits); | ||
170 | |||
171 | int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) | ||
172 | { | ||
173 | struct tps6586x *tps6586x = dev_get_drvdata(dev); | ||
174 | uint8_t reg_val; | ||
175 | int ret = 0; | ||
176 | |||
177 | mutex_lock(&tps6586x->lock); | ||
178 | |||
179 | ret = __tps6586x_read(tps6586x->client, reg, ®_val); | ||
180 | if (ret) | ||
181 | goto out; | ||
182 | |||
183 | if ((reg_val & mask) != val) { | ||
184 | reg_val = (reg_val & ~mask) | val; | ||
185 | ret = __tps6586x_write(tps6586x->client, reg, reg_val); | ||
186 | } | ||
187 | out: | ||
188 | mutex_unlock(&tps6586x->lock); | ||
189 | return ret; | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(tps6586x_update); | ||
192 | |||
193 | static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
194 | { | ||
195 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
196 | uint8_t val; | ||
197 | int ret; | ||
198 | |||
199 | ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
203 | return !!(val & (1 << offset)); | ||
204 | } | ||
205 | |||
206 | |||
207 | static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, | ||
208 | int value) | ||
209 | { | ||
210 | struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); | ||
211 | |||
212 | __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2, | ||
213 | value << offset); | ||
214 | } | ||
215 | |||
216 | static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, | ||
217 | int value) | ||
218 | { | ||
219 | struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); | ||
220 | uint8_t val, mask; | ||
221 | |||
222 | tps6586x_gpio_set(gc, offset, value); | ||
223 | |||
224 | val = 0x1 << (offset * 2); | ||
225 | mask = 0x3 << (offset * 2); | ||
226 | |||
227 | return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); | ||
228 | } | ||
229 | |||
230 | static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | if (!gpio_base) | ||
235 | return; | ||
236 | |||
237 | tps6586x->gpio.owner = THIS_MODULE; | ||
238 | tps6586x->gpio.label = tps6586x->client->name; | ||
239 | tps6586x->gpio.dev = tps6586x->dev; | ||
240 | tps6586x->gpio.base = gpio_base; | ||
241 | tps6586x->gpio.ngpio = 4; | ||
242 | tps6586x->gpio.can_sleep = 1; | ||
243 | |||
244 | /* FIXME: add handling of GPIOs as dedicated inputs */ | ||
245 | tps6586x->gpio.direction_output = tps6586x_gpio_output; | ||
246 | tps6586x->gpio.set = tps6586x_gpio_set; | ||
247 | tps6586x->gpio.get = tps6586x_gpio_get; | ||
248 | |||
249 | ret = gpiochip_add(&tps6586x->gpio); | ||
250 | if (ret) | ||
251 | dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret); | ||
252 | } | ||
253 | |||
254 | static int __remove_subdev(struct device *dev, void *unused) | ||
255 | { | ||
256 | platform_device_unregister(to_platform_device(dev)); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int tps6586x_remove_subdevs(struct tps6586x *tps6586x) | ||
261 | { | ||
262 | return device_for_each_child(tps6586x->dev, NULL, __remove_subdev); | ||
263 | } | ||
264 | |||
265 | static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x, | ||
266 | struct tps6586x_platform_data *pdata) | ||
267 | { | ||
268 | struct tps6586x_subdev_info *subdev; | ||
269 | struct platform_device *pdev; | ||
270 | int i, ret = 0; | ||
271 | |||
272 | for (i = 0; i < pdata->num_subdevs; i++) { | ||
273 | subdev = &pdata->subdevs[i]; | ||
274 | |||
275 | pdev = platform_device_alloc(subdev->name, subdev->id); | ||
276 | |||
277 | pdev->dev.parent = tps6586x->dev; | ||
278 | pdev->dev.platform_data = subdev->platform_data; | ||
279 | |||
280 | ret = platform_device_add(pdev); | ||
281 | if (ret) | ||
282 | goto failed; | ||
283 | } | ||
284 | return 0; | ||
285 | |||
286 | failed: | ||
287 | tps6586x_remove_subdevs(tps6586x); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int __devinit tps6586x_i2c_probe(struct i2c_client *client, | ||
292 | const struct i2c_device_id *id) | ||
293 | { | ||
294 | struct tps6586x_platform_data *pdata = client->dev.platform_data; | ||
295 | struct tps6586x *tps6586x; | ||
296 | int ret; | ||
297 | |||
298 | if (!pdata) { | ||
299 | dev_err(&client->dev, "tps6586x requires platform data\n"); | ||
300 | return -ENOTSUPP; | ||
301 | } | ||
302 | |||
303 | ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC); | ||
304 | if (ret < 0) { | ||
305 | dev_err(&client->dev, "Chip ID read failed: %d\n", ret); | ||
306 | return -EIO; | ||
307 | } | ||
308 | |||
309 | if (ret != TPS658621A_VERSIONCRC) { | ||
310 | dev_err(&client->dev, "Unsupported chip ID: %x\n", ret); | ||
311 | return -ENODEV; | ||
312 | } | ||
313 | |||
314 | tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); | ||
315 | if (tps6586x == NULL) | ||
316 | return -ENOMEM; | ||
317 | |||
318 | tps6586x->client = client; | ||
319 | tps6586x->dev = &client->dev; | ||
320 | i2c_set_clientdata(client, tps6586x); | ||
321 | |||
322 | mutex_init(&tps6586x->lock); | ||
323 | |||
324 | ret = tps6586x_add_subdevs(tps6586x, pdata); | ||
325 | if (ret) { | ||
326 | dev_err(&client->dev, "add devices failed: %d\n", ret); | ||
327 | goto err_add_devs; | ||
328 | } | ||
329 | |||
330 | tps6586x_gpio_init(tps6586x, pdata->gpio_base); | ||
331 | |||
332 | return 0; | ||
333 | |||
334 | err_add_devs: | ||
335 | kfree(tps6586x); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int __devexit tps6586x_i2c_remove(struct i2c_client *client) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static const struct i2c_device_id tps6586x_id_table[] = { | ||
345 | { "tps6586x", 0 }, | ||
346 | { }, | ||
347 | }; | ||
348 | MODULE_DEVICE_TABLE(i2c, tps6586x_id_table); | ||
349 | |||
350 | static struct i2c_driver tps6586x_driver = { | ||
351 | .driver = { | ||
352 | .name = "tps6586x", | ||
353 | .owner = THIS_MODULE, | ||
354 | }, | ||
355 | .probe = tps6586x_i2c_probe, | ||
356 | .remove = __devexit_p(tps6586x_i2c_remove), | ||
357 | .id_table = tps6586x_id_table, | ||
358 | }; | ||
359 | |||
360 | static int __init tps6586x_init(void) | ||
361 | { | ||
362 | return i2c_add_driver(&tps6586x_driver); | ||
363 | } | ||
364 | subsys_initcall(tps6586x_init); | ||
365 | |||
366 | static void __exit tps6586x_exit(void) | ||
367 | { | ||
368 | i2c_del_driver(&tps6586x_driver); | ||
369 | } | ||
370 | module_exit(tps6586x_exit); | ||
371 | |||
372 | MODULE_DESCRIPTION("TPS6586X core driver"); | ||
373 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
374 | MODULE_LICENSE("GPL"); | ||
375 | |||
diff --git a/drivers/mfd/twl6030-pwm.c b/drivers/mfd/twl6030-pwm.c new file mode 100644 index 000000000000..5d25bdc78424 --- /dev/null +++ b/drivers/mfd/twl6030-pwm.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * twl6030_pwm.c | ||
3 | * Driver for PHOENIX (TWL6030) Pulse Width Modulator | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments | ||
6 | * Author: Hemanth V <hemanthv@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/i2c/twl.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #define LED_PWM_CTRL1 0xF4 | ||
27 | #define LED_PWM_CTRL2 0xF5 | ||
28 | |||
29 | /* Max value for CTRL1 register */ | ||
30 | #define PWM_CTRL1_MAX 255 | ||
31 | |||
32 | /* Pull down disable */ | ||
33 | #define PWM_CTRL2_DIS_PD (1 << 6) | ||
34 | |||
35 | /* Current control 2.5 milli Amps */ | ||
36 | #define PWM_CTRL2_CURR_02 (2 << 4) | ||
37 | |||
38 | /* LED supply source */ | ||
39 | #define PWM_CTRL2_SRC_VAC (1 << 2) | ||
40 | |||
41 | /* LED modes */ | ||
42 | #define PWM_CTRL2_MODE_HW (0 << 0) | ||
43 | #define PWM_CTRL2_MODE_SW (1 << 0) | ||
44 | #define PWM_CTRL2_MODE_DIS (2 << 0) | ||
45 | |||
46 | #define PWM_CTRL2_MODE_MASK 0x3 | ||
47 | |||
48 | struct pwm_device { | ||
49 | const char *label; | ||
50 | unsigned int pwm_id; | ||
51 | }; | ||
52 | |||
53 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | ||
54 | { | ||
55 | u8 duty_cycle; | ||
56 | int ret; | ||
57 | |||
58 | if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) | ||
59 | return -EINVAL; | ||
60 | |||
61 | duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns; | ||
62 | |||
63 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1); | ||
64 | |||
65 | if (ret < 0) { | ||
66 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
67 | pwm->label, ret); | ||
68 | return ret; | ||
69 | } | ||
70 | return 0; | ||
71 | } | ||
72 | EXPORT_SYMBOL(pwm_config); | ||
73 | |||
74 | int pwm_enable(struct pwm_device *pwm) | ||
75 | { | ||
76 | u8 val; | ||
77 | int ret; | ||
78 | |||
79 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
80 | if (ret < 0) { | ||
81 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | /* Change mode to software control */ | ||
86 | val &= ~PWM_CTRL2_MODE_MASK; | ||
87 | val |= PWM_CTRL2_MODE_SW; | ||
88 | |||
89 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
90 | if (ret < 0) { | ||
91 | pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
96 | return 0; | ||
97 | } | ||
98 | EXPORT_SYMBOL(pwm_enable); | ||
99 | |||
100 | void pwm_disable(struct pwm_device *pwm) | ||
101 | { | ||
102 | u8 val; | ||
103 | int ret; | ||
104 | |||
105 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
106 | if (ret < 0) { | ||
107 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
108 | pwm->label, ret); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | val &= ~PWM_CTRL2_MODE_MASK; | ||
113 | val |= PWM_CTRL2_MODE_HW; | ||
114 | |||
115 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
116 | if (ret < 0) { | ||
117 | pr_err("%s: Failed to disable PWM, Error %d\n", | ||
118 | pwm->label, ret); | ||
119 | return; | ||
120 | } | ||
121 | return; | ||
122 | } | ||
123 | EXPORT_SYMBOL(pwm_disable); | ||
124 | |||
125 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
126 | { | ||
127 | u8 val; | ||
128 | int ret; | ||
129 | struct pwm_device *pwm; | ||
130 | |||
131 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | ||
132 | if (pwm == NULL) { | ||
133 | pr_err("%s: failed to allocate memory\n", label); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | pwm->label = label; | ||
138 | pwm->pwm_id = pwm_id; | ||
139 | |||
140 | /* Configure PWM */ | ||
141 | val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC | | ||
142 | PWM_CTRL2_MODE_HW; | ||
143 | |||
144 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
145 | |||
146 | if (ret < 0) { | ||
147 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
148 | pwm->label, ret); | ||
149 | |||
150 | kfree(pwm); | ||
151 | return NULL; | ||
152 | } | ||
153 | |||
154 | return pwm; | ||
155 | } | ||
156 | EXPORT_SYMBOL(pwm_request); | ||
157 | |||
158 | void pwm_free(struct pwm_device *pwm) | ||
159 | { | ||
160 | pwm_disable(pwm); | ||
161 | kfree(pwm); | ||
162 | } | ||
163 | EXPORT_SYMBOL(pwm_free); | ||
diff --git a/drivers/mfd/ucb1400_core.c b/drivers/mfd/ucb1400_core.c index dbe280153f9e..d73f84ba0f08 100644 --- a/drivers/mfd/ucb1400_core.c +++ b/drivers/mfd/ucb1400_core.c | |||
@@ -114,7 +114,7 @@ static int ucb1400_core_probe(struct device *dev) | |||
114 | err3: | 114 | err3: |
115 | platform_device_put(ucb->ucb1400_ts); | 115 | platform_device_put(ucb->ucb1400_ts); |
116 | err2: | 116 | err2: |
117 | platform_device_unregister(ucb->ucb1400_gpio); | 117 | platform_device_del(ucb->ucb1400_gpio); |
118 | err1: | 118 | err1: |
119 | platform_device_put(ucb->ucb1400_gpio); | 119 | platform_device_put(ucb->ucb1400_gpio); |
120 | err0: | 120 | err0: |
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 1a968f34d679..1e7aaaf6cc6f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -95,6 +95,7 @@ enum wm831x_parent { | |||
95 | WM8311 = 0x8311, | 95 | WM8311 = 0x8311, |
96 | WM8312 = 0x8312, | 96 | WM8312 = 0x8312, |
97 | WM8320 = 0x8320, | 97 | WM8320 = 0x8320, |
98 | WM8321 = 0x8321, | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) | 101 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) |
@@ -1533,6 +1534,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1533 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); | 1534 | dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev); |
1534 | break; | 1535 | break; |
1535 | 1536 | ||
1537 | case WM8321: | ||
1538 | parent = WM8321; | ||
1539 | wm831x->num_gpio = 12; | ||
1540 | dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev); | ||
1541 | break; | ||
1542 | |||
1536 | default: | 1543 | default: |
1537 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); | 1544 | dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); |
1538 | ret = -EINVAL; | 1545 | ret = -EINVAL; |
@@ -1607,6 +1614,12 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1607 | NULL, 0); | 1614 | NULL, 0); |
1608 | break; | 1615 | break; |
1609 | 1616 | ||
1617 | case WM8321: | ||
1618 | ret = mfd_add_devices(wm831x->dev, -1, | ||
1619 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | ||
1620 | NULL, 0); | ||
1621 | break; | ||
1622 | |||
1610 | default: | 1623 | default: |
1611 | /* If this happens the bus probe function is buggy */ | 1624 | /* If this happens the bus probe function is buggy */ |
1612 | BUG(); | 1625 | BUG(); |
@@ -1744,10 +1757,8 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, | |||
1744 | struct wm831x *wm831x; | 1757 | struct wm831x *wm831x; |
1745 | 1758 | ||
1746 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); | 1759 | wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); |
1747 | if (wm831x == NULL) { | 1760 | if (wm831x == NULL) |
1748 | kfree(i2c); | ||
1749 | return -ENOMEM; | 1761 | return -ENOMEM; |
1750 | } | ||
1751 | 1762 | ||
1752 | i2c_set_clientdata(i2c, wm831x); | 1763 | i2c_set_clientdata(i2c, wm831x); |
1753 | wm831x->dev = &i2c->dev; | 1764 | wm831x->dev = &i2c->dev; |
@@ -1779,6 +1790,7 @@ static const struct i2c_device_id wm831x_i2c_id[] = { | |||
1779 | { "wm8311", WM8311 }, | 1790 | { "wm8311", WM8311 }, |
1780 | { "wm8312", WM8312 }, | 1791 | { "wm8312", WM8312 }, |
1781 | { "wm8320", WM8320 }, | 1792 | { "wm8320", WM8320 }, |
1793 | { "wm8321", WM8321 }, | ||
1782 | { } | 1794 | { } |
1783 | }; | 1795 | }; |
1784 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | 1796 | MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); |
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index b5807484b4c9..e81cc31e4202 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -536,6 +536,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) | |||
536 | } | 536 | } |
537 | 537 | ||
538 | out: | 538 | out: |
539 | kfree(wm8350->reg_cache); | ||
539 | return ret; | 540 | return ret; |
540 | } | 541 | } |
541 | 542 | ||
@@ -700,7 +701,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
700 | 701 | ||
701 | ret = wm8350_irq_init(wm8350, irq, pdata); | 702 | ret = wm8350_irq_init(wm8350, irq, pdata); |
702 | if (ret < 0) | 703 | if (ret < 0) |
703 | goto err; | 704 | goto err_free; |
704 | 705 | ||
705 | if (wm8350->irq_base) { | 706 | if (wm8350->irq_base) { |
706 | ret = request_threaded_irq(wm8350->irq_base + | 707 | ret = request_threaded_irq(wm8350->irq_base + |
@@ -738,8 +739,9 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
738 | 739 | ||
739 | err_irq: | 740 | err_irq: |
740 | wm8350_irq_exit(wm8350); | 741 | wm8350_irq_exit(wm8350); |
741 | err: | 742 | err_free: |
742 | kfree(wm8350->reg_cache); | 743 | kfree(wm8350->reg_cache); |
744 | err: | ||
743 | return ret; | 745 | return ret; |
744 | } | 746 | } |
745 | EXPORT_SYMBOL_GPL(wm8350_device_init); | 747 | EXPORT_SYMBOL_GPL(wm8350_device_init); |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index ec71c9368906..b3b2aaf89dbe 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -326,8 +326,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * | 326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * |
327 | ARRAY_SIZE(wm8994_main_supplies), | 327 | ARRAY_SIZE(wm8994_main_supplies), |
328 | GFP_KERNEL); | 328 | GFP_KERNEL); |
329 | if (!wm8994->supplies) | 329 | if (!wm8994->supplies) { |
330 | ret = -ENOMEM; | ||
330 | goto err; | 331 | goto err; |
332 | } | ||
331 | 333 | ||
332 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 334 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) |
333 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 335 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
@@ -495,10 +497,8 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
495 | struct wm8994 *wm8994; | 497 | struct wm8994 *wm8994; |
496 | 498 | ||
497 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); | 499 | wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL); |
498 | if (wm8994 == NULL) { | 500 | if (wm8994 == NULL) |
499 | kfree(i2c); | ||
500 | return -ENOMEM; | 501 | return -ENOMEM; |
501 | } | ||
502 | 502 | ||
503 | i2c_set_clientdata(i2c, wm8994); | 503 | i2c_set_clientdata(i2c, wm8994); |
504 | wm8994->dev = &i2c->dev; | 504 | wm8994->dev = &i2c->dev; |
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c index 2d44b3300104..6f6218061b0d 100644 --- a/drivers/misc/cs5535-mfgpt.c +++ b/drivers/misc/cs5535-mfgpt.c | |||
@@ -211,6 +211,17 @@ EXPORT_SYMBOL_GPL(cs5535_mfgpt_alloc_timer); | |||
211 | */ | 211 | */ |
212 | void cs5535_mfgpt_free_timer(struct cs5535_mfgpt_timer *timer) | 212 | void cs5535_mfgpt_free_timer(struct cs5535_mfgpt_timer *timer) |
213 | { | 213 | { |
214 | unsigned long flags; | ||
215 | uint16_t val; | ||
216 | |||
217 | /* timer can be made available again only if never set up */ | ||
218 | val = cs5535_mfgpt_read(timer, MFGPT_REG_SETUP); | ||
219 | if (!(val & MFGPT_SETUP_SETUP)) { | ||
220 | spin_lock_irqsave(&timer->chip->lock, flags); | ||
221 | __set_bit(timer->nr, timer->chip->avail); | ||
222 | spin_unlock_irqrestore(&timer->chip->lock, flags); | ||
223 | } | ||
224 | |||
214 | kfree(timer); | 225 | kfree(timer); |
215 | } | 226 | } |
216 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_free_timer); | 227 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_free_timer); |
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 5bfb2a2041b8..ef34de7a8026 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -124,9 +124,9 @@ static int count = DEFAULT_COUNT; | |||
124 | module_param(recur_count, int, 0644); | 124 | module_param(recur_count, int, 0644); |
125 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ | 125 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ |
126 | "default is 10"); | 126 | "default is 10"); |
127 | module_param(cpoint_name, charp, 0644); | 127 | module_param(cpoint_name, charp, 0444); |
128 | MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); | 128 | MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); |
129 | module_param(cpoint_type, charp, 0644); | 129 | module_param(cpoint_type, charp, 0444); |
130 | MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ | 130 | MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ |
131 | "hitting the crash point"); | 131 | "hitting the crash point"); |
132 | module_param(cpoint_count, int, 0644); | 132 | module_param(cpoint_count, int, 0644); |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 8433cde29c8b..d545f79f6000 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -247,7 +247,76 @@ static u32 get_card_status(struct mmc_card *card, struct request *req) | |||
247 | return cmd.resp[0]; | 247 | return cmd.resp[0]; |
248 | } | 248 | } |
249 | 249 | ||
250 | static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | 250 | static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) |
251 | { | ||
252 | struct mmc_blk_data *md = mq->data; | ||
253 | struct mmc_card *card = md->queue.card; | ||
254 | unsigned int from, nr, arg; | ||
255 | int err = 0; | ||
256 | |||
257 | mmc_claim_host(card->host); | ||
258 | |||
259 | if (!mmc_can_erase(card)) { | ||
260 | err = -EOPNOTSUPP; | ||
261 | goto out; | ||
262 | } | ||
263 | |||
264 | from = blk_rq_pos(req); | ||
265 | nr = blk_rq_sectors(req); | ||
266 | |||
267 | if (mmc_can_trim(card)) | ||
268 | arg = MMC_TRIM_ARG; | ||
269 | else | ||
270 | arg = MMC_ERASE_ARG; | ||
271 | |||
272 | err = mmc_erase(card, from, nr, arg); | ||
273 | out: | ||
274 | spin_lock_irq(&md->lock); | ||
275 | __blk_end_request(req, err, blk_rq_bytes(req)); | ||
276 | spin_unlock_irq(&md->lock); | ||
277 | |||
278 | mmc_release_host(card->host); | ||
279 | |||
280 | return err ? 0 : 1; | ||
281 | } | ||
282 | |||
283 | static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, | ||
284 | struct request *req) | ||
285 | { | ||
286 | struct mmc_blk_data *md = mq->data; | ||
287 | struct mmc_card *card = md->queue.card; | ||
288 | unsigned int from, nr, arg; | ||
289 | int err = 0; | ||
290 | |||
291 | mmc_claim_host(card->host); | ||
292 | |||
293 | if (!mmc_can_secure_erase_trim(card)) { | ||
294 | err = -EOPNOTSUPP; | ||
295 | goto out; | ||
296 | } | ||
297 | |||
298 | from = blk_rq_pos(req); | ||
299 | nr = blk_rq_sectors(req); | ||
300 | |||
301 | if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) | ||
302 | arg = MMC_SECURE_TRIM1_ARG; | ||
303 | else | ||
304 | arg = MMC_SECURE_ERASE_ARG; | ||
305 | |||
306 | err = mmc_erase(card, from, nr, arg); | ||
307 | if (!err && arg == MMC_SECURE_TRIM1_ARG) | ||
308 | err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); | ||
309 | out: | ||
310 | spin_lock_irq(&md->lock); | ||
311 | __blk_end_request(req, err, blk_rq_bytes(req)); | ||
312 | spin_unlock_irq(&md->lock); | ||
313 | |||
314 | mmc_release_host(card->host); | ||
315 | |||
316 | return err ? 0 : 1; | ||
317 | } | ||
318 | |||
319 | static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | ||
251 | { | 320 | { |
252 | struct mmc_blk_data *md = mq->data; | 321 | struct mmc_blk_data *md = mq->data; |
253 | struct mmc_card *card = md->queue.card; | 322 | struct mmc_card *card = md->queue.card; |
@@ -475,6 +544,17 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
475 | return 0; | 544 | return 0; |
476 | } | 545 | } |
477 | 546 | ||
547 | static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | ||
548 | { | ||
549 | if (req->cmd_flags & REQ_DISCARD) { | ||
550 | if (req->cmd_flags & REQ_SECURE) | ||
551 | return mmc_blk_issue_secdiscard_rq(mq, req); | ||
552 | else | ||
553 | return mmc_blk_issue_discard_rq(mq, req); | ||
554 | } else { | ||
555 | return mmc_blk_issue_rw_rq(mq, req); | ||
556 | } | ||
557 | } | ||
478 | 558 | ||
479 | static inline int mmc_blk_readonly(struct mmc_card *card) | 559 | static inline int mmc_blk_readonly(struct mmc_card *card) |
480 | { | 560 | { |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 445d7db2277e..5dd8576b5c18 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | 17 | ||
18 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
19 | #include <linux/swap.h> /* For nr_free_buffer_pages() */ | ||
19 | 20 | ||
20 | #define RESULT_OK 0 | 21 | #define RESULT_OK 0 |
21 | #define RESULT_FAIL 1 | 22 | #define RESULT_FAIL 1 |
@@ -25,6 +26,60 @@ | |||
25 | #define BUFFER_ORDER 2 | 26 | #define BUFFER_ORDER 2 |
26 | #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) | 27 | #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) |
27 | 28 | ||
29 | /* | ||
30 | * Limit the test area size to the maximum MMC HC erase group size. Note that | ||
31 | * the maximum SD allocation unit size is just 4MiB. | ||
32 | */ | ||
33 | #define TEST_AREA_MAX_SIZE (128 * 1024 * 1024) | ||
34 | |||
35 | /** | ||
36 | * struct mmc_test_pages - pages allocated by 'alloc_pages()'. | ||
37 | * @page: first page in the allocation | ||
38 | * @order: order of the number of pages allocated | ||
39 | */ | ||
40 | struct mmc_test_pages { | ||
41 | struct page *page; | ||
42 | unsigned int order; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * struct mmc_test_mem - allocated memory. | ||
47 | * @arr: array of allocations | ||
48 | * @cnt: number of allocations | ||
49 | */ | ||
50 | struct mmc_test_mem { | ||
51 | struct mmc_test_pages *arr; | ||
52 | unsigned int cnt; | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * struct mmc_test_area - information for performance tests. | ||
57 | * @max_sz: test area size (in bytes) | ||
58 | * @dev_addr: address on card at which to do performance tests | ||
59 | * @max_segs: maximum segments in scatterlist @sg | ||
60 | * @blocks: number of (512 byte) blocks currently mapped by @sg | ||
61 | * @sg_len: length of currently mapped scatterlist @sg | ||
62 | * @mem: allocated memory | ||
63 | * @sg: scatterlist | ||
64 | */ | ||
65 | struct mmc_test_area { | ||
66 | unsigned long max_sz; | ||
67 | unsigned int dev_addr; | ||
68 | unsigned int max_segs; | ||
69 | unsigned int blocks; | ||
70 | unsigned int sg_len; | ||
71 | struct mmc_test_mem *mem; | ||
72 | struct scatterlist *sg; | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct mmc_test_card - test information. | ||
77 | * @card: card under test | ||
78 | * @scratch: transfer buffer | ||
79 | * @buffer: transfer buffer | ||
80 | * @highmem: buffer for highmem tests | ||
81 | * @area: information for performance tests | ||
82 | */ | ||
28 | struct mmc_test_card { | 83 | struct mmc_test_card { |
29 | struct mmc_card *card; | 84 | struct mmc_card *card; |
30 | 85 | ||
@@ -33,6 +88,7 @@ struct mmc_test_card { | |||
33 | #ifdef CONFIG_HIGHMEM | 88 | #ifdef CONFIG_HIGHMEM |
34 | struct page *highmem; | 89 | struct page *highmem; |
35 | #endif | 90 | #endif |
91 | struct mmc_test_area area; | ||
36 | }; | 92 | }; |
37 | 93 | ||
38 | /*******************************************************************/ | 94 | /*******************************************************************/ |
@@ -97,6 +153,12 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test, | |||
97 | mmc_set_data_timeout(mrq->data, test->card); | 153 | mmc_set_data_timeout(mrq->data, test->card); |
98 | } | 154 | } |
99 | 155 | ||
156 | static int mmc_test_busy(struct mmc_command *cmd) | ||
157 | { | ||
158 | return !(cmd->resp[0] & R1_READY_FOR_DATA) || | ||
159 | (R1_CURRENT_STATE(cmd->resp[0]) == 7); | ||
160 | } | ||
161 | |||
100 | /* | 162 | /* |
101 | * Wait for the card to finish the busy state | 163 | * Wait for the card to finish the busy state |
102 | */ | 164 | */ |
@@ -117,13 +179,13 @@ static int mmc_test_wait_busy(struct mmc_test_card *test) | |||
117 | if (ret) | 179 | if (ret) |
118 | break; | 180 | break; |
119 | 181 | ||
120 | if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) { | 182 | if (!busy && mmc_test_busy(&cmd)) { |
121 | busy = 1; | 183 | busy = 1; |
122 | printk(KERN_INFO "%s: Warning: Host did not " | 184 | printk(KERN_INFO "%s: Warning: Host did not " |
123 | "wait for busy state to end.\n", | 185 | "wait for busy state to end.\n", |
124 | mmc_hostname(test->card->host)); | 186 | mmc_hostname(test->card->host)); |
125 | } | 187 | } |
126 | } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); | 188 | } while (mmc_test_busy(&cmd)); |
127 | 189 | ||
128 | return ret; | 190 | return ret; |
129 | } | 191 | } |
@@ -170,6 +232,248 @@ static int mmc_test_buffer_transfer(struct mmc_test_card *test, | |||
170 | return 0; | 232 | return 0; |
171 | } | 233 | } |
172 | 234 | ||
235 | static void mmc_test_free_mem(struct mmc_test_mem *mem) | ||
236 | { | ||
237 | if (!mem) | ||
238 | return; | ||
239 | while (mem->cnt--) | ||
240 | __free_pages(mem->arr[mem->cnt].page, | ||
241 | mem->arr[mem->cnt].order); | ||
242 | kfree(mem->arr); | ||
243 | kfree(mem); | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * Allocate a lot of memory, preferrably max_sz but at least min_sz. In case | ||
248 | * there isn't much memory do not exceed 1/16th total lowmem pages. | ||
249 | */ | ||
250 | static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz, | ||
251 | unsigned long max_sz) | ||
252 | { | ||
253 | unsigned long max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE); | ||
254 | unsigned long min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE); | ||
255 | unsigned long page_cnt = 0; | ||
256 | unsigned long limit = nr_free_buffer_pages() >> 4; | ||
257 | struct mmc_test_mem *mem; | ||
258 | |||
259 | if (max_page_cnt > limit) | ||
260 | max_page_cnt = limit; | ||
261 | if (max_page_cnt < min_page_cnt) | ||
262 | max_page_cnt = min_page_cnt; | ||
263 | |||
264 | mem = kzalloc(sizeof(struct mmc_test_mem), GFP_KERNEL); | ||
265 | if (!mem) | ||
266 | return NULL; | ||
267 | |||
268 | mem->arr = kzalloc(sizeof(struct mmc_test_pages) * max_page_cnt, | ||
269 | GFP_KERNEL); | ||
270 | if (!mem->arr) | ||
271 | goto out_free; | ||
272 | |||
273 | while (max_page_cnt) { | ||
274 | struct page *page; | ||
275 | unsigned int order; | ||
276 | gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN | | ||
277 | __GFP_NORETRY; | ||
278 | |||
279 | order = get_order(max_page_cnt << PAGE_SHIFT); | ||
280 | while (1) { | ||
281 | page = alloc_pages(flags, order); | ||
282 | if (page || !order) | ||
283 | break; | ||
284 | order -= 1; | ||
285 | } | ||
286 | if (!page) { | ||
287 | if (page_cnt < min_page_cnt) | ||
288 | goto out_free; | ||
289 | break; | ||
290 | } | ||
291 | mem->arr[mem->cnt].page = page; | ||
292 | mem->arr[mem->cnt].order = order; | ||
293 | mem->cnt += 1; | ||
294 | if (max_page_cnt <= (1UL << order)) | ||
295 | break; | ||
296 | max_page_cnt -= 1UL << order; | ||
297 | page_cnt += 1UL << order; | ||
298 | } | ||
299 | |||
300 | return mem; | ||
301 | |||
302 | out_free: | ||
303 | mmc_test_free_mem(mem); | ||
304 | return NULL; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Map memory into a scatterlist. Optionally allow the same memory to be | ||
309 | * mapped more than once. | ||
310 | */ | ||
311 | static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz, | ||
312 | struct scatterlist *sglist, int repeat, | ||
313 | unsigned int max_segs, unsigned int *sg_len) | ||
314 | { | ||
315 | struct scatterlist *sg = NULL; | ||
316 | unsigned int i; | ||
317 | |||
318 | sg_init_table(sglist, max_segs); | ||
319 | |||
320 | *sg_len = 0; | ||
321 | do { | ||
322 | for (i = 0; i < mem->cnt; i++) { | ||
323 | unsigned long len = PAGE_SIZE << mem->arr[i].order; | ||
324 | |||
325 | if (sz < len) | ||
326 | len = sz; | ||
327 | if (sg) | ||
328 | sg = sg_next(sg); | ||
329 | else | ||
330 | sg = sglist; | ||
331 | if (!sg) | ||
332 | return -EINVAL; | ||
333 | sg_set_page(sg, mem->arr[i].page, len, 0); | ||
334 | sz -= len; | ||
335 | *sg_len += 1; | ||
336 | if (!sz) | ||
337 | break; | ||
338 | } | ||
339 | } while (sz && repeat); | ||
340 | |||
341 | if (sz) | ||
342 | return -EINVAL; | ||
343 | |||
344 | if (sg) | ||
345 | sg_mark_end(sg); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Map memory into a scatterlist so that no pages are contiguous. Allow the | ||
352 | * same memory to be mapped more than once. | ||
353 | */ | ||
354 | static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, | ||
355 | unsigned long sz, | ||
356 | struct scatterlist *sglist, | ||
357 | unsigned int max_segs, | ||
358 | unsigned int *sg_len) | ||
359 | { | ||
360 | struct scatterlist *sg = NULL; | ||
361 | unsigned int i = mem->cnt, cnt; | ||
362 | unsigned long len; | ||
363 | void *base, *addr, *last_addr = NULL; | ||
364 | |||
365 | sg_init_table(sglist, max_segs); | ||
366 | |||
367 | *sg_len = 0; | ||
368 | while (sz && i) { | ||
369 | base = page_address(mem->arr[--i].page); | ||
370 | cnt = 1 << mem->arr[i].order; | ||
371 | while (sz && cnt) { | ||
372 | addr = base + PAGE_SIZE * --cnt; | ||
373 | if (last_addr && last_addr + PAGE_SIZE == addr) | ||
374 | continue; | ||
375 | last_addr = addr; | ||
376 | len = PAGE_SIZE; | ||
377 | if (sz < len) | ||
378 | len = sz; | ||
379 | if (sg) | ||
380 | sg = sg_next(sg); | ||
381 | else | ||
382 | sg = sglist; | ||
383 | if (!sg) | ||
384 | return -EINVAL; | ||
385 | sg_set_page(sg, virt_to_page(addr), len, 0); | ||
386 | sz -= len; | ||
387 | *sg_len += 1; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | if (sg) | ||
392 | sg_mark_end(sg); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * Calculate transfer rate in bytes per second. | ||
399 | */ | ||
400 | static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts) | ||
401 | { | ||
402 | uint64_t ns; | ||
403 | |||
404 | ns = ts->tv_sec; | ||
405 | ns *= 1000000000; | ||
406 | ns += ts->tv_nsec; | ||
407 | |||
408 | bytes *= 1000000000; | ||
409 | |||
410 | while (ns > UINT_MAX) { | ||
411 | bytes >>= 1; | ||
412 | ns >>= 1; | ||
413 | } | ||
414 | |||
415 | if (!ns) | ||
416 | return 0; | ||
417 | |||
418 | do_div(bytes, (uint32_t)ns); | ||
419 | |||
420 | return bytes; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * Print the transfer rate. | ||
425 | */ | ||
426 | static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes, | ||
427 | struct timespec *ts1, struct timespec *ts2) | ||
428 | { | ||
429 | unsigned int rate, sectors = bytes >> 9; | ||
430 | struct timespec ts; | ||
431 | |||
432 | ts = timespec_sub(*ts2, *ts1); | ||
433 | |||
434 | rate = mmc_test_rate(bytes, &ts); | ||
435 | |||
436 | printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu " | ||
437 | "seconds (%u kB/s, %u KiB/s)\n", | ||
438 | mmc_hostname(test->card->host), sectors, sectors >> 1, | ||
439 | (sectors == 1 ? ".5" : ""), (unsigned long)ts.tv_sec, | ||
440 | (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024); | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Print the average transfer rate. | ||
445 | */ | ||
446 | static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes, | ||
447 | unsigned int count, struct timespec *ts1, | ||
448 | struct timespec *ts2) | ||
449 | { | ||
450 | unsigned int rate, sectors = bytes >> 9; | ||
451 | uint64_t tot = bytes * count; | ||
452 | struct timespec ts; | ||
453 | |||
454 | ts = timespec_sub(*ts2, *ts1); | ||
455 | |||
456 | rate = mmc_test_rate(tot, &ts); | ||
457 | |||
458 | printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " | ||
459 | "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n", | ||
460 | mmc_hostname(test->card->host), count, sectors, count, | ||
461 | sectors >> 1, (sectors == 1 ? ".5" : ""), | ||
462 | (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec, | ||
463 | rate / 1000, rate / 1024); | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * Return the card size in sectors. | ||
468 | */ | ||
469 | static unsigned int mmc_test_capacity(struct mmc_card *card) | ||
470 | { | ||
471 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) | ||
472 | return card->ext_csd.sectors; | ||
473 | else | ||
474 | return card->csd.capacity << (card->csd.read_blkbits - 9); | ||
475 | } | ||
476 | |||
173 | /*******************************************************************/ | 477 | /*******************************************************************/ |
174 | /* Test preparation and cleanup */ | 478 | /* Test preparation and cleanup */ |
175 | /*******************************************************************/ | 479 | /*******************************************************************/ |
@@ -893,8 +1197,419 @@ static int mmc_test_multi_read_high(struct mmc_test_card *test) | |||
893 | return 0; | 1197 | return 0; |
894 | } | 1198 | } |
895 | 1199 | ||
1200 | #else | ||
1201 | |||
1202 | static int mmc_test_no_highmem(struct mmc_test_card *test) | ||
1203 | { | ||
1204 | printk(KERN_INFO "%s: Highmem not configured - test skipped\n", | ||
1205 | mmc_hostname(test->card->host)); | ||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
896 | #endif /* CONFIG_HIGHMEM */ | 1209 | #endif /* CONFIG_HIGHMEM */ |
897 | 1210 | ||
1211 | /* | ||
1212 | * Map sz bytes so that it can be transferred. | ||
1213 | */ | ||
1214 | static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, | ||
1215 | int max_scatter) | ||
1216 | { | ||
1217 | struct mmc_test_area *t = &test->area; | ||
1218 | |||
1219 | t->blocks = sz >> 9; | ||
1220 | |||
1221 | if (max_scatter) { | ||
1222 | return mmc_test_map_sg_max_scatter(t->mem, sz, t->sg, | ||
1223 | t->max_segs, &t->sg_len); | ||
1224 | } else { | ||
1225 | return mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs, | ||
1226 | &t->sg_len); | ||
1227 | } | ||
1228 | } | ||
1229 | |||
1230 | /* | ||
1231 | * Transfer bytes mapped by mmc_test_area_map(). | ||
1232 | */ | ||
1233 | static int mmc_test_area_transfer(struct mmc_test_card *test, | ||
1234 | unsigned int dev_addr, int write) | ||
1235 | { | ||
1236 | struct mmc_test_area *t = &test->area; | ||
1237 | |||
1238 | return mmc_test_simple_transfer(test, t->sg, t->sg_len, dev_addr, | ||
1239 | t->blocks, 512, write); | ||
1240 | } | ||
1241 | |||
1242 | /* | ||
1243 | * Map and transfer bytes. | ||
1244 | */ | ||
1245 | static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz, | ||
1246 | unsigned int dev_addr, int write, int max_scatter, | ||
1247 | int timed) | ||
1248 | { | ||
1249 | struct timespec ts1, ts2; | ||
1250 | int ret; | ||
1251 | |||
1252 | ret = mmc_test_area_map(test, sz, max_scatter); | ||
1253 | if (ret) | ||
1254 | return ret; | ||
1255 | |||
1256 | if (timed) | ||
1257 | getnstimeofday(&ts1); | ||
1258 | |||
1259 | ret = mmc_test_area_transfer(test, dev_addr, write); | ||
1260 | if (ret) | ||
1261 | return ret; | ||
1262 | |||
1263 | if (timed) | ||
1264 | getnstimeofday(&ts2); | ||
1265 | |||
1266 | if (timed) | ||
1267 | mmc_test_print_rate(test, sz, &ts1, &ts2); | ||
1268 | |||
1269 | return 0; | ||
1270 | } | ||
1271 | |||
1272 | /* | ||
1273 | * Write the test area entirely. | ||
1274 | */ | ||
1275 | static int mmc_test_area_fill(struct mmc_test_card *test) | ||
1276 | { | ||
1277 | return mmc_test_area_io(test, test->area.max_sz, test->area.dev_addr, | ||
1278 | 1, 0, 0); | ||
1279 | } | ||
1280 | |||
1281 | /* | ||
1282 | * Erase the test area entirely. | ||
1283 | */ | ||
1284 | static int mmc_test_area_erase(struct mmc_test_card *test) | ||
1285 | { | ||
1286 | struct mmc_test_area *t = &test->area; | ||
1287 | |||
1288 | if (!mmc_can_erase(test->card)) | ||
1289 | return 0; | ||
1290 | |||
1291 | return mmc_erase(test->card, t->dev_addr, test->area.max_sz >> 9, | ||
1292 | MMC_ERASE_ARG); | ||
1293 | } | ||
1294 | |||
1295 | /* | ||
1296 | * Cleanup struct mmc_test_area. | ||
1297 | */ | ||
1298 | static int mmc_test_area_cleanup(struct mmc_test_card *test) | ||
1299 | { | ||
1300 | struct mmc_test_area *t = &test->area; | ||
1301 | |||
1302 | kfree(t->sg); | ||
1303 | mmc_test_free_mem(t->mem); | ||
1304 | |||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | /* | ||
1309 | * Initialize an area for testing large transfers. The size of the area is the | ||
1310 | * preferred erase size which is a good size for optimal transfer speed. Note | ||
1311 | * that is typically 4MiB for modern cards. The test area is set to the middle | ||
1312 | * of the card because cards may have different charateristics at the front | ||
1313 | * (for FAT file system optimization). Optionally, the area is erased (if the | ||
1314 | * card supports it) which may improve write performance. Optionally, the area | ||
1315 | * is filled with data for subsequent read tests. | ||
1316 | */ | ||
1317 | static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) | ||
1318 | { | ||
1319 | struct mmc_test_area *t = &test->area; | ||
1320 | unsigned long min_sz = 64 * 1024; | ||
1321 | int ret; | ||
1322 | |||
1323 | ret = mmc_test_set_blksize(test, 512); | ||
1324 | if (ret) | ||
1325 | return ret; | ||
1326 | |||
1327 | if (test->card->pref_erase > TEST_AREA_MAX_SIZE >> 9) | ||
1328 | t->max_sz = TEST_AREA_MAX_SIZE; | ||
1329 | else | ||
1330 | t->max_sz = (unsigned long)test->card->pref_erase << 9; | ||
1331 | /* | ||
1332 | * Try to allocate enough memory for the whole area. Less is OK | ||
1333 | * because the same memory can be mapped into the scatterlist more than | ||
1334 | * once. | ||
1335 | */ | ||
1336 | t->mem = mmc_test_alloc_mem(min_sz, t->max_sz); | ||
1337 | if (!t->mem) | ||
1338 | return -ENOMEM; | ||
1339 | |||
1340 | t->max_segs = DIV_ROUND_UP(t->max_sz, PAGE_SIZE); | ||
1341 | t->sg = kmalloc(sizeof(struct scatterlist) * t->max_segs, GFP_KERNEL); | ||
1342 | if (!t->sg) { | ||
1343 | ret = -ENOMEM; | ||
1344 | goto out_free; | ||
1345 | } | ||
1346 | |||
1347 | t->dev_addr = mmc_test_capacity(test->card) / 2; | ||
1348 | t->dev_addr -= t->dev_addr % (t->max_sz >> 9); | ||
1349 | |||
1350 | if (erase) { | ||
1351 | ret = mmc_test_area_erase(test); | ||
1352 | if (ret) | ||
1353 | goto out_free; | ||
1354 | } | ||
1355 | |||
1356 | if (fill) { | ||
1357 | ret = mmc_test_area_fill(test); | ||
1358 | if (ret) | ||
1359 | goto out_free; | ||
1360 | } | ||
1361 | |||
1362 | return 0; | ||
1363 | |||
1364 | out_free: | ||
1365 | mmc_test_area_cleanup(test); | ||
1366 | return ret; | ||
1367 | } | ||
1368 | |||
1369 | /* | ||
1370 | * Prepare for large transfers. Do not erase the test area. | ||
1371 | */ | ||
1372 | static int mmc_test_area_prepare(struct mmc_test_card *test) | ||
1373 | { | ||
1374 | return mmc_test_area_init(test, 0, 0); | ||
1375 | } | ||
1376 | |||
1377 | /* | ||
1378 | * Prepare for large transfers. Do erase the test area. | ||
1379 | */ | ||
1380 | static int mmc_test_area_prepare_erase(struct mmc_test_card *test) | ||
1381 | { | ||
1382 | return mmc_test_area_init(test, 1, 0); | ||
1383 | } | ||
1384 | |||
1385 | /* | ||
1386 | * Prepare for large transfers. Erase and fill the test area. | ||
1387 | */ | ||
1388 | static int mmc_test_area_prepare_fill(struct mmc_test_card *test) | ||
1389 | { | ||
1390 | return mmc_test_area_init(test, 1, 1); | ||
1391 | } | ||
1392 | |||
1393 | /* | ||
1394 | * Test best-case performance. Best-case performance is expected from | ||
1395 | * a single large transfer. | ||
1396 | * | ||
1397 | * An additional option (max_scatter) allows the measurement of the same | ||
1398 | * transfer but with no contiguous pages in the scatter list. This tests | ||
1399 | * the efficiency of DMA to handle scattered pages. | ||
1400 | */ | ||
1401 | static int mmc_test_best_performance(struct mmc_test_card *test, int write, | ||
1402 | int max_scatter) | ||
1403 | { | ||
1404 | return mmc_test_area_io(test, test->area.max_sz, test->area.dev_addr, | ||
1405 | write, max_scatter, 1); | ||
1406 | } | ||
1407 | |||
1408 | /* | ||
1409 | * Best-case read performance. | ||
1410 | */ | ||
1411 | static int mmc_test_best_read_performance(struct mmc_test_card *test) | ||
1412 | { | ||
1413 | return mmc_test_best_performance(test, 0, 0); | ||
1414 | } | ||
1415 | |||
1416 | /* | ||
1417 | * Best-case write performance. | ||
1418 | */ | ||
1419 | static int mmc_test_best_write_performance(struct mmc_test_card *test) | ||
1420 | { | ||
1421 | return mmc_test_best_performance(test, 1, 0); | ||
1422 | } | ||
1423 | |||
1424 | /* | ||
1425 | * Best-case read performance into scattered pages. | ||
1426 | */ | ||
1427 | static int mmc_test_best_read_perf_max_scatter(struct mmc_test_card *test) | ||
1428 | { | ||
1429 | return mmc_test_best_performance(test, 0, 1); | ||
1430 | } | ||
1431 | |||
1432 | /* | ||
1433 | * Best-case write performance from scattered pages. | ||
1434 | */ | ||
1435 | static int mmc_test_best_write_perf_max_scatter(struct mmc_test_card *test) | ||
1436 | { | ||
1437 | return mmc_test_best_performance(test, 1, 1); | ||
1438 | } | ||
1439 | |||
1440 | /* | ||
1441 | * Single read performance by transfer size. | ||
1442 | */ | ||
1443 | static int mmc_test_profile_read_perf(struct mmc_test_card *test) | ||
1444 | { | ||
1445 | unsigned long sz; | ||
1446 | unsigned int dev_addr; | ||
1447 | int ret; | ||
1448 | |||
1449 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | ||
1450 | dev_addr = test->area.dev_addr + (sz >> 9); | ||
1451 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); | ||
1452 | if (ret) | ||
1453 | return ret; | ||
1454 | } | ||
1455 | dev_addr = test->area.dev_addr; | ||
1456 | return mmc_test_area_io(test, sz, dev_addr, 0, 0, 1); | ||
1457 | } | ||
1458 | |||
1459 | /* | ||
1460 | * Single write performance by transfer size. | ||
1461 | */ | ||
1462 | static int mmc_test_profile_write_perf(struct mmc_test_card *test) | ||
1463 | { | ||
1464 | unsigned long sz; | ||
1465 | unsigned int dev_addr; | ||
1466 | int ret; | ||
1467 | |||
1468 | ret = mmc_test_area_erase(test); | ||
1469 | if (ret) | ||
1470 | return ret; | ||
1471 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | ||
1472 | dev_addr = test->area.dev_addr + (sz >> 9); | ||
1473 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); | ||
1474 | if (ret) | ||
1475 | return ret; | ||
1476 | } | ||
1477 | ret = mmc_test_area_erase(test); | ||
1478 | if (ret) | ||
1479 | return ret; | ||
1480 | dev_addr = test->area.dev_addr; | ||
1481 | return mmc_test_area_io(test, sz, dev_addr, 1, 0, 1); | ||
1482 | } | ||
1483 | |||
1484 | /* | ||
1485 | * Single trim performance by transfer size. | ||
1486 | */ | ||
1487 | static int mmc_test_profile_trim_perf(struct mmc_test_card *test) | ||
1488 | { | ||
1489 | unsigned long sz; | ||
1490 | unsigned int dev_addr; | ||
1491 | struct timespec ts1, ts2; | ||
1492 | int ret; | ||
1493 | |||
1494 | if (!mmc_can_trim(test->card)) | ||
1495 | return RESULT_UNSUP_CARD; | ||
1496 | |||
1497 | if (!mmc_can_erase(test->card)) | ||
1498 | return RESULT_UNSUP_HOST; | ||
1499 | |||
1500 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | ||
1501 | dev_addr = test->area.dev_addr + (sz >> 9); | ||
1502 | getnstimeofday(&ts1); | ||
1503 | ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG); | ||
1504 | if (ret) | ||
1505 | return ret; | ||
1506 | getnstimeofday(&ts2); | ||
1507 | mmc_test_print_rate(test, sz, &ts1, &ts2); | ||
1508 | } | ||
1509 | dev_addr = test->area.dev_addr; | ||
1510 | getnstimeofday(&ts1); | ||
1511 | ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG); | ||
1512 | if (ret) | ||
1513 | return ret; | ||
1514 | getnstimeofday(&ts2); | ||
1515 | mmc_test_print_rate(test, sz, &ts1, &ts2); | ||
1516 | return 0; | ||
1517 | } | ||
1518 | |||
1519 | /* | ||
1520 | * Consecutive read performance by transfer size. | ||
1521 | */ | ||
1522 | static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) | ||
1523 | { | ||
1524 | unsigned long sz; | ||
1525 | unsigned int dev_addr, i, cnt; | ||
1526 | struct timespec ts1, ts2; | ||
1527 | int ret; | ||
1528 | |||
1529 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | ||
1530 | cnt = test->area.max_sz / sz; | ||
1531 | dev_addr = test->area.dev_addr; | ||
1532 | getnstimeofday(&ts1); | ||
1533 | for (i = 0; i < cnt; i++) { | ||
1534 | ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 0); | ||
1535 | if (ret) | ||
1536 | return ret; | ||
1537 | dev_addr += (sz >> 9); | ||
1538 | } | ||
1539 | getnstimeofday(&ts2); | ||
1540 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1541 | } | ||
1542 | return 0; | ||
1543 | } | ||
1544 | |||
1545 | /* | ||
1546 | * Consecutive write performance by transfer size. | ||
1547 | */ | ||
1548 | static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) | ||
1549 | { | ||
1550 | unsigned long sz; | ||
1551 | unsigned int dev_addr, i, cnt; | ||
1552 | struct timespec ts1, ts2; | ||
1553 | int ret; | ||
1554 | |||
1555 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | ||
1556 | ret = mmc_test_area_erase(test); | ||
1557 | if (ret) | ||
1558 | return ret; | ||
1559 | cnt = test->area.max_sz / sz; | ||
1560 | dev_addr = test->area.dev_addr; | ||
1561 | getnstimeofday(&ts1); | ||
1562 | for (i = 0; i < cnt; i++) { | ||
1563 | ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 0); | ||
1564 | if (ret) | ||
1565 | return ret; | ||
1566 | dev_addr += (sz >> 9); | ||
1567 | } | ||
1568 | getnstimeofday(&ts2); | ||
1569 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1570 | } | ||
1571 | return 0; | ||
1572 | } | ||
1573 | |||
1574 | /* | ||
1575 | * Consecutive trim performance by transfer size. | ||
1576 | */ | ||
1577 | static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test) | ||
1578 | { | ||
1579 | unsigned long sz; | ||
1580 | unsigned int dev_addr, i, cnt; | ||
1581 | struct timespec ts1, ts2; | ||
1582 | int ret; | ||
1583 | |||
1584 | if (!mmc_can_trim(test->card)) | ||
1585 | return RESULT_UNSUP_CARD; | ||
1586 | |||
1587 | if (!mmc_can_erase(test->card)) | ||
1588 | return RESULT_UNSUP_HOST; | ||
1589 | |||
1590 | for (sz = 512; sz <= test->area.max_sz; sz <<= 1) { | ||
1591 | ret = mmc_test_area_erase(test); | ||
1592 | if (ret) | ||
1593 | return ret; | ||
1594 | ret = mmc_test_area_fill(test); | ||
1595 | if (ret) | ||
1596 | return ret; | ||
1597 | cnt = test->area.max_sz / sz; | ||
1598 | dev_addr = test->area.dev_addr; | ||
1599 | getnstimeofday(&ts1); | ||
1600 | for (i = 0; i < cnt; i++) { | ||
1601 | ret = mmc_erase(test->card, dev_addr, sz >> 9, | ||
1602 | MMC_TRIM_ARG); | ||
1603 | if (ret) | ||
1604 | return ret; | ||
1605 | dev_addr += (sz >> 9); | ||
1606 | } | ||
1607 | getnstimeofday(&ts2); | ||
1608 | mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2); | ||
1609 | } | ||
1610 | return 0; | ||
1611 | } | ||
1612 | |||
898 | static const struct mmc_test_case mmc_test_cases[] = { | 1613 | static const struct mmc_test_case mmc_test_cases[] = { |
899 | { | 1614 | { |
900 | .name = "Basic write (no data verification)", | 1615 | .name = "Basic write (no data verification)", |
@@ -1040,8 +1755,100 @@ static const struct mmc_test_case mmc_test_cases[] = { | |||
1040 | .cleanup = mmc_test_cleanup, | 1755 | .cleanup = mmc_test_cleanup, |
1041 | }, | 1756 | }, |
1042 | 1757 | ||
1758 | #else | ||
1759 | |||
1760 | { | ||
1761 | .name = "Highmem write", | ||
1762 | .run = mmc_test_no_highmem, | ||
1763 | }, | ||
1764 | |||
1765 | { | ||
1766 | .name = "Highmem read", | ||
1767 | .run = mmc_test_no_highmem, | ||
1768 | }, | ||
1769 | |||
1770 | { | ||
1771 | .name = "Multi-block highmem write", | ||
1772 | .run = mmc_test_no_highmem, | ||
1773 | }, | ||
1774 | |||
1775 | { | ||
1776 | .name = "Multi-block highmem read", | ||
1777 | .run = mmc_test_no_highmem, | ||
1778 | }, | ||
1779 | |||
1043 | #endif /* CONFIG_HIGHMEM */ | 1780 | #endif /* CONFIG_HIGHMEM */ |
1044 | 1781 | ||
1782 | { | ||
1783 | .name = "Best-case read performance", | ||
1784 | .prepare = mmc_test_area_prepare_fill, | ||
1785 | .run = mmc_test_best_read_performance, | ||
1786 | .cleanup = mmc_test_area_cleanup, | ||
1787 | }, | ||
1788 | |||
1789 | { | ||
1790 | .name = "Best-case write performance", | ||
1791 | .prepare = mmc_test_area_prepare_erase, | ||
1792 | .run = mmc_test_best_write_performance, | ||
1793 | .cleanup = mmc_test_area_cleanup, | ||
1794 | }, | ||
1795 | |||
1796 | { | ||
1797 | .name = "Best-case read performance into scattered pages", | ||
1798 | .prepare = mmc_test_area_prepare_fill, | ||
1799 | .run = mmc_test_best_read_perf_max_scatter, | ||
1800 | .cleanup = mmc_test_area_cleanup, | ||
1801 | }, | ||
1802 | |||
1803 | { | ||
1804 | .name = "Best-case write performance from scattered pages", | ||
1805 | .prepare = mmc_test_area_prepare_erase, | ||
1806 | .run = mmc_test_best_write_perf_max_scatter, | ||
1807 | .cleanup = mmc_test_area_cleanup, | ||
1808 | }, | ||
1809 | |||
1810 | { | ||
1811 | .name = "Single read performance by transfer size", | ||
1812 | .prepare = mmc_test_area_prepare_fill, | ||
1813 | .run = mmc_test_profile_read_perf, | ||
1814 | .cleanup = mmc_test_area_cleanup, | ||
1815 | }, | ||
1816 | |||
1817 | { | ||
1818 | .name = "Single write performance by transfer size", | ||
1819 | .prepare = mmc_test_area_prepare, | ||
1820 | .run = mmc_test_profile_write_perf, | ||
1821 | .cleanup = mmc_test_area_cleanup, | ||
1822 | }, | ||
1823 | |||
1824 | { | ||
1825 | .name = "Single trim performance by transfer size", | ||
1826 | .prepare = mmc_test_area_prepare_fill, | ||
1827 | .run = mmc_test_profile_trim_perf, | ||
1828 | .cleanup = mmc_test_area_cleanup, | ||
1829 | }, | ||
1830 | |||
1831 | { | ||
1832 | .name = "Consecutive read performance by transfer size", | ||
1833 | .prepare = mmc_test_area_prepare_fill, | ||
1834 | .run = mmc_test_profile_seq_read_perf, | ||
1835 | .cleanup = mmc_test_area_cleanup, | ||
1836 | }, | ||
1837 | |||
1838 | { | ||
1839 | .name = "Consecutive write performance by transfer size", | ||
1840 | .prepare = mmc_test_area_prepare, | ||
1841 | .run = mmc_test_profile_seq_write_perf, | ||
1842 | .cleanup = mmc_test_area_cleanup, | ||
1843 | }, | ||
1844 | |||
1845 | { | ||
1846 | .name = "Consecutive trim performance by transfer size", | ||
1847 | .prepare = mmc_test_area_prepare, | ||
1848 | .run = mmc_test_profile_seq_trim_perf, | ||
1849 | .cleanup = mmc_test_area_cleanup, | ||
1850 | }, | ||
1851 | |||
1045 | }; | 1852 | }; |
1046 | 1853 | ||
1047 | static DEFINE_MUTEX(mmc_test_lock); | 1854 | static DEFINE_MUTEX(mmc_test_lock); |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index c77eb49eda0e..e876678176be 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -30,9 +30,9 @@ | |||
30 | static int mmc_prep_request(struct request_queue *q, struct request *req) | 30 | static int mmc_prep_request(struct request_queue *q, struct request *req) |
31 | { | 31 | { |
32 | /* | 32 | /* |
33 | * We only like normal block requests. | 33 | * We only like normal block requests and discards. |
34 | */ | 34 | */ |
35 | if (req->cmd_type != REQ_TYPE_FS) { | 35 | if (req->cmd_type != REQ_TYPE_FS && !(req->cmd_flags & REQ_DISCARD)) { |
36 | blk_dump_rq_flags(req, "MMC bad request"); | 36 | blk_dump_rq_flags(req, "MMC bad request"); |
37 | return BLKPREP_KILL; | 37 | return BLKPREP_KILL; |
38 | } | 38 | } |
@@ -130,6 +130,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
130 | blk_queue_prep_rq(mq->queue, mmc_prep_request); | 130 | blk_queue_prep_rq(mq->queue, mmc_prep_request); |
131 | blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); | 131 | blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); |
132 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); | 132 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); |
133 | if (mmc_can_erase(card)) { | ||
134 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue); | ||
135 | mq->queue->limits.max_discard_sectors = UINT_MAX; | ||
136 | if (card->erased_byte == 0) | ||
137 | mq->queue->limits.discard_zeroes_data = 1; | ||
138 | if (!mmc_can_trim(card) && is_power_of_2(card->erase_size)) { | ||
139 | mq->queue->limits.discard_granularity = | ||
140 | card->erase_size << 9; | ||
141 | mq->queue->limits.discard_alignment = | ||
142 | card->erase_size << 9; | ||
143 | } | ||
144 | if (mmc_can_secure_erase_trim(card)) | ||
145 | queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, | ||
146 | mq->queue); | ||
147 | } | ||
133 | 148 | ||
134 | #ifdef CONFIG_MMC_BLOCK_BOUNCE | 149 | #ifdef CONFIG_MMC_BLOCK_BOUNCE |
135 | if (host->max_hw_segs == 1) { | 150 | if (host->max_hw_segs == 1) { |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 49d9dcaeca49..7cd9749dc21d 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -37,6 +37,8 @@ static ssize_t mmc_type_show(struct device *dev, | |||
37 | return sprintf(buf, "SD\n"); | 37 | return sprintf(buf, "SD\n"); |
38 | case MMC_TYPE_SDIO: | 38 | case MMC_TYPE_SDIO: |
39 | return sprintf(buf, "SDIO\n"); | 39 | return sprintf(buf, "SDIO\n"); |
40 | case MMC_TYPE_SD_COMBO: | ||
41 | return sprintf(buf, "SDcombo\n"); | ||
40 | default: | 42 | default: |
41 | return -EFAULT; | 43 | return -EFAULT; |
42 | } | 44 | } |
@@ -74,6 +76,9 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
74 | case MMC_TYPE_SDIO: | 76 | case MMC_TYPE_SDIO: |
75 | type = "SDIO"; | 77 | type = "SDIO"; |
76 | break; | 78 | break; |
79 | case MMC_TYPE_SD_COMBO: | ||
80 | type = "SDcombo"; | ||
81 | break; | ||
77 | default: | 82 | default: |
78 | type = NULL; | 83 | type = NULL; |
79 | } | 84 | } |
@@ -239,6 +244,10 @@ int mmc_add_card(struct mmc_card *card) | |||
239 | case MMC_TYPE_SDIO: | 244 | case MMC_TYPE_SDIO: |
240 | type = "SDIO"; | 245 | type = "SDIO"; |
241 | break; | 246 | break; |
247 | case MMC_TYPE_SD_COMBO: | ||
248 | type = "SD-combo"; | ||
249 | if (mmc_card_blockaddr(card)) | ||
250 | type = "SDHC-combo"; | ||
242 | default: | 251 | default: |
243 | type = "?"; | 252 | type = "?"; |
244 | break; | 253 | break; |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 569e94da844c..5db49b124ffa 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1050,6 +1050,352 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) | |||
1050 | 1050 | ||
1051 | EXPORT_SYMBOL(mmc_detect_change); | 1051 | EXPORT_SYMBOL(mmc_detect_change); |
1052 | 1052 | ||
1053 | void mmc_init_erase(struct mmc_card *card) | ||
1054 | { | ||
1055 | unsigned int sz; | ||
1056 | |||
1057 | if (is_power_of_2(card->erase_size)) | ||
1058 | card->erase_shift = ffs(card->erase_size) - 1; | ||
1059 | else | ||
1060 | card->erase_shift = 0; | ||
1061 | |||
1062 | /* | ||
1063 | * It is possible to erase an arbitrarily large area of an SD or MMC | ||
1064 | * card. That is not desirable because it can take a long time | ||
1065 | * (minutes) potentially delaying more important I/O, and also the | ||
1066 | * timeout calculations become increasingly hugely over-estimated. | ||
1067 | * Consequently, 'pref_erase' is defined as a guide to limit erases | ||
1068 | * to that size and alignment. | ||
1069 | * | ||
1070 | * For SD cards that define Allocation Unit size, limit erases to one | ||
1071 | * Allocation Unit at a time. For MMC cards that define High Capacity | ||
1072 | * Erase Size, whether it is switched on or not, limit to that size. | ||
1073 | * Otherwise just have a stab at a good value. For modern cards it | ||
1074 | * will end up being 4MiB. Note that if the value is too small, it | ||
1075 | * can end up taking longer to erase. | ||
1076 | */ | ||
1077 | if (mmc_card_sd(card) && card->ssr.au) { | ||
1078 | card->pref_erase = card->ssr.au; | ||
1079 | card->erase_shift = ffs(card->ssr.au) - 1; | ||
1080 | } else if (card->ext_csd.hc_erase_size) { | ||
1081 | card->pref_erase = card->ext_csd.hc_erase_size; | ||
1082 | } else { | ||
1083 | sz = (card->csd.capacity << (card->csd.read_blkbits - 9)) >> 11; | ||
1084 | if (sz < 128) | ||
1085 | card->pref_erase = 512 * 1024 / 512; | ||
1086 | else if (sz < 512) | ||
1087 | card->pref_erase = 1024 * 1024 / 512; | ||
1088 | else if (sz < 1024) | ||
1089 | card->pref_erase = 2 * 1024 * 1024 / 512; | ||
1090 | else | ||
1091 | card->pref_erase = 4 * 1024 * 1024 / 512; | ||
1092 | if (card->pref_erase < card->erase_size) | ||
1093 | card->pref_erase = card->erase_size; | ||
1094 | else { | ||
1095 | sz = card->pref_erase % card->erase_size; | ||
1096 | if (sz) | ||
1097 | card->pref_erase += card->erase_size - sz; | ||
1098 | } | ||
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | static void mmc_set_mmc_erase_timeout(struct mmc_card *card, | ||
1103 | struct mmc_command *cmd, | ||
1104 | unsigned int arg, unsigned int qty) | ||
1105 | { | ||
1106 | unsigned int erase_timeout; | ||
1107 | |||
1108 | if (card->ext_csd.erase_group_def & 1) { | ||
1109 | /* High Capacity Erase Group Size uses HC timeouts */ | ||
1110 | if (arg == MMC_TRIM_ARG) | ||
1111 | erase_timeout = card->ext_csd.trim_timeout; | ||
1112 | else | ||
1113 | erase_timeout = card->ext_csd.hc_erase_timeout; | ||
1114 | } else { | ||
1115 | /* CSD Erase Group Size uses write timeout */ | ||
1116 | unsigned int mult = (10 << card->csd.r2w_factor); | ||
1117 | unsigned int timeout_clks = card->csd.tacc_clks * mult; | ||
1118 | unsigned int timeout_us; | ||
1119 | |||
1120 | /* Avoid overflow: e.g. tacc_ns=80000000 mult=1280 */ | ||
1121 | if (card->csd.tacc_ns < 1000000) | ||
1122 | timeout_us = (card->csd.tacc_ns * mult) / 1000; | ||
1123 | else | ||
1124 | timeout_us = (card->csd.tacc_ns / 1000) * mult; | ||
1125 | |||
1126 | /* | ||
1127 | * ios.clock is only a target. The real clock rate might be | ||
1128 | * less but not that much less, so fudge it by multiplying by 2. | ||
1129 | */ | ||
1130 | timeout_clks <<= 1; | ||
1131 | timeout_us += (timeout_clks * 1000) / | ||
1132 | (card->host->ios.clock / 1000); | ||
1133 | |||
1134 | erase_timeout = timeout_us / 1000; | ||
1135 | |||
1136 | /* | ||
1137 | * Theoretically, the calculation could underflow so round up | ||
1138 | * to 1ms in that case. | ||
1139 | */ | ||
1140 | if (!erase_timeout) | ||
1141 | erase_timeout = 1; | ||
1142 | } | ||
1143 | |||
1144 | /* Multiplier for secure operations */ | ||
1145 | if (arg & MMC_SECURE_ARGS) { | ||
1146 | if (arg == MMC_SECURE_ERASE_ARG) | ||
1147 | erase_timeout *= card->ext_csd.sec_erase_mult; | ||
1148 | else | ||
1149 | erase_timeout *= card->ext_csd.sec_trim_mult; | ||
1150 | } | ||
1151 | |||
1152 | erase_timeout *= qty; | ||
1153 | |||
1154 | /* | ||
1155 | * Ensure at least a 1 second timeout for SPI as per | ||
1156 | * 'mmc_set_data_timeout()' | ||
1157 | */ | ||
1158 | if (mmc_host_is_spi(card->host) && erase_timeout < 1000) | ||
1159 | erase_timeout = 1000; | ||
1160 | |||
1161 | cmd->erase_timeout = erase_timeout; | ||
1162 | } | ||
1163 | |||
1164 | static void mmc_set_sd_erase_timeout(struct mmc_card *card, | ||
1165 | struct mmc_command *cmd, unsigned int arg, | ||
1166 | unsigned int qty) | ||
1167 | { | ||
1168 | if (card->ssr.erase_timeout) { | ||
1169 | /* Erase timeout specified in SD Status Register (SSR) */ | ||
1170 | cmd->erase_timeout = card->ssr.erase_timeout * qty + | ||
1171 | card->ssr.erase_offset; | ||
1172 | } else { | ||
1173 | /* | ||
1174 | * Erase timeout not specified in SD Status Register (SSR) so | ||
1175 | * use 250ms per write block. | ||
1176 | */ | ||
1177 | cmd->erase_timeout = 250 * qty; | ||
1178 | } | ||
1179 | |||
1180 | /* Must not be less than 1 second */ | ||
1181 | if (cmd->erase_timeout < 1000) | ||
1182 | cmd->erase_timeout = 1000; | ||
1183 | } | ||
1184 | |||
1185 | static void mmc_set_erase_timeout(struct mmc_card *card, | ||
1186 | struct mmc_command *cmd, unsigned int arg, | ||
1187 | unsigned int qty) | ||
1188 | { | ||
1189 | if (mmc_card_sd(card)) | ||
1190 | mmc_set_sd_erase_timeout(card, cmd, arg, qty); | ||
1191 | else | ||
1192 | mmc_set_mmc_erase_timeout(card, cmd, arg, qty); | ||
1193 | } | ||
1194 | |||
1195 | static int mmc_do_erase(struct mmc_card *card, unsigned int from, | ||
1196 | unsigned int to, unsigned int arg) | ||
1197 | { | ||
1198 | struct mmc_command cmd; | ||
1199 | unsigned int qty = 0; | ||
1200 | int err; | ||
1201 | |||
1202 | /* | ||
1203 | * qty is used to calculate the erase timeout which depends on how many | ||
1204 | * erase groups (or allocation units in SD terminology) are affected. | ||
1205 | * We count erasing part of an erase group as one erase group. | ||
1206 | * For SD, the allocation units are always a power of 2. For MMC, the | ||
1207 | * erase group size is almost certainly also power of 2, but it does not | ||
1208 | * seem to insist on that in the JEDEC standard, so we fall back to | ||
1209 | * division in that case. SD may not specify an allocation unit size, | ||
1210 | * in which case the timeout is based on the number of write blocks. | ||
1211 | * | ||
1212 | * Note that the timeout for secure trim 2 will only be correct if the | ||
1213 | * number of erase groups specified is the same as the total of all | ||
1214 | * preceding secure trim 1 commands. Since the power may have been | ||
1215 | * lost since the secure trim 1 commands occurred, it is generally | ||
1216 | * impossible to calculate the secure trim 2 timeout correctly. | ||
1217 | */ | ||
1218 | if (card->erase_shift) | ||
1219 | qty += ((to >> card->erase_shift) - | ||
1220 | (from >> card->erase_shift)) + 1; | ||
1221 | else if (mmc_card_sd(card)) | ||
1222 | qty += to - from + 1; | ||
1223 | else | ||
1224 | qty += ((to / card->erase_size) - | ||
1225 | (from / card->erase_size)) + 1; | ||
1226 | |||
1227 | if (!mmc_card_blockaddr(card)) { | ||
1228 | from <<= 9; | ||
1229 | to <<= 9; | ||
1230 | } | ||
1231 | |||
1232 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1233 | if (mmc_card_sd(card)) | ||
1234 | cmd.opcode = SD_ERASE_WR_BLK_START; | ||
1235 | else | ||
1236 | cmd.opcode = MMC_ERASE_GROUP_START; | ||
1237 | cmd.arg = from; | ||
1238 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
1239 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1240 | if (err) { | ||
1241 | printk(KERN_ERR "mmc_erase: group start error %d, " | ||
1242 | "status %#x\n", err, cmd.resp[0]); | ||
1243 | err = -EINVAL; | ||
1244 | goto out; | ||
1245 | } | ||
1246 | |||
1247 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1248 | if (mmc_card_sd(card)) | ||
1249 | cmd.opcode = SD_ERASE_WR_BLK_END; | ||
1250 | else | ||
1251 | cmd.opcode = MMC_ERASE_GROUP_END; | ||
1252 | cmd.arg = to; | ||
1253 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
1254 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1255 | if (err) { | ||
1256 | printk(KERN_ERR "mmc_erase: group end error %d, status %#x\n", | ||
1257 | err, cmd.resp[0]); | ||
1258 | err = -EINVAL; | ||
1259 | goto out; | ||
1260 | } | ||
1261 | |||
1262 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1263 | cmd.opcode = MMC_ERASE; | ||
1264 | cmd.arg = arg; | ||
1265 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | ||
1266 | mmc_set_erase_timeout(card, &cmd, arg, qty); | ||
1267 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1268 | if (err) { | ||
1269 | printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n", | ||
1270 | err, cmd.resp[0]); | ||
1271 | err = -EIO; | ||
1272 | goto out; | ||
1273 | } | ||
1274 | |||
1275 | if (mmc_host_is_spi(card->host)) | ||
1276 | goto out; | ||
1277 | |||
1278 | do { | ||
1279 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1280 | cmd.opcode = MMC_SEND_STATUS; | ||
1281 | cmd.arg = card->rca << 16; | ||
1282 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | ||
1283 | /* Do not retry else we can't see errors */ | ||
1284 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | ||
1285 | if (err || (cmd.resp[0] & 0xFDF92000)) { | ||
1286 | printk(KERN_ERR "error %d requesting status %#x\n", | ||
1287 | err, cmd.resp[0]); | ||
1288 | err = -EIO; | ||
1289 | goto out; | ||
1290 | } | ||
1291 | } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || | ||
1292 | R1_CURRENT_STATE(cmd.resp[0]) == 7); | ||
1293 | out: | ||
1294 | return err; | ||
1295 | } | ||
1296 | |||
1297 | /** | ||
1298 | * mmc_erase - erase sectors. | ||
1299 | * @card: card to erase | ||
1300 | * @from: first sector to erase | ||
1301 | * @nr: number of sectors to erase | ||
1302 | * @arg: erase command argument (SD supports only %MMC_ERASE_ARG) | ||
1303 | * | ||
1304 | * Caller must claim host before calling this function. | ||
1305 | */ | ||
1306 | int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, | ||
1307 | unsigned int arg) | ||
1308 | { | ||
1309 | unsigned int rem, to = from + nr; | ||
1310 | |||
1311 | if (!(card->host->caps & MMC_CAP_ERASE) || | ||
1312 | !(card->csd.cmdclass & CCC_ERASE)) | ||
1313 | return -EOPNOTSUPP; | ||
1314 | |||
1315 | if (!card->erase_size) | ||
1316 | return -EOPNOTSUPP; | ||
1317 | |||
1318 | if (mmc_card_sd(card) && arg != MMC_ERASE_ARG) | ||
1319 | return -EOPNOTSUPP; | ||
1320 | |||
1321 | if ((arg & MMC_SECURE_ARGS) && | ||
1322 | !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)) | ||
1323 | return -EOPNOTSUPP; | ||
1324 | |||
1325 | if ((arg & MMC_TRIM_ARGS) && | ||
1326 | !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)) | ||
1327 | return -EOPNOTSUPP; | ||
1328 | |||
1329 | if (arg == MMC_SECURE_ERASE_ARG) { | ||
1330 | if (from % card->erase_size || nr % card->erase_size) | ||
1331 | return -EINVAL; | ||
1332 | } | ||
1333 | |||
1334 | if (arg == MMC_ERASE_ARG) { | ||
1335 | rem = from % card->erase_size; | ||
1336 | if (rem) { | ||
1337 | rem = card->erase_size - rem; | ||
1338 | from += rem; | ||
1339 | if (nr > rem) | ||
1340 | nr -= rem; | ||
1341 | else | ||
1342 | return 0; | ||
1343 | } | ||
1344 | rem = nr % card->erase_size; | ||
1345 | if (rem) | ||
1346 | nr -= rem; | ||
1347 | } | ||
1348 | |||
1349 | if (nr == 0) | ||
1350 | return 0; | ||
1351 | |||
1352 | to = from + nr; | ||
1353 | |||
1354 | if (to <= from) | ||
1355 | return -EINVAL; | ||
1356 | |||
1357 | /* 'from' and 'to' are inclusive */ | ||
1358 | to -= 1; | ||
1359 | |||
1360 | return mmc_do_erase(card, from, to, arg); | ||
1361 | } | ||
1362 | EXPORT_SYMBOL(mmc_erase); | ||
1363 | |||
1364 | int mmc_can_erase(struct mmc_card *card) | ||
1365 | { | ||
1366 | if ((card->host->caps & MMC_CAP_ERASE) && | ||
1367 | (card->csd.cmdclass & CCC_ERASE) && card->erase_size) | ||
1368 | return 1; | ||
1369 | return 0; | ||
1370 | } | ||
1371 | EXPORT_SYMBOL(mmc_can_erase); | ||
1372 | |||
1373 | int mmc_can_trim(struct mmc_card *card) | ||
1374 | { | ||
1375 | if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) | ||
1376 | return 1; | ||
1377 | return 0; | ||
1378 | } | ||
1379 | EXPORT_SYMBOL(mmc_can_trim); | ||
1380 | |||
1381 | int mmc_can_secure_erase_trim(struct mmc_card *card) | ||
1382 | { | ||
1383 | if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN) | ||
1384 | return 1; | ||
1385 | return 0; | ||
1386 | } | ||
1387 | EXPORT_SYMBOL(mmc_can_secure_erase_trim); | ||
1388 | |||
1389 | int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | ||
1390 | unsigned int nr) | ||
1391 | { | ||
1392 | if (!card->erase_size) | ||
1393 | return 0; | ||
1394 | if (from % card->erase_size || nr % card->erase_size) | ||
1395 | return 0; | ||
1396 | return 1; | ||
1397 | } | ||
1398 | EXPORT_SYMBOL(mmc_erase_group_aligned); | ||
1053 | 1399 | ||
1054 | void mmc_rescan(struct work_struct *work) | 1400 | void mmc_rescan(struct work_struct *work) |
1055 | { | 1401 | { |
@@ -1057,6 +1403,17 @@ void mmc_rescan(struct work_struct *work) | |||
1057 | container_of(work, struct mmc_host, detect.work); | 1403 | container_of(work, struct mmc_host, detect.work); |
1058 | u32 ocr; | 1404 | u32 ocr; |
1059 | int err; | 1405 | int err; |
1406 | unsigned long flags; | ||
1407 | |||
1408 | spin_lock_irqsave(&host->lock, flags); | ||
1409 | |||
1410 | if (host->rescan_disable) { | ||
1411 | spin_unlock_irqrestore(&host->lock, flags); | ||
1412 | return; | ||
1413 | } | ||
1414 | |||
1415 | spin_unlock_irqrestore(&host->lock, flags); | ||
1416 | |||
1060 | 1417 | ||
1061 | mmc_bus_get(host); | 1418 | mmc_bus_get(host); |
1062 | 1419 | ||
@@ -1099,8 +1456,15 @@ void mmc_rescan(struct work_struct *work) | |||
1099 | */ | 1456 | */ |
1100 | err = mmc_send_io_op_cond(host, 0, &ocr); | 1457 | err = mmc_send_io_op_cond(host, 0, &ocr); |
1101 | if (!err) { | 1458 | if (!err) { |
1102 | if (mmc_attach_sdio(host, ocr)) | 1459 | if (mmc_attach_sdio(host, ocr)) { |
1103 | mmc_power_off(host); | 1460 | mmc_claim_host(host); |
1461 | /* try SDMEM (but not MMC) even if SDIO is broken */ | ||
1462 | if (mmc_send_app_op_cond(host, 0, &ocr)) | ||
1463 | goto out_fail; | ||
1464 | |||
1465 | if (mmc_attach_sd(host, ocr)) | ||
1466 | mmc_power_off(host); | ||
1467 | } | ||
1104 | goto out; | 1468 | goto out; |
1105 | } | 1469 | } |
1106 | 1470 | ||
@@ -1124,6 +1488,7 @@ void mmc_rescan(struct work_struct *work) | |||
1124 | goto out; | 1488 | goto out; |
1125 | } | 1489 | } |
1126 | 1490 | ||
1491 | out_fail: | ||
1127 | mmc_release_host(host); | 1492 | mmc_release_host(host); |
1128 | mmc_power_off(host); | 1493 | mmc_power_off(host); |
1129 | 1494 | ||
@@ -1266,19 +1631,6 @@ int mmc_suspend_host(struct mmc_host *host) | |||
1266 | if (host->bus_ops && !host->bus_dead) { | 1631 | if (host->bus_ops && !host->bus_dead) { |
1267 | if (host->bus_ops->suspend) | 1632 | if (host->bus_ops->suspend) |
1268 | err = host->bus_ops->suspend(host); | 1633 | err = host->bus_ops->suspend(host); |
1269 | if (err == -ENOSYS || !host->bus_ops->resume) { | ||
1270 | /* | ||
1271 | * We simply "remove" the card in this case. | ||
1272 | * It will be redetected on resume. | ||
1273 | */ | ||
1274 | if (host->bus_ops->remove) | ||
1275 | host->bus_ops->remove(host); | ||
1276 | mmc_claim_host(host); | ||
1277 | mmc_detach_bus(host); | ||
1278 | mmc_release_host(host); | ||
1279 | host->pm_flags = 0; | ||
1280 | err = 0; | ||
1281 | } | ||
1282 | } | 1634 | } |
1283 | mmc_bus_put(host); | 1635 | mmc_bus_put(host); |
1284 | 1636 | ||
@@ -1310,28 +1662,61 @@ int mmc_resume_host(struct mmc_host *host) | |||
1310 | printk(KERN_WARNING "%s: error %d during resume " | 1662 | printk(KERN_WARNING "%s: error %d during resume " |
1311 | "(card was removed?)\n", | 1663 | "(card was removed?)\n", |
1312 | mmc_hostname(host), err); | 1664 | mmc_hostname(host), err); |
1313 | if (host->bus_ops->remove) | ||
1314 | host->bus_ops->remove(host); | ||
1315 | mmc_claim_host(host); | ||
1316 | mmc_detach_bus(host); | ||
1317 | mmc_release_host(host); | ||
1318 | /* no need to bother upper layers */ | ||
1319 | err = 0; | 1665 | err = 0; |
1320 | } | 1666 | } |
1321 | } | 1667 | } |
1322 | mmc_bus_put(host); | 1668 | mmc_bus_put(host); |
1323 | 1669 | ||
1324 | /* | ||
1325 | * We add a slight delay here so that resume can progress | ||
1326 | * in parallel. | ||
1327 | */ | ||
1328 | mmc_detect_change(host, 1); | ||
1329 | |||
1330 | return err; | 1670 | return err; |
1331 | } | 1671 | } |
1332 | |||
1333 | EXPORT_SYMBOL(mmc_resume_host); | 1672 | EXPORT_SYMBOL(mmc_resume_host); |
1334 | 1673 | ||
1674 | /* Do the card removal on suspend if card is assumed removeable | ||
1675 | * Do that in pm notifier while userspace isn't yet frozen, so we will be able | ||
1676 | to sync the card. | ||
1677 | */ | ||
1678 | int mmc_pm_notify(struct notifier_block *notify_block, | ||
1679 | unsigned long mode, void *unused) | ||
1680 | { | ||
1681 | struct mmc_host *host = container_of( | ||
1682 | notify_block, struct mmc_host, pm_notify); | ||
1683 | unsigned long flags; | ||
1684 | |||
1685 | |||
1686 | switch (mode) { | ||
1687 | case PM_HIBERNATION_PREPARE: | ||
1688 | case PM_SUSPEND_PREPARE: | ||
1689 | |||
1690 | spin_lock_irqsave(&host->lock, flags); | ||
1691 | host->rescan_disable = 1; | ||
1692 | spin_unlock_irqrestore(&host->lock, flags); | ||
1693 | cancel_delayed_work_sync(&host->detect); | ||
1694 | |||
1695 | if (!host->bus_ops || host->bus_ops->suspend) | ||
1696 | break; | ||
1697 | |||
1698 | mmc_claim_host(host); | ||
1699 | |||
1700 | if (host->bus_ops->remove) | ||
1701 | host->bus_ops->remove(host); | ||
1702 | |||
1703 | mmc_detach_bus(host); | ||
1704 | mmc_release_host(host); | ||
1705 | host->pm_flags = 0; | ||
1706 | break; | ||
1707 | |||
1708 | case PM_POST_SUSPEND: | ||
1709 | case PM_POST_HIBERNATION: | ||
1710 | |||
1711 | spin_lock_irqsave(&host->lock, flags); | ||
1712 | host->rescan_disable = 0; | ||
1713 | spin_unlock_irqrestore(&host->lock, flags); | ||
1714 | mmc_detect_change(host, 0); | ||
1715 | |||
1716 | } | ||
1717 | |||
1718 | return 0; | ||
1719 | } | ||
1335 | #endif | 1720 | #endif |
1336 | 1721 | ||
1337 | static int __init mmc_init(void) | 1722 | static int __init mmc_init(void) |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index a811c52a1659..9d9eef50e5d1 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
@@ -29,6 +29,8 @@ struct mmc_bus_ops { | |||
29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); | 29 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); |
30 | void mmc_detach_bus(struct mmc_host *host); | 30 | void mmc_detach_bus(struct mmc_host *host); |
31 | 31 | ||
32 | void mmc_init_erase(struct mmc_card *card); | ||
33 | |||
32 | void mmc_set_chip_select(struct mmc_host *host, int mode); | 34 | void mmc_set_chip_select(struct mmc_host *host, int mode); |
33 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); | 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); |
34 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); | 36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); |
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 47353909e345..0efe631e50ca 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
18 | #include <linux/leds.h> | 18 | #include <linux/leds.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/suspend.h> | ||
20 | 21 | ||
21 | #include <linux/mmc/host.h> | 22 | #include <linux/mmc/host.h> |
22 | 23 | ||
@@ -85,6 +86,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
85 | init_waitqueue_head(&host->wq); | 86 | init_waitqueue_head(&host->wq); |
86 | INIT_DELAYED_WORK(&host->detect, mmc_rescan); | 87 | INIT_DELAYED_WORK(&host->detect, mmc_rescan); |
87 | INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); | 88 | INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); |
89 | host->pm_notify.notifier_call = mmc_pm_notify; | ||
88 | 90 | ||
89 | /* | 91 | /* |
90 | * By default, hosts do not support SGIO or large requests. | 92 | * By default, hosts do not support SGIO or large requests. |
@@ -133,6 +135,7 @@ int mmc_add_host(struct mmc_host *host) | |||
133 | #endif | 135 | #endif |
134 | 136 | ||
135 | mmc_start_host(host); | 137 | mmc_start_host(host); |
138 | register_pm_notifier(&host->pm_notify); | ||
136 | 139 | ||
137 | return 0; | 140 | return 0; |
138 | } | 141 | } |
@@ -149,6 +152,7 @@ EXPORT_SYMBOL(mmc_add_host); | |||
149 | */ | 152 | */ |
150 | void mmc_remove_host(struct mmc_host *host) | 153 | void mmc_remove_host(struct mmc_host *host) |
151 | { | 154 | { |
155 | unregister_pm_notifier(&host->pm_notify); | ||
152 | mmc_stop_host(host); | 156 | mmc_stop_host(host); |
153 | 157 | ||
154 | #ifdef CONFIG_DEBUG_FS | 158 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 89f7a25b7ac1..6909a54c39be 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -108,23 +108,34 @@ static int mmc_decode_cid(struct mmc_card *card) | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static void mmc_set_erase_size(struct mmc_card *card) | ||
112 | { | ||
113 | if (card->ext_csd.erase_group_def & 1) | ||
114 | card->erase_size = card->ext_csd.hc_erase_size; | ||
115 | else | ||
116 | card->erase_size = card->csd.erase_size; | ||
117 | |||
118 | mmc_init_erase(card); | ||
119 | } | ||
120 | |||
111 | /* | 121 | /* |
112 | * Given a 128-bit response, decode to our card CSD structure. | 122 | * Given a 128-bit response, decode to our card CSD structure. |
113 | */ | 123 | */ |
114 | static int mmc_decode_csd(struct mmc_card *card) | 124 | static int mmc_decode_csd(struct mmc_card *card) |
115 | { | 125 | { |
116 | struct mmc_csd *csd = &card->csd; | 126 | struct mmc_csd *csd = &card->csd; |
117 | unsigned int e, m, csd_struct; | 127 | unsigned int e, m, a, b; |
118 | u32 *resp = card->raw_csd; | 128 | u32 *resp = card->raw_csd; |
119 | 129 | ||
120 | /* | 130 | /* |
121 | * We only understand CSD structure v1.1 and v1.2. | 131 | * We only understand CSD structure v1.1 and v1.2. |
122 | * v1.2 has extra information in bits 15, 11 and 10. | 132 | * v1.2 has extra information in bits 15, 11 and 10. |
133 | * We also support eMMC v4.4 & v4.41. | ||
123 | */ | 134 | */ |
124 | csd_struct = UNSTUFF_BITS(resp, 126, 2); | 135 | csd->structure = UNSTUFF_BITS(resp, 126, 2); |
125 | if (csd_struct != 1 && csd_struct != 2) { | 136 | if (csd->structure == 0) { |
126 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", | 137 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", |
127 | mmc_hostname(card->host), csd_struct); | 138 | mmc_hostname(card->host), csd->structure); |
128 | return -EINVAL; | 139 | return -EINVAL; |
129 | } | 140 | } |
130 | 141 | ||
@@ -151,6 +162,13 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
151 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | 162 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); |
152 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | 163 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); |
153 | 164 | ||
165 | if (csd->write_blkbits >= 9) { | ||
166 | a = UNSTUFF_BITS(resp, 42, 5); | ||
167 | b = UNSTUFF_BITS(resp, 37, 5); | ||
168 | csd->erase_size = (a + 1) * (b + 1); | ||
169 | csd->erase_size <<= csd->write_blkbits - 9; | ||
170 | } | ||
171 | |||
154 | return 0; | 172 | return 0; |
155 | } | 173 | } |
156 | 174 | ||
@@ -207,11 +225,22 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
207 | goto out; | 225 | goto out; |
208 | } | 226 | } |
209 | 227 | ||
228 | /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ | ||
229 | if (card->csd.structure == 3) { | ||
230 | int ext_csd_struct = ext_csd[EXT_CSD_STRUCTURE]; | ||
231 | if (ext_csd_struct > 2) { | ||
232 | printk(KERN_ERR "%s: unrecognised EXT_CSD structure " | ||
233 | "version %d\n", mmc_hostname(card->host), | ||
234 | ext_csd_struct); | ||
235 | err = -EINVAL; | ||
236 | goto out; | ||
237 | } | ||
238 | } | ||
239 | |||
210 | card->ext_csd.rev = ext_csd[EXT_CSD_REV]; | 240 | card->ext_csd.rev = ext_csd[EXT_CSD_REV]; |
211 | if (card->ext_csd.rev > 5) { | 241 | if (card->ext_csd.rev > 5) { |
212 | printk(KERN_ERR "%s: unrecognised EXT_CSD structure " | 242 | printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", |
213 | "version %d\n", mmc_hostname(card->host), | 243 | mmc_hostname(card->host), card->ext_csd.rev); |
214 | card->ext_csd.rev); | ||
215 | err = -EINVAL; | 244 | err = -EINVAL; |
216 | goto out; | 245 | goto out; |
217 | } | 246 | } |
@@ -222,7 +251,9 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
222 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | | 251 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | |
223 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | | 252 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | |
224 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; | 253 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; |
225 | if (card->ext_csd.sectors) | 254 | |
255 | /* Cards with density > 2GiB are sector addressed */ | ||
256 | if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) | ||
226 | mmc_card_set_blockaddr(card); | 257 | mmc_card_set_blockaddr(card); |
227 | } | 258 | } |
228 | 259 | ||
@@ -247,8 +278,30 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
247 | if (sa_shift > 0 && sa_shift <= 0x17) | 278 | if (sa_shift > 0 && sa_shift <= 0x17) |
248 | card->ext_csd.sa_timeout = | 279 | card->ext_csd.sa_timeout = |
249 | 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; | 280 | 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; |
281 | card->ext_csd.erase_group_def = | ||
282 | ext_csd[EXT_CSD_ERASE_GROUP_DEF]; | ||
283 | card->ext_csd.hc_erase_timeout = 300 * | ||
284 | ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; | ||
285 | card->ext_csd.hc_erase_size = | ||
286 | ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; | ||
250 | } | 287 | } |
251 | 288 | ||
289 | if (card->ext_csd.rev >= 4) { | ||
290 | card->ext_csd.sec_trim_mult = | ||
291 | ext_csd[EXT_CSD_SEC_TRIM_MULT]; | ||
292 | card->ext_csd.sec_erase_mult = | ||
293 | ext_csd[EXT_CSD_SEC_ERASE_MULT]; | ||
294 | card->ext_csd.sec_feature_support = | ||
295 | ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; | ||
296 | card->ext_csd.trim_timeout = 300 * | ||
297 | ext_csd[EXT_CSD_TRIM_MULT]; | ||
298 | } | ||
299 | |||
300 | if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) | ||
301 | card->erased_byte = 0xFF; | ||
302 | else | ||
303 | card->erased_byte = 0x0; | ||
304 | |||
252 | out: | 305 | out: |
253 | kfree(ext_csd); | 306 | kfree(ext_csd); |
254 | 307 | ||
@@ -260,6 +313,8 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], | |||
260 | MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | 313 | MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], |
261 | card->raw_csd[2], card->raw_csd[3]); | 314 | card->raw_csd[2], card->raw_csd[3]); |
262 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | 315 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); |
316 | MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); | ||
317 | MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); | ||
263 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | 318 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); |
264 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | 319 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); |
265 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); | 320 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); |
@@ -271,6 +326,8 @@ static struct attribute *mmc_std_attrs[] = { | |||
271 | &dev_attr_cid.attr, | 326 | &dev_attr_cid.attr, |
272 | &dev_attr_csd.attr, | 327 | &dev_attr_csd.attr, |
273 | &dev_attr_date.attr, | 328 | &dev_attr_date.attr, |
329 | &dev_attr_erase_size.attr, | ||
330 | &dev_attr_preferred_erase_size.attr, | ||
274 | &dev_attr_fwrev.attr, | 331 | &dev_attr_fwrev.attr, |
275 | &dev_attr_hwrev.attr, | 332 | &dev_attr_hwrev.attr, |
276 | &dev_attr_manfid.attr, | 333 | &dev_attr_manfid.attr, |
@@ -407,6 +464,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
407 | err = mmc_read_ext_csd(card); | 464 | err = mmc_read_ext_csd(card); |
408 | if (err) | 465 | if (err) |
409 | goto free_card; | 466 | goto free_card; |
467 | /* Erase size depends on CSD and Extended CSD */ | ||
468 | mmc_set_erase_size(card); | ||
410 | } | 469 | } |
411 | 470 | ||
412 | /* | 471 | /* |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5eac21df4809..0f5241085557 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -59,7 +59,7 @@ static const unsigned int tacc_mant[] = { | |||
59 | /* | 59 | /* |
60 | * Given the decoded CSD structure, decode the raw CID to our CID structure. | 60 | * Given the decoded CSD structure, decode the raw CID to our CID structure. |
61 | */ | 61 | */ |
62 | static void mmc_decode_cid(struct mmc_card *card) | 62 | void mmc_decode_cid(struct mmc_card *card) |
63 | { | 63 | { |
64 | u32 *resp = card->raw_cid; | 64 | u32 *resp = card->raw_cid; |
65 | 65 | ||
@@ -119,6 +119,13 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
119 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); | 119 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); |
120 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | 120 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); |
121 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | 121 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); |
122 | |||
123 | if (UNSTUFF_BITS(resp, 46, 1)) { | ||
124 | csd->erase_size = 1; | ||
125 | } else if (csd->write_blkbits >= 9) { | ||
126 | csd->erase_size = UNSTUFF_BITS(resp, 39, 7) + 1; | ||
127 | csd->erase_size <<= csd->write_blkbits - 9; | ||
128 | } | ||
122 | break; | 129 | break; |
123 | case 1: | 130 | case 1: |
124 | /* | 131 | /* |
@@ -147,6 +154,7 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
147 | csd->r2w_factor = 4; /* Unused */ | 154 | csd->r2w_factor = 4; /* Unused */ |
148 | csd->write_blkbits = 9; | 155 | csd->write_blkbits = 9; |
149 | csd->write_partial = 0; | 156 | csd->write_partial = 0; |
157 | csd->erase_size = 1; | ||
150 | break; | 158 | break; |
151 | default: | 159 | default: |
152 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", | 160 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", |
@@ -154,6 +162,8 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
154 | return -EINVAL; | 162 | return -EINVAL; |
155 | } | 163 | } |
156 | 164 | ||
165 | card->erase_size = csd->erase_size; | ||
166 | |||
157 | return 0; | 167 | return 0; |
158 | } | 168 | } |
159 | 169 | ||
@@ -179,10 +189,68 @@ static int mmc_decode_scr(struct mmc_card *card) | |||
179 | scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); | 189 | scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); |
180 | scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); | 190 | scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); |
181 | 191 | ||
192 | if (UNSTUFF_BITS(resp, 55, 1)) | ||
193 | card->erased_byte = 0xFF; | ||
194 | else | ||
195 | card->erased_byte = 0x0; | ||
196 | |||
182 | return 0; | 197 | return 0; |
183 | } | 198 | } |
184 | 199 | ||
185 | /* | 200 | /* |
201 | * Fetch and process SD Status register. | ||
202 | */ | ||
203 | static int mmc_read_ssr(struct mmc_card *card) | ||
204 | { | ||
205 | unsigned int au, es, et, eo; | ||
206 | int err, i; | ||
207 | u32 *ssr; | ||
208 | |||
209 | if (!(card->csd.cmdclass & CCC_APP_SPEC)) { | ||
210 | printk(KERN_WARNING "%s: card lacks mandatory SD Status " | ||
211 | "function.\n", mmc_hostname(card->host)); | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | ssr = kmalloc(64, GFP_KERNEL); | ||
216 | if (!ssr) | ||
217 | return -ENOMEM; | ||
218 | |||
219 | err = mmc_app_sd_status(card, ssr); | ||
220 | if (err) { | ||
221 | printk(KERN_WARNING "%s: problem reading SD Status " | ||
222 | "register.\n", mmc_hostname(card->host)); | ||
223 | err = 0; | ||
224 | goto out; | ||
225 | } | ||
226 | |||
227 | for (i = 0; i < 16; i++) | ||
228 | ssr[i] = be32_to_cpu(ssr[i]); | ||
229 | |||
230 | /* | ||
231 | * UNSTUFF_BITS only works with four u32s so we have to offset the | ||
232 | * bitfield positions accordingly. | ||
233 | */ | ||
234 | au = UNSTUFF_BITS(ssr, 428 - 384, 4); | ||
235 | if (au > 0 || au <= 9) { | ||
236 | card->ssr.au = 1 << (au + 4); | ||
237 | es = UNSTUFF_BITS(ssr, 408 - 384, 16); | ||
238 | et = UNSTUFF_BITS(ssr, 402 - 384, 6); | ||
239 | eo = UNSTUFF_BITS(ssr, 400 - 384, 2); | ||
240 | if (es && et) { | ||
241 | card->ssr.erase_timeout = (et * 1000) / es; | ||
242 | card->ssr.erase_offset = eo * 1000; | ||
243 | } | ||
244 | } else { | ||
245 | printk(KERN_WARNING "%s: SD Status: Invalid Allocation Unit " | ||
246 | "size.\n", mmc_hostname(card->host)); | ||
247 | } | ||
248 | out: | ||
249 | kfree(ssr); | ||
250 | return err; | ||
251 | } | ||
252 | |||
253 | /* | ||
186 | * Fetches and decodes switch information | 254 | * Fetches and decodes switch information |
187 | */ | 255 | */ |
188 | static int mmc_read_switch(struct mmc_card *card) | 256 | static int mmc_read_switch(struct mmc_card *card) |
@@ -238,7 +306,7 @@ out: | |||
238 | /* | 306 | /* |
239 | * Test if the card supports high-speed mode and, if so, switch to it. | 307 | * Test if the card supports high-speed mode and, if so, switch to it. |
240 | */ | 308 | */ |
241 | static int mmc_switch_hs(struct mmc_card *card) | 309 | int mmc_sd_switch_hs(struct mmc_card *card) |
242 | { | 310 | { |
243 | int err; | 311 | int err; |
244 | u8 *status; | 312 | u8 *status; |
@@ -272,9 +340,9 @@ static int mmc_switch_hs(struct mmc_card *card) | |||
272 | printk(KERN_WARNING "%s: Problem switching card " | 340 | printk(KERN_WARNING "%s: Problem switching card " |
273 | "into high-speed mode!\n", | 341 | "into high-speed mode!\n", |
274 | mmc_hostname(card->host)); | 342 | mmc_hostname(card->host)); |
343 | err = 0; | ||
275 | } else { | 344 | } else { |
276 | mmc_card_set_highspeed(card); | 345 | err = 1; |
277 | mmc_set_timing(card->host, MMC_TIMING_SD_HS); | ||
278 | } | 346 | } |
279 | 347 | ||
280 | out: | 348 | out: |
@@ -289,6 +357,8 @@ MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | |||
289 | card->raw_csd[2], card->raw_csd[3]); | 357 | card->raw_csd[2], card->raw_csd[3]); |
290 | MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); | 358 | MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); |
291 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | 359 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); |
360 | MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); | ||
361 | MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); | ||
292 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | 362 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); |
293 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | 363 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); |
294 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); | 364 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); |
@@ -302,6 +372,8 @@ static struct attribute *sd_std_attrs[] = { | |||
302 | &dev_attr_csd.attr, | 372 | &dev_attr_csd.attr, |
303 | &dev_attr_scr.attr, | 373 | &dev_attr_scr.attr, |
304 | &dev_attr_date.attr, | 374 | &dev_attr_date.attr, |
375 | &dev_attr_erase_size.attr, | ||
376 | &dev_attr_preferred_erase_size.attr, | ||
305 | &dev_attr_fwrev.attr, | 377 | &dev_attr_fwrev.attr, |
306 | &dev_attr_hwrev.attr, | 378 | &dev_attr_hwrev.attr, |
307 | &dev_attr_manfid.attr, | 379 | &dev_attr_manfid.attr, |
@@ -320,26 +392,16 @@ static const struct attribute_group *sd_attr_groups[] = { | |||
320 | NULL, | 392 | NULL, |
321 | }; | 393 | }; |
322 | 394 | ||
323 | static struct device_type sd_type = { | 395 | struct device_type sd_type = { |
324 | .groups = sd_attr_groups, | 396 | .groups = sd_attr_groups, |
325 | }; | 397 | }; |
326 | 398 | ||
327 | /* | 399 | /* |
328 | * Handle the detection and initialisation of a card. | 400 | * Fetch CID from card. |
329 | * | ||
330 | * In the case of a resume, "oldcard" will contain the card | ||
331 | * we're trying to reinitialise. | ||
332 | */ | 401 | */ |
333 | static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | 402 | int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid) |
334 | struct mmc_card *oldcard) | ||
335 | { | 403 | { |
336 | struct mmc_card *card; | ||
337 | int err; | 404 | int err; |
338 | u32 cid[4]; | ||
339 | unsigned int max_dtr; | ||
340 | |||
341 | BUG_ON(!host); | ||
342 | WARN_ON(!host->claimed); | ||
343 | 405 | ||
344 | /* | 406 | /* |
345 | * Since we're changing the OCR value, we seem to | 407 | * Since we're changing the OCR value, we seem to |
@@ -361,92 +423,67 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
361 | 423 | ||
362 | err = mmc_send_app_op_cond(host, ocr, NULL); | 424 | err = mmc_send_app_op_cond(host, ocr, NULL); |
363 | if (err) | 425 | if (err) |
364 | goto err; | 426 | return err; |
365 | 427 | ||
366 | /* | ||
367 | * Fetch CID from card. | ||
368 | */ | ||
369 | if (mmc_host_is_spi(host)) | 428 | if (mmc_host_is_spi(host)) |
370 | err = mmc_send_cid(host, cid); | 429 | err = mmc_send_cid(host, cid); |
371 | else | 430 | else |
372 | err = mmc_all_send_cid(host, cid); | 431 | err = mmc_all_send_cid(host, cid); |
373 | if (err) | ||
374 | goto err; | ||
375 | 432 | ||
376 | if (oldcard) { | 433 | return err; |
377 | if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { | 434 | } |
378 | err = -ENOENT; | ||
379 | goto err; | ||
380 | } | ||
381 | |||
382 | card = oldcard; | ||
383 | } else { | ||
384 | /* | ||
385 | * Allocate card structure. | ||
386 | */ | ||
387 | card = mmc_alloc_card(host, &sd_type); | ||
388 | if (IS_ERR(card)) { | ||
389 | err = PTR_ERR(card); | ||
390 | goto err; | ||
391 | } | ||
392 | 435 | ||
393 | card->type = MMC_TYPE_SD; | 436 | int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card) |
394 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); | 437 | { |
395 | } | 438 | int err; |
396 | 439 | ||
397 | /* | 440 | /* |
398 | * For native busses: get card RCA and quit open drain mode. | 441 | * Fetch CSD from card. |
399 | */ | 442 | */ |
400 | if (!mmc_host_is_spi(host)) { | 443 | err = mmc_send_csd(card, card->raw_csd); |
401 | err = mmc_send_relative_addr(host, &card->rca); | 444 | if (err) |
402 | if (err) | 445 | return err; |
403 | goto free_card; | ||
404 | 446 | ||
405 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); | 447 | err = mmc_decode_csd(card); |
406 | } | 448 | if (err) |
449 | return err; | ||
407 | 450 | ||
408 | if (!oldcard) { | 451 | return 0; |
452 | } | ||
453 | |||
454 | int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, | ||
455 | bool reinit) | ||
456 | { | ||
457 | int err; | ||
458 | |||
459 | if (!reinit) { | ||
409 | /* | 460 | /* |
410 | * Fetch CSD from card. | 461 | * Fetch SCR from card. |
411 | */ | 462 | */ |
412 | err = mmc_send_csd(card, card->raw_csd); | 463 | err = mmc_app_send_scr(card, card->raw_scr); |
413 | if (err) | ||
414 | goto free_card; | ||
415 | |||
416 | err = mmc_decode_csd(card); | ||
417 | if (err) | 464 | if (err) |
418 | goto free_card; | 465 | return err; |
419 | |||
420 | mmc_decode_cid(card); | ||
421 | } | ||
422 | 466 | ||
423 | /* | 467 | err = mmc_decode_scr(card); |
424 | * Select card, as all following commands rely on that. | ||
425 | */ | ||
426 | if (!mmc_host_is_spi(host)) { | ||
427 | err = mmc_select_card(card); | ||
428 | if (err) | 468 | if (err) |
429 | goto free_card; | 469 | return err; |
430 | } | ||
431 | 470 | ||
432 | if (!oldcard) { | ||
433 | /* | 471 | /* |
434 | * Fetch SCR from card. | 472 | * Fetch and process SD Status register. |
435 | */ | 473 | */ |
436 | err = mmc_app_send_scr(card, card->raw_scr); | 474 | err = mmc_read_ssr(card); |
437 | if (err) | 475 | if (err) |
438 | goto free_card; | 476 | return err; |
439 | 477 | ||
440 | err = mmc_decode_scr(card); | 478 | /* Erase init depends on CSD and SSR */ |
441 | if (err < 0) | 479 | mmc_init_erase(card); |
442 | goto free_card; | ||
443 | 480 | ||
444 | /* | 481 | /* |
445 | * Fetch switch information from card. | 482 | * Fetch switch information from card. |
446 | */ | 483 | */ |
447 | err = mmc_read_switch(card); | 484 | err = mmc_read_switch(card); |
448 | if (err) | 485 | if (err) |
449 | goto free_card; | 486 | return err; |
450 | } | 487 | } |
451 | 488 | ||
452 | /* | 489 | /* |
@@ -458,20 +495,34 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
458 | if (mmc_host_is_spi(host)) { | 495 | if (mmc_host_is_spi(host)) { |
459 | err = mmc_spi_set_crc(host, use_spi_crc); | 496 | err = mmc_spi_set_crc(host, use_spi_crc); |
460 | if (err) | 497 | if (err) |
461 | goto free_card; | 498 | return err; |
462 | } | 499 | } |
463 | 500 | ||
464 | /* | 501 | /* |
465 | * Attempt to change to high-speed (if supported) | 502 | * Check if read-only switch is active. |
466 | */ | 503 | */ |
467 | err = mmc_switch_hs(card); | 504 | if (!reinit) { |
468 | if (err) | 505 | int ro = -1; |
469 | goto free_card; | ||
470 | 506 | ||
471 | /* | 507 | if (host->ops->get_ro) |
472 | * Compute bus speed. | 508 | ro = host->ops->get_ro(host); |
473 | */ | 509 | |
474 | max_dtr = (unsigned int)-1; | 510 | if (ro < 0) { |
511 | printk(KERN_WARNING "%s: host does not " | ||
512 | "support reading read-only " | ||
513 | "switch. assuming write-enable.\n", | ||
514 | mmc_hostname(host)); | ||
515 | } else if (ro > 0) { | ||
516 | mmc_card_set_readonly(card); | ||
517 | } | ||
518 | } | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | unsigned mmc_sd_get_max_clock(struct mmc_card *card) | ||
524 | { | ||
525 | unsigned max_dtr = (unsigned int)-1; | ||
475 | 526 | ||
476 | if (mmc_card_highspeed(card)) { | 527 | if (mmc_card_highspeed(card)) { |
477 | if (max_dtr > card->sw_caps.hs_max_dtr) | 528 | if (max_dtr > card->sw_caps.hs_max_dtr) |
@@ -480,7 +531,97 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
480 | max_dtr = card->csd.max_dtr; | 531 | max_dtr = card->csd.max_dtr; |
481 | } | 532 | } |
482 | 533 | ||
483 | mmc_set_clock(host, max_dtr); | 534 | return max_dtr; |
535 | } | ||
536 | |||
537 | void mmc_sd_go_highspeed(struct mmc_card *card) | ||
538 | { | ||
539 | mmc_card_set_highspeed(card); | ||
540 | mmc_set_timing(card->host, MMC_TIMING_SD_HS); | ||
541 | } | ||
542 | |||
543 | /* | ||
544 | * Handle the detection and initialisation of a card. | ||
545 | * | ||
546 | * In the case of a resume, "oldcard" will contain the card | ||
547 | * we're trying to reinitialise. | ||
548 | */ | ||
549 | static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | ||
550 | struct mmc_card *oldcard) | ||
551 | { | ||
552 | struct mmc_card *card; | ||
553 | int err; | ||
554 | u32 cid[4]; | ||
555 | |||
556 | BUG_ON(!host); | ||
557 | WARN_ON(!host->claimed); | ||
558 | |||
559 | err = mmc_sd_get_cid(host, ocr, cid); | ||
560 | if (err) | ||
561 | return err; | ||
562 | |||
563 | if (oldcard) { | ||
564 | if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) | ||
565 | return -ENOENT; | ||
566 | |||
567 | card = oldcard; | ||
568 | } else { | ||
569 | /* | ||
570 | * Allocate card structure. | ||
571 | */ | ||
572 | card = mmc_alloc_card(host, &sd_type); | ||
573 | if (IS_ERR(card)) | ||
574 | return PTR_ERR(card); | ||
575 | |||
576 | card->type = MMC_TYPE_SD; | ||
577 | memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); | ||
578 | } | ||
579 | |||
580 | /* | ||
581 | * For native busses: get card RCA and quit open drain mode. | ||
582 | */ | ||
583 | if (!mmc_host_is_spi(host)) { | ||
584 | err = mmc_send_relative_addr(host, &card->rca); | ||
585 | if (err) | ||
586 | return err; | ||
587 | |||
588 | mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); | ||
589 | } | ||
590 | |||
591 | if (!oldcard) { | ||
592 | err = mmc_sd_get_csd(host, card); | ||
593 | if (err) | ||
594 | return err; | ||
595 | |||
596 | mmc_decode_cid(card); | ||
597 | } | ||
598 | |||
599 | /* | ||
600 | * Select card, as all following commands rely on that. | ||
601 | */ | ||
602 | if (!mmc_host_is_spi(host)) { | ||
603 | err = mmc_select_card(card); | ||
604 | if (err) | ||
605 | return err; | ||
606 | } | ||
607 | |||
608 | err = mmc_sd_setup_card(host, card, oldcard != NULL); | ||
609 | if (err) | ||
610 | goto free_card; | ||
611 | |||
612 | /* | ||
613 | * Attempt to change to high-speed (if supported) | ||
614 | */ | ||
615 | err = mmc_sd_switch_hs(card); | ||
616 | if (err > 0) | ||
617 | mmc_sd_go_highspeed(card); | ||
618 | else if (err) | ||
619 | goto free_card; | ||
620 | |||
621 | /* | ||
622 | * Set bus speed. | ||
623 | */ | ||
624 | mmc_set_clock(host, mmc_sd_get_max_clock(card)); | ||
484 | 625 | ||
485 | /* | 626 | /* |
486 | * Switch to wider bus (if supported). | 627 | * Switch to wider bus (if supported). |
@@ -494,30 +635,12 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
494 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); | 635 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); |
495 | } | 636 | } |
496 | 637 | ||
497 | /* | 638 | host->card = card; |
498 | * Check if read-only switch is active. | ||
499 | */ | ||
500 | if (!oldcard) { | ||
501 | if (!host->ops->get_ro || host->ops->get_ro(host) < 0) { | ||
502 | printk(KERN_WARNING "%s: host does not " | ||
503 | "support reading read-only " | ||
504 | "switch. assuming write-enable.\n", | ||
505 | mmc_hostname(host)); | ||
506 | } else { | ||
507 | if (host->ops->get_ro(host) > 0) | ||
508 | mmc_card_set_readonly(card); | ||
509 | } | ||
510 | } | ||
511 | |||
512 | if (!oldcard) | ||
513 | host->card = card; | ||
514 | |||
515 | return 0; | 639 | return 0; |
516 | 640 | ||
517 | free_card: | 641 | free_card: |
518 | if (!oldcard) | 642 | if (!oldcard) |
519 | mmc_remove_card(card); | 643 | mmc_remove_card(card); |
520 | err: | ||
521 | 644 | ||
522 | return err; | 645 | return err; |
523 | } | 646 | } |
diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h new file mode 100644 index 000000000000..3d8800fa7600 --- /dev/null +++ b/drivers/mmc/core/sd.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef _MMC_CORE_SD_H | ||
2 | #define _MMC_CORE_SD_H | ||
3 | |||
4 | #include <linux/mmc/card.h> | ||
5 | |||
6 | extern struct device_type sd_type; | ||
7 | |||
8 | int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid); | ||
9 | int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card); | ||
10 | void mmc_decode_cid(struct mmc_card *card); | ||
11 | int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, | ||
12 | bool reinit); | ||
13 | unsigned mmc_sd_get_max_clock(struct mmc_card *card); | ||
14 | int mmc_sd_switch_hs(struct mmc_card *card); | ||
15 | void mmc_sd_go_highspeed(struct mmc_card *card); | ||
16 | |||
17 | #endif | ||
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 63772e7e7608..797cdb5887fd 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c | |||
@@ -346,3 +346,51 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |||
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
348 | 348 | ||
349 | int mmc_app_sd_status(struct mmc_card *card, void *ssr) | ||
350 | { | ||
351 | int err; | ||
352 | struct mmc_request mrq; | ||
353 | struct mmc_command cmd; | ||
354 | struct mmc_data data; | ||
355 | struct scatterlist sg; | ||
356 | |||
357 | BUG_ON(!card); | ||
358 | BUG_ON(!card->host); | ||
359 | BUG_ON(!ssr); | ||
360 | |||
361 | /* NOTE: caller guarantees ssr is heap-allocated */ | ||
362 | |||
363 | err = mmc_app_cmd(card->host, card); | ||
364 | if (err) | ||
365 | return err; | ||
366 | |||
367 | memset(&mrq, 0, sizeof(struct mmc_request)); | ||
368 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
369 | memset(&data, 0, sizeof(struct mmc_data)); | ||
370 | |||
371 | mrq.cmd = &cmd; | ||
372 | mrq.data = &data; | ||
373 | |||
374 | cmd.opcode = SD_APP_SD_STATUS; | ||
375 | cmd.arg = 0; | ||
376 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_ADTC; | ||
377 | |||
378 | data.blksz = 64; | ||
379 | data.blocks = 1; | ||
380 | data.flags = MMC_DATA_READ; | ||
381 | data.sg = &sg; | ||
382 | data.sg_len = 1; | ||
383 | |||
384 | sg_init_one(&sg, ssr, 64); | ||
385 | |||
386 | mmc_set_data_timeout(&data, card); | ||
387 | |||
388 | mmc_wait_for_req(card->host, &mrq); | ||
389 | |||
390 | if (cmd.error) | ||
391 | return cmd.error; | ||
392 | if (data.error) | ||
393 | return data.error; | ||
394 | |||
395 | return 0; | ||
396 | } | ||
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 9742d8a30664..ffc2305d905f 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h | |||
@@ -19,6 +19,7 @@ int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca); | |||
19 | int mmc_app_send_scr(struct mmc_card *card, u32 *scr); | 19 | int mmc_app_send_scr(struct mmc_card *card, u32 *scr); |
20 | int mmc_sd_switch(struct mmc_card *card, int mode, int group, | 20 | int mmc_sd_switch(struct mmc_card *card, int mode, int group, |
21 | u8 value, u8 *resp); | 21 | u8 value, u8 *resp); |
22 | int mmc_app_sd_status(struct mmc_card *card, void *ssr); | ||
22 | 23 | ||
23 | #endif | 24 | #endif |
24 | 25 | ||
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index b9dee28ee7d0..bd2755e8d9a3 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include "core.h" | 19 | #include "core.h" |
20 | #include "bus.h" | 20 | #include "bus.h" |
21 | #include "sd.h" | ||
21 | #include "sdio_bus.h" | 22 | #include "sdio_bus.h" |
22 | #include "mmc_ops.h" | 23 | #include "mmc_ops.h" |
23 | #include "sd_ops.h" | 24 | #include "sd_ops.h" |
@@ -62,13 +63,19 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn) | |||
62 | 63 | ||
63 | func->num = fn; | 64 | func->num = fn; |
64 | 65 | ||
65 | ret = sdio_read_fbr(func); | 66 | if (!(card->quirks & MMC_QUIRK_NONSTD_SDIO)) { |
66 | if (ret) | 67 | ret = sdio_read_fbr(func); |
67 | goto fail; | 68 | if (ret) |
69 | goto fail; | ||
68 | 70 | ||
69 | ret = sdio_read_func_cis(func); | 71 | ret = sdio_read_func_cis(func); |
70 | if (ret) | 72 | if (ret) |
71 | goto fail; | 73 | goto fail; |
74 | } else { | ||
75 | func->vendor = func->card->cis.vendor; | ||
76 | func->device = func->card->cis.device; | ||
77 | func->max_blksize = func->card->cis.blksize; | ||
78 | } | ||
72 | 79 | ||
73 | card->sdio_func[fn - 1] = func; | 80 | card->sdio_func[fn - 1] = func; |
74 | 81 | ||
@@ -159,9 +166,7 @@ static int sdio_enable_wide(struct mmc_card *card) | |||
159 | if (ret) | 166 | if (ret) |
160 | return ret; | 167 | return ret; |
161 | 168 | ||
162 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | 169 | return 1; |
163 | |||
164 | return 0; | ||
165 | } | 170 | } |
166 | 171 | ||
167 | /* | 172 | /* |
@@ -221,10 +226,34 @@ static int sdio_disable_wide(struct mmc_card *card) | |||
221 | return 0; | 226 | return 0; |
222 | } | 227 | } |
223 | 228 | ||
229 | |||
230 | static int sdio_enable_4bit_bus(struct mmc_card *card) | ||
231 | { | ||
232 | int err; | ||
233 | |||
234 | if (card->type == MMC_TYPE_SDIO) | ||
235 | return sdio_enable_wide(card); | ||
236 | |||
237 | if ((card->host->caps & MMC_CAP_4_BIT_DATA) && | ||
238 | (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { | ||
239 | err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); | ||
240 | if (err) | ||
241 | return err; | ||
242 | } else | ||
243 | return 0; | ||
244 | |||
245 | err = sdio_enable_wide(card); | ||
246 | if (err <= 0) | ||
247 | mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); | ||
248 | |||
249 | return err; | ||
250 | } | ||
251 | |||
252 | |||
224 | /* | 253 | /* |
225 | * Test if the card supports high-speed mode and, if so, switch to it. | 254 | * Test if the card supports high-speed mode and, if so, switch to it. |
226 | */ | 255 | */ |
227 | static int sdio_enable_hs(struct mmc_card *card) | 256 | static int mmc_sdio_switch_hs(struct mmc_card *card, int enable) |
228 | { | 257 | { |
229 | int ret; | 258 | int ret; |
230 | u8 speed; | 259 | u8 speed; |
@@ -239,16 +268,56 @@ static int sdio_enable_hs(struct mmc_card *card) | |||
239 | if (ret) | 268 | if (ret) |
240 | return ret; | 269 | return ret; |
241 | 270 | ||
242 | speed |= SDIO_SPEED_EHS; | 271 | if (enable) |
272 | speed |= SDIO_SPEED_EHS; | ||
273 | else | ||
274 | speed &= ~SDIO_SPEED_EHS; | ||
243 | 275 | ||
244 | ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); | 276 | ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); |
245 | if (ret) | 277 | if (ret) |
246 | return ret; | 278 | return ret; |
247 | 279 | ||
248 | mmc_card_set_highspeed(card); | 280 | return 1; |
249 | mmc_set_timing(card->host, MMC_TIMING_SD_HS); | 281 | } |
250 | 282 | ||
251 | return 0; | 283 | /* |
284 | * Enable SDIO/combo card's high-speed mode. Return 0/1 if [not]supported. | ||
285 | */ | ||
286 | static int sdio_enable_hs(struct mmc_card *card) | ||
287 | { | ||
288 | int ret; | ||
289 | |||
290 | ret = mmc_sdio_switch_hs(card, true); | ||
291 | if (ret <= 0 || card->type == MMC_TYPE_SDIO) | ||
292 | return ret; | ||
293 | |||
294 | ret = mmc_sd_switch_hs(card); | ||
295 | if (ret <= 0) | ||
296 | mmc_sdio_switch_hs(card, false); | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) | ||
302 | { | ||
303 | unsigned max_dtr; | ||
304 | |||
305 | if (mmc_card_highspeed(card)) { | ||
306 | /* | ||
307 | * The SDIO specification doesn't mention how | ||
308 | * the CIS transfer speed register relates to | ||
309 | * high-speed, but it seems that 50 MHz is | ||
310 | * mandatory. | ||
311 | */ | ||
312 | max_dtr = 50000000; | ||
313 | } else { | ||
314 | max_dtr = card->cis.max_dtr; | ||
315 | } | ||
316 | |||
317 | if (card->type == MMC_TYPE_SD_COMBO) | ||
318 | max_dtr = min(max_dtr, mmc_sd_get_max_clock(card)); | ||
319 | |||
320 | return max_dtr; | ||
252 | } | 321 | } |
253 | 322 | ||
254 | /* | 323 | /* |
@@ -293,7 +362,24 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
293 | goto err; | 362 | goto err; |
294 | } | 363 | } |
295 | 364 | ||
296 | card->type = MMC_TYPE_SDIO; | 365 | err = mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid); |
366 | |||
367 | if (!err) { | ||
368 | card->type = MMC_TYPE_SD_COMBO; | ||
369 | |||
370 | if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || | ||
371 | memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) { | ||
372 | mmc_remove_card(card); | ||
373 | return -ENOENT; | ||
374 | } | ||
375 | } else { | ||
376 | card->type = MMC_TYPE_SDIO; | ||
377 | |||
378 | if (oldcard && oldcard->type != MMC_TYPE_SDIO) { | ||
379 | mmc_remove_card(card); | ||
380 | return -ENOENT; | ||
381 | } | ||
382 | } | ||
297 | 383 | ||
298 | /* | 384 | /* |
299 | * Call the optional HC's init_card function to handle quirks. | 385 | * Call the optional HC's init_card function to handle quirks. |
@@ -313,6 +399,17 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
313 | } | 399 | } |
314 | 400 | ||
315 | /* | 401 | /* |
402 | * Read CSD, before selecting the card | ||
403 | */ | ||
404 | if (!oldcard && card->type == MMC_TYPE_SD_COMBO) { | ||
405 | err = mmc_sd_get_csd(host, card); | ||
406 | if (err) | ||
407 | return err; | ||
408 | |||
409 | mmc_decode_cid(card); | ||
410 | } | ||
411 | |||
412 | /* | ||
316 | * Select card, as all following commands rely on that. | 413 | * Select card, as all following commands rely on that. |
317 | */ | 414 | */ |
318 | if (!powered_resume && !mmc_host_is_spi(host)) { | 415 | if (!powered_resume && !mmc_host_is_spi(host)) { |
@@ -321,6 +418,23 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
321 | goto remove; | 418 | goto remove; |
322 | } | 419 | } |
323 | 420 | ||
421 | if (card->quirks & MMC_QUIRK_NONSTD_SDIO) { | ||
422 | /* | ||
423 | * This is non-standard SDIO device, meaning it doesn't | ||
424 | * have any CIA (Common I/O area) registers present. | ||
425 | * It's host's responsibility to fill cccr and cis | ||
426 | * structures in init_card(). | ||
427 | */ | ||
428 | mmc_set_clock(host, card->cis.max_dtr); | ||
429 | |||
430 | if (card->cccr.high_speed) { | ||
431 | mmc_card_set_highspeed(card); | ||
432 | mmc_set_timing(card->host, MMC_TIMING_SD_HS); | ||
433 | } | ||
434 | |||
435 | goto finish; | ||
436 | } | ||
437 | |||
324 | /* | 438 | /* |
325 | * Read the common registers. | 439 | * Read the common registers. |
326 | */ | 440 | */ |
@@ -339,43 +453,57 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
339 | int same = (card->cis.vendor == oldcard->cis.vendor && | 453 | int same = (card->cis.vendor == oldcard->cis.vendor && |
340 | card->cis.device == oldcard->cis.device); | 454 | card->cis.device == oldcard->cis.device); |
341 | mmc_remove_card(card); | 455 | mmc_remove_card(card); |
342 | if (!same) { | 456 | if (!same) |
343 | err = -ENOENT; | 457 | return -ENOENT; |
344 | goto err; | 458 | |
345 | } | ||
346 | card = oldcard; | 459 | card = oldcard; |
347 | return 0; | 460 | return 0; |
348 | } | 461 | } |
349 | 462 | ||
463 | if (card->type == MMC_TYPE_SD_COMBO) { | ||
464 | err = mmc_sd_setup_card(host, card, oldcard != NULL); | ||
465 | /* handle as SDIO-only card if memory init failed */ | ||
466 | if (err) { | ||
467 | mmc_go_idle(host); | ||
468 | if (mmc_host_is_spi(host)) | ||
469 | /* should not fail, as it worked previously */ | ||
470 | mmc_spi_set_crc(host, use_spi_crc); | ||
471 | card->type = MMC_TYPE_SDIO; | ||
472 | } else | ||
473 | card->dev.type = &sd_type; | ||
474 | } | ||
475 | |||
476 | /* | ||
477 | * If needed, disconnect card detection pull-up resistor. | ||
478 | */ | ||
479 | err = sdio_disable_cd(card); | ||
480 | if (err) | ||
481 | goto remove; | ||
482 | |||
350 | /* | 483 | /* |
351 | * Switch to high-speed (if supported). | 484 | * Switch to high-speed (if supported). |
352 | */ | 485 | */ |
353 | err = sdio_enable_hs(card); | 486 | err = sdio_enable_hs(card); |
354 | if (err) | 487 | if (err > 0) |
488 | mmc_sd_go_highspeed(card); | ||
489 | else if (err) | ||
355 | goto remove; | 490 | goto remove; |
356 | 491 | ||
357 | /* | 492 | /* |
358 | * Change to the card's maximum speed. | 493 | * Change to the card's maximum speed. |
359 | */ | 494 | */ |
360 | if (mmc_card_highspeed(card)) { | 495 | mmc_set_clock(host, mmc_sdio_get_max_clock(card)); |
361 | /* | ||
362 | * The SDIO specification doesn't mention how | ||
363 | * the CIS transfer speed register relates to | ||
364 | * high-speed, but it seems that 50 MHz is | ||
365 | * mandatory. | ||
366 | */ | ||
367 | mmc_set_clock(host, 50000000); | ||
368 | } else { | ||
369 | mmc_set_clock(host, card->cis.max_dtr); | ||
370 | } | ||
371 | 496 | ||
372 | /* | 497 | /* |
373 | * Switch to wider bus (if supported). | 498 | * Switch to wider bus (if supported). |
374 | */ | 499 | */ |
375 | err = sdio_enable_wide(card); | 500 | err = sdio_enable_4bit_bus(card); |
376 | if (err) | 501 | if (err > 0) |
502 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); | ||
503 | else if (err) | ||
377 | goto remove; | 504 | goto remove; |
378 | 505 | ||
506 | finish: | ||
379 | if (!oldcard) | 507 | if (!oldcard) |
380 | host->card = card; | 508 | host->card = card; |
381 | return 0; | 509 | return 0; |
@@ -487,9 +615,14 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
487 | mmc_claim_host(host); | 615 | mmc_claim_host(host); |
488 | err = mmc_sdio_init_card(host, host->ocr, host->card, | 616 | err = mmc_sdio_init_card(host, host->ocr, host->card, |
489 | (host->pm_flags & MMC_PM_KEEP_POWER)); | 617 | (host->pm_flags & MMC_PM_KEEP_POWER)); |
490 | if (!err) | 618 | if (!err) { |
491 | /* We may have switched to 1-bit mode during suspend. */ | 619 | /* We may have switched to 1-bit mode during suspend. */ |
492 | err = sdio_enable_wide(host->card); | 620 | err = sdio_enable_4bit_bus(host->card); |
621 | if (err > 0) { | ||
622 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); | ||
623 | err = 0; | ||
624 | } | ||
625 | } | ||
493 | if (!err && host->sdio_irqs) | 626 | if (!err && host->sdio_irqs) |
494 | mmc_signal_sdio_irq(host); | 627 | mmc_signal_sdio_irq(host); |
495 | mmc_release_host(host); | 628 | mmc_release_host(host); |
@@ -574,13 +707,6 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
574 | card->sdio_funcs = 0; | 707 | card->sdio_funcs = 0; |
575 | 708 | ||
576 | /* | 709 | /* |
577 | * If needed, disconnect card detection pull-up resistor. | ||
578 | */ | ||
579 | err = sdio_disable_cd(card); | ||
580 | if (err) | ||
581 | goto remove; | ||
582 | |||
583 | /* | ||
584 | * Initialize (but don't add) all present functions. | 710 | * Initialize (but don't add) all present functions. |
585 | */ | 711 | */ |
586 | for (i = 0; i < funcs; i++, card->sdio_funcs++) { | 712 | for (i = 0; i < funcs; i++, card->sdio_funcs++) { |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index d25e22cee4c4..c997474c649f 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -121,6 +121,15 @@ config MMC_SDHCI_PLTFM | |||
121 | 121 | ||
122 | If unsure, say N. | 122 | If unsure, say N. |
123 | 123 | ||
124 | config MMC_SDHCI_CNS3XXX | ||
125 | bool "SDHCI support on the Cavium Networks CNS3xxx SoC" | ||
126 | depends on ARCH_CNS3XXX | ||
127 | depends on MMC_SDHCI_PLTFM | ||
128 | help | ||
129 | This selects the SDHCI support for CNS3xxx System-on-Chip devices. | ||
130 | |||
131 | If unsure, say N. | ||
132 | |||
124 | config MMC_SDHCI_S3C | 133 | config MMC_SDHCI_S3C |
125 | tristate "SDHCI support on Samsung S3C SoC" | 134 | tristate "SDHCI support on Samsung S3C SoC" |
126 | depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX) | 135 | depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX) |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index f4e53c98d944..fe0ba4e2b8b0 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -12,7 +12,6 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o | |||
12 | obj-$(CONFIG_MMC_MXC) += mxcmmc.o | 12 | obj-$(CONFIG_MMC_MXC) += mxcmmc.o |
13 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 13 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
15 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o | ||
16 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 15 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
17 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o | 16 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o |
18 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 17 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
@@ -38,6 +37,10 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | |||
38 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 37 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
39 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 38 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
40 | 39 | ||
40 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o | ||
41 | sdhci-platform-y := sdhci-pltfm.o | ||
42 | sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o | ||
43 | |||
41 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o | 44 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o |
42 | sdhci-of-y := sdhci-of-core.o | 45 | sdhci-of-y := sdhci-of-core.o |
43 | sdhci-of-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o | 46 | sdhci-of-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 7b0f3ef50f96..1145ea0792e6 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -1536,6 +1536,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi) | |||
1536 | #if defined(CONFIG_OF) | 1536 | #if defined(CONFIG_OF) |
1537 | static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { | 1537 | static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { |
1538 | { .compatible = "mmc-spi-slot", }, | 1538 | { .compatible = "mmc-spi-slot", }, |
1539 | {}, | ||
1539 | }; | 1540 | }; |
1540 | #endif | 1541 | #endif |
1541 | 1542 | ||
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 24e09454e522..6824917f5c60 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -1057,26 +1057,10 @@ msmsdcc_init_dma(struct msmsdcc_host *host) | |||
1057 | return 0; | 1057 | return 0; |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | #ifdef CONFIG_MMC_MSM7X00A_RESUME_IN_WQ | ||
1061 | static void | ||
1062 | do_resume_work(struct work_struct *work) | ||
1063 | { | ||
1064 | struct msmsdcc_host *host = | ||
1065 | container_of(work, struct msmsdcc_host, resume_task); | ||
1066 | struct mmc_host *mmc = host->mmc; | ||
1067 | |||
1068 | if (mmc) { | ||
1069 | mmc_resume_host(mmc); | ||
1070 | if (host->stat_irq) | ||
1071 | enable_irq(host->stat_irq); | ||
1072 | } | ||
1073 | } | ||
1074 | #endif | ||
1075 | |||
1076 | static int | 1060 | static int |
1077 | msmsdcc_probe(struct platform_device *pdev) | 1061 | msmsdcc_probe(struct platform_device *pdev) |
1078 | { | 1062 | { |
1079 | struct mmc_platform_data *plat = pdev->dev.platform_data; | 1063 | struct msm_mmc_platform_data *plat = pdev->dev.platform_data; |
1080 | struct msmsdcc_host *host; | 1064 | struct msmsdcc_host *host; |
1081 | struct mmc_host *mmc; | 1065 | struct mmc_host *mmc; |
1082 | struct resource *cmd_irqres = NULL; | 1066 | struct resource *cmd_irqres = NULL; |
@@ -1145,15 +1129,6 @@ msmsdcc_probe(struct platform_device *pdev) | |||
1145 | host->dmares = dmares; | 1129 | host->dmares = dmares; |
1146 | spin_lock_init(&host->lock); | 1130 | spin_lock_init(&host->lock); |
1147 | 1131 | ||
1148 | #ifdef CONFIG_MMC_EMBEDDED_SDIO | ||
1149 | if (plat->embedded_sdio) | ||
1150 | mmc_set_embedded_sdio_data(mmc, | ||
1151 | &plat->embedded_sdio->cis, | ||
1152 | &plat->embedded_sdio->cccr, | ||
1153 | plat->embedded_sdio->funcs, | ||
1154 | plat->embedded_sdio->num_funcs); | ||
1155 | #endif | ||
1156 | |||
1157 | /* | 1132 | /* |
1158 | * Setup DMA | 1133 | * Setup DMA |
1159 | */ | 1134 | */ |
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h index da0039c9285e..ff2b0f74f6f4 100644 --- a/drivers/mmc/host/msm_sdcc.h +++ b/drivers/mmc/host/msm_sdcc.h | |||
@@ -225,7 +225,7 @@ struct msmsdcc_host { | |||
225 | 225 | ||
226 | u32 pwr; | 226 | u32 pwr; |
227 | u32 saved_irq0mask; /* MMCIMASK0 reg value */ | 227 | u32 saved_irq0mask; /* MMCIMASK0 reg value */ |
228 | struct mmc_platform_data *plat; | 228 | struct msm_mmc_platform_data *plat; |
229 | 229 | ||
230 | struct timer_list timer; | 230 | struct timer_list timer; |
231 | unsigned int oldstat; | 231 | unsigned int oldstat; |
@@ -235,10 +235,6 @@ struct msmsdcc_host { | |||
235 | int cmdpoll; | 235 | int cmdpoll; |
236 | struct msmsdcc_stats stats; | 236 | struct msmsdcc_stats stats; |
237 | 237 | ||
238 | #ifdef CONFIG_MMC_MSM7X00A_RESUME_IN_WQ | ||
239 | struct work_struct resume_task; | ||
240 | #endif | ||
241 | |||
242 | /* Command parameters */ | 238 | /* Command parameters */ |
243 | unsigned int cmd_timeout; | 239 | unsigned int cmd_timeout; |
244 | unsigned int cmd_pio_irqmask; | 240 | unsigned int cmd_pio_irqmask; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b032828c6126..4a8776f8afdd 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | #include <linux/mmc/core.h> | 30 | #include <linux/mmc/core.h> |
31 | #include <linux/mmc/mmc.h> | ||
31 | #include <linux/io.h> | 32 | #include <linux/io.h> |
32 | #include <linux/semaphore.h> | 33 | #include <linux/semaphore.h> |
33 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
@@ -78,6 +79,7 @@ | |||
78 | #define INT_EN_MASK 0x307F0033 | 79 | #define INT_EN_MASK 0x307F0033 |
79 | #define BWR_ENABLE (1 << 4) | 80 | #define BWR_ENABLE (1 << 4) |
80 | #define BRR_ENABLE (1 << 5) | 81 | #define BRR_ENABLE (1 << 5) |
82 | #define DTO_ENABLE (1 << 20) | ||
81 | #define INIT_STREAM (1 << 1) | 83 | #define INIT_STREAM (1 << 1) |
82 | #define DP_SELECT (1 << 21) | 84 | #define DP_SELECT (1 << 21) |
83 | #define DDIR (1 << 4) | 85 | #define DDIR (1 << 4) |
@@ -523,7 +525,8 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) | |||
523 | dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); | 525 | dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); |
524 | } | 526 | } |
525 | 527 | ||
526 | static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host) | 528 | static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, |
529 | struct mmc_command *cmd) | ||
527 | { | 530 | { |
528 | unsigned int irq_mask; | 531 | unsigned int irq_mask; |
529 | 532 | ||
@@ -532,6 +535,10 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host) | |||
532 | else | 535 | else |
533 | irq_mask = INT_EN_MASK; | 536 | irq_mask = INT_EN_MASK; |
534 | 537 | ||
538 | /* Disable timeout for erases */ | ||
539 | if (cmd->opcode == MMC_ERASE) | ||
540 | irq_mask &= ~DTO_ENABLE; | ||
541 | |||
535 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | 542 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); |
536 | OMAP_HSMMC_WRITE(host->base, ISE, irq_mask); | 543 | OMAP_HSMMC_WRITE(host->base, ISE, irq_mask); |
537 | OMAP_HSMMC_WRITE(host->base, IE, irq_mask); | 544 | OMAP_HSMMC_WRITE(host->base, IE, irq_mask); |
@@ -782,7 +789,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
782 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | 789 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); |
783 | host->cmd = cmd; | 790 | host->cmd = cmd; |
784 | 791 | ||
785 | omap_hsmmc_enable_irq(host); | 792 | omap_hsmmc_enable_irq(host, cmd); |
786 | 793 | ||
787 | host->response_busy = 0; | 794 | host->response_busy = 0; |
788 | if (cmd->flags & MMC_RSP_PRESENT) { | 795 | if (cmd->flags & MMC_RSP_PRESENT) { |
@@ -1273,8 +1280,11 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) | |||
1273 | struct mmc_data *data = host->mrq->data; | 1280 | struct mmc_data *data = host->mrq->data; |
1274 | int dma_ch, req_in_progress; | 1281 | int dma_ch, req_in_progress; |
1275 | 1282 | ||
1276 | if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ) | 1283 | if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { |
1277 | dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n"); | 1284 | dev_warn(mmc_dev(host->mmc), "unexpected dma status %x\n", |
1285 | ch_status); | ||
1286 | return; | ||
1287 | } | ||
1278 | 1288 | ||
1279 | spin_lock(&host->irq_lock); | 1289 | spin_lock(&host->irq_lock); |
1280 | if (host->dma_ch < 0) { | 1290 | if (host->dma_ch < 0) { |
@@ -1598,6 +1608,14 @@ static int omap_hsmmc_get_ro(struct mmc_host *mmc) | |||
1598 | return mmc_slot(host).get_ro(host->dev, 0); | 1608 | return mmc_slot(host).get_ro(host->dev, 0); |
1599 | } | 1609 | } |
1600 | 1610 | ||
1611 | static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) | ||
1612 | { | ||
1613 | struct omap_hsmmc_host *host = mmc_priv(mmc); | ||
1614 | |||
1615 | if (mmc_slot(host).init_card) | ||
1616 | mmc_slot(host).init_card(card); | ||
1617 | } | ||
1618 | |||
1601 | static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | 1619 | static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) |
1602 | { | 1620 | { |
1603 | u32 hctl, capa, value; | 1621 | u32 hctl, capa, value; |
@@ -1869,6 +1887,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = { | |||
1869 | .set_ios = omap_hsmmc_set_ios, | 1887 | .set_ios = omap_hsmmc_set_ios, |
1870 | .get_cd = omap_hsmmc_get_cd, | 1888 | .get_cd = omap_hsmmc_get_cd, |
1871 | .get_ro = omap_hsmmc_get_ro, | 1889 | .get_ro = omap_hsmmc_get_ro, |
1890 | .init_card = omap_hsmmc_init_card, | ||
1872 | /* NYET -- enable_sdio_irq */ | 1891 | /* NYET -- enable_sdio_irq */ |
1873 | }; | 1892 | }; |
1874 | 1893 | ||
@@ -1879,6 +1898,7 @@ static const struct mmc_host_ops omap_hsmmc_ps_ops = { | |||
1879 | .set_ios = omap_hsmmc_set_ios, | 1898 | .set_ios = omap_hsmmc_set_ios, |
1880 | .get_cd = omap_hsmmc_get_cd, | 1899 | .get_cd = omap_hsmmc_get_cd, |
1881 | .get_ro = omap_hsmmc_get_ro, | 1900 | .get_ro = omap_hsmmc_get_ro, |
1901 | .init_card = omap_hsmmc_init_card, | ||
1882 | /* NYET -- enable_sdio_irq */ | 1902 | /* NYET -- enable_sdio_irq */ |
1883 | }; | 1903 | }; |
1884 | 1904 | ||
@@ -2094,12 +2114,25 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2094 | mmc->max_seg_size = mmc->max_req_size; | 2114 | mmc->max_seg_size = mmc->max_req_size; |
2095 | 2115 | ||
2096 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | | 2116 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | |
2097 | MMC_CAP_WAIT_WHILE_BUSY; | 2117 | MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE; |
2098 | 2118 | ||
2099 | if (mmc_slot(host).wires >= 8) | 2119 | switch (mmc_slot(host).wires) { |
2120 | case 8: | ||
2100 | mmc->caps |= MMC_CAP_8_BIT_DATA; | 2121 | mmc->caps |= MMC_CAP_8_BIT_DATA; |
2101 | else if (mmc_slot(host).wires >= 4) | 2122 | /* Fall through */ |
2123 | case 4: | ||
2102 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 2124 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
2125 | break; | ||
2126 | case 1: | ||
2127 | /* Nothing to crib here */ | ||
2128 | case 0: | ||
2129 | /* Assuming nothing was given by board, Core use's 1-Bit */ | ||
2130 | break; | ||
2131 | default: | ||
2132 | /* Completely unexpected.. Core goes with 1-Bit Width */ | ||
2133 | dev_crit(mmc_dev(host->mmc), "Invalid width %d\n used!" | ||
2134 | "using 1 instead\n", mmc_slot(host).wires); | ||
2135 | } | ||
2103 | 2136 | ||
2104 | if (mmc_slot(host).nonremovable) | 2137 | if (mmc_slot(host).nonremovable) |
2105 | mmc->caps |= MMC_CAP_NONREMOVABLE; | 2138 | mmc->caps |= MMC_CAP_NONREMOVABLE; |
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c new file mode 100644 index 000000000000..b7050b380d5f --- /dev/null +++ b/drivers/mmc/host/sdhci-cns3xxx.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * SDHCI support for CNS3xxx SoC | ||
3 | * | ||
4 | * Copyright 2008 Cavium Networks | ||
5 | * Copyright 2010 MontaVista Software, LLC. | ||
6 | * | ||
7 | * Authors: Scott Shu | ||
8 | * Anton Vorontsov <avorontsov@mvista.com> | ||
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/delay.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/mmc/host.h> | ||
18 | #include <linux/sdhci-pltfm.h> | ||
19 | #include <mach/cns3xxx.h> | ||
20 | #include "sdhci.h" | ||
21 | #include "sdhci-pltfm.h" | ||
22 | |||
23 | static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host) | ||
24 | { | ||
25 | return 150000000; | ||
26 | } | ||
27 | |||
28 | static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock) | ||
29 | { | ||
30 | struct device *dev = mmc_dev(host->mmc); | ||
31 | int div = 1; | ||
32 | u16 clk; | ||
33 | unsigned long timeout; | ||
34 | |||
35 | if (clock == host->clock) | ||
36 | return; | ||
37 | |||
38 | sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); | ||
39 | |||
40 | if (clock == 0) | ||
41 | goto out; | ||
42 | |||
43 | while (host->max_clk / div > clock) { | ||
44 | /* | ||
45 | * On CNS3xxx divider grows linearly up to 4, and then | ||
46 | * exponentially up to 256. | ||
47 | */ | ||
48 | if (div < 4) | ||
49 | div += 1; | ||
50 | else if (div < 256) | ||
51 | div *= 2; | ||
52 | else | ||
53 | break; | ||
54 | } | ||
55 | |||
56 | dev_dbg(dev, "desired SD clock: %d, actual: %d\n", | ||
57 | clock, host->max_clk / div); | ||
58 | |||
59 | /* Divide by 3 is special. */ | ||
60 | if (div != 3) | ||
61 | div >>= 1; | ||
62 | |||
63 | clk = div << SDHCI_DIVIDER_SHIFT; | ||
64 | clk |= SDHCI_CLOCK_INT_EN; | ||
65 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
66 | |||
67 | timeout = 20; | ||
68 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) | ||
69 | & SDHCI_CLOCK_INT_STABLE)) { | ||
70 | if (timeout == 0) { | ||
71 | dev_warn(dev, "clock is unstable"); | ||
72 | break; | ||
73 | } | ||
74 | timeout--; | ||
75 | mdelay(1); | ||
76 | } | ||
77 | |||
78 | clk |= SDHCI_CLOCK_CARD_EN; | ||
79 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
80 | out: | ||
81 | host->clock = clock; | ||
82 | } | ||
83 | |||
84 | static struct sdhci_ops sdhci_cns3xxx_ops = { | ||
85 | .get_max_clock = sdhci_cns3xxx_get_max_clk, | ||
86 | .set_clock = sdhci_cns3xxx_set_clock, | ||
87 | }; | ||
88 | |||
89 | struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { | ||
90 | .ops = &sdhci_cns3xxx_ops, | ||
91 | .quirks = SDHCI_QUIRK_BROKEN_DMA | | ||
92 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | ||
93 | SDHCI_QUIRK_INVERTED_WRITE_PROTECT | | ||
94 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | | ||
95 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | ||
96 | SDHCI_QUIRK_NONSTANDARD_CLOCK, | ||
97 | }; | ||
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c index a2e9820cd42f..c51b71174c1d 100644 --- a/drivers/mmc/host/sdhci-of-core.c +++ b/drivers/mmc/host/sdhci-of-core.c | |||
@@ -85,14 +85,14 @@ void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) | |||
85 | 85 | ||
86 | #ifdef CONFIG_PM | 86 | #ifdef CONFIG_PM |
87 | 87 | ||
88 | static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state) | 88 | static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state) |
89 | { | 89 | { |
90 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | 90 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); |
91 | 91 | ||
92 | return mmc_suspend_host(host->mmc); | 92 | return mmc_suspend_host(host->mmc); |
93 | } | 93 | } |
94 | 94 | ||
95 | static int sdhci_of_resume(struct of_device *ofdev) | 95 | static int sdhci_of_resume(struct platform_device *ofdev) |
96 | { | 96 | { |
97 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | 97 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); |
98 | 98 | ||
@@ -115,7 +115,7 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np) | |||
115 | return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); | 115 | return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); |
116 | } | 116 | } |
117 | 117 | ||
118 | static int __devinit sdhci_of_probe(struct of_device *ofdev, | 118 | static int __devinit sdhci_of_probe(struct platform_device *ofdev, |
119 | const struct of_device_id *match) | 119 | const struct of_device_id *match) |
120 | { | 120 | { |
121 | struct device_node *np = ofdev->dev.of_node; | 121 | struct device_node *np = ofdev->dev.of_node; |
@@ -154,6 +154,10 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev, | |||
154 | host->ops = &sdhci_of_data->ops; | 154 | host->ops = &sdhci_of_data->ops; |
155 | } | 155 | } |
156 | 156 | ||
157 | if (of_get_property(np, "sdhci,auto-cmd12", NULL)) | ||
158 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; | ||
159 | |||
160 | |||
157 | if (of_get_property(np, "sdhci,1-bit-only", NULL)) | 161 | if (of_get_property(np, "sdhci,1-bit-only", NULL)) |
158 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; | 162 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; |
159 | 163 | ||
@@ -179,7 +183,7 @@ err_addr_map: | |||
179 | return ret; | 183 | return ret; |
180 | } | 184 | } |
181 | 185 | ||
182 | static int __devexit sdhci_of_remove(struct of_device *ofdev) | 186 | static int __devexit sdhci_of_remove(struct platform_device *ofdev) |
183 | { | 187 | { |
184 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | 188 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); |
185 | 189 | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 65483fdea45b..e8aa99deae9a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/device.h> | ||
20 | 21 | ||
21 | #include <linux/mmc/host.h> | 22 | #include <linux/mmc/host.h> |
22 | 23 | ||
@@ -84,7 +85,30 @@ static int ricoh_probe(struct sdhci_pci_chip *chip) | |||
84 | if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG || | 85 | if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG || |
85 | chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY) | 86 | chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY) |
86 | chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET; | 87 | chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET; |
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int ricoh_mmc_probe_slot(struct sdhci_pci_slot *slot) | ||
92 | { | ||
93 | slot->host->caps = | ||
94 | ((0x21 << SDHCI_TIMEOUT_CLK_SHIFT) | ||
95 | & SDHCI_TIMEOUT_CLK_MASK) | | ||
96 | |||
97 | ((0x21 << SDHCI_CLOCK_BASE_SHIFT) | ||
98 | & SDHCI_CLOCK_BASE_MASK) | | ||
87 | 99 | ||
100 | SDHCI_TIMEOUT_CLK_UNIT | | ||
101 | SDHCI_CAN_VDD_330 | | ||
102 | SDHCI_CAN_DO_SDMA; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int ricoh_mmc_resume(struct sdhci_pci_chip *chip) | ||
107 | { | ||
108 | /* Apply a delay to allow controller to settle */ | ||
109 | /* Otherwise it becomes confused if card state changed | ||
110 | during suspend */ | ||
111 | msleep(500); | ||
88 | return 0; | 112 | return 0; |
89 | } | 113 | } |
90 | 114 | ||
@@ -95,6 +119,15 @@ static const struct sdhci_pci_fixes sdhci_ricoh = { | |||
95 | SDHCI_QUIRK_CLOCK_BEFORE_RESET, | 119 | SDHCI_QUIRK_CLOCK_BEFORE_RESET, |
96 | }; | 120 | }; |
97 | 121 | ||
122 | static const struct sdhci_pci_fixes sdhci_ricoh_mmc = { | ||
123 | .probe_slot = ricoh_mmc_probe_slot, | ||
124 | .resume = ricoh_mmc_resume, | ||
125 | .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | | ||
126 | SDHCI_QUIRK_CLOCK_BEFORE_RESET | | ||
127 | SDHCI_QUIRK_NO_CARD_NO_RESET | | ||
128 | SDHCI_QUIRK_MISSING_CAPS | ||
129 | }; | ||
130 | |||
98 | static const struct sdhci_pci_fixes sdhci_ene_712 = { | 131 | static const struct sdhci_pci_fixes sdhci_ene_712 = { |
99 | .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE | | 132 | .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE | |
100 | SDHCI_QUIRK_BROKEN_DMA, | 133 | SDHCI_QUIRK_BROKEN_DMA, |
@@ -374,6 +407,22 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
374 | }, | 407 | }, |
375 | 408 | ||
376 | { | 409 | { |
410 | .vendor = PCI_VENDOR_ID_RICOH, | ||
411 | .device = 0x843, | ||
412 | .subvendor = PCI_ANY_ID, | ||
413 | .subdevice = PCI_ANY_ID, | ||
414 | .driver_data = (kernel_ulong_t)&sdhci_ricoh_mmc, | ||
415 | }, | ||
416 | |||
417 | { | ||
418 | .vendor = PCI_VENDOR_ID_RICOH, | ||
419 | .device = 0xe822, | ||
420 | .subvendor = PCI_ANY_ID, | ||
421 | .subdevice = PCI_ANY_ID, | ||
422 | .driver_data = (kernel_ulong_t)&sdhci_ricoh_mmc, | ||
423 | }, | ||
424 | |||
425 | { | ||
377 | .vendor = PCI_VENDOR_ID_ENE, | 426 | .vendor = PCI_VENDOR_ID_ENE, |
378 | .device = PCI_DEVICE_ID_ENE_CB712_SD, | 427 | .device = PCI_DEVICE_ID_ENE_CB712_SD, |
379 | .subvendor = PCI_ANY_ID, | 428 | .subvendor = PCI_ANY_ID, |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index b6ee0d719698..e045e3c61dde 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/highmem.h> | 26 | #include <linux/highmem.h> |
27 | #include <linux/mod_devicetable.h> | ||
27 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
28 | 29 | ||
29 | #include <linux/mmc/host.h> | 30 | #include <linux/mmc/host.h> |
@@ -32,6 +33,7 @@ | |||
32 | #include <linux/sdhci-pltfm.h> | 33 | #include <linux/sdhci-pltfm.h> |
33 | 34 | ||
34 | #include "sdhci.h" | 35 | #include "sdhci.h" |
36 | #include "sdhci-pltfm.h" | ||
35 | 37 | ||
36 | /*****************************************************************************\ | 38 | /*****************************************************************************\ |
37 | * * | 39 | * * |
@@ -51,10 +53,14 @@ static struct sdhci_ops sdhci_pltfm_ops = { | |||
51 | static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | 53 | static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) |
52 | { | 54 | { |
53 | struct sdhci_pltfm_data *pdata = pdev->dev.platform_data; | 55 | struct sdhci_pltfm_data *pdata = pdev->dev.platform_data; |
56 | const struct platform_device_id *platid = platform_get_device_id(pdev); | ||
54 | struct sdhci_host *host; | 57 | struct sdhci_host *host; |
55 | struct resource *iomem; | 58 | struct resource *iomem; |
56 | int ret; | 59 | int ret; |
57 | 60 | ||
61 | if (!pdata && platid && platid->driver_data) | ||
62 | pdata = (void *)platid->driver_data; | ||
63 | |||
58 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 64 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
59 | if (!iomem) { | 65 | if (!iomem) { |
60 | ret = -ENOMEM; | 66 | ret = -ENOMEM; |
@@ -150,6 +156,15 @@ static int __devexit sdhci_pltfm_remove(struct platform_device *pdev) | |||
150 | return 0; | 156 | return 0; |
151 | } | 157 | } |
152 | 158 | ||
159 | static const struct platform_device_id sdhci_pltfm_ids[] = { | ||
160 | { "sdhci", }, | ||
161 | #ifdef CONFIG_MMC_SDHCI_CNS3XXX | ||
162 | { "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata }, | ||
163 | #endif | ||
164 | { }, | ||
165 | }; | ||
166 | MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids); | ||
167 | |||
153 | static struct platform_driver sdhci_pltfm_driver = { | 168 | static struct platform_driver sdhci_pltfm_driver = { |
154 | .driver = { | 169 | .driver = { |
155 | .name = "sdhci", | 170 | .name = "sdhci", |
@@ -157,6 +172,7 @@ static struct platform_driver sdhci_pltfm_driver = { | |||
157 | }, | 172 | }, |
158 | .probe = sdhci_pltfm_probe, | 173 | .probe = sdhci_pltfm_probe, |
159 | .remove = __devexit_p(sdhci_pltfm_remove), | 174 | .remove = __devexit_p(sdhci_pltfm_remove), |
175 | .id_table = sdhci_pltfm_ids, | ||
160 | }; | 176 | }; |
161 | 177 | ||
162 | /*****************************************************************************\ | 178 | /*****************************************************************************\ |
@@ -181,4 +197,3 @@ module_exit(sdhci_drv_exit); | |||
181 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver"); | 197 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver"); |
182 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); | 198 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); |
183 | MODULE_LICENSE("GPL v2"); | 199 | MODULE_LICENSE("GPL v2"); |
184 | MODULE_ALIAS("platform:sdhci"); | ||
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h new file mode 100644 index 000000000000..900f32902f73 --- /dev/null +++ b/drivers/mmc/host/sdhci-pltfm.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Copyright 2010 MontaVista Software, LLC. | ||
3 | * | ||
4 | * Author: Anton Vorontsov <avorontsov@ru.mvista.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 _DRIVERS_MMC_SDHCI_PLTFM_H | ||
12 | #define _DRIVERS_MMC_SDHCI_PLTFM_H | ||
13 | |||
14 | #include <linux/sdhci-pltfm.h> | ||
15 | |||
16 | extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata; | ||
17 | |||
18 | #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ | ||
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index ad30f074ee15..0a7f2614c6f0 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/gpio.h> | ||
21 | 22 | ||
22 | #include <linux/mmc/host.h> | 23 | #include <linux/mmc/host.h> |
23 | 24 | ||
@@ -44,6 +45,8 @@ struct sdhci_s3c { | |||
44 | struct resource *ioarea; | 45 | struct resource *ioarea; |
45 | struct s3c_sdhci_platdata *pdata; | 46 | struct s3c_sdhci_platdata *pdata; |
46 | unsigned int cur_clk; | 47 | unsigned int cur_clk; |
48 | int ext_cd_irq; | ||
49 | int ext_cd_gpio; | ||
47 | 50 | ||
48 | struct clk *clk_io; | 51 | struct clk *clk_io; |
49 | struct clk *clk_bus[MAX_BUS_CLK]; | 52 | struct clk *clk_bus[MAX_BUS_CLK]; |
@@ -110,11 +113,6 @@ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) | |||
110 | return max; | 113 | return max; |
111 | } | 114 | } |
112 | 115 | ||
113 | static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host) | ||
114 | { | ||
115 | return sdhci_s3c_get_max_clk(host) / 1000000; | ||
116 | } | ||
117 | |||
118 | /** | 116 | /** |
119 | * sdhci_s3c_consider_clock - consider one the bus clocks for current setting | 117 | * sdhci_s3c_consider_clock - consider one the bus clocks for current setting |
120 | * @ourhost: Our SDHCI instance. | 118 | * @ourhost: Our SDHCI instance. |
@@ -188,7 +186,6 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | |||
188 | 186 | ||
189 | ourhost->cur_clk = best_src; | 187 | ourhost->cur_clk = best_src; |
190 | host->max_clk = clk_get_rate(clk); | 188 | host->max_clk = clk_get_rate(clk); |
191 | host->timeout_clk = sdhci_s3c_get_timeout_clk(host); | ||
192 | 189 | ||
193 | ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); | 190 | ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); |
194 | ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | 191 | ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; |
@@ -209,12 +206,93 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | |||
209 | } | 206 | } |
210 | } | 207 | } |
211 | 208 | ||
209 | /** | ||
210 | * sdhci_s3c_get_min_clock - callback to get minimal supported clock value | ||
211 | * @host: The SDHCI host being queried | ||
212 | * | ||
213 | * To init mmc host properly a minimal clock value is needed. For high system | ||
214 | * bus clock's values the standard formula gives values out of allowed range. | ||
215 | * The clock still can be set to lower values, if clock source other then | ||
216 | * system bus is selected. | ||
217 | */ | ||
218 | static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host) | ||
219 | { | ||
220 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
221 | unsigned int delta, min = UINT_MAX; | ||
222 | int src; | ||
223 | |||
224 | for (src = 0; src < MAX_BUS_CLK; src++) { | ||
225 | delta = sdhci_s3c_consider_clock(ourhost, src, 0); | ||
226 | if (delta == UINT_MAX) | ||
227 | continue; | ||
228 | /* delta is a negative value in this case */ | ||
229 | if (-delta < min) | ||
230 | min = -delta; | ||
231 | } | ||
232 | return min; | ||
233 | } | ||
234 | |||
212 | static struct sdhci_ops sdhci_s3c_ops = { | 235 | static struct sdhci_ops sdhci_s3c_ops = { |
213 | .get_max_clock = sdhci_s3c_get_max_clk, | 236 | .get_max_clock = sdhci_s3c_get_max_clk, |
214 | .get_timeout_clock = sdhci_s3c_get_timeout_clk, | ||
215 | .set_clock = sdhci_s3c_set_clock, | 237 | .set_clock = sdhci_s3c_set_clock, |
238 | .get_min_clock = sdhci_s3c_get_min_clock, | ||
216 | }; | 239 | }; |
217 | 240 | ||
241 | static void sdhci_s3c_notify_change(struct platform_device *dev, int state) | ||
242 | { | ||
243 | struct sdhci_host *host = platform_get_drvdata(dev); | ||
244 | if (host) { | ||
245 | mutex_lock(&host->lock); | ||
246 | if (state) { | ||
247 | dev_dbg(&dev->dev, "card inserted.\n"); | ||
248 | host->flags &= ~SDHCI_DEVICE_DEAD; | ||
249 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
250 | } else { | ||
251 | dev_dbg(&dev->dev, "card removed.\n"); | ||
252 | host->flags |= SDHCI_DEVICE_DEAD; | ||
253 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
254 | } | ||
255 | sdhci_card_detect(host); | ||
256 | mutex_unlock(&host->lock); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | static irqreturn_t sdhci_s3c_gpio_card_detect_thread(int irq, void *dev_id) | ||
261 | { | ||
262 | struct sdhci_s3c *sc = dev_id; | ||
263 | int status = gpio_get_value(sc->ext_cd_gpio); | ||
264 | if (sc->pdata->ext_cd_gpio_invert) | ||
265 | status = !status; | ||
266 | sdhci_s3c_notify_change(sc->pdev, status); | ||
267 | return IRQ_HANDLED; | ||
268 | } | ||
269 | |||
270 | static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) | ||
271 | { | ||
272 | struct s3c_sdhci_platdata *pdata = sc->pdata; | ||
273 | struct device *dev = &sc->pdev->dev; | ||
274 | |||
275 | if (gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) { | ||
276 | sc->ext_cd_gpio = pdata->ext_cd_gpio; | ||
277 | sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio); | ||
278 | if (sc->ext_cd_irq && | ||
279 | request_threaded_irq(sc->ext_cd_irq, NULL, | ||
280 | sdhci_s3c_gpio_card_detect_thread, | ||
281 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
282 | dev_name(dev), sc) == 0) { | ||
283 | int status = gpio_get_value(sc->ext_cd_gpio); | ||
284 | if (pdata->ext_cd_gpio_invert) | ||
285 | status = !status; | ||
286 | sdhci_s3c_notify_change(sc->pdev, status); | ||
287 | } else { | ||
288 | dev_warn(dev, "cannot request irq for card detect\n"); | ||
289 | sc->ext_cd_irq = 0; | ||
290 | } | ||
291 | } else { | ||
292 | dev_err(dev, "cannot request gpio for card detect\n"); | ||
293 | } | ||
294 | } | ||
295 | |||
218 | static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | 296 | static int __devinit sdhci_s3c_probe(struct platform_device *pdev) |
219 | { | 297 | { |
220 | struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; | 298 | struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; |
@@ -252,6 +330,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
252 | sc->host = host; | 330 | sc->host = host; |
253 | sc->pdev = pdev; | 331 | sc->pdev = pdev; |
254 | sc->pdata = pdata; | 332 | sc->pdata = pdata; |
333 | sc->ext_cd_gpio = -1; /* invalid gpio number */ | ||
255 | 334 | ||
256 | platform_set_drvdata(pdev, host); | 335 | platform_set_drvdata(pdev, host); |
257 | 336 | ||
@@ -318,6 +397,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
318 | 397 | ||
319 | /* Setup quirks for the controller */ | 398 | /* Setup quirks for the controller */ |
320 | host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; | 399 | host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; |
400 | host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; | ||
321 | 401 | ||
322 | #ifndef CONFIG_MMC_SDHCI_S3C_DMA | 402 | #ifndef CONFIG_MMC_SDHCI_S3C_DMA |
323 | 403 | ||
@@ -332,15 +412,34 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
332 | * SDHCI block, or a missing configuration that needs to be set. */ | 412 | * SDHCI block, or a missing configuration that needs to be set. */ |
333 | host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; | 413 | host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; |
334 | 414 | ||
415 | if (pdata->cd_type == S3C_SDHCI_CD_NONE || | ||
416 | pdata->cd_type == S3C_SDHCI_CD_PERMANENT) | ||
417 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
418 | |||
419 | if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) | ||
420 | host->mmc->caps = MMC_CAP_NONREMOVABLE; | ||
421 | |||
335 | host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | | 422 | host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | |
336 | SDHCI_QUIRK_32BIT_DMA_SIZE); | 423 | SDHCI_QUIRK_32BIT_DMA_SIZE); |
337 | 424 | ||
425 | /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ | ||
426 | host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; | ||
427 | |||
338 | ret = sdhci_add_host(host); | 428 | ret = sdhci_add_host(host); |
339 | if (ret) { | 429 | if (ret) { |
340 | dev_err(dev, "sdhci_add_host() failed\n"); | 430 | dev_err(dev, "sdhci_add_host() failed\n"); |
341 | goto err_add_host; | 431 | goto err_add_host; |
342 | } | 432 | } |
343 | 433 | ||
434 | /* The following two methods of card detection might call | ||
435 | sdhci_s3c_notify_change() immediately, so they can be called | ||
436 | only after sdhci_add_host(). Setup errors are ignored. */ | ||
437 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init) | ||
438 | pdata->ext_cd_init(&sdhci_s3c_notify_change); | ||
439 | if (pdata->cd_type == S3C_SDHCI_CD_GPIO && | ||
440 | gpio_is_valid(pdata->ext_cd_gpio)) | ||
441 | sdhci_s3c_setup_card_detect_gpio(sc); | ||
442 | |||
344 | return 0; | 443 | return 0; |
345 | 444 | ||
346 | err_add_host: | 445 | err_add_host: |
@@ -365,10 +464,20 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
365 | 464 | ||
366 | static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | 465 | static int __devexit sdhci_s3c_remove(struct platform_device *pdev) |
367 | { | 466 | { |
467 | struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; | ||
368 | struct sdhci_host *host = platform_get_drvdata(pdev); | 468 | struct sdhci_host *host = platform_get_drvdata(pdev); |
369 | struct sdhci_s3c *sc = sdhci_priv(host); | 469 | struct sdhci_s3c *sc = sdhci_priv(host); |
370 | int ptr; | 470 | int ptr; |
371 | 471 | ||
472 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) | ||
473 | pdata->ext_cd_cleanup(&sdhci_s3c_notify_change); | ||
474 | |||
475 | if (sc->ext_cd_irq) | ||
476 | free_irq(sc->ext_cd_irq, sc); | ||
477 | |||
478 | if (gpio_is_valid(sc->ext_cd_gpio)) | ||
479 | gpio_free(sc->ext_cd_gpio); | ||
480 | |||
372 | sdhci_remove_host(host, 1); | 481 | sdhci_remove_host(host, 1); |
373 | 482 | ||
374 | for (ptr = 0; ptr < 3; ptr++) { | 483 | for (ptr = 0; ptr < 3; ptr++) { |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c6d1bd8d4ac4..785512133b50 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
22 | #include <linux/regulator/consumer.h> | ||
22 | 23 | ||
23 | #include <linux/leds.h> | 24 | #include <linux/leds.h> |
24 | 25 | ||
@@ -817,8 +818,12 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, | |||
817 | WARN_ON(!host->data); | 818 | WARN_ON(!host->data); |
818 | 819 | ||
819 | mode = SDHCI_TRNS_BLK_CNT_EN; | 820 | mode = SDHCI_TRNS_BLK_CNT_EN; |
820 | if (data->blocks > 1) | 821 | if (data->blocks > 1) { |
821 | mode |= SDHCI_TRNS_MULTI; | 822 | if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) |
823 | mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12; | ||
824 | else | ||
825 | mode |= SDHCI_TRNS_MULTI; | ||
826 | } | ||
822 | if (data->flags & MMC_DATA_READ) | 827 | if (data->flags & MMC_DATA_READ) |
823 | mode |= SDHCI_TRNS_READ; | 828 | mode |= SDHCI_TRNS_READ; |
824 | if (host->flags & SDHCI_REQ_USE_DMA) | 829 | if (host->flags & SDHCI_REQ_USE_DMA) |
@@ -1108,6 +1113,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1108 | #ifndef SDHCI_USE_LEDS_CLASS | 1113 | #ifndef SDHCI_USE_LEDS_CLASS |
1109 | sdhci_activate_led(host); | 1114 | sdhci_activate_led(host); |
1110 | #endif | 1115 | #endif |
1116 | if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) { | ||
1117 | if (mrq->stop) { | ||
1118 | mrq->data->stop = NULL; | ||
1119 | mrq->stop = NULL; | ||
1120 | } | ||
1121 | } | ||
1111 | 1122 | ||
1112 | host->mrq = mrq; | 1123 | host->mrq = mrq; |
1113 | 1124 | ||
@@ -1159,6 +1170,11 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1159 | 1170 | ||
1160 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | 1171 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
1161 | 1172 | ||
1173 | if (ios->bus_width == MMC_BUS_WIDTH_8) | ||
1174 | ctrl |= SDHCI_CTRL_8BITBUS; | ||
1175 | else | ||
1176 | ctrl &= ~SDHCI_CTRL_8BITBUS; | ||
1177 | |||
1162 | if (ios->bus_width == MMC_BUS_WIDTH_4) | 1178 | if (ios->bus_width == MMC_BUS_WIDTH_4) |
1163 | ctrl |= SDHCI_CTRL_4BITBUS; | 1179 | ctrl |= SDHCI_CTRL_4BITBUS; |
1164 | else | 1180 | else |
@@ -1603,7 +1619,10 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) | |||
1603 | 1619 | ||
1604 | free_irq(host->irq, host); | 1620 | free_irq(host->irq, host); |
1605 | 1621 | ||
1606 | return 0; | 1622 | if (host->vmmc) |
1623 | ret = regulator_disable(host->vmmc); | ||
1624 | |||
1625 | return ret; | ||
1607 | } | 1626 | } |
1608 | 1627 | ||
1609 | EXPORT_SYMBOL_GPL(sdhci_suspend_host); | 1628 | EXPORT_SYMBOL_GPL(sdhci_suspend_host); |
@@ -1612,6 +1631,13 @@ int sdhci_resume_host(struct sdhci_host *host) | |||
1612 | { | 1631 | { |
1613 | int ret; | 1632 | int ret; |
1614 | 1633 | ||
1634 | if (host->vmmc) { | ||
1635 | int ret = regulator_enable(host->vmmc); | ||
1636 | if (ret) | ||
1637 | return ret; | ||
1638 | } | ||
1639 | |||
1640 | |||
1615 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { | 1641 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { |
1616 | if (host->ops->enable_dma) | 1642 | if (host->ops->enable_dma) |
1617 | host->ops->enable_dma(host); | 1643 | host->ops->enable_dma(host); |
@@ -1687,7 +1713,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1687 | host->version); | 1713 | host->version); |
1688 | } | 1714 | } |
1689 | 1715 | ||
1690 | caps = sdhci_readl(host, SDHCI_CAPABILITIES); | 1716 | caps = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps : |
1717 | sdhci_readl(host, SDHCI_CAPABILITIES); | ||
1691 | 1718 | ||
1692 | if (host->quirks & SDHCI_QUIRK_FORCE_DMA) | 1719 | if (host->quirks & SDHCI_QUIRK_FORCE_DMA) |
1693 | host->flags |= SDHCI_USE_SDMA; | 1720 | host->flags |= SDHCI_USE_SDMA; |
@@ -1785,13 +1812,12 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1785 | * Set host parameters. | 1812 | * Set host parameters. |
1786 | */ | 1813 | */ |
1787 | mmc->ops = &sdhci_ops; | 1814 | mmc->ops = &sdhci_ops; |
1788 | if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK && | 1815 | if (host->ops->get_min_clock) |
1789 | host->ops->set_clock && host->ops->get_min_clock) | ||
1790 | mmc->f_min = host->ops->get_min_clock(host); | 1816 | mmc->f_min = host->ops->get_min_clock(host); |
1791 | else | 1817 | else |
1792 | mmc->f_min = host->max_clk / 256; | 1818 | mmc->f_min = host->max_clk / 256; |
1793 | mmc->f_max = host->max_clk; | 1819 | mmc->f_max = host->max_clk; |
1794 | mmc->caps = MMC_CAP_SDIO_IRQ; | 1820 | mmc->caps |= MMC_CAP_SDIO_IRQ; |
1795 | 1821 | ||
1796 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) | 1822 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) |
1797 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1823 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
@@ -1884,6 +1910,14 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1884 | if (ret) | 1910 | if (ret) |
1885 | goto untasklet; | 1911 | goto untasklet; |
1886 | 1912 | ||
1913 | host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); | ||
1914 | if (IS_ERR(host->vmmc)) { | ||
1915 | printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc)); | ||
1916 | host->vmmc = NULL; | ||
1917 | } else { | ||
1918 | regulator_enable(host->vmmc); | ||
1919 | } | ||
1920 | |||
1887 | sdhci_init(host, 0); | 1921 | sdhci_init(host, 0); |
1888 | 1922 | ||
1889 | #ifdef CONFIG_MMC_DEBUG | 1923 | #ifdef CONFIG_MMC_DEBUG |
@@ -1968,6 +2002,11 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) | |||
1968 | tasklet_kill(&host->card_tasklet); | 2002 | tasklet_kill(&host->card_tasklet); |
1969 | tasklet_kill(&host->finish_tasklet); | 2003 | tasklet_kill(&host->finish_tasklet); |
1970 | 2004 | ||
2005 | if (host->vmmc) { | ||
2006 | regulator_disable(host->vmmc); | ||
2007 | regulator_put(host->vmmc); | ||
2008 | } | ||
2009 | |||
1971 | kfree(host->adma_desc); | 2010 | kfree(host->adma_desc); |
1972 | kfree(host->align_buffer); | 2011 | kfree(host->align_buffer); |
1973 | 2012 | ||
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c8468134adc9..036cfae76368 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -72,6 +72,7 @@ | |||
72 | #define SDHCI_CTRL_ADMA1 0x08 | 72 | #define SDHCI_CTRL_ADMA1 0x08 |
73 | #define SDHCI_CTRL_ADMA32 0x10 | 73 | #define SDHCI_CTRL_ADMA32 0x10 |
74 | #define SDHCI_CTRL_ADMA64 0x18 | 74 | #define SDHCI_CTRL_ADMA64 0x18 |
75 | #define SDHCI_CTRL_8BITBUS 0x20 | ||
75 | 76 | ||
76 | #define SDHCI_POWER_CONTROL 0x29 | 77 | #define SDHCI_POWER_CONTROL 0x29 |
77 | #define SDHCI_POWER_ON 0x01 | 78 | #define SDHCI_POWER_ON 0x01 |
@@ -240,12 +241,18 @@ struct sdhci_host { | |||
240 | #define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) | 241 | #define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) |
241 | /* Controller cannot support End Attribute in NOP ADMA descriptor */ | 242 | /* Controller cannot support End Attribute in NOP ADMA descriptor */ |
242 | #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) | 243 | #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) |
244 | /* Controller is missing device caps. Use caps provided by host */ | ||
245 | #define SDHCI_QUIRK_MISSING_CAPS (1<<27) | ||
246 | /* Controller uses Auto CMD12 command to stop the transfer */ | ||
247 | #define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28) | ||
243 | 248 | ||
244 | int irq; /* Device IRQ */ | 249 | int irq; /* Device IRQ */ |
245 | void __iomem * ioaddr; /* Mapped address */ | 250 | void __iomem * ioaddr; /* Mapped address */ |
246 | 251 | ||
247 | const struct sdhci_ops *ops; /* Low level hw interface */ | 252 | const struct sdhci_ops *ops; /* Low level hw interface */ |
248 | 253 | ||
254 | struct regulator *vmmc; /* Power regulator */ | ||
255 | |||
249 | /* Internal data */ | 256 | /* Internal data */ |
250 | struct mmc_host *mmc; /* MMC structure */ | 257 | struct mmc_host *mmc; /* MMC structure */ |
251 | u64 dma_mask; /* custom DMA mask */ | 258 | u64 dma_mask; /* custom DMA mask */ |
@@ -292,6 +299,8 @@ struct sdhci_host { | |||
292 | 299 | ||
293 | struct timer_list timer; /* Timer for timeouts */ | 300 | struct timer_list timer; /* Timer for timeouts */ |
294 | 301 | ||
302 | unsigned int caps; /* Alternative capabilities */ | ||
303 | |||
295 | unsigned long private[0] ____cacheline_aligned; | 304 | unsigned long private[0] ____cacheline_aligned; |
296 | }; | 305 | }; |
297 | 306 | ||
@@ -407,6 +416,7 @@ static inline void *sdhci_priv(struct sdhci_host *host) | |||
407 | return (void *)host->private; | 416 | return (void *)host->private; |
408 | } | 417 | } |
409 | 418 | ||
419 | extern void sdhci_card_detect(struct sdhci_host *host); | ||
410 | extern int sdhci_add_host(struct sdhci_host *host); | 420 | extern int sdhci_add_host(struct sdhci_host *host); |
411 | extern void sdhci_remove_host(struct sdhci_host *host, int dead); | 421 | extern void sdhci_remove_host(struct sdhci_host *host, int dead); |
412 | 422 | ||
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 6ac5f9f28ac3..00af55d7afba 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -43,7 +43,7 @@ struct of_flash { | |||
43 | #ifdef CONFIG_MTD_PARTITIONS | 43 | #ifdef CONFIG_MTD_PARTITIONS |
44 | #define OF_FLASH_PARTS(info) ((info)->parts) | 44 | #define OF_FLASH_PARTS(info) ((info)->parts) |
45 | 45 | ||
46 | static int parse_obsolete_partitions(struct of_device *dev, | 46 | static int parse_obsolete_partitions(struct platform_device *dev, |
47 | struct of_flash *info, | 47 | struct of_flash *info, |
48 | struct device_node *dp) | 48 | struct device_node *dp) |
49 | { | 49 | { |
@@ -93,7 +93,7 @@ static int parse_obsolete_partitions(struct of_device *dev, | |||
93 | #define parse_partitions(info, dev) (0) | 93 | #define parse_partitions(info, dev) (0) |
94 | #endif /* MTD_PARTITIONS */ | 94 | #endif /* MTD_PARTITIONS */ |
95 | 95 | ||
96 | static int of_flash_remove(struct of_device *dev) | 96 | static int of_flash_remove(struct platform_device *dev) |
97 | { | 97 | { |
98 | struct of_flash *info; | 98 | struct of_flash *info; |
99 | int i; | 99 | int i; |
@@ -140,7 +140,7 @@ static int of_flash_remove(struct of_device *dev) | |||
140 | /* Helper function to handle probing of the obsolete "direct-mapped" | 140 | /* Helper function to handle probing of the obsolete "direct-mapped" |
141 | * compatible binding, which has an extra "probe-type" property | 141 | * compatible binding, which has an extra "probe-type" property |
142 | * describing the type of flash probe necessary. */ | 142 | * describing the type of flash probe necessary. */ |
143 | static struct mtd_info * __devinit obsolete_probe(struct of_device *dev, | 143 | static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, |
144 | struct map_info *map) | 144 | struct map_info *map) |
145 | { | 145 | { |
146 | struct device_node *dp = dev->dev.of_node; | 146 | struct device_node *dp = dev->dev.of_node; |
@@ -215,7 +215,7 @@ static void __devinit of_free_probes(const char **probes) | |||
215 | } | 215 | } |
216 | #endif | 216 | #endif |
217 | 217 | ||
218 | static int __devinit of_flash_probe(struct of_device *dev, | 218 | static int __devinit of_flash_probe(struct platform_device *dev, |
219 | const struct of_device_id *match) | 219 | const struct of_device_id *match) |
220 | { | 220 | { |
221 | #ifdef CONFIG_MTD_PARTITIONS | 221 | #ifdef CONFIG_MTD_PARTITIONS |
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 8984236a8d0a..3582ba1f9b09 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
@@ -48,7 +48,7 @@ struct map_info uflash_map_templ = { | |||
48 | .bankwidth = UFLASH_BUSWIDTH, | 48 | .bankwidth = UFLASH_BUSWIDTH, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | int uflash_devinit(struct of_device *op, struct device_node *dp) | 51 | int uflash_devinit(struct platform_device *op, struct device_node *dp) |
52 | { | 52 | { |
53 | struct uflash_dev *up; | 53 | struct uflash_dev *up; |
54 | 54 | ||
@@ -108,7 +108,7 @@ int uflash_devinit(struct of_device *op, struct device_node *dp) | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int __devinit uflash_probe(struct of_device *op, const struct of_device_id *match) | 111 | static int __devinit uflash_probe(struct platform_device *op, const struct of_device_id *match) |
112 | { | 112 | { |
113 | struct device_node *dp = op->dev.of_node; | 113 | struct device_node *dp = op->dev.of_node; |
114 | 114 | ||
@@ -121,7 +121,7 @@ static int __devinit uflash_probe(struct of_device *op, const struct of_device_i | |||
121 | return uflash_devinit(op, dp); | 121 | return uflash_devinit(op, dp); |
122 | } | 122 | } |
123 | 123 | ||
124 | static int __devexit uflash_remove(struct of_device *op) | 124 | static int __devexit uflash_remove(struct platform_device *op) |
125 | { | 125 | { |
126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); | 126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); |
127 | 127 | ||
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 5084cc517944..80de0bff6c3a 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -958,7 +958,7 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) | |||
958 | return 0; | 958 | return 0; |
959 | } | 959 | } |
960 | 960 | ||
961 | static int fsl_elbc_ctrl_remove(struct of_device *ofdev) | 961 | static int fsl_elbc_ctrl_remove(struct platform_device *ofdev) |
962 | { | 962 | { |
963 | struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); | 963 | struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); |
964 | int i; | 964 | int i; |
@@ -1013,7 +1013,7 @@ static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) | |||
1013 | * in the chip probe function. | 1013 | * in the chip probe function. |
1014 | */ | 1014 | */ |
1015 | 1015 | ||
1016 | static int __devinit fsl_elbc_ctrl_probe(struct of_device *ofdev, | 1016 | static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev, |
1017 | const struct of_device_id *match) | 1017 | const struct of_device_id *match) |
1018 | { | 1018 | { |
1019 | struct device_node *child; | 1019 | struct device_node *child; |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 1312eda57ba6..4eff8b25e5af 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -217,7 +217,7 @@ err: | |||
217 | return ret; | 217 | return ret; |
218 | } | 218 | } |
219 | 219 | ||
220 | static int __devinit fun_probe(struct of_device *ofdev, | 220 | static int __devinit fun_probe(struct platform_device *ofdev, |
221 | const struct of_device_id *ofid) | 221 | const struct of_device_id *ofid) |
222 | { | 222 | { |
223 | struct fsl_upm_nand *fun; | 223 | struct fsl_upm_nand *fun; |
@@ -335,7 +335,7 @@ err1: | |||
335 | return ret; | 335 | return ret; |
336 | } | 336 | } |
337 | 337 | ||
338 | static int __devexit fun_remove(struct of_device *ofdev) | 338 | static int __devexit fun_remove(struct platform_device *ofdev) |
339 | { | 339 | { |
340 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); | 340 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); |
341 | int i; | 341 | int i; |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 0a130dcaa129..df0c1da4ff49 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -647,7 +647,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) | |||
647 | iounmap(prv->csreg); | 647 | iounmap(prv->csreg); |
648 | } | 648 | } |
649 | 649 | ||
650 | static int __devinit mpc5121_nfc_probe(struct of_device *op, | 650 | static int __devinit mpc5121_nfc_probe(struct platform_device *op, |
651 | const struct of_device_id *match) | 651 | const struct of_device_id *match) |
652 | { | 652 | { |
653 | struct device_node *rootnode, *dn = op->dev.of_node; | 653 | struct device_node *rootnode, *dn = op->dev.of_node; |
@@ -869,7 +869,7 @@ error: | |||
869 | return retval; | 869 | return retval; |
870 | } | 870 | } |
871 | 871 | ||
872 | static int __devexit mpc5121_nfc_remove(struct of_device *op) | 872 | static int __devexit mpc5121_nfc_remove(struct platform_device *op) |
873 | { | 873 | { |
874 | struct device *dev = &op->dev; | 874 | struct device *dev = &op->dev; |
875 | struct mtd_info *mtd = dev_get_drvdata(dev); | 875 | struct mtd_info *mtd = dev_get_drvdata(dev); |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 16a1714df008..a3c7473dd409 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -889,17 +889,17 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
889 | } | 889 | } |
890 | 890 | ||
891 | /** | 891 | /** |
892 | * __nand_unlock - [REPLACABLE] unlocks specified locked blockes | 892 | * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks |
893 | * | 893 | * |
894 | * @param mtd - mtd info | 894 | * @mtd: mtd info |
895 | * @param ofs - offset to start unlock from | 895 | * @ofs: offset to start unlock from |
896 | * @param len - length to unlock | 896 | * @len: length to unlock |
897 | * @invert - when = 0, unlock the range of blocks within the lower and | 897 | * @invert: when = 0, unlock the range of blocks within the lower and |
898 | * upper boundary address | 898 | * upper boundary address |
899 | * whne = 1, unlock the range of blocks outside the boundaries | 899 | * when = 1, unlock the range of blocks outside the boundaries |
900 | * of the lower and upper boundary address | 900 | * of the lower and upper boundary address |
901 | * | 901 | * |
902 | * @return - unlock status | 902 | * return - unlock status |
903 | */ | 903 | */ |
904 | static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, | 904 | static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, |
905 | uint64_t len, int invert) | 905 | uint64_t len, int invert) |
@@ -931,13 +931,13 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, | |||
931 | } | 931 | } |
932 | 932 | ||
933 | /** | 933 | /** |
934 | * nand_unlock - [REPLACABLE] unlocks specified locked blockes | 934 | * nand_unlock - [REPLACEABLE] unlocks specified locked blocks |
935 | * | 935 | * |
936 | * @param mtd - mtd info | 936 | * @mtd: mtd info |
937 | * @param ofs - offset to start unlock from | 937 | * @ofs: offset to start unlock from |
938 | * @param len - length to unlock | 938 | * @len: length to unlock |
939 | * | 939 | * |
940 | * @return - unlock status | 940 | * return - unlock status |
941 | */ | 941 | */ |
942 | int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 942 | int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
943 | { | 943 | { |
@@ -982,16 +982,16 @@ out: | |||
982 | } | 982 | } |
983 | 983 | ||
984 | /** | 984 | /** |
985 | * nand_lock - [REPLACABLE] locks all blockes present in the device | 985 | * nand_lock - [REPLACEABLE] locks all blocks present in the device |
986 | * | 986 | * |
987 | * @param mtd - mtd info | 987 | * @mtd: mtd info |
988 | * @param ofs - offset to start unlock from | 988 | * @ofs: offset to start unlock from |
989 | * @param len - length to unlock | 989 | * @len: length to unlock |
990 | * | 990 | * |
991 | * @return - lock status | 991 | * return - lock status |
992 | * | 992 | * |
993 | * This feature is not support in many NAND parts. 'Micron' NAND parts | 993 | * This feature is not supported in many NAND parts. 'Micron' NAND parts |
994 | * do have this feature, but it allows only to lock all blocks not for | 994 | * do have this feature, but it allows only to lock all blocks, not for |
995 | * specified range for block. | 995 | * specified range for block. |
996 | * | 996 | * |
997 | * Implementing 'lock' feature by making use of 'unlock', for now. | 997 | * Implementing 'lock' feature by making use of 'unlock', for now. |
@@ -2093,6 +2093,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
2093 | * nand_fill_oob - [Internal] Transfer client buffer to oob | 2093 | * nand_fill_oob - [Internal] Transfer client buffer to oob |
2094 | * @chip: nand chip structure | 2094 | * @chip: nand chip structure |
2095 | * @oob: oob data buffer | 2095 | * @oob: oob data buffer |
2096 | * @len: oob data write length | ||
2096 | * @ops: oob ops structure | 2097 | * @ops: oob ops structure |
2097 | */ | 2098 | */ |
2098 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | 2099 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 98fd2bdf8be1..510554e6c115 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | 36 | ||
37 | struct ndfc_controller { | 37 | struct ndfc_controller { |
38 | struct of_device *ofdev; | 38 | struct platform_device *ofdev; |
39 | void __iomem *ndfcbase; | 39 | void __iomem *ndfcbase; |
40 | struct mtd_info mtd; | 40 | struct mtd_info mtd; |
41 | struct nand_chip chip; | 41 | struct nand_chip chip; |
@@ -225,7 +225,7 @@ err: | |||
225 | return ret; | 225 | return ret; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int __devinit ndfc_probe(struct of_device *ofdev, | 228 | static int __devinit ndfc_probe(struct platform_device *ofdev, |
229 | const struct of_device_id *match) | 229 | const struct of_device_id *match) |
230 | { | 230 | { |
231 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 231 | struct ndfc_controller *ndfc = &ndfc_ctrl; |
@@ -277,7 +277,7 @@ static int __devinit ndfc_probe(struct of_device *ofdev, | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | static int __devexit ndfc_remove(struct of_device *ofdev) | 280 | static int __devexit ndfc_remove(struct platform_device *ofdev) |
281 | { | 281 | { |
282 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); | 282 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); |
283 | 283 | ||
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index f02af24d033a..6ddb2461d740 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
@@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd) | |||
89 | return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); | 89 | return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int __devinit pasemi_nand_probe(struct of_device *ofdev, | 92 | static int __devinit pasemi_nand_probe(struct platform_device *ofdev, |
93 | const struct of_device_id *match) | 93 | const struct of_device_id *match) |
94 | { | 94 | { |
95 | struct pci_dev *pdev; | 95 | struct pci_dev *pdev; |
@@ -185,7 +185,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev, | |||
185 | return err; | 185 | return err; |
186 | } | 186 | } |
187 | 187 | ||
188 | static int __devexit pasemi_nand_remove(struct of_device *ofdev) | 188 | static int __devexit pasemi_nand_remove(struct platform_device *ofdev) |
189 | { | 189 | { |
190 | struct nand_chip *chip; | 190 | struct nand_chip *chip; |
191 | 191 | ||
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index cc728b12de82..a8e403eebedb 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c | |||
@@ -162,7 +162,7 @@ static const char *part_probes[] = { "cmdlinepart", NULL }; | |||
162 | /* | 162 | /* |
163 | * Probe for the NAND device. | 163 | * Probe for the NAND device. |
164 | */ | 164 | */ |
165 | static int __devinit socrates_nand_probe(struct of_device *ofdev, | 165 | static int __devinit socrates_nand_probe(struct platform_device *ofdev, |
166 | const struct of_device_id *ofid) | 166 | const struct of_device_id *ofid) |
167 | { | 167 | { |
168 | struct socrates_nand_host *host; | 168 | struct socrates_nand_host *host; |
@@ -276,7 +276,7 @@ out: | |||
276 | /* | 276 | /* |
277 | * Remove a NAND device. | 277 | * Remove a NAND device. |
278 | */ | 278 | */ |
279 | static int __devexit socrates_nand_remove(struct of_device *ofdev) | 279 | static int __devexit socrates_nand_remove(struct platform_device *ofdev) |
280 | { | 280 | { |
281 | struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); | 281 | struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); |
282 | struct mtd_info *mtd = &host->mtd; | 282 | struct mtd_info *mtd = &host->mtd; |
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 4f1cc7164ad9..6028226a7270 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c | |||
@@ -241,7 +241,7 @@ static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt) | |||
241 | 241 | ||
242 | static spinlock_t mdio_lock; | 242 | static spinlock_t mdio_lock; |
243 | static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */ | 243 | static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */ |
244 | struct mii_bus *mdio_bus; | 244 | static struct mii_bus *mdio_bus; |
245 | static int ports_open; | 245 | static int ports_open; |
246 | static struct port *npe_port_tab[MAX_NPES]; | 246 | static struct port *npe_port_tab[MAX_NPES]; |
247 | static struct dma_pool *dma_pool; | 247 | static struct dma_pool *dma_pool; |
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c index 077ccf840edf..2111dbfea6fe 100644 --- a/drivers/net/caif/caif_spi_slave.c +++ b/drivers/net/caif/caif_spi_slave.c | |||
@@ -22,13 +22,13 @@ | |||
22 | #include <net/caif/caif_spi.h> | 22 | #include <net/caif/caif_spi.h> |
23 | 23 | ||
24 | #ifndef CONFIG_CAIF_SPI_SYNC | 24 | #ifndef CONFIG_CAIF_SPI_SYNC |
25 | #define SPI_DATA_POS SPI_CMD_SZ | 25 | #define SPI_DATA_POS 0 |
26 | static inline int forward_to_spi_cmd(struct cfspi *cfspi) | 26 | static inline int forward_to_spi_cmd(struct cfspi *cfspi) |
27 | { | 27 | { |
28 | return cfspi->rx_cpck_len; | 28 | return cfspi->rx_cpck_len; |
29 | } | 29 | } |
30 | #else | 30 | #else |
31 | #define SPI_DATA_POS 0 | 31 | #define SPI_DATA_POS SPI_CMD_SZ |
32 | static inline int forward_to_spi_cmd(struct cfspi *cfspi) | 32 | static inline int forward_to_spi_cmd(struct cfspi *cfspi) |
33 | { | 33 | { |
34 | return 0; | 34 | return 0; |
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index af753936e835..b1bdc909090f 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | struct mpc5xxx_can_data { | 39 | struct mpc5xxx_can_data { |
40 | unsigned int type; | 40 | unsigned int type; |
41 | u32 (*get_clock)(struct of_device *ofdev, const char *clock_name, | 41 | u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name, |
42 | int *mscan_clksrc); | 42 | int *mscan_clksrc); |
43 | }; | 43 | }; |
44 | 44 | ||
@@ -48,7 +48,7 @@ static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = { | |||
48 | {} | 48 | {} |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, | 51 | static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, |
52 | const char *clock_name, | 52 | const char *clock_name, |
53 | int *mscan_clksrc) | 53 | int *mscan_clksrc) |
54 | { | 54 | { |
@@ -101,7 +101,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, | |||
101 | return freq; | 101 | return freq; |
102 | } | 102 | } |
103 | #else /* !CONFIG_PPC_MPC52xx */ | 103 | #else /* !CONFIG_PPC_MPC52xx */ |
104 | static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, | 104 | static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, |
105 | const char *clock_name, | 105 | const char *clock_name, |
106 | int *mscan_clksrc) | 106 | int *mscan_clksrc) |
107 | { | 107 | { |
@@ -129,7 +129,7 @@ static struct of_device_id __devinitdata mpc512x_clock_ids[] = { | |||
129 | {} | 129 | {} |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | 132 | static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, |
133 | const char *clock_name, | 133 | const char *clock_name, |
134 | int *mscan_clksrc) | 134 | int *mscan_clksrc) |
135 | { | 135 | { |
@@ -239,7 +239,7 @@ exit_unmap: | |||
239 | return freq; | 239 | return freq; |
240 | } | 240 | } |
241 | #else /* !CONFIG_PPC_MPC512x */ | 241 | #else /* !CONFIG_PPC_MPC512x */ |
242 | static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | 242 | static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, |
243 | const char *clock_name, | 243 | const char *clock_name, |
244 | int *mscan_clksrc) | 244 | int *mscan_clksrc) |
245 | { | 245 | { |
@@ -247,7 +247,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, | |||
247 | } | 247 | } |
248 | #endif /* CONFIG_PPC_MPC512x */ | 248 | #endif /* CONFIG_PPC_MPC512x */ |
249 | 249 | ||
250 | static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, | 250 | static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev, |
251 | const struct of_device_id *id) | 251 | const struct of_device_id *id) |
252 | { | 252 | { |
253 | struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; | 253 | struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; |
@@ -317,7 +317,7 @@ exit_unmap_mem: | |||
317 | return err; | 317 | return err; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) | 320 | static int __devexit mpc5xxx_can_remove(struct platform_device *ofdev) |
321 | { | 321 | { |
322 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 322 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
323 | struct mscan_priv *priv = netdev_priv(dev); | 323 | struct mscan_priv *priv = netdev_priv(dev); |
@@ -334,7 +334,7 @@ static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) | |||
334 | 334 | ||
335 | #ifdef CONFIG_PM | 335 | #ifdef CONFIG_PM |
336 | static struct mscan_regs saved_regs; | 336 | static struct mscan_regs saved_regs; |
337 | static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) | 337 | static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state) |
338 | { | 338 | { |
339 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 339 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
340 | struct mscan_priv *priv = netdev_priv(dev); | 340 | struct mscan_priv *priv = netdev_priv(dev); |
@@ -345,7 +345,7 @@ static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) | |||
345 | return 0; | 345 | return 0; |
346 | } | 346 | } |
347 | 347 | ||
348 | static int mpc5xxx_can_resume(struct of_device *ofdev) | 348 | static int mpc5xxx_can_resume(struct platform_device *ofdev) |
349 | { | 349 | { |
350 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 350 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
351 | struct mscan_priv *priv = netdev_priv(dev); | 351 | struct mscan_priv *priv = netdev_priv(dev); |
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index ac1a83d7c204..5bfccfdf3bbb 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c | |||
@@ -67,7 +67,7 @@ static void sja1000_ofp_write_reg(const struct sja1000_priv *priv, | |||
67 | out_8(priv->reg_base + reg, val); | 67 | out_8(priv->reg_base + reg, val); |
68 | } | 68 | } |
69 | 69 | ||
70 | static int __devexit sja1000_ofp_remove(struct of_device *ofdev) | 70 | static int __devexit sja1000_ofp_remove(struct platform_device *ofdev) |
71 | { | 71 | { |
72 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); | 72 | struct net_device *dev = dev_get_drvdata(&ofdev->dev); |
73 | struct sja1000_priv *priv = netdev_priv(dev); | 73 | struct sja1000_priv *priv = netdev_priv(dev); |
@@ -87,7 +87,7 @@ static int __devexit sja1000_ofp_remove(struct of_device *ofdev) | |||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int __devinit sja1000_ofp_probe(struct of_device *ofdev, | 90 | static int __devinit sja1000_ofp_probe(struct platform_device *ofdev, |
91 | const struct of_device_id *id) | 91 | const struct of_device_id *id) |
92 | { | 92 | { |
93 | struct device_node *np = ofdev->dev.of_node; | 93 | struct device_node *np = ofdev->dev.of_node; |
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0060e422f171..99a929964e3c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h | |||
@@ -413,7 +413,7 @@ struct ehea_port_res { | |||
413 | 413 | ||
414 | struct ehea_adapter { | 414 | struct ehea_adapter { |
415 | u64 handle; | 415 | u64 handle; |
416 | struct of_device *ofdev; | 416 | struct platform_device *ofdev; |
417 | struct ehea_port *port[EHEA_MAX_PORTS]; | 417 | struct ehea_port *port[EHEA_MAX_PORTS]; |
418 | struct ehea_eq *neq; /* notification event queue */ | 418 | struct ehea_eq *neq; /* notification event queue */ |
419 | struct tasklet_struct neq_tasklet; | 419 | struct tasklet_struct neq_tasklet; |
@@ -465,7 +465,7 @@ struct ehea_port { | |||
465 | struct net_device *netdev; | 465 | struct net_device *netdev; |
466 | struct net_device_stats stats; | 466 | struct net_device_stats stats; |
467 | struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; | 467 | struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; |
468 | struct of_device ofdev; /* Open Firmware Device */ | 468 | struct platform_device ofdev; /* Open Firmware Device */ |
469 | struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ | 469 | struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ |
470 | struct vlan_group *vgrp; | 470 | struct vlan_group *vgrp; |
471 | struct ehea_eq *qp_eq; | 471 | struct ehea_eq *qp_eq; |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 3beba70b7dea..897719b49f96 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -107,10 +107,10 @@ struct ehea_fw_handle_array ehea_fw_handles; | |||
107 | struct ehea_bcmc_reg_array ehea_bcmc_regs; | 107 | struct ehea_bcmc_reg_array ehea_bcmc_regs; |
108 | 108 | ||
109 | 109 | ||
110 | static int __devinit ehea_probe_adapter(struct of_device *dev, | 110 | static int __devinit ehea_probe_adapter(struct platform_device *dev, |
111 | const struct of_device_id *id); | 111 | const struct of_device_id *id); |
112 | 112 | ||
113 | static int __devexit ehea_remove(struct of_device *dev); | 113 | static int __devexit ehea_remove(struct platform_device *dev); |
114 | 114 | ||
115 | static struct of_device_id ehea_device_table[] = { | 115 | static struct of_device_id ehea_device_table[] = { |
116 | { | 116 | { |
@@ -3376,7 +3376,7 @@ static ssize_t ehea_remove_port(struct device *dev, | |||
3376 | static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); | 3376 | static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); |
3377 | static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); | 3377 | static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); |
3378 | 3378 | ||
3379 | int ehea_create_device_sysfs(struct of_device *dev) | 3379 | int ehea_create_device_sysfs(struct platform_device *dev) |
3380 | { | 3380 | { |
3381 | int ret = device_create_file(&dev->dev, &dev_attr_probe_port); | 3381 | int ret = device_create_file(&dev->dev, &dev_attr_probe_port); |
3382 | if (ret) | 3382 | if (ret) |
@@ -3387,13 +3387,13 @@ out: | |||
3387 | return ret; | 3387 | return ret; |
3388 | } | 3388 | } |
3389 | 3389 | ||
3390 | void ehea_remove_device_sysfs(struct of_device *dev) | 3390 | void ehea_remove_device_sysfs(struct platform_device *dev) |
3391 | { | 3391 | { |
3392 | device_remove_file(&dev->dev, &dev_attr_probe_port); | 3392 | device_remove_file(&dev->dev, &dev_attr_probe_port); |
3393 | device_remove_file(&dev->dev, &dev_attr_remove_port); | 3393 | device_remove_file(&dev->dev, &dev_attr_remove_port); |
3394 | } | 3394 | } |
3395 | 3395 | ||
3396 | static int __devinit ehea_probe_adapter(struct of_device *dev, | 3396 | static int __devinit ehea_probe_adapter(struct platform_device *dev, |
3397 | const struct of_device_id *id) | 3397 | const struct of_device_id *id) |
3398 | { | 3398 | { |
3399 | struct ehea_adapter *adapter; | 3399 | struct ehea_adapter *adapter; |
@@ -3492,7 +3492,7 @@ out: | |||
3492 | return ret; | 3492 | return ret; |
3493 | } | 3493 | } |
3494 | 3494 | ||
3495 | static int __devexit ehea_remove(struct of_device *dev) | 3495 | static int __devexit ehea_remove(struct platform_device *dev) |
3496 | { | 3496 | { |
3497 | struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); | 3497 | struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); |
3498 | int i; | 3498 | int i; |
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index d1a5b17b2a95..e3e10b4add9c 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c | |||
@@ -850,7 +850,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = { | |||
850 | /* ======================================================================== */ | 850 | /* ======================================================================== */ |
851 | 851 | ||
852 | static int __devinit | 852 | static int __devinit |
853 | mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) | 853 | mpc52xx_fec_probe(struct platform_device *op, const struct of_device_id *match) |
854 | { | 854 | { |
855 | int rv; | 855 | int rv; |
856 | struct net_device *ndev; | 856 | struct net_device *ndev; |
@@ -995,7 +995,7 @@ err_netdev: | |||
995 | } | 995 | } |
996 | 996 | ||
997 | static int | 997 | static int |
998 | mpc52xx_fec_remove(struct of_device *op) | 998 | mpc52xx_fec_remove(struct platform_device *op) |
999 | { | 999 | { |
1000 | struct net_device *ndev; | 1000 | struct net_device *ndev; |
1001 | struct mpc52xx_fec_priv *priv; | 1001 | struct mpc52xx_fec_priv *priv; |
@@ -1025,7 +1025,7 @@ mpc52xx_fec_remove(struct of_device *op) | |||
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | #ifdef CONFIG_PM | 1027 | #ifdef CONFIG_PM |
1028 | static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) | 1028 | static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) |
1029 | { | 1029 | { |
1030 | struct net_device *dev = dev_get_drvdata(&op->dev); | 1030 | struct net_device *dev = dev_get_drvdata(&op->dev); |
1031 | 1031 | ||
@@ -1035,7 +1035,7 @@ static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) | |||
1035 | return 0; | 1035 | return 0; |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | static int mpc52xx_fec_of_resume(struct of_device *op) | 1038 | static int mpc52xx_fec_of_resume(struct platform_device *op) |
1039 | { | 1039 | { |
1040 | struct net_device *dev = dev_get_drvdata(&op->dev); | 1040 | struct net_device *dev = dev_get_drvdata(&op->dev); |
1041 | 1041 | ||
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index dbaf72cbb233..0b4cb6f15984 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c | |||
@@ -61,7 +61,7 @@ static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, | |||
61 | data | FEC_MII_WRITE_FRAME); | 61 | data | FEC_MII_WRITE_FRAME); |
62 | } | 62 | } |
63 | 63 | ||
64 | static int mpc52xx_fec_mdio_probe(struct of_device *of, | 64 | static int mpc52xx_fec_mdio_probe(struct platform_device *of, |
65 | const struct of_device_id *match) | 65 | const struct of_device_id *match) |
66 | { | 66 | { |
67 | struct device *dev = &of->dev; | 67 | struct device *dev = &of->dev; |
@@ -122,7 +122,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, | |||
122 | return err; | 122 | return err; |
123 | } | 123 | } |
124 | 124 | ||
125 | static int mpc52xx_fec_mdio_remove(struct of_device *of) | 125 | static int mpc52xx_fec_mdio_remove(struct platform_device *of) |
126 | { | 126 | { |
127 | struct device *dev = &of->dev; | 127 | struct device *dev = &of->dev; |
128 | struct mii_bus *bus = dev_get_drvdata(dev); | 128 | struct mii_bus *bus = dev_get_drvdata(dev); |
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index f08cff9020bd..d6e3111959ab 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c | |||
@@ -997,7 +997,7 @@ static const struct net_device_ops fs_enet_netdev_ops = { | |||
997 | #endif | 997 | #endif |
998 | }; | 998 | }; |
999 | 999 | ||
1000 | static int __devinit fs_enet_probe(struct of_device *ofdev, | 1000 | static int __devinit fs_enet_probe(struct platform_device *ofdev, |
1001 | const struct of_device_id *match) | 1001 | const struct of_device_id *match) |
1002 | { | 1002 | { |
1003 | struct net_device *ndev; | 1003 | struct net_device *ndev; |
@@ -1105,7 +1105,7 @@ out_free_fpi: | |||
1105 | return ret; | 1105 | return ret; |
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | static int fs_enet_remove(struct of_device *ofdev) | 1108 | static int fs_enet_remove(struct platform_device *ofdev) |
1109 | { | 1109 | { |
1110 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); | 1110 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); |
1111 | struct fs_enet_private *fep = netdev_priv(ndev); | 1111 | struct fs_enet_private *fep = netdev_priv(ndev); |
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 48e91b6242ce..7a84e45487e8 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c | |||
@@ -84,7 +84,7 @@ static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op) | |||
84 | 84 | ||
85 | static int do_pd_setup(struct fs_enet_private *fep) | 85 | static int do_pd_setup(struct fs_enet_private *fep) |
86 | { | 86 | { |
87 | struct of_device *ofdev = to_of_device(fep->dev); | 87 | struct platform_device *ofdev = to_platform_device(fep->dev); |
88 | struct fs_platform_info *fpi = fep->fpi; | 88 | struct fs_platform_info *fpi = fep->fpi; |
89 | int ret = -EINVAL; | 89 | int ret = -EINVAL; |
90 | 90 | ||
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 7ca1642276d0..61035fc5599b 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c | |||
@@ -96,7 +96,7 @@ static int whack_reset(struct fec __iomem *fecp) | |||
96 | 96 | ||
97 | static int do_pd_setup(struct fs_enet_private *fep) | 97 | static int do_pd_setup(struct fs_enet_private *fep) |
98 | { | 98 | { |
99 | struct of_device *ofdev = to_of_device(fep->dev); | 99 | struct platform_device *ofdev = to_platform_device(fep->dev); |
100 | 100 | ||
101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); | 101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); |
102 | if (fep->interrupt == NO_IRQ) | 102 | if (fep->interrupt == NO_IRQ) |
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index a3c44544846d..22a02a767069 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c | |||
@@ -96,7 +96,7 @@ static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op) | |||
96 | 96 | ||
97 | static int do_pd_setup(struct fs_enet_private *fep) | 97 | static int do_pd_setup(struct fs_enet_private *fep) |
98 | { | 98 | { |
99 | struct of_device *ofdev = to_of_device(fep->dev); | 99 | struct platform_device *ofdev = to_platform_device(fep->dev); |
100 | 100 | ||
101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); | 101 | fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); |
102 | if (fep->interrupt == NO_IRQ) | 102 | if (fep->interrupt == NO_IRQ) |
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 3607340f3da7..3cda2b515471 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c | |||
@@ -150,7 +150,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, | |||
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, | 153 | static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, |
154 | const struct of_device_id *match) | 154 | const struct of_device_id *match) |
155 | { | 155 | { |
156 | struct mii_bus *new_bus; | 156 | struct mii_bus *new_bus; |
@@ -200,7 +200,7 @@ out: | |||
200 | return ret; | 200 | return ret; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int fs_enet_mdio_remove(struct of_device *ofdev) | 203 | static int fs_enet_mdio_remove(struct platform_device *ofdev) |
204 | { | 204 | { |
205 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); | 205 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); |
206 | struct bb_info *bitbang = bus->priv; | 206 | struct bb_info *bitbang = bus->priv; |
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index bddffd169b93..dbb9c48623df 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c | |||
@@ -101,7 +101,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus) | |||
101 | return 0; | 101 | return 0; |
102 | } | 102 | } |
103 | 103 | ||
104 | static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, | 104 | static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, |
105 | const struct of_device_id *match) | 105 | const struct of_device_id *match) |
106 | { | 106 | { |
107 | struct resource res; | 107 | struct resource res; |
@@ -192,7 +192,7 @@ out: | |||
192 | return ret; | 192 | return ret; |
193 | } | 193 | } |
194 | 194 | ||
195 | static int fs_enet_mdio_remove(struct of_device *ofdev) | 195 | static int fs_enet_mdio_remove(struct platform_device *ofdev) |
196 | { | 196 | { |
197 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); | 197 | struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); |
198 | struct fec_info *fec = bus->priv; | 198 | struct fec_info *fec = bus->priv; |
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index f53f850b6418..d4bf91aac25f 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c | |||
@@ -265,7 +265,7 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) | |||
265 | #endif | 265 | #endif |
266 | 266 | ||
267 | 267 | ||
268 | static int fsl_pq_mdio_probe(struct of_device *ofdev, | 268 | static int fsl_pq_mdio_probe(struct platform_device *ofdev, |
269 | const struct of_device_id *match) | 269 | const struct of_device_id *match) |
270 | { | 270 | { |
271 | struct device_node *np = ofdev->dev.of_node; | 271 | struct device_node *np = ofdev->dev.of_node; |
@@ -425,7 +425,7 @@ err_free_priv: | |||
425 | } | 425 | } |
426 | 426 | ||
427 | 427 | ||
428 | static int fsl_pq_mdio_remove(struct of_device *ofdev) | 428 | static int fsl_pq_mdio_remove(struct platform_device *ofdev) |
429 | { | 429 | { |
430 | struct device *device = &ofdev->dev; | 430 | struct device *device = &ofdev->dev; |
431 | struct mii_bus *bus = dev_get_drvdata(device); | 431 | struct mii_bus *bus = dev_get_drvdata(device); |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a1b6301bc674..4f7c3f3ca234 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -122,9 +122,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id); | |||
122 | static void adjust_link(struct net_device *dev); | 122 | static void adjust_link(struct net_device *dev); |
123 | static void init_registers(struct net_device *dev); | 123 | static void init_registers(struct net_device *dev); |
124 | static int init_phy(struct net_device *dev); | 124 | static int init_phy(struct net_device *dev); |
125 | static int gfar_probe(struct of_device *ofdev, | 125 | static int gfar_probe(struct platform_device *ofdev, |
126 | const struct of_device_id *match); | 126 | const struct of_device_id *match); |
127 | static int gfar_remove(struct of_device *ofdev); | 127 | static int gfar_remove(struct platform_device *ofdev); |
128 | static void free_skb_resources(struct gfar_private *priv); | 128 | static void free_skb_resources(struct gfar_private *priv); |
129 | static void gfar_set_multi(struct net_device *dev); | 129 | static void gfar_set_multi(struct net_device *dev); |
130 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); | 130 | static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); |
@@ -605,7 +605,7 @@ static int gfar_parse_group(struct device_node *np, | |||
605 | return 0; | 605 | return 0; |
606 | } | 606 | } |
607 | 607 | ||
608 | static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev) | 608 | static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) |
609 | { | 609 | { |
610 | const char *model; | 610 | const char *model; |
611 | const char *ctype; | 611 | const char *ctype; |
@@ -959,7 +959,7 @@ static void gfar_detect_errata(struct gfar_private *priv) | |||
959 | 959 | ||
960 | /* Set up the ethernet device structure, private data, | 960 | /* Set up the ethernet device structure, private data, |
961 | * and anything else we need before we start */ | 961 | * and anything else we need before we start */ |
962 | static int gfar_probe(struct of_device *ofdev, | 962 | static int gfar_probe(struct platform_device *ofdev, |
963 | const struct of_device_id *match) | 963 | const struct of_device_id *match) |
964 | { | 964 | { |
965 | u32 tempval; | 965 | u32 tempval; |
@@ -1238,7 +1238,7 @@ register_fail: | |||
1238 | return err; | 1238 | return err; |
1239 | } | 1239 | } |
1240 | 1240 | ||
1241 | static int gfar_remove(struct of_device *ofdev) | 1241 | static int gfar_remove(struct platform_device *ofdev) |
1242 | { | 1242 | { |
1243 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); | 1243 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); |
1244 | 1244 | ||
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 710810e2adb4..68984eb88ae0 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -1054,7 +1054,7 @@ struct gfar_private { | |||
1054 | 1054 | ||
1055 | struct device_node *node; | 1055 | struct device_node *node; |
1056 | struct net_device *ndev; | 1056 | struct net_device *ndev; |
1057 | struct of_device *ofdev; | 1057 | struct platform_device *ofdev; |
1058 | enum gfar_errata errata; | 1058 | enum gfar_errata errata; |
1059 | 1059 | ||
1060 | struct gfar_priv_grp gfargrp[MAXGROUPS]; | 1060 | struct gfar_priv_grp gfargrp[MAXGROUPS]; |
diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 4d09eab3548e..f15c64f1cd38 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c | |||
@@ -1373,7 +1373,7 @@ error: | |||
1373 | } | 1373 | } |
1374 | 1374 | ||
1375 | /* Initialize the GRETH MAC */ | 1375 | /* Initialize the GRETH MAC */ |
1376 | static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_device_id *match) | 1376 | static int __devinit greth_of_probe(struct platform_device *ofdev, const struct of_device_id *match) |
1377 | { | 1377 | { |
1378 | struct net_device *dev; | 1378 | struct net_device *dev; |
1379 | struct greth_private *greth; | 1379 | struct greth_private *greth; |
@@ -1412,7 +1412,7 @@ static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_dev | |||
1412 | } | 1412 | } |
1413 | 1413 | ||
1414 | regs = (struct greth_regs *) greth->regs; | 1414 | regs = (struct greth_regs *) greth->regs; |
1415 | greth->irq = ofdev->irqs[0]; | 1415 | greth->irq = ofdev->archdata.irqs[0]; |
1416 | 1416 | ||
1417 | dev_set_drvdata(greth->dev, dev); | 1417 | dev_set_drvdata(greth->dev, dev); |
1418 | SET_NETDEV_DEV(dev, greth->dev); | 1418 | SET_NETDEV_DEV(dev, greth->dev); |
@@ -1572,7 +1572,7 @@ error1: | |||
1572 | return err; | 1572 | return err; |
1573 | } | 1573 | } |
1574 | 1574 | ||
1575 | static int __devexit greth_of_remove(struct of_device *of_dev) | 1575 | static int __devexit greth_of_remove(struct platform_device *of_dev) |
1576 | { | 1576 | { |
1577 | struct net_device *ndev = dev_get_drvdata(&of_dev->dev); | 1577 | struct net_device *ndev = dev_get_drvdata(&of_dev->dev); |
1578 | struct greth_private *greth = netdev_priv(ndev); | 1578 | struct greth_private *greth = netdev_priv(ndev); |
diff --git a/drivers/net/greth.h b/drivers/net/greth.h index 973388d6abca..03ad903cd676 100644 --- a/drivers/net/greth.h +++ b/drivers/net/greth.h | |||
@@ -118,7 +118,7 @@ struct greth_private { | |||
118 | 118 | ||
119 | int irq; | 119 | int irq; |
120 | 120 | ||
121 | struct device *dev; /* Pointer to of_device->dev */ | 121 | struct device *dev; /* Pointer to platform_device->dev */ |
122 | struct net_device *netdev; | 122 | struct net_device *netdev; |
123 | struct napi_struct napi; | 123 | struct napi_struct napi; |
124 | spinlock_t devlock; | 124 | spinlock_t devlock; |
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index eeec7bc2ce74..3506fd6ad726 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c | |||
@@ -2245,7 +2245,7 @@ static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) | |||
2245 | struct emac_depentry { | 2245 | struct emac_depentry { |
2246 | u32 phandle; | 2246 | u32 phandle; |
2247 | struct device_node *node; | 2247 | struct device_node *node; |
2248 | struct of_device *ofdev; | 2248 | struct platform_device *ofdev; |
2249 | void *drvdata; | 2249 | void *drvdata; |
2250 | }; | 2250 | }; |
2251 | 2251 | ||
@@ -2719,7 +2719,7 @@ static const struct net_device_ops emac_gige_netdev_ops = { | |||
2719 | .ndo_change_mtu = emac_change_mtu, | 2719 | .ndo_change_mtu = emac_change_mtu, |
2720 | }; | 2720 | }; |
2721 | 2721 | ||
2722 | static int __devinit emac_probe(struct of_device *ofdev, | 2722 | static int __devinit emac_probe(struct platform_device *ofdev, |
2723 | const struct of_device_id *match) | 2723 | const struct of_device_id *match) |
2724 | { | 2724 | { |
2725 | struct net_device *ndev; | 2725 | struct net_device *ndev; |
@@ -2941,7 +2941,7 @@ static int __devinit emac_probe(struct of_device *ofdev, | |||
2941 | return err; | 2941 | return err; |
2942 | } | 2942 | } |
2943 | 2943 | ||
2944 | static int __devexit emac_remove(struct of_device *ofdev) | 2944 | static int __devexit emac_remove(struct platform_device *ofdev) |
2945 | { | 2945 | { |
2946 | struct emac_instance *dev = dev_get_drvdata(&ofdev->dev); | 2946 | struct emac_instance *dev = dev_get_drvdata(&ofdev->dev); |
2947 | 2947 | ||
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index b1cbe6fdfc7a..9e37e3d9c51d 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h | |||
@@ -170,12 +170,12 @@ struct emac_instance { | |||
170 | struct net_device *ndev; | 170 | struct net_device *ndev; |
171 | struct resource rsrc_regs; | 171 | struct resource rsrc_regs; |
172 | struct emac_regs __iomem *emacp; | 172 | struct emac_regs __iomem *emacp; |
173 | struct of_device *ofdev; | 173 | struct platform_device *ofdev; |
174 | struct device_node **blist; /* bootlist entry */ | 174 | struct device_node **blist; /* bootlist entry */ |
175 | 175 | ||
176 | /* MAL linkage */ | 176 | /* MAL linkage */ |
177 | u32 mal_ph; | 177 | u32 mal_ph; |
178 | struct of_device *mal_dev; | 178 | struct platform_device *mal_dev; |
179 | u32 mal_rx_chan; | 179 | u32 mal_rx_chan; |
180 | u32 mal_tx_chan; | 180 | u32 mal_tx_chan; |
181 | struct mal_instance *mal; | 181 | struct mal_instance *mal; |
@@ -196,24 +196,24 @@ struct emac_instance { | |||
196 | 196 | ||
197 | /* Shared MDIO if any */ | 197 | /* Shared MDIO if any */ |
198 | u32 mdio_ph; | 198 | u32 mdio_ph; |
199 | struct of_device *mdio_dev; | 199 | struct platform_device *mdio_dev; |
200 | struct emac_instance *mdio_instance; | 200 | struct emac_instance *mdio_instance; |
201 | struct mutex mdio_lock; | 201 | struct mutex mdio_lock; |
202 | 202 | ||
203 | /* ZMII infos if any */ | 203 | /* ZMII infos if any */ |
204 | u32 zmii_ph; | 204 | u32 zmii_ph; |
205 | u32 zmii_port; | 205 | u32 zmii_port; |
206 | struct of_device *zmii_dev; | 206 | struct platform_device *zmii_dev; |
207 | 207 | ||
208 | /* RGMII infos if any */ | 208 | /* RGMII infos if any */ |
209 | u32 rgmii_ph; | 209 | u32 rgmii_ph; |
210 | u32 rgmii_port; | 210 | u32 rgmii_port; |
211 | struct of_device *rgmii_dev; | 211 | struct platform_device *rgmii_dev; |
212 | 212 | ||
213 | /* TAH infos if any */ | 213 | /* TAH infos if any */ |
214 | u32 tah_ph; | 214 | u32 tah_ph; |
215 | u32 tah_port; | 215 | u32 tah_port; |
216 | struct of_device *tah_dev; | 216 | struct platform_device *tah_dev; |
217 | 217 | ||
218 | /* IRQs */ | 218 | /* IRQs */ |
219 | int wol_irq; | 219 | int wol_irq; |
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index fcff9e0bd382..d5717e2123e1 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c | |||
@@ -517,7 +517,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf) | |||
517 | return regs + 1; | 517 | return regs + 1; |
518 | } | 518 | } |
519 | 519 | ||
520 | static int __devinit mal_probe(struct of_device *ofdev, | 520 | static int __devinit mal_probe(struct platform_device *ofdev, |
521 | const struct of_device_id *match) | 521 | const struct of_device_id *match) |
522 | { | 522 | { |
523 | struct mal_instance *mal; | 523 | struct mal_instance *mal; |
@@ -730,7 +730,7 @@ static int __devinit mal_probe(struct of_device *ofdev, | |||
730 | return err; | 730 | return err; |
731 | } | 731 | } |
732 | 732 | ||
733 | static int __devexit mal_remove(struct of_device *ofdev) | 733 | static int __devexit mal_remove(struct platform_device *ofdev) |
734 | { | 734 | { |
735 | struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); | 735 | struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); |
736 | 736 | ||
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 9ededfbf0726..66084214bf45 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h | |||
@@ -210,7 +210,7 @@ struct mal_instance { | |||
210 | dma_addr_t bd_dma; | 210 | dma_addr_t bd_dma; |
211 | struct mal_descriptor *bd_virt; | 211 | struct mal_descriptor *bd_virt; |
212 | 212 | ||
213 | struct of_device *ofdev; | 213 | struct platform_device *ofdev; |
214 | int index; | 214 | int index; |
215 | spinlock_t lock; | 215 | spinlock_t lock; |
216 | 216 | ||
diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 108919bcdf13..dd61798897ac 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c | |||
@@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input) | |||
93 | } | 93 | } |
94 | } | 94 | } |
95 | 95 | ||
96 | int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) | 96 | int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode) |
97 | { | 97 | { |
98 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 98 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
99 | struct rgmii_regs __iomem *p = dev->base; | 99 | struct rgmii_regs __iomem *p = dev->base; |
@@ -122,7 +122,7 @@ int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) | |||
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
124 | 124 | ||
125 | void rgmii_set_speed(struct of_device *ofdev, int input, int speed) | 125 | void rgmii_set_speed(struct platform_device *ofdev, int input, int speed) |
126 | { | 126 | { |
127 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 127 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
128 | struct rgmii_regs __iomem *p = dev->base; | 128 | struct rgmii_regs __iomem *p = dev->base; |
@@ -144,7 +144,7 @@ void rgmii_set_speed(struct of_device *ofdev, int input, int speed) | |||
144 | mutex_unlock(&dev->lock); | 144 | mutex_unlock(&dev->lock); |
145 | } | 145 | } |
146 | 146 | ||
147 | void rgmii_get_mdio(struct of_device *ofdev, int input) | 147 | void rgmii_get_mdio(struct platform_device *ofdev, int input) |
148 | { | 148 | { |
149 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 149 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
150 | struct rgmii_regs __iomem *p = dev->base; | 150 | struct rgmii_regs __iomem *p = dev->base; |
@@ -165,7 +165,7 @@ void rgmii_get_mdio(struct of_device *ofdev, int input) | |||
165 | DBG2(dev, " fer = 0x%08x\n", fer); | 165 | DBG2(dev, " fer = 0x%08x\n", fer); |
166 | } | 166 | } |
167 | 167 | ||
168 | void rgmii_put_mdio(struct of_device *ofdev, int input) | 168 | void rgmii_put_mdio(struct platform_device *ofdev, int input) |
169 | { | 169 | { |
170 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 170 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
171 | struct rgmii_regs __iomem *p = dev->base; | 171 | struct rgmii_regs __iomem *p = dev->base; |
@@ -186,7 +186,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) | |||
186 | mutex_unlock(&dev->lock); | 186 | mutex_unlock(&dev->lock); |
187 | } | 187 | } |
188 | 188 | ||
189 | void rgmii_detach(struct of_device *ofdev, int input) | 189 | void rgmii_detach(struct platform_device *ofdev, int input) |
190 | { | 190 | { |
191 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 191 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
192 | struct rgmii_regs __iomem *p; | 192 | struct rgmii_regs __iomem *p; |
@@ -206,13 +206,13 @@ void rgmii_detach(struct of_device *ofdev, int input) | |||
206 | mutex_unlock(&dev->lock); | 206 | mutex_unlock(&dev->lock); |
207 | } | 207 | } |
208 | 208 | ||
209 | int rgmii_get_regs_len(struct of_device *ofdev) | 209 | int rgmii_get_regs_len(struct platform_device *ofdev) |
210 | { | 210 | { |
211 | return sizeof(struct emac_ethtool_regs_subhdr) + | 211 | return sizeof(struct emac_ethtool_regs_subhdr) + |
212 | sizeof(struct rgmii_regs); | 212 | sizeof(struct rgmii_regs); |
213 | } | 213 | } |
214 | 214 | ||
215 | void *rgmii_dump_regs(struct of_device *ofdev, void *buf) | 215 | void *rgmii_dump_regs(struct platform_device *ofdev, void *buf) |
216 | { | 216 | { |
217 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 217 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
218 | struct emac_ethtool_regs_subhdr *hdr = buf; | 218 | struct emac_ethtool_regs_subhdr *hdr = buf; |
@@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct of_device *ofdev, void *buf) | |||
228 | } | 228 | } |
229 | 229 | ||
230 | 230 | ||
231 | static int __devinit rgmii_probe(struct of_device *ofdev, | 231 | static int __devinit rgmii_probe(struct platform_device *ofdev, |
232 | const struct of_device_id *match) | 232 | const struct of_device_id *match) |
233 | { | 233 | { |
234 | struct device_node *np = ofdev->dev.of_node; | 234 | struct device_node *np = ofdev->dev.of_node; |
@@ -293,7 +293,7 @@ static int __devinit rgmii_probe(struct of_device *ofdev, | |||
293 | return rc; | 293 | return rc; |
294 | } | 294 | } |
295 | 295 | ||
296 | static int __devexit rgmii_remove(struct of_device *ofdev) | 296 | static int __devexit rgmii_remove(struct platform_device *ofdev) |
297 | { | 297 | { |
298 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 298 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
299 | 299 | ||
diff --git a/drivers/net/ibm_newemac/rgmii.h b/drivers/net/ibm_newemac/rgmii.h index c4a4b358a270..d69799049865 100644 --- a/drivers/net/ibm_newemac/rgmii.h +++ b/drivers/net/ibm_newemac/rgmii.h | |||
@@ -51,20 +51,20 @@ struct rgmii_instance { | |||
51 | int users; | 51 | int users; |
52 | 52 | ||
53 | /* OF device instance */ | 53 | /* OF device instance */ |
54 | struct of_device *ofdev; | 54 | struct platform_device *ofdev; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | #ifdef CONFIG_IBM_NEW_EMAC_RGMII | 57 | #ifdef CONFIG_IBM_NEW_EMAC_RGMII |
58 | 58 | ||
59 | extern int rgmii_init(void); | 59 | extern int rgmii_init(void); |
60 | extern void rgmii_exit(void); | 60 | extern void rgmii_exit(void); |
61 | extern int rgmii_attach(struct of_device *ofdev, int input, int mode); | 61 | extern int rgmii_attach(struct platform_device *ofdev, int input, int mode); |
62 | extern void rgmii_detach(struct of_device *ofdev, int input); | 62 | extern void rgmii_detach(struct platform_device *ofdev, int input); |
63 | extern void rgmii_get_mdio(struct of_device *ofdev, int input); | 63 | extern void rgmii_get_mdio(struct platform_device *ofdev, int input); |
64 | extern void rgmii_put_mdio(struct of_device *ofdev, int input); | 64 | extern void rgmii_put_mdio(struct platform_device *ofdev, int input); |
65 | extern void rgmii_set_speed(struct of_device *ofdev, int input, int speed); | 65 | extern void rgmii_set_speed(struct platform_device *ofdev, int input, int speed); |
66 | extern int rgmii_get_regs_len(struct of_device *ofdev); | 66 | extern int rgmii_get_regs_len(struct platform_device *ofdev); |
67 | extern void *rgmii_dump_regs(struct of_device *ofdev, void *buf); | 67 | extern void *rgmii_dump_regs(struct platform_device *ofdev, void *buf); |
68 | 68 | ||
69 | #else | 69 | #else |
70 | 70 | ||
diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c index 044637144c43..299aa49490c0 100644 --- a/drivers/net/ibm_newemac/tah.c +++ b/drivers/net/ibm_newemac/tah.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "emac.h" | 23 | #include "emac.h" |
24 | #include "core.h" | 24 | #include "core.h" |
25 | 25 | ||
26 | int __devinit tah_attach(struct of_device *ofdev, int channel) | 26 | int __devinit tah_attach(struct platform_device *ofdev, int channel) |
27 | { | 27 | { |
28 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 28 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
29 | 29 | ||
@@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel) | |||
35 | return 0; | 35 | return 0; |
36 | } | 36 | } |
37 | 37 | ||
38 | void tah_detach(struct of_device *ofdev, int channel) | 38 | void tah_detach(struct platform_device *ofdev, int channel) |
39 | { | 39 | { |
40 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 40 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
41 | 41 | ||
@@ -44,7 +44,7 @@ void tah_detach(struct of_device *ofdev, int channel) | |||
44 | mutex_unlock(&dev->lock); | 44 | mutex_unlock(&dev->lock); |
45 | } | 45 | } |
46 | 46 | ||
47 | void tah_reset(struct of_device *ofdev) | 47 | void tah_reset(struct platform_device *ofdev) |
48 | { | 48 | { |
49 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 49 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
50 | struct tah_regs __iomem *p = dev->base; | 50 | struct tah_regs __iomem *p = dev->base; |
@@ -66,13 +66,13 @@ void tah_reset(struct of_device *ofdev) | |||
66 | TAH_MR_DIG); | 66 | TAH_MR_DIG); |
67 | } | 67 | } |
68 | 68 | ||
69 | int tah_get_regs_len(struct of_device *ofdev) | 69 | int tah_get_regs_len(struct platform_device *ofdev) |
70 | { | 70 | { |
71 | return sizeof(struct emac_ethtool_regs_subhdr) + | 71 | return sizeof(struct emac_ethtool_regs_subhdr) + |
72 | sizeof(struct tah_regs); | 72 | sizeof(struct tah_regs); |
73 | } | 73 | } |
74 | 74 | ||
75 | void *tah_dump_regs(struct of_device *ofdev, void *buf) | 75 | void *tah_dump_regs(struct platform_device *ofdev, void *buf) |
76 | { | 76 | { |
77 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 77 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
78 | struct emac_ethtool_regs_subhdr *hdr = buf; | 78 | struct emac_ethtool_regs_subhdr *hdr = buf; |
@@ -87,7 +87,7 @@ void *tah_dump_regs(struct of_device *ofdev, void *buf) | |||
87 | return regs + 1; | 87 | return regs + 1; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int __devinit tah_probe(struct of_device *ofdev, | 90 | static int __devinit tah_probe(struct platform_device *ofdev, |
91 | const struct of_device_id *match) | 91 | const struct of_device_id *match) |
92 | { | 92 | { |
93 | struct device_node *np = ofdev->dev.of_node; | 93 | struct device_node *np = ofdev->dev.of_node; |
@@ -139,7 +139,7 @@ static int __devinit tah_probe(struct of_device *ofdev, | |||
139 | return rc; | 139 | return rc; |
140 | } | 140 | } |
141 | 141 | ||
142 | static int __devexit tah_remove(struct of_device *ofdev) | 142 | static int __devexit tah_remove(struct platform_device *ofdev) |
143 | { | 143 | { |
144 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 144 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
145 | 145 | ||
diff --git a/drivers/net/ibm_newemac/tah.h b/drivers/net/ibm_newemac/tah.h index a068b5658dad..61dbeca006d1 100644 --- a/drivers/net/ibm_newemac/tah.h +++ b/drivers/net/ibm_newemac/tah.h | |||
@@ -48,7 +48,7 @@ struct tah_instance { | |||
48 | int users; | 48 | int users; |
49 | 49 | ||
50 | /* OF device instance */ | 50 | /* OF device instance */ |
51 | struct of_device *ofdev; | 51 | struct platform_device *ofdev; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | 54 | ||
@@ -74,11 +74,11 @@ struct tah_instance { | |||
74 | 74 | ||
75 | extern int tah_init(void); | 75 | extern int tah_init(void); |
76 | extern void tah_exit(void); | 76 | extern void tah_exit(void); |
77 | extern int tah_attach(struct of_device *ofdev, int channel); | 77 | extern int tah_attach(struct platform_device *ofdev, int channel); |
78 | extern void tah_detach(struct of_device *ofdev, int channel); | 78 | extern void tah_detach(struct platform_device *ofdev, int channel); |
79 | extern void tah_reset(struct of_device *ofdev); | 79 | extern void tah_reset(struct platform_device *ofdev); |
80 | extern int tah_get_regs_len(struct of_device *ofdev); | 80 | extern int tah_get_regs_len(struct platform_device *ofdev); |
81 | extern void *tah_dump_regs(struct of_device *ofdev, void *buf); | 81 | extern void *tah_dump_regs(struct platform_device *ofdev, void *buf); |
82 | 82 | ||
83 | #else | 83 | #else |
84 | 84 | ||
diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c index 046dcd069c45..34ed6ee8ca8a 100644 --- a/drivers/net/ibm_newemac/zmii.c +++ b/drivers/net/ibm_newemac/zmii.c | |||
@@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input) | |||
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) | 85 | int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode) |
86 | { | 86 | { |
87 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 87 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
88 | struct zmii_regs __iomem *p = dev->base; | 88 | struct zmii_regs __iomem *p = dev->base; |
@@ -148,7 +148,7 @@ int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) | |||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | void zmii_get_mdio(struct of_device *ofdev, int input) | 151 | void zmii_get_mdio(struct platform_device *ofdev, int input) |
152 | { | 152 | { |
153 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 153 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
154 | u32 fer; | 154 | u32 fer; |
@@ -161,7 +161,7 @@ void zmii_get_mdio(struct of_device *ofdev, int input) | |||
161 | out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input)); | 161 | out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input)); |
162 | } | 162 | } |
163 | 163 | ||
164 | void zmii_put_mdio(struct of_device *ofdev, int input) | 164 | void zmii_put_mdio(struct platform_device *ofdev, int input) |
165 | { | 165 | { |
166 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 166 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
167 | 167 | ||
@@ -170,7 +170,7 @@ void zmii_put_mdio(struct of_device *ofdev, int input) | |||
170 | } | 170 | } |
171 | 171 | ||
172 | 172 | ||
173 | void zmii_set_speed(struct of_device *ofdev, int input, int speed) | 173 | void zmii_set_speed(struct platform_device *ofdev, int input, int speed) |
174 | { | 174 | { |
175 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 175 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
176 | u32 ssr; | 176 | u32 ssr; |
@@ -191,7 +191,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed) | |||
191 | mutex_unlock(&dev->lock); | 191 | mutex_unlock(&dev->lock); |
192 | } | 192 | } |
193 | 193 | ||
194 | void zmii_detach(struct of_device *ofdev, int input) | 194 | void zmii_detach(struct platform_device *ofdev, int input) |
195 | { | 195 | { |
196 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 196 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
197 | 197 | ||
@@ -210,13 +210,13 @@ void zmii_detach(struct of_device *ofdev, int input) | |||
210 | mutex_unlock(&dev->lock); | 210 | mutex_unlock(&dev->lock); |
211 | } | 211 | } |
212 | 212 | ||
213 | int zmii_get_regs_len(struct of_device *ofdev) | 213 | int zmii_get_regs_len(struct platform_device *ofdev) |
214 | { | 214 | { |
215 | return sizeof(struct emac_ethtool_regs_subhdr) + | 215 | return sizeof(struct emac_ethtool_regs_subhdr) + |
216 | sizeof(struct zmii_regs); | 216 | sizeof(struct zmii_regs); |
217 | } | 217 | } |
218 | 218 | ||
219 | void *zmii_dump_regs(struct of_device *ofdev, void *buf) | 219 | void *zmii_dump_regs(struct platform_device *ofdev, void *buf) |
220 | { | 220 | { |
221 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 221 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
222 | struct emac_ethtool_regs_subhdr *hdr = buf; | 222 | struct emac_ethtool_regs_subhdr *hdr = buf; |
@@ -231,7 +231,7 @@ void *zmii_dump_regs(struct of_device *ofdev, void *buf) | |||
231 | return regs + 1; | 231 | return regs + 1; |
232 | } | 232 | } |
233 | 233 | ||
234 | static int __devinit zmii_probe(struct of_device *ofdev, | 234 | static int __devinit zmii_probe(struct platform_device *ofdev, |
235 | const struct of_device_id *match) | 235 | const struct of_device_id *match) |
236 | { | 236 | { |
237 | struct device_node *np = ofdev->dev.of_node; | 237 | struct device_node *np = ofdev->dev.of_node; |
@@ -286,7 +286,7 @@ static int __devinit zmii_probe(struct of_device *ofdev, | |||
286 | return rc; | 286 | return rc; |
287 | } | 287 | } |
288 | 288 | ||
289 | static int __devexit zmii_remove(struct of_device *ofdev) | 289 | static int __devexit zmii_remove(struct platform_device *ofdev) |
290 | { | 290 | { |
291 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 291 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
292 | 292 | ||
diff --git a/drivers/net/ibm_newemac/zmii.h b/drivers/net/ibm_newemac/zmii.h index 6c9beba0c4b6..1333fa2b2781 100644 --- a/drivers/net/ibm_newemac/zmii.h +++ b/drivers/net/ibm_newemac/zmii.h | |||
@@ -48,20 +48,20 @@ struct zmii_instance { | |||
48 | u32 fer_save; | 48 | u32 fer_save; |
49 | 49 | ||
50 | /* OF device instance */ | 50 | /* OF device instance */ |
51 | struct of_device *ofdev; | 51 | struct platform_device *ofdev; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | #ifdef CONFIG_IBM_NEW_EMAC_ZMII | 54 | #ifdef CONFIG_IBM_NEW_EMAC_ZMII |
55 | 55 | ||
56 | extern int zmii_init(void); | 56 | extern int zmii_init(void); |
57 | extern void zmii_exit(void); | 57 | extern void zmii_exit(void); |
58 | extern int zmii_attach(struct of_device *ofdev, int input, int *mode); | 58 | extern int zmii_attach(struct platform_device *ofdev, int input, int *mode); |
59 | extern void zmii_detach(struct of_device *ofdev, int input); | 59 | extern void zmii_detach(struct platform_device *ofdev, int input); |
60 | extern void zmii_get_mdio(struct of_device *ofdev, int input); | 60 | extern void zmii_get_mdio(struct platform_device *ofdev, int input); |
61 | extern void zmii_put_mdio(struct of_device *ofdev, int input); | 61 | extern void zmii_put_mdio(struct platform_device *ofdev, int input); |
62 | extern void zmii_set_speed(struct of_device *ofdev, int input, int speed); | 62 | extern void zmii_set_speed(struct platform_device *ofdev, int input, int speed); |
63 | extern int zmii_get_regs_len(struct of_device *ocpdev); | 63 | extern int zmii_get_regs_len(struct platform_device *ocpdev); |
64 | extern void *zmii_dump_regs(struct of_device *ofdev, void *buf); | 64 | extern void *zmii_dump_regs(struct platform_device *ofdev, void *buf); |
65 | 65 | ||
66 | #else | 66 | #else |
67 | # define zmii_init() 0 | 67 | # define zmii_init() 0 |
diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c index edd5666f0ffb..9e3f4f54281d 100644 --- a/drivers/net/irda/sh_irda.c +++ b/drivers/net/irda/sh_irda.c | |||
@@ -748,7 +748,6 @@ static int __devinit sh_irda_probe(struct platform_device *pdev) | |||
748 | struct net_device *ndev; | 748 | struct net_device *ndev; |
749 | struct sh_irda_self *self; | 749 | struct sh_irda_self *self; |
750 | struct resource *res; | 750 | struct resource *res; |
751 | char clk_name[8]; | ||
752 | int irq; | 751 | int irq; |
753 | int err = -ENOMEM; | 752 | int err = -ENOMEM; |
754 | 753 | ||
@@ -775,10 +774,9 @@ static int __devinit sh_irda_probe(struct platform_device *pdev) | |||
775 | if (err) | 774 | if (err) |
776 | goto err_mem_2; | 775 | goto err_mem_2; |
777 | 776 | ||
778 | snprintf(clk_name, sizeof(clk_name), "irda%d", pdev->id); | 777 | self->clk = clk_get(&pdev->dev, NULL); |
779 | self->clk = clk_get(&pdev->dev, clk_name); | ||
780 | if (IS_ERR(self->clk)) { | 778 | if (IS_ERR(self->clk)) { |
781 | dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); | 779 | dev_err(&pdev->dev, "cannot get irda clock\n"); |
782 | goto err_mem_3; | 780 | goto err_mem_3; |
783 | } | 781 | } |
784 | 782 | ||
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 4eea3f70c5cf..c7b624711f5e 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c | |||
@@ -159,7 +159,7 @@ static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value) | |||
159 | * temac_dcr_setup - If the DMA is DCR based, then setup the address and | 159 | * temac_dcr_setup - If the DMA is DCR based, then setup the address and |
160 | * I/O functions | 160 | * I/O functions |
161 | */ | 161 | */ |
162 | static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, | 162 | static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, |
163 | struct device_node *np) | 163 | struct device_node *np) |
164 | { | 164 | { |
165 | unsigned int dcrs; | 165 | unsigned int dcrs; |
@@ -184,7 +184,7 @@ static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, | |||
184 | * temac_dcr_setup - This is a stub for when DCR is not supported, | 184 | * temac_dcr_setup - This is a stub for when DCR is not supported, |
185 | * such as with MicroBlaze | 185 | * such as with MicroBlaze |
186 | */ | 186 | */ |
187 | static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, | 187 | static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, |
188 | struct device_node *np) | 188 | struct device_node *np) |
189 | { | 189 | { |
190 | return -1; | 190 | return -1; |
@@ -952,7 +952,7 @@ static const struct attribute_group temac_attr_group = { | |||
952 | }; | 952 | }; |
953 | 953 | ||
954 | static int __init | 954 | static int __init |
955 | temac_of_probe(struct of_device *op, const struct of_device_id *match) | 955 | temac_of_probe(struct platform_device *op, const struct of_device_id *match) |
956 | { | 956 | { |
957 | struct device_node *np; | 957 | struct device_node *np; |
958 | struct temac_local *lp; | 958 | struct temac_local *lp; |
@@ -1094,7 +1094,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1094 | return rc; | 1094 | return rc; |
1095 | } | 1095 | } |
1096 | 1096 | ||
1097 | static int __devexit temac_of_remove(struct of_device *op) | 1097 | static int __devexit temac_of_remove(struct platform_device *op) |
1098 | { | 1098 | { |
1099 | struct net_device *ndev = dev_get_drvdata(&op->dev); | 1099 | struct net_device *ndev = dev_get_drvdata(&op->dev); |
1100 | struct temac_local *lp = netdev_priv(ndev); | 1100 | struct temac_local *lp = netdev_priv(ndev); |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index d771d1650d60..fb2c0927d3cc 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -239,6 +239,7 @@ struct myri10ge_priv { | |||
239 | int watchdog_resets; | 239 | int watchdog_resets; |
240 | int watchdog_pause; | 240 | int watchdog_pause; |
241 | int pause; | 241 | int pause; |
242 | bool fw_name_allocated; | ||
242 | char *fw_name; | 243 | char *fw_name; |
243 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; | 244 | char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; |
244 | char *product_code_string; | 245 | char *product_code_string; |
@@ -271,6 +272,7 @@ MODULE_FIRMWARE("myri10ge_eth_z8e.dat"); | |||
271 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); | 272 | MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); |
272 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); | 273 | MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); |
273 | 274 | ||
275 | /* Careful: must be accessed under kparam_block_sysfs_write */ | ||
274 | static char *myri10ge_fw_name = NULL; | 276 | static char *myri10ge_fw_name = NULL; |
275 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); | 277 | module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); |
276 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); | 278 | MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); |
@@ -376,6 +378,14 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) | |||
376 | 378 | ||
377 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); | 379 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); |
378 | 380 | ||
381 | static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated) | ||
382 | { | ||
383 | if (mgp->fw_name_allocated) | ||
384 | kfree(mgp->fw_name); | ||
385 | mgp->fw_name = name; | ||
386 | mgp->fw_name_allocated = allocated; | ||
387 | } | ||
388 | |||
379 | static int | 389 | static int |
380 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, | 390 | myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, |
381 | struct myri10ge_cmd *data, int atomic) | 391 | struct myri10ge_cmd *data, int atomic) |
@@ -747,7 +757,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt) | |||
747 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); | 757 | dev_warn(&mgp->pdev->dev, "via hotplug\n"); |
748 | } | 758 | } |
749 | 759 | ||
750 | mgp->fw_name = "adopted"; | 760 | set_fw_name(mgp, "adopted", false); |
751 | mgp->tx_boundary = 2048; | 761 | mgp->tx_boundary = 2048; |
752 | myri10ge_dummy_rdma(mgp, 1); | 762 | myri10ge_dummy_rdma(mgp, 1); |
753 | status = myri10ge_get_firmware_capabilities(mgp); | 763 | status = myri10ge_get_firmware_capabilities(mgp); |
@@ -3233,7 +3243,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
3233 | * load the optimized firmware (which assumes aligned PCIe | 3243 | * load the optimized firmware (which assumes aligned PCIe |
3234 | * completions) in order to see if it works on this host. | 3244 | * completions) in order to see if it works on this host. |
3235 | */ | 3245 | */ |
3236 | mgp->fw_name = myri10ge_fw_aligned; | 3246 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3237 | status = myri10ge_load_firmware(mgp, 1); | 3247 | status = myri10ge_load_firmware(mgp, 1); |
3238 | if (status != 0) { | 3248 | if (status != 0) { |
3239 | goto abort; | 3249 | goto abort; |
@@ -3261,7 +3271,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) | |||
3261 | abort: | 3271 | abort: |
3262 | /* fall back to using the unaligned firmware */ | 3272 | /* fall back to using the unaligned firmware */ |
3263 | mgp->tx_boundary = 2048; | 3273 | mgp->tx_boundary = 2048; |
3264 | mgp->fw_name = myri10ge_fw_unaligned; | 3274 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
3265 | 3275 | ||
3266 | } | 3276 | } |
3267 | 3277 | ||
@@ -3284,7 +3294,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3284 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", | 3294 | dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", |
3285 | link_width); | 3295 | link_width); |
3286 | mgp->tx_boundary = 4096; | 3296 | mgp->tx_boundary = 4096; |
3287 | mgp->fw_name = myri10ge_fw_aligned; | 3297 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3288 | } else { | 3298 | } else { |
3289 | myri10ge_firmware_probe(mgp); | 3299 | myri10ge_firmware_probe(mgp); |
3290 | } | 3300 | } |
@@ -3293,22 +3303,29 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3293 | dev_info(&mgp->pdev->dev, | 3303 | dev_info(&mgp->pdev->dev, |
3294 | "Assuming aligned completions (forced)\n"); | 3304 | "Assuming aligned completions (forced)\n"); |
3295 | mgp->tx_boundary = 4096; | 3305 | mgp->tx_boundary = 4096; |
3296 | mgp->fw_name = myri10ge_fw_aligned; | 3306 | set_fw_name(mgp, myri10ge_fw_aligned, false); |
3297 | } else { | 3307 | } else { |
3298 | dev_info(&mgp->pdev->dev, | 3308 | dev_info(&mgp->pdev->dev, |
3299 | "Assuming unaligned completions (forced)\n"); | 3309 | "Assuming unaligned completions (forced)\n"); |
3300 | mgp->tx_boundary = 2048; | 3310 | mgp->tx_boundary = 2048; |
3301 | mgp->fw_name = myri10ge_fw_unaligned; | 3311 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
3302 | } | 3312 | } |
3303 | } | 3313 | } |
3314 | |||
3315 | kparam_block_sysfs_write(myri10ge_fw_name); | ||
3304 | if (myri10ge_fw_name != NULL) { | 3316 | if (myri10ge_fw_name != NULL) { |
3305 | overridden = 1; | 3317 | char *fw_name = kstrdup(myri10ge_fw_name, GFP_KERNEL); |
3306 | mgp->fw_name = myri10ge_fw_name; | 3318 | if (fw_name) { |
3319 | overridden = 1; | ||
3320 | set_fw_name(mgp, fw_name, true); | ||
3321 | } | ||
3307 | } | 3322 | } |
3323 | kparam_unblock_sysfs_write(myri10ge_fw_name); | ||
3324 | |||
3308 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && | 3325 | if (mgp->board_number < MYRI10GE_MAX_BOARDS && |
3309 | myri10ge_fw_names[mgp->board_number] != NULL && | 3326 | myri10ge_fw_names[mgp->board_number] != NULL && |
3310 | strlen(myri10ge_fw_names[mgp->board_number])) { | 3327 | strlen(myri10ge_fw_names[mgp->board_number])) { |
3311 | mgp->fw_name = myri10ge_fw_names[mgp->board_number]; | 3328 | set_fw_name(mgp, myri10ge_fw_names[mgp->board_number], false); |
3312 | overridden = 1; | 3329 | overridden = 1; |
3313 | } | 3330 | } |
3314 | if (overridden) | 3331 | if (overridden) |
@@ -3660,6 +3677,7 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3660 | struct myri10ge_cmd cmd; | 3677 | struct myri10ge_cmd cmd; |
3661 | struct pci_dev *pdev = mgp->pdev; | 3678 | struct pci_dev *pdev = mgp->pdev; |
3662 | char *old_fw; | 3679 | char *old_fw; |
3680 | bool old_allocated; | ||
3663 | int i, status, ncpus, msix_cap; | 3681 | int i, status, ncpus, msix_cap; |
3664 | 3682 | ||
3665 | mgp->num_slices = 1; | 3683 | mgp->num_slices = 1; |
@@ -3672,17 +3690,23 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3672 | 3690 | ||
3673 | /* try to load the slice aware rss firmware */ | 3691 | /* try to load the slice aware rss firmware */ |
3674 | old_fw = mgp->fw_name; | 3692 | old_fw = mgp->fw_name; |
3693 | old_allocated = mgp->fw_name_allocated; | ||
3694 | /* don't free old_fw if we override it. */ | ||
3695 | mgp->fw_name_allocated = false; | ||
3696 | |||
3675 | if (myri10ge_fw_name != NULL) { | 3697 | if (myri10ge_fw_name != NULL) { |
3676 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", | 3698 | dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", |
3677 | myri10ge_fw_name); | 3699 | myri10ge_fw_name); |
3678 | mgp->fw_name = myri10ge_fw_name; | 3700 | set_fw_name(mgp, myri10ge_fw_name, false); |
3679 | } else if (old_fw == myri10ge_fw_aligned) | 3701 | } else if (old_fw == myri10ge_fw_aligned) |
3680 | mgp->fw_name = myri10ge_fw_rss_aligned; | 3702 | set_fw_name(mgp, myri10ge_fw_rss_aligned, false); |
3681 | else | 3703 | else |
3682 | mgp->fw_name = myri10ge_fw_rss_unaligned; | 3704 | set_fw_name(mgp, myri10ge_fw_rss_unaligned, false); |
3683 | status = myri10ge_load_firmware(mgp, 0); | 3705 | status = myri10ge_load_firmware(mgp, 0); |
3684 | if (status != 0) { | 3706 | if (status != 0) { |
3685 | dev_info(&pdev->dev, "Rss firmware not found\n"); | 3707 | dev_info(&pdev->dev, "Rss firmware not found\n"); |
3708 | if (old_allocated) | ||
3709 | kfree(old_fw); | ||
3686 | return; | 3710 | return; |
3687 | } | 3711 | } |
3688 | 3712 | ||
@@ -3747,6 +3771,8 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) | |||
3747 | mgp->num_slices); | 3771 | mgp->num_slices); |
3748 | if (status == 0) { | 3772 | if (status == 0) { |
3749 | pci_disable_msix(pdev); | 3773 | pci_disable_msix(pdev); |
3774 | if (old_allocated) | ||
3775 | kfree(old_fw); | ||
3750 | return; | 3776 | return; |
3751 | } | 3777 | } |
3752 | if (status > 0) | 3778 | if (status > 0) |
@@ -3763,7 +3789,7 @@ disable_msix: | |||
3763 | 3789 | ||
3764 | abort_with_fw: | 3790 | abort_with_fw: |
3765 | mgp->num_slices = 1; | 3791 | mgp->num_slices = 1; |
3766 | mgp->fw_name = old_fw; | 3792 | set_fw_name(mgp, old_fw, old_allocated); |
3767 | myri10ge_load_firmware(mgp, 0); | 3793 | myri10ge_load_firmware(mgp, 0); |
3768 | } | 3794 | } |
3769 | 3795 | ||
@@ -3993,6 +4019,7 @@ abort_with_enabled: | |||
3993 | pci_disable_device(pdev); | 4019 | pci_disable_device(pdev); |
3994 | 4020 | ||
3995 | abort_with_netdev: | 4021 | abort_with_netdev: |
4022 | set_fw_name(mgp, NULL, false); | ||
3996 | free_netdev(netdev); | 4023 | free_netdev(netdev); |
3997 | return status; | 4024 | return status; |
3998 | } | 4025 | } |
@@ -4037,6 +4064,7 @@ static void myri10ge_remove(struct pci_dev *pdev) | |||
4037 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), | 4064 | dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), |
4038 | mgp->cmd, mgp->cmd_bus); | 4065 | mgp->cmd, mgp->cmd_bus); |
4039 | 4066 | ||
4067 | set_fw_name(mgp, NULL, false); | ||
4040 | free_netdev(netdev); | 4068 | free_netdev(netdev); |
4041 | pci_disable_device(pdev); | 4069 | pci_disable_device(pdev); |
4042 | pci_set_drvdata(pdev, NULL); | 4070 | pci_set_drvdata(pdev, NULL); |
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 04e552aa14ec..617f898ba5f0 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c | |||
@@ -926,7 +926,7 @@ static const struct net_device_ops myri_ops = { | |||
926 | .ndo_validate_addr = eth_validate_addr, | 926 | .ndo_validate_addr = eth_validate_addr, |
927 | }; | 927 | }; |
928 | 928 | ||
929 | static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) | 929 | static int __devinit myri_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
930 | { | 930 | { |
931 | struct device_node *dp = op->dev.of_node; | 931 | struct device_node *dp = op->dev.of_node; |
932 | static unsigned version_printed; | 932 | static unsigned version_printed; |
@@ -1124,7 +1124,7 @@ err: | |||
1124 | return -ENODEV; | 1124 | return -ENODEV; |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | static int __devexit myri_sbus_remove(struct of_device *op) | 1127 | static int __devexit myri_sbus_remove(struct platform_device *op) |
1128 | { | 1128 | { |
1129 | struct myri_eth *mp = dev_get_drvdata(&op->dev); | 1129 | struct myri_eth *mp = dev_get_drvdata(&op->dev); |
1130 | struct net_device *net_dev = mp->dev; | 1130 | struct net_device *net_dev = mp->dev; |
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index ff363e95d9cf..80a2fa5cf757 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h | |||
@@ -288,7 +288,7 @@ struct myri_eth { | |||
288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ | 288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ |
289 | unsigned int reg_size; /* Size of register space. */ | 289 | unsigned int reg_size; /* Size of register space. */ |
290 | unsigned int shmem_base; /* Offset to shared ram. */ | 290 | unsigned int shmem_base; /* Offset to shared ram. */ |
291 | struct of_device *myri_op; /* Our OF device struct. */ | 291 | struct platform_device *myri_op; /* Our OF device struct. */ |
292 | }; | 292 | }; |
293 | 293 | ||
294 | /* We use this to acquire receive skb's that we can DMA directly into. */ | 294 | /* We use this to acquire receive skb's that we can DMA directly into. */ |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 404f2d552888..bc695d53cdcc 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
@@ -9103,7 +9103,7 @@ retry: | |||
9103 | static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) | 9103 | static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) |
9104 | { | 9104 | { |
9105 | #ifdef CONFIG_SPARC64 | 9105 | #ifdef CONFIG_SPARC64 |
9106 | struct of_device *op = np->op; | 9106 | struct platform_device *op = np->op; |
9107 | const u32 *int_prop; | 9107 | const u32 *int_prop; |
9108 | int i; | 9108 | int i; |
9109 | 9109 | ||
@@ -9688,7 +9688,7 @@ static void __devinit niu_driver_version(void) | |||
9688 | 9688 | ||
9689 | static struct net_device * __devinit niu_alloc_and_init( | 9689 | static struct net_device * __devinit niu_alloc_and_init( |
9690 | struct device *gen_dev, struct pci_dev *pdev, | 9690 | struct device *gen_dev, struct pci_dev *pdev, |
9691 | struct of_device *op, const struct niu_ops *ops, | 9691 | struct platform_device *op, const struct niu_ops *ops, |
9692 | u8 port) | 9692 | u8 port) |
9693 | { | 9693 | { |
9694 | struct net_device *dev; | 9694 | struct net_device *dev; |
@@ -10064,7 +10064,7 @@ static const struct niu_ops niu_phys_ops = { | |||
10064 | .unmap_single = niu_phys_unmap_single, | 10064 | .unmap_single = niu_phys_unmap_single, |
10065 | }; | 10065 | }; |
10066 | 10066 | ||
10067 | static int __devinit niu_of_probe(struct of_device *op, | 10067 | static int __devinit niu_of_probe(struct platform_device *op, |
10068 | const struct of_device_id *match) | 10068 | const struct of_device_id *match) |
10069 | { | 10069 | { |
10070 | union niu_parent_id parent_id; | 10070 | union niu_parent_id parent_id; |
@@ -10179,7 +10179,7 @@ err_out: | |||
10179 | return err; | 10179 | return err; |
10180 | } | 10180 | } |
10181 | 10181 | ||
10182 | static int __devexit niu_of_remove(struct of_device *op) | 10182 | static int __devexit niu_of_remove(struct platform_device *op) |
10183 | { | 10183 | { |
10184 | struct net_device *dev = dev_get_drvdata(&op->dev); | 10184 | struct net_device *dev = dev_get_drvdata(&op->dev); |
10185 | 10185 | ||
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index a527e37728cd..eb799b36c86a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
@@ -5,7 +5,7 @@ | |||
5 | menuconfig PHYLIB | 5 | menuconfig PHYLIB |
6 | tristate "PHY Device support and infrastructure" | 6 | tristate "PHY Device support and infrastructure" |
7 | depends on !S390 | 7 | depends on !S390 |
8 | depends on NET_ETHERNET | 8 | depends on NETDEVICES |
9 | help | 9 | help |
10 | Ethernet controllers are usually attached to PHY | 10 | Ethernet controllers are usually attached to PHY |
11 | devices. This option provides infrastructure for | 11 | devices. This option provides infrastructure for |
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index fc5fef2a8175..f62c7b717bc8 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c | |||
@@ -188,7 +188,7 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev) | |||
188 | 188 | ||
189 | #ifdef CONFIG_OF_GPIO | 189 | #ifdef CONFIG_OF_GPIO |
190 | 190 | ||
191 | static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, | 191 | static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev, |
192 | const struct of_device_id *match) | 192 | const struct of_device_id *match) |
193 | { | 193 | { |
194 | struct mdio_gpio_platform_data *pdata; | 194 | struct mdio_gpio_platform_data *pdata; |
@@ -224,7 +224,7 @@ out_free: | |||
224 | return -ENODEV; | 224 | return -ENODEV; |
225 | } | 225 | } |
226 | 226 | ||
227 | static int __devexit mdio_ofgpio_remove(struct of_device *ofdev) | 227 | static int __devexit mdio_ofgpio_remove(struct platform_device *ofdev) |
228 | { | 228 | { |
229 | mdio_gpio_bus_destroy(&ofdev->dev); | 229 | mdio_gpio_bus_destroy(&ofdev->dev); |
230 | kfree(ofdev->dev.platform_data); | 230 | kfree(ofdev->dev.platform_data); |
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 5130db8f5c4e..1bb16cb79433 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
@@ -301,7 +301,7 @@ EXPORT_SYMBOL(phy_ethtool_gset); | |||
301 | /** | 301 | /** |
302 | * phy_mii_ioctl - generic PHY MII ioctl interface | 302 | * phy_mii_ioctl - generic PHY MII ioctl interface |
303 | * @phydev: the phy_device struct | 303 | * @phydev: the phy_device struct |
304 | * @mii_data: MII ioctl data | 304 | * @ifr: &struct ifreq for socket ioctl's |
305 | * @cmd: ioctl cmd to execute | 305 | * @cmd: ioctl cmd to execute |
306 | * | 306 | * |
307 | * Note that this function is currently incompatible with the | 307 | * Note that this function is currently incompatible with the |
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index b9615bd745ea..bf6d87adda4f 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c | |||
@@ -473,48 +473,58 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) | |||
473 | static int | 473 | static int |
474 | qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | 474 | qlcnic_init_pci_info(struct qlcnic_adapter *adapter) |
475 | { | 475 | { |
476 | struct qlcnic_pci_info pci_info[QLCNIC_MAX_PCI_FUNC]; | 476 | struct qlcnic_pci_info *pci_info; |
477 | int i, ret = 0, err; | 477 | int i, ret = 0, err; |
478 | u8 pfn; | 478 | u8 pfn; |
479 | 479 | ||
480 | if (!adapter->npars) | 480 | pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); |
481 | adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * | 481 | if (!pci_info) |
482 | QLCNIC_MAX_PCI_FUNC, GFP_KERNEL); | ||
483 | if (!adapter->npars) | ||
484 | return -ENOMEM; | 482 | return -ENOMEM; |
485 | 483 | ||
486 | if (!adapter->eswitch) | 484 | adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * |
487 | adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) * | 485 | QLCNIC_MAX_PCI_FUNC, GFP_KERNEL); |
486 | if (!adapter->npars) { | ||
487 | err = -ENOMEM; | ||
488 | goto err_pci_info; | ||
489 | } | ||
490 | |||
491 | adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) * | ||
488 | QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL); | 492 | QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL); |
489 | if (!adapter->eswitch) { | 493 | if (!adapter->eswitch) { |
490 | err = -ENOMEM; | 494 | err = -ENOMEM; |
491 | goto err_eswitch; | 495 | goto err_npars; |
492 | } | 496 | } |
493 | 497 | ||
494 | ret = qlcnic_get_pci_info(adapter, pci_info); | 498 | ret = qlcnic_get_pci_info(adapter, pci_info); |
495 | if (!ret) { | 499 | if (ret) |
496 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 500 | goto err_eswitch; |
497 | pfn = pci_info[i].id; | ||
498 | if (pfn > QLCNIC_MAX_PCI_FUNC) | ||
499 | return QL_STATUS_INVALID_PARAM; | ||
500 | adapter->npars[pfn].active = pci_info[i].active; | ||
501 | adapter->npars[pfn].type = pci_info[i].type; | ||
502 | adapter->npars[pfn].phy_port = pci_info[i].default_port; | ||
503 | adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN; | ||
504 | adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw; | ||
505 | adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw; | ||
506 | } | ||
507 | |||
508 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) | ||
509 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; | ||
510 | 501 | ||
511 | return ret; | 502 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
503 | pfn = pci_info[i].id; | ||
504 | if (pfn > QLCNIC_MAX_PCI_FUNC) | ||
505 | return QL_STATUS_INVALID_PARAM; | ||
506 | adapter->npars[pfn].active = pci_info[i].active; | ||
507 | adapter->npars[pfn].type = pci_info[i].type; | ||
508 | adapter->npars[pfn].phy_port = pci_info[i].default_port; | ||
509 | adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN; | ||
510 | adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw; | ||
511 | adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw; | ||
512 | } | 512 | } |
513 | 513 | ||
514 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) | ||
515 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; | ||
516 | |||
517 | kfree(pci_info); | ||
518 | return 0; | ||
519 | |||
520 | err_eswitch: | ||
514 | kfree(adapter->eswitch); | 521 | kfree(adapter->eswitch); |
515 | adapter->eswitch = NULL; | 522 | adapter->eswitch = NULL; |
516 | err_eswitch: | 523 | err_npars: |
517 | kfree(adapter->npars); | 524 | kfree(adapter->npars); |
525 | adapter->npars = NULL; | ||
526 | err_pci_info: | ||
527 | kfree(pci_info); | ||
518 | 528 | ||
519 | return ret; | 529 | return ret; |
520 | } | 530 | } |
@@ -3361,15 +3371,21 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj, | |||
3361 | struct device *dev = container_of(kobj, struct device, kobj); | 3371 | struct device *dev = container_of(kobj, struct device, kobj); |
3362 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 3372 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
3363 | struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC]; | 3373 | struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC]; |
3364 | struct qlcnic_pci_info pci_info[QLCNIC_MAX_PCI_FUNC]; | 3374 | struct qlcnic_pci_info *pci_info; |
3365 | int i, ret; | 3375 | int i, ret; |
3366 | 3376 | ||
3367 | if (size != sizeof(pci_cfg)) | 3377 | if (size != sizeof(pci_cfg)) |
3368 | return QL_STATUS_INVALID_PARAM; | 3378 | return QL_STATUS_INVALID_PARAM; |
3369 | 3379 | ||
3380 | pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); | ||
3381 | if (!pci_info) | ||
3382 | return -ENOMEM; | ||
3383 | |||
3370 | ret = qlcnic_get_pci_info(adapter, pci_info); | 3384 | ret = qlcnic_get_pci_info(adapter, pci_info); |
3371 | if (ret) | 3385 | if (ret) { |
3386 | kfree(pci_info); | ||
3372 | return ret; | 3387 | return ret; |
3388 | } | ||
3373 | 3389 | ||
3374 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { | 3390 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { |
3375 | pci_cfg[i].pci_func = pci_info[i].id; | 3391 | pci_cfg[i].pci_func = pci_info[i].id; |
@@ -3380,8 +3396,8 @@ qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj, | |||
3380 | memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); | 3396 | memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); |
3381 | } | 3397 | } |
3382 | memcpy(buf, &pci_cfg, size); | 3398 | memcpy(buf, &pci_cfg, size); |
3399 | kfree(pci_info); | ||
3383 | return size; | 3400 | return size; |
3384 | |||
3385 | } | 3401 | } |
3386 | static struct bin_attribute bin_attr_npar_config = { | 3402 | static struct bin_attribute bin_attr_npar_config = { |
3387 | .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)}, | 3403 | .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)}, |
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 09c071bd6ad4..618643e3ca3e 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c | |||
@@ -97,7 +97,7 @@ static int qec_global_reset(void __iomem *gregs) | |||
97 | 97 | ||
98 | static void qec_init(struct bigmac *bp) | 98 | static void qec_init(struct bigmac *bp) |
99 | { | 99 | { |
100 | struct of_device *qec_op = bp->qec_op; | 100 | struct platform_device *qec_op = bp->qec_op; |
101 | void __iomem *gregs = bp->gregs; | 101 | void __iomem *gregs = bp->gregs; |
102 | u8 bsizes = bp->bigmac_bursts; | 102 | u8 bsizes = bp->bigmac_bursts; |
103 | u32 regval; | 103 | u32 regval; |
@@ -1083,8 +1083,8 @@ static const struct net_device_ops bigmac_ops = { | |||
1083 | .ndo_validate_addr = eth_validate_addr, | 1083 | .ndo_validate_addr = eth_validate_addr, |
1084 | }; | 1084 | }; |
1085 | 1085 | ||
1086 | static int __devinit bigmac_ether_init(struct of_device *op, | 1086 | static int __devinit bigmac_ether_init(struct platform_device *op, |
1087 | struct of_device *qec_op) | 1087 | struct platform_device *qec_op) |
1088 | { | 1088 | { |
1089 | static int version_printed; | 1089 | static int version_printed; |
1090 | struct net_device *dev; | 1090 | struct net_device *dev; |
@@ -1242,25 +1242,25 @@ fail_and_cleanup: | |||
1242 | /* QEC can be the parent of either QuadEthernet or a BigMAC. We want | 1242 | /* QEC can be the parent of either QuadEthernet or a BigMAC. We want |
1243 | * the latter. | 1243 | * the latter. |
1244 | */ | 1244 | */ |
1245 | static int __devinit bigmac_sbus_probe(struct of_device *op, | 1245 | static int __devinit bigmac_sbus_probe(struct platform_device *op, |
1246 | const struct of_device_id *match) | 1246 | const struct of_device_id *match) |
1247 | { | 1247 | { |
1248 | struct device *parent = op->dev.parent; | 1248 | struct device *parent = op->dev.parent; |
1249 | struct of_device *qec_op; | 1249 | struct platform_device *qec_op; |
1250 | 1250 | ||
1251 | qec_op = to_of_device(parent); | 1251 | qec_op = to_platform_device(parent); |
1252 | 1252 | ||
1253 | return bigmac_ether_init(op, qec_op); | 1253 | return bigmac_ether_init(op, qec_op); |
1254 | } | 1254 | } |
1255 | 1255 | ||
1256 | static int __devexit bigmac_sbus_remove(struct of_device *op) | 1256 | static int __devexit bigmac_sbus_remove(struct platform_device *op) |
1257 | { | 1257 | { |
1258 | struct bigmac *bp = dev_get_drvdata(&op->dev); | 1258 | struct bigmac *bp = dev_get_drvdata(&op->dev); |
1259 | struct device *parent = op->dev.parent; | 1259 | struct device *parent = op->dev.parent; |
1260 | struct net_device *net_dev = bp->dev; | 1260 | struct net_device *net_dev = bp->dev; |
1261 | struct of_device *qec_op; | 1261 | struct platform_device *qec_op; |
1262 | 1262 | ||
1263 | qec_op = to_of_device(parent); | 1263 | qec_op = to_platform_device(parent); |
1264 | 1264 | ||
1265 | unregister_netdev(net_dev); | 1265 | unregister_netdev(net_dev); |
1266 | 1266 | ||
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index 8840bc0b840b..8db88945b889 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h | |||
@@ -329,8 +329,8 @@ struct bigmac { | |||
329 | unsigned int timer_ticks; | 329 | unsigned int timer_ticks; |
330 | 330 | ||
331 | struct net_device_stats enet_stats; | 331 | struct net_device_stats enet_stats; |
332 | struct of_device *qec_op; | 332 | struct platform_device *qec_op; |
333 | struct of_device *bigmac_op; | 333 | struct platform_device *bigmac_op; |
334 | struct net_device *dev; | 334 | struct net_device *dev; |
335 | }; | 335 | }; |
336 | 336 | ||
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index eec443f64079..bd0df1c14955 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c | |||
@@ -1591,7 +1591,7 @@ static int happy_meal_init(struct happy_meal *hp) | |||
1591 | */ | 1591 | */ |
1592 | #ifdef CONFIG_SBUS | 1592 | #ifdef CONFIG_SBUS |
1593 | if ((hp->happy_flags & HFLAG_PCI) == 0) { | 1593 | if ((hp->happy_flags & HFLAG_PCI) == 0) { |
1594 | struct of_device *op = hp->happy_dev; | 1594 | struct platform_device *op = hp->happy_dev; |
1595 | if (sbus_can_dma_64bit()) { | 1595 | if (sbus_can_dma_64bit()) { |
1596 | sbus_set_sbus64(&op->dev, | 1596 | sbus_set_sbus64(&op->dev, |
1597 | hp->happy_bursts); | 1597 | hp->happy_bursts); |
@@ -2480,7 +2480,7 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info | |||
2480 | #ifdef CONFIG_SBUS | 2480 | #ifdef CONFIG_SBUS |
2481 | else { | 2481 | else { |
2482 | const struct linux_prom_registers *regs; | 2482 | const struct linux_prom_registers *regs; |
2483 | struct of_device *op = hp->happy_dev; | 2483 | struct platform_device *op = hp->happy_dev; |
2484 | regs = of_get_property(op->dev.of_node, "regs", NULL); | 2484 | regs = of_get_property(op->dev.of_node, "regs", NULL); |
2485 | if (regs) | 2485 | if (regs) |
2486 | sprintf(info->bus_info, "SBUS:%d", | 2486 | sprintf(info->bus_info, "SBUS:%d", |
@@ -2515,13 +2515,13 @@ static int hme_version_printed; | |||
2515 | * | 2515 | * |
2516 | * Return NULL on failure. | 2516 | * Return NULL on failure. |
2517 | */ | 2517 | */ |
2518 | static struct quattro * __devinit quattro_sbus_find(struct of_device *child) | 2518 | static struct quattro * __devinit quattro_sbus_find(struct platform_device *child) |
2519 | { | 2519 | { |
2520 | struct device *parent = child->dev.parent; | 2520 | struct device *parent = child->dev.parent; |
2521 | struct of_device *op; | 2521 | struct platform_device *op; |
2522 | struct quattro *qp; | 2522 | struct quattro *qp; |
2523 | 2523 | ||
2524 | op = to_of_device(parent); | 2524 | op = to_platform_device(parent); |
2525 | qp = dev_get_drvdata(&op->dev); | 2525 | qp = dev_get_drvdata(&op->dev); |
2526 | if (qp) | 2526 | if (qp) |
2527 | return qp; | 2527 | return qp; |
@@ -2551,7 +2551,7 @@ static int __init quattro_sbus_register_irqs(void) | |||
2551 | struct quattro *qp; | 2551 | struct quattro *qp; |
2552 | 2552 | ||
2553 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2553 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
2554 | struct of_device *op = qp->quattro_dev; | 2554 | struct platform_device *op = qp->quattro_dev; |
2555 | int err, qfe_slot, skip = 0; | 2555 | int err, qfe_slot, skip = 0; |
2556 | 2556 | ||
2557 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { | 2557 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { |
@@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void) | |||
2580 | struct quattro *qp; | 2580 | struct quattro *qp; |
2581 | 2581 | ||
2582 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2582 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
2583 | struct of_device *op = qp->quattro_dev; | 2583 | struct platform_device *op = qp->quattro_dev; |
2584 | int qfe_slot, skip = 0; | 2584 | int qfe_slot, skip = 0; |
2585 | 2585 | ||
2586 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { | 2586 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { |
@@ -2639,7 +2639,7 @@ static const struct net_device_ops hme_netdev_ops = { | |||
2639 | }; | 2639 | }; |
2640 | 2640 | ||
2641 | #ifdef CONFIG_SBUS | 2641 | #ifdef CONFIG_SBUS |
2642 | static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) | 2642 | static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe) |
2643 | { | 2643 | { |
2644 | struct device_node *dp = op->dev.of_node, *sbus_dp; | 2644 | struct device_node *dp = op->dev.of_node, *sbus_dp; |
2645 | struct quattro *qp = NULL; | 2645 | struct quattro *qp = NULL; |
@@ -2648,7 +2648,7 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) | |||
2648 | int i, qfe_slot = -1; | 2648 | int i, qfe_slot = -1; |
2649 | int err = -ENODEV; | 2649 | int err = -ENODEV; |
2650 | 2650 | ||
2651 | sbus_dp = to_of_device(op->dev.parent)->dev.of_node; | 2651 | sbus_dp = op->dev.parent->of_node; |
2652 | 2652 | ||
2653 | /* We can match PCI devices too, do not accept those here. */ | 2653 | /* We can match PCI devices too, do not accept those here. */ |
2654 | if (strcmp(sbus_dp->name, "sbus")) | 2654 | if (strcmp(sbus_dp->name, "sbus")) |
@@ -3235,7 +3235,7 @@ static void happy_meal_pci_exit(void) | |||
3235 | #endif | 3235 | #endif |
3236 | 3236 | ||
3237 | #ifdef CONFIG_SBUS | 3237 | #ifdef CONFIG_SBUS |
3238 | static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device_id *match) | 3238 | static int __devinit hme_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
3239 | { | 3239 | { |
3240 | struct device_node *dp = op->dev.of_node; | 3240 | struct device_node *dp = op->dev.of_node; |
3241 | const char *model = of_get_property(dp, "model", NULL); | 3241 | const char *model = of_get_property(dp, "model", NULL); |
@@ -3247,7 +3247,7 @@ static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device | |||
3247 | return happy_meal_sbus_probe_one(op, is_qfe); | 3247 | return happy_meal_sbus_probe_one(op, is_qfe); |
3248 | } | 3248 | } |
3249 | 3249 | ||
3250 | static int __devexit hme_sbus_remove(struct of_device *op) | 3250 | static int __devexit hme_sbus_remove(struct platform_device *op) |
3251 | { | 3251 | { |
3252 | struct happy_meal *hp = dev_get_drvdata(&op->dev); | 3252 | struct happy_meal *hp = dev_get_drvdata(&op->dev); |
3253 | struct net_device *net_dev = hp->dev; | 3253 | struct net_device *net_dev = hp->dev; |
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index efd2ca0fcad3..756b5bf3aa89 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h | |||
@@ -407,7 +407,7 @@ struct happy_meal { | |||
407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); | 407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); |
408 | #endif | 408 | #endif |
409 | 409 | ||
410 | /* This is either an of_device or a pci_dev. */ | 410 | /* This is either an platform_device or a pci_dev. */ |
411 | void *happy_dev; | 411 | void *happy_dev; |
412 | struct device *dma_dev; | 412 | struct device *dma_dev; |
413 | 413 | ||
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index ee364fa75634..8dcb858f2168 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c | |||
@@ -250,7 +250,7 @@ struct lance_private { | |||
250 | int rx_new, tx_new; | 250 | int rx_new, tx_new; |
251 | int rx_old, tx_old; | 251 | int rx_old, tx_old; |
252 | 252 | ||
253 | struct of_device *ledma; /* If set this points to ledma */ | 253 | struct platform_device *ledma; /* If set this points to ledma */ |
254 | char tpe; /* cable-selection is TPE */ | 254 | char tpe; /* cable-selection is TPE */ |
255 | char auto_select; /* cable-selection by carrier */ | 255 | char auto_select; /* cable-selection by carrier */ |
256 | char burst_sizes; /* ledma SBus burst sizes */ | 256 | char burst_sizes; /* ledma SBus burst sizes */ |
@@ -265,8 +265,8 @@ struct lance_private { | |||
265 | char *name; | 265 | char *name; |
266 | dma_addr_t init_block_dvma; | 266 | dma_addr_t init_block_dvma; |
267 | struct net_device *dev; /* Backpointer */ | 267 | struct net_device *dev; /* Backpointer */ |
268 | struct of_device *op; | 268 | struct platform_device *op; |
269 | struct of_device *lebuffer; | 269 | struct platform_device *lebuffer; |
270 | struct timer_list multicast_timer; | 270 | struct timer_list multicast_timer; |
271 | }; | 271 | }; |
272 | 272 | ||
@@ -1272,7 +1272,7 @@ static void lance_free_hwresources(struct lance_private *lp) | |||
1272 | if (lp->lregs) | 1272 | if (lp->lregs) |
1273 | of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); | 1273 | of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); |
1274 | if (lp->dregs) { | 1274 | if (lp->dregs) { |
1275 | struct of_device *ledma = lp->ledma; | 1275 | struct platform_device *ledma = lp->ledma; |
1276 | 1276 | ||
1277 | of_iounmap(&ledma->resource[0], lp->dregs, | 1277 | of_iounmap(&ledma->resource[0], lp->dregs, |
1278 | resource_size(&ledma->resource[0])); | 1278 | resource_size(&ledma->resource[0])); |
@@ -1319,9 +1319,9 @@ static const struct net_device_ops sparc_lance_ops = { | |||
1319 | .ndo_validate_addr = eth_validate_addr, | 1319 | .ndo_validate_addr = eth_validate_addr, |
1320 | }; | 1320 | }; |
1321 | 1321 | ||
1322 | static int __devinit sparc_lance_probe_one(struct of_device *op, | 1322 | static int __devinit sparc_lance_probe_one(struct platform_device *op, |
1323 | struct of_device *ledma, | 1323 | struct platform_device *ledma, |
1324 | struct of_device *lebuffer) | 1324 | struct platform_device *lebuffer) |
1325 | { | 1325 | { |
1326 | struct device_node *dp = op->dev.of_node; | 1326 | struct device_node *dp = op->dev.of_node; |
1327 | static unsigned version_printed; | 1327 | static unsigned version_printed; |
@@ -1503,9 +1503,9 @@ fail: | |||
1503 | return -ENODEV; | 1503 | return -ENODEV; |
1504 | } | 1504 | } |
1505 | 1505 | ||
1506 | static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_device_id *match) | 1506 | static int __devinit sunlance_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
1507 | { | 1507 | { |
1508 | struct of_device *parent = to_of_device(op->dev.parent); | 1508 | struct platform_device *parent = to_platform_device(op->dev.parent); |
1509 | struct device_node *parent_dp = parent->dev.of_node; | 1509 | struct device_node *parent_dp = parent->dev.of_node; |
1510 | int err; | 1510 | int err; |
1511 | 1511 | ||
@@ -1519,7 +1519,7 @@ static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_d | |||
1519 | return err; | 1519 | return err; |
1520 | } | 1520 | } |
1521 | 1521 | ||
1522 | static int __devexit sunlance_sbus_remove(struct of_device *op) | 1522 | static int __devexit sunlance_sbus_remove(struct platform_device *op) |
1523 | { | 1523 | { |
1524 | struct lance_private *lp = dev_get_drvdata(&op->dev); | 1524 | struct lance_private *lp = dev_get_drvdata(&op->dev); |
1525 | struct net_device *net_dev = lp->dev; | 1525 | struct net_device *net_dev = lp->dev; |
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 5f84a5dadedd..72e65d4666ef 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c | |||
@@ -689,7 +689,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
689 | { | 689 | { |
690 | const struct linux_prom_registers *regs; | 690 | const struct linux_prom_registers *regs; |
691 | struct sunqe *qep = netdev_priv(dev); | 691 | struct sunqe *qep = netdev_priv(dev); |
692 | struct of_device *op; | 692 | struct platform_device *op; |
693 | 693 | ||
694 | strcpy(info->driver, "sunqe"); | 694 | strcpy(info->driver, "sunqe"); |
695 | strcpy(info->version, "3.0"); | 695 | strcpy(info->version, "3.0"); |
@@ -720,7 +720,7 @@ static const struct ethtool_ops qe_ethtool_ops = { | |||
720 | }; | 720 | }; |
721 | 721 | ||
722 | /* This is only called once at boot time for each card probed. */ | 722 | /* This is only called once at boot time for each card probed. */ |
723 | static void qec_init_once(struct sunqec *qecp, struct of_device *op) | 723 | static void qec_init_once(struct sunqec *qecp, struct platform_device *op) |
724 | { | 724 | { |
725 | u8 bsizes = qecp->qec_bursts; | 725 | u8 bsizes = qecp->qec_bursts; |
726 | 726 | ||
@@ -770,9 +770,9 @@ static u8 __devinit qec_get_burst(struct device_node *dp) | |||
770 | return bsizes; | 770 | return bsizes; |
771 | } | 771 | } |
772 | 772 | ||
773 | static struct sunqec * __devinit get_qec(struct of_device *child) | 773 | static struct sunqec * __devinit get_qec(struct platform_device *child) |
774 | { | 774 | { |
775 | struct of_device *op = to_of_device(child->dev.parent); | 775 | struct platform_device *op = to_platform_device(child->dev.parent); |
776 | struct sunqec *qecp; | 776 | struct sunqec *qecp; |
777 | 777 | ||
778 | qecp = dev_get_drvdata(&op->dev); | 778 | qecp = dev_get_drvdata(&op->dev); |
@@ -836,7 +836,7 @@ static const struct net_device_ops qec_ops = { | |||
836 | .ndo_validate_addr = eth_validate_addr, | 836 | .ndo_validate_addr = eth_validate_addr, |
837 | }; | 837 | }; |
838 | 838 | ||
839 | static int __devinit qec_ether_init(struct of_device *op) | 839 | static int __devinit qec_ether_init(struct platform_device *op) |
840 | { | 840 | { |
841 | static unsigned version_printed; | 841 | static unsigned version_printed; |
842 | struct net_device *dev; | 842 | struct net_device *dev; |
@@ -941,12 +941,12 @@ fail: | |||
941 | return res; | 941 | return res; |
942 | } | 942 | } |
943 | 943 | ||
944 | static int __devinit qec_sbus_probe(struct of_device *op, const struct of_device_id *match) | 944 | static int __devinit qec_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
945 | { | 945 | { |
946 | return qec_ether_init(op); | 946 | return qec_ether_init(op); |
947 | } | 947 | } |
948 | 948 | ||
949 | static int __devexit qec_sbus_remove(struct of_device *op) | 949 | static int __devexit qec_sbus_remove(struct platform_device *op) |
950 | { | 950 | { |
951 | struct sunqe *qp = dev_get_drvdata(&op->dev); | 951 | struct sunqe *qp = dev_get_drvdata(&op->dev); |
952 | struct net_device *net_dev = qp->dev; | 952 | struct net_device *net_dev = qp->dev; |
@@ -997,7 +997,7 @@ static void __exit qec_exit(void) | |||
997 | 997 | ||
998 | while (root_qec_dev) { | 998 | while (root_qec_dev) { |
999 | struct sunqec *next = root_qec_dev->next_module; | 999 | struct sunqec *next = root_qec_dev->next_module; |
1000 | struct of_device *op = root_qec_dev->op; | 1000 | struct platform_device *op = root_qec_dev->op; |
1001 | 1001 | ||
1002 | free_irq(op->archdata.irqs[0], (void *) root_qec_dev); | 1002 | free_irq(op->archdata.irqs[0], (void *) root_qec_dev); |
1003 | of_iounmap(&op->resource[0], root_qec_dev->gregs, | 1003 | of_iounmap(&op->resource[0], root_qec_dev->gregs, |
diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h index 5813a7b2faa5..581781b6b2fa 100644 --- a/drivers/net/sunqe.h +++ b/drivers/net/sunqe.h | |||
@@ -314,7 +314,7 @@ struct sunqec { | |||
314 | void __iomem *gregs; /* QEC Global Registers */ | 314 | void __iomem *gregs; /* QEC Global Registers */ |
315 | struct sunqe *qes[4]; /* Each child MACE */ | 315 | struct sunqe *qes[4]; /* Each child MACE */ |
316 | unsigned int qec_bursts; /* Support burst sizes */ | 316 | unsigned int qec_bursts; /* Support burst sizes */ |
317 | struct of_device *op; /* QEC's OF device */ | 317 | struct platform_device *op; /* QEC's OF device */ |
318 | struct sunqec *next_module; /* List of all QECs in system */ | 318 | struct sunqec *next_module; /* List of all QECs in system */ |
319 | }; | 319 | }; |
320 | 320 | ||
@@ -342,7 +342,7 @@ struct sunqe { | |||
342 | __u32 buffers_dvma; /* DVMA visible address. */ | 342 | __u32 buffers_dvma; /* DVMA visible address. */ |
343 | struct sunqec *parent; | 343 | struct sunqec *parent; |
344 | u8 mconfig; /* Base MACE mconfig value */ | 344 | u8 mconfig; /* Base MACE mconfig value */ |
345 | struct of_device *op; /* QE's OF device struct */ | 345 | struct platform_device *op; /* QE's OF device struct */ |
346 | struct net_device *dev; /* QE's netdevice struct */ | 346 | struct net_device *dev; /* QE's netdevice struct */ |
347 | int channel; /* Who am I? */ | 347 | int channel; /* Who am I? */ |
348 | }; | 348 | }; |
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8d532f9b50d0..a4c3f5708246 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -3601,7 +3601,7 @@ static void ucc_geth_timeout(struct net_device *dev) | |||
3601 | 3601 | ||
3602 | #ifdef CONFIG_PM | 3602 | #ifdef CONFIG_PM |
3603 | 3603 | ||
3604 | static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) | 3604 | static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) |
3605 | { | 3605 | { |
3606 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); | 3606 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); |
3607 | struct ucc_geth_private *ugeth = netdev_priv(ndev); | 3607 | struct ucc_geth_private *ugeth = netdev_priv(ndev); |
@@ -3629,7 +3629,7 @@ static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) | |||
3629 | return 0; | 3629 | return 0; |
3630 | } | 3630 | } |
3631 | 3631 | ||
3632 | static int ucc_geth_resume(struct of_device *ofdev) | 3632 | static int ucc_geth_resume(struct platform_device *ofdev) |
3633 | { | 3633 | { |
3634 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); | 3634 | struct net_device *ndev = dev_get_drvdata(&ofdev->dev); |
3635 | struct ucc_geth_private *ugeth = netdev_priv(ndev); | 3635 | struct ucc_geth_private *ugeth = netdev_priv(ndev); |
@@ -3732,7 +3732,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = { | |||
3732 | #endif | 3732 | #endif |
3733 | }; | 3733 | }; |
3734 | 3734 | ||
3735 | static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) | 3735 | static int ucc_geth_probe(struct platform_device* ofdev, const struct of_device_id *match) |
3736 | { | 3736 | { |
3737 | struct device *device = &ofdev->dev; | 3737 | struct device *device = &ofdev->dev; |
3738 | struct device_node *np = ofdev->dev.of_node; | 3738 | struct device_node *np = ofdev->dev.of_node; |
@@ -3954,7 +3954,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
3954 | return 0; | 3954 | return 0; |
3955 | } | 3955 | } |
3956 | 3956 | ||
3957 | static int ucc_geth_remove(struct of_device* ofdev) | 3957 | static int ucc_geth_remove(struct platform_device* ofdev) |
3958 | { | 3958 | { |
3959 | struct device *device = &ofdev->dev; | 3959 | struct device *device = &ofdev->dev; |
3960 | struct net_device *dev = dev_get_drvdata(device); | 3960 | struct net_device *dev = dev_get_drvdata(device); |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 7f62e2dea28f..ca7fc9df1ccf 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -315,7 +315,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent); | |||
315 | 315 | ||
316 | static void rx_complete (struct urb *urb); | 316 | static void rx_complete (struct urb *urb); |
317 | 317 | ||
318 | static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) | 318 | static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) |
319 | { | 319 | { |
320 | struct sk_buff *skb; | 320 | struct sk_buff *skb; |
321 | struct skb_data *entry; | 321 | struct skb_data *entry; |
@@ -327,7 +327,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) | |||
327 | netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); | 327 | netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); |
328 | usbnet_defer_kevent (dev, EVENT_RX_MEMORY); | 328 | usbnet_defer_kevent (dev, EVENT_RX_MEMORY); |
329 | usb_free_urb (urb); | 329 | usb_free_urb (urb); |
330 | return; | 330 | return -ENOMEM; |
331 | } | 331 | } |
332 | skb_reserve (skb, NET_IP_ALIGN); | 332 | skb_reserve (skb, NET_IP_ALIGN); |
333 | 333 | ||
@@ -357,6 +357,9 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) | |||
357 | netif_dbg(dev, ifdown, dev->net, "device gone\n"); | 357 | netif_dbg(dev, ifdown, dev->net, "device gone\n"); |
358 | netif_device_detach (dev->net); | 358 | netif_device_detach (dev->net); |
359 | break; | 359 | break; |
360 | case -EHOSTUNREACH: | ||
361 | retval = -ENOLINK; | ||
362 | break; | ||
360 | default: | 363 | default: |
361 | netif_dbg(dev, rx_err, dev->net, | 364 | netif_dbg(dev, rx_err, dev->net, |
362 | "rx submit, %d\n", retval); | 365 | "rx submit, %d\n", retval); |
@@ -374,6 +377,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) | |||
374 | dev_kfree_skb_any (skb); | 377 | dev_kfree_skb_any (skb); |
375 | usb_free_urb (urb); | 378 | usb_free_urb (urb); |
376 | } | 379 | } |
380 | return retval; | ||
377 | } | 381 | } |
378 | 382 | ||
379 | 383 | ||
@@ -912,6 +916,7 @@ fail_halt: | |||
912 | /* tasklet could resubmit itself forever if memory is tight */ | 916 | /* tasklet could resubmit itself forever if memory is tight */ |
913 | if (test_bit (EVENT_RX_MEMORY, &dev->flags)) { | 917 | if (test_bit (EVENT_RX_MEMORY, &dev->flags)) { |
914 | struct urb *urb = NULL; | 918 | struct urb *urb = NULL; |
919 | int resched = 1; | ||
915 | 920 | ||
916 | if (netif_running (dev->net)) | 921 | if (netif_running (dev->net)) |
917 | urb = usb_alloc_urb (0, GFP_KERNEL); | 922 | urb = usb_alloc_urb (0, GFP_KERNEL); |
@@ -922,10 +927,12 @@ fail_halt: | |||
922 | status = usb_autopm_get_interface(dev->intf); | 927 | status = usb_autopm_get_interface(dev->intf); |
923 | if (status < 0) | 928 | if (status < 0) |
924 | goto fail_lowmem; | 929 | goto fail_lowmem; |
925 | rx_submit (dev, urb, GFP_KERNEL); | 930 | if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK) |
931 | resched = 0; | ||
926 | usb_autopm_put_interface(dev->intf); | 932 | usb_autopm_put_interface(dev->intf); |
927 | fail_lowmem: | 933 | fail_lowmem: |
928 | tasklet_schedule (&dev->bh); | 934 | if (resched) |
935 | tasklet_schedule (&dev->bh); | ||
929 | } | 936 | } |
930 | } | 937 | } |
931 | 938 | ||
@@ -1175,8 +1182,11 @@ static void usbnet_bh (unsigned long param) | |||
1175 | // don't refill the queue all at once | 1182 | // don't refill the queue all at once |
1176 | for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { | 1183 | for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { |
1177 | urb = usb_alloc_urb (0, GFP_ATOMIC); | 1184 | urb = usb_alloc_urb (0, GFP_ATOMIC); |
1178 | if (urb != NULL) | 1185 | if (urb != NULL) { |
1179 | rx_submit (dev, urb, GFP_ATOMIC); | 1186 | if (rx_submit (dev, urb, GFP_ATOMIC) == |
1187 | -ENOLINK) | ||
1188 | return; | ||
1189 | } | ||
1180 | } | 1190 | } |
1181 | if (temp != dev->rxq.qlen) | 1191 | if (temp != dev->rxq.qlen) |
1182 | netif_dbg(dev, link, dev->net, | 1192 | netif_dbg(dev, link, dev->net, |
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index ad7719fe6d0a..e050bd65e037 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c | |||
@@ -885,20 +885,21 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, | |||
885 | * Receive a frame through the DMA | 885 | * Receive a frame through the DMA |
886 | */ | 886 | */ |
887 | static inline void | 887 | static inline void |
888 | fst_rx_dma(struct fst_card_info *card, unsigned char *skb, | 888 | fst_rx_dma(struct fst_card_info *card, dma_addr_t skb, |
889 | unsigned char *mem, int len) | 889 | dma_addr_t mem, int len) |
890 | { | 890 | { |
891 | /* | 891 | /* |
892 | * This routine will setup the DMA and start it | 892 | * This routine will setup the DMA and start it |
893 | */ | 893 | */ |
894 | 894 | ||
895 | dbg(DBG_RX, "In fst_rx_dma %p %p %d\n", skb, mem, len); | 895 | dbg(DBG_RX, "In fst_rx_dma %lx %lx %d\n", |
896 | (unsigned long) skb, (unsigned long) mem, len); | ||
896 | if (card->dmarx_in_progress) { | 897 | if (card->dmarx_in_progress) { |
897 | dbg(DBG_ASS, "In fst_rx_dma while dma in progress\n"); | 898 | dbg(DBG_ASS, "In fst_rx_dma while dma in progress\n"); |
898 | } | 899 | } |
899 | 900 | ||
900 | outl((unsigned long) skb, card->pci_conf + DMAPADR0); /* Copy to here */ | 901 | outl(skb, card->pci_conf + DMAPADR0); /* Copy to here */ |
901 | outl((unsigned long) mem, card->pci_conf + DMALADR0); /* from here */ | 902 | outl(mem, card->pci_conf + DMALADR0); /* from here */ |
902 | outl(len, card->pci_conf + DMASIZ0); /* for this length */ | 903 | outl(len, card->pci_conf + DMASIZ0); /* for this length */ |
903 | outl(0x00000000c, card->pci_conf + DMADPR0); /* In this direction */ | 904 | outl(0x00000000c, card->pci_conf + DMADPR0); /* In this direction */ |
904 | 905 | ||
@@ -1309,8 +1310,8 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port) | |||
1309 | card->dma_port_rx = port; | 1310 | card->dma_port_rx = port; |
1310 | card->dma_len_rx = len; | 1311 | card->dma_len_rx = len; |
1311 | card->dma_rxpos = rxp; | 1312 | card->dma_rxpos = rxp; |
1312 | fst_rx_dma(card, (char *) card->rx_dma_handle_card, | 1313 | fst_rx_dma(card, card->rx_dma_handle_card, |
1313 | (char *) BUF_OFFSET(rxBuffer[pi][rxp][0]), len); | 1314 | BUF_OFFSET(rxBuffer[pi][rxp][0]), len); |
1314 | } | 1315 | } |
1315 | if (rxp != port->rxpos) { | 1316 | if (rxp != port->rxpos) { |
1316 | dbg(DBG_ASS, "About to increment rxpos by more than 1\n"); | 1317 | dbg(DBG_ASS, "About to increment rxpos by more than 1\n"); |
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 88e363033e23..6c571e198835 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c | |||
@@ -396,7 +396,7 @@ static void hss_config(struct port *port) | |||
396 | msg.cmd = PORT_CONFIG_WRITE; | 396 | msg.cmd = PORT_CONFIG_WRITE; |
397 | msg.hss_port = port->id; | 397 | msg.hss_port = port->id; |
398 | msg.index = HSS_CONFIG_TX_PCR; | 398 | msg.index = HSS_CONFIG_TX_PCR; |
399 | msg.data32 = PCR_FRM_SYNC_OUTPUT_RISING | PCR_MSB_ENDIAN | | 399 | msg.data32 = PCR_FRM_PULSE_DISABLED | PCR_MSB_ENDIAN | |
400 | PCR_TX_DATA_ENABLE | PCR_SOF_NO_FBIT; | 400 | PCR_TX_DATA_ENABLE | PCR_SOF_NO_FBIT; |
401 | if (port->clock_type == CLOCK_INT) | 401 | if (port->clock_type == CLOCK_INT) |
402 | msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT; | 402 | msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 8848333bc3a9..fec026212326 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -260,7 +260,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
260 | .shadow_ram_support = false, | 260 | .shadow_ram_support = false, |
261 | .ht_greenfield_support = true, | 261 | .ht_greenfield_support = true, |
262 | .led_compensation = 51, | 262 | .led_compensation = 51, |
263 | .use_rts_for_ht = true, /* use rts/cts protection */ | 263 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
264 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 264 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
265 | .support_ct_kill_exit = true, | 265 | .support_ct_kill_exit = true, |
266 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 266 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index a07310fefcf2..6950a783913b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -769,22 +769,6 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
769 | rts_retry_limit = data_retry_limit; | 769 | rts_retry_limit = data_retry_limit; |
770 | tx_cmd->rts_retry_limit = rts_retry_limit; | 770 | tx_cmd->rts_retry_limit = rts_retry_limit; |
771 | 771 | ||
772 | if (ieee80211_is_mgmt(fc)) { | ||
773 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
774 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
775 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
776 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
777 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
778 | if (tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
779 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
780 | tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
781 | } | ||
782 | break; | ||
783 | default: | ||
784 | break; | ||
785 | } | ||
786 | } | ||
787 | |||
788 | tx_cmd->rate = rate; | 772 | tx_cmd->rate = rate; |
789 | tx_cmd->tx_flags = tx_flags; | 773 | tx_cmd->tx_flags = tx_flags; |
790 | 774 | ||
@@ -2717,7 +2701,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2717 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2701 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { |
2718 | .get_hcmd_size = iwl3945_get_hcmd_size, | 2702 | .get_hcmd_size = iwl3945_get_hcmd_size, |
2719 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, | 2703 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, |
2720 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | 2704 | .tx_cmd_protection = iwlcore_tx_cmd_protection, |
2721 | .request_scan = iwl3945_request_scan, | 2705 | .request_scan = iwl3945_request_scan, |
2722 | }; | 2706 | }; |
2723 | 2707 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d6531ad3906a..d6da356608fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2223,7 +2223,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2223 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 2223 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
2224 | .chain_noise_reset = iwl4965_chain_noise_reset, | 2224 | .chain_noise_reset = iwl4965_chain_noise_reset, |
2225 | .gain_computation = iwl4965_gain_computation, | 2225 | .gain_computation = iwl4965_gain_computation, |
2226 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | 2226 | .tx_cmd_protection = iwlcore_tx_cmd_protection, |
2227 | .calc_rssi = iwl4965_calc_rssi, | 2227 | .calc_rssi = iwl4965_calc_rssi, |
2228 | .request_scan = iwlagn_request_scan, | 2228 | .request_scan = iwlagn_request_scan, |
2229 | }; | 2229 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8093ce2804fb..aacf3770f075 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -506,7 +506,7 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
506 | .use_bsm = false, | 506 | .use_bsm = false, |
507 | .ht_greenfield_support = true, | 507 | .ht_greenfield_support = true, |
508 | .led_compensation = 51, | 508 | .led_compensation = 51, |
509 | .use_rts_for_ht = true, /* use rts/cts protection */ | 509 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
510 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 510 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
511 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 511 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
512 | .chain_noise_scale = 1000, | 512 | .chain_noise_scale = 1000, |
@@ -537,7 +537,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { | |||
537 | .use_bsm = false, | 537 | .use_bsm = false, |
538 | .ht_greenfield_support = true, | 538 | .ht_greenfield_support = true, |
539 | .led_compensation = 51, | 539 | .led_compensation = 51, |
540 | .use_rts_for_ht = true, /* use rts/cts protection */ | 540 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
541 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 541 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
542 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 542 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
543 | .chain_noise_scale = 1000, | 543 | .chain_noise_scale = 1000, |
@@ -597,7 +597,7 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
597 | .use_bsm = false, | 597 | .use_bsm = false, |
598 | .ht_greenfield_support = true, | 598 | .ht_greenfield_support = true, |
599 | .led_compensation = 51, | 599 | .led_compensation = 51, |
600 | .use_rts_for_ht = true, /* use rts/cts protection */ | 600 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
601 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 601 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
602 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 602 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
603 | .chain_noise_scale = 1000, | 603 | .chain_noise_scale = 1000, |
@@ -628,7 +628,7 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
628 | .use_bsm = false, | 628 | .use_bsm = false, |
629 | .ht_greenfield_support = true, | 629 | .ht_greenfield_support = true, |
630 | .led_compensation = 51, | 630 | .led_compensation = 51, |
631 | .use_rts_for_ht = true, /* use rts/cts protection */ | 631 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
632 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 632 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
633 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 633 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
634 | .chain_noise_scale = 1000, | 634 | .chain_noise_scale = 1000, |
@@ -659,7 +659,7 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
659 | .use_bsm = false, | 659 | .use_bsm = false, |
660 | .ht_greenfield_support = true, | 660 | .ht_greenfield_support = true, |
661 | .led_compensation = 51, | 661 | .led_compensation = 51, |
662 | .use_rts_for_ht = true, /* use rts/cts protection */ | 662 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
663 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 663 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
664 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 664 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
665 | .chain_noise_scale = 1000, | 665 | .chain_noise_scale = 1000, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 58270529a0e4..af4fd50f3405 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -381,7 +381,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { | |||
381 | .shadow_ram_support = true, | 381 | .shadow_ram_support = true, |
382 | .ht_greenfield_support = true, | 382 | .ht_greenfield_support = true, |
383 | .led_compensation = 51, | 383 | .led_compensation = 51, |
384 | .use_rts_for_ht = true, /* use rts/cts protection */ | 384 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
385 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 385 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
386 | .supports_idle = true, | 386 | .supports_idle = true, |
387 | .adv_thermal_throttle = true, | 387 | .adv_thermal_throttle = true, |
@@ -489,7 +489,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { | |||
489 | .shadow_ram_support = true, | 489 | .shadow_ram_support = true, |
490 | .ht_greenfield_support = true, | 490 | .ht_greenfield_support = true, |
491 | .led_compensation = 51, | 491 | .led_compensation = 51, |
492 | .use_rts_for_ht = true, /* use rts/cts protection */ | 492 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
493 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 493 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
494 | .supports_idle = true, | 494 | .supports_idle = true, |
495 | .adv_thermal_throttle = true, | 495 | .adv_thermal_throttle = true, |
@@ -563,7 +563,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { | |||
563 | .shadow_ram_support = true, | 563 | .shadow_ram_support = true, |
564 | .ht_greenfield_support = true, | 564 | .ht_greenfield_support = true, |
565 | .led_compensation = 51, | 565 | .led_compensation = 51, |
566 | .use_rts_for_ht = true, /* use rts/cts protection */ | 566 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
567 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 567 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
568 | .supports_idle = true, | 568 | .supports_idle = true, |
569 | .adv_thermal_throttle = true, | 569 | .adv_thermal_throttle = true, |
@@ -637,7 +637,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { | |||
637 | .shadow_ram_support = true, | 637 | .shadow_ram_support = true, |
638 | .ht_greenfield_support = true, | 638 | .ht_greenfield_support = true, |
639 | .led_compensation = 51, | 639 | .led_compensation = 51, |
640 | .use_rts_for_ht = true, /* use rts/cts protection */ | 640 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
641 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 641 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
642 | .supports_idle = true, | 642 | .supports_idle = true, |
643 | .adv_thermal_throttle = true, | 643 | .adv_thermal_throttle = true, |
@@ -714,7 +714,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
714 | .shadow_ram_support = true, | 714 | .shadow_ram_support = true, |
715 | .ht_greenfield_support = true, | 715 | .ht_greenfield_support = true, |
716 | .led_compensation = 51, | 716 | .led_compensation = 51, |
717 | .use_rts_for_ht = true, /* use rts/cts protection */ | 717 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
718 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 718 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
719 | .supports_idle = true, | 719 | .supports_idle = true, |
720 | .adv_thermal_throttle = true, | 720 | .adv_thermal_throttle = true, |
@@ -821,7 +821,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
821 | .shadow_ram_support = true, | 821 | .shadow_ram_support = true, |
822 | .ht_greenfield_support = true, | 822 | .ht_greenfield_support = true, |
823 | .led_compensation = 51, | 823 | .led_compensation = 51, |
824 | .use_rts_for_ht = true, /* use rts/cts protection */ | 824 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
825 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 825 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
826 | .supports_idle = true, | 826 | .supports_idle = true, |
827 | .adv_thermal_throttle = true, | 827 | .adv_thermal_throttle = true, |
@@ -859,7 +859,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = { | |||
859 | .shadow_ram_support = true, | 859 | .shadow_ram_support = true, |
860 | .ht_greenfield_support = true, | 860 | .ht_greenfield_support = true, |
861 | .led_compensation = 51, | 861 | .led_compensation = 51, |
862 | .use_rts_for_ht = true, /* use rts/cts protection */ | 862 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
863 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 863 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
864 | .supports_idle = true, | 864 | .supports_idle = true, |
865 | .adv_thermal_throttle = true, | 865 | .adv_thermal_throttle = true, |
@@ -933,7 +933,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
933 | .shadow_ram_support = true, | 933 | .shadow_ram_support = true, |
934 | .ht_greenfield_support = true, | 934 | .ht_greenfield_support = true, |
935 | .led_compensation = 51, | 935 | .led_compensation = 51, |
936 | .use_rts_for_ht = true, /* use rts/cts protection */ | 936 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
937 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 937 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
938 | .supports_idle = true, | 938 | .supports_idle = true, |
939 | .adv_thermal_throttle = true, | 939 | .adv_thermal_throttle = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index a7216dda9786..75b901b3eb1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -211,10 +211,21 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | |||
211 | } | 211 | } |
212 | } | 212 | } |
213 | 213 | ||
214 | static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | 214 | static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, |
215 | __le32 *tx_flags) | 215 | struct ieee80211_tx_info *info, |
216 | __le16 fc, __le32 *tx_flags) | ||
216 | { | 217 | { |
217 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | 218 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || |
219 | info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
220 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | ||
221 | return; | ||
222 | } | ||
223 | |||
224 | if (priv->cfg->use_rts_for_aggregation && | ||
225 | info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
226 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | ||
227 | return; | ||
228 | } | ||
218 | } | 229 | } |
219 | 230 | ||
220 | /* Calc max signal level (dBm) among 3 possible receivers */ | 231 | /* Calc max signal level (dBm) among 3 possible receivers */ |
@@ -268,7 +279,7 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | |||
268 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, | 279 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, |
269 | .gain_computation = iwlagn_gain_computation, | 280 | .gain_computation = iwlagn_gain_computation, |
270 | .chain_noise_reset = iwlagn_chain_noise_reset, | 281 | .chain_noise_reset = iwlagn_chain_noise_reset, |
271 | .rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag, | 282 | .tx_cmd_protection = iwlagn_tx_cmd_protection, |
272 | .calc_rssi = iwlagn_calc_rssi, | 283 | .calc_rssi = iwlagn_calc_rssi, |
273 | .request_scan = iwlagn_request_scan, | 284 | .request_scan = iwlagn_request_scan, |
274 | }; | 285 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index d04502d54df3..69155aa448fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -379,10 +379,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
379 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 379 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
380 | } | 380 | } |
381 | 381 | ||
382 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | 382 | priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags); |
383 | |||
384 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
385 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
386 | 383 | ||
387 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | 384 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); |
388 | if (ieee80211_is_mgmt(fc)) { | 385 | if (ieee80211_is_mgmt(fc)) { |
@@ -456,21 +453,6 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
456 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | 453 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) |
457 | rate_flags |= RATE_MCS_CCK_MSK; | 454 | rate_flags |= RATE_MCS_CCK_MSK; |
458 | 455 | ||
459 | /* Set up RTS and CTS flags for certain packets */ | ||
460 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
461 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
462 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
463 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
464 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
465 | if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
466 | tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
467 | tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
468 | } | ||
469 | break; | ||
470 | default: | ||
471 | break; | ||
472 | } | ||
473 | |||
474 | /* Set up antennas */ | 456 | /* Set up antennas */ |
475 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 457 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
476 | priv->hw_params.valid_tx_ant); | 458 | priv->hw_params.valid_tx_ant); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 35337b1e7cac..c1882fd8345d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -202,13 +202,6 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
202 | 202 | ||
203 | priv->start_calib = 0; | 203 | priv->start_calib = 0; |
204 | if (new_assoc) { | 204 | if (new_assoc) { |
205 | /* | ||
206 | * allow CTS-to-self if possible for new association. | ||
207 | * this is relevant only for 5000 series and up, | ||
208 | * but will not damage 4965 | ||
209 | */ | ||
210 | priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; | ||
211 | |||
212 | /* Apply the new configuration | 205 | /* Apply the new configuration |
213 | * RXON assoc doesn't clear the station table in uCode, | 206 | * RXON assoc doesn't clear the station table in uCode, |
214 | */ | 207 | */ |
@@ -1618,45 +1611,9 @@ static ssize_t store_tx_power(struct device *d, | |||
1618 | 1611 | ||
1619 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | 1612 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); |
1620 | 1613 | ||
1621 | static ssize_t show_rts_ht_protection(struct device *d, | ||
1622 | struct device_attribute *attr, char *buf) | ||
1623 | { | ||
1624 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1625 | |||
1626 | return sprintf(buf, "%s\n", | ||
1627 | priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); | ||
1628 | } | ||
1629 | |||
1630 | static ssize_t store_rts_ht_protection(struct device *d, | ||
1631 | struct device_attribute *attr, | ||
1632 | const char *buf, size_t count) | ||
1633 | { | ||
1634 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
1635 | unsigned long val; | ||
1636 | int ret; | ||
1637 | |||
1638 | ret = strict_strtoul(buf, 10, &val); | ||
1639 | if (ret) | ||
1640 | IWL_INFO(priv, "Input is not in decimal form.\n"); | ||
1641 | else { | ||
1642 | if (!iwl_is_associated(priv)) | ||
1643 | priv->cfg->use_rts_for_ht = val ? true : false; | ||
1644 | else | ||
1645 | IWL_ERR(priv, "Sta associated with AP - " | ||
1646 | "Change protection mechanism is not allowed\n"); | ||
1647 | ret = count; | ||
1648 | } | ||
1649 | return ret; | ||
1650 | } | ||
1651 | |||
1652 | static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, | ||
1653 | show_rts_ht_protection, store_rts_ht_protection); | ||
1654 | |||
1655 | |||
1656 | static struct attribute *iwl_sysfs_entries[] = { | 1614 | static struct attribute *iwl_sysfs_entries[] = { |
1657 | &dev_attr_temperature.attr, | 1615 | &dev_attr_temperature.attr, |
1658 | &dev_attr_tx_power.attr, | 1616 | &dev_attr_tx_power.attr, |
1659 | &dev_attr_rts_ht_protection.attr, | ||
1660 | #ifdef CONFIG_IWLWIFI_DEBUG | 1617 | #ifdef CONFIG_IWLWIFI_DEBUG |
1661 | &dev_attr_debug_level.attr, | 1618 | &dev_attr_debug_level.attr, |
1662 | #endif | 1619 | #endif |
@@ -3464,25 +3421,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3464 | return ret; | 3421 | return ret; |
3465 | } | 3422 | } |
3466 | 3423 | ||
3467 | /* | ||
3468 | * switch to RTS/CTS for TX | ||
3469 | */ | ||
3470 | static void iwl_enable_rts_cts(struct iwl_priv *priv) | ||
3471 | { | ||
3472 | |||
3473 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3474 | return; | ||
3475 | |||
3476 | priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; | ||
3477 | if (!test_bit(STATUS_SCANNING, &priv->status)) { | ||
3478 | IWL_DEBUG_INFO(priv, "use RTS/CTS protection\n"); | ||
3479 | iwlcore_commit_rxon(priv); | ||
3480 | } else { | ||
3481 | /* scanning, defer the request until scan completed */ | ||
3482 | IWL_DEBUG_INFO(priv, "defer setting RTS/CTS protection\n"); | ||
3483 | } | ||
3484 | } | ||
3485 | |||
3486 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 3424 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, |
3487 | struct ieee80211_vif *vif, | 3425 | struct ieee80211_vif *vif, |
3488 | enum ieee80211_ampdu_mlme_action action, | 3426 | enum ieee80211_ampdu_mlme_action action, |
@@ -3529,14 +3467,33 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3529 | } | 3467 | } |
3530 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3468 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3531 | ret = 0; | 3469 | ret = 0; |
3470 | if (priv->cfg->use_rts_for_aggregation) { | ||
3471 | struct iwl_station_priv *sta_priv = | ||
3472 | (void *) sta->drv_priv; | ||
3473 | /* | ||
3474 | * switch off RTS/CTS if it was previously enabled | ||
3475 | */ | ||
3476 | |||
3477 | sta_priv->lq_sta.lq.general_params.flags &= | ||
3478 | ~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | ||
3479 | iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, | ||
3480 | CMD_ASYNC, false); | ||
3481 | } | ||
3532 | break; | 3482 | break; |
3533 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3483 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
3534 | if (priv->cfg->use_rts_for_ht) { | 3484 | if (priv->cfg->use_rts_for_aggregation) { |
3485 | struct iwl_station_priv *sta_priv = | ||
3486 | (void *) sta->drv_priv; | ||
3487 | |||
3535 | /* | 3488 | /* |
3536 | * switch to RTS/CTS if it is the prefer protection | 3489 | * switch to RTS/CTS if it is the prefer protection |
3537 | * method for HT traffic | 3490 | * method for HT traffic |
3538 | */ | 3491 | */ |
3539 | iwl_enable_rts_cts(priv); | 3492 | |
3493 | sta_priv->lq_sta.lq.general_params.flags |= | ||
3494 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | ||
3495 | iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq, | ||
3496 | CMD_ASYNC, false); | ||
3540 | } | 3497 | } |
3541 | ret = 0; | 3498 | ret = 0; |
3542 | break; | 3499 | break; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8ccb6d205b6d..2c03c6e20a72 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -401,21 +401,38 @@ void iwlcore_free_geos(struct iwl_priv *priv) | |||
401 | EXPORT_SYMBOL(iwlcore_free_geos); | 401 | EXPORT_SYMBOL(iwlcore_free_geos); |
402 | 402 | ||
403 | /* | 403 | /* |
404 | * iwlcore_rts_tx_cmd_flag: Set rts/cts. 3945 and 4965 only share this | 404 | * iwlcore_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this |
405 | * function. | 405 | * function. |
406 | */ | 406 | */ |
407 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | 407 | void iwlcore_tx_cmd_protection(struct iwl_priv *priv, |
408 | __le32 *tx_flags) | 408 | struct ieee80211_tx_info *info, |
409 | __le16 fc, __le32 *tx_flags) | ||
409 | { | 410 | { |
410 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 411 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
411 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | 412 | *tx_flags |= TX_CMD_FLG_RTS_MSK; |
412 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | 413 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; |
414 | *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
415 | |||
416 | if (!ieee80211_is_mgmt(fc)) | ||
417 | return; | ||
418 | |||
419 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
420 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
421 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
422 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
423 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
424 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
425 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
426 | break; | ||
427 | } | ||
413 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 428 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
414 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | 429 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; |
415 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | 430 | *tx_flags |= TX_CMD_FLG_CTS_MSK; |
431 | *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
416 | } | 432 | } |
417 | } | 433 | } |
418 | EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); | 434 | EXPORT_SYMBOL(iwlcore_tx_cmd_protection); |
435 | |||
419 | 436 | ||
420 | static bool is_single_rx_stream(struct iwl_priv *priv) | 437 | static bool is_single_rx_stream(struct iwl_priv *priv) |
421 | { | 438 | { |
@@ -1869,6 +1886,10 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1869 | priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; | 1886 | priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; |
1870 | else | 1887 | else |
1871 | priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; | 1888 | priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; |
1889 | if (bss_conf->use_cts_prot) | ||
1890 | priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; | ||
1891 | else | ||
1892 | priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; | ||
1872 | } | 1893 | } |
1873 | 1894 | ||
1874 | if (changes & BSS_CHANGED_BASIC_RATES) { | 1895 | if (changes & BSS_CHANGED_BASIC_RATES) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e9d23f2f869d..4a71dfb10a15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -104,8 +104,9 @@ struct iwl_hcmd_utils_ops { | |||
104 | u32 min_average_noise, | 104 | u32 min_average_noise, |
105 | u8 default_chain); | 105 | u8 default_chain); |
106 | void (*chain_noise_reset)(struct iwl_priv *priv); | 106 | void (*chain_noise_reset)(struct iwl_priv *priv); |
107 | void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, | 107 | void (*tx_cmd_protection)(struct iwl_priv *priv, |
108 | __le32 *tx_flags); | 108 | struct ieee80211_tx_info *info, |
109 | __le16 fc, __le32 *tx_flags); | ||
109 | int (*calc_rssi)(struct iwl_priv *priv, | 110 | int (*calc_rssi)(struct iwl_priv *priv, |
110 | struct iwl_rx_phy_res *rx_resp); | 111 | struct iwl_rx_phy_res *rx_resp); |
111 | void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); | 112 | void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); |
@@ -249,7 +250,7 @@ struct iwl_mod_params { | |||
249 | * @led_compensation: compensate on the led on/off time per HW according | 250 | * @led_compensation: compensate on the led on/off time per HW according |
250 | * to the deviation to achieve the desired led frequency. | 251 | * to the deviation to achieve the desired led frequency. |
251 | * The detail algorithm is described in iwl-led.c | 252 | * The detail algorithm is described in iwl-led.c |
252 | * @use_rts_for_ht: use rts/cts protection for HT traffic | 253 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic |
253 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 254 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
254 | * @adv_thermal_throttle: support advance thermal throttle | 255 | * @adv_thermal_throttle: support advance thermal throttle |
255 | * @support_ct_kill_exit: support ct kill exit condition | 256 | * @support_ct_kill_exit: support ct kill exit condition |
@@ -318,7 +319,7 @@ struct iwl_cfg { | |||
318 | const bool ht_greenfield_support; | 319 | const bool ht_greenfield_support; |
319 | u16 led_compensation; | 320 | u16 led_compensation; |
320 | const bool broken_powersave; | 321 | const bool broken_powersave; |
321 | bool use_rts_for_ht; | 322 | bool use_rts_for_aggregation; |
322 | int chain_noise_num_beacons; | 323 | int chain_noise_num_beacons; |
323 | const bool supports_idle; | 324 | const bool supports_idle; |
324 | bool adv_thermal_throttle; | 325 | bool adv_thermal_throttle; |
@@ -390,8 +391,9 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); | |||
390 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); | 391 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); |
391 | int iwl_alloc_txq_mem(struct iwl_priv *priv); | 392 | int iwl_alloc_txq_mem(struct iwl_priv *priv); |
392 | void iwl_free_txq_mem(struct iwl_priv *priv); | 393 | void iwl_free_txq_mem(struct iwl_priv *priv); |
393 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | 394 | void iwlcore_tx_cmd_protection(struct iwl_priv *priv, |
394 | __le32 *tx_flags); | 395 | struct ieee80211_tx_info *info, |
396 | __le16 fc, __le32 *tx_flags); | ||
395 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 397 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
396 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); | 398 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); |
397 | void iwl_free_traffic_mem(struct iwl_priv *priv); | 399 | void iwl_free_traffic_mem(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d24eb47d3705..70c4b8fba0ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -435,10 +435,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
435 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 435 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
436 | } | 436 | } |
437 | 437 | ||
438 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | 438 | priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags); |
439 | |||
440 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
441 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
442 | 439 | ||
443 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | 440 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); |
444 | if (ieee80211_is_mgmt(fc)) { | 441 | if (ieee80211_is_mgmt(fc)) { |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 8e9fbfd804b6..3e82f1627209 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -6,7 +6,10 @@ | |||
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/wait.h> | ||
9 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/sched.h> | ||
10 | #include <linux/ieee80211.h> | 13 | #include <linux/ieee80211.h> |
11 | #include <net/cfg80211.h> | 14 | #include <net/cfg80211.h> |
12 | #include <asm/unaligned.h> | 15 | #include <asm/unaligned.h> |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 6e71346a7550..ba854c70ab94 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -125,6 +125,8 @@ struct if_sdio_card { | |||
125 | 125 | ||
126 | const char *helper; | 126 | const char *helper; |
127 | const char *firmware; | 127 | const char *firmware; |
128 | bool helper_allocated; | ||
129 | bool firmware_allocated; | ||
128 | 130 | ||
129 | u8 buffer[65536]; | 131 | u8 buffer[65536]; |
130 | 132 | ||
@@ -984,16 +986,34 @@ static int if_sdio_probe(struct sdio_func *func, | |||
984 | card->helper = if_sdio_models[i].helper; | 986 | card->helper = if_sdio_models[i].helper; |
985 | card->firmware = if_sdio_models[i].firmware; | 987 | card->firmware = if_sdio_models[i].firmware; |
986 | 988 | ||
989 | kparam_block_sysfs_write(helper_name); | ||
987 | if (lbs_helper_name) { | 990 | if (lbs_helper_name) { |
991 | char *helper = kstrdup(lbs_helper_name, GFP_KERNEL); | ||
992 | if (!helper) { | ||
993 | kparam_unblock_sysfs_write(helper_name); | ||
994 | ret = -ENOMEM; | ||
995 | goto free; | ||
996 | } | ||
988 | lbs_deb_sdio("overriding helper firmware: %s\n", | 997 | lbs_deb_sdio("overriding helper firmware: %s\n", |
989 | lbs_helper_name); | 998 | lbs_helper_name); |
990 | card->helper = lbs_helper_name; | 999 | card->helper = helper; |
1000 | card->helper_allocated = true; | ||
991 | } | 1001 | } |
1002 | kparam_unblock_sysfs_write(helper_name); | ||
992 | 1003 | ||
1004 | kparam_block_sysfs_write(fw_name); | ||
993 | if (lbs_fw_name) { | 1005 | if (lbs_fw_name) { |
1006 | char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL); | ||
1007 | if (!fw_name) { | ||
1008 | kparam_unblock_sysfs_write(fw_name); | ||
1009 | ret = -ENOMEM; | ||
1010 | goto free; | ||
1011 | } | ||
994 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); | 1012 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); |
995 | card->firmware = lbs_fw_name; | 1013 | card->firmware = fw_name; |
1014 | card->firmware_allocated = true; | ||
996 | } | 1015 | } |
1016 | kparam_unblock_sysfs_write(fw_name); | ||
997 | 1017 | ||
998 | sdio_claim_host(func); | 1018 | sdio_claim_host(func); |
999 | 1019 | ||
@@ -1127,6 +1147,10 @@ free: | |||
1127 | kfree(packet); | 1147 | kfree(packet); |
1128 | } | 1148 | } |
1129 | 1149 | ||
1150 | if (card->helper_allocated) | ||
1151 | kfree(card->helper); | ||
1152 | if (card->firmware_allocated) | ||
1153 | kfree(card->firmware); | ||
1130 | kfree(card); | 1154 | kfree(card); |
1131 | 1155 | ||
1132 | goto out; | 1156 | goto out; |
@@ -1177,6 +1201,10 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1177 | kfree(packet); | 1201 | kfree(packet); |
1178 | } | 1202 | } |
1179 | 1203 | ||
1204 | if (card->helper_allocated) | ||
1205 | kfree(card->helper); | ||
1206 | if (card->firmware_allocated) | ||
1207 | kfree(card->firmware); | ||
1180 | kfree(card); | 1208 | kfree(card); |
1181 | 1209 | ||
1182 | lbs_deb_leave(LBS_DEB_SDIO); | 1210 | lbs_deb_leave(LBS_DEB_SDIO); |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 07ece9d26c63..3ff61063671a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -289,10 +289,13 @@ static int if_usb_probe(struct usb_interface *intf, | |||
289 | } | 289 | } |
290 | 290 | ||
291 | /* Upload firmware */ | 291 | /* Upload firmware */ |
292 | kparam_block_sysfs_write(fw_name); | ||
292 | if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { | 293 | if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { |
294 | kparam_unblock_sysfs_write(fw_name); | ||
293 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); | 295 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); |
294 | goto err_prog_firmware; | 296 | goto err_prog_firmware; |
295 | } | 297 | } |
298 | kparam_unblock_sysfs_write(fw_name); | ||
296 | 299 | ||
297 | if (!(priv = lbs_add_card(cardp, &udev->dev))) | 300 | if (!(priv = lbs_add_card(cardp, &udev->dev))) |
298 | goto err_prog_firmware; | 301 | goto err_prog_firmware; |
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index b172f5d87a3b..41a4f214ade1 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c | |||
@@ -811,12 +811,15 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) | |||
811 | 811 | ||
812 | lbtf_deb_enter(LBTF_DEB_USB); | 812 | lbtf_deb_enter(LBTF_DEB_USB); |
813 | 813 | ||
814 | kparam_block_sysfs_write(fw_name); | ||
814 | ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); | 815 | ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); |
815 | if (ret < 0) { | 816 | if (ret < 0) { |
816 | pr_err("request_firmware() failed with %#x\n", ret); | 817 | pr_err("request_firmware() failed with %#x\n", ret); |
817 | pr_err("firmware %s not found\n", lbtf_fw_name); | 818 | pr_err("firmware %s not found\n", lbtf_fw_name); |
819 | kparam_unblock_sysfs_write(fw_name); | ||
818 | goto done; | 820 | goto done; |
819 | } | 821 | } |
822 | kparam_unblock_sysfs_write(fw_name); | ||
820 | 823 | ||
821 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) | 824 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) |
822 | goto release_fw; | 825 | goto release_fw; |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 71a101fb2e4e..822f8dc26e9c 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -43,8 +43,6 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = { | |||
43 | { PCI_DEVICE(0x1260, 0x3886) }, | 43 | { PCI_DEVICE(0x1260, 0x3886) }, |
44 | /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ | 44 | /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ |
45 | { PCI_DEVICE(0x1260, 0xffff) }, | 45 | { PCI_DEVICE(0x1260, 0xffff) }, |
46 | /* Standard Microsystems Corp SMC2802W Wireless PCI */ | ||
47 | { PCI_DEVICE(0x10b8, 0x2802) }, | ||
48 | { }, | 46 | { }, |
49 | }; | 47 | }; |
50 | 48 | ||
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index b2c2f391b29d..ecbbb688eba0 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c | |||
@@ -1086,7 +1086,7 @@ static void xemaclite_remove_ndev(struct net_device *ndev) | |||
1086 | * | 1086 | * |
1087 | * Return: Value of the parameter if the parameter is found, or 0 otherwise | 1087 | * Return: Value of the parameter if the parameter is found, or 0 otherwise |
1088 | */ | 1088 | */ |
1089 | static bool get_bool(struct of_device *ofdev, const char *s) | 1089 | static bool get_bool(struct platform_device *ofdev, const char *s) |
1090 | { | 1090 | { |
1091 | u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL); | 1091 | u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL); |
1092 | 1092 | ||
@@ -1115,7 +1115,7 @@ static struct net_device_ops xemaclite_netdev_ops; | |||
1115 | * Return: 0, if the driver is bound to the Emaclite device, or | 1115 | * Return: 0, if the driver is bound to the Emaclite device, or |
1116 | * a negative error if there is failure. | 1116 | * a negative error if there is failure. |
1117 | */ | 1117 | */ |
1118 | static int __devinit xemaclite_of_probe(struct of_device *ofdev, | 1118 | static int __devinit xemaclite_of_probe(struct platform_device *ofdev, |
1119 | const struct of_device_id *match) | 1119 | const struct of_device_id *match) |
1120 | { | 1120 | { |
1121 | struct resource r_irq; /* Interrupt resources */ | 1121 | struct resource r_irq; /* Interrupt resources */ |
@@ -1240,7 +1240,7 @@ error2: | |||
1240 | * | 1240 | * |
1241 | * Return: 0, always. | 1241 | * Return: 0, always. |
1242 | */ | 1242 | */ |
1243 | static int __devexit xemaclite_of_remove(struct of_device *of_dev) | 1243 | static int __devexit xemaclite_of_remove(struct platform_device *of_dev) |
1244 | { | 1244 | { |
1245 | struct device *dev = &of_dev->dev; | 1245 | struct device *dev = &of_dev->dev; |
1246 | struct net_device *ndev = dev_get_drvdata(dev); | 1246 | struct net_device *ndev = dev_get_drvdata(dev); |
diff --git a/drivers/of/device.c b/drivers/of/device.c index 0d8a0644f540..92de0eb74aea 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * @ids: array of of device match structures to search in | 14 | * @ids: array of of device match structures to search in |
15 | * @dev: the of device structure to match against | 15 | * @dev: the of device structure to match against |
16 | * | 16 | * |
17 | * Used by a driver to check whether an of_device present in the | 17 | * Used by a driver to check whether an platform_device present in the |
18 | * system is in its list of supported devices. | 18 | * system is in its list of supported devices. |
19 | */ | 19 | */ |
20 | const struct of_device_id *of_match_device(const struct of_device_id *matches, | 20 | const struct of_device_id *of_match_device(const struct of_device_id *matches, |
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 40e208d130f5..f01e26440f11 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c | |||
@@ -342,7 +342,6 @@ static int __devinit parport_register (struct pci_dev *dev, | |||
342 | dev_dbg(&dev->dev, | 342 | dev_dbg(&dev->dev, |
343 | "PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n", | 343 | "PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n", |
344 | io_lo, io_hi, irq); | 344 | io_lo, io_hi, irq); |
345 | irq = PARPORT_IRQ_NONE; | ||
346 | } | 345 | } |
347 | port = parport_pc_probe_port (io_lo, io_hi, irq, | 346 | port = parport_pc_probe_port (io_lo, io_hi, irq, |
348 | PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED); | 347 | PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED); |
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 210a6441a066..55ba118f1cf1 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c | |||
@@ -286,7 +286,7 @@ static struct parport_operations parport_sunbpp_ops = | |||
286 | .owner = THIS_MODULE, | 286 | .owner = THIS_MODULE, |
287 | }; | 287 | }; |
288 | 288 | ||
289 | static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match) | 289 | static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match) |
290 | { | 290 | { |
291 | struct parport_operations *ops; | 291 | struct parport_operations *ops; |
292 | struct bpp_regs __iomem *regs; | 292 | struct bpp_regs __iomem *regs; |
@@ -351,7 +351,7 @@ out_unmap: | |||
351 | return err; | 351 | return err; |
352 | } | 352 | } |
353 | 353 | ||
354 | static int __devexit bpp_remove(struct of_device *op) | 354 | static int __devexit bpp_remove(struct platform_device *op) |
355 | { | 355 | { |
356 | struct parport *p = dev_get_drvdata(&op->dev); | 356 | struct parport *p = dev_get_drvdata(&op->dev); |
357 | struct parport_operations *ops = p->ops; | 357 | struct parport_operations *ops = p->ops; |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index c988514eb551..c80a7a6e7698 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -215,7 +215,7 @@ config PCMCIA_PXA2XX | |||
215 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ | 215 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ |
216 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ | 216 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ |
217 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ | 217 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ |
218 | || MACH_VPAC270) | 218 | || MACH_VPAC270 || MACH_BALLOON3) |
219 | select PCMCIA_SOC_COMMON | 219 | select PCMCIA_SOC_COMMON |
220 | help | 220 | help |
221 | Say Y here to include support for the PXA2xx PCMCIA controller | 221 | Say Y here to include support for the PXA2xx PCMCIA controller |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 7a2b1604bf1c..8d9386a22eb3 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -69,6 +69,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o | |||
69 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o | 69 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o |
70 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o | 70 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o |
71 | pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o | 71 | pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o |
72 | pxa2xx-obj-$(CONFIG_MACH_BALLOON3) += pxa2xx_balloon3.o | ||
72 | 73 | ||
73 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) | 74 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) |
74 | 75 | ||
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index f94d8281cfb0..546d3024b6f0 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c | |||
@@ -44,7 +44,7 @@ struct electra_cf_socket { | |||
44 | unsigned present:1; | 44 | unsigned present:1; |
45 | unsigned active:1; | 45 | unsigned active:1; |
46 | 46 | ||
47 | struct of_device *ofdev; | 47 | struct platform_device *ofdev; |
48 | unsigned long mem_phys; | 48 | unsigned long mem_phys; |
49 | void __iomem * mem_base; | 49 | void __iomem * mem_base; |
50 | unsigned long mem_size; | 50 | unsigned long mem_size; |
@@ -181,7 +181,7 @@ static struct pccard_operations electra_cf_ops = { | |||
181 | .set_mem_map = electra_cf_set_mem_map, | 181 | .set_mem_map = electra_cf_set_mem_map, |
182 | }; | 182 | }; |
183 | 183 | ||
184 | static int __devinit electra_cf_probe(struct of_device *ofdev, | 184 | static int __devinit electra_cf_probe(struct platform_device *ofdev, |
185 | const struct of_device_id *match) | 185 | const struct of_device_id *match) |
186 | { | 186 | { |
187 | struct device *device = &ofdev->dev; | 187 | struct device *device = &ofdev->dev; |
@@ -325,7 +325,7 @@ fail1: | |||
325 | 325 | ||
326 | } | 326 | } |
327 | 327 | ||
328 | static int __devexit electra_cf_remove(struct of_device *ofdev) | 328 | static int __devexit electra_cf_remove(struct platform_device *ofdev) |
329 | { | 329 | { |
330 | struct device *device = &ofdev->dev; | 330 | struct device *device = &ofdev->dev; |
331 | struct electra_cf_socket *cf; | 331 | struct electra_cf_socket *cf; |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index f2f90a7d3e12..f0ecad99ce81 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
@@ -1149,7 +1149,7 @@ static struct pccard_operations m8xx_services = { | |||
1149 | .set_mem_map = m8xx_set_mem_map, | 1149 | .set_mem_map = m8xx_set_mem_map, |
1150 | }; | 1150 | }; |
1151 | 1151 | ||
1152 | static int __init m8xx_probe(struct of_device *ofdev, | 1152 | static int __init m8xx_probe(struct platform_device *ofdev, |
1153 | const struct of_device_id *match) | 1153 | const struct of_device_id *match) |
1154 | { | 1154 | { |
1155 | struct pcmcia_win *w; | 1155 | struct pcmcia_win *w; |
@@ -1249,7 +1249,7 @@ static int __init m8xx_probe(struct of_device *ofdev, | |||
1249 | return 0; | 1249 | return 0; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | static int m8xx_remove(struct of_device *ofdev) | 1252 | static int m8xx_remove(struct platform_device *ofdev) |
1253 | { | 1253 | { |
1254 | u32 m, i; | 1254 | u32 m, i; |
1255 | struct pcmcia_win *w; | 1255 | struct pcmcia_win *w; |
diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c new file mode 100644 index 000000000000..dbbdd0063202 --- /dev/null +++ b/drivers/pcmcia/pxa2xx_balloon3.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * linux/drivers/pcmcia/pxa2xx_balloon3.c | ||
3 | * | ||
4 | * Balloon3 PCMCIA specific routines. | ||
5 | * | ||
6 | * Author: Nick Bane | ||
7 | * Created: June, 2006 | ||
8 | * Copyright: Toby Churchill Ltd | ||
9 | * Derived from pxa2xx_mainstone.c, by Nico Pitre | ||
10 | * | ||
11 | * Various modification by Marek Vasut <marek.vasut@gmail.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #include <mach/balloon3.h> | ||
27 | |||
28 | #include "soc_common.h" | ||
29 | |||
30 | /* | ||
31 | * These are a list of interrupt sources that provokes a polled | ||
32 | * check of status | ||
33 | */ | ||
34 | static struct pcmcia_irqs irqs[] = { | ||
35 | { 0, BALLOON3_S0_CD_IRQ, "PCMCIA0 CD" }, | ||
36 | { 0, BALLOON3_BP_NSTSCHG_IRQ, "PCMCIA0 STSCHG" }, | ||
37 | }; | ||
38 | |||
39 | static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | ||
40 | { | ||
41 | uint16_t ver; | ||
42 | int ret; | ||
43 | static void __iomem *fpga_ver; | ||
44 | |||
45 | ver = __raw_readw(BALLOON3_FPGA_VER); | ||
46 | if (ver > 0x0201) | ||
47 | pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. " | ||
48 | "PCMCIA/CF support might be broken in this version!", | ||
49 | ver); | ||
50 | |||
51 | skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ; | ||
52 | return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
53 | } | ||
54 | |||
55 | static void balloon3_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | ||
56 | { | ||
57 | soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
58 | } | ||
59 | |||
60 | static unsigned long balloon3_pcmcia_status[2] = { | ||
61 | BALLOON3_CF_nSTSCHG_BVD1, | ||
62 | BALLOON3_CF_nSTSCHG_BVD1 | ||
63 | }; | ||
64 | |||
65 | static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | ||
66 | struct pcmcia_state *state) | ||
67 | { | ||
68 | uint16_t status; | ||
69 | int flip; | ||
70 | |||
71 | /* This actually reads the STATUS register */ | ||
72 | status = __raw_readw(BALLOON3_CF_STATUS_REG); | ||
73 | flip = (status ^ balloon3_pcmcia_status[skt->nr]) | ||
74 | & BALLOON3_CF_nSTSCHG_BVD1; | ||
75 | /* | ||
76 | * Workaround for STSCHG which can't be deasserted: | ||
77 | * We therefore disable/enable corresponding IRQs | ||
78 | * as needed to avoid IRQ locks. | ||
79 | */ | ||
80 | if (flip) { | ||
81 | balloon3_pcmcia_status[skt->nr] = status; | ||
82 | if (status & BALLOON3_CF_nSTSCHG_BVD1) | ||
83 | enable_irq(BALLOON3_BP_NSTSCHG_IRQ); | ||
84 | else | ||
85 | disable_irq(BALLOON3_BP_NSTSCHG_IRQ); | ||
86 | } | ||
87 | |||
88 | state->detect = !gpio_get_value(BALLOON3_GPIO_S0_CD); | ||
89 | state->ready = !!(status & BALLOON3_CF_nIRQ); | ||
90 | state->bvd1 = !!(status & BALLOON3_CF_nSTSCHG_BVD1); | ||
91 | state->bvd2 = 0; /* not available */ | ||
92 | state->vs_3v = 1; /* Always true its a CF card */ | ||
93 | state->vs_Xv = 0; /* not available */ | ||
94 | state->wrprot = 0; /* not available */ | ||
95 | } | ||
96 | |||
97 | static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | ||
98 | const socket_state_t *state) | ||
99 | { | ||
100 | __raw_writew((state->flags & SS_RESET) ? BALLOON3_CF_RESET : 0, | ||
101 | BALLOON3_CF_CONTROL_REG); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static void balloon3_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | ||
106 | { | ||
107 | } | ||
108 | |||
109 | static void balloon3_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | ||
110 | { | ||
111 | } | ||
112 | |||
113 | static struct pcmcia_low_level balloon3_pcmcia_ops = { | ||
114 | .owner = THIS_MODULE, | ||
115 | .hw_init = balloon3_pcmcia_hw_init, | ||
116 | .hw_shutdown = balloon3_pcmcia_hw_shutdown, | ||
117 | .socket_state = balloon3_pcmcia_socket_state, | ||
118 | .configure_socket = balloon3_pcmcia_configure_socket, | ||
119 | .socket_init = balloon3_pcmcia_socket_init, | ||
120 | .socket_suspend = balloon3_pcmcia_socket_suspend, | ||
121 | .first = 0, | ||
122 | .nr = 1, | ||
123 | }; | ||
124 | |||
125 | static struct platform_device *balloon3_pcmcia_device; | ||
126 | |||
127 | static int __init balloon3_pcmcia_init(void) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | ||
132 | if (!balloon3_pcmcia_device) | ||
133 | return -ENOMEM; | ||
134 | |||
135 | ret = platform_device_add_data(balloon3_pcmcia_device, | ||
136 | &balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops)); | ||
137 | |||
138 | if (!ret) | ||
139 | ret = platform_device_add(balloon3_pcmcia_device); | ||
140 | |||
141 | if (ret) | ||
142 | platform_device_put(balloon3_pcmcia_device); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static void __exit balloon3_pcmcia_exit(void) | ||
148 | { | ||
149 | platform_device_unregister(balloon3_pcmcia_device); | ||
150 | } | ||
151 | |||
152 | module_init(balloon3_pcmcia_init); | ||
153 | module_exit(balloon3_pcmcia_exit); | ||
154 | |||
155 | MODULE_LICENSE("GPL"); | ||
156 | MODULE_AUTHOR("Nick Bane <nick@cecomputing.co.uk>"); | ||
157 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
158 | MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver"); | ||
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 1e5506be39b4..07343568a12e 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -136,6 +136,12 @@ config BATTERY_Z2 | |||
136 | help | 136 | help |
137 | Say Y to include support for the battery on the Zipit Z2. | 137 | Say Y to include support for the battery on the Zipit Z2. |
138 | 138 | ||
139 | config BATTERY_S3C_ADC | ||
140 | tristate "Battery driver for Samsung ADC based monitoring" | ||
141 | depends on S3C_ADC | ||
142 | help | ||
143 | Say Y here to enable support for iPAQ h1930/h1940/rx1950 battery | ||
144 | |||
139 | config CHARGER_PCF50633 | 145 | config CHARGER_PCF50633 |
140 | tristate "NXP PCF50633 MBC" | 146 | tristate "NXP PCF50633 MBC" |
141 | depends on MFD_PCF50633 | 147 | depends on MFD_PCF50633 |
@@ -153,4 +159,11 @@ config BATTERY_JZ4740 | |||
153 | This driver can be build as a module. If so, the module will be | 159 | This driver can be build as a module. If so, the module will be |
154 | called jz4740-battery. | 160 | called jz4740-battery. |
155 | 161 | ||
162 | config BATTERY_INTEL_MID | ||
163 | tristate "Battery driver for Intel MID platforms" | ||
164 | depends on INTEL_SCU_IPC && SPI | ||
165 | help | ||
166 | Say Y here to enable the battery driver on Intel MID | ||
167 | platforms. | ||
168 | |||
156 | endif # POWER_SUPPLY | 169 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index cf95009d9bcd..10143aaf4ee3 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -33,5 +33,7 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o | |||
33 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o | 33 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o |
34 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o | 34 | obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o |
35 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o | 35 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o |
36 | obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o | ||
36 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | 37 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o |
37 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 38 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
39 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | ||
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c new file mode 100644 index 000000000000..c61ffec2ff10 --- /dev/null +++ b/drivers/power/intel_mid_battery.c | |||
@@ -0,0 +1,799 @@ | |||
1 | /* | ||
2 | * intel_mid_battery.c - Intel MID PMIC Battery Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Intel Corporation | ||
5 | * | ||
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 as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * | ||
21 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
22 | * Author: Nithish Mahalingam <nithish.mahalingam@intel.com> | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | #include <linux/jiffies.h> | ||
31 | #include <linux/param.h> | ||
32 | #include <linux/device.h> | ||
33 | #include <linux/spi/spi.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/power_supply.h> | ||
36 | |||
37 | #include <asm/intel_scu_ipc.h> | ||
38 | |||
39 | #define DRIVER_NAME "pmic_battery" | ||
40 | |||
41 | /********************************************************************* | ||
42 | * Generic defines | ||
43 | *********************************************************************/ | ||
44 | |||
45 | static int debug; | ||
46 | module_param(debug, int, 0444); | ||
47 | MODULE_PARM_DESC(debug, "Flag to enable PMIC Battery debug messages."); | ||
48 | |||
49 | #define PMIC_BATT_DRV_INFO_UPDATED 1 | ||
50 | #define PMIC_BATT_PRESENT 1 | ||
51 | #define PMIC_BATT_NOT_PRESENT 0 | ||
52 | #define PMIC_USB_PRESENT PMIC_BATT_PRESENT | ||
53 | #define PMIC_USB_NOT_PRESENT PMIC_BATT_NOT_PRESENT | ||
54 | |||
55 | /* pmic battery register related */ | ||
56 | #define PMIC_BATT_CHR_SCHRGINT_ADDR 0xD2 | ||
57 | #define PMIC_BATT_CHR_SBATOVP_MASK (1 << 1) | ||
58 | #define PMIC_BATT_CHR_STEMP_MASK (1 << 2) | ||
59 | #define PMIC_BATT_CHR_SCOMP_MASK (1 << 3) | ||
60 | #define PMIC_BATT_CHR_SUSBDET_MASK (1 << 4) | ||
61 | #define PMIC_BATT_CHR_SBATDET_MASK (1 << 5) | ||
62 | #define PMIC_BATT_CHR_SDCLMT_MASK (1 << 6) | ||
63 | #define PMIC_BATT_CHR_SUSBOVP_MASK (1 << 7) | ||
64 | #define PMIC_BATT_CHR_EXCPT_MASK 0xC6 | ||
65 | #define PMIC_BATT_ADC_ACCCHRG_MASK (1 << 31) | ||
66 | #define PMIC_BATT_ADC_ACCCHRGVAL_MASK 0x7FFFFFFF | ||
67 | |||
68 | /* pmic ipc related */ | ||
69 | #define PMIC_BATT_CHR_IPC_FCHRG_SUBID 0x4 | ||
70 | #define PMIC_BATT_CHR_IPC_TCHRG_SUBID 0x6 | ||
71 | |||
72 | /* types of battery charging */ | ||
73 | enum batt_charge_type { | ||
74 | BATT_USBOTG_500MA_CHARGE, | ||
75 | BATT_USBOTG_TRICKLE_CHARGE, | ||
76 | }; | ||
77 | |||
78 | /* valid battery events */ | ||
79 | enum batt_event { | ||
80 | BATT_EVENT_BATOVP_EXCPT, | ||
81 | BATT_EVENT_USBOVP_EXCPT, | ||
82 | BATT_EVENT_TEMP_EXCPT, | ||
83 | BATT_EVENT_DCLMT_EXCPT, | ||
84 | BATT_EVENT_EXCPT | ||
85 | }; | ||
86 | |||
87 | |||
88 | /********************************************************************* | ||
89 | * Battery properties | ||
90 | *********************************************************************/ | ||
91 | |||
92 | /* | ||
93 | * pmic battery info | ||
94 | */ | ||
95 | struct pmic_power_module_info { | ||
96 | bool is_dev_info_updated; | ||
97 | struct device *dev; | ||
98 | /* pmic battery data */ | ||
99 | unsigned long update_time; /* jiffies when data read */ | ||
100 | unsigned int usb_is_present; | ||
101 | unsigned int batt_is_present; | ||
102 | unsigned int batt_health; | ||
103 | unsigned int usb_health; | ||
104 | unsigned int batt_status; | ||
105 | unsigned int batt_charge_now; /* in mAS */ | ||
106 | unsigned int batt_prev_charge_full; /* in mAS */ | ||
107 | unsigned int batt_charge_rate; /* in units per second */ | ||
108 | |||
109 | struct power_supply usb; | ||
110 | struct power_supply batt; | ||
111 | int irq; /* GPE_ID or IRQ# */ | ||
112 | struct workqueue_struct *monitor_wqueue; | ||
113 | struct delayed_work monitor_battery; | ||
114 | struct work_struct handler; | ||
115 | }; | ||
116 | |||
117 | static unsigned int delay_time = 2000; /* in ms */ | ||
118 | |||
119 | /* | ||
120 | * pmic ac properties | ||
121 | */ | ||
122 | static enum power_supply_property pmic_usb_props[] = { | ||
123 | POWER_SUPPLY_PROP_PRESENT, | ||
124 | POWER_SUPPLY_PROP_HEALTH, | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * pmic battery properties | ||
129 | */ | ||
130 | static enum power_supply_property pmic_battery_props[] = { | ||
131 | POWER_SUPPLY_PROP_STATUS, | ||
132 | POWER_SUPPLY_PROP_HEALTH, | ||
133 | POWER_SUPPLY_PROP_PRESENT, | ||
134 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
135 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
136 | }; | ||
137 | |||
138 | |||
139 | /* | ||
140 | * Glue functions for talking to the IPC | ||
141 | */ | ||
142 | |||
143 | struct battery_property { | ||
144 | u32 capacity; /* Charger capacity */ | ||
145 | u8 crnt; /* Quick charge current value*/ | ||
146 | u8 volt; /* Fine adjustment of constant charge voltage */ | ||
147 | u8 prot; /* CHRGPROT register value */ | ||
148 | u8 prot2; /* CHRGPROT1 register value */ | ||
149 | u8 timer; /* Charging timer */ | ||
150 | }; | ||
151 | |||
152 | #define IPCMSG_BATTERY 0xEF | ||
153 | |||
154 | /* Battery coulomb counter accumulator commands */ | ||
155 | #define IPC_CMD_CC_WR 0 /* Update coulomb counter value */ | ||
156 | #define IPC_CMD_CC_RD 1 /* Read coulomb counter value */ | ||
157 | #define IPC_CMD_BATTERY_PROPERTY 2 /* Read Battery property */ | ||
158 | |||
159 | /** | ||
160 | * pmic_scu_ipc_battery_cc_read - read battery cc | ||
161 | * @value: battery coulomb counter read | ||
162 | * | ||
163 | * Reads the battery couloumb counter value, returns 0 on success, or | ||
164 | * an error code | ||
165 | * | ||
166 | * This function may sleep. Locking for SCU accesses is handled for | ||
167 | * the caller. | ||
168 | */ | ||
169 | static int pmic_scu_ipc_battery_cc_read(u32 *value) | ||
170 | { | ||
171 | return intel_scu_ipc_command(IPCMSG_BATTERY, IPC_CMD_CC_RD, | ||
172 | NULL, 0, value, 1); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * pmic_scu_ipc_battery_property_get - fetch properties | ||
177 | * @prop: battery properties | ||
178 | * | ||
179 | * Retrieve the battery properties from the power management | ||
180 | * | ||
181 | * This function may sleep. Locking for SCU accesses is handled for | ||
182 | * the caller. | ||
183 | */ | ||
184 | static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) | ||
185 | { | ||
186 | u32 data[3]; | ||
187 | u8 *p = (u8 *)&data[1]; | ||
188 | int err = intel_scu_ipc_command(IPC_CMD_BATTERY_PROPERTY, | ||
189 | IPCMSG_BATTERY, NULL, 0, data, 3); | ||
190 | |||
191 | prop->capacity = data[0]; | ||
192 | prop->crnt = *p++; | ||
193 | prop->volt = *p++; | ||
194 | prop->prot = *p++; | ||
195 | prop->prot2 = *p++; | ||
196 | prop->timer = *p++; | ||
197 | |||
198 | return err; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * pmic_scu_ipc_set_charger - set charger | ||
203 | * @charger: charger to select | ||
204 | * | ||
205 | * Switch the charging mode for the SCU | ||
206 | */ | ||
207 | |||
208 | static int pmic_scu_ipc_set_charger(int charger) | ||
209 | { | ||
210 | return intel_scu_ipc_simple_command(charger, IPCMSG_BATTERY); | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * pmic_battery_log_event - log battery events | ||
215 | * @event: battery event to be logged | ||
216 | * Context: can sleep | ||
217 | * | ||
218 | * There are multiple battery events which may be of interest to users; | ||
219 | * this battery function logs the different battery events onto the | ||
220 | * kernel log messages. | ||
221 | */ | ||
222 | static void pmic_battery_log_event(enum batt_event event) | ||
223 | { | ||
224 | printk(KERN_WARNING "pmic-battery: "); | ||
225 | switch (event) { | ||
226 | case BATT_EVENT_BATOVP_EXCPT: | ||
227 | printk(KERN_CONT "battery overvoltage condition\n"); | ||
228 | break; | ||
229 | case BATT_EVENT_USBOVP_EXCPT: | ||
230 | printk(KERN_CONT "usb charger overvoltage condition\n"); | ||
231 | break; | ||
232 | case BATT_EVENT_TEMP_EXCPT: | ||
233 | printk(KERN_CONT "high battery temperature condition\n"); | ||
234 | break; | ||
235 | case BATT_EVENT_DCLMT_EXCPT: | ||
236 | printk(KERN_CONT "over battery charge current condition\n"); | ||
237 | break; | ||
238 | default: | ||
239 | printk(KERN_CONT "charger/battery exception %d\n", event); | ||
240 | break; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * pmic_battery_read_status - read battery status information | ||
246 | * @pbi: device info structure to update the read information | ||
247 | * Context: can sleep | ||
248 | * | ||
249 | * PMIC power source information need to be updated based on the data read | ||
250 | * from the PMIC battery registers. | ||
251 | * | ||
252 | */ | ||
253 | static void pmic_battery_read_status(struct pmic_power_module_info *pbi) | ||
254 | { | ||
255 | unsigned int update_time_intrvl; | ||
256 | unsigned int chrg_val; | ||
257 | u32 ccval; | ||
258 | u8 r8; | ||
259 | struct battery_property batt_prop; | ||
260 | int batt_present = 0; | ||
261 | int usb_present = 0; | ||
262 | int batt_exception = 0; | ||
263 | |||
264 | /* make sure the last batt_status read happened delay_time before */ | ||
265 | if (pbi->update_time && time_before(jiffies, pbi->update_time + | ||
266 | msecs_to_jiffies(delay_time))) | ||
267 | return; | ||
268 | |||
269 | update_time_intrvl = jiffies_to_msecs(jiffies - pbi->update_time); | ||
270 | pbi->update_time = jiffies; | ||
271 | |||
272 | /* read coulomb counter registers and schrgint register */ | ||
273 | if (pmic_scu_ipc_battery_cc_read(&ccval)) { | ||
274 | dev_warn(pbi->dev, "%s(): ipc config cmd failed\n", | ||
275 | __func__); | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) { | ||
280 | dev_warn(pbi->dev, "%s(): ipc pmic read failed\n", | ||
281 | __func__); | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * set pmic_power_module_info members based on pmic register values | ||
287 | * read. | ||
288 | */ | ||
289 | |||
290 | /* set batt_is_present */ | ||
291 | if (r8 & PMIC_BATT_CHR_SBATDET_MASK) { | ||
292 | pbi->batt_is_present = PMIC_BATT_PRESENT; | ||
293 | batt_present = 1; | ||
294 | } else { | ||
295 | pbi->batt_is_present = PMIC_BATT_NOT_PRESENT; | ||
296 | pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
297 | pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
298 | } | ||
299 | |||
300 | /* set batt_health */ | ||
301 | if (batt_present) { | ||
302 | if (r8 & PMIC_BATT_CHR_SBATOVP_MASK) { | ||
303 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
304 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
305 | pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT); | ||
306 | batt_exception = 1; | ||
307 | } else if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { | ||
308 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
309 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
310 | pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); | ||
311 | batt_exception = 1; | ||
312 | } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) { | ||
313 | pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
314 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
315 | pmic_battery_log_event(BATT_EVENT_TEMP_EXCPT); | ||
316 | batt_exception = 1; | ||
317 | } else { | ||
318 | pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* set usb_is_present */ | ||
323 | if (r8 & PMIC_BATT_CHR_SUSBDET_MASK) { | ||
324 | pbi->usb_is_present = PMIC_USB_PRESENT; | ||
325 | usb_present = 1; | ||
326 | } else { | ||
327 | pbi->usb_is_present = PMIC_USB_NOT_PRESENT; | ||
328 | pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
329 | } | ||
330 | |||
331 | if (usb_present) { | ||
332 | if (r8 & PMIC_BATT_CHR_SUSBOVP_MASK) { | ||
333 | pbi->usb_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
334 | pmic_battery_log_event(BATT_EVENT_USBOVP_EXCPT); | ||
335 | } else { | ||
336 | pbi->usb_health = POWER_SUPPLY_HEALTH_GOOD; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | chrg_val = ccval & PMIC_BATT_ADC_ACCCHRGVAL_MASK; | ||
341 | |||
342 | /* set batt_prev_charge_full to battery capacity the first time */ | ||
343 | if (!pbi->is_dev_info_updated) { | ||
344 | if (pmic_scu_ipc_battery_property_get(&batt_prop)) { | ||
345 | dev_warn(pbi->dev, "%s(): ipc config cmd failed\n", | ||
346 | __func__); | ||
347 | return; | ||
348 | } | ||
349 | pbi->batt_prev_charge_full = batt_prop.capacity; | ||
350 | } | ||
351 | |||
352 | /* set batt_status */ | ||
353 | if (batt_present && !batt_exception) { | ||
354 | if (r8 & PMIC_BATT_CHR_SCOMP_MASK) { | ||
355 | pbi->batt_status = POWER_SUPPLY_STATUS_FULL; | ||
356 | pbi->batt_prev_charge_full = chrg_val; | ||
357 | } else if (ccval & PMIC_BATT_ADC_ACCCHRG_MASK) { | ||
358 | pbi->batt_status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
359 | } else { | ||
360 | pbi->batt_status = POWER_SUPPLY_STATUS_CHARGING; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | /* set batt_charge_rate */ | ||
365 | if (pbi->is_dev_info_updated && batt_present && !batt_exception) { | ||
366 | if (pbi->batt_status == POWER_SUPPLY_STATUS_DISCHARGING) { | ||
367 | if (pbi->batt_charge_now - chrg_val) { | ||
368 | pbi->batt_charge_rate = ((pbi->batt_charge_now - | ||
369 | chrg_val) * 1000 * 60) / | ||
370 | update_time_intrvl; | ||
371 | } | ||
372 | } else if (pbi->batt_status == POWER_SUPPLY_STATUS_CHARGING) { | ||
373 | if (chrg_val - pbi->batt_charge_now) { | ||
374 | pbi->batt_charge_rate = ((chrg_val - | ||
375 | pbi->batt_charge_now) * 1000 * 60) / | ||
376 | update_time_intrvl; | ||
377 | } | ||
378 | } else | ||
379 | pbi->batt_charge_rate = 0; | ||
380 | } else { | ||
381 | pbi->batt_charge_rate = -1; | ||
382 | } | ||
383 | |||
384 | /* batt_charge_now */ | ||
385 | if (batt_present && !batt_exception) | ||
386 | pbi->batt_charge_now = chrg_val; | ||
387 | else | ||
388 | pbi->batt_charge_now = -1; | ||
389 | |||
390 | pbi->is_dev_info_updated = PMIC_BATT_DRV_INFO_UPDATED; | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * pmic_usb_get_property - usb power source get property | ||
395 | * @psy: usb power supply context | ||
396 | * @psp: usb power source property | ||
397 | * @val: usb power source property value | ||
398 | * Context: can sleep | ||
399 | * | ||
400 | * PMIC usb power source property needs to be provided to power_supply | ||
401 | * subsytem for it to provide the information to users. | ||
402 | */ | ||
403 | static int pmic_usb_get_property(struct power_supply *psy, | ||
404 | enum power_supply_property psp, | ||
405 | union power_supply_propval *val) | ||
406 | { | ||
407 | struct pmic_power_module_info *pbi = container_of(psy, | ||
408 | struct pmic_power_module_info, usb); | ||
409 | |||
410 | /* update pmic_power_module_info members */ | ||
411 | pmic_battery_read_status(pbi); | ||
412 | |||
413 | switch (psp) { | ||
414 | case POWER_SUPPLY_PROP_PRESENT: | ||
415 | val->intval = pbi->usb_is_present; | ||
416 | break; | ||
417 | case POWER_SUPPLY_PROP_HEALTH: | ||
418 | val->intval = pbi->usb_health; | ||
419 | break; | ||
420 | default: | ||
421 | return -EINVAL; | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static inline unsigned long mAStouAh(unsigned long v) | ||
428 | { | ||
429 | /* seconds to hours, mA to µA */ | ||
430 | return (v * 1000) / 3600; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * pmic_battery_get_property - battery power source get property | ||
435 | * @psy: battery power supply context | ||
436 | * @psp: battery power source property | ||
437 | * @val: battery power source property value | ||
438 | * Context: can sleep | ||
439 | * | ||
440 | * PMIC battery power source property needs to be provided to power_supply | ||
441 | * subsytem for it to provide the information to users. | ||
442 | */ | ||
443 | static int pmic_battery_get_property(struct power_supply *psy, | ||
444 | enum power_supply_property psp, | ||
445 | union power_supply_propval *val) | ||
446 | { | ||
447 | struct pmic_power_module_info *pbi = container_of(psy, | ||
448 | struct pmic_power_module_info, batt); | ||
449 | |||
450 | /* update pmic_power_module_info members */ | ||
451 | pmic_battery_read_status(pbi); | ||
452 | |||
453 | switch (psp) { | ||
454 | case POWER_SUPPLY_PROP_STATUS: | ||
455 | val->intval = pbi->batt_status; | ||
456 | break; | ||
457 | case POWER_SUPPLY_PROP_HEALTH: | ||
458 | val->intval = pbi->batt_health; | ||
459 | break; | ||
460 | case POWER_SUPPLY_PROP_PRESENT: | ||
461 | val->intval = pbi->batt_is_present; | ||
462 | break; | ||
463 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
464 | val->intval = mAStouAh(pbi->batt_charge_now); | ||
465 | break; | ||
466 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
467 | val->intval = mAStouAh(pbi->batt_prev_charge_full); | ||
468 | break; | ||
469 | default: | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * pmic_battery_monitor - monitor battery status | ||
478 | * @work: work structure | ||
479 | * Context: can sleep | ||
480 | * | ||
481 | * PMIC battery status needs to be monitored for any change | ||
482 | * and information needs to be frequently updated. | ||
483 | */ | ||
484 | static void pmic_battery_monitor(struct work_struct *work) | ||
485 | { | ||
486 | struct pmic_power_module_info *pbi = container_of(work, | ||
487 | struct pmic_power_module_info, monitor_battery.work); | ||
488 | |||
489 | /* update pmic_power_module_info members */ | ||
490 | pmic_battery_read_status(pbi); | ||
491 | queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 10); | ||
492 | } | ||
493 | |||
494 | /** | ||
495 | * pmic_battery_set_charger - set battery charger | ||
496 | * @pbi: device info structure | ||
497 | * @chrg: charge mode to set battery charger in | ||
498 | * Context: can sleep | ||
499 | * | ||
500 | * PMIC battery charger needs to be enabled based on the usb charge | ||
501 | * capabilities connected to the platform. | ||
502 | */ | ||
503 | static int pmic_battery_set_charger(struct pmic_power_module_info *pbi, | ||
504 | enum batt_charge_type chrg) | ||
505 | { | ||
506 | int retval; | ||
507 | |||
508 | /* set usblmt bits and chrgcntl register bits appropriately */ | ||
509 | switch (chrg) { | ||
510 | case BATT_USBOTG_500MA_CHARGE: | ||
511 | retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_FCHRG_SUBID); | ||
512 | break; | ||
513 | case BATT_USBOTG_TRICKLE_CHARGE: | ||
514 | retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_TCHRG_SUBID); | ||
515 | break; | ||
516 | default: | ||
517 | dev_warn(pbi->dev, "%s(): out of range usb charger " | ||
518 | "charge detected\n", __func__); | ||
519 | return -EINVAL; | ||
520 | } | ||
521 | |||
522 | if (retval) { | ||
523 | dev_warn(pbi->dev, "%s(): ipc pmic read failed\n", | ||
524 | __func__); | ||
525 | return retval;; | ||
526 | } | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | /** | ||
532 | * pmic_battery_interrupt_handler - pmic battery interrupt handler | ||
533 | * Context: interrupt context | ||
534 | * | ||
535 | * PMIC battery interrupt handler which will be called with either | ||
536 | * battery full condition occurs or usb otg & battery connect | ||
537 | * condition occurs. | ||
538 | */ | ||
539 | static irqreturn_t pmic_battery_interrupt_handler(int id, void *dev) | ||
540 | { | ||
541 | struct pmic_power_module_info *pbi = dev; | ||
542 | |||
543 | schedule_work(&pbi->handler); | ||
544 | |||
545 | return IRQ_HANDLED; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * pmic_battery_handle_intrpt - pmic battery service interrupt | ||
550 | * @work: work structure | ||
551 | * Context: can sleep | ||
552 | * | ||
553 | * PMIC battery needs to either update the battery status as full | ||
554 | * if it detects battery full condition caused the interrupt or needs | ||
555 | * to enable battery charger if it detects usb and battery detect | ||
556 | * caused the source of interrupt. | ||
557 | */ | ||
558 | static void pmic_battery_handle_intrpt(struct work_struct *work) | ||
559 | { | ||
560 | struct pmic_power_module_info *pbi = container_of(work, | ||
561 | struct pmic_power_module_info, handler); | ||
562 | enum batt_charge_type chrg; | ||
563 | u8 r8; | ||
564 | |||
565 | if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) { | ||
566 | dev_warn(pbi->dev, "%s(): ipc pmic read failed\n", | ||
567 | __func__); | ||
568 | return; | ||
569 | } | ||
570 | /* find the cause of the interrupt */ | ||
571 | if (r8 & PMIC_BATT_CHR_SBATDET_MASK) { | ||
572 | pbi->batt_is_present = PMIC_BATT_PRESENT; | ||
573 | } else { | ||
574 | pbi->batt_is_present = PMIC_BATT_NOT_PRESENT; | ||
575 | pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
576 | pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN; | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | if (r8 & PMIC_BATT_CHR_EXCPT_MASK) { | ||
581 | pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
582 | pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
583 | pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
584 | pmic_battery_log_event(BATT_EVENT_EXCPT); | ||
585 | return; | ||
586 | } else { | ||
587 | pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; | ||
588 | pbi->usb_health = POWER_SUPPLY_HEALTH_GOOD; | ||
589 | } | ||
590 | |||
591 | if (r8 & PMIC_BATT_CHR_SCOMP_MASK) { | ||
592 | u32 ccval; | ||
593 | pbi->batt_status = POWER_SUPPLY_STATUS_FULL; | ||
594 | |||
595 | if (pmic_scu_ipc_battery_cc_read(&ccval)) { | ||
596 | dev_warn(pbi->dev, "%s(): ipc config cmd " | ||
597 | "failed\n", __func__); | ||
598 | return; | ||
599 | } | ||
600 | pbi->batt_prev_charge_full = ccval & | ||
601 | PMIC_BATT_ADC_ACCCHRGVAL_MASK; | ||
602 | return; | ||
603 | } | ||
604 | |||
605 | if (r8 & PMIC_BATT_CHR_SUSBDET_MASK) { | ||
606 | pbi->usb_is_present = PMIC_USB_PRESENT; | ||
607 | } else { | ||
608 | pbi->usb_is_present = PMIC_USB_NOT_PRESENT; | ||
609 | pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | /* setup battery charging */ | ||
614 | |||
615 | #if 0 | ||
616 | /* check usb otg power capability and set charger accordingly */ | ||
617 | retval = langwell_udc_maxpower(&power); | ||
618 | if (retval) { | ||
619 | dev_warn(pbi->dev, | ||
620 | "%s(): usb otg power query failed with error code %d\n", | ||
621 | __func__, retval); | ||
622 | return; | ||
623 | } | ||
624 | |||
625 | if (power >= 500) | ||
626 | chrg = BATT_USBOTG_500MA_CHARGE; | ||
627 | else | ||
628 | #endif | ||
629 | chrg = BATT_USBOTG_TRICKLE_CHARGE; | ||
630 | |||
631 | /* enable battery charging */ | ||
632 | if (pmic_battery_set_charger(pbi, chrg)) { | ||
633 | dev_warn(pbi->dev, | ||
634 | "%s(): failed to set up battery charging\n", __func__); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | dev_dbg(pbi->dev, | ||
639 | "pmic-battery: %s() - setting up battery charger successful\n", | ||
640 | __func__); | ||
641 | } | ||
642 | |||
643 | /** | ||
644 | * pmic_battery_probe - pmic battery initialize | ||
645 | * @irq: pmic battery device irq | ||
646 | * @dev: pmic battery device structure | ||
647 | * Context: can sleep | ||
648 | * | ||
649 | * PMIC battery initializes its internal data structue and other | ||
650 | * infrastructure components for it to work as expected. | ||
651 | */ | ||
652 | static __devinit int probe(int irq, struct device *dev) | ||
653 | { | ||
654 | int retval = 0; | ||
655 | struct pmic_power_module_info *pbi; | ||
656 | |||
657 | dev_dbg(dev, "pmic-battery: found pmic battery device\n"); | ||
658 | |||
659 | pbi = kzalloc(sizeof(*pbi), GFP_KERNEL); | ||
660 | if (!pbi) { | ||
661 | dev_err(dev, "%s(): memory allocation failed\n", | ||
662 | __func__); | ||
663 | return -ENOMEM; | ||
664 | } | ||
665 | |||
666 | pbi->dev = dev; | ||
667 | pbi->irq = irq; | ||
668 | dev_set_drvdata(dev, pbi); | ||
669 | |||
670 | /* initialize all required framework before enabling interrupts */ | ||
671 | INIT_WORK(&pbi->handler, pmic_battery_handle_intrpt); | ||
672 | INIT_DELAYED_WORK(&pbi->monitor_battery, pmic_battery_monitor); | ||
673 | pbi->monitor_wqueue = | ||
674 | create_singlethread_workqueue(dev_name(dev)); | ||
675 | if (!pbi->monitor_wqueue) { | ||
676 | dev_err(dev, "%s(): wqueue init failed\n", __func__); | ||
677 | retval = -ESRCH; | ||
678 | goto wqueue_failed; | ||
679 | } | ||
680 | |||
681 | /* register interrupt */ | ||
682 | retval = request_irq(pbi->irq, pmic_battery_interrupt_handler, | ||
683 | 0, DRIVER_NAME, pbi); | ||
684 | if (retval) { | ||
685 | dev_err(dev, "%s(): cannot get IRQ\n", __func__); | ||
686 | goto requestirq_failed; | ||
687 | } | ||
688 | |||
689 | /* register pmic-batt with power supply subsystem */ | ||
690 | pbi->batt.name = "pmic-batt"; | ||
691 | pbi->batt.type = POWER_SUPPLY_TYPE_BATTERY; | ||
692 | pbi->batt.properties = pmic_battery_props; | ||
693 | pbi->batt.num_properties = ARRAY_SIZE(pmic_battery_props); | ||
694 | pbi->batt.get_property = pmic_battery_get_property; | ||
695 | retval = power_supply_register(dev, &pbi->batt); | ||
696 | if (retval) { | ||
697 | dev_err(dev, | ||
698 | "%s(): failed to register pmic battery device with power supply subsystem\n", | ||
699 | __func__); | ||
700 | goto power_reg_failed; | ||
701 | } | ||
702 | |||
703 | dev_dbg(dev, "pmic-battery: %s() - pmic battery device " | ||
704 | "registration with power supply subsystem successful\n", | ||
705 | __func__); | ||
706 | |||
707 | queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 1); | ||
708 | |||
709 | /* register pmic-usb with power supply subsystem */ | ||
710 | pbi->usb.name = "pmic-usb"; | ||
711 | pbi->usb.type = POWER_SUPPLY_TYPE_USB; | ||
712 | pbi->usb.properties = pmic_usb_props; | ||
713 | pbi->usb.num_properties = ARRAY_SIZE(pmic_usb_props); | ||
714 | pbi->usb.get_property = pmic_usb_get_property; | ||
715 | retval = power_supply_register(dev, &pbi->usb); | ||
716 | if (retval) { | ||
717 | dev_err(dev, | ||
718 | "%s(): failed to register pmic usb device with power supply subsystem\n", | ||
719 | __func__); | ||
720 | goto power_reg_failed_1; | ||
721 | } | ||
722 | |||
723 | if (debug) | ||
724 | printk(KERN_INFO "pmic-battery: %s() - pmic usb device " | ||
725 | "registration with power supply subsystem successful\n", | ||
726 | __func__); | ||
727 | |||
728 | return retval; | ||
729 | |||
730 | power_reg_failed_1: | ||
731 | power_supply_unregister(&pbi->batt); | ||
732 | power_reg_failed: | ||
733 | cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, | ||
734 | &pbi->monitor_battery); | ||
735 | requestirq_failed: | ||
736 | destroy_workqueue(pbi->monitor_wqueue); | ||
737 | wqueue_failed: | ||
738 | kfree(pbi); | ||
739 | |||
740 | return retval; | ||
741 | } | ||
742 | |||
743 | static int __devinit platform_pmic_battery_probe(struct platform_device *pdev) | ||
744 | { | ||
745 | return probe(pdev->id, &pdev->dev); | ||
746 | } | ||
747 | |||
748 | /** | ||
749 | * pmic_battery_remove - pmic battery finalize | ||
750 | * @dev: pmic battery device structure | ||
751 | * Context: can sleep | ||
752 | * | ||
753 | * PMIC battery finalizes its internal data structue and other | ||
754 | * infrastructure components that it initialized in | ||
755 | * pmic_battery_probe. | ||
756 | */ | ||
757 | |||
758 | static int __devexit platform_pmic_battery_remove(struct platform_device *pdev) | ||
759 | { | ||
760 | struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev); | ||
761 | |||
762 | free_irq(pbi->irq, pbi); | ||
763 | cancel_rearming_delayed_workqueue(pbi->monitor_wqueue, | ||
764 | &pbi->monitor_battery); | ||
765 | destroy_workqueue(pbi->monitor_wqueue); | ||
766 | |||
767 | power_supply_unregister(&pbi->usb); | ||
768 | power_supply_unregister(&pbi->batt); | ||
769 | |||
770 | flush_scheduled_work(); | ||
771 | kfree(pbi); | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | static struct platform_driver platform_pmic_battery_driver = { | ||
776 | .driver = { | ||
777 | .name = DRIVER_NAME, | ||
778 | .owner = THIS_MODULE, | ||
779 | }, | ||
780 | .probe = platform_pmic_battery_probe, | ||
781 | .remove = __devexit_p(platform_pmic_battery_remove), | ||
782 | }; | ||
783 | |||
784 | static int __init platform_pmic_battery_module_init(void) | ||
785 | { | ||
786 | return platform_driver_register(&platform_pmic_battery_driver); | ||
787 | } | ||
788 | |||
789 | static void __exit platform_pmic_battery_module_exit(void) | ||
790 | { | ||
791 | platform_driver_unregister(&platform_pmic_battery_driver); | ||
792 | } | ||
793 | |||
794 | module_init(platform_pmic_battery_module_init); | ||
795 | module_exit(platform_pmic_battery_module_exit); | ||
796 | |||
797 | MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>"); | ||
798 | MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver"); | ||
799 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index 5ab9109b69e6..aafc1c506eda 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Battery driver for One Laptop Per Child board. | 2 | * Battery driver for One Laptop Per Child board. |
3 | * | 3 | * |
4 | * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> | 4 | * Copyright © 2006-2010 David Woodhouse <dwmw2@infradead.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 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 | 7 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c new file mode 100644 index 000000000000..fe16b482e912 --- /dev/null +++ b/drivers/power/s3c_adc_battery.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * iPAQ h1930/h1940/rx1950 battery controler driver | ||
3 | * Copyright (c) Vasily Khoruzhick | ||
4 | * Based on h1940_battery.c by Arnaud Patard | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive for | ||
8 | * more details. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/power_supply.h> | ||
15 | #include <linux/leds.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/timer.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/s3c_adc_battery.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/init.h> | ||
23 | |||
24 | #include <plat/adc.h> | ||
25 | |||
26 | #define BAT_POLL_INTERVAL 10000 /* ms */ | ||
27 | #define JITTER_DELAY 500 /* ms */ | ||
28 | |||
29 | struct s3c_adc_bat { | ||
30 | struct power_supply psy; | ||
31 | struct s3c_adc_client *client; | ||
32 | struct s3c_adc_bat_pdata *pdata; | ||
33 | int volt_value; | ||
34 | int cur_value; | ||
35 | unsigned int timestamp; | ||
36 | int level; | ||
37 | int status; | ||
38 | int cable_plugged:1; | ||
39 | }; | ||
40 | |||
41 | static struct delayed_work bat_work; | ||
42 | |||
43 | static void s3c_adc_bat_ext_power_changed(struct power_supply *psy) | ||
44 | { | ||
45 | schedule_delayed_work(&bat_work, | ||
46 | msecs_to_jiffies(JITTER_DELAY)); | ||
47 | } | ||
48 | |||
49 | static enum power_supply_property s3c_adc_backup_bat_props[] = { | ||
50 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
51 | POWER_SUPPLY_PROP_VOLTAGE_MIN, | ||
52 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
53 | }; | ||
54 | |||
55 | static int s3c_adc_backup_bat_get_property(struct power_supply *psy, | ||
56 | enum power_supply_property psp, | ||
57 | union power_supply_propval *val) | ||
58 | { | ||
59 | struct s3c_adc_bat *bat = container_of(psy, struct s3c_adc_bat, psy); | ||
60 | |||
61 | if (!bat) { | ||
62 | dev_err(psy->dev, "%s: no battery infos ?!\n", __func__); | ||
63 | return -EINVAL; | ||
64 | } | ||
65 | |||
66 | if (bat->volt_value < 0 || | ||
67 | jiffies_to_msecs(jiffies - bat->timestamp) > | ||
68 | BAT_POLL_INTERVAL) { | ||
69 | bat->volt_value = s3c_adc_read(bat->client, | ||
70 | bat->pdata->backup_volt_channel); | ||
71 | bat->volt_value *= bat->pdata->backup_volt_mult; | ||
72 | bat->timestamp = jiffies; | ||
73 | } | ||
74 | |||
75 | switch (psp) { | ||
76 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
77 | val->intval = bat->volt_value; | ||
78 | return 0; | ||
79 | case POWER_SUPPLY_PROP_VOLTAGE_MIN: | ||
80 | val->intval = bat->pdata->backup_volt_min; | ||
81 | return 0; | ||
82 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
83 | val->intval = bat->pdata->backup_volt_max; | ||
84 | return 0; | ||
85 | default: | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static struct s3c_adc_bat backup_bat = { | ||
91 | .psy = { | ||
92 | .name = "backup-battery", | ||
93 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
94 | .properties = s3c_adc_backup_bat_props, | ||
95 | .num_properties = ARRAY_SIZE(s3c_adc_backup_bat_props), | ||
96 | .get_property = s3c_adc_backup_bat_get_property, | ||
97 | .use_for_apm = 1, | ||
98 | }, | ||
99 | }; | ||
100 | |||
101 | static enum power_supply_property s3c_adc_main_bat_props[] = { | ||
102 | POWER_SUPPLY_PROP_STATUS, | ||
103 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
104 | POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN, | ||
105 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
106 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
107 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
108 | }; | ||
109 | |||
110 | static int calc_full_volt(int volt_val, int cur_val, int impedance) | ||
111 | { | ||
112 | return volt_val + cur_val * impedance / 1000; | ||
113 | } | ||
114 | |||
115 | static int s3c_adc_bat_get_property(struct power_supply *psy, | ||
116 | enum power_supply_property psp, | ||
117 | union power_supply_propval *val) | ||
118 | { | ||
119 | struct s3c_adc_bat *bat = container_of(psy, struct s3c_adc_bat, psy); | ||
120 | |||
121 | int new_level; | ||
122 | int full_volt; | ||
123 | const struct s3c_adc_bat_thresh *lut = bat->pdata->lut_noac; | ||
124 | unsigned int lut_size = bat->pdata->lut_noac_cnt; | ||
125 | |||
126 | if (!bat) { | ||
127 | dev_err(psy->dev, "no battery infos ?!\n"); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | if (bat->volt_value < 0 || bat->cur_value < 0 || | ||
132 | jiffies_to_msecs(jiffies - bat->timestamp) > | ||
133 | BAT_POLL_INTERVAL) { | ||
134 | bat->volt_value = s3c_adc_read(bat->client, | ||
135 | bat->pdata->volt_channel) * bat->pdata->volt_mult; | ||
136 | bat->cur_value = s3c_adc_read(bat->client, | ||
137 | bat->pdata->current_channel) * bat->pdata->current_mult; | ||
138 | bat->timestamp = jiffies; | ||
139 | } | ||
140 | |||
141 | if (bat->cable_plugged && | ||
142 | ((bat->pdata->gpio_charge_finished < 0) || | ||
143 | !gpio_get_value(bat->pdata->gpio_charge_finished))) { | ||
144 | lut = bat->pdata->lut_acin; | ||
145 | lut_size = bat->pdata->lut_acin_cnt; | ||
146 | } | ||
147 | |||
148 | new_level = 100000; | ||
149 | full_volt = calc_full_volt((bat->volt_value / 1000), | ||
150 | (bat->cur_value / 1000), bat->pdata->internal_impedance); | ||
151 | |||
152 | if (full_volt < calc_full_volt(lut->volt, lut->cur, | ||
153 | bat->pdata->internal_impedance)) { | ||
154 | lut_size--; | ||
155 | while (lut_size--) { | ||
156 | int lut_volt1; | ||
157 | int lut_volt2; | ||
158 | |||
159 | lut_volt1 = calc_full_volt(lut[0].volt, lut[0].cur, | ||
160 | bat->pdata->internal_impedance); | ||
161 | lut_volt2 = calc_full_volt(lut[1].volt, lut[1].cur, | ||
162 | bat->pdata->internal_impedance); | ||
163 | if (full_volt < lut_volt1 && full_volt >= lut_volt2) { | ||
164 | new_level = (lut[1].level + | ||
165 | (lut[0].level - lut[1].level) * | ||
166 | (full_volt - lut_volt2) / | ||
167 | (lut_volt1 - lut_volt2)) * 1000; | ||
168 | break; | ||
169 | } | ||
170 | new_level = lut[1].level * 1000; | ||
171 | lut++; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | bat->level = new_level; | ||
176 | |||
177 | switch (psp) { | ||
178 | case POWER_SUPPLY_PROP_STATUS: | ||
179 | if (bat->pdata->gpio_charge_finished < 0) | ||
180 | val->intval = bat->level == 100000 ? | ||
181 | POWER_SUPPLY_STATUS_FULL : bat->status; | ||
182 | else | ||
183 | val->intval = bat->status; | ||
184 | return 0; | ||
185 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
186 | val->intval = 100000; | ||
187 | return 0; | ||
188 | case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN: | ||
189 | val->intval = 0; | ||
190 | return 0; | ||
191 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
192 | val->intval = bat->level; | ||
193 | return 0; | ||
194 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
195 | val->intval = bat->volt_value; | ||
196 | return 0; | ||
197 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
198 | val->intval = bat->cur_value; | ||
199 | return 0; | ||
200 | default: | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static struct s3c_adc_bat main_bat = { | ||
206 | .psy = { | ||
207 | .name = "main-battery", | ||
208 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
209 | .properties = s3c_adc_main_bat_props, | ||
210 | .num_properties = ARRAY_SIZE(s3c_adc_main_bat_props), | ||
211 | .get_property = s3c_adc_bat_get_property, | ||
212 | .external_power_changed = s3c_adc_bat_ext_power_changed, | ||
213 | .use_for_apm = 1, | ||
214 | }, | ||
215 | }; | ||
216 | |||
217 | static void s3c_adc_bat_work(struct work_struct *work) | ||
218 | { | ||
219 | struct s3c_adc_bat *bat = &main_bat; | ||
220 | int is_charged; | ||
221 | int is_plugged; | ||
222 | static int was_plugged; | ||
223 | |||
224 | is_plugged = power_supply_am_i_supplied(&bat->psy); | ||
225 | bat->cable_plugged = is_plugged; | ||
226 | if (is_plugged != was_plugged) { | ||
227 | was_plugged = is_plugged; | ||
228 | if (is_plugged) { | ||
229 | if (bat->pdata->enable_charger) | ||
230 | bat->pdata->enable_charger(); | ||
231 | bat->status = POWER_SUPPLY_STATUS_CHARGING; | ||
232 | } else { | ||
233 | if (bat->pdata->disable_charger) | ||
234 | bat->pdata->disable_charger(); | ||
235 | bat->status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
236 | } | ||
237 | } else { | ||
238 | if ((bat->pdata->gpio_charge_finished >= 0) && is_plugged) { | ||
239 | is_charged = gpio_get_value( | ||
240 | main_bat.pdata->gpio_charge_finished); | ||
241 | if (is_charged) { | ||
242 | if (bat->pdata->disable_charger) | ||
243 | bat->pdata->disable_charger(); | ||
244 | bat->status = POWER_SUPPLY_STATUS_FULL; | ||
245 | } else { | ||
246 | if (bat->pdata->enable_charger) | ||
247 | bat->pdata->enable_charger(); | ||
248 | bat->status = POWER_SUPPLY_STATUS_CHARGING; | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | power_supply_changed(&bat->psy); | ||
254 | } | ||
255 | |||
256 | static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id) | ||
257 | { | ||
258 | schedule_delayed_work(&bat_work, | ||
259 | msecs_to_jiffies(JITTER_DELAY)); | ||
260 | return IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | static int __init s3c_adc_bat_probe(struct platform_device *pdev) | ||
264 | { | ||
265 | struct s3c_adc_client *client; | ||
266 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
267 | int ret; | ||
268 | |||
269 | client = s3c_adc_register(pdev, NULL, NULL, 0); | ||
270 | if (IS_ERR(client)) { | ||
271 | dev_err(&pdev->dev, "cannot register adc\n"); | ||
272 | return PTR_ERR(client); | ||
273 | } | ||
274 | |||
275 | platform_set_drvdata(pdev, client); | ||
276 | |||
277 | main_bat.client = client; | ||
278 | main_bat.pdata = pdata; | ||
279 | main_bat.volt_value = -1; | ||
280 | main_bat.cur_value = -1; | ||
281 | main_bat.cable_plugged = 0; | ||
282 | main_bat.status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
283 | |||
284 | ret = power_supply_register(&pdev->dev, &main_bat.psy); | ||
285 | if (ret) | ||
286 | goto err_reg_main; | ||
287 | if (pdata->backup_volt_mult) { | ||
288 | backup_bat.client = client; | ||
289 | backup_bat.pdata = pdev->dev.platform_data; | ||
290 | backup_bat.volt_value = -1; | ||
291 | ret = power_supply_register(&pdev->dev, &backup_bat.psy); | ||
292 | if (ret) | ||
293 | goto err_reg_backup; | ||
294 | } | ||
295 | |||
296 | INIT_DELAYED_WORK(&bat_work, s3c_adc_bat_work); | ||
297 | |||
298 | if (pdata->gpio_charge_finished >= 0) { | ||
299 | ret = gpio_request(pdata->gpio_charge_finished, "charged"); | ||
300 | if (ret) | ||
301 | goto err_gpio; | ||
302 | |||
303 | ret = request_irq(gpio_to_irq(pdata->gpio_charge_finished), | ||
304 | s3c_adc_bat_charged, | ||
305 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
306 | "battery charged", NULL); | ||
307 | if (ret) | ||
308 | goto err_irq; | ||
309 | } | ||
310 | |||
311 | if (pdata->init) { | ||
312 | ret = pdata->init(); | ||
313 | if (ret) | ||
314 | goto err_platform; | ||
315 | } | ||
316 | |||
317 | dev_info(&pdev->dev, "successfully loaded\n"); | ||
318 | device_init_wakeup(&pdev->dev, 1); | ||
319 | |||
320 | /* Schedule timer to check current status */ | ||
321 | schedule_delayed_work(&bat_work, | ||
322 | msecs_to_jiffies(JITTER_DELAY)); | ||
323 | |||
324 | return 0; | ||
325 | |||
326 | err_platform: | ||
327 | if (pdata->gpio_charge_finished >= 0) | ||
328 | free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL); | ||
329 | err_irq: | ||
330 | if (pdata->gpio_charge_finished >= 0) | ||
331 | gpio_free(pdata->gpio_charge_finished); | ||
332 | err_gpio: | ||
333 | if (pdata->backup_volt_mult) | ||
334 | power_supply_unregister(&backup_bat.psy); | ||
335 | err_reg_backup: | ||
336 | power_supply_unregister(&main_bat.psy); | ||
337 | err_reg_main: | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static int s3c_adc_bat_remove(struct platform_device *pdev) | ||
342 | { | ||
343 | struct s3c_adc_client *client = platform_get_drvdata(pdev); | ||
344 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
345 | |||
346 | power_supply_unregister(&main_bat.psy); | ||
347 | if (pdata->backup_volt_mult) | ||
348 | power_supply_unregister(&backup_bat.psy); | ||
349 | |||
350 | s3c_adc_release(client); | ||
351 | |||
352 | if (pdata->gpio_charge_finished >= 0) { | ||
353 | free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL); | ||
354 | gpio_free(pdata->gpio_charge_finished); | ||
355 | } | ||
356 | |||
357 | cancel_delayed_work(&bat_work); | ||
358 | |||
359 | if (pdata->exit) | ||
360 | pdata->exit(); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | #ifdef CONFIG_PM | ||
366 | static int s3c_adc_bat_suspend(struct platform_device *pdev, | ||
367 | pm_message_t state) | ||
368 | { | ||
369 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
370 | |||
371 | if (pdata->gpio_charge_finished >= 0) { | ||
372 | if (device_may_wakeup(&pdev->dev)) | ||
373 | enable_irq_wake( | ||
374 | gpio_to_irq(pdata->gpio_charge_finished)); | ||
375 | else { | ||
376 | disable_irq(gpio_to_irq(pdata->gpio_charge_finished)); | ||
377 | main_bat.pdata->disable_charger(); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static int s3c_adc_bat_resume(struct platform_device *pdev) | ||
385 | { | ||
386 | struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; | ||
387 | |||
388 | if (pdata->gpio_charge_finished >= 0) { | ||
389 | if (device_may_wakeup(&pdev->dev)) | ||
390 | disable_irq_wake( | ||
391 | gpio_to_irq(pdata->gpio_charge_finished)); | ||
392 | else | ||
393 | enable_irq(gpio_to_irq(pdata->gpio_charge_finished)); | ||
394 | } | ||
395 | |||
396 | /* Schedule timer to check current status */ | ||
397 | schedule_delayed_work(&bat_work, | ||
398 | msecs_to_jiffies(JITTER_DELAY)); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | #else | ||
403 | #define s3c_adc_battery_suspend NULL | ||
404 | #define s3c_adc_battery_resume NULL | ||
405 | #endif | ||
406 | |||
407 | static struct platform_driver s3c_adc_bat_driver = { | ||
408 | .driver = { | ||
409 | .name = "s3c-adc-battery", | ||
410 | }, | ||
411 | .probe = s3c_adc_bat_probe, | ||
412 | .remove = s3c_adc_bat_remove, | ||
413 | .suspend = s3c_adc_bat_suspend, | ||
414 | .resume = s3c_adc_bat_resume, | ||
415 | }; | ||
416 | |||
417 | static int __init s3c_adc_bat_init(void) | ||
418 | { | ||
419 | return platform_driver_register(&s3c_adc_bat_driver); | ||
420 | } | ||
421 | module_init(s3c_adc_bat_init); | ||
422 | |||
423 | static void __exit s3c_adc_bat_exit(void) | ||
424 | { | ||
425 | platform_driver_unregister(&s3c_adc_bat_driver); | ||
426 | } | ||
427 | module_exit(s3c_adc_bat_exit); | ||
428 | |||
429 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); | ||
430 | MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controler driver"); | ||
431 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c index 4e8afce0c818..5071d85ec12d 100644 --- a/drivers/power/wm97xx_battery.c +++ b/drivers/power/wm97xx_battery.c | |||
@@ -29,7 +29,6 @@ static DEFINE_MUTEX(bat_lock); | |||
29 | static struct work_struct bat_work; | 29 | static struct work_struct bat_work; |
30 | static struct mutex work_lock; | 30 | static struct mutex work_lock; |
31 | static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; | 31 | static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; |
32 | static struct wm97xx_batt_info *gpdata; | ||
33 | static enum power_supply_property *prop; | 32 | static enum power_supply_property *prop; |
34 | 33 | ||
35 | static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) | 34 | static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) |
@@ -172,12 +171,6 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) | |||
172 | struct wm97xx_pdata *wmdata = dev->dev.platform_data; | 171 | struct wm97xx_pdata *wmdata = dev->dev.platform_data; |
173 | struct wm97xx_batt_pdata *pdata; | 172 | struct wm97xx_batt_pdata *pdata; |
174 | 173 | ||
175 | if (gpdata) { | ||
176 | dev_err(&dev->dev, "Do not pass platform_data through " | ||
177 | "wm97xx_bat_set_pdata!\n"); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | if (!wmdata) { | 174 | if (!wmdata) { |
182 | dev_err(&dev->dev, "No platform data supplied\n"); | 175 | dev_err(&dev->dev, "No platform data supplied\n"); |
183 | return -EINVAL; | 176 | return -EINVAL; |
@@ -308,15 +301,6 @@ static void __exit wm97xx_bat_exit(void) | |||
308 | platform_driver_unregister(&wm97xx_bat_driver); | 301 | platform_driver_unregister(&wm97xx_bat_driver); |
309 | } | 302 | } |
310 | 303 | ||
311 | /* The interface is deprecated, as well as linux/wm97xx_batt.h */ | ||
312 | void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data); | ||
313 | |||
314 | void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) | ||
315 | { | ||
316 | gpdata = data; | ||
317 | } | ||
318 | EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata); | ||
319 | |||
320 | module_init(wm97xx_bat_init); | 304 | module_init(wm97xx_bat_init); |
321 | module_exit(wm97xx_bat_exit); | 305 | module_exit(wm97xx_bat_exit); |
322 | 306 | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 04f2e085116a..172951bf23a4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -100,6 +100,14 @@ config REGULATOR_MAX8925 | |||
100 | help | 100 | help |
101 | Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC. | 101 | Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC. |
102 | 102 | ||
103 | config REGULATOR_MAX8998 | ||
104 | tristate "Maxim 8998 voltage regulator" | ||
105 | depends on MFD_MAX8998 | ||
106 | help | ||
107 | This driver controls a Maxim 8998 voltage output regulator | ||
108 | via I2C bus. The provided regulator is suitable for S3C6410 | ||
109 | and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages. | ||
110 | |||
103 | config REGULATOR_TWL4030 | 111 | config REGULATOR_TWL4030 |
104 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" | 112 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" |
105 | depends on TWL4030_CORE | 113 | depends on TWL4030_CORE |
@@ -201,5 +209,31 @@ config REGULATOR_88PM8607 | |||
201 | help | 209 | help |
202 | This driver supports 88PM8607 voltage regulator chips. | 210 | This driver supports 88PM8607 voltage regulator chips. |
203 | 211 | ||
212 | config REGULATOR_ISL6271A | ||
213 | tristate "Intersil ISL6271A Power regulator" | ||
214 | depends on I2C | ||
215 | help | ||
216 | This driver supports ISL6271A voltage regulator chip. | ||
217 | |||
218 | config REGULATOR_AD5398 | ||
219 | tristate "Analog Devices AD5398/AD5821 regulators" | ||
220 | depends on I2C | ||
221 | help | ||
222 | This driver supports AD5398 and AD5821 current regulator chips. | ||
223 | If building into module, its name is ad5398.ko. | ||
224 | |||
225 | config REGULATOR_AB8500 | ||
226 | bool "ST-Ericsson AB8500 Power Regulators" | ||
227 | depends on AB8500_CORE | ||
228 | help | ||
229 | This driver supports the regulators found on the ST-Ericsson mixed | ||
230 | signal AB8500 PMIC | ||
231 | |||
232 | config REGULATOR_TPS6586X | ||
233 | tristate "TI TPS6586X Power regulators" | ||
234 | depends on MFD_TPS6586X | ||
235 | help | ||
236 | This driver supports TPS6586X voltage regulator chips. | ||
237 | |||
204 | endif | 238 | endif |
205 | 239 | ||
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 4e7feece22d5..8285fd832e16 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o | |||
8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o | 8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o |
9 | obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o | 9 | obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o |
10 | 10 | ||
11 | obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o | ||
11 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o | 12 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o |
12 | obj-$(CONFIG_REGULATOR_DUMMY) += dummy.o | 13 | obj-$(CONFIG_REGULATOR_DUMMY) += dummy.o |
13 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o | 14 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o |
@@ -16,12 +17,14 @@ obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o | |||
16 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o | 17 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o |
17 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o | 18 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o |
18 | obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o | 19 | obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o |
20 | obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o | ||
19 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o | 21 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o |
20 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o | 22 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o |
21 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o | 23 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o |
22 | obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o | 24 | obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o |
23 | obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o | 25 | obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o |
24 | obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o | 26 | obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o |
27 | obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o | ||
25 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 28 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
26 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o | 29 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o |
27 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 30 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
@@ -31,5 +34,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o | |||
31 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o | 34 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o |
32 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o | 35 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o |
33 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o | 36 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o |
37 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o | ||
38 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o | ||
34 | 39 | ||
35 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG | 40 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG |
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c new file mode 100644 index 000000000000..dc3f1a491675 --- /dev/null +++ b/drivers/regulator/ab8500.c | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * | ||
6 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson | ||
7 | * | ||
8 | * AB8500 peripheral regulators | ||
9 | * | ||
10 | * AB8500 supports the following regulators, | ||
11 | * LDOs - VAUDIO, VANAMIC2/2, VDIGMIC, VINTCORE12, VTVOUT, | ||
12 | * VAUX1/2/3, VANA | ||
13 | * | ||
14 | * for DB8500 cut 1.0 and previous versions of the silicon, all accesses | ||
15 | * to registers are through the DB8500 SPI. In cut 1.1 onwards, these | ||
16 | * accesses are through the DB8500 PRCMU I2C | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/mfd/ab8500.h> | ||
24 | #include <linux/regulator/driver.h> | ||
25 | #include <linux/regulator/machine.h> | ||
26 | #include <linux/regulator/ab8500.h> | ||
27 | |||
28 | /** | ||
29 | * struct ab8500_regulator_info - ab8500 regulator information | ||
30 | * @desc: regulator description | ||
31 | * @ab8500: ab8500 parent | ||
32 | * @regulator_dev: regulator device | ||
33 | * @max_uV: maximum voltage (for variable voltage supplies) | ||
34 | * @min_uV: minimum voltage (for variable voltage supplies) | ||
35 | * @fixed_uV: typical voltage (for fixed voltage supplies) | ||
36 | * @update_reg: register to control on/off | ||
37 | * @mask: mask to enable/disable regulator | ||
38 | * @enable: bits to enable the regulator in normal(high power) mode | ||
39 | * @voltage_reg: register to control regulator voltage | ||
40 | * @voltage_mask: mask to control regulator voltage | ||
41 | * @supported_voltages: supported voltage table | ||
42 | * @voltages_len: number of supported voltages for the regulator | ||
43 | */ | ||
44 | struct ab8500_regulator_info { | ||
45 | struct device *dev; | ||
46 | struct regulator_desc desc; | ||
47 | struct ab8500 *ab8500; | ||
48 | struct regulator_dev *regulator; | ||
49 | int max_uV; | ||
50 | int min_uV; | ||
51 | int fixed_uV; | ||
52 | int update_reg; | ||
53 | int mask; | ||
54 | int enable; | ||
55 | int voltage_reg; | ||
56 | int voltage_mask; | ||
57 | int const *supported_voltages; | ||
58 | int voltages_len; | ||
59 | }; | ||
60 | |||
61 | /* voltage tables for the vauxn/vintcore supplies */ | ||
62 | static const int ldo_vauxn_voltages[] = { | ||
63 | 1100000, | ||
64 | 1200000, | ||
65 | 1300000, | ||
66 | 1400000, | ||
67 | 1500000, | ||
68 | 1800000, | ||
69 | 1850000, | ||
70 | 1900000, | ||
71 | 2500000, | ||
72 | 2650000, | ||
73 | 2700000, | ||
74 | 2750000, | ||
75 | 2800000, | ||
76 | 2900000, | ||
77 | 3000000, | ||
78 | 3300000, | ||
79 | }; | ||
80 | |||
81 | static const int ldo_vintcore_voltages[] = { | ||
82 | 1200000, | ||
83 | 1225000, | ||
84 | 1250000, | ||
85 | 1275000, | ||
86 | 1300000, | ||
87 | 1325000, | ||
88 | 1350000, | ||
89 | }; | ||
90 | |||
91 | static int ab8500_regulator_enable(struct regulator_dev *rdev) | ||
92 | { | ||
93 | int regulator_id, ret; | ||
94 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
95 | |||
96 | regulator_id = rdev_get_id(rdev); | ||
97 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
98 | return -EINVAL; | ||
99 | |||
100 | ret = ab8500_set_bits(info->ab8500, info->update_reg, | ||
101 | info->mask, info->enable); | ||
102 | if (ret < 0) | ||
103 | dev_err(rdev_get_dev(rdev), | ||
104 | "couldn't set enable bits for regulator\n"); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | static int ab8500_regulator_disable(struct regulator_dev *rdev) | ||
109 | { | ||
110 | int regulator_id, ret; | ||
111 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
112 | |||
113 | regulator_id = rdev_get_id(rdev); | ||
114 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
115 | return -EINVAL; | ||
116 | |||
117 | ret = ab8500_set_bits(info->ab8500, info->update_reg, | ||
118 | info->mask, 0x0); | ||
119 | if (ret < 0) | ||
120 | dev_err(rdev_get_dev(rdev), | ||
121 | "couldn't set disable bits for regulator\n"); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) | ||
126 | { | ||
127 | int regulator_id, ret; | ||
128 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
129 | |||
130 | regulator_id = rdev_get_id(rdev); | ||
131 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
132 | return -EINVAL; | ||
133 | |||
134 | ret = ab8500_read(info->ab8500, info->update_reg); | ||
135 | if (ret < 0) { | ||
136 | dev_err(rdev_get_dev(rdev), | ||
137 | "couldn't read 0x%x register\n", info->update_reg); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | if (ret & info->mask) | ||
142 | return true; | ||
143 | else | ||
144 | return false; | ||
145 | } | ||
146 | |||
147 | static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) | ||
148 | { | ||
149 | int regulator_id; | ||
150 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
151 | |||
152 | regulator_id = rdev_get_id(rdev); | ||
153 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
154 | return -EINVAL; | ||
155 | |||
156 | /* return the uV for the fixed regulators */ | ||
157 | if (info->fixed_uV) | ||
158 | return info->fixed_uV; | ||
159 | |||
160 | if (selector > info->voltages_len) | ||
161 | return -EINVAL; | ||
162 | |||
163 | return info->supported_voltages[selector]; | ||
164 | } | ||
165 | |||
166 | static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) | ||
167 | { | ||
168 | int regulator_id, ret, val; | ||
169 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
170 | |||
171 | regulator_id = rdev_get_id(rdev); | ||
172 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
173 | return -EINVAL; | ||
174 | |||
175 | ret = ab8500_read(info->ab8500, info->voltage_reg); | ||
176 | if (ret < 0) { | ||
177 | dev_err(rdev_get_dev(rdev), | ||
178 | "couldn't read voltage reg for regulator\n"); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | /* vintcore has a different layout */ | ||
183 | val = ret & info->voltage_mask; | ||
184 | if (regulator_id == AB8500_LDO_INTCORE) | ||
185 | ret = info->supported_voltages[val >> 0x3]; | ||
186 | else | ||
187 | ret = info->supported_voltages[val]; | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static int ab8500_get_best_voltage_index(struct regulator_dev *rdev, | ||
193 | int min_uV, int max_uV) | ||
194 | { | ||
195 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
196 | int i; | ||
197 | |||
198 | /* check the supported voltage */ | ||
199 | for (i = 0; i < info->voltages_len; i++) { | ||
200 | if ((info->supported_voltages[i] >= min_uV) && | ||
201 | (info->supported_voltages[i] <= max_uV)) | ||
202 | return i; | ||
203 | } | ||
204 | |||
205 | return -EINVAL; | ||
206 | } | ||
207 | |||
208 | static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, | ||
209 | int min_uV, int max_uV) | ||
210 | { | ||
211 | int regulator_id, ret; | ||
212 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
213 | |||
214 | regulator_id = rdev_get_id(rdev); | ||
215 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
216 | return -EINVAL; | ||
217 | |||
218 | /* get the appropriate voltages within the range */ | ||
219 | ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV); | ||
220 | if (ret < 0) { | ||
221 | dev_err(rdev_get_dev(rdev), | ||
222 | "couldn't get best voltage for regulator\n"); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | /* set the registers for the request */ | ||
227 | ret = ab8500_set_bits(info->ab8500, info->voltage_reg, | ||
228 | info->voltage_mask, ret); | ||
229 | if (ret < 0) | ||
230 | dev_err(rdev_get_dev(rdev), | ||
231 | "couldn't set voltage reg for regulator\n"); | ||
232 | |||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static struct regulator_ops ab8500_regulator_ops = { | ||
237 | .enable = ab8500_regulator_enable, | ||
238 | .disable = ab8500_regulator_disable, | ||
239 | .is_enabled = ab8500_regulator_is_enabled, | ||
240 | .get_voltage = ab8500_regulator_get_voltage, | ||
241 | .set_voltage = ab8500_regulator_set_voltage, | ||
242 | .list_voltage = ab8500_list_voltage, | ||
243 | }; | ||
244 | |||
245 | static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) | ||
246 | { | ||
247 | int regulator_id; | ||
248 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | ||
249 | |||
250 | regulator_id = rdev_get_id(rdev); | ||
251 | if (regulator_id >= AB8500_NUM_REGULATORS) | ||
252 | return -EINVAL; | ||
253 | |||
254 | return info->fixed_uV; | ||
255 | } | ||
256 | |||
257 | static struct regulator_ops ab8500_ldo_fixed_ops = { | ||
258 | .enable = ab8500_regulator_enable, | ||
259 | .disable = ab8500_regulator_disable, | ||
260 | .is_enabled = ab8500_regulator_is_enabled, | ||
261 | .get_voltage = ab8500_fixed_get_voltage, | ||
262 | .list_voltage = ab8500_list_voltage, | ||
263 | }; | ||
264 | |||
265 | #define AB8500_LDO(_id, min, max, reg, reg_mask, reg_enable, \ | ||
266 | volt_reg, volt_mask, voltages, \ | ||
267 | len_volts) \ | ||
268 | { \ | ||
269 | .desc = { \ | ||
270 | .name = "LDO-" #_id, \ | ||
271 | .ops = &ab8500_regulator_ops, \ | ||
272 | .type = REGULATOR_VOLTAGE, \ | ||
273 | .id = AB8500_LDO_##_id, \ | ||
274 | .owner = THIS_MODULE, \ | ||
275 | }, \ | ||
276 | .min_uV = (min) * 1000, \ | ||
277 | .max_uV = (max) * 1000, \ | ||
278 | .update_reg = reg, \ | ||
279 | .mask = reg_mask, \ | ||
280 | .enable = reg_enable, \ | ||
281 | .voltage_reg = volt_reg, \ | ||
282 | .voltage_mask = volt_mask, \ | ||
283 | .supported_voltages = voltages, \ | ||
284 | .voltages_len = len_volts, \ | ||
285 | .fixed_uV = 0, \ | ||
286 | } | ||
287 | |||
288 | #define AB8500_FIXED_LDO(_id, fixed, reg, reg_mask, \ | ||
289 | reg_enable) \ | ||
290 | { \ | ||
291 | .desc = { \ | ||
292 | .name = "LDO-" #_id, \ | ||
293 | .ops = &ab8500_ldo_fixed_ops, \ | ||
294 | .type = REGULATOR_VOLTAGE, \ | ||
295 | .id = AB8500_LDO_##_id, \ | ||
296 | .owner = THIS_MODULE, \ | ||
297 | }, \ | ||
298 | .fixed_uV = fixed * 1000, \ | ||
299 | .update_reg = reg, \ | ||
300 | .mask = reg_mask, \ | ||
301 | .enable = reg_enable, \ | ||
302 | } | ||
303 | |||
304 | static struct ab8500_regulator_info ab8500_regulator_info[] = { | ||
305 | /* | ||
306 | * Variable Voltage LDOs | ||
307 | * name, min uV, max uV, ctrl reg, reg mask, enable mask, | ||
308 | * volt ctrl reg, volt ctrl mask, volt table, num supported volts | ||
309 | */ | ||
310 | AB8500_LDO(AUX1, 1100, 3300, 0x0409, 0x3, 0x1, 0x041f, 0xf, | ||
311 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | ||
312 | AB8500_LDO(AUX2, 1100, 3300, 0x0409, 0xc, 0x4, 0x0420, 0xf, | ||
313 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | ||
314 | AB8500_LDO(AUX3, 1100, 3300, 0x040a, 0x3, 0x1, 0x0421, 0xf, | ||
315 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | ||
316 | AB8500_LDO(INTCORE, 1100, 3300, 0x0380, 0x4, 0x4, 0x0380, 0x38, | ||
317 | ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)), | ||
318 | |||
319 | /* | ||
320 | * Fixed Voltage LDOs | ||
321 | * name, o/p uV, ctrl reg, enable, disable | ||
322 | */ | ||
323 | AB8500_FIXED_LDO(TVOUT, 2000, 0x0380, 0x2, 0x2), | ||
324 | AB8500_FIXED_LDO(AUDIO, 2000, 0x0383, 0x2, 0x2), | ||
325 | AB8500_FIXED_LDO(ANAMIC1, 2050, 0x0383, 0x4, 0x4), | ||
326 | AB8500_FIXED_LDO(ANAMIC2, 2050, 0x0383, 0x8, 0x8), | ||
327 | AB8500_FIXED_LDO(DMIC, 1800, 0x0383, 0x10, 0x10), | ||
328 | AB8500_FIXED_LDO(ANA, 1200, 0x0383, 0xc, 0x4), | ||
329 | }; | ||
330 | |||
331 | static inline struct ab8500_regulator_info *find_regulator_info(int id) | ||
332 | { | ||
333 | struct ab8500_regulator_info *info; | ||
334 | int i; | ||
335 | |||
336 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | ||
337 | info = &ab8500_regulator_info[i]; | ||
338 | if (info->desc.id == id) | ||
339 | return info; | ||
340 | } | ||
341 | return NULL; | ||
342 | } | ||
343 | |||
344 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | ||
345 | { | ||
346 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
347 | struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); | ||
348 | int i, err; | ||
349 | |||
350 | if (!ab8500) { | ||
351 | dev_err(&pdev->dev, "null mfd parent\n"); | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | |||
355 | /* register all regulators */ | ||
356 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | ||
357 | struct ab8500_regulator_info *info = NULL; | ||
358 | |||
359 | /* assign per-regulator data */ | ||
360 | info = &ab8500_regulator_info[i]; | ||
361 | info->dev = &pdev->dev; | ||
362 | info->ab8500 = ab8500; | ||
363 | |||
364 | info->regulator = regulator_register(&info->desc, &pdev->dev, | ||
365 | pdata->regulator[i], info); | ||
366 | if (IS_ERR(info->regulator)) { | ||
367 | err = PTR_ERR(info->regulator); | ||
368 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
369 | info->desc.name); | ||
370 | /* when we fail, un-register all earlier regulators */ | ||
371 | i--; | ||
372 | while (i > 0) { | ||
373 | info = &ab8500_regulator_info[i]; | ||
374 | regulator_unregister(info->regulator); | ||
375 | i--; | ||
376 | } | ||
377 | return err; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static __devexit int ab8500_regulator_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | int i; | ||
387 | |||
388 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | ||
389 | struct ab8500_regulator_info *info = NULL; | ||
390 | info = &ab8500_regulator_info[i]; | ||
391 | regulator_unregister(info->regulator); | ||
392 | } | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static struct platform_driver ab8500_regulator_driver = { | ||
398 | .probe = ab8500_regulator_probe, | ||
399 | .remove = __devexit_p(ab8500_regulator_remove), | ||
400 | .driver = { | ||
401 | .name = "ab8500-regulator", | ||
402 | .owner = THIS_MODULE, | ||
403 | }, | ||
404 | }; | ||
405 | |||
406 | static int __init ab8500_regulator_init(void) | ||
407 | { | ||
408 | int ret; | ||
409 | |||
410 | ret = platform_driver_register(&ab8500_regulator_driver); | ||
411 | if (ret != 0) | ||
412 | pr_err("Failed to register ab8500 regulator: %d\n", ret); | ||
413 | |||
414 | return ret; | ||
415 | } | ||
416 | subsys_initcall(ab8500_regulator_init); | ||
417 | |||
418 | static void __exit ab8500_regulator_exit(void) | ||
419 | { | ||
420 | platform_driver_unregister(&ab8500_regulator_driver); | ||
421 | } | ||
422 | module_exit(ab8500_regulator_exit); | ||
423 | |||
424 | MODULE_LICENSE("GPL v2"); | ||
425 | MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>"); | ||
426 | MODULE_DESCRIPTION("Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC"); | ||
427 | MODULE_ALIAS("platform:ab8500-regulator"); | ||
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c new file mode 100644 index 000000000000..d59d2f2314af --- /dev/null +++ b/drivers/regulator/ad5398.c | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * Voltage and current regulation for AD5398 and AD5821 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Enter bugs at http://blackfin.uclinux.org/ | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/regulator/driver.h> | ||
17 | #include <linux/regulator/machine.h> | ||
18 | |||
19 | #define AD5398_CURRENT_EN_MASK 0x8000 | ||
20 | |||
21 | struct ad5398_chip_info { | ||
22 | struct i2c_client *client; | ||
23 | int min_uA; | ||
24 | int max_uA; | ||
25 | unsigned int current_level; | ||
26 | unsigned int current_mask; | ||
27 | unsigned int current_offset; | ||
28 | struct regulator_dev rdev; | ||
29 | }; | ||
30 | |||
31 | static int ad5398_calc_current(struct ad5398_chip_info *chip, | ||
32 | unsigned selector) | ||
33 | { | ||
34 | unsigned range_uA = chip->max_uA - chip->min_uA; | ||
35 | |||
36 | return chip->min_uA + (selector * range_uA / chip->current_level); | ||
37 | } | ||
38 | |||
39 | static int ad5398_read_reg(struct i2c_client *client, unsigned short *data) | ||
40 | { | ||
41 | unsigned short val; | ||
42 | int ret; | ||
43 | |||
44 | ret = i2c_master_recv(client, (char *)&val, 2); | ||
45 | if (ret < 0) { | ||
46 | dev_err(&client->dev, "I2C read error\n"); | ||
47 | return ret; | ||
48 | } | ||
49 | *data = be16_to_cpu(val); | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | static int ad5398_write_reg(struct i2c_client *client, const unsigned short data) | ||
55 | { | ||
56 | unsigned short val; | ||
57 | int ret; | ||
58 | |||
59 | val = cpu_to_be16(data); | ||
60 | ret = i2c_master_send(client, (char *)&val, 2); | ||
61 | if (ret < 0) | ||
62 | dev_err(&client->dev, "I2C write error\n"); | ||
63 | |||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | static int ad5398_get_current_limit(struct regulator_dev *rdev) | ||
68 | { | ||
69 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
70 | struct i2c_client *client = chip->client; | ||
71 | unsigned short data; | ||
72 | int ret; | ||
73 | |||
74 | ret = ad5398_read_reg(client, &data); | ||
75 | if (ret < 0) | ||
76 | return ret; | ||
77 | |||
78 | ret = (data & chip->current_mask) >> chip->current_offset; | ||
79 | |||
80 | return ad5398_calc_current(chip, ret); | ||
81 | } | ||
82 | |||
83 | static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int max_uA) | ||
84 | { | ||
85 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
86 | struct i2c_client *client = chip->client; | ||
87 | unsigned range_uA = chip->max_uA - chip->min_uA; | ||
88 | unsigned selector; | ||
89 | unsigned short data; | ||
90 | int ret; | ||
91 | |||
92 | if (min_uA > chip->max_uA || min_uA < chip->min_uA) | ||
93 | return -EINVAL; | ||
94 | if (max_uA > chip->max_uA || max_uA < chip->min_uA) | ||
95 | return -EINVAL; | ||
96 | |||
97 | selector = ((min_uA - chip->min_uA) * chip->current_level + | ||
98 | range_uA - 1) / range_uA; | ||
99 | if (ad5398_calc_current(chip, selector) > max_uA) | ||
100 | return -EINVAL; | ||
101 | |||
102 | dev_dbg(&client->dev, "changing current %dmA\n", | ||
103 | ad5398_calc_current(chip, selector) / 1000); | ||
104 | |||
105 | /* read chip enable bit */ | ||
106 | ret = ad5398_read_reg(client, &data); | ||
107 | if (ret < 0) | ||
108 | return ret; | ||
109 | |||
110 | /* prepare register data */ | ||
111 | selector = (selector << chip->current_offset) & chip->current_mask; | ||
112 | data = (unsigned short)selector | (data & AD5398_CURRENT_EN_MASK); | ||
113 | |||
114 | /* write the new current value back as well as enable bit */ | ||
115 | ret = ad5398_write_reg(client, data); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static int ad5398_is_enabled(struct regulator_dev *rdev) | ||
121 | { | ||
122 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
123 | struct i2c_client *client = chip->client; | ||
124 | unsigned short data; | ||
125 | int ret; | ||
126 | |||
127 | ret = ad5398_read_reg(client, &data); | ||
128 | if (ret < 0) | ||
129 | return ret; | ||
130 | |||
131 | if (data & AD5398_CURRENT_EN_MASK) | ||
132 | return 1; | ||
133 | else | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int ad5398_enable(struct regulator_dev *rdev) | ||
138 | { | ||
139 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
140 | struct i2c_client *client = chip->client; | ||
141 | unsigned short data; | ||
142 | int ret; | ||
143 | |||
144 | ret = ad5398_read_reg(client, &data); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | |||
148 | if (data & AD5398_CURRENT_EN_MASK) | ||
149 | return 0; | ||
150 | |||
151 | data |= AD5398_CURRENT_EN_MASK; | ||
152 | |||
153 | ret = ad5398_write_reg(client, data); | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static int ad5398_disable(struct regulator_dev *rdev) | ||
159 | { | ||
160 | struct ad5398_chip_info *chip = rdev_get_drvdata(rdev); | ||
161 | struct i2c_client *client = chip->client; | ||
162 | unsigned short data; | ||
163 | int ret; | ||
164 | |||
165 | ret = ad5398_read_reg(client, &data); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | |||
169 | if (!(data & AD5398_CURRENT_EN_MASK)) | ||
170 | return 0; | ||
171 | |||
172 | data &= ~AD5398_CURRENT_EN_MASK; | ||
173 | |||
174 | ret = ad5398_write_reg(client, data); | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static struct regulator_ops ad5398_ops = { | ||
180 | .get_current_limit = ad5398_get_current_limit, | ||
181 | .set_current_limit = ad5398_set_current_limit, | ||
182 | .enable = ad5398_enable, | ||
183 | .disable = ad5398_disable, | ||
184 | .is_enabled = ad5398_is_enabled, | ||
185 | }; | ||
186 | |||
187 | static struct regulator_desc ad5398_reg = { | ||
188 | .name = "isink", | ||
189 | .id = 0, | ||
190 | .ops = &ad5398_ops, | ||
191 | .type = REGULATOR_CURRENT, | ||
192 | .owner = THIS_MODULE, | ||
193 | }; | ||
194 | |||
195 | struct ad5398_current_data_format { | ||
196 | int current_bits; | ||
197 | int current_offset; | ||
198 | int min_uA; | ||
199 | int max_uA; | ||
200 | }; | ||
201 | |||
202 | static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000}; | ||
203 | |||
204 | static const struct i2c_device_id ad5398_id[] = { | ||
205 | { "ad5398", (kernel_ulong_t)&df_10_4_120 }, | ||
206 | { "ad5821", (kernel_ulong_t)&df_10_4_120 }, | ||
207 | { } | ||
208 | }; | ||
209 | MODULE_DEVICE_TABLE(i2c, ad5398_id); | ||
210 | |||
211 | static int __devinit ad5398_probe(struct i2c_client *client, | ||
212 | const struct i2c_device_id *id) | ||
213 | { | ||
214 | struct regulator_dev *rdev; | ||
215 | struct regulator_init_data *init_data = client->dev.platform_data; | ||
216 | struct ad5398_chip_info *chip; | ||
217 | const struct ad5398_current_data_format *df = | ||
218 | (struct ad5398_current_data_format *)id->driver_data; | ||
219 | int ret; | ||
220 | |||
221 | if (!init_data) | ||
222 | return -EINVAL; | ||
223 | |||
224 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
225 | if (!chip) | ||
226 | return -ENOMEM; | ||
227 | |||
228 | chip->client = client; | ||
229 | |||
230 | chip->min_uA = df->min_uA; | ||
231 | chip->max_uA = df->max_uA; | ||
232 | chip->current_level = 1 << df->current_bits; | ||
233 | chip->current_offset = df->current_offset; | ||
234 | chip->current_mask = (chip->current_level - 1) << chip->current_offset; | ||
235 | |||
236 | rdev = regulator_register(&ad5398_reg, &client->dev, init_data, chip); | ||
237 | if (IS_ERR(rdev)) { | ||
238 | ret = PTR_ERR(rdev); | ||
239 | dev_err(&client->dev, "failed to register %s %s\n", | ||
240 | id->name, ad5398_reg.name); | ||
241 | goto err; | ||
242 | } | ||
243 | |||
244 | i2c_set_clientdata(client, chip); | ||
245 | dev_dbg(&client->dev, "%s regulator driver is registered.\n", id->name); | ||
246 | return 0; | ||
247 | |||
248 | err: | ||
249 | kfree(chip); | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | static int __devexit ad5398_remove(struct i2c_client *client) | ||
254 | { | ||
255 | struct ad5398_chip_info *chip = i2c_get_clientdata(client); | ||
256 | |||
257 | regulator_unregister(&chip->rdev); | ||
258 | kfree(chip); | ||
259 | i2c_set_clientdata(client, NULL); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static struct i2c_driver ad5398_driver = { | ||
265 | .probe = ad5398_probe, | ||
266 | .remove = __devexit_p(ad5398_remove), | ||
267 | .driver = { | ||
268 | .name = "ad5398", | ||
269 | }, | ||
270 | .id_table = ad5398_id, | ||
271 | }; | ||
272 | |||
273 | static int __init ad5398_init(void) | ||
274 | { | ||
275 | return i2c_add_driver(&ad5398_driver); | ||
276 | } | ||
277 | subsys_initcall(ad5398_init); | ||
278 | |||
279 | static void __exit ad5398_exit(void) | ||
280 | { | ||
281 | i2c_del_driver(&ad5398_driver); | ||
282 | } | ||
283 | module_exit(ad5398_exit); | ||
284 | |||
285 | MODULE_DESCRIPTION("AD5398 and AD5821 current regulator driver"); | ||
286 | MODULE_AUTHOR("Sonic Zhang"); | ||
287 | MODULE_LICENSE("GPL"); | ||
288 | MODULE_ALIAS("i2c:ad5398-regulator"); | ||
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c new file mode 100644 index 000000000000..e49d2bd393f2 --- /dev/null +++ b/drivers/regulator/isl6271a-regulator.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | * isl6271a-regulator.c | ||
3 | * | ||
4 | * Support for Intersil ISL6271A voltage regulator | ||
5 | * | ||
6 | * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation version 2. | ||
11 | * | ||
12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
13 | * whether express or implied; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/regulator/driver.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #define ISL6271A_VOLTAGE_MIN 850000 | ||
29 | #define ISL6271A_VOLTAGE_MAX 1600000 | ||
30 | #define ISL6271A_VOLTAGE_STEP 50000 | ||
31 | |||
32 | /* PMIC details */ | ||
33 | struct isl_pmic { | ||
34 | struct i2c_client *client; | ||
35 | struct regulator_dev *rdev[3]; | ||
36 | struct mutex mtx; | ||
37 | }; | ||
38 | |||
39 | static int isl6271a_get_voltage(struct regulator_dev *dev) | ||
40 | { | ||
41 | struct isl_pmic *pmic = rdev_get_drvdata(dev); | ||
42 | int idx, data; | ||
43 | |||
44 | mutex_lock(&pmic->mtx); | ||
45 | |||
46 | idx = i2c_smbus_read_byte(pmic->client); | ||
47 | if (idx < 0) { | ||
48 | dev_err(&pmic->client->dev, "Error getting voltage\n"); | ||
49 | data = idx; | ||
50 | goto out; | ||
51 | } | ||
52 | |||
53 | /* Convert the data from chip to microvolts */ | ||
54 | data = ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * (idx & 0xf)); | ||
55 | |||
56 | out: | ||
57 | mutex_unlock(&pmic->mtx); | ||
58 | return data; | ||
59 | } | ||
60 | |||
61 | static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV) | ||
62 | { | ||
63 | struct isl_pmic *pmic = rdev_get_drvdata(dev); | ||
64 | int vsel, err, data; | ||
65 | |||
66 | if (minuV < ISL6271A_VOLTAGE_MIN || minuV > ISL6271A_VOLTAGE_MAX) | ||
67 | return -EINVAL; | ||
68 | if (maxuV < ISL6271A_VOLTAGE_MIN || maxuV > ISL6271A_VOLTAGE_MAX) | ||
69 | return -EINVAL; | ||
70 | |||
71 | /* Align to 50000 mV */ | ||
72 | vsel = minuV - (minuV % ISL6271A_VOLTAGE_STEP); | ||
73 | |||
74 | /* If the result fell out of [minuV,maxuV] range, put it back */ | ||
75 | if (vsel < minuV) | ||
76 | vsel += ISL6271A_VOLTAGE_STEP; | ||
77 | |||
78 | /* Convert the microvolts to data for the chip */ | ||
79 | data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP; | ||
80 | |||
81 | mutex_lock(&pmic->mtx); | ||
82 | |||
83 | err = i2c_smbus_write_byte(pmic->client, data); | ||
84 | if (err < 0) | ||
85 | dev_err(&pmic->client->dev, "Error setting voltage\n"); | ||
86 | |||
87 | mutex_unlock(&pmic->mtx); | ||
88 | return err; | ||
89 | } | ||
90 | |||
91 | static int isl6271a_list_voltage(struct regulator_dev *dev, unsigned selector) | ||
92 | { | ||
93 | return ISL6271A_VOLTAGE_MIN + (ISL6271A_VOLTAGE_STEP * selector); | ||
94 | } | ||
95 | |||
96 | static struct regulator_ops isl_core_ops = { | ||
97 | .get_voltage = isl6271a_get_voltage, | ||
98 | .set_voltage = isl6271a_set_voltage, | ||
99 | .list_voltage = isl6271a_list_voltage, | ||
100 | }; | ||
101 | |||
102 | static int isl6271a_get_fixed_voltage(struct regulator_dev *dev) | ||
103 | { | ||
104 | int id = rdev_get_id(dev); | ||
105 | return (id == 1) ? 1100000 : 1300000; | ||
106 | } | ||
107 | |||
108 | static int isl6271a_list_fixed_voltage(struct regulator_dev *dev, unsigned selector) | ||
109 | { | ||
110 | int id = rdev_get_id(dev); | ||
111 | return (id == 1) ? 1100000 : 1300000; | ||
112 | } | ||
113 | |||
114 | static struct regulator_ops isl_fixed_ops = { | ||
115 | .get_voltage = isl6271a_get_fixed_voltage, | ||
116 | .list_voltage = isl6271a_list_fixed_voltage, | ||
117 | }; | ||
118 | |||
119 | static struct regulator_desc isl_rd[] = { | ||
120 | { | ||
121 | .name = "Core Buck", | ||
122 | .id = 0, | ||
123 | .n_voltages = 16, | ||
124 | .ops = &isl_core_ops, | ||
125 | .type = REGULATOR_VOLTAGE, | ||
126 | .owner = THIS_MODULE, | ||
127 | }, { | ||
128 | .name = "LDO1", | ||
129 | .id = 1, | ||
130 | .n_voltages = 1, | ||
131 | .ops = &isl_fixed_ops, | ||
132 | .type = REGULATOR_VOLTAGE, | ||
133 | .owner = THIS_MODULE, | ||
134 | }, { | ||
135 | .name = "LDO2", | ||
136 | .id = 2, | ||
137 | .n_voltages = 1, | ||
138 | .ops = &isl_fixed_ops, | ||
139 | .type = REGULATOR_VOLTAGE, | ||
140 | .owner = THIS_MODULE, | ||
141 | }, | ||
142 | }; | ||
143 | |||
144 | static int __devinit isl6271a_probe(struct i2c_client *i2c, | ||
145 | const struct i2c_device_id *id) | ||
146 | { | ||
147 | struct regulator_init_data *init_data = i2c->dev.platform_data; | ||
148 | struct isl_pmic *pmic; | ||
149 | int err, i; | ||
150 | |||
151 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
152 | return -EIO; | ||
153 | |||
154 | if (!init_data) { | ||
155 | dev_err(&i2c->dev, "no platform data supplied\n"); | ||
156 | return -EIO; | ||
157 | } | ||
158 | |||
159 | pmic = kzalloc(sizeof(struct isl_pmic), GFP_KERNEL); | ||
160 | if (!pmic) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | pmic->client = i2c; | ||
164 | |||
165 | mutex_init(&pmic->mtx); | ||
166 | |||
167 | for (i = 0; i < 3; i++) { | ||
168 | pmic->rdev[i] = regulator_register(&isl_rd[0], &i2c->dev, | ||
169 | init_data, pmic); | ||
170 | if (IS_ERR(pmic->rdev[i])) { | ||
171 | dev_err(&i2c->dev, "failed to register %s\n", id->name); | ||
172 | err = PTR_ERR(pmic->rdev); | ||
173 | goto error; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | i2c_set_clientdata(i2c, pmic); | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | error: | ||
182 | while (--i >= 0) | ||
183 | regulator_unregister(pmic->rdev[i]); | ||
184 | |||
185 | kfree(pmic); | ||
186 | return err; | ||
187 | } | ||
188 | |||
189 | static int __devexit isl6271a_remove(struct i2c_client *i2c) | ||
190 | { | ||
191 | struct isl_pmic *pmic = i2c_get_clientdata(i2c); | ||
192 | int i; | ||
193 | |||
194 | i2c_set_clientdata(i2c, NULL); | ||
195 | |||
196 | for (i = 0; i < 3; i++) | ||
197 | regulator_unregister(pmic->rdev[i]); | ||
198 | |||
199 | kfree(pmic); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static const struct i2c_device_id isl6271a_id[] = { | ||
205 | {.name = "isl6271a", 0 }, | ||
206 | { }, | ||
207 | }; | ||
208 | |||
209 | MODULE_DEVICE_TABLE(i2c, isl6271a_id); | ||
210 | |||
211 | static struct i2c_driver isl6271a_i2c_driver = { | ||
212 | .driver = { | ||
213 | .name = "isl6271a", | ||
214 | .owner = THIS_MODULE, | ||
215 | }, | ||
216 | .probe = isl6271a_probe, | ||
217 | .remove = __devexit_p(isl6271a_remove), | ||
218 | .id_table = isl6271a_id, | ||
219 | }; | ||
220 | |||
221 | static int __init isl6271a_init(void) | ||
222 | { | ||
223 | return i2c_add_driver(&isl6271a_i2c_driver); | ||
224 | } | ||
225 | |||
226 | static void __exit isl6271a_cleanup(void) | ||
227 | { | ||
228 | i2c_del_driver(&isl6271a_i2c_driver); | ||
229 | } | ||
230 | |||
231 | subsys_initcall(isl6271a_init); | ||
232 | module_exit(isl6271a_cleanup); | ||
233 | |||
234 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
235 | MODULE_DESCRIPTION("Intersil ISL6271A voltage regulator driver"); | ||
236 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 8ae3732eb24b..3bb82b624e19 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c | |||
@@ -377,7 +377,7 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, | |||
377 | if (count != 1) | 377 | if (count != 1) |
378 | return -EIO; | 378 | return -EIO; |
379 | ret = i2c_smbus_read_byte_data(i2c, reg); | 379 | ret = i2c_smbus_read_byte_data(i2c, reg); |
380 | if (ret < 0 || count != 1) | 380 | if (ret < 0) |
381 | return -EIO; | 381 | return -EIO; |
382 | 382 | ||
383 | *dest = ret; | 383 | *dest = ret; |
@@ -387,15 +387,9 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, | |||
387 | static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count, | 387 | static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count, |
388 | const u16 *src) | 388 | const u16 *src) |
389 | { | 389 | { |
390 | int ret; | ||
391 | |||
392 | if (count != 1) | 390 | if (count != 1) |
393 | return -EIO; | 391 | return -EIO; |
394 | ret = i2c_smbus_write_byte_data(i2c, reg, *src); | 392 | return i2c_smbus_write_byte_data(i2c, reg, *src); |
395 | if (ret >= 0) | ||
396 | return 0; | ||
397 | |||
398 | return ret; | ||
399 | } | 393 | } |
400 | 394 | ||
401 | static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg) | 395 | static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg) |
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 2b54d9d75f11..8867c2710a6d 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c | |||
@@ -223,7 +223,7 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
226 | i2c_set_clientdata(client, rdev); | 226 | i2c_set_clientdata(client, max1586); |
227 | dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n"); | 227 | dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n"); |
228 | return 0; | 228 | return 0; |
229 | 229 | ||
@@ -238,13 +238,13 @@ out: | |||
238 | 238 | ||
239 | static int __devexit max1586_pmic_remove(struct i2c_client *client) | 239 | static int __devexit max1586_pmic_remove(struct i2c_client *client) |
240 | { | 240 | { |
241 | struct regulator_dev **rdev = i2c_get_clientdata(client); | 241 | struct max1586_data *max1586 = i2c_get_clientdata(client); |
242 | int i; | 242 | int i; |
243 | 243 | ||
244 | for (i = 0; i <= MAX1586_V6; i++) | 244 | for (i = 0; i <= MAX1586_V6; i++) |
245 | if (rdev[i]) | 245 | if (max1586->rdev[i]) |
246 | regulator_unregister(rdev[i]); | 246 | regulator_unregister(max1586->rdev[i]); |
247 | kfree(rdev); | 247 | kfree(max1586); |
248 | 248 | ||
249 | return 0; | 249 | return 0; |
250 | } | 250 | } |
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index d97220efae5a..c570e6eb0db2 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c | |||
@@ -450,7 +450,7 @@ static int __devinit max8660_probe(struct i2c_client *client, | |||
450 | } | 450 | } |
451 | } | 451 | } |
452 | 452 | ||
453 | i2c_set_clientdata(client, rdev); | 453 | i2c_set_clientdata(client, max8660); |
454 | dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n"); | 454 | dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n"); |
455 | return 0; | 455 | return 0; |
456 | 456 | ||
@@ -465,13 +465,13 @@ out: | |||
465 | 465 | ||
466 | static int __devexit max8660_remove(struct i2c_client *client) | 466 | static int __devexit max8660_remove(struct i2c_client *client) |
467 | { | 467 | { |
468 | struct regulator_dev **rdev = i2c_get_clientdata(client); | 468 | struct max8660 *max8660 = i2c_get_clientdata(client); |
469 | int i; | 469 | int i; |
470 | 470 | ||
471 | for (i = 0; i < MAX8660_V_END; i++) | 471 | for (i = 0; i < MAX8660_V_END; i++) |
472 | if (rdev[i]) | 472 | if (max8660->rdev[i]) |
473 | regulator_unregister(rdev[i]); | 473 | regulator_unregister(max8660->rdev[i]); |
474 | kfree(rdev); | 474 | kfree(max8660); |
475 | 475 | ||
476 | return 0; | 476 | return 0; |
477 | } | 477 | } |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c new file mode 100644 index 000000000000..ab67298799f9 --- /dev/null +++ b/drivers/regulator/max8998.c | |||
@@ -0,0 +1,635 @@ | |||
1 | /* | ||
2 | * max8998.c - Voltage regulator driver for the Maxim 8998 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Samsung Electronics | ||
5 | * Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * Marek Szyprowski <m.szyprowski@samsung.com> | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/regulator/driver.h> | ||
34 | #include <linux/mfd/max8998.h> | ||
35 | #include <linux/mfd/max8998-private.h> | ||
36 | |||
37 | struct max8998_data { | ||
38 | struct device *dev; | ||
39 | struct max8998_dev *iodev; | ||
40 | int num_regulators; | ||
41 | struct regulator_dev **rdev; | ||
42 | }; | ||
43 | |||
44 | struct voltage_map_desc { | ||
45 | int min; | ||
46 | int max; | ||
47 | int step; | ||
48 | }; | ||
49 | |||
50 | /* Voltage maps */ | ||
51 | static const struct voltage_map_desc ldo23_voltage_map_desc = { | ||
52 | .min = 800, .step = 50, .max = 1300, | ||
53 | }; | ||
54 | static const struct voltage_map_desc ldo456711_voltage_map_desc = { | ||
55 | .min = 1600, .step = 100, .max = 3600, | ||
56 | }; | ||
57 | static const struct voltage_map_desc ldo8_voltage_map_desc = { | ||
58 | .min = 3000, .step = 100, .max = 3600, | ||
59 | }; | ||
60 | static const struct voltage_map_desc ldo9_voltage_map_desc = { | ||
61 | .min = 2800, .step = 100, .max = 3100, | ||
62 | }; | ||
63 | static const struct voltage_map_desc ldo10_voltage_map_desc = { | ||
64 | .min = 950, .step = 50, .max = 1300, | ||
65 | }; | ||
66 | static const struct voltage_map_desc ldo1213_voltage_map_desc = { | ||
67 | .min = 800, .step = 100, .max = 3300, | ||
68 | }; | ||
69 | static const struct voltage_map_desc ldo1415_voltage_map_desc = { | ||
70 | .min = 1200, .step = 100, .max = 3300, | ||
71 | }; | ||
72 | static const struct voltage_map_desc ldo1617_voltage_map_desc = { | ||
73 | .min = 1600, .step = 100, .max = 3600, | ||
74 | }; | ||
75 | static const struct voltage_map_desc buck12_voltage_map_desc = { | ||
76 | .min = 750, .step = 25, .max = 1525, | ||
77 | }; | ||
78 | static const struct voltage_map_desc buck3_voltage_map_desc = { | ||
79 | .min = 1600, .step = 100, .max = 3600, | ||
80 | }; | ||
81 | static const struct voltage_map_desc buck4_voltage_map_desc = { | ||
82 | .min = 800, .step = 100, .max = 2300, | ||
83 | }; | ||
84 | |||
85 | static const struct voltage_map_desc *ldo_voltage_map[] = { | ||
86 | NULL, | ||
87 | NULL, | ||
88 | &ldo23_voltage_map_desc, /* LDO2 */ | ||
89 | &ldo23_voltage_map_desc, /* LDO3 */ | ||
90 | &ldo456711_voltage_map_desc, /* LDO4 */ | ||
91 | &ldo456711_voltage_map_desc, /* LDO5 */ | ||
92 | &ldo456711_voltage_map_desc, /* LDO6 */ | ||
93 | &ldo456711_voltage_map_desc, /* LDO7 */ | ||
94 | &ldo8_voltage_map_desc, /* LDO8 */ | ||
95 | &ldo9_voltage_map_desc, /* LDO9 */ | ||
96 | &ldo10_voltage_map_desc, /* LDO10 */ | ||
97 | &ldo456711_voltage_map_desc, /* LDO11 */ | ||
98 | &ldo1213_voltage_map_desc, /* LDO12 */ | ||
99 | &ldo1213_voltage_map_desc, /* LDO13 */ | ||
100 | &ldo1415_voltage_map_desc, /* LDO14 */ | ||
101 | &ldo1415_voltage_map_desc, /* LDO15 */ | ||
102 | &ldo1617_voltage_map_desc, /* LDO16 */ | ||
103 | &ldo1617_voltage_map_desc, /* LDO17 */ | ||
104 | &buck12_voltage_map_desc, /* BUCK1 */ | ||
105 | &buck12_voltage_map_desc, /* BUCK2 */ | ||
106 | &buck3_voltage_map_desc, /* BUCK3 */ | ||
107 | &buck4_voltage_map_desc, /* BUCK4 */ | ||
108 | }; | ||
109 | |||
110 | static inline int max8998_get_ldo(struct regulator_dev *rdev) | ||
111 | { | ||
112 | return rdev_get_id(rdev); | ||
113 | } | ||
114 | |||
115 | static int max8998_list_voltage(struct regulator_dev *rdev, | ||
116 | unsigned int selector) | ||
117 | { | ||
118 | const struct voltage_map_desc *desc; | ||
119 | int ldo = max8998_get_ldo(rdev); | ||
120 | int val; | ||
121 | |||
122 | if (ldo >= ARRAY_SIZE(ldo_voltage_map)) | ||
123 | return -EINVAL; | ||
124 | |||
125 | desc = ldo_voltage_map[ldo]; | ||
126 | if (desc == NULL) | ||
127 | return -EINVAL; | ||
128 | |||
129 | val = desc->min + desc->step * selector; | ||
130 | if (val > desc->max) | ||
131 | return -EINVAL; | ||
132 | |||
133 | return val * 1000; | ||
134 | } | ||
135 | |||
136 | static int max8998_get_enable_register(struct regulator_dev *rdev, | ||
137 | int *reg, int *shift) | ||
138 | { | ||
139 | int ldo = max8998_get_ldo(rdev); | ||
140 | |||
141 | switch (ldo) { | ||
142 | case MAX8998_LDO2 ... MAX8998_LDO5: | ||
143 | *reg = MAX8998_REG_ONOFF1; | ||
144 | *shift = 3 - (ldo - MAX8998_LDO2); | ||
145 | break; | ||
146 | case MAX8998_LDO6 ... MAX8998_LDO13: | ||
147 | *reg = MAX8998_REG_ONOFF2; | ||
148 | *shift = 7 - (ldo - MAX8998_LDO6); | ||
149 | break; | ||
150 | case MAX8998_LDO14 ... MAX8998_LDO17: | ||
151 | *reg = MAX8998_REG_ONOFF3; | ||
152 | *shift = 7 - (ldo - MAX8998_LDO14); | ||
153 | break; | ||
154 | case MAX8998_BUCK1 ... MAX8998_BUCK4: | ||
155 | *reg = MAX8998_REG_ONOFF1; | ||
156 | *shift = 7 - (ldo - MAX8998_BUCK1); | ||
157 | break; | ||
158 | case MAX8998_EN32KHZ_AP ... MAX8998_ENVICHG: | ||
159 | *reg = MAX8998_REG_ONOFF4; | ||
160 | *shift = 7 - (ldo - MAX8998_EN32KHZ_AP); | ||
161 | break; | ||
162 | case MAX8998_ESAFEOUT1 ... MAX8998_ESAFEOUT2: | ||
163 | *reg = MAX8998_REG_CHGR2; | ||
164 | *shift = 7 - (ldo - MAX8998_ESAFEOUT1); | ||
165 | break; | ||
166 | default: | ||
167 | return -EINVAL; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int max8998_ldo_is_enabled(struct regulator_dev *rdev) | ||
174 | { | ||
175 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
176 | int ret, reg, shift = 8; | ||
177 | u8 val; | ||
178 | |||
179 | ret = max8998_get_enable_register(rdev, ®, &shift); | ||
180 | if (ret) | ||
181 | return ret; | ||
182 | |||
183 | ret = max8998_read_reg(max8998->iodev, reg, &val); | ||
184 | if (ret) | ||
185 | return ret; | ||
186 | |||
187 | return val & (1 << shift); | ||
188 | } | ||
189 | |||
190 | static int max8998_ldo_enable(struct regulator_dev *rdev) | ||
191 | { | ||
192 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
193 | int reg, shift = 8, ret; | ||
194 | |||
195 | ret = max8998_get_enable_register(rdev, ®, &shift); | ||
196 | if (ret) | ||
197 | return ret; | ||
198 | |||
199 | return max8998_update_reg(max8998->iodev, reg, 1<<shift, 1<<shift); | ||
200 | } | ||
201 | |||
202 | static int max8998_ldo_disable(struct regulator_dev *rdev) | ||
203 | { | ||
204 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
205 | int reg, shift = 8, ret; | ||
206 | |||
207 | ret = max8998_get_enable_register(rdev, ®, &shift); | ||
208 | if (ret) | ||
209 | return ret; | ||
210 | |||
211 | return max8998_update_reg(max8998->iodev, reg, 0, 1<<shift); | ||
212 | } | ||
213 | |||
214 | static int max8998_get_voltage_register(struct regulator_dev *rdev, | ||
215 | int *_reg, int *_shift, int *_mask) | ||
216 | { | ||
217 | int ldo = max8998_get_ldo(rdev); | ||
218 | int reg, shift = 0, mask = 0xff; | ||
219 | |||
220 | switch (ldo) { | ||
221 | case MAX8998_LDO2 ... MAX8998_LDO3: | ||
222 | reg = MAX8998_REG_LDO2_LDO3; | ||
223 | mask = 0xf; | ||
224 | if (ldo == MAX8998_LDO2) | ||
225 | shift = 4; | ||
226 | else | ||
227 | shift = 0; | ||
228 | break; | ||
229 | case MAX8998_LDO4 ... MAX8998_LDO7: | ||
230 | reg = MAX8998_REG_LDO4 + (ldo - MAX8998_LDO4); | ||
231 | break; | ||
232 | case MAX8998_LDO8 ... MAX8998_LDO9: | ||
233 | reg = MAX8998_REG_LDO8_LDO9; | ||
234 | mask = 0xf; | ||
235 | if (ldo == MAX8998_LDO8) | ||
236 | shift = 4; | ||
237 | else | ||
238 | shift = 0; | ||
239 | break; | ||
240 | case MAX8998_LDO10 ... MAX8998_LDO11: | ||
241 | reg = MAX8998_REG_LDO10_LDO11; | ||
242 | if (ldo == MAX8998_LDO10) { | ||
243 | shift = 5; | ||
244 | mask = 0x7; | ||
245 | } else { | ||
246 | shift = 0; | ||
247 | mask = 0x1f; | ||
248 | } | ||
249 | break; | ||
250 | case MAX8998_LDO12 ... MAX8998_LDO17: | ||
251 | reg = MAX8998_REG_LDO12 + (ldo - MAX8998_LDO12); | ||
252 | break; | ||
253 | case MAX8998_BUCK1: | ||
254 | reg = MAX8998_REG_BUCK1_DVSARM1; | ||
255 | break; | ||
256 | case MAX8998_BUCK2: | ||
257 | reg = MAX8998_REG_BUCK2_DVSINT1; | ||
258 | break; | ||
259 | case MAX8998_BUCK3: | ||
260 | reg = MAX8998_REG_BUCK3; | ||
261 | break; | ||
262 | case MAX8998_BUCK4: | ||
263 | reg = MAX8998_REG_BUCK4; | ||
264 | break; | ||
265 | default: | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | *_reg = reg; | ||
270 | *_shift = shift; | ||
271 | *_mask = mask; | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int max8998_get_voltage(struct regulator_dev *rdev) | ||
277 | { | ||
278 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
279 | int reg, shift = 0, mask, ret; | ||
280 | u8 val; | ||
281 | |||
282 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | ||
283 | if (ret) | ||
284 | return ret; | ||
285 | |||
286 | ret = max8998_read_reg(max8998->iodev, reg, &val); | ||
287 | if (ret) | ||
288 | return ret; | ||
289 | |||
290 | val >>= shift; | ||
291 | val &= mask; | ||
292 | |||
293 | return max8998_list_voltage(rdev, val); | ||
294 | } | ||
295 | |||
296 | static int max8998_set_voltage(struct regulator_dev *rdev, | ||
297 | int min_uV, int max_uV) | ||
298 | { | ||
299 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | ||
300 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
301 | int previous_vol = 0; | ||
302 | const struct voltage_map_desc *desc; | ||
303 | int ldo = max8998_get_ldo(rdev); | ||
304 | int reg, shift = 0, mask, ret; | ||
305 | int i = 0; | ||
306 | u8 val; | ||
307 | bool en_ramp = false; | ||
308 | |||
309 | if (ldo >= ARRAY_SIZE(ldo_voltage_map)) | ||
310 | return -EINVAL; | ||
311 | |||
312 | desc = ldo_voltage_map[ldo]; | ||
313 | if (desc == NULL) | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (max_vol < desc->min || min_vol > desc->max) | ||
317 | return -EINVAL; | ||
318 | |||
319 | while (desc->min + desc->step*i < min_vol && | ||
320 | desc->min + desc->step*i < desc->max) | ||
321 | i++; | ||
322 | |||
323 | if (desc->min + desc->step*i > max_vol) | ||
324 | return -EINVAL; | ||
325 | |||
326 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | ||
327 | if (ret) | ||
328 | return ret; | ||
329 | |||
330 | /* wait for RAMP_UP_DELAY if rdev is BUCK1/2 and | ||
331 | * ENRAMP is ON */ | ||
332 | if (ldo == MAX8998_BUCK1 || ldo == MAX8998_BUCK2) { | ||
333 | max8998_read_reg(max8998->iodev, MAX8998_REG_ONOFF4, &val); | ||
334 | if (val & (1 << 4)) { | ||
335 | en_ramp = true; | ||
336 | previous_vol = max8998_get_voltage(rdev); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | ret = max8998_update_reg(max8998->iodev, reg, i<<shift, mask<<shift); | ||
341 | |||
342 | if (en_ramp == true) { | ||
343 | int difference = desc->min + desc->step*i - previous_vol/1000; | ||
344 | if (difference > 0) | ||
345 | udelay(difference / ((val & 0x0f) + 1)); | ||
346 | } | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | static struct regulator_ops max8998_ldo_ops = { | ||
352 | .list_voltage = max8998_list_voltage, | ||
353 | .is_enabled = max8998_ldo_is_enabled, | ||
354 | .enable = max8998_ldo_enable, | ||
355 | .disable = max8998_ldo_disable, | ||
356 | .get_voltage = max8998_get_voltage, | ||
357 | .set_voltage = max8998_set_voltage, | ||
358 | .set_suspend_enable = max8998_ldo_enable, | ||
359 | .set_suspend_disable = max8998_ldo_disable, | ||
360 | }; | ||
361 | |||
362 | static struct regulator_ops max8998_buck_ops = { | ||
363 | .list_voltage = max8998_list_voltage, | ||
364 | .is_enabled = max8998_ldo_is_enabled, | ||
365 | .enable = max8998_ldo_enable, | ||
366 | .disable = max8998_ldo_disable, | ||
367 | .get_voltage = max8998_get_voltage, | ||
368 | .set_voltage = max8998_set_voltage, | ||
369 | .set_suspend_enable = max8998_ldo_enable, | ||
370 | .set_suspend_disable = max8998_ldo_disable, | ||
371 | }; | ||
372 | |||
373 | static struct regulator_ops max8998_others_ops = { | ||
374 | .is_enabled = max8998_ldo_is_enabled, | ||
375 | .enable = max8998_ldo_enable, | ||
376 | .disable = max8998_ldo_disable, | ||
377 | .set_suspend_enable = max8998_ldo_enable, | ||
378 | .set_suspend_disable = max8998_ldo_disable, | ||
379 | }; | ||
380 | |||
381 | static struct regulator_desc regulators[] = { | ||
382 | { | ||
383 | .name = "LDO2", | ||
384 | .id = MAX8998_LDO2, | ||
385 | .ops = &max8998_ldo_ops, | ||
386 | .type = REGULATOR_VOLTAGE, | ||
387 | .owner = THIS_MODULE, | ||
388 | }, { | ||
389 | .name = "LDO3", | ||
390 | .id = MAX8998_LDO3, | ||
391 | .ops = &max8998_ldo_ops, | ||
392 | .type = REGULATOR_VOLTAGE, | ||
393 | .owner = THIS_MODULE, | ||
394 | }, { | ||
395 | .name = "LDO4", | ||
396 | .id = MAX8998_LDO4, | ||
397 | .ops = &max8998_ldo_ops, | ||
398 | .type = REGULATOR_VOLTAGE, | ||
399 | .owner = THIS_MODULE, | ||
400 | }, { | ||
401 | .name = "LDO5", | ||
402 | .id = MAX8998_LDO5, | ||
403 | .ops = &max8998_ldo_ops, | ||
404 | .type = REGULATOR_VOLTAGE, | ||
405 | .owner = THIS_MODULE, | ||
406 | }, { | ||
407 | .name = "LDO6", | ||
408 | .id = MAX8998_LDO6, | ||
409 | .ops = &max8998_ldo_ops, | ||
410 | .type = REGULATOR_VOLTAGE, | ||
411 | .owner = THIS_MODULE, | ||
412 | }, { | ||
413 | .name = "LDO7", | ||
414 | .id = MAX8998_LDO7, | ||
415 | .ops = &max8998_ldo_ops, | ||
416 | .type = REGULATOR_VOLTAGE, | ||
417 | .owner = THIS_MODULE, | ||
418 | }, { | ||
419 | .name = "LDO8", | ||
420 | .id = MAX8998_LDO8, | ||
421 | .ops = &max8998_ldo_ops, | ||
422 | .type = REGULATOR_VOLTAGE, | ||
423 | .owner = THIS_MODULE, | ||
424 | }, { | ||
425 | .name = "LDO9", | ||
426 | .id = MAX8998_LDO9, | ||
427 | .ops = &max8998_ldo_ops, | ||
428 | .type = REGULATOR_VOLTAGE, | ||
429 | .owner = THIS_MODULE, | ||
430 | }, { | ||
431 | .name = "LDO10", | ||
432 | .id = MAX8998_LDO10, | ||
433 | .ops = &max8998_ldo_ops, | ||
434 | .type = REGULATOR_VOLTAGE, | ||
435 | .owner = THIS_MODULE, | ||
436 | }, { | ||
437 | .name = "LDO11", | ||
438 | .id = MAX8998_LDO11, | ||
439 | .ops = &max8998_ldo_ops, | ||
440 | .type = REGULATOR_VOLTAGE, | ||
441 | .owner = THIS_MODULE, | ||
442 | }, { | ||
443 | .name = "LDO12", | ||
444 | .id = MAX8998_LDO12, | ||
445 | .ops = &max8998_ldo_ops, | ||
446 | .type = REGULATOR_VOLTAGE, | ||
447 | .owner = THIS_MODULE, | ||
448 | }, { | ||
449 | .name = "LDO13", | ||
450 | .id = MAX8998_LDO13, | ||
451 | .ops = &max8998_ldo_ops, | ||
452 | .type = REGULATOR_VOLTAGE, | ||
453 | .owner = THIS_MODULE, | ||
454 | }, { | ||
455 | .name = "LDO14", | ||
456 | .id = MAX8998_LDO14, | ||
457 | .ops = &max8998_ldo_ops, | ||
458 | .type = REGULATOR_VOLTAGE, | ||
459 | .owner = THIS_MODULE, | ||
460 | }, { | ||
461 | .name = "LDO15", | ||
462 | .id = MAX8998_LDO15, | ||
463 | .ops = &max8998_ldo_ops, | ||
464 | .type = REGULATOR_VOLTAGE, | ||
465 | .owner = THIS_MODULE, | ||
466 | }, { | ||
467 | .name = "LDO16", | ||
468 | .id = MAX8998_LDO16, | ||
469 | .ops = &max8998_ldo_ops, | ||
470 | .type = REGULATOR_VOLTAGE, | ||
471 | .owner = THIS_MODULE, | ||
472 | }, { | ||
473 | .name = "LDO17", | ||
474 | .id = MAX8998_LDO17, | ||
475 | .ops = &max8998_ldo_ops, | ||
476 | .type = REGULATOR_VOLTAGE, | ||
477 | .owner = THIS_MODULE, | ||
478 | }, { | ||
479 | .name = "BUCK1", | ||
480 | .id = MAX8998_BUCK1, | ||
481 | .ops = &max8998_buck_ops, | ||
482 | .type = REGULATOR_VOLTAGE, | ||
483 | .owner = THIS_MODULE, | ||
484 | }, { | ||
485 | .name = "BUCK2", | ||
486 | .id = MAX8998_BUCK2, | ||
487 | .ops = &max8998_buck_ops, | ||
488 | .type = REGULATOR_VOLTAGE, | ||
489 | .owner = THIS_MODULE, | ||
490 | }, { | ||
491 | .name = "BUCK3", | ||
492 | .id = MAX8998_BUCK3, | ||
493 | .ops = &max8998_buck_ops, | ||
494 | .type = REGULATOR_VOLTAGE, | ||
495 | .owner = THIS_MODULE, | ||
496 | }, { | ||
497 | .name = "BUCK4", | ||
498 | .id = MAX8998_BUCK4, | ||
499 | .ops = &max8998_buck_ops, | ||
500 | .type = REGULATOR_VOLTAGE, | ||
501 | .owner = THIS_MODULE, | ||
502 | }, { | ||
503 | .name = "EN32KHz AP", | ||
504 | .id = MAX8998_EN32KHZ_AP, | ||
505 | .ops = &max8998_others_ops, | ||
506 | .type = REGULATOR_VOLTAGE, | ||
507 | .owner = THIS_MODULE, | ||
508 | }, { | ||
509 | .name = "EN32KHz CP", | ||
510 | .id = MAX8998_EN32KHZ_CP, | ||
511 | .ops = &max8998_others_ops, | ||
512 | .type = REGULATOR_VOLTAGE, | ||
513 | .owner = THIS_MODULE, | ||
514 | }, { | ||
515 | .name = "ENVICHG", | ||
516 | .id = MAX8998_ENVICHG, | ||
517 | .ops = &max8998_others_ops, | ||
518 | .type = REGULATOR_VOLTAGE, | ||
519 | .owner = THIS_MODULE, | ||
520 | }, { | ||
521 | .name = "ESAFEOUT1", | ||
522 | .id = MAX8998_ESAFEOUT1, | ||
523 | .ops = &max8998_others_ops, | ||
524 | .type = REGULATOR_VOLTAGE, | ||
525 | .owner = THIS_MODULE, | ||
526 | }, { | ||
527 | .name = "ESAFEOUT2", | ||
528 | .id = MAX8998_ESAFEOUT2, | ||
529 | .ops = &max8998_others_ops, | ||
530 | .type = REGULATOR_VOLTAGE, | ||
531 | .owner = THIS_MODULE, | ||
532 | } | ||
533 | }; | ||
534 | |||
535 | static __devinit int max8998_pmic_probe(struct platform_device *pdev) | ||
536 | { | ||
537 | struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
538 | struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); | ||
539 | struct regulator_dev **rdev; | ||
540 | struct max8998_data *max8998; | ||
541 | int i, ret, size; | ||
542 | |||
543 | if (!pdata) { | ||
544 | dev_err(pdev->dev.parent, "No platform init data supplied\n"); | ||
545 | return -ENODEV; | ||
546 | } | ||
547 | |||
548 | max8998 = kzalloc(sizeof(struct max8998_data), GFP_KERNEL); | ||
549 | if (!max8998) | ||
550 | return -ENOMEM; | ||
551 | |||
552 | size = sizeof(struct regulator_dev *) * (pdata->num_regulators + 1); | ||
553 | max8998->rdev = kzalloc(size, GFP_KERNEL); | ||
554 | if (!max8998->rdev) { | ||
555 | kfree(max8998); | ||
556 | return -ENOMEM; | ||
557 | } | ||
558 | |||
559 | rdev = max8998->rdev; | ||
560 | max8998->iodev = iodev; | ||
561 | platform_set_drvdata(pdev, max8998); | ||
562 | |||
563 | for (i = 0; i < pdata->num_regulators; i++) { | ||
564 | const struct voltage_map_desc *desc; | ||
565 | int id = pdata->regulators[i].id; | ||
566 | int index = id - MAX8998_LDO2; | ||
567 | |||
568 | desc = ldo_voltage_map[id]; | ||
569 | if (desc && regulators[index].ops != &max8998_others_ops) { | ||
570 | int count = (desc->max - desc->min) / desc->step + 1; | ||
571 | regulators[index].n_voltages = count; | ||
572 | } | ||
573 | rdev[i] = regulator_register(®ulators[index], max8998->dev, | ||
574 | pdata->regulators[i].initdata, max8998); | ||
575 | if (IS_ERR(rdev[i])) { | ||
576 | ret = PTR_ERR(rdev[i]); | ||
577 | dev_err(max8998->dev, "regulator init failed\n"); | ||
578 | rdev[i] = NULL; | ||
579 | goto err; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | |||
584 | return 0; | ||
585 | err: | ||
586 | for (i = 0; i <= max8998->num_regulators; i++) | ||
587 | if (rdev[i]) | ||
588 | regulator_unregister(rdev[i]); | ||
589 | |||
590 | kfree(max8998->rdev); | ||
591 | kfree(max8998); | ||
592 | |||
593 | return ret; | ||
594 | } | ||
595 | |||
596 | static int __devexit max8998_pmic_remove(struct platform_device *pdev) | ||
597 | { | ||
598 | struct max8998_data *max8998 = platform_get_drvdata(pdev); | ||
599 | struct regulator_dev **rdev = max8998->rdev; | ||
600 | int i; | ||
601 | |||
602 | for (i = 0; i <= max8998->num_regulators; i++) | ||
603 | if (rdev[i]) | ||
604 | regulator_unregister(rdev[i]); | ||
605 | |||
606 | kfree(max8998->rdev); | ||
607 | kfree(max8998); | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static struct platform_driver max8998_pmic_driver = { | ||
613 | .driver = { | ||
614 | .name = "max8998-pmic", | ||
615 | .owner = THIS_MODULE, | ||
616 | }, | ||
617 | .probe = max8998_pmic_probe, | ||
618 | .remove = __devexit_p(max8998_pmic_remove), | ||
619 | }; | ||
620 | |||
621 | static int __init max8998_pmic_init(void) | ||
622 | { | ||
623 | return platform_driver_register(&max8998_pmic_driver); | ||
624 | } | ||
625 | subsys_initcall(max8998_pmic_init); | ||
626 | |||
627 | static void __exit max8998_pmic_cleanup(void) | ||
628 | { | ||
629 | platform_driver_unregister(&max8998_pmic_driver); | ||
630 | } | ||
631 | module_exit(max8998_pmic_cleanup); | ||
632 | |||
633 | MODULE_DESCRIPTION("MAXIM 8998 voltage regulator driver"); | ||
634 | MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); | ||
635 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index f50afc9f287a..cd6d4fc9d74f 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c | |||
@@ -585,6 +585,8 @@ static const struct tps_info tps65023_regs[] = { | |||
585 | static const struct i2c_device_id tps_65023_id[] = { | 585 | static const struct i2c_device_id tps_65023_id[] = { |
586 | {.name = "tps65023", | 586 | {.name = "tps65023", |
587 | .driver_data = (unsigned long) tps65023_regs,}, | 587 | .driver_data = (unsigned long) tps65023_regs,}, |
588 | {.name = "tps65021", | ||
589 | .driver_data = (unsigned long) tps65023_regs,}, | ||
588 | { }, | 590 | { }, |
589 | }; | 591 | }; |
590 | 592 | ||
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 8152d65220f5..c239f42aa4a3 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -614,6 +614,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) | |||
614 | } | 614 | } |
615 | 615 | ||
616 | tps6507x_dev->pmic = tps; | 616 | tps6507x_dev->pmic = tps; |
617 | platform_set_drvdata(pdev, tps6507x_dev); | ||
617 | 618 | ||
618 | return 0; | 619 | return 0; |
619 | 620 | ||
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c new file mode 100644 index 000000000000..8cff1413a147 --- /dev/null +++ b/drivers/regulator/tps6586x-regulator.c | |||
@@ -0,0 +1,396 @@ | |||
1 | /* | ||
2 | * Regulator driver for TI TPS6586x | ||
3 | * | ||
4 | * Copyright (C) 2010 Compulab Ltd. | ||
5 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on da903x | ||
8 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
9 | * Copyright (C) 2008 Compulab Ltd. | ||
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/init.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regulator/driver.h> | ||
22 | #include <linux/regulator/machine.h> | ||
23 | #include <linux/mfd/tps6586x.h> | ||
24 | |||
25 | /* supply control and voltage setting */ | ||
26 | #define TPS6586X_SUPPLYENA 0x10 | ||
27 | #define TPS6586X_SUPPLYENB 0x11 | ||
28 | #define TPS6586X_SUPPLYENC 0x12 | ||
29 | #define TPS6586X_SUPPLYEND 0x13 | ||
30 | #define TPS6586X_SUPPLYENE 0x14 | ||
31 | #define TPS6586X_VCC1 0x20 | ||
32 | #define TPS6586X_VCC2 0x21 | ||
33 | #define TPS6586X_SM1V1 0x23 | ||
34 | #define TPS6586X_SM1V2 0x24 | ||
35 | #define TPS6586X_SM1SL 0x25 | ||
36 | #define TPS6586X_SM0V1 0x26 | ||
37 | #define TPS6586X_SM0V2 0x27 | ||
38 | #define TPS6586X_SM0SL 0x28 | ||
39 | #define TPS6586X_LDO2AV1 0x29 | ||
40 | #define TPS6586X_LDO2AV2 0x2A | ||
41 | #define TPS6586X_LDO2BV1 0x2F | ||
42 | #define TPS6586X_LDO2BV2 0x30 | ||
43 | #define TPS6586X_LDO4V1 0x32 | ||
44 | #define TPS6586X_LDO4V2 0x33 | ||
45 | |||
46 | /* converter settings */ | ||
47 | #define TPS6586X_SUPPLYV1 0x41 | ||
48 | #define TPS6586X_SUPPLYV2 0x42 | ||
49 | #define TPS6586X_SUPPLYV3 0x43 | ||
50 | #define TPS6586X_SUPPLYV4 0x44 | ||
51 | #define TPS6586X_SUPPLYV5 0x45 | ||
52 | #define TPS6586X_SUPPLYV6 0x46 | ||
53 | #define TPS6586X_SMODE1 0x47 | ||
54 | #define TPS6586X_SMODE2 0x48 | ||
55 | |||
56 | struct tps6586x_regulator { | ||
57 | struct regulator_desc desc; | ||
58 | |||
59 | int volt_reg; | ||
60 | int volt_shift; | ||
61 | int volt_nbits; | ||
62 | int enable_bit[2]; | ||
63 | int enable_reg[2]; | ||
64 | |||
65 | int *voltages; | ||
66 | |||
67 | /* for DVM regulators */ | ||
68 | int go_reg; | ||
69 | int go_bit; | ||
70 | }; | ||
71 | |||
72 | static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) | ||
73 | { | ||
74 | return rdev_get_dev(rdev)->parent->parent; | ||
75 | } | ||
76 | |||
77 | static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev, | ||
78 | unsigned selector) | ||
79 | { | ||
80 | struct tps6586x_regulator *info = rdev_get_drvdata(rdev); | ||
81 | |||
82 | return info->voltages[selector] * 1000; | ||
83 | } | ||
84 | |||
85 | |||
86 | static int __tps6586x_ldo_set_voltage(struct device *parent, | ||
87 | struct tps6586x_regulator *ri, | ||
88 | int min_uV, int max_uV) | ||
89 | { | ||
90 | int val, uV; | ||
91 | uint8_t mask; | ||
92 | |||
93 | for (val = 0; val < ri->desc.n_voltages; val++) { | ||
94 | uV = ri->voltages[val] * 1000; | ||
95 | |||
96 | /* LDO0 has minimal voltage 1.2 rather than 1.25 */ | ||
97 | if (ri->desc.id == TPS6586X_ID_LDO_0 && val == 0) | ||
98 | uV -= 50 * 1000; | ||
99 | |||
100 | /* use the first in-range value */ | ||
101 | if (min_uV <= uV && uV <= max_uV) { | ||
102 | |||
103 | val <<= ri->volt_shift; | ||
104 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; | ||
105 | |||
106 | return tps6586x_update(parent, ri->volt_reg, val, mask); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | return -EINVAL; | ||
111 | } | ||
112 | |||
113 | static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, | ||
114 | int min_uV, int max_uV) | ||
115 | { | ||
116 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
117 | struct device *parent = to_tps6586x_dev(rdev); | ||
118 | |||
119 | return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); | ||
120 | } | ||
121 | |||
122 | static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) | ||
123 | { | ||
124 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
125 | struct device *parent = to_tps6586x_dev(rdev); | ||
126 | uint8_t val, mask; | ||
127 | int ret; | ||
128 | |||
129 | ret = tps6586x_read(parent, ri->volt_reg, &val); | ||
130 | if (ret) | ||
131 | return ret; | ||
132 | |||
133 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; | ||
134 | val = (val & mask) >> ri->volt_shift; | ||
135 | |||
136 | if (val > ri->desc.n_voltages) | ||
137 | BUG(); | ||
138 | |||
139 | return ri->voltages[val] * 1000; | ||
140 | } | ||
141 | |||
142 | static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, | ||
143 | int min_uV, int max_uV) | ||
144 | { | ||
145 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
146 | struct device *parent = to_tps6586x_dev(rdev); | ||
147 | int ret; | ||
148 | |||
149 | ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); | ||
150 | if (ret) | ||
151 | return ret; | ||
152 | |||
153 | return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit); | ||
154 | } | ||
155 | |||
156 | static int tps6586x_regulator_enable(struct regulator_dev *rdev) | ||
157 | { | ||
158 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
159 | struct device *parent = to_tps6586x_dev(rdev); | ||
160 | |||
161 | return tps6586x_set_bits(parent, ri->enable_reg[0], | ||
162 | 1 << ri->enable_bit[0]); | ||
163 | } | ||
164 | |||
165 | static int tps6586x_regulator_disable(struct regulator_dev *rdev) | ||
166 | { | ||
167 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
168 | struct device *parent = to_tps6586x_dev(rdev); | ||
169 | |||
170 | return tps6586x_clr_bits(parent, ri->enable_reg[0], | ||
171 | 1 << ri->enable_bit[0]); | ||
172 | } | ||
173 | |||
174 | static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) | ||
175 | { | ||
176 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
177 | struct device *parent = to_tps6586x_dev(rdev); | ||
178 | uint8_t reg_val; | ||
179 | int ret; | ||
180 | |||
181 | ret = tps6586x_read(parent, ri->enable_reg[0], ®_val); | ||
182 | if (ret) | ||
183 | return ret; | ||
184 | |||
185 | return !!(reg_val & (1 << ri->enable_bit[0])); | ||
186 | } | ||
187 | |||
188 | static struct regulator_ops tps6586x_regulator_ldo_ops = { | ||
189 | .list_voltage = tps6586x_ldo_list_voltage, | ||
190 | .get_voltage = tps6586x_ldo_get_voltage, | ||
191 | .set_voltage = tps6586x_ldo_set_voltage, | ||
192 | |||
193 | .is_enabled = tps6586x_regulator_is_enabled, | ||
194 | .enable = tps6586x_regulator_enable, | ||
195 | .disable = tps6586x_regulator_disable, | ||
196 | }; | ||
197 | |||
198 | static struct regulator_ops tps6586x_regulator_dvm_ops = { | ||
199 | .list_voltage = tps6586x_ldo_list_voltage, | ||
200 | .get_voltage = tps6586x_ldo_get_voltage, | ||
201 | .set_voltage = tps6586x_dvm_set_voltage, | ||
202 | |||
203 | .is_enabled = tps6586x_regulator_is_enabled, | ||
204 | .enable = tps6586x_regulator_enable, | ||
205 | .disable = tps6586x_regulator_disable, | ||
206 | }; | ||
207 | |||
208 | static int tps6586x_ldo_voltages[] = { | ||
209 | 1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300, | ||
210 | }; | ||
211 | |||
212 | static int tps6586x_ldo4_voltages[] = { | ||
213 | 1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875, | ||
214 | 1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075, | ||
215 | 2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275, | ||
216 | 2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475, | ||
217 | }; | ||
218 | |||
219 | static int tps6586x_sm2_voltages[] = { | ||
220 | 3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350, | ||
221 | 3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750, | ||
222 | 3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150, | ||
223 | 4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550, | ||
224 | }; | ||
225 | |||
226 | static int tps6586x_dvm_voltages[] = { | ||
227 | 725, 750, 775, 800, 825, 850, 875, 900, | ||
228 | 925, 950, 975, 1000, 1025, 1050, 1075, 1100, | ||
229 | 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, | ||
230 | 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, | ||
231 | }; | ||
232 | |||
233 | #define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits, \ | ||
234 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | ||
235 | { \ | ||
236 | .desc = { \ | ||
237 | .name = "REG-" #_id, \ | ||
238 | .ops = &tps6586x_regulator_##_ops, \ | ||
239 | .type = REGULATOR_VOLTAGE, \ | ||
240 | .id = TPS6586X_ID_##_id, \ | ||
241 | .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \ | ||
242 | .owner = THIS_MODULE, \ | ||
243 | }, \ | ||
244 | .volt_reg = TPS6586X_##vreg, \ | ||
245 | .volt_shift = (shift), \ | ||
246 | .volt_nbits = (nbits), \ | ||
247 | .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ | ||
248 | .enable_bit[0] = (ebit0), \ | ||
249 | .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ | ||
250 | .enable_bit[1] = (ebit1), \ | ||
251 | .voltages = tps6586x_##vdata##_voltages, \ | ||
252 | } | ||
253 | |||
254 | #define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \ | ||
255 | ereg0, ebit0, ereg1, ebit1) \ | ||
256 | TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits, \ | ||
257 | ereg0, ebit0, ereg1, ebit1, 0, 0) | ||
258 | |||
259 | #define TPS6586X_DVM(_id, vdata, vreg, shift, nbits, \ | ||
260 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | ||
261 | TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits, \ | ||
262 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) | ||
263 | |||
264 | static struct tps6586x_regulator tps6586x_regulator[] = { | ||
265 | TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0), | ||
266 | TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2), | ||
267 | TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), | ||
268 | TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4), | ||
269 | TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5), | ||
270 | TPS6586X_LDO(LDO_8, ldo, SUPPLYV1, 5, 3, ENC, 6, END, 6), | ||
271 | TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), | ||
272 | TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, ENE, 7, ENE, 7), | ||
273 | TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), | ||
274 | TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 1, END, 1), | ||
275 | |||
276 | TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6), | ||
277 | TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6), | ||
278 | TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), | ||
279 | TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), | ||
280 | }; | ||
281 | |||
282 | /* | ||
283 | * TPS6586X has 2 enable bits that are OR'ed to determine the actual | ||
284 | * regulator state. Clearing one of this bits allows switching | ||
285 | * regulator on and of with single register write. | ||
286 | */ | ||
287 | static inline int tps6586x_regulator_preinit(struct device *parent, | ||
288 | struct tps6586x_regulator *ri) | ||
289 | { | ||
290 | uint8_t val1, val2; | ||
291 | int ret; | ||
292 | |||
293 | ret = tps6586x_read(parent, ri->enable_reg[0], &val1); | ||
294 | if (ret) | ||
295 | return ret; | ||
296 | |||
297 | ret = tps6586x_read(parent, ri->enable_reg[1], &val2); | ||
298 | if (ret) | ||
299 | return ret; | ||
300 | |||
301 | if (!(val2 & ri->enable_bit[1])) | ||
302 | return 0; | ||
303 | |||
304 | /* | ||
305 | * The regulator is on, but it's enabled with the bit we don't | ||
306 | * want to use, so we switch the enable bits | ||
307 | */ | ||
308 | if (!(val1 & ri->enable_bit[0])) { | ||
309 | ret = tps6586x_set_bits(parent, ri->enable_reg[0], | ||
310 | 1 << ri->enable_bit[0]); | ||
311 | if (ret) | ||
312 | return ret; | ||
313 | } | ||
314 | |||
315 | return tps6586x_clr_bits(parent, ri->enable_reg[1], | ||
316 | 1 << ri->enable_bit[1]); | ||
317 | } | ||
318 | |||
319 | static inline struct tps6586x_regulator *find_regulator_info(int id) | ||
320 | { | ||
321 | struct tps6586x_regulator *ri; | ||
322 | int i; | ||
323 | |||
324 | for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) { | ||
325 | ri = &tps6586x_regulator[i]; | ||
326 | if (ri->desc.id == id) | ||
327 | return ri; | ||
328 | } | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) | ||
333 | { | ||
334 | struct tps6586x_regulator *ri = NULL; | ||
335 | struct regulator_dev *rdev; | ||
336 | int id = pdev->id; | ||
337 | int err; | ||
338 | |||
339 | dev_dbg(&pdev->dev, "Probing reulator %d\n", id); | ||
340 | |||
341 | ri = find_regulator_info(id); | ||
342 | if (ri == NULL) { | ||
343 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); | ||
344 | return -EINVAL; | ||
345 | } | ||
346 | |||
347 | err = tps6586x_regulator_preinit(pdev->dev.parent, ri); | ||
348 | if (err) | ||
349 | return err; | ||
350 | |||
351 | rdev = regulator_register(&ri->desc, &pdev->dev, | ||
352 | pdev->dev.platform_data, ri); | ||
353 | if (IS_ERR(rdev)) { | ||
354 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
355 | ri->desc.name); | ||
356 | return PTR_ERR(rdev); | ||
357 | } | ||
358 | |||
359 | platform_set_drvdata(pdev, rdev); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int __devexit tps6586x_regulator_remove(struct platform_device *pdev) | ||
365 | { | ||
366 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
367 | |||
368 | regulator_unregister(rdev); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static struct platform_driver tps6586x_regulator_driver = { | ||
373 | .driver = { | ||
374 | .name = "tps6586x-regulator", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | .probe = tps6586x_regulator_probe, | ||
378 | .remove = __devexit_p(tps6586x_regulator_remove), | ||
379 | }; | ||
380 | |||
381 | static int __init tps6586x_regulator_init(void) | ||
382 | { | ||
383 | return platform_driver_register(&tps6586x_regulator_driver); | ||
384 | } | ||
385 | subsys_initcall(tps6586x_regulator_init); | ||
386 | |||
387 | static void __exit tps6586x_regulator_exit(void) | ||
388 | { | ||
389 | platform_driver_unregister(&tps6586x_regulator_driver); | ||
390 | } | ||
391 | module_exit(tps6586x_regulator_exit); | ||
392 | |||
393 | MODULE_LICENSE("GPL"); | ||
394 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
395 | MODULE_DESCRIPTION("Regulator Driver for TI TPS6586X PMIC"); | ||
396 | MODULE_ALIAS("platform:tps6586x-regulator"); | ||
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 5a1dc8a24d35..03713bc66e4a 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c | |||
@@ -219,8 +219,6 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) | |||
219 | 219 | ||
220 | ldo->wm8994 = wm8994; | 220 | ldo->wm8994 = wm8994; |
221 | 221 | ||
222 | ldo->is_enabled = true; | ||
223 | |||
224 | if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) { | 222 | if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) { |
225 | ldo->enable = pdata->ldo[id].enable; | 223 | ldo->enable = pdata->ldo[id].enable; |
226 | 224 | ||
@@ -237,7 +235,8 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) | |||
237 | ret); | 235 | ret); |
238 | goto err_gpio; | 236 | goto err_gpio; |
239 | } | 237 | } |
240 | } | 238 | } else |
239 | ldo->is_enabled = true; | ||
241 | 240 | ||
242 | ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, | 241 | ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, |
243 | pdata->ldo[id].init_data, ldo); | 242 | pdata->ldo[id].init_data, ldo); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4301a6c7ed3b..48ca7132cc05 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -166,6 +166,16 @@ config RTC_DRV_DS1672 | |||
166 | This driver can also be built as a module. If so, the module | 166 | This driver can also be built as a module. If so, the module |
167 | will be called rtc-ds1672. | 167 | will be called rtc-ds1672. |
168 | 168 | ||
169 | config RTC_DRV_DS3232 | ||
170 | tristate "Dallas/Maxim DS3232" | ||
171 | depends on RTC_CLASS && I2C | ||
172 | help | ||
173 | If you say yes here you get support for Dallas Semiconductor | ||
174 | DS3232 real-time clock chips. | ||
175 | |||
176 | This driver can also be built as a module. If so, the module | ||
177 | will be called rtc-ds3232. | ||
178 | |||
169 | config RTC_DRV_MAX6900 | 179 | config RTC_DRV_MAX6900 |
170 | tristate "Maxim MAX6900" | 180 | tristate "Maxim MAX6900" |
171 | help | 181 | help |
@@ -203,6 +213,15 @@ config RTC_DRV_ISL1208 | |||
203 | This driver can also be built as a module. If so, the module | 213 | This driver can also be built as a module. If so, the module |
204 | will be called rtc-isl1208. | 214 | will be called rtc-isl1208. |
205 | 215 | ||
216 | config RTC_DRV_ISL12022 | ||
217 | tristate "Intersil ISL12022" | ||
218 | help | ||
219 | If you say yes here you get support for the | ||
220 | Intersil ISL12022 RTC chip. | ||
221 | |||
222 | This driver can also be built as a module. If so, the module | ||
223 | will be called rtc-isl12022. | ||
224 | |||
206 | config RTC_DRV_X1205 | 225 | config RTC_DRV_X1205 |
207 | tristate "Xicor/Intersil X1205" | 226 | tristate "Xicor/Intersil X1205" |
208 | help | 227 | help |
@@ -537,6 +556,16 @@ config RTC_DRV_MSM6242 | |||
537 | This driver can also be built as a module. If so, the module | 556 | This driver can also be built as a module. If so, the module |
538 | will be called rtc-msm6242. | 557 | will be called rtc-msm6242. |
539 | 558 | ||
559 | config RTC_DRV_IMXDI | ||
560 | tristate "Freescale IMX DryIce Real Time Clock" | ||
561 | depends on ARCH_MX25 | ||
562 | depends on RTC_CLASS | ||
563 | help | ||
564 | Support for Freescale IMX DryIce RTC | ||
565 | |||
566 | This driver can also be built as a module, if so, the module | ||
567 | will be called "rtc-imxdi". | ||
568 | |||
540 | config RTC_MXC | 569 | config RTC_MXC |
541 | tristate "Freescale MXC Real Time Clock" | 570 | tristate "Freescale MXC Real Time Clock" |
542 | depends on ARCH_MXC | 571 | depends on ARCH_MXC |
@@ -645,9 +674,16 @@ config RTC_DRV_OMAP | |||
645 | DA8xx/OMAP-L13x chips. This driver can also be built as a | 674 | DA8xx/OMAP-L13x chips. This driver can also be built as a |
646 | module called rtc-omap. | 675 | module called rtc-omap. |
647 | 676 | ||
677 | config HAVE_S3C_RTC | ||
678 | bool | ||
679 | help | ||
680 | This will include RTC support for Samsung SoCs. If | ||
681 | you want to include RTC support for any machine, kindly | ||
682 | select this in the respective mach-XXXX/Kconfig file. | ||
683 | |||
648 | config RTC_DRV_S3C | 684 | config RTC_DRV_S3C |
649 | tristate "Samsung S3C series SoC RTC" | 685 | tristate "Samsung S3C series SoC RTC" |
650 | depends on ARCH_S3C2410 || ARCH_S3C64XX | 686 | depends on ARCH_S3C2410 || ARCH_S3C64XX || HAVE_S3C_RTC |
651 | help | 687 | help |
652 | RTC (Realtime Clock) driver for the clock inbuilt into the | 688 | RTC (Realtime Clock) driver for the clock inbuilt into the |
653 | Samsung S3C24XX series of SoCs. This can provide periodic | 689 | Samsung S3C24XX series of SoCs. This can provide periodic |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index fedf9bb36593..0f207b3b5833 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -41,12 +41,15 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | |||
41 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 41 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
42 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 42 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
43 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 43 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
44 | obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o | ||
44 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 45 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
45 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | 46 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o |
46 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 47 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
47 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 48 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
48 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o | 49 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o |
50 | obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o | ||
49 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 51 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
52 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | ||
50 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | 53 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o |
51 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 54 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
52 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 55 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 11b8ea29d2b7..5856167a0c90 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -970,7 +970,6 @@ static inline int cmos_poweroff(struct device *dev) | |||
970 | 970 | ||
971 | #include <linux/acpi.h> | 971 | #include <linux/acpi.h> |
972 | 972 | ||
973 | #ifdef CONFIG_PM | ||
974 | static u32 rtc_handler(void *context) | 973 | static u32 rtc_handler(void *context) |
975 | { | 974 | { |
976 | acpi_clear_event(ACPI_EVENT_RTC); | 975 | acpi_clear_event(ACPI_EVENT_RTC); |
@@ -999,11 +998,6 @@ static void rtc_wake_off(struct device *dev) | |||
999 | { | 998 | { |
1000 | acpi_disable_event(ACPI_EVENT_RTC, 0); | 999 | acpi_disable_event(ACPI_EVENT_RTC, 0); |
1001 | } | 1000 | } |
1002 | #else | ||
1003 | #define rtc_wake_setup() do{}while(0) | ||
1004 | #define rtc_wake_on NULL | ||
1005 | #define rtc_wake_off NULL | ||
1006 | #endif | ||
1007 | 1001 | ||
1008 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find | 1002 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find |
1009 | * its device node and pass extra config data. This helps its driver use | 1003 | * its device node and pass extra config data. This helps its driver use |
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c new file mode 100644 index 000000000000..9daed8db83d3 --- /dev/null +++ b/drivers/rtc/rtc-ds3232.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Freescale Semiconductor. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | /* | ||
12 | * It would be more efficient to use i2c msgs/i2c_transfer directly but, as | ||
13 | * recommened in .../Documentation/i2c/writing-clients section | ||
14 | * "Sending and receiving", using SMBus level communication is preferred. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/rtc.h> | ||
22 | #include <linux/bcd.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #define DS3232_REG_SECONDS 0x00 | ||
27 | #define DS3232_REG_MINUTES 0x01 | ||
28 | #define DS3232_REG_HOURS 0x02 | ||
29 | #define DS3232_REG_AMPM 0x02 | ||
30 | #define DS3232_REG_DAY 0x03 | ||
31 | #define DS3232_REG_DATE 0x04 | ||
32 | #define DS3232_REG_MONTH 0x05 | ||
33 | #define DS3232_REG_CENTURY 0x05 | ||
34 | #define DS3232_REG_YEAR 0x06 | ||
35 | #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */ | ||
36 | #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */ | ||
37 | #define DS3232_REG_CR 0x0E /* Control register */ | ||
38 | # define DS3232_REG_CR_nEOSC 0x80 | ||
39 | # define DS3232_REG_CR_INTCN 0x04 | ||
40 | # define DS3232_REG_CR_A2IE 0x02 | ||
41 | # define DS3232_REG_CR_A1IE 0x01 | ||
42 | |||
43 | #define DS3232_REG_SR 0x0F /* control/status register */ | ||
44 | # define DS3232_REG_SR_OSF 0x80 | ||
45 | # define DS3232_REG_SR_BSY 0x04 | ||
46 | # define DS3232_REG_SR_A2F 0x02 | ||
47 | # define DS3232_REG_SR_A1F 0x01 | ||
48 | |||
49 | struct ds3232 { | ||
50 | struct i2c_client *client; | ||
51 | struct rtc_device *rtc; | ||
52 | struct work_struct work; | ||
53 | |||
54 | /* The mutex protects alarm operations, and prevents a race | ||
55 | * between the enable_irq() in the workqueue and the free_irq() | ||
56 | * in the remove function. | ||
57 | */ | ||
58 | struct mutex mutex; | ||
59 | int exiting; | ||
60 | }; | ||
61 | |||
62 | static struct i2c_driver ds3232_driver; | ||
63 | |||
64 | static int ds3232_check_rtc_status(struct i2c_client *client) | ||
65 | { | ||
66 | int ret = 0; | ||
67 | int control, stat; | ||
68 | |||
69 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
70 | if (stat < 0) | ||
71 | return stat; | ||
72 | |||
73 | if (stat & DS3232_REG_SR_OSF) | ||
74 | dev_warn(&client->dev, | ||
75 | "oscillator discontinuity flagged, " | ||
76 | "time unreliable\n"); | ||
77 | |||
78 | stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); | ||
79 | |||
80 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | |||
84 | /* If the alarm is pending, clear it before requesting | ||
85 | * the interrupt, so an interrupt event isn't reported | ||
86 | * before everything is initialized. | ||
87 | */ | ||
88 | |||
89 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
90 | if (control < 0) | ||
91 | return control; | ||
92 | |||
93 | control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); | ||
94 | control |= DS3232_REG_CR_INTCN; | ||
95 | |||
96 | return i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
97 | } | ||
98 | |||
99 | static int ds3232_read_time(struct device *dev, struct rtc_time *time) | ||
100 | { | ||
101 | struct i2c_client *client = to_i2c_client(dev); | ||
102 | int ret; | ||
103 | u8 buf[7]; | ||
104 | unsigned int year, month, day, hour, minute, second; | ||
105 | unsigned int week, twelve_hr, am_pm; | ||
106 | unsigned int century, add_century = 0; | ||
107 | |||
108 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf); | ||
109 | |||
110 | if (ret < 0) | ||
111 | return ret; | ||
112 | if (ret < 7) | ||
113 | return -EIO; | ||
114 | |||
115 | second = buf[0]; | ||
116 | minute = buf[1]; | ||
117 | hour = buf[2]; | ||
118 | week = buf[3]; | ||
119 | day = buf[4]; | ||
120 | month = buf[5]; | ||
121 | year = buf[6]; | ||
122 | |||
123 | /* Extract additional information for AM/PM and century */ | ||
124 | |||
125 | twelve_hr = hour & 0x40; | ||
126 | am_pm = hour & 0x20; | ||
127 | century = month & 0x80; | ||
128 | |||
129 | /* Write to rtc_time structure */ | ||
130 | |||
131 | time->tm_sec = bcd2bin(second); | ||
132 | time->tm_min = bcd2bin(minute); | ||
133 | if (twelve_hr) { | ||
134 | /* Convert to 24 hr */ | ||
135 | if (am_pm) | ||
136 | time->tm_hour = bcd2bin(hour & 0x1F) + 12; | ||
137 | else | ||
138 | time->tm_hour = bcd2bin(hour & 0x1F); | ||
139 | } else { | ||
140 | time->tm_hour = bcd2bin(hour); | ||
141 | } | ||
142 | |||
143 | time->tm_wday = bcd2bin(week); | ||
144 | time->tm_mday = bcd2bin(day); | ||
145 | time->tm_mon = bcd2bin(month & 0x7F); | ||
146 | if (century) | ||
147 | add_century = 100; | ||
148 | |||
149 | time->tm_year = bcd2bin(year) + add_century; | ||
150 | |||
151 | return rtc_valid_tm(time); | ||
152 | } | ||
153 | |||
154 | static int ds3232_set_time(struct device *dev, struct rtc_time *time) | ||
155 | { | ||
156 | struct i2c_client *client = to_i2c_client(dev); | ||
157 | u8 buf[7]; | ||
158 | |||
159 | /* Extract time from rtc_time and load into ds3232*/ | ||
160 | |||
161 | buf[0] = bin2bcd(time->tm_sec); | ||
162 | buf[1] = bin2bcd(time->tm_min); | ||
163 | buf[2] = bin2bcd(time->tm_hour); | ||
164 | buf[3] = bin2bcd(time->tm_wday); /* Day of the week */ | ||
165 | buf[4] = bin2bcd(time->tm_mday); /* Date */ | ||
166 | buf[5] = bin2bcd(time->tm_mon); | ||
167 | if (time->tm_year >= 100) { | ||
168 | buf[5] |= 0x80; | ||
169 | buf[6] = bin2bcd(time->tm_year - 100); | ||
170 | } else { | ||
171 | buf[6] = bin2bcd(time->tm_year); | ||
172 | } | ||
173 | |||
174 | return i2c_smbus_write_i2c_block_data(client, | ||
175 | DS3232_REG_SECONDS, 7, buf); | ||
176 | } | ||
177 | |||
178 | static irqreturn_t ds3232_irq(int irq, void *dev_id) | ||
179 | { | ||
180 | struct i2c_client *client = dev_id; | ||
181 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
182 | |||
183 | disable_irq_nosync(irq); | ||
184 | schedule_work(&ds3232->work); | ||
185 | return IRQ_HANDLED; | ||
186 | } | ||
187 | |||
188 | static void ds3232_work(struct work_struct *work) | ||
189 | { | ||
190 | struct ds3232 *ds3232 = container_of(work, struct ds3232, work); | ||
191 | struct i2c_client *client = ds3232->client; | ||
192 | int stat, control; | ||
193 | |||
194 | mutex_lock(&ds3232->mutex); | ||
195 | |||
196 | stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
197 | if (stat < 0) | ||
198 | goto unlock; | ||
199 | |||
200 | if (stat & DS3232_REG_SR_A1F) { | ||
201 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
202 | if (control < 0) | ||
203 | goto out; | ||
204 | /* disable alarm1 interrupt */ | ||
205 | control &= ~(DS3232_REG_CR_A1IE); | ||
206 | i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
207 | |||
208 | /* clear the alarm pend flag */ | ||
209 | stat &= ~DS3232_REG_SR_A1F; | ||
210 | i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
211 | |||
212 | rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF); | ||
213 | } | ||
214 | |||
215 | out: | ||
216 | if (!ds3232->exiting) | ||
217 | enable_irq(client->irq); | ||
218 | unlock: | ||
219 | mutex_unlock(&ds3232->mutex); | ||
220 | } | ||
221 | |||
222 | static const struct rtc_class_ops ds3232_rtc_ops = { | ||
223 | .read_time = ds3232_read_time, | ||
224 | .set_time = ds3232_set_time, | ||
225 | }; | ||
226 | |||
227 | static int __devinit ds3232_probe(struct i2c_client *client, | ||
228 | const struct i2c_device_id *id) | ||
229 | { | ||
230 | struct ds3232 *ds3232; | ||
231 | int ret; | ||
232 | |||
233 | ds3232 = kzalloc(sizeof(struct ds3232), GFP_KERNEL); | ||
234 | if (!ds3232) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | ds3232->client = client; | ||
238 | i2c_set_clientdata(client, ds3232); | ||
239 | |||
240 | INIT_WORK(&ds3232->work, ds3232_work); | ||
241 | mutex_init(&ds3232->mutex); | ||
242 | |||
243 | ret = ds3232_check_rtc_status(client); | ||
244 | if (ret) | ||
245 | goto out_free; | ||
246 | |||
247 | ds3232->rtc = rtc_device_register(client->name, &client->dev, | ||
248 | &ds3232_rtc_ops, THIS_MODULE); | ||
249 | if (IS_ERR(ds3232->rtc)) { | ||
250 | ret = PTR_ERR(ds3232->rtc); | ||
251 | dev_err(&client->dev, "unable to register the class device\n"); | ||
252 | goto out_irq; | ||
253 | } | ||
254 | |||
255 | if (client->irq >= 0) { | ||
256 | ret = request_irq(client->irq, ds3232_irq, 0, | ||
257 | "ds3232", client); | ||
258 | if (ret) { | ||
259 | dev_err(&client->dev, "unable to request IRQ\n"); | ||
260 | goto out_free; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | |||
266 | out_irq: | ||
267 | if (client->irq >= 0) | ||
268 | free_irq(client->irq, client); | ||
269 | |||
270 | out_free: | ||
271 | i2c_set_clientdata(client, NULL); | ||
272 | kfree(ds3232); | ||
273 | return ret; | ||
274 | } | ||
275 | |||
276 | static int __devexit ds3232_remove(struct i2c_client *client) | ||
277 | { | ||
278 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
279 | |||
280 | if (client->irq >= 0) { | ||
281 | mutex_lock(&ds3232->mutex); | ||
282 | ds3232->exiting = 1; | ||
283 | mutex_unlock(&ds3232->mutex); | ||
284 | |||
285 | free_irq(client->irq, client); | ||
286 | flush_scheduled_work(); | ||
287 | } | ||
288 | |||
289 | rtc_device_unregister(ds3232->rtc); | ||
290 | i2c_set_clientdata(client, NULL); | ||
291 | kfree(ds3232); | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static const struct i2c_device_id ds3232_id[] = { | ||
296 | { "ds3232", 0 }, | ||
297 | { } | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(i2c, ds3232_id); | ||
300 | |||
301 | static struct i2c_driver ds3232_driver = { | ||
302 | .driver = { | ||
303 | .name = "rtc-ds3232", | ||
304 | .owner = THIS_MODULE, | ||
305 | }, | ||
306 | .probe = ds3232_probe, | ||
307 | .remove = __devexit_p(ds3232_remove), | ||
308 | .id_table = ds3232_id, | ||
309 | }; | ||
310 | |||
311 | static int __init ds3232_init(void) | ||
312 | { | ||
313 | return i2c_add_driver(&ds3232_driver); | ||
314 | } | ||
315 | |||
316 | static void __exit ds3232_exit(void) | ||
317 | { | ||
318 | i2c_del_driver(&ds3232_driver); | ||
319 | } | ||
320 | |||
321 | module_init(ds3232_init); | ||
322 | module_exit(ds3232_exit); | ||
323 | |||
324 | MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>"); | ||
325 | MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver"); | ||
326 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index e4de8f37ae4a..4cf2e70c5078 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c | |||
@@ -52,8 +52,8 @@ struct fm3130 { | |||
52 | struct i2c_msg msg[4]; | 52 | struct i2c_msg msg[4]; |
53 | struct i2c_client *client; | 53 | struct i2c_client *client; |
54 | struct rtc_device *rtc; | 54 | struct rtc_device *rtc; |
55 | int alarm_valid; | ||
55 | int data_valid; | 56 | int data_valid; |
56 | int alarm; | ||
57 | }; | 57 | }; |
58 | static const struct i2c_device_id fm3130_id[] = { | 58 | static const struct i2c_device_id fm3130_id[] = { |
59 | { "fm3130", 0 }, | 59 | { "fm3130", 0 }, |
@@ -87,11 +87,7 @@ static void fm3130_rtc_mode(struct device *dev, int mode) | |||
87 | dev_dbg(dev, "invalid mode %d\n", mode); | 87 | dev_dbg(dev, "invalid mode %d\n", mode); |
88 | break; | 88 | break; |
89 | } | 89 | } |
90 | /* Checking for alarm */ | 90 | |
91 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | ||
92 | fm3130->alarm = 1; | ||
93 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
94 | } | ||
95 | i2c_smbus_write_byte_data(fm3130->client, | 91 | i2c_smbus_write_byte_data(fm3130->client, |
96 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); | 92 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); |
97 | } | 93 | } |
@@ -208,6 +204,17 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
208 | struct fm3130 *fm3130 = dev_get_drvdata(dev); | 204 | struct fm3130 *fm3130 = dev_get_drvdata(dev); |
209 | int tmp; | 205 | int tmp; |
210 | struct rtc_time *tm = &alrm->time; | 206 | struct rtc_time *tm = &alrm->time; |
207 | |||
208 | if (!fm3130->alarm_valid) { | ||
209 | /* | ||
210 | * We have invalid alarm in RTC, probably due to battery faults | ||
211 | * or other problems. Return EIO for now, it will allow us to | ||
212 | * set alarm value later instead of error during probing which | ||
213 | * disables device | ||
214 | */ | ||
215 | return -EIO; | ||
216 | } | ||
217 | |||
211 | /* read the RTC alarm registers all at once */ | 218 | /* read the RTC alarm registers all at once */ |
212 | tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), | 219 | tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), |
213 | &fm3130->msg[2], 2); | 220 | &fm3130->msg[2], 2); |
@@ -222,20 +229,31 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
222 | fm3130->regs[FM3130_ALARM_DATE], | 229 | fm3130->regs[FM3130_ALARM_DATE], |
223 | fm3130->regs[FM3130_ALARM_MONTHS]); | 230 | fm3130->regs[FM3130_ALARM_MONTHS]); |
224 | 231 | ||
225 | |||
226 | tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); | 232 | tm->tm_sec = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); |
227 | tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); | 233 | tm->tm_min = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); |
228 | tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); | 234 | tm->tm_hour = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); |
229 | tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); | 235 | tm->tm_mday = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); |
230 | tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); | 236 | tm->tm_mon = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); |
237 | |||
231 | if (tm->tm_mon > 0) | 238 | if (tm->tm_mon > 0) |
232 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ | 239 | tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ |
240 | |||
233 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 241 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
234 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | 242 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", |
235 | "read alarm", tm->tm_sec, tm->tm_min, | 243 | "read alarm", tm->tm_sec, tm->tm_min, |
236 | tm->tm_hour, tm->tm_mday, | 244 | tm->tm_hour, tm->tm_mday, |
237 | tm->tm_mon, tm->tm_year, tm->tm_wday); | 245 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
238 | 246 | ||
247 | /* check if alarm enabled */ | ||
248 | fm3130->regs[FM3130_RTC_CONTROL] = | ||
249 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | ||
250 | |||
251 | if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) && | ||
252 | (~fm3130->regs[FM3130_RTC_CONTROL] & | ||
253 | FM3130_RTC_CONTROL_BIT_CAL)) { | ||
254 | alrm->enabled = 1; | ||
255 | } | ||
256 | |||
239 | return 0; | 257 | return 0; |
240 | } | 258 | } |
241 | 259 | ||
@@ -251,25 +269,20 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
251 | tm->tm_hour, tm->tm_mday, | 269 | tm->tm_hour, tm->tm_mday, |
252 | tm->tm_mon, tm->tm_year, tm->tm_wday); | 270 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
253 | 271 | ||
254 | if (tm->tm_sec != -1) | 272 | fm3130->regs[FM3130_ALARM_SECONDS] = |
255 | fm3130->regs[FM3130_ALARM_SECONDS] = | 273 | (tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80; |
256 | bin2bcd(tm->tm_sec) | 0x80; | ||
257 | 274 | ||
258 | if (tm->tm_min != -1) | 275 | fm3130->regs[FM3130_ALARM_MINUTES] = |
259 | fm3130->regs[FM3130_ALARM_MINUTES] = | 276 | (tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80; |
260 | bin2bcd(tm->tm_min) | 0x80; | ||
261 | 277 | ||
262 | if (tm->tm_hour != -1) | 278 | fm3130->regs[FM3130_ALARM_HOURS] = |
263 | fm3130->regs[FM3130_ALARM_HOURS] = | 279 | (tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80; |
264 | bin2bcd(tm->tm_hour) | 0x80; | ||
265 | 280 | ||
266 | if (tm->tm_mday != -1) | 281 | fm3130->regs[FM3130_ALARM_DATE] = |
267 | fm3130->regs[FM3130_ALARM_DATE] = | 282 | (tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80; |
268 | bin2bcd(tm->tm_mday) | 0x80; | ||
269 | 283 | ||
270 | if (tm->tm_mon != -1) | 284 | fm3130->regs[FM3130_ALARM_MONTHS] = |
271 | fm3130->regs[FM3130_ALARM_MONTHS] = | 285 | (tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80; |
272 | bin2bcd(tm->tm_mon + 1) | 0x80; | ||
273 | 286 | ||
274 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", | 287 | dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", |
275 | fm3130->regs[FM3130_ALARM_SECONDS], | 288 | fm3130->regs[FM3130_ALARM_SECONDS], |
@@ -285,11 +298,8 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
285 | } | 298 | } |
286 | fm3130->regs[FM3130_RTC_CONTROL] = | 299 | fm3130->regs[FM3130_RTC_CONTROL] = |
287 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | 300 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); |
288 | /* Checking for alarm */ | 301 | |
289 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | 302 | /* enable or disable alarm */ |
290 | fm3130->alarm = 1; | ||
291 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
292 | } | ||
293 | if (alrm->enabled) { | 303 | if (alrm->enabled) { |
294 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, | 304 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, |
295 | (fm3130->regs[FM3130_RTC_CONTROL] & | 305 | (fm3130->regs[FM3130_RTC_CONTROL] & |
@@ -298,16 +308,55 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
298 | } else { | 308 | } else { |
299 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, | 309 | i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, |
300 | fm3130->regs[FM3130_RTC_CONTROL] & | 310 | fm3130->regs[FM3130_RTC_CONTROL] & |
301 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | 311 | ~(FM3130_RTC_CONTROL_BIT_CAL) & |
312 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | ||
302 | } | 313 | } |
314 | |||
315 | /* We assume here that data is valid once written */ | ||
316 | if (!fm3130->alarm_valid) | ||
317 | fm3130->alarm_valid = 1; | ||
318 | |||
303 | return 0; | 319 | return 0; |
304 | } | 320 | } |
305 | 321 | ||
322 | static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
323 | { | ||
324 | struct fm3130 *fm3130 = dev_get_drvdata(dev); | ||
325 | int ret = 0; | ||
326 | |||
327 | fm3130->regs[FM3130_RTC_CONTROL] = | ||
328 | i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); | ||
329 | |||
330 | dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n", | ||
331 | enabled, fm3130->regs[FM3130_RTC_CONTROL]); | ||
332 | |||
333 | switch (enabled) { | ||
334 | case 0: /* alarm off */ | ||
335 | ret = i2c_smbus_write_byte_data(fm3130->client, | ||
336 | FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] & | ||
337 | ~(FM3130_RTC_CONTROL_BIT_CAL) & | ||
338 | ~(FM3130_RTC_CONTROL_BIT_AEN)); | ||
339 | break; | ||
340 | case 1: /* alarm on */ | ||
341 | ret = i2c_smbus_write_byte_data(fm3130->client, | ||
342 | FM3130_RTC_CONTROL, (fm3130->regs[FM3130_RTC_CONTROL] & | ||
343 | ~(FM3130_RTC_CONTROL_BIT_CAL)) | | ||
344 | FM3130_RTC_CONTROL_BIT_AEN); | ||
345 | break; | ||
346 | default: | ||
347 | ret = -EINVAL; | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
306 | static const struct rtc_class_ops fm3130_rtc_ops = { | 354 | static const struct rtc_class_ops fm3130_rtc_ops = { |
307 | .read_time = fm3130_get_time, | 355 | .read_time = fm3130_get_time, |
308 | .set_time = fm3130_set_time, | 356 | .set_time = fm3130_set_time, |
309 | .read_alarm = fm3130_read_alarm, | 357 | .read_alarm = fm3130_read_alarm, |
310 | .set_alarm = fm3130_set_alarm, | 358 | .set_alarm = fm3130_set_alarm, |
359 | .alarm_irq_enable = fm3130_alarm_irq_enable, | ||
311 | }; | 360 | }; |
312 | 361 | ||
313 | static struct i2c_driver fm3130_driver; | 362 | static struct i2c_driver fm3130_driver; |
@@ -356,6 +405,7 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
356 | fm3130->msg[3].len = FM3130_ALARM_REGS; | 405 | fm3130->msg[3].len = FM3130_ALARM_REGS; |
357 | fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; | 406 | fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; |
358 | 407 | ||
408 | fm3130->alarm_valid = 0; | ||
359 | fm3130->data_valid = 0; | 409 | fm3130->data_valid = 0; |
360 | 410 | ||
361 | tmp = i2c_transfer(adapter, fm3130->msg, 4); | 411 | tmp = i2c_transfer(adapter, fm3130->msg, 4); |
@@ -370,12 +420,6 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
370 | fm3130->regs[FM3130_CAL_CONTROL] = | 420 | fm3130->regs[FM3130_CAL_CONTROL] = |
371 | i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); | 421 | i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); |
372 | 422 | ||
373 | /* Checking for alarm */ | ||
374 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { | ||
375 | fm3130->alarm = 1; | ||
376 | fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; | ||
377 | } | ||
378 | |||
379 | /* Disabling calibration mode */ | 423 | /* Disabling calibration mode */ |
380 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { | 424 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { |
381 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 425 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
@@ -400,44 +444,79 @@ static int __devinit fm3130_probe(struct i2c_client *client, | |||
400 | fm3130->regs[FM3130_CAL_CONTROL] & | 444 | fm3130->regs[FM3130_CAL_CONTROL] & |
401 | ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); | 445 | ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); |
402 | 446 | ||
403 | /* oscillator fault? clear flag, and warn */ | 447 | /* low battery? clear flag, and warn */ |
404 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) | 448 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) { |
449 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | ||
450 | fm3130->regs[FM3130_RTC_CONTROL] & | ||
451 | ~(FM3130_RTC_CONTROL_BIT_LB)); | ||
405 | dev_warn(&client->dev, "Low battery!\n"); | 452 | dev_warn(&client->dev, "Low battery!\n"); |
453 | } | ||
406 | 454 | ||
407 | /* oscillator fault? clear flag, and warn */ | 455 | /* check if Power On Reset bit is set */ |
408 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { | 456 | if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { |
409 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, | 457 | i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, |
410 | fm3130->regs[FM3130_RTC_CONTROL] & | 458 | fm3130->regs[FM3130_RTC_CONTROL] & |
411 | ~FM3130_RTC_CONTROL_BIT_POR); | 459 | ~FM3130_RTC_CONTROL_BIT_POR); |
412 | dev_warn(&client->dev, "SET TIME!\n"); | 460 | dev_dbg(&client->dev, "POR bit is set\n"); |
413 | } | 461 | } |
414 | /* ACS is controlled by alarm */ | 462 | /* ACS is controlled by alarm */ |
415 | i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); | 463 | i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); |
416 | 464 | ||
417 | /* TODO */ | 465 | /* alarm registers sanity check */ |
418 | /* TODO need to sanity check alarm */ | 466 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); |
419 | tmp = fm3130->regs[FM3130_RTC_SECONDS]; | 467 | if (tmp > 59) |
420 | tmp = bcd2bin(tmp & 0x7f); | 468 | goto bad_alarm; |
421 | if (tmp > 60) | 469 | |
422 | goto exit_bad; | ||
423 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | 470 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); |
424 | if (tmp > 60) | 471 | if (tmp > 59) |
425 | goto exit_bad; | 472 | goto bad_alarm; |
473 | |||
474 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f); | ||
475 | if (tmp > 23) | ||
476 | goto bad_alarm; | ||
426 | 477 | ||
427 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | 478 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); |
428 | if (tmp == 0 || tmp > 31) | 479 | if (tmp == 0 || tmp > 31) |
429 | goto exit_bad; | 480 | goto bad_alarm; |
430 | 481 | ||
431 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); | 482 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); |
432 | if (tmp == 0 || tmp > 12) | 483 | if (tmp == 0 || tmp > 12) |
433 | goto exit_bad; | 484 | goto bad_alarm; |
434 | 485 | ||
435 | tmp = fm3130->regs[FM3130_RTC_HOURS]; | 486 | fm3130->alarm_valid = 1; |
487 | |||
488 | bad_alarm: | ||
489 | |||
490 | /* clock registers sanity chek */ | ||
491 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); | ||
492 | if (tmp > 59) | ||
493 | goto bad_clock; | ||
494 | |||
495 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); | ||
496 | if (tmp > 59) | ||
497 | goto bad_clock; | ||
498 | |||
499 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f); | ||
500 | if (tmp > 23) | ||
501 | goto bad_clock; | ||
502 | |||
503 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7); | ||
504 | if (tmp == 0 || tmp > 7) | ||
505 | goto bad_clock; | ||
506 | |||
507 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f); | ||
508 | if (tmp == 0 || tmp > 31) | ||
509 | goto bad_clock; | ||
510 | |||
511 | tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); | ||
512 | if (tmp == 0 || tmp > 12) | ||
513 | goto bad_clock; | ||
436 | 514 | ||
437 | fm3130->data_valid = 1; | 515 | fm3130->data_valid = 1; |
438 | 516 | ||
439 | exit_bad: | 517 | bad_clock: |
440 | if (!fm3130->data_valid) | 518 | |
519 | if (!fm3130->data_valid || !fm3130->alarm_valid) | ||
441 | dev_dbg(&client->dev, | 520 | dev_dbg(&client->dev, |
442 | "%s: %02x %02x %02x %02x %02x %02x %02x %02x" | 521 | "%s: %02x %02x %02x %02x %02x %02x %02x %02x" |
443 | "%02x %02x %02x %02x %02x %02x %02x\n", | 522 | "%02x %02x %02x %02x %02x %02x %02x\n", |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c new file mode 100644 index 000000000000..2dd3c0163272 --- /dev/null +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -0,0 +1,519 @@ | |||
1 | /* | ||
2 | * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * Copyright 2010 Orex Computed Radiography | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * The code contained herein is licensed under the GNU General Public | ||
8 | * License. You may obtain a copy of the GNU General Public License | ||
9 | * Version 2 or later at the following locations: | ||
10 | * | ||
11 | * http://www.opensource.org/licenses/gpl-license.html | ||
12 | * http://www.gnu.org/copyleft/gpl.html | ||
13 | */ | ||
14 | |||
15 | /* based on rtc-mc13892.c */ | ||
16 | |||
17 | /* | ||
18 | * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block | ||
19 | * to implement a Linux RTC. Times and alarms are truncated to seconds. | ||
20 | * Since the RTC framework performs API locking via rtc->ops_lock the | ||
21 | * only simultaneous accesses we need to deal with is updating DryIce | ||
22 | * registers while servicing an alarm. | ||
23 | * | ||
24 | * Note that reading the DSR (DryIce Status Register) automatically clears | ||
25 | * the WCF (Write Complete Flag). All DryIce writes are synchronized to the | ||
26 | * LP (Low Power) domain and set the WCF upon completion. Writes to the | ||
27 | * DIER (DryIce Interrupt Enable Register) are the only exception. These | ||
28 | * occur at normal bus speeds and do not set WCF. Periodic interrupts are | ||
29 | * not supported by the hardware. | ||
30 | */ | ||
31 | |||
32 | #include <linux/io.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/rtc.h> | ||
38 | #include <linux/workqueue.h> | ||
39 | |||
40 | /* DryIce Register Definitions */ | ||
41 | |||
42 | #define DTCMR 0x00 /* Time Counter MSB Reg */ | ||
43 | #define DTCLR 0x04 /* Time Counter LSB Reg */ | ||
44 | |||
45 | #define DCAMR 0x08 /* Clock Alarm MSB Reg */ | ||
46 | #define DCALR 0x0c /* Clock Alarm LSB Reg */ | ||
47 | #define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */ | ||
48 | |||
49 | #define DCR 0x10 /* Control Reg */ | ||
50 | #define DCR_TCE (1 << 3) /* Time Counter Enable */ | ||
51 | |||
52 | #define DSR 0x14 /* Status Reg */ | ||
53 | #define DSR_WBF (1 << 10) /* Write Busy Flag */ | ||
54 | #define DSR_WNF (1 << 9) /* Write Next Flag */ | ||
55 | #define DSR_WCF (1 << 8) /* Write Complete Flag */ | ||
56 | #define DSR_WEF (1 << 7) /* Write Error Flag */ | ||
57 | #define DSR_CAF (1 << 4) /* Clock Alarm Flag */ | ||
58 | #define DSR_NVF (1 << 1) /* Non-Valid Flag */ | ||
59 | #define DSR_SVF (1 << 0) /* Security Violation Flag */ | ||
60 | |||
61 | #define DIER 0x18 /* Interrupt Enable Reg */ | ||
62 | #define DIER_WNIE (1 << 9) /* Write Next Interrupt Enable */ | ||
63 | #define DIER_WCIE (1 << 8) /* Write Complete Interrupt Enable */ | ||
64 | #define DIER_WEIE (1 << 7) /* Write Error Interrupt Enable */ | ||
65 | #define DIER_CAIE (1 << 4) /* Clock Alarm Interrupt Enable */ | ||
66 | |||
67 | /** | ||
68 | * struct imxdi_dev - private imxdi rtc data | ||
69 | * @pdev: pionter to platform dev | ||
70 | * @rtc: pointer to rtc struct | ||
71 | * @ioaddr: IO registers pointer | ||
72 | * @irq: dryice normal interrupt | ||
73 | * @clk: input reference clock | ||
74 | * @dsr: copy of the DSR register | ||
75 | * @irq_lock: interrupt enable register (DIER) lock | ||
76 | * @write_wait: registers write complete queue | ||
77 | * @write_mutex: serialize registers write | ||
78 | * @work: schedule alarm work | ||
79 | */ | ||
80 | struct imxdi_dev { | ||
81 | struct platform_device *pdev; | ||
82 | struct rtc_device *rtc; | ||
83 | void __iomem *ioaddr; | ||
84 | int irq; | ||
85 | struct clk *clk; | ||
86 | u32 dsr; | ||
87 | spinlock_t irq_lock; | ||
88 | wait_queue_head_t write_wait; | ||
89 | struct mutex write_mutex; | ||
90 | struct work_struct work; | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * enable a dryice interrupt | ||
95 | */ | ||
96 | static void di_int_enable(struct imxdi_dev *imxdi, u32 intr) | ||
97 | { | ||
98 | unsigned long flags; | ||
99 | |||
100 | spin_lock_irqsave(&imxdi->irq_lock, flags); | ||
101 | __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr, | ||
102 | imxdi->ioaddr + DIER); | ||
103 | spin_unlock_irqrestore(&imxdi->irq_lock, flags); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * disable a dryice interrupt | ||
108 | */ | ||
109 | static void di_int_disable(struct imxdi_dev *imxdi, u32 intr) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | |||
113 | spin_lock_irqsave(&imxdi->irq_lock, flags); | ||
114 | __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr, | ||
115 | imxdi->ioaddr + DIER); | ||
116 | spin_unlock_irqrestore(&imxdi->irq_lock, flags); | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * This function attempts to clear the dryice write-error flag. | ||
121 | * | ||
122 | * A dryice write error is similar to a bus fault and should not occur in | ||
123 | * normal operation. Clearing the flag requires another write, so the root | ||
124 | * cause of the problem may need to be fixed before the flag can be cleared. | ||
125 | */ | ||
126 | static void clear_write_error(struct imxdi_dev *imxdi) | ||
127 | { | ||
128 | int cnt; | ||
129 | |||
130 | dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n"); | ||
131 | |||
132 | /* clear the write error flag */ | ||
133 | __raw_writel(DSR_WEF, imxdi->ioaddr + DSR); | ||
134 | |||
135 | /* wait for it to take effect */ | ||
136 | for (cnt = 0; cnt < 1000; cnt++) { | ||
137 | if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0) | ||
138 | return; | ||
139 | udelay(10); | ||
140 | } | ||
141 | dev_err(&imxdi->pdev->dev, | ||
142 | "ERROR: Cannot clear write-error flag!\n"); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Write a dryice register and wait until it completes. | ||
147 | * | ||
148 | * This function uses interrupts to determine when the | ||
149 | * write has completed. | ||
150 | */ | ||
151 | static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg) | ||
152 | { | ||
153 | int ret; | ||
154 | int rc = 0; | ||
155 | |||
156 | /* serialize register writes */ | ||
157 | mutex_lock(&imxdi->write_mutex); | ||
158 | |||
159 | /* enable the write-complete interrupt */ | ||
160 | di_int_enable(imxdi, DIER_WCIE); | ||
161 | |||
162 | imxdi->dsr = 0; | ||
163 | |||
164 | /* do the register write */ | ||
165 | __raw_writel(val, imxdi->ioaddr + reg); | ||
166 | |||
167 | /* wait for the write to finish */ | ||
168 | ret = wait_event_interruptible_timeout(imxdi->write_wait, | ||
169 | imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1)); | ||
170 | if (ret < 0) { | ||
171 | rc = ret; | ||
172 | goto out; | ||
173 | } else if (ret == 0) { | ||
174 | dev_warn(&imxdi->pdev->dev, | ||
175 | "Write-wait timeout " | ||
176 | "val = 0x%08x reg = 0x%08x\n", val, reg); | ||
177 | } | ||
178 | |||
179 | /* check for write error */ | ||
180 | if (imxdi->dsr & DSR_WEF) { | ||
181 | clear_write_error(imxdi); | ||
182 | rc = -EIO; | ||
183 | } | ||
184 | |||
185 | out: | ||
186 | mutex_unlock(&imxdi->write_mutex); | ||
187 | |||
188 | return rc; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * read the seconds portion of the current time from the dryice time counter | ||
193 | */ | ||
194 | static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
195 | { | ||
196 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
197 | unsigned long now; | ||
198 | |||
199 | now = __raw_readl(imxdi->ioaddr + DTCMR); | ||
200 | rtc_time_to_tm(now, tm); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * set the seconds portion of dryice time counter and clear the | ||
207 | * fractional part. | ||
208 | */ | ||
209 | static int dryice_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
210 | { | ||
211 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
212 | int rc; | ||
213 | |||
214 | /* zero the fractional part first */ | ||
215 | rc = di_write_wait(imxdi, 0, DTCLR); | ||
216 | if (rc == 0) | ||
217 | rc = di_write_wait(imxdi, secs, DTCMR); | ||
218 | |||
219 | return rc; | ||
220 | } | ||
221 | |||
222 | static int dryice_rtc_alarm_irq_enable(struct device *dev, | ||
223 | unsigned int enabled) | ||
224 | { | ||
225 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
226 | |||
227 | if (enabled) | ||
228 | di_int_enable(imxdi, DIER_CAIE); | ||
229 | else | ||
230 | di_int_disable(imxdi, DIER_CAIE); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * read the seconds portion of the alarm register. | ||
237 | * the fractional part of the alarm register is always zero. | ||
238 | */ | ||
239 | static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
240 | { | ||
241 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
242 | u32 dcamr; | ||
243 | |||
244 | dcamr = __raw_readl(imxdi->ioaddr + DCAMR); | ||
245 | rtc_time_to_tm(dcamr, &alarm->time); | ||
246 | |||
247 | /* alarm is enabled if the interrupt is enabled */ | ||
248 | alarm->enabled = (__raw_readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0; | ||
249 | |||
250 | /* don't allow the DSR read to mess up DSR_WCF */ | ||
251 | mutex_lock(&imxdi->write_mutex); | ||
252 | |||
253 | /* alarm is pending if the alarm flag is set */ | ||
254 | alarm->pending = (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0; | ||
255 | |||
256 | mutex_unlock(&imxdi->write_mutex); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * set the seconds portion of dryice alarm register | ||
263 | */ | ||
264 | static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
265 | { | ||
266 | struct imxdi_dev *imxdi = dev_get_drvdata(dev); | ||
267 | unsigned long now; | ||
268 | unsigned long alarm_time; | ||
269 | int rc; | ||
270 | |||
271 | rc = rtc_tm_to_time(&alarm->time, &alarm_time); | ||
272 | if (rc) | ||
273 | return rc; | ||
274 | |||
275 | /* don't allow setting alarm in the past */ | ||
276 | now = __raw_readl(imxdi->ioaddr + DTCMR); | ||
277 | if (alarm_time < now) | ||
278 | return -EINVAL; | ||
279 | |||
280 | /* write the new alarm time */ | ||
281 | rc = di_write_wait(imxdi, (u32)alarm_time, DCAMR); | ||
282 | if (rc) | ||
283 | return rc; | ||
284 | |||
285 | if (alarm->enabled) | ||
286 | di_int_enable(imxdi, DIER_CAIE); /* enable alarm intr */ | ||
287 | else | ||
288 | di_int_disable(imxdi, DIER_CAIE); /* disable alarm intr */ | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static struct rtc_class_ops dryice_rtc_ops = { | ||
294 | .read_time = dryice_rtc_read_time, | ||
295 | .set_mmss = dryice_rtc_set_mmss, | ||
296 | .alarm_irq_enable = dryice_rtc_alarm_irq_enable, | ||
297 | .read_alarm = dryice_rtc_read_alarm, | ||
298 | .set_alarm = dryice_rtc_set_alarm, | ||
299 | }; | ||
300 | |||
301 | /* | ||
302 | * dryice "normal" interrupt handler | ||
303 | */ | ||
304 | static irqreturn_t dryice_norm_irq(int irq, void *dev_id) | ||
305 | { | ||
306 | struct imxdi_dev *imxdi = dev_id; | ||
307 | u32 dsr, dier; | ||
308 | irqreturn_t rc = IRQ_NONE; | ||
309 | |||
310 | dier = __raw_readl(imxdi->ioaddr + DIER); | ||
311 | |||
312 | /* handle write complete and write error cases */ | ||
313 | if ((dier & DIER_WCIE)) { | ||
314 | /*If the write wait queue is empty then there is no pending | ||
315 | operations. It means the interrupt is for DryIce -Security. | ||
316 | IRQ must be returned as none.*/ | ||
317 | if (list_empty_careful(&imxdi->write_wait.task_list)) | ||
318 | return rc; | ||
319 | |||
320 | /* DSR_WCF clears itself on DSR read */ | ||
321 | dsr = __raw_readl(imxdi->ioaddr + DSR); | ||
322 | if ((dsr & (DSR_WCF | DSR_WEF))) { | ||
323 | /* mask the interrupt */ | ||
324 | di_int_disable(imxdi, DIER_WCIE); | ||
325 | |||
326 | /* save the dsr value for the wait queue */ | ||
327 | imxdi->dsr |= dsr; | ||
328 | |||
329 | wake_up_interruptible(&imxdi->write_wait); | ||
330 | rc = IRQ_HANDLED; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | /* handle the alarm case */ | ||
335 | if ((dier & DIER_CAIE)) { | ||
336 | /* DSR_WCF clears itself on DSR read */ | ||
337 | dsr = __raw_readl(imxdi->ioaddr + DSR); | ||
338 | if (dsr & DSR_CAF) { | ||
339 | /* mask the interrupt */ | ||
340 | di_int_disable(imxdi, DIER_CAIE); | ||
341 | |||
342 | /* finish alarm in user context */ | ||
343 | schedule_work(&imxdi->work); | ||
344 | rc = IRQ_HANDLED; | ||
345 | } | ||
346 | } | ||
347 | return rc; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * post the alarm event from user context so it can sleep | ||
352 | * on the write completion. | ||
353 | */ | ||
354 | static void dryice_work(struct work_struct *work) | ||
355 | { | ||
356 | struct imxdi_dev *imxdi = container_of(work, | ||
357 | struct imxdi_dev, work); | ||
358 | |||
359 | /* dismiss the interrupt (ignore error) */ | ||
360 | di_write_wait(imxdi, DSR_CAF, DSR); | ||
361 | |||
362 | /* pass the alarm event to the rtc framework. */ | ||
363 | rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF); | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * probe for dryice rtc device | ||
368 | */ | ||
369 | static int dryice_rtc_probe(struct platform_device *pdev) | ||
370 | { | ||
371 | struct resource *res; | ||
372 | struct imxdi_dev *imxdi; | ||
373 | int rc; | ||
374 | |||
375 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
376 | if (!res) | ||
377 | return -ENODEV; | ||
378 | |||
379 | imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); | ||
380 | if (!imxdi) | ||
381 | return -ENOMEM; | ||
382 | |||
383 | imxdi->pdev = pdev; | ||
384 | |||
385 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | ||
386 | pdev->name)) | ||
387 | return -EBUSY; | ||
388 | |||
389 | imxdi->ioaddr = devm_ioremap(&pdev->dev, res->start, | ||
390 | resource_size(res)); | ||
391 | if (imxdi->ioaddr == NULL) | ||
392 | return -ENOMEM; | ||
393 | |||
394 | imxdi->irq = platform_get_irq(pdev, 0); | ||
395 | if (imxdi->irq < 0) | ||
396 | return imxdi->irq; | ||
397 | |||
398 | init_waitqueue_head(&imxdi->write_wait); | ||
399 | |||
400 | INIT_WORK(&imxdi->work, dryice_work); | ||
401 | |||
402 | mutex_init(&imxdi->write_mutex); | ||
403 | |||
404 | imxdi->clk = clk_get(&pdev->dev, NULL); | ||
405 | if (IS_ERR(imxdi->clk)) | ||
406 | return PTR_ERR(imxdi->clk); | ||
407 | clk_enable(imxdi->clk); | ||
408 | |||
409 | /* | ||
410 | * Initialize dryice hardware | ||
411 | */ | ||
412 | |||
413 | /* mask all interrupts */ | ||
414 | __raw_writel(0, imxdi->ioaddr + DIER); | ||
415 | |||
416 | rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq, | ||
417 | IRQF_SHARED, pdev->name, imxdi); | ||
418 | if (rc) { | ||
419 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
420 | goto err; | ||
421 | } | ||
422 | |||
423 | /* put dryice into valid state */ | ||
424 | if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) { | ||
425 | rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR); | ||
426 | if (rc) | ||
427 | goto err; | ||
428 | } | ||
429 | |||
430 | /* initialize alarm */ | ||
431 | rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR); | ||
432 | if (rc) | ||
433 | goto err; | ||
434 | rc = di_write_wait(imxdi, 0, DCALR); | ||
435 | if (rc) | ||
436 | goto err; | ||
437 | |||
438 | /* clear alarm flag */ | ||
439 | if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) { | ||
440 | rc = di_write_wait(imxdi, DSR_CAF, DSR); | ||
441 | if (rc) | ||
442 | goto err; | ||
443 | } | ||
444 | |||
445 | /* the timer won't count if it has never been written to */ | ||
446 | if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) { | ||
447 | rc = di_write_wait(imxdi, 0, DTCMR); | ||
448 | if (rc) | ||
449 | goto err; | ||
450 | } | ||
451 | |||
452 | /* start keeping time */ | ||
453 | if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) { | ||
454 | rc = di_write_wait(imxdi, | ||
455 | __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE, | ||
456 | DCR); | ||
457 | if (rc) | ||
458 | goto err; | ||
459 | } | ||
460 | |||
461 | platform_set_drvdata(pdev, imxdi); | ||
462 | imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
463 | &dryice_rtc_ops, THIS_MODULE); | ||
464 | if (IS_ERR(imxdi->rtc)) { | ||
465 | rc = PTR_ERR(imxdi->rtc); | ||
466 | goto err; | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | |||
471 | err: | ||
472 | clk_disable(imxdi->clk); | ||
473 | clk_put(imxdi->clk); | ||
474 | |||
475 | return rc; | ||
476 | } | ||
477 | |||
478 | static int __devexit dryice_rtc_remove(struct platform_device *pdev) | ||
479 | { | ||
480 | struct imxdi_dev *imxdi = platform_get_drvdata(pdev); | ||
481 | |||
482 | flush_work(&imxdi->work); | ||
483 | |||
484 | /* mask all interrupts */ | ||
485 | __raw_writel(0, imxdi->ioaddr + DIER); | ||
486 | |||
487 | rtc_device_unregister(imxdi->rtc); | ||
488 | |||
489 | clk_disable(imxdi->clk); | ||
490 | clk_put(imxdi->clk); | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static struct platform_driver dryice_rtc_driver = { | ||
496 | .driver = { | ||
497 | .name = "imxdi_rtc", | ||
498 | .owner = THIS_MODULE, | ||
499 | }, | ||
500 | .remove = __devexit_p(dryice_rtc_remove), | ||
501 | }; | ||
502 | |||
503 | static int __init dryice_rtc_init(void) | ||
504 | { | ||
505 | return platform_driver_probe(&dryice_rtc_driver, dryice_rtc_probe); | ||
506 | } | ||
507 | |||
508 | static void __exit dryice_rtc_exit(void) | ||
509 | { | ||
510 | platform_driver_unregister(&dryice_rtc_driver); | ||
511 | } | ||
512 | |||
513 | module_init(dryice_rtc_init); | ||
514 | module_exit(dryice_rtc_exit); | ||
515 | |||
516 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
517 | MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); | ||
518 | MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)"); | ||
519 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c new file mode 100644 index 000000000000..ddbc797ea6cd --- /dev/null +++ b/drivers/rtc/rtc-isl12022.c | |||
@@ -0,0 +1,327 @@ | |||
1 | /* | ||
2 | * An I2C driver for the Intersil ISL 12022 | ||
3 | * | ||
4 | * Author: Roman Fietze <roman.fietze@telemotive.de> | ||
5 | * | ||
6 | * Based on the Philips PCF8563 RTC | ||
7 | * by Alessandro Zummo <a.zummo@towertech.it>. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/bcd.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/slab.h> | ||
18 | |||
19 | #define DRV_VERSION "0.1" | ||
20 | |||
21 | /* ISL register offsets */ | ||
22 | #define ISL12022_REG_SC 0x00 | ||
23 | #define ISL12022_REG_MN 0x01 | ||
24 | #define ISL12022_REG_HR 0x02 | ||
25 | #define ISL12022_REG_DT 0x03 | ||
26 | #define ISL12022_REG_MO 0x04 | ||
27 | #define ISL12022_REG_YR 0x05 | ||
28 | #define ISL12022_REG_DW 0x06 | ||
29 | |||
30 | #define ISL12022_REG_SR 0x07 | ||
31 | #define ISL12022_REG_INT 0x08 | ||
32 | |||
33 | /* ISL register bits */ | ||
34 | #define ISL12022_HR_MIL (1 << 7) /* military or 24 hour time */ | ||
35 | |||
36 | #define ISL12022_SR_LBAT85 (1 << 2) | ||
37 | #define ISL12022_SR_LBAT75 (1 << 1) | ||
38 | |||
39 | #define ISL12022_INT_WRTC (1 << 6) | ||
40 | |||
41 | |||
42 | static struct i2c_driver isl12022_driver; | ||
43 | |||
44 | struct isl12022 { | ||
45 | struct rtc_device *rtc; | ||
46 | |||
47 | bool write_enabled; /* true if write enable is set */ | ||
48 | }; | ||
49 | |||
50 | |||
51 | static int isl12022_read_regs(struct i2c_client *client, uint8_t reg, | ||
52 | uint8_t *data, size_t n) | ||
53 | { | ||
54 | struct i2c_msg msgs[] = { | ||
55 | { | ||
56 | .addr = client->addr, | ||
57 | .flags = 0, | ||
58 | .len = 1, | ||
59 | .buf = data | ||
60 | }, /* setup read ptr */ | ||
61 | { | ||
62 | .addr = client->addr, | ||
63 | .flags = I2C_M_RD, | ||
64 | .len = n, | ||
65 | .buf = data | ||
66 | } | ||
67 | }; | ||
68 | |||
69 | int ret; | ||
70 | |||
71 | data[0] = reg; | ||
72 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
73 | if (ret != ARRAY_SIZE(msgs)) { | ||
74 | dev_err(&client->dev, "%s: read error, ret=%d\n", | ||
75 | __func__, ret); | ||
76 | return -EIO; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | |||
83 | static int isl12022_write_reg(struct i2c_client *client, | ||
84 | uint8_t reg, uint8_t val) | ||
85 | { | ||
86 | uint8_t data[2] = { reg, val }; | ||
87 | int err; | ||
88 | |||
89 | err = i2c_master_send(client, data, sizeof(data)); | ||
90 | if (err != sizeof(data)) { | ||
91 | dev_err(&client->dev, | ||
92 | "%s: err=%d addr=%02x, data=%02x\n", | ||
93 | __func__, err, data[0], data[1]); | ||
94 | return -EIO; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | /* | ||
102 | * In the routines that deal directly with the isl12022 hardware, we use | ||
103 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
104 | */ | ||
105 | static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
106 | { | ||
107 | uint8_t buf[ISL12022_REG_INT + 1]; | ||
108 | int ret; | ||
109 | |||
110 | ret = isl12022_read_regs(client, ISL12022_REG_SC, buf, sizeof(buf)); | ||
111 | if (ret) | ||
112 | return ret; | ||
113 | |||
114 | if (buf[ISL12022_REG_SR] & (ISL12022_SR_LBAT85 | ISL12022_SR_LBAT75)) { | ||
115 | dev_warn(&client->dev, | ||
116 | "voltage dropped below %u%%, " | ||
117 | "date and time is not reliable.\n", | ||
118 | buf[ISL12022_REG_SR] & ISL12022_SR_LBAT85 ? 85 : 75); | ||
119 | } | ||
120 | |||
121 | dev_dbg(&client->dev, | ||
122 | "%s: raw data is sec=%02x, min=%02x, hr=%02x, " | ||
123 | "mday=%02x, mon=%02x, year=%02x, wday=%02x, " | ||
124 | "sr=%02x, int=%02x", | ||
125 | __func__, | ||
126 | buf[ISL12022_REG_SC], | ||
127 | buf[ISL12022_REG_MN], | ||
128 | buf[ISL12022_REG_HR], | ||
129 | buf[ISL12022_REG_DT], | ||
130 | buf[ISL12022_REG_MO], | ||
131 | buf[ISL12022_REG_YR], | ||
132 | buf[ISL12022_REG_DW], | ||
133 | buf[ISL12022_REG_SR], | ||
134 | buf[ISL12022_REG_INT]); | ||
135 | |||
136 | tm->tm_sec = bcd2bin(buf[ISL12022_REG_SC] & 0x7F); | ||
137 | tm->tm_min = bcd2bin(buf[ISL12022_REG_MN] & 0x7F); | ||
138 | tm->tm_hour = bcd2bin(buf[ISL12022_REG_HR] & 0x3F); | ||
139 | tm->tm_mday = bcd2bin(buf[ISL12022_REG_DT] & 0x3F); | ||
140 | tm->tm_wday = buf[ISL12022_REG_DW] & 0x07; | ||
141 | tm->tm_mon = bcd2bin(buf[ISL12022_REG_MO] & 0x1F) - 1; | ||
142 | tm->tm_year = bcd2bin(buf[ISL12022_REG_YR]) + 100; | ||
143 | |||
144 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
145 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
146 | __func__, | ||
147 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
148 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
149 | |||
150 | /* The clock can give out invalid datetime, but we cannot return | ||
151 | * -EINVAL otherwise hwclock will refuse to set the time on bootup. */ | ||
152 | if (rtc_valid_tm(tm) < 0) | ||
153 | dev_err(&client->dev, "retrieved date and time is invalid.\n"); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
159 | { | ||
160 | struct isl12022 *isl12022 = i2c_get_clientdata(client); | ||
161 | size_t i; | ||
162 | int ret; | ||
163 | uint8_t buf[ISL12022_REG_DW + 1]; | ||
164 | |||
165 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
166 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
167 | __func__, | ||
168 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
169 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
170 | |||
171 | if (!isl12022->write_enabled) { | ||
172 | |||
173 | ret = isl12022_read_regs(client, ISL12022_REG_INT, buf, 1); | ||
174 | if (ret) | ||
175 | return ret; | ||
176 | |||
177 | /* Check if WRTC (write rtc enable) is set factory default is | ||
178 | * 0 (not set) */ | ||
179 | if (!(buf[0] & ISL12022_INT_WRTC)) { | ||
180 | dev_info(&client->dev, | ||
181 | "init write enable and 24 hour format\n"); | ||
182 | |||
183 | /* Set the write enable bit. */ | ||
184 | ret = isl12022_write_reg(client, | ||
185 | ISL12022_REG_INT, | ||
186 | buf[0] | ISL12022_INT_WRTC); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | /* Write to any RTC register to start RTC, we use the | ||
191 | * HR register, setting the MIL bit to use the 24 hour | ||
192 | * format. */ | ||
193 | ret = isl12022_read_regs(client, ISL12022_REG_HR, | ||
194 | buf, 1); | ||
195 | if (ret) | ||
196 | return ret; | ||
197 | |||
198 | ret = isl12022_write_reg(client, | ||
199 | ISL12022_REG_HR, | ||
200 | buf[0] | ISL12022_HR_MIL); | ||
201 | if (ret) | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | isl12022->write_enabled = 1; | ||
206 | } | ||
207 | |||
208 | /* hours, minutes and seconds */ | ||
209 | buf[ISL12022_REG_SC] = bin2bcd(tm->tm_sec); | ||
210 | buf[ISL12022_REG_MN] = bin2bcd(tm->tm_min); | ||
211 | buf[ISL12022_REG_HR] = bin2bcd(tm->tm_hour) | ISL12022_HR_MIL; | ||
212 | |||
213 | buf[ISL12022_REG_DT] = bin2bcd(tm->tm_mday); | ||
214 | |||
215 | /* month, 1 - 12 */ | ||
216 | buf[ISL12022_REG_MO] = bin2bcd(tm->tm_mon + 1); | ||
217 | |||
218 | /* year and century */ | ||
219 | buf[ISL12022_REG_YR] = bin2bcd(tm->tm_year % 100); | ||
220 | |||
221 | buf[ISL12022_REG_DW] = tm->tm_wday & 0x07; | ||
222 | |||
223 | /* write register's data */ | ||
224 | for (i = 0; i < ARRAY_SIZE(buf); i++) { | ||
225 | ret = isl12022_write_reg(client, ISL12022_REG_SC + i, | ||
226 | buf[ISL12022_REG_SC + i]); | ||
227 | if (ret) | ||
228 | return -EIO; | ||
229 | }; | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
235 | { | ||
236 | return isl12022_get_datetime(to_i2c_client(dev), tm); | ||
237 | } | ||
238 | |||
239 | static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
240 | { | ||
241 | return isl12022_set_datetime(to_i2c_client(dev), tm); | ||
242 | } | ||
243 | |||
244 | static const struct rtc_class_ops isl12022_rtc_ops = { | ||
245 | .read_time = isl12022_rtc_read_time, | ||
246 | .set_time = isl12022_rtc_set_time, | ||
247 | }; | ||
248 | |||
249 | static int isl12022_probe(struct i2c_client *client, | ||
250 | const struct i2c_device_id *id) | ||
251 | { | ||
252 | struct isl12022 *isl12022; | ||
253 | |||
254 | int ret = 0; | ||
255 | |||
256 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
257 | return -ENODEV; | ||
258 | |||
259 | isl12022 = kzalloc(sizeof(struct isl12022), GFP_KERNEL); | ||
260 | if (!isl12022) | ||
261 | return -ENOMEM; | ||
262 | |||
263 | dev_dbg(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
264 | |||
265 | i2c_set_clientdata(client, isl12022); | ||
266 | |||
267 | isl12022->rtc = rtc_device_register(isl12022_driver.driver.name, | ||
268 | &client->dev, | ||
269 | &isl12022_rtc_ops, | ||
270 | THIS_MODULE); | ||
271 | |||
272 | if (IS_ERR(isl12022->rtc)) { | ||
273 | ret = PTR_ERR(isl12022->rtc); | ||
274 | goto exit_kfree; | ||
275 | } | ||
276 | |||
277 | return 0; | ||
278 | |||
279 | exit_kfree: | ||
280 | kfree(isl12022); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static int isl12022_remove(struct i2c_client *client) | ||
286 | { | ||
287 | struct isl12022 *isl12022 = i2c_get_clientdata(client); | ||
288 | |||
289 | rtc_device_unregister(isl12022->rtc); | ||
290 | kfree(isl12022); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static const struct i2c_device_id isl12022_id[] = { | ||
296 | { "isl12022", 0 }, | ||
297 | { "rtc8564", 0 }, | ||
298 | { } | ||
299 | }; | ||
300 | MODULE_DEVICE_TABLE(i2c, isl12022_id); | ||
301 | |||
302 | static struct i2c_driver isl12022_driver = { | ||
303 | .driver = { | ||
304 | .name = "rtc-isl12022", | ||
305 | }, | ||
306 | .probe = isl12022_probe, | ||
307 | .remove = isl12022_remove, | ||
308 | .id_table = isl12022_id, | ||
309 | }; | ||
310 | |||
311 | static int __init isl12022_init(void) | ||
312 | { | ||
313 | return i2c_add_driver(&isl12022_driver); | ||
314 | } | ||
315 | |||
316 | static void __exit isl12022_exit(void) | ||
317 | { | ||
318 | i2c_del_driver(&isl12022_driver); | ||
319 | } | ||
320 | |||
321 | module_init(isl12022_init); | ||
322 | module_exit(isl12022_exit); | ||
323 | |||
324 | MODULE_AUTHOR("roman.fietze@telemotive.de"); | ||
325 | MODULE_DESCRIPTION("ISL 12022 RTC driver"); | ||
326 | MODULE_LICENSE("GPL"); | ||
327 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 6dc4e6241418..66377f3e28b8 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -121,7 +121,7 @@ static int m41t80_get_datetime(struct i2c_client *client, | |||
121 | 121 | ||
122 | /* assume 20YY not 19YY, and ignore the Century Bit */ | 122 | /* assume 20YY not 19YY, and ignore the Century Bit */ |
123 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; | 123 | tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100; |
124 | return 0; | 124 | return rtc_valid_tm(tm); |
125 | } | 125 | } |
126 | 126 | ||
127 | /* Sets the given date and time to the real time clock. */ | 127 | /* Sets the given date and time to the real time clock. */ |
@@ -364,7 +364,7 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
364 | t->time.tm_isdst = -1; | 364 | t->time.tm_isdst = -1; |
365 | t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE); | 365 | t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE); |
366 | t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF); | 366 | t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF); |
367 | return 0; | 367 | return rtc_valid_tm(t); |
368 | } | 368 | } |
369 | 369 | ||
370 | static struct rtc_class_ops m41t80_rtc_ops = { | 370 | static struct rtc_class_ops m41t80_rtc_ops = { |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index be8359fdb65a..a99a0b554eb8 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -105,7 +105,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
105 | dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", | 105 | dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", |
106 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, | 106 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, |
107 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 107 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
108 | return 0; | 108 | return rtc_valid_tm(tm); |
109 | } | 109 | } |
110 | 110 | ||
111 | static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) | 111 | static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -196,7 +196,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
196 | dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", | 196 | dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", |
197 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, | 197 | tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, |
198 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 198 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
199 | return 0; | 199 | return rtc_valid_tm(tm); |
200 | } | 200 | } |
201 | 201 | ||
202 | /* | 202 | /* |
@@ -506,7 +506,6 @@ out: | |||
506 | free_irq(m48t59->irq, &pdev->dev); | 506 | free_irq(m48t59->irq, &pdev->dev); |
507 | if (m48t59->ioaddr) | 507 | if (m48t59->ioaddr) |
508 | iounmap(m48t59->ioaddr); | 508 | iounmap(m48t59->ioaddr); |
509 | if (m48t59) | ||
510 | kfree(m48t59); | 509 | kfree(m48t59); |
511 | return ret; | 510 | return ret; |
512 | } | 511 | } |
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 7c045cffa9ff..f981287d582b 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c | |||
@@ -77,7 +77,7 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
77 | if (ops->readbyte(M48T86_REG_HOUR) & 0x80) | 77 | if (ops->readbyte(M48T86_REG_HOUR) & 0x80) |
78 | tm->tm_hour += 12; | 78 | tm->tm_hour += 12; |
79 | 79 | ||
80 | return 0; | 80 | return rtc_valid_tm(tm); |
81 | } | 81 | } |
82 | 82 | ||
83 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | 83 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index a4f6665ab3c5..486142c2637a 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
@@ -159,7 +159,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
159 | bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; | 159 | bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900; |
160 | tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); | 160 | tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]); |
161 | 161 | ||
162 | return 0; | 162 | return rtc_valid_tm(tm); |
163 | } | 163 | } |
164 | 164 | ||
165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) | 165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) |
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index db5d8c416d26..dfcdf0901d21 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -268,7 +268,7 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { | |||
268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, | 268 | .update_irq_enable = mpc5121_rtc_update_irq_enable, |
269 | }; | 269 | }; |
270 | 270 | ||
271 | static int __devinit mpc5121_rtc_probe(struct of_device *op, | 271 | static int __devinit mpc5121_rtc_probe(struct platform_device *op, |
272 | const struct of_device_id *match) | 272 | const struct of_device_id *match) |
273 | { | 273 | { |
274 | struct mpc5121_rtc_data *rtc; | 274 | struct mpc5121_rtc_data *rtc; |
@@ -338,7 +338,7 @@ out_free: | |||
338 | return err; | 338 | return err; |
339 | } | 339 | } |
340 | 340 | ||
341 | static int __devexit mpc5121_rtc_remove(struct of_device *op) | 341 | static int __devexit mpc5121_rtc_remove(struct platform_device *op) |
342 | { | 342 | { |
343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); | 343 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); |
344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | 344 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 25ec921db07c..0b06c1e03fd5 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -83,12 +83,6 @@ struct rtc_plat_data { | |||
83 | void __iomem *ioaddr; | 83 | void __iomem *ioaddr; |
84 | int irq; | 84 | int irq; |
85 | struct clk *clk; | 85 | struct clk *clk; |
86 | unsigned int irqen; | ||
87 | int alrm_sec; | ||
88 | int alrm_min; | ||
89 | int alrm_hour; | ||
90 | int alrm_mday; | ||
91 | struct timespec mxc_rtc_delta; | ||
92 | struct rtc_time g_rtc_alarm; | 86 | struct rtc_time g_rtc_alarm; |
93 | }; | 87 | }; |
94 | 88 | ||
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index a351bd5d8176..62de66af0a68 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c | |||
@@ -85,25 +85,24 @@ static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) | |||
85 | 85 | ||
86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) | 86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) |
87 | { | 87 | { |
88 | unsigned int i; | 88 | unsigned int timeout = 0x1000; |
89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); | 89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); |
90 | 90 | ||
91 | mdelay(10); | 91 | mdelay(10); |
92 | 92 | ||
93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); | 93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); |
94 | 94 | ||
95 | for (i = 0; i < 1000; i++) { | 95 | while (!(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) |
96 | if (__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) | 96 | && timeout--) |
97 | return 0; | 97 | mdelay(1); |
98 | } | ||
99 | 98 | ||
100 | if ((__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) == 0x0) | 99 | if (!timeout) |
101 | return ERR_PTR(-ENODEV); | 100 | return ERR_PTR(-EPERM); |
102 | 101 | ||
103 | return ERR_PTR(-EPERM); | 102 | return 0; |
104 | } | 103 | } |
105 | 104 | ||
106 | static void nuc900_rtc_bcd2bin(unsigned int timereg, | 105 | static int nuc900_rtc_bcd2bin(unsigned int timereg, |
107 | unsigned int calreg, struct rtc_time *tm) | 106 | unsigned int calreg, struct rtc_time *tm) |
108 | { | 107 | { |
109 | tm->tm_mday = bcd2bin(calreg >> 0); | 108 | tm->tm_mday = bcd2bin(calreg >> 0); |
@@ -114,15 +113,21 @@ static void nuc900_rtc_bcd2bin(unsigned int timereg, | |||
114 | tm->tm_min = bcd2bin(timereg >> 8); | 113 | tm->tm_min = bcd2bin(timereg >> 8); |
115 | tm->tm_hour = bcd2bin(timereg >> 16); | 114 | tm->tm_hour = bcd2bin(timereg >> 16); |
116 | 115 | ||
117 | rtc_valid_tm(tm); | 116 | return rtc_valid_tm(tm); |
118 | } | 117 | } |
119 | 118 | ||
120 | static void nuc900_rtc_bin2bcd(struct rtc_time *settm, | 119 | static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, |
121 | struct nuc900_bcd_time *gettm) | 120 | struct nuc900_bcd_time *gettm) |
122 | { | 121 | { |
123 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; | 122 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; |
124 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; | 123 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; |
125 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | 124 | |
125 | if (settm->tm_year < 100) { | ||
126 | dev_warn(dev, "The year will be between 1970-1999, right?\n"); | ||
127 | gettm->bcd_year = bin2bcd(settm->tm_year) << 16; | ||
128 | } else { | ||
129 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | ||
130 | } | ||
126 | 131 | ||
127 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; | 132 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; |
128 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; | 133 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; |
@@ -165,9 +170,7 @@ static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
165 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); | 170 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); |
166 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); | 171 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); |
167 | 172 | ||
168 | nuc900_rtc_bcd2bin(timeval, clrval, tm); | 173 | return nuc900_rtc_bcd2bin(timeval, clrval, tm); |
169 | |||
170 | return 0; | ||
171 | } | 174 | } |
172 | 175 | ||
173 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | 176 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -177,7 +180,7 @@ static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
177 | unsigned long val; | 180 | unsigned long val; |
178 | int *err; | 181 | int *err; |
179 | 182 | ||
180 | nuc900_rtc_bin2bcd(tm, &gettm); | 183 | nuc900_rtc_bin2bcd(dev, tm, &gettm); |
181 | 184 | ||
182 | err = check_rtc_access_enable(rtc); | 185 | err = check_rtc_access_enable(rtc); |
183 | if (IS_ERR(err)) | 186 | if (IS_ERR(err)) |
@@ -200,9 +203,7 @@ static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
200 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); | 203 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); |
201 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); | 204 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); |
202 | 205 | ||
203 | nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); | 206 | return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); |
204 | |||
205 | return 0; | ||
206 | } | 207 | } |
207 | 208 | ||
208 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 209 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -212,7 +213,7 @@ static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
212 | unsigned long val; | 213 | unsigned long val; |
213 | int *err; | 214 | int *err; |
214 | 215 | ||
215 | nuc900_rtc_bin2bcd(&alrm->time, &tm); | 216 | nuc900_rtc_bin2bcd(dev, &alrm->time, &tm); |
216 | 217 | ||
217 | err = check_rtc_access_enable(rtc); | 218 | err = check_rtc_access_enable(rtc); |
218 | if (IS_ERR(err)) | 219 | if (IS_ERR(err)) |
@@ -268,29 +269,30 @@ static int __devinit nuc900_rtc_probe(struct platform_device *pdev) | |||
268 | goto fail2; | 269 | goto fail2; |
269 | } | 270 | } |
270 | 271 | ||
271 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | 272 | platform_set_drvdata(pdev, nuc900_rtc); |
272 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
273 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
274 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
275 | err = -EBUSY; | ||
276 | goto fail3; | ||
277 | } | ||
278 | 273 | ||
279 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | 274 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, |
280 | &nuc900_rtc_ops, THIS_MODULE); | 275 | &nuc900_rtc_ops, THIS_MODULE); |
281 | if (IS_ERR(nuc900_rtc->rtcdev)) { | 276 | if (IS_ERR(nuc900_rtc->rtcdev)) { |
282 | dev_err(&pdev->dev, "rtc device register faild\n"); | 277 | dev_err(&pdev->dev, "rtc device register faild\n"); |
283 | err = PTR_ERR(nuc900_rtc->rtcdev); | 278 | err = PTR_ERR(nuc900_rtc->rtcdev); |
284 | goto fail4; | 279 | goto fail3; |
285 | } | 280 | } |
286 | 281 | ||
287 | platform_set_drvdata(pdev, nuc900_rtc); | ||
288 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, | 282 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, |
289 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); | 283 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); |
290 | 284 | ||
285 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | ||
286 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
287 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
288 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
289 | err = -EBUSY; | ||
290 | goto fail4; | ||
291 | } | ||
292 | |||
291 | return 0; | 293 | return 0; |
292 | 294 | ||
293 | fail4: free_irq(nuc900_rtc->irq_num, nuc900_rtc); | 295 | fail4: rtc_device_unregister(nuc900_rtc->rtcdev); |
294 | fail3: iounmap(nuc900_rtc->rtc_reg); | 296 | fail3: iounmap(nuc900_rtc->rtc_reg); |
295 | fail2: release_mem_region(res->start, resource_size(res)); | 297 | fail2: release_mem_region(res->start, resource_size(res)); |
296 | fail1: kfree(nuc900_rtc); | 298 | fail1: kfree(nuc900_rtc); |
@@ -302,8 +304,8 @@ static int __devexit nuc900_rtc_remove(struct platform_device *pdev) | |||
302 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); | 304 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); |
303 | struct resource *res; | 305 | struct resource *res; |
304 | 306 | ||
305 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
306 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); | 307 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); |
308 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
307 | iounmap(nuc900_rtc->rtc_reg); | 309 | iounmap(nuc900_rtc->rtc_reg); |
308 | 310 | ||
309 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 311 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 1af42b4a6f59..b42c0c679266 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -172,14 +172,6 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
175 | struct pcf8563_limit | ||
176 | { | ||
177 | unsigned char reg; | ||
178 | unsigned char mask; | ||
179 | unsigned char min; | ||
180 | unsigned char max; | ||
181 | }; | ||
182 | |||
183 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | 175 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) |
184 | { | 176 | { |
185 | return pcf8563_get_datetime(to_i2c_client(dev), tm); | 177 | return pcf8563_get_datetime(to_i2c_client(dev), tm); |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 71bbefc3544e..6c418fe7f288 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/bcd.h> | 24 | #include <linux/bcd.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/version.h> | ||
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | 27 | ||
29 | /* | 28 | /* |
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index e9c6fa035989..29e867a1aaa8 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
@@ -87,7 +87,6 @@ struct pxa_rtc { | |||
87 | int irq_Alrm; | 87 | int irq_Alrm; |
88 | struct rtc_device *rtc; | 88 | struct rtc_device *rtc; |
89 | spinlock_t lock; /* Protects this structure */ | 89 | spinlock_t lock; /* Protects this structure */ |
90 | struct rtc_time rtc_alarm; | ||
91 | }; | 90 | }; |
92 | 91 | ||
93 | static u32 ryxr_calc(struct rtc_time *tm) | 92 | static u32 ryxr_calc(struct rtc_time *tm) |
@@ -236,32 +235,34 @@ static int pxa_periodic_irq_set_state(struct device *dev, int enabled) | |||
236 | return 0; | 235 | return 0; |
237 | } | 236 | } |
238 | 237 | ||
239 | static int pxa_rtc_ioctl(struct device *dev, unsigned int cmd, | 238 | static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled) |
240 | unsigned long arg) | ||
241 | { | 239 | { |
242 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); | 240 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); |
243 | int ret = 0; | ||
244 | 241 | ||
245 | spin_lock_irq(&pxa_rtc->lock); | 242 | spin_lock_irq(&pxa_rtc->lock); |
246 | switch (cmd) { | 243 | |
247 | case RTC_AIE_OFF: | 244 | if (enabled) |
248 | rtsr_clear_bits(pxa_rtc, RTSR_RDALE1); | ||
249 | break; | ||
250 | case RTC_AIE_ON: | ||
251 | rtsr_set_bits(pxa_rtc, RTSR_RDALE1); | 245 | rtsr_set_bits(pxa_rtc, RTSR_RDALE1); |
252 | break; | 246 | else |
253 | case RTC_UIE_OFF: | 247 | rtsr_clear_bits(pxa_rtc, RTSR_RDALE1); |
254 | rtsr_clear_bits(pxa_rtc, RTSR_HZE); | 248 | |
255 | break; | 249 | spin_unlock_irq(&pxa_rtc->lock); |
256 | case RTC_UIE_ON: | 250 | return 0; |
251 | } | ||
252 | |||
253 | static int pxa_update_irq_enable(struct device *dev, unsigned int enabled) | ||
254 | { | ||
255 | struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev); | ||
256 | |||
257 | spin_lock_irq(&pxa_rtc->lock); | ||
258 | |||
259 | if (enabled) | ||
257 | rtsr_set_bits(pxa_rtc, RTSR_HZE); | 260 | rtsr_set_bits(pxa_rtc, RTSR_HZE); |
258 | break; | 261 | else |
259 | default: | 262 | rtsr_clear_bits(pxa_rtc, RTSR_HZE); |
260 | ret = -ENOIOCTLCMD; | ||
261 | } | ||
262 | 263 | ||
263 | spin_unlock_irq(&pxa_rtc->lock); | 264 | spin_unlock_irq(&pxa_rtc->lock); |
264 | return ret; | 265 | return 0; |
265 | } | 266 | } |
266 | 267 | ||
267 | static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm) | 268 | static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -340,11 +341,12 @@ static int pxa_rtc_proc(struct device *dev, struct seq_file *seq) | |||
340 | static const struct rtc_class_ops pxa_rtc_ops = { | 341 | static const struct rtc_class_ops pxa_rtc_ops = { |
341 | .open = pxa_rtc_open, | 342 | .open = pxa_rtc_open, |
342 | .release = pxa_rtc_release, | 343 | .release = pxa_rtc_release, |
343 | .ioctl = pxa_rtc_ioctl, | ||
344 | .read_time = pxa_rtc_read_time, | 344 | .read_time = pxa_rtc_read_time, |
345 | .set_time = pxa_rtc_set_time, | 345 | .set_time = pxa_rtc_set_time, |
346 | .read_alarm = pxa_rtc_read_alarm, | 346 | .read_alarm = pxa_rtc_read_alarm, |
347 | .set_alarm = pxa_rtc_set_alarm, | 347 | .set_alarm = pxa_rtc_set_alarm, |
348 | .alarm_irq_enable = pxa_alarm_irq_enable, | ||
349 | .update_irq_enable = pxa_update_irq_enable, | ||
348 | .proc = pxa_rtc_proc, | 350 | .proc = pxa_rtc_proc, |
349 | .irq_set_state = pxa_periodic_irq_set_state, | 351 | .irq_set_state = pxa_periodic_irq_set_state, |
350 | .irq_set_freq = pxa_periodic_irq_set_freq, | 352 | .irq_set_freq = pxa_periodic_irq_set_freq, |
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c index a95f733bb15a..36eb66184461 100644 --- a/drivers/rtc/rtc-rp5c01.c +++ b/drivers/rtc/rtc-rp5c01.c | |||
@@ -63,6 +63,8 @@ enum { | |||
63 | struct rp5c01_priv { | 63 | struct rp5c01_priv { |
64 | u32 __iomem *regs; | 64 | u32 __iomem *regs; |
65 | struct rtc_device *rtc; | 65 | struct rtc_device *rtc; |
66 | spinlock_t lock; /* against concurrent RTC/NVRAM access */ | ||
67 | struct bin_attribute nvram_attr; | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, | 70 | static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, |
@@ -92,6 +94,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) | |||
92 | { | 94 | { |
93 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | 95 | struct rp5c01_priv *priv = dev_get_drvdata(dev); |
94 | 96 | ||
97 | spin_lock_irq(&priv->lock); | ||
95 | rp5c01_lock(priv); | 98 | rp5c01_lock(priv); |
96 | 99 | ||
97 | tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + | 100 | tm->tm_sec = rp5c01_read(priv, RP5C01_10_SECOND) * 10 + |
@@ -111,6 +114,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm) | |||
111 | tm->tm_year += 100; | 114 | tm->tm_year += 100; |
112 | 115 | ||
113 | rp5c01_unlock(priv); | 116 | rp5c01_unlock(priv); |
117 | spin_unlock_irq(&priv->lock); | ||
114 | 118 | ||
115 | return rtc_valid_tm(tm); | 119 | return rtc_valid_tm(tm); |
116 | } | 120 | } |
@@ -119,6 +123,7 @@ static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) | |||
119 | { | 123 | { |
120 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | 124 | struct rp5c01_priv *priv = dev_get_drvdata(dev); |
121 | 125 | ||
126 | spin_lock_irq(&priv->lock); | ||
122 | rp5c01_lock(priv); | 127 | rp5c01_lock(priv); |
123 | 128 | ||
124 | rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); | 129 | rp5c01_write(priv, tm->tm_sec / 10, RP5C01_10_SECOND); |
@@ -139,6 +144,7 @@ static int rp5c01_set_time(struct device *dev, struct rtc_time *tm) | |||
139 | rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); | 144 | rp5c01_write(priv, tm->tm_year % 10, RP5C01_1_YEAR); |
140 | 145 | ||
141 | rp5c01_unlock(priv); | 146 | rp5c01_unlock(priv); |
147 | spin_unlock_irq(&priv->lock); | ||
142 | return 0; | 148 | return 0; |
143 | } | 149 | } |
144 | 150 | ||
@@ -147,6 +153,72 @@ static const struct rtc_class_ops rp5c01_rtc_ops = { | |||
147 | .set_time = rp5c01_set_time, | 153 | .set_time = rp5c01_set_time, |
148 | }; | 154 | }; |
149 | 155 | ||
156 | |||
157 | /* | ||
158 | * The NVRAM is organized as 2 blocks of 13 nibbles of 4 bits. | ||
159 | * We provide access to them like AmigaOS does: the high nibble of each 8-bit | ||
160 | * byte is stored in BLOCK10, the low nibble in BLOCK11. | ||
161 | */ | ||
162 | |||
163 | static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj, | ||
164 | struct bin_attribute *bin_attr, | ||
165 | char *buf, loff_t pos, size_t size) | ||
166 | { | ||
167 | struct device *dev = container_of(kobj, struct device, kobj); | ||
168 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
169 | ssize_t count; | ||
170 | |||
171 | spin_lock_irq(&priv->lock); | ||
172 | |||
173 | for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { | ||
174 | u8 data; | ||
175 | |||
176 | rp5c01_write(priv, | ||
177 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10, | ||
178 | RP5C01_MODE); | ||
179 | data = rp5c01_read(priv, pos) << 4; | ||
180 | rp5c01_write(priv, | ||
181 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11, | ||
182 | RP5C01_MODE); | ||
183 | data |= rp5c01_read(priv, pos++); | ||
184 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
185 | RP5C01_MODE); | ||
186 | *buf++ = data; | ||
187 | } | ||
188 | |||
189 | spin_unlock_irq(&priv->lock); | ||
190 | return count; | ||
191 | } | ||
192 | |||
193 | static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj, | ||
194 | struct bin_attribute *bin_attr, | ||
195 | char *buf, loff_t pos, size_t size) | ||
196 | { | ||
197 | struct device *dev = container_of(kobj, struct device, kobj); | ||
198 | struct rp5c01_priv *priv = dev_get_drvdata(dev); | ||
199 | ssize_t count; | ||
200 | |||
201 | spin_lock_irq(&priv->lock); | ||
202 | |||
203 | for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) { | ||
204 | u8 data = *buf++; | ||
205 | |||
206 | rp5c01_write(priv, | ||
207 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK10, | ||
208 | RP5C01_MODE); | ||
209 | rp5c01_write(priv, data >> 4, pos); | ||
210 | rp5c01_write(priv, | ||
211 | RP5C01_MODE_TIMER_EN | RP5C01_MODE_RAM_BLOCK11, | ||
212 | RP5C01_MODE); | ||
213 | rp5c01_write(priv, data & 0xf, pos++); | ||
214 | rp5c01_write(priv, RP5C01_MODE_TIMER_EN | RP5C01_MODE_MODE01, | ||
215 | RP5C01_MODE); | ||
216 | } | ||
217 | |||
218 | spin_unlock_irq(&priv->lock); | ||
219 | return count; | ||
220 | } | ||
221 | |||
150 | static int __init rp5c01_rtc_probe(struct platform_device *dev) | 222 | static int __init rp5c01_rtc_probe(struct platform_device *dev) |
151 | { | 223 | { |
152 | struct resource *res; | 224 | struct resource *res; |
@@ -168,6 +240,15 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) | |||
168 | goto out_free_priv; | 240 | goto out_free_priv; |
169 | } | 241 | } |
170 | 242 | ||
243 | sysfs_bin_attr_init(&priv->nvram_attr); | ||
244 | priv->nvram_attr.attr.name = "nvram"; | ||
245 | priv->nvram_attr.attr.mode = S_IRUGO | S_IWUSR; | ||
246 | priv->nvram_attr.read = rp5c01_nvram_read; | ||
247 | priv->nvram_attr.write = rp5c01_nvram_write; | ||
248 | priv->nvram_attr.size = RP5C01_MODE; | ||
249 | |||
250 | spin_lock_init(&priv->lock); | ||
251 | |||
171 | rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, | 252 | rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops, |
172 | THIS_MODULE); | 253 | THIS_MODULE); |
173 | if (IS_ERR(rtc)) { | 254 | if (IS_ERR(rtc)) { |
@@ -177,8 +258,15 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev) | |||
177 | 258 | ||
178 | priv->rtc = rtc; | 259 | priv->rtc = rtc; |
179 | platform_set_drvdata(dev, priv); | 260 | platform_set_drvdata(dev, priv); |
261 | |||
262 | error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr); | ||
263 | if (error) | ||
264 | goto out_unregister; | ||
265 | |||
180 | return 0; | 266 | return 0; |
181 | 267 | ||
268 | out_unregister: | ||
269 | rtc_device_unregister(rtc); | ||
182 | out_unmap: | 270 | out_unmap: |
183 | iounmap(priv->regs); | 271 | iounmap(priv->regs); |
184 | out_free_priv: | 272 | out_free_priv: |
@@ -190,6 +278,7 @@ static int __exit rp5c01_rtc_remove(struct platform_device *dev) | |||
190 | { | 278 | { |
191 | struct rp5c01_priv *priv = platform_get_drvdata(dev); | 279 | struct rp5c01_priv *priv = platform_get_drvdata(dev); |
192 | 280 | ||
281 | sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr); | ||
193 | rtc_device_unregister(priv->rtc); | 282 | rtc_device_unregister(priv->rtc); |
194 | iounmap(priv->regs); | 283 | iounmap(priv->regs); |
195 | kfree(priv); | 284 | kfree(priv); |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 70b68d35f969..a0d3ec89d412 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -1,5 +1,8 @@ | |||
1 | /* drivers/rtc/rtc-s3c.c | 1 | /* drivers/rtc/rtc-s3c.c |
2 | * | 2 | * |
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
3 | * Copyright (c) 2004,2006 Simtec Electronics | 6 | * Copyright (c) 2004,2006 Simtec Electronics |
4 | * Ben Dooks, <ben@simtec.co.uk> | 7 | * Ben Dooks, <ben@simtec.co.uk> |
5 | * http://armlinux.simtec.co.uk/ | 8 | * http://armlinux.simtec.co.uk/ |
@@ -39,6 +42,7 @@ enum s3c_cpu_type { | |||
39 | 42 | ||
40 | static struct resource *s3c_rtc_mem; | 43 | static struct resource *s3c_rtc_mem; |
41 | 44 | ||
45 | static struct clk *rtc_clk; | ||
42 | static void __iomem *s3c_rtc_base; | 46 | static void __iomem *s3c_rtc_base; |
43 | static int s3c_rtc_alarmno = NO_IRQ; | 47 | static int s3c_rtc_alarmno = NO_IRQ; |
44 | static int s3c_rtc_tickno = NO_IRQ; | 48 | static int s3c_rtc_tickno = NO_IRQ; |
@@ -53,6 +57,10 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | |||
53 | struct rtc_device *rdev = id; | 57 | struct rtc_device *rdev = id; |
54 | 58 | ||
55 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); | 59 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); |
60 | |||
61 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
62 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); | ||
63 | |||
56 | return IRQ_HANDLED; | 64 | return IRQ_HANDLED; |
57 | } | 65 | } |
58 | 66 | ||
@@ -61,6 +69,10 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
61 | struct rtc_device *rdev = id; | 69 | struct rtc_device *rdev = id; |
62 | 70 | ||
63 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); | 71 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
72 | |||
73 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | ||
74 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); | ||
75 | |||
64 | return IRQ_HANDLED; | 76 | return IRQ_HANDLED; |
65 | } | 77 | } |
66 | 78 | ||
@@ -94,7 +106,7 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
94 | if (enabled) | 106 | if (enabled) |
95 | tmp |= S3C64XX_RTCCON_TICEN; | 107 | tmp |= S3C64XX_RTCCON_TICEN; |
96 | 108 | ||
97 | writeb(tmp, s3c_rtc_base + S3C2410_RTCCON); | 109 | writew(tmp, s3c_rtc_base + S3C2410_RTCCON); |
98 | } else { | 110 | } else { |
99 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); | 111 | tmp = readb(s3c_rtc_base + S3C2410_TICNT); |
100 | tmp &= ~S3C2410_TICNT_ENABLE; | 112 | tmp &= ~S3C2410_TICNT_ENABLE; |
@@ -128,7 +140,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
128 | 140 | ||
129 | tmp |= (rtc_dev->max_user_freq / freq)-1; | 141 | tmp |= (rtc_dev->max_user_freq / freq)-1; |
130 | 142 | ||
131 | writeb(tmp, s3c_rtc_base + S3C2410_TICNT); | 143 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); |
132 | spin_unlock_irq(&s3c_rtc_pie_lock); | 144 | spin_unlock_irq(&s3c_rtc_pie_lock); |
133 | 145 | ||
134 | return 0; | 146 | return 0; |
@@ -431,6 +443,10 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
431 | s3c_rtc_setpie(&dev->dev, 0); | 443 | s3c_rtc_setpie(&dev->dev, 0); |
432 | s3c_rtc_setaie(0); | 444 | s3c_rtc_setaie(0); |
433 | 445 | ||
446 | clk_disable(rtc_clk); | ||
447 | clk_put(rtc_clk); | ||
448 | rtc_clk = NULL; | ||
449 | |||
434 | iounmap(s3c_rtc_base); | 450 | iounmap(s3c_rtc_base); |
435 | release_resource(s3c_rtc_mem); | 451 | release_resource(s3c_rtc_mem); |
436 | kfree(s3c_rtc_mem); | 452 | kfree(s3c_rtc_mem); |
@@ -442,6 +458,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
442 | { | 458 | { |
443 | struct rtc_device *rtc; | 459 | struct rtc_device *rtc; |
444 | struct resource *res; | 460 | struct resource *res; |
461 | unsigned int tmp, i; | ||
445 | int ret; | 462 | int ret; |
446 | 463 | ||
447 | pr_debug("%s: probe=%p\n", __func__, pdev); | 464 | pr_debug("%s: probe=%p\n", __func__, pdev); |
@@ -488,6 +505,16 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
488 | goto err_nomap; | 505 | goto err_nomap; |
489 | } | 506 | } |
490 | 507 | ||
508 | rtc_clk = clk_get(&pdev->dev, "rtc"); | ||
509 | if (IS_ERR(rtc_clk)) { | ||
510 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); | ||
511 | ret = PTR_ERR(rtc_clk); | ||
512 | rtc_clk = NULL; | ||
513 | goto err_clk; | ||
514 | } | ||
515 | |||
516 | clk_enable(rtc_clk); | ||
517 | |||
491 | /* check to see if everything is setup correctly */ | 518 | /* check to see if everything is setup correctly */ |
492 | 519 | ||
493 | s3c_rtc_enable(pdev, 1); | 520 | s3c_rtc_enable(pdev, 1); |
@@ -510,6 +537,15 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
510 | 537 | ||
511 | s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; | 538 | s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; |
512 | 539 | ||
540 | /* Check RTC Time */ | ||
541 | |||
542 | for (i = S3C2410_RTCSEC; i <= S3C2410_RTCYEAR; i += 0x4) { | ||
543 | tmp = readb(s3c_rtc_base + i); | ||
544 | |||
545 | if ((tmp & 0xf) > 0x9 || ((tmp >> 4) & 0xf) > 0x9) | ||
546 | writeb(0, s3c_rtc_base + i); | ||
547 | } | ||
548 | |||
513 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 549 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
514 | rtc->max_user_freq = 32768; | 550 | rtc->max_user_freq = 32768; |
515 | else | 551 | else |
@@ -523,6 +559,10 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
523 | 559 | ||
524 | err_nortc: | 560 | err_nortc: |
525 | s3c_rtc_enable(pdev, 0); | 561 | s3c_rtc_enable(pdev, 0); |
562 | clk_disable(rtc_clk); | ||
563 | clk_put(rtc_clk); | ||
564 | |||
565 | err_clk: | ||
526 | iounmap(s3c_rtc_base); | 566 | iounmap(s3c_rtc_base); |
527 | 567 | ||
528 | err_nomap: | 568 | err_nomap: |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 1a84fae155e1..8373ca0de8e0 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1325,14 +1325,14 @@ static void __dasd_device_check_expire(struct dasd_device *device) | |||
1325 | if (device->discipline->term_IO(cqr) != 0) { | 1325 | if (device->discipline->term_IO(cqr) != 0) { |
1326 | /* Hmpf, try again in 5 sec */ | 1326 | /* Hmpf, try again in 5 sec */ |
1327 | dev_err(&device->cdev->dev, | 1327 | dev_err(&device->cdev->dev, |
1328 | "cqr %p timed out (%is) but cannot be " | 1328 | "cqr %p timed out (%lus) but cannot be " |
1329 | "ended, retrying in 5 s\n", | 1329 | "ended, retrying in 5 s\n", |
1330 | cqr, (cqr->expires/HZ)); | 1330 | cqr, (cqr->expires/HZ)); |
1331 | cqr->expires += 5*HZ; | 1331 | cqr->expires += 5*HZ; |
1332 | dasd_device_set_timer(device, 5*HZ); | 1332 | dasd_device_set_timer(device, 5*HZ); |
1333 | } else { | 1333 | } else { |
1334 | dev_err(&device->cdev->dev, | 1334 | dev_err(&device->cdev->dev, |
1335 | "cqr %p timed out (%is), %i retries " | 1335 | "cqr %p timed out (%lus), %i retries " |
1336 | "remaining\n", cqr, (cqr->expires/HZ), | 1336 | "remaining\n", cqr, (cqr->expires/HZ), |
1337 | cqr->retries); | 1337 | cqr->retries); |
1338 | } | 1338 | } |
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index a75ed3083a6a..8e4153d740f3 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -386,7 +386,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev) | |||
386 | struct chbk *p_ch; | 386 | struct chbk *p_ch; |
387 | 387 | ||
388 | CLAW_DBF_TEXT(4, trace, "claw_tx"); | 388 | CLAW_DBF_TEXT(4, trace, "claw_tx"); |
389 | p_ch=&privptr->channel[WRITE]; | 389 | p_ch = &privptr->channel[WRITE_CHANNEL]; |
390 | spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags); | 390 | spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags); |
391 | rc=claw_hw_tx( skb, dev, 1 ); | 391 | rc=claw_hw_tx( skb, dev, 1 ); |
392 | spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags); | 392 | spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags); |
@@ -407,7 +407,7 @@ static struct sk_buff * | |||
407 | claw_pack_skb(struct claw_privbk *privptr) | 407 | claw_pack_skb(struct claw_privbk *privptr) |
408 | { | 408 | { |
409 | struct sk_buff *new_skb,*held_skb; | 409 | struct sk_buff *new_skb,*held_skb; |
410 | struct chbk *p_ch = &privptr->channel[WRITE]; | 410 | struct chbk *p_ch = &privptr->channel[WRITE_CHANNEL]; |
411 | struct claw_env *p_env = privptr->p_env; | 411 | struct claw_env *p_env = privptr->p_env; |
412 | int pkt_cnt,pk_ind,so_far; | 412 | int pkt_cnt,pk_ind,so_far; |
413 | 413 | ||
@@ -515,15 +515,15 @@ claw_open(struct net_device *dev) | |||
515 | privptr->p_env->write_size=CLAW_FRAME_SIZE; | 515 | privptr->p_env->write_size=CLAW_FRAME_SIZE; |
516 | } | 516 | } |
517 | claw_set_busy(dev); | 517 | claw_set_busy(dev); |
518 | tasklet_init(&privptr->channel[READ].tasklet, claw_irq_tasklet, | 518 | tasklet_init(&privptr->channel[READ_CHANNEL].tasklet, claw_irq_tasklet, |
519 | (unsigned long) &privptr->channel[READ]); | 519 | (unsigned long) &privptr->channel[READ_CHANNEL]); |
520 | for ( i = 0; i < 2; i++) { | 520 | for ( i = 0; i < 2; i++) { |
521 | CLAW_DBF_TEXT_(2, trace, "opn_ch%d", i); | 521 | CLAW_DBF_TEXT_(2, trace, "opn_ch%d", i); |
522 | init_waitqueue_head(&privptr->channel[i].wait); | 522 | init_waitqueue_head(&privptr->channel[i].wait); |
523 | /* skb_queue_head_init(&p_ch->io_queue); */ | 523 | /* skb_queue_head_init(&p_ch->io_queue); */ |
524 | if (i == WRITE) | 524 | if (i == WRITE_CHANNEL) |
525 | skb_queue_head_init( | 525 | skb_queue_head_init( |
526 | &privptr->channel[WRITE].collect_queue); | 526 | &privptr->channel[WRITE_CHANNEL].collect_queue); |
527 | privptr->channel[i].flag_a = 0; | 527 | privptr->channel[i].flag_a = 0; |
528 | privptr->channel[i].IO_active = 0; | 528 | privptr->channel[i].IO_active = 0; |
529 | privptr->channel[i].flag &= ~CLAW_TIMER; | 529 | privptr->channel[i].flag &= ~CLAW_TIMER; |
@@ -551,12 +551,12 @@ claw_open(struct net_device *dev) | |||
551 | if((privptr->channel[i].flag & CLAW_TIMER) == 0x00) | 551 | if((privptr->channel[i].flag & CLAW_TIMER) == 0x00) |
552 | del_timer(&timer); | 552 | del_timer(&timer); |
553 | } | 553 | } |
554 | if ((((privptr->channel[READ].last_dstat | | 554 | if ((((privptr->channel[READ_CHANNEL].last_dstat | |
555 | privptr->channel[WRITE].last_dstat) & | 555 | privptr->channel[WRITE_CHANNEL].last_dstat) & |
556 | ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) || | 556 | ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) || |
557 | (((privptr->channel[READ].flag | | 557 | (((privptr->channel[READ_CHANNEL].flag | |
558 | privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) { | 558 | privptr->channel[WRITE_CHANNEL].flag) & CLAW_TIMER) != 0x00)) { |
559 | dev_info(&privptr->channel[READ].cdev->dev, | 559 | dev_info(&privptr->channel[READ_CHANNEL].cdev->dev, |
560 | "%s: remote side is not ready\n", dev->name); | 560 | "%s: remote side is not ready\n", dev->name); |
561 | CLAW_DBF_TEXT(2, trace, "notrdy"); | 561 | CLAW_DBF_TEXT(2, trace, "notrdy"); |
562 | 562 | ||
@@ -608,8 +608,8 @@ claw_open(struct net_device *dev) | |||
608 | } | 608 | } |
609 | } | 609 | } |
610 | privptr->buffs_alloc = 0; | 610 | privptr->buffs_alloc = 0; |
611 | privptr->channel[READ].flag= 0x00; | 611 | privptr->channel[READ_CHANNEL].flag = 0x00; |
612 | privptr->channel[WRITE].flag = 0x00; | 612 | privptr->channel[WRITE_CHANNEL].flag = 0x00; |
613 | privptr->p_buff_ccw=NULL; | 613 | privptr->p_buff_ccw=NULL; |
614 | privptr->p_buff_read=NULL; | 614 | privptr->p_buff_read=NULL; |
615 | privptr->p_buff_write=NULL; | 615 | privptr->p_buff_write=NULL; |
@@ -652,10 +652,10 @@ claw_irq_handler(struct ccw_device *cdev, | |||
652 | } | 652 | } |
653 | 653 | ||
654 | /* Try to extract channel from driver data. */ | 654 | /* Try to extract channel from driver data. */ |
655 | if (privptr->channel[READ].cdev == cdev) | 655 | if (privptr->channel[READ_CHANNEL].cdev == cdev) |
656 | p_ch = &privptr->channel[READ]; | 656 | p_ch = &privptr->channel[READ_CHANNEL]; |
657 | else if (privptr->channel[WRITE].cdev == cdev) | 657 | else if (privptr->channel[WRITE_CHANNEL].cdev == cdev) |
658 | p_ch = &privptr->channel[WRITE]; | 658 | p_ch = &privptr->channel[WRITE_CHANNEL]; |
659 | else { | 659 | else { |
660 | dev_warn(&cdev->dev, "The device is not a CLAW device\n"); | 660 | dev_warn(&cdev->dev, "The device is not a CLAW device\n"); |
661 | CLAW_DBF_TEXT(2, trace, "badchan"); | 661 | CLAW_DBF_TEXT(2, trace, "badchan"); |
@@ -813,7 +813,7 @@ claw_irq_handler(struct ccw_device *cdev, | |||
813 | claw_clearbit_busy(TB_TX, dev); | 813 | claw_clearbit_busy(TB_TX, dev); |
814 | claw_clear_busy(dev); | 814 | claw_clear_busy(dev); |
815 | } | 815 | } |
816 | p_ch_r = (struct chbk *)&privptr->channel[READ]; | 816 | p_ch_r = (struct chbk *)&privptr->channel[READ_CHANNEL]; |
817 | if (test_and_set_bit(CLAW_BH_ACTIVE, | 817 | if (test_and_set_bit(CLAW_BH_ACTIVE, |
818 | (void *)&p_ch_r->flag_a) == 0) | 818 | (void *)&p_ch_r->flag_a) == 0) |
819 | tasklet_schedule(&p_ch_r->tasklet); | 819 | tasklet_schedule(&p_ch_r->tasklet); |
@@ -878,13 +878,13 @@ claw_release(struct net_device *dev) | |||
878 | for ( i = 1; i >=0 ; i--) { | 878 | for ( i = 1; i >=0 ; i--) { |
879 | spin_lock_irqsave( | 879 | spin_lock_irqsave( |
880 | get_ccwdev_lock(privptr->channel[i].cdev), saveflags); | 880 | get_ccwdev_lock(privptr->channel[i].cdev), saveflags); |
881 | /* del_timer(&privptr->channel[READ].timer); */ | 881 | /* del_timer(&privptr->channel[READ_CHANNEL].timer); */ |
882 | privptr->channel[i].claw_state = CLAW_STOP; | 882 | privptr->channel[i].claw_state = CLAW_STOP; |
883 | privptr->channel[i].IO_active = 0; | 883 | privptr->channel[i].IO_active = 0; |
884 | parm = (unsigned long) &privptr->channel[i]; | 884 | parm = (unsigned long) &privptr->channel[i]; |
885 | if (i == WRITE) | 885 | if (i == WRITE_CHANNEL) |
886 | claw_purge_skb_queue( | 886 | claw_purge_skb_queue( |
887 | &privptr->channel[WRITE].collect_queue); | 887 | &privptr->channel[WRITE_CHANNEL].collect_queue); |
888 | rc = ccw_device_halt (privptr->channel[i].cdev, parm); | 888 | rc = ccw_device_halt (privptr->channel[i].cdev, parm); |
889 | if (privptr->system_validate_comp==0x00) /* never opened? */ | 889 | if (privptr->system_validate_comp==0x00) /* never opened? */ |
890 | init_waitqueue_head(&privptr->channel[i].wait); | 890 | init_waitqueue_head(&privptr->channel[i].wait); |
@@ -971,16 +971,16 @@ claw_release(struct net_device *dev) | |||
971 | privptr->mtc_skipping = 1; | 971 | privptr->mtc_skipping = 1; |
972 | privptr->mtc_offset=0; | 972 | privptr->mtc_offset=0; |
973 | 973 | ||
974 | if (((privptr->channel[READ].last_dstat | | 974 | if (((privptr->channel[READ_CHANNEL].last_dstat | |
975 | privptr->channel[WRITE].last_dstat) & | 975 | privptr->channel[WRITE_CHANNEL].last_dstat) & |
976 | ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { | 976 | ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { |
977 | dev_warn(&privptr->channel[READ].cdev->dev, | 977 | dev_warn(&privptr->channel[READ_CHANNEL].cdev->dev, |
978 | "Deactivating %s completed with incorrect" | 978 | "Deactivating %s completed with incorrect" |
979 | " subchannel status " | 979 | " subchannel status " |
980 | "(read %02x, write %02x)\n", | 980 | "(read %02x, write %02x)\n", |
981 | dev->name, | 981 | dev->name, |
982 | privptr->channel[READ].last_dstat, | 982 | privptr->channel[READ_CHANNEL].last_dstat, |
983 | privptr->channel[WRITE].last_dstat); | 983 | privptr->channel[WRITE_CHANNEL].last_dstat); |
984 | CLAW_DBF_TEXT(2, trace, "badclose"); | 984 | CLAW_DBF_TEXT(2, trace, "badclose"); |
985 | } | 985 | } |
986 | CLAW_DBF_TEXT(4, trace, "rlsexit"); | 986 | CLAW_DBF_TEXT(4, trace, "rlsexit"); |
@@ -1324,7 +1324,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) | |||
1324 | 1324 | ||
1325 | CLAW_DBF_TEXT(4, trace, "hw_tx"); | 1325 | CLAW_DBF_TEXT(4, trace, "hw_tx"); |
1326 | privptr = (struct claw_privbk *)(dev->ml_priv); | 1326 | privptr = (struct claw_privbk *)(dev->ml_priv); |
1327 | p_ch=(struct chbk *)&privptr->channel[WRITE]; | 1327 | p_ch = (struct chbk *)&privptr->channel[WRITE_CHANNEL]; |
1328 | p_env =privptr->p_env; | 1328 | p_env =privptr->p_env; |
1329 | claw_free_wrt_buf(dev); /* Clean up free chain if posible */ | 1329 | claw_free_wrt_buf(dev); /* Clean up free chain if posible */ |
1330 | /* scan the write queue to free any completed write packets */ | 1330 | /* scan the write queue to free any completed write packets */ |
@@ -1357,7 +1357,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) | |||
1357 | claw_strt_out_IO(dev ); | 1357 | claw_strt_out_IO(dev ); |
1358 | claw_free_wrt_buf( dev ); | 1358 | claw_free_wrt_buf( dev ); |
1359 | if (privptr->write_free_count==0) { | 1359 | if (privptr->write_free_count==0) { |
1360 | ch = &privptr->channel[WRITE]; | 1360 | ch = &privptr->channel[WRITE_CHANNEL]; |
1361 | atomic_inc(&skb->users); | 1361 | atomic_inc(&skb->users); |
1362 | skb_queue_tail(&ch->collect_queue, skb); | 1362 | skb_queue_tail(&ch->collect_queue, skb); |
1363 | goto Done; | 1363 | goto Done; |
@@ -1369,7 +1369,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) | |||
1369 | } | 1369 | } |
1370 | /* tx lock */ | 1370 | /* tx lock */ |
1371 | if (claw_test_and_setbit_busy(TB_TX,dev)) { /* set to busy */ | 1371 | if (claw_test_and_setbit_busy(TB_TX,dev)) { /* set to busy */ |
1372 | ch = &privptr->channel[WRITE]; | 1372 | ch = &privptr->channel[WRITE_CHANNEL]; |
1373 | atomic_inc(&skb->users); | 1373 | atomic_inc(&skb->users); |
1374 | skb_queue_tail(&ch->collect_queue, skb); | 1374 | skb_queue_tail(&ch->collect_queue, skb); |
1375 | claw_strt_out_IO(dev ); | 1375 | claw_strt_out_IO(dev ); |
@@ -1385,7 +1385,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) | |||
1385 | privptr->p_write_free_chain == NULL ) { | 1385 | privptr->p_write_free_chain == NULL ) { |
1386 | 1386 | ||
1387 | claw_setbit_busy(TB_NOBUFFER,dev); | 1387 | claw_setbit_busy(TB_NOBUFFER,dev); |
1388 | ch = &privptr->channel[WRITE]; | 1388 | ch = &privptr->channel[WRITE_CHANNEL]; |
1389 | atomic_inc(&skb->users); | 1389 | atomic_inc(&skb->users); |
1390 | skb_queue_tail(&ch->collect_queue, skb); | 1390 | skb_queue_tail(&ch->collect_queue, skb); |
1391 | CLAW_DBF_TEXT(2, trace, "clawbusy"); | 1391 | CLAW_DBF_TEXT(2, trace, "clawbusy"); |
@@ -1397,7 +1397,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) | |||
1397 | while (len_of_data > 0) { | 1397 | while (len_of_data > 0) { |
1398 | p_this_ccw=privptr->p_write_free_chain; /* get a block */ | 1398 | p_this_ccw=privptr->p_write_free_chain; /* get a block */ |
1399 | if (p_this_ccw == NULL) { /* lost the race */ | 1399 | if (p_this_ccw == NULL) { /* lost the race */ |
1400 | ch = &privptr->channel[WRITE]; | 1400 | ch = &privptr->channel[WRITE_CHANNEL]; |
1401 | atomic_inc(&skb->users); | 1401 | atomic_inc(&skb->users); |
1402 | skb_queue_tail(&ch->collect_queue, skb); | 1402 | skb_queue_tail(&ch->collect_queue, skb); |
1403 | goto Done2; | 1403 | goto Done2; |
@@ -2067,7 +2067,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) | |||
2067 | *catch up to each other */ | 2067 | *catch up to each other */ |
2068 | privptr = dev->ml_priv; | 2068 | privptr = dev->ml_priv; |
2069 | p_env=privptr->p_env; | 2069 | p_env=privptr->p_env; |
2070 | tdev = &privptr->channel[READ].cdev->dev; | 2070 | tdev = &privptr->channel[READ_CHANNEL].cdev->dev; |
2071 | memcpy( &temp_host_name, p_env->host_name, 8); | 2071 | memcpy( &temp_host_name, p_env->host_name, 8); |
2072 | memcpy( &temp_ws_name, p_env->adapter_name , 8); | 2072 | memcpy( &temp_ws_name, p_env->adapter_name , 8); |
2073 | dev_info(tdev, "%s: CLAW device %.8s: " | 2073 | dev_info(tdev, "%s: CLAW device %.8s: " |
@@ -2245,7 +2245,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) | |||
2245 | dev->name, temp_ws_name, | 2245 | dev->name, temp_ws_name, |
2246 | p_ctlbk->linkid); | 2246 | p_ctlbk->linkid); |
2247 | privptr->active_link_ID = p_ctlbk->linkid; | 2247 | privptr->active_link_ID = p_ctlbk->linkid; |
2248 | p_ch = &privptr->channel[WRITE]; | 2248 | p_ch = &privptr->channel[WRITE_CHANNEL]; |
2249 | wake_up(&p_ch->wait); /* wake up claw_open ( WRITE) */ | 2249 | wake_up(&p_ch->wait); /* wake up claw_open ( WRITE) */ |
2250 | break; | 2250 | break; |
2251 | case CONNECTION_RESPONSE: | 2251 | case CONNECTION_RESPONSE: |
@@ -2296,7 +2296,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) | |||
2296 | "%s: Confirmed Now packing\n", dev->name); | 2296 | "%s: Confirmed Now packing\n", dev->name); |
2297 | p_env->packing = DO_PACKED; | 2297 | p_env->packing = DO_PACKED; |
2298 | } | 2298 | } |
2299 | p_ch = &privptr->channel[WRITE]; | 2299 | p_ch = &privptr->channel[WRITE_CHANNEL]; |
2300 | wake_up(&p_ch->wait); | 2300 | wake_up(&p_ch->wait); |
2301 | } else { | 2301 | } else { |
2302 | dev_warn(tdev, "Activating %s failed because of" | 2302 | dev_warn(tdev, "Activating %s failed because of" |
@@ -2556,7 +2556,7 @@ unpack_read(struct net_device *dev ) | |||
2556 | p_packd=NULL; | 2556 | p_packd=NULL; |
2557 | privptr = dev->ml_priv; | 2557 | privptr = dev->ml_priv; |
2558 | 2558 | ||
2559 | p_dev = &privptr->channel[READ].cdev->dev; | 2559 | p_dev = &privptr->channel[READ_CHANNEL].cdev->dev; |
2560 | p_env = privptr->p_env; | 2560 | p_env = privptr->p_env; |
2561 | p_this_ccw=privptr->p_read_active_first; | 2561 | p_this_ccw=privptr->p_read_active_first; |
2562 | while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) { | 2562 | while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) { |
@@ -2728,7 +2728,7 @@ claw_strt_read (struct net_device *dev, int lock ) | |||
2728 | struct ccwbk*p_ccwbk; | 2728 | struct ccwbk*p_ccwbk; |
2729 | struct chbk *p_ch; | 2729 | struct chbk *p_ch; |
2730 | struct clawh *p_clawh; | 2730 | struct clawh *p_clawh; |
2731 | p_ch=&privptr->channel[READ]; | 2731 | p_ch = &privptr->channel[READ_CHANNEL]; |
2732 | 2732 | ||
2733 | CLAW_DBF_TEXT(4, trace, "StRdNter"); | 2733 | CLAW_DBF_TEXT(4, trace, "StRdNter"); |
2734 | p_clawh=(struct clawh *)privptr->p_claw_signal_blk; | 2734 | p_clawh=(struct clawh *)privptr->p_claw_signal_blk; |
@@ -2782,7 +2782,7 @@ claw_strt_out_IO( struct net_device *dev ) | |||
2782 | return; | 2782 | return; |
2783 | } | 2783 | } |
2784 | privptr = (struct claw_privbk *)dev->ml_priv; | 2784 | privptr = (struct claw_privbk *)dev->ml_priv; |
2785 | p_ch=&privptr->channel[WRITE]; | 2785 | p_ch = &privptr->channel[WRITE_CHANNEL]; |
2786 | 2786 | ||
2787 | CLAW_DBF_TEXT(4, trace, "strt_io"); | 2787 | CLAW_DBF_TEXT(4, trace, "strt_io"); |
2788 | p_first_ccw=privptr->p_write_active_first; | 2788 | p_first_ccw=privptr->p_write_active_first; |
@@ -2875,7 +2875,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev) | |||
2875 | if (dev->flags & IFF_RUNNING) | 2875 | if (dev->flags & IFF_RUNNING) |
2876 | claw_release(dev); | 2876 | claw_release(dev); |
2877 | if (privptr) { | 2877 | if (privptr) { |
2878 | privptr->channel[READ].ndev = NULL; /* say it's free */ | 2878 | privptr->channel[READ_CHANNEL].ndev = NULL; /* say it's free */ |
2879 | } | 2879 | } |
2880 | dev->ml_priv = NULL; | 2880 | dev->ml_priv = NULL; |
2881 | #ifdef MODULE | 2881 | #ifdef MODULE |
@@ -2960,18 +2960,18 @@ claw_new_device(struct ccwgroup_device *cgdev) | |||
2960 | struct ccw_dev_id dev_id; | 2960 | struct ccw_dev_id dev_id; |
2961 | 2961 | ||
2962 | dev_info(&cgdev->dev, "add for %s\n", | 2962 | dev_info(&cgdev->dev, "add for %s\n", |
2963 | dev_name(&cgdev->cdev[READ]->dev)); | 2963 | dev_name(&cgdev->cdev[READ_CHANNEL]->dev)); |
2964 | CLAW_DBF_TEXT(2, setup, "new_dev"); | 2964 | CLAW_DBF_TEXT(2, setup, "new_dev"); |
2965 | privptr = dev_get_drvdata(&cgdev->dev); | 2965 | privptr = dev_get_drvdata(&cgdev->dev); |
2966 | dev_set_drvdata(&cgdev->cdev[READ]->dev, privptr); | 2966 | dev_set_drvdata(&cgdev->cdev[READ_CHANNEL]->dev, privptr); |
2967 | dev_set_drvdata(&cgdev->cdev[WRITE]->dev, privptr); | 2967 | dev_set_drvdata(&cgdev->cdev[WRITE_CHANNEL]->dev, privptr); |
2968 | if (!privptr) | 2968 | if (!privptr) |
2969 | return -ENODEV; | 2969 | return -ENODEV; |
2970 | p_env = privptr->p_env; | 2970 | p_env = privptr->p_env; |
2971 | ccw_device_get_id(cgdev->cdev[READ], &dev_id); | 2971 | ccw_device_get_id(cgdev->cdev[READ_CHANNEL], &dev_id); |
2972 | p_env->devno[READ] = dev_id.devno; | 2972 | p_env->devno[READ_CHANNEL] = dev_id.devno; |
2973 | ccw_device_get_id(cgdev->cdev[WRITE], &dev_id); | 2973 | ccw_device_get_id(cgdev->cdev[WRITE_CHANNEL], &dev_id); |
2974 | p_env->devno[WRITE] = dev_id.devno; | 2974 | p_env->devno[WRITE_CHANNEL] = dev_id.devno; |
2975 | ret = add_channel(cgdev->cdev[0],0,privptr); | 2975 | ret = add_channel(cgdev->cdev[0],0,privptr); |
2976 | if (ret == 0) | 2976 | if (ret == 0) |
2977 | ret = add_channel(cgdev->cdev[1],1,privptr); | 2977 | ret = add_channel(cgdev->cdev[1],1,privptr); |
@@ -2980,14 +2980,14 @@ claw_new_device(struct ccwgroup_device *cgdev) | |||
2980 | " failed with error code %d\n", ret); | 2980 | " failed with error code %d\n", ret); |
2981 | goto out; | 2981 | goto out; |
2982 | } | 2982 | } |
2983 | ret = ccw_device_set_online(cgdev->cdev[READ]); | 2983 | ret = ccw_device_set_online(cgdev->cdev[READ_CHANNEL]); |
2984 | if (ret != 0) { | 2984 | if (ret != 0) { |
2985 | dev_warn(&cgdev->dev, | 2985 | dev_warn(&cgdev->dev, |
2986 | "Setting the read subchannel online" | 2986 | "Setting the read subchannel online" |
2987 | " failed with error code %d\n", ret); | 2987 | " failed with error code %d\n", ret); |
2988 | goto out; | 2988 | goto out; |
2989 | } | 2989 | } |
2990 | ret = ccw_device_set_online(cgdev->cdev[WRITE]); | 2990 | ret = ccw_device_set_online(cgdev->cdev[WRITE_CHANNEL]); |
2991 | if (ret != 0) { | 2991 | if (ret != 0) { |
2992 | dev_warn(&cgdev->dev, | 2992 | dev_warn(&cgdev->dev, |
2993 | "Setting the write subchannel online " | 2993 | "Setting the write subchannel online " |
@@ -3002,8 +3002,8 @@ claw_new_device(struct ccwgroup_device *cgdev) | |||
3002 | } | 3002 | } |
3003 | dev->ml_priv = privptr; | 3003 | dev->ml_priv = privptr; |
3004 | dev_set_drvdata(&cgdev->dev, privptr); | 3004 | dev_set_drvdata(&cgdev->dev, privptr); |
3005 | dev_set_drvdata(&cgdev->cdev[READ]->dev, privptr); | 3005 | dev_set_drvdata(&cgdev->cdev[READ_CHANNEL]->dev, privptr); |
3006 | dev_set_drvdata(&cgdev->cdev[WRITE]->dev, privptr); | 3006 | dev_set_drvdata(&cgdev->cdev[WRITE_CHANNEL]->dev, privptr); |
3007 | /* sysfs magic */ | 3007 | /* sysfs magic */ |
3008 | SET_NETDEV_DEV(dev, &cgdev->dev); | 3008 | SET_NETDEV_DEV(dev, &cgdev->dev); |
3009 | if (register_netdev(dev) != 0) { | 3009 | if (register_netdev(dev) != 0) { |
@@ -3021,16 +3021,16 @@ claw_new_device(struct ccwgroup_device *cgdev) | |||
3021 | goto out; | 3021 | goto out; |
3022 | } | 3022 | } |
3023 | } | 3023 | } |
3024 | privptr->channel[READ].ndev = dev; | 3024 | privptr->channel[READ_CHANNEL].ndev = dev; |
3025 | privptr->channel[WRITE].ndev = dev; | 3025 | privptr->channel[WRITE_CHANNEL].ndev = dev; |
3026 | privptr->p_env->ndev = dev; | 3026 | privptr->p_env->ndev = dev; |
3027 | 3027 | ||
3028 | dev_info(&cgdev->dev, "%s:readsize=%d writesize=%d " | 3028 | dev_info(&cgdev->dev, "%s:readsize=%d writesize=%d " |
3029 | "readbuffer=%d writebuffer=%d read=0x%04x write=0x%04x\n", | 3029 | "readbuffer=%d writebuffer=%d read=0x%04x write=0x%04x\n", |
3030 | dev->name, p_env->read_size, | 3030 | dev->name, p_env->read_size, |
3031 | p_env->write_size, p_env->read_buffers, | 3031 | p_env->write_size, p_env->read_buffers, |
3032 | p_env->write_buffers, p_env->devno[READ], | 3032 | p_env->write_buffers, p_env->devno[READ_CHANNEL], |
3033 | p_env->devno[WRITE]); | 3033 | p_env->devno[WRITE_CHANNEL]); |
3034 | dev_info(&cgdev->dev, "%s:host_name:%.8s, adapter_name " | 3034 | dev_info(&cgdev->dev, "%s:host_name:%.8s, adapter_name " |
3035 | ":%.8s api_type: %.8s\n", | 3035 | ":%.8s api_type: %.8s\n", |
3036 | dev->name, p_env->host_name, | 3036 | dev->name, p_env->host_name, |
@@ -3072,10 +3072,10 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) | |||
3072 | priv = dev_get_drvdata(&cgdev->dev); | 3072 | priv = dev_get_drvdata(&cgdev->dev); |
3073 | if (!priv) | 3073 | if (!priv) |
3074 | return -ENODEV; | 3074 | return -ENODEV; |
3075 | ndev = priv->channel[READ].ndev; | 3075 | ndev = priv->channel[READ_CHANNEL].ndev; |
3076 | if (ndev) { | 3076 | if (ndev) { |
3077 | /* Close the device */ | 3077 | /* Close the device */ |
3078 | dev_info(&cgdev->dev, "%s: shutting down \n", | 3078 | dev_info(&cgdev->dev, "%s: shutting down\n", |
3079 | ndev->name); | 3079 | ndev->name); |
3080 | if (ndev->flags & IFF_RUNNING) | 3080 | if (ndev->flags & IFF_RUNNING) |
3081 | ret = claw_release(ndev); | 3081 | ret = claw_release(ndev); |
@@ -3083,8 +3083,8 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) | |||
3083 | unregister_netdev(ndev); | 3083 | unregister_netdev(ndev); |
3084 | ndev->ml_priv = NULL; /* cgdev data, not ndev's to free */ | 3084 | ndev->ml_priv = NULL; /* cgdev data, not ndev's to free */ |
3085 | claw_free_netdevice(ndev, 1); | 3085 | claw_free_netdevice(ndev, 1); |
3086 | priv->channel[READ].ndev = NULL; | 3086 | priv->channel[READ_CHANNEL].ndev = NULL; |
3087 | priv->channel[WRITE].ndev = NULL; | 3087 | priv->channel[WRITE_CHANNEL].ndev = NULL; |
3088 | priv->p_env->ndev = NULL; | 3088 | priv->p_env->ndev = NULL; |
3089 | } | 3089 | } |
3090 | ccw_device_set_offline(cgdev->cdev[1]); | 3090 | ccw_device_set_offline(cgdev->cdev[1]); |
@@ -3115,8 +3115,8 @@ claw_remove_device(struct ccwgroup_device *cgdev) | |||
3115 | priv->channel[1].irb=NULL; | 3115 | priv->channel[1].irb=NULL; |
3116 | kfree(priv); | 3116 | kfree(priv); |
3117 | dev_set_drvdata(&cgdev->dev, NULL); | 3117 | dev_set_drvdata(&cgdev->dev, NULL); |
3118 | dev_set_drvdata(&cgdev->cdev[READ]->dev, NULL); | 3118 | dev_set_drvdata(&cgdev->cdev[READ_CHANNEL]->dev, NULL); |
3119 | dev_set_drvdata(&cgdev->cdev[WRITE]->dev, NULL); | 3119 | dev_set_drvdata(&cgdev->cdev[WRITE_CHANNEL]->dev, NULL); |
3120 | put_device(&cgdev->dev); | 3120 | put_device(&cgdev->dev); |
3121 | 3121 | ||
3122 | return; | 3122 | return; |
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 46d59a13db12..1bc5904df19f 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h | |||
@@ -74,8 +74,8 @@ | |||
74 | #define MAX_ENVELOPE_SIZE 65536 | 74 | #define MAX_ENVELOPE_SIZE 65536 |
75 | #define CLAW_DEFAULT_MTU_SIZE 4096 | 75 | #define CLAW_DEFAULT_MTU_SIZE 4096 |
76 | #define DEF_PACK_BUFSIZE 32768 | 76 | #define DEF_PACK_BUFSIZE 32768 |
77 | #define READ 0 | 77 | #define READ_CHANNEL 0 |
78 | #define WRITE 1 | 78 | #define WRITE_CHANNEL 1 |
79 | 79 | ||
80 | #define TB_TX 0 /* sk buffer handling in process */ | 80 | #define TB_TX 0 /* sk buffer handling in process */ |
81 | #define TB_STOP 1 /* network device stop in process */ | 81 | #define TB_STOP 1 /* network device stop in process */ |
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 70eb7f138414..8c921fc3511a 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c | |||
@@ -454,7 +454,7 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg) | |||
454 | if ((fsmstate == CTC_STATE_SETUPWAIT) && | 454 | if ((fsmstate == CTC_STATE_SETUPWAIT) && |
455 | (ch->protocol == CTCM_PROTO_OS390)) { | 455 | (ch->protocol == CTCM_PROTO_OS390)) { |
456 | /* OS/390 resp. z/OS */ | 456 | /* OS/390 resp. z/OS */ |
457 | if (CHANNEL_DIRECTION(ch->flags) == READ) { | 457 | if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) { |
458 | *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN; | 458 | *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN; |
459 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, | 459 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, |
460 | CTC_EVENT_TIMER, ch); | 460 | CTC_EVENT_TIMER, ch); |
@@ -472,14 +472,14 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg) | |||
472 | * if in compatibility mode, since VM TCP delays the initial | 472 | * if in compatibility mode, since VM TCP delays the initial |
473 | * frame until it has some data to send. | 473 | * frame until it has some data to send. |
474 | */ | 474 | */ |
475 | if ((CHANNEL_DIRECTION(ch->flags) == WRITE) || | 475 | if ((CHANNEL_DIRECTION(ch->flags) == CTCM_WRITE) || |
476 | (ch->protocol != CTCM_PROTO_S390)) | 476 | (ch->protocol != CTCM_PROTO_S390)) |
477 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); | 477 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); |
478 | 478 | ||
479 | *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN; | 479 | *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN; |
480 | ch->ccw[1].count = 2; /* Transfer only length */ | 480 | ch->ccw[1].count = 2; /* Transfer only length */ |
481 | 481 | ||
482 | fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ) | 482 | fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) |
483 | ? CTC_STATE_RXINIT : CTC_STATE_TXINIT); | 483 | ? CTC_STATE_RXINIT : CTC_STATE_TXINIT); |
484 | rc = ccw_device_start(ch->cdev, &ch->ccw[0], | 484 | rc = ccw_device_start(ch->cdev, &ch->ccw[0], |
485 | (unsigned long)ch, 0xff, 0); | 485 | (unsigned long)ch, 0xff, 0); |
@@ -495,7 +495,7 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg) | |||
495 | * reply from VM TCP which brings up the RX channel to it's | 495 | * reply from VM TCP which brings up the RX channel to it's |
496 | * final state. | 496 | * final state. |
497 | */ | 497 | */ |
498 | if ((CHANNEL_DIRECTION(ch->flags) == READ) && | 498 | if ((CHANNEL_DIRECTION(ch->flags) == CTCM_READ) && |
499 | (ch->protocol == CTCM_PROTO_S390)) { | 499 | (ch->protocol == CTCM_PROTO_S390)) { |
500 | struct net_device *dev = ch->netdev; | 500 | struct net_device *dev = ch->netdev; |
501 | struct ctcm_priv *priv = dev->ml_priv; | 501 | struct ctcm_priv *priv = dev->ml_priv; |
@@ -600,15 +600,15 @@ static void ctcm_chx_start(fsm_instance *fi, int event, void *arg) | |||
600 | int rc; | 600 | int rc; |
601 | 601 | ||
602 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s): %s", | 602 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s): %s", |
603 | CTCM_FUNTAIL, ch->id, | 603 | CTCM_FUNTAIL, ch->id, |
604 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); | 604 | (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? "RX" : "TX"); |
605 | 605 | ||
606 | if (ch->trans_skb != NULL) { | 606 | if (ch->trans_skb != NULL) { |
607 | clear_normalized_cda(&ch->ccw[1]); | 607 | clear_normalized_cda(&ch->ccw[1]); |
608 | dev_kfree_skb(ch->trans_skb); | 608 | dev_kfree_skb(ch->trans_skb); |
609 | ch->trans_skb = NULL; | 609 | ch->trans_skb = NULL; |
610 | } | 610 | } |
611 | if (CHANNEL_DIRECTION(ch->flags) == READ) { | 611 | if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) { |
612 | ch->ccw[1].cmd_code = CCW_CMD_READ; | 612 | ch->ccw[1].cmd_code = CCW_CMD_READ; |
613 | ch->ccw[1].flags = CCW_FLAG_SLI; | 613 | ch->ccw[1].flags = CCW_FLAG_SLI; |
614 | ch->ccw[1].count = 0; | 614 | ch->ccw[1].count = 0; |
@@ -622,7 +622,8 @@ static void ctcm_chx_start(fsm_instance *fi, int event, void *arg) | |||
622 | "%s(%s): %s trans_skb alloc delayed " | 622 | "%s(%s): %s trans_skb alloc delayed " |
623 | "until first transfer", | 623 | "until first transfer", |
624 | CTCM_FUNTAIL, ch->id, | 624 | CTCM_FUNTAIL, ch->id, |
625 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); | 625 | (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? |
626 | "RX" : "TX"); | ||
626 | } | 627 | } |
627 | ch->ccw[0].cmd_code = CCW_CMD_PREPARE; | 628 | ch->ccw[0].cmd_code = CCW_CMD_PREPARE; |
628 | ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC; | 629 | ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC; |
@@ -720,7 +721,7 @@ static void ctcm_chx_cleanup(fsm_instance *fi, int state, | |||
720 | 721 | ||
721 | ch->th_seg = 0x00; | 722 | ch->th_seg = 0x00; |
722 | ch->th_seq_num = 0x00; | 723 | ch->th_seq_num = 0x00; |
723 | if (CHANNEL_DIRECTION(ch->flags) == READ) { | 724 | if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) { |
724 | skb_queue_purge(&ch->io_queue); | 725 | skb_queue_purge(&ch->io_queue); |
725 | fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev); | 726 | fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev); |
726 | } else { | 727 | } else { |
@@ -799,7 +800,8 @@ static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg) | |||
799 | fsm_newstate(fi, CTC_STATE_STARTRETRY); | 800 | fsm_newstate(fi, CTC_STATE_STARTRETRY); |
800 | fsm_deltimer(&ch->timer); | 801 | fsm_deltimer(&ch->timer); |
801 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); | 802 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); |
802 | if (!IS_MPC(ch) && (CHANNEL_DIRECTION(ch->flags) == READ)) { | 803 | if (!IS_MPC(ch) && |
804 | (CHANNEL_DIRECTION(ch->flags) == CTCM_READ)) { | ||
803 | int rc = ccw_device_halt(ch->cdev, (unsigned long)ch); | 805 | int rc = ccw_device_halt(ch->cdev, (unsigned long)ch); |
804 | if (rc != 0) | 806 | if (rc != 0) |
805 | ctcm_ccw_check_rc(ch, rc, | 807 | ctcm_ccw_check_rc(ch, rc, |
@@ -811,10 +813,10 @@ static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg) | |||
811 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT, | 813 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT, |
812 | "%s(%s) : %s error during %s channel setup state=%s\n", | 814 | "%s(%s) : %s error during %s channel setup state=%s\n", |
813 | CTCM_FUNTAIL, dev->name, ctc_ch_event_names[event], | 815 | CTCM_FUNTAIL, dev->name, ctc_ch_event_names[event], |
814 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX", | 816 | (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? "RX" : "TX", |
815 | fsm_getstate_str(fi)); | 817 | fsm_getstate_str(fi)); |
816 | 818 | ||
817 | if (CHANNEL_DIRECTION(ch->flags) == READ) { | 819 | if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) { |
818 | fsm_newstate(fi, CTC_STATE_RXERR); | 820 | fsm_newstate(fi, CTC_STATE_RXERR); |
819 | fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev); | 821 | fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev); |
820 | } else { | 822 | } else { |
@@ -945,7 +947,7 @@ static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg) | |||
945 | fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev); | 947 | fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev); |
946 | 948 | ||
947 | fsm_newstate(fi, CTC_STATE_DTERM); | 949 | fsm_newstate(fi, CTC_STATE_DTERM); |
948 | ch2 = priv->channel[WRITE]; | 950 | ch2 = priv->channel[CTCM_WRITE]; |
949 | fsm_newstate(ch2->fsm, CTC_STATE_DTERM); | 951 | fsm_newstate(ch2->fsm, CTC_STATE_DTERM); |
950 | 952 | ||
951 | ccw_device_halt(ch->cdev, (unsigned long)ch); | 953 | ccw_device_halt(ch->cdev, (unsigned long)ch); |
@@ -1074,13 +1076,13 @@ static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg) | |||
1074 | fsm_deltimer(&ch->timer); | 1076 | fsm_deltimer(&ch->timer); |
1075 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, | 1077 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
1076 | "%s: %s: %s unrecoverable channel error", | 1078 | "%s: %s: %s unrecoverable channel error", |
1077 | CTCM_FUNTAIL, ch->id, rd == READ ? "RX" : "TX"); | 1079 | CTCM_FUNTAIL, ch->id, rd == CTCM_READ ? "RX" : "TX"); |
1078 | 1080 | ||
1079 | if (IS_MPC(ch)) { | 1081 | if (IS_MPC(ch)) { |
1080 | priv->stats.tx_dropped++; | 1082 | priv->stats.tx_dropped++; |
1081 | priv->stats.tx_errors++; | 1083 | priv->stats.tx_errors++; |
1082 | } | 1084 | } |
1083 | if (rd == READ) { | 1085 | if (rd == CTCM_READ) { |
1084 | fsm_newstate(fi, CTC_STATE_RXERR); | 1086 | fsm_newstate(fi, CTC_STATE_RXERR); |
1085 | fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev); | 1087 | fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev); |
1086 | } else { | 1088 | } else { |
@@ -1503,7 +1505,7 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg) | |||
1503 | switch (fsm_getstate(fi)) { | 1505 | switch (fsm_getstate(fi)) { |
1504 | case CTC_STATE_STARTRETRY: | 1506 | case CTC_STATE_STARTRETRY: |
1505 | case CTC_STATE_SETUPWAIT: | 1507 | case CTC_STATE_SETUPWAIT: |
1506 | if (CHANNEL_DIRECTION(ch->flags) == READ) { | 1508 | if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) { |
1507 | ctcmpc_chx_rxidle(fi, event, arg); | 1509 | ctcmpc_chx_rxidle(fi, event, arg); |
1508 | } else { | 1510 | } else { |
1509 | fsm_newstate(fi, CTC_STATE_TXIDLE); | 1511 | fsm_newstate(fi, CTC_STATE_TXIDLE); |
@@ -1514,7 +1516,7 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg) | |||
1514 | break; | 1516 | break; |
1515 | }; | 1517 | }; |
1516 | 1518 | ||
1517 | fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ) | 1519 | fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) |
1518 | ? CTC_STATE_RXINIT : CTC_STATE_TXINIT); | 1520 | ? CTC_STATE_RXINIT : CTC_STATE_TXINIT); |
1519 | 1521 | ||
1520 | done: | 1522 | done: |
@@ -1753,8 +1755,8 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg) | |||
1753 | struct net_device *dev = ach->netdev; | 1755 | struct net_device *dev = ach->netdev; |
1754 | struct ctcm_priv *priv = dev->ml_priv; | 1756 | struct ctcm_priv *priv = dev->ml_priv; |
1755 | struct mpc_group *grp = priv->mpcg; | 1757 | struct mpc_group *grp = priv->mpcg; |
1756 | struct channel *wch = priv->channel[WRITE]; | 1758 | struct channel *wch = priv->channel[CTCM_WRITE]; |
1757 | struct channel *rch = priv->channel[READ]; | 1759 | struct channel *rch = priv->channel[CTCM_READ]; |
1758 | struct sk_buff *skb; | 1760 | struct sk_buff *skb; |
1759 | struct th_sweep *header; | 1761 | struct th_sweep *header; |
1760 | int rc = 0; | 1762 | int rc = 0; |
@@ -2070,7 +2072,7 @@ static void dev_action_start(fsm_instance *fi, int event, void *arg) | |||
2070 | fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX); | 2072 | fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX); |
2071 | if (IS_MPC(priv)) | 2073 | if (IS_MPC(priv)) |
2072 | priv->mpcg->channels_terminating = 0; | 2074 | priv->mpcg->channels_terminating = 0; |
2073 | for (direction = READ; direction <= WRITE; direction++) { | 2075 | for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) { |
2074 | struct channel *ch = priv->channel[direction]; | 2076 | struct channel *ch = priv->channel[direction]; |
2075 | fsm_event(ch->fsm, CTC_EVENT_START, ch); | 2077 | fsm_event(ch->fsm, CTC_EVENT_START, ch); |
2076 | } | 2078 | } |
@@ -2092,7 +2094,7 @@ static void dev_action_stop(fsm_instance *fi, int event, void *arg) | |||
2092 | CTCMY_DBF_DEV_NAME(SETUP, dev, ""); | 2094 | CTCMY_DBF_DEV_NAME(SETUP, dev, ""); |
2093 | 2095 | ||
2094 | fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX); | 2096 | fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX); |
2095 | for (direction = READ; direction <= WRITE; direction++) { | 2097 | for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) { |
2096 | struct channel *ch = priv->channel[direction]; | 2098 | struct channel *ch = priv->channel[direction]; |
2097 | fsm_event(ch->fsm, CTC_EVENT_STOP, ch); | 2099 | fsm_event(ch->fsm, CTC_EVENT_STOP, ch); |
2098 | ch->th_seq_num = 0x00; | 2100 | ch->th_seq_num = 0x00; |
@@ -2183,11 +2185,11 @@ static void dev_action_chup(fsm_instance *fi, int event, void *arg) | |||
2183 | 2185 | ||
2184 | if (IS_MPC(priv)) { | 2186 | if (IS_MPC(priv)) { |
2185 | if (event == DEV_EVENT_RXUP) | 2187 | if (event == DEV_EVENT_RXUP) |
2186 | mpc_channel_action(priv->channel[READ], | 2188 | mpc_channel_action(priv->channel[CTCM_READ], |
2187 | READ, MPC_CHANNEL_ADD); | 2189 | CTCM_READ, MPC_CHANNEL_ADD); |
2188 | else | 2190 | else |
2189 | mpc_channel_action(priv->channel[WRITE], | 2191 | mpc_channel_action(priv->channel[CTCM_WRITE], |
2190 | WRITE, MPC_CHANNEL_ADD); | 2192 | CTCM_WRITE, MPC_CHANNEL_ADD); |
2191 | } | 2193 | } |
2192 | } | 2194 | } |
2193 | 2195 | ||
@@ -2239,11 +2241,11 @@ static void dev_action_chdown(fsm_instance *fi, int event, void *arg) | |||
2239 | } | 2241 | } |
2240 | if (IS_MPC(priv)) { | 2242 | if (IS_MPC(priv)) { |
2241 | if (event == DEV_EVENT_RXDOWN) | 2243 | if (event == DEV_EVENT_RXDOWN) |
2242 | mpc_channel_action(priv->channel[READ], | 2244 | mpc_channel_action(priv->channel[CTCM_READ], |
2243 | READ, MPC_CHANNEL_REMOVE); | 2245 | CTCM_READ, MPC_CHANNEL_REMOVE); |
2244 | else | 2246 | else |
2245 | mpc_channel_action(priv->channel[WRITE], | 2247 | mpc_channel_action(priv->channel[CTCM_WRITE], |
2246 | WRITE, MPC_CHANNEL_REMOVE); | 2248 | CTCM_WRITE, MPC_CHANNEL_REMOVE); |
2247 | } | 2249 | } |
2248 | } | 2250 | } |
2249 | 2251 | ||
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 4ecafbf91211..6edf20b62de5 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -267,7 +267,7 @@ static struct channel *channel_get(enum ctcm_channel_types type, | |||
267 | else { | 267 | else { |
268 | ch->flags |= CHANNEL_FLAGS_INUSE; | 268 | ch->flags |= CHANNEL_FLAGS_INUSE; |
269 | ch->flags &= ~CHANNEL_FLAGS_RWMASK; | 269 | ch->flags &= ~CHANNEL_FLAGS_RWMASK; |
270 | ch->flags |= (direction == WRITE) | 270 | ch->flags |= (direction == CTCM_WRITE) |
271 | ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ; | 271 | ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ; |
272 | fsm_newstate(ch->fsm, CTC_STATE_STOPPED); | 272 | fsm_newstate(ch->fsm, CTC_STATE_STOPPED); |
273 | } | 273 | } |
@@ -388,7 +388,8 @@ int ctcm_ch_alloc_buffer(struct channel *ch) | |||
388 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, | 388 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
389 | "%s(%s): %s trans_skb allocation error", | 389 | "%s(%s): %s trans_skb allocation error", |
390 | CTCM_FUNTAIL, ch->id, | 390 | CTCM_FUNTAIL, ch->id, |
391 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); | 391 | (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? |
392 | "RX" : "TX"); | ||
392 | return -ENOMEM; | 393 | return -ENOMEM; |
393 | } | 394 | } |
394 | 395 | ||
@@ -399,7 +400,8 @@ int ctcm_ch_alloc_buffer(struct channel *ch) | |||
399 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, | 400 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
400 | "%s(%s): %s set norm_cda failed", | 401 | "%s(%s): %s set norm_cda failed", |
401 | CTCM_FUNTAIL, ch->id, | 402 | CTCM_FUNTAIL, ch->id, |
402 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); | 403 | (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? |
404 | "RX" : "TX"); | ||
403 | return -ENOMEM; | 405 | return -ENOMEM; |
404 | } | 406 | } |
405 | 407 | ||
@@ -603,14 +605,14 @@ static void ctcmpc_send_sweep_req(struct channel *rch) | |||
603 | 605 | ||
604 | priv = dev->ml_priv; | 606 | priv = dev->ml_priv; |
605 | grp = priv->mpcg; | 607 | grp = priv->mpcg; |
606 | ch = priv->channel[WRITE]; | 608 | ch = priv->channel[CTCM_WRITE]; |
607 | 609 | ||
608 | /* sweep processing is not complete until response and request */ | 610 | /* sweep processing is not complete until response and request */ |
609 | /* has completed for all read channels in group */ | 611 | /* has completed for all read channels in group */ |
610 | if (grp->in_sweep == 0) { | 612 | if (grp->in_sweep == 0) { |
611 | grp->in_sweep = 1; | 613 | grp->in_sweep = 1; |
612 | grp->sweep_rsp_pend_num = grp->active_channels[READ]; | 614 | grp->sweep_rsp_pend_num = grp->active_channels[CTCM_READ]; |
613 | grp->sweep_req_pend_num = grp->active_channels[READ]; | 615 | grp->sweep_req_pend_num = grp->active_channels[CTCM_READ]; |
614 | } | 616 | } |
615 | 617 | ||
616 | sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA); | 618 | sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA); |
@@ -911,7 +913,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) | |||
911 | return NETDEV_TX_BUSY; | 913 | return NETDEV_TX_BUSY; |
912 | 914 | ||
913 | dev->trans_start = jiffies; | 915 | dev->trans_start = jiffies; |
914 | if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0) | 916 | if (ctcm_transmit_skb(priv->channel[CTCM_WRITE], skb) != 0) |
915 | return NETDEV_TX_BUSY; | 917 | return NETDEV_TX_BUSY; |
916 | return NETDEV_TX_OK; | 918 | return NETDEV_TX_OK; |
917 | } | 919 | } |
@@ -994,7 +996,7 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) | |||
994 | } | 996 | } |
995 | 997 | ||
996 | dev->trans_start = jiffies; | 998 | dev->trans_start = jiffies; |
997 | if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) { | 999 | if (ctcmpc_transmit_skb(priv->channel[CTCM_WRITE], skb) != 0) { |
998 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, | 1000 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, |
999 | "%s(%s): device error - dropped", | 1001 | "%s(%s): device error - dropped", |
1000 | CTCM_FUNTAIL, dev->name); | 1002 | CTCM_FUNTAIL, dev->name); |
@@ -1035,7 +1037,7 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu) | |||
1035 | return -EINVAL; | 1037 | return -EINVAL; |
1036 | 1038 | ||
1037 | priv = dev->ml_priv; | 1039 | priv = dev->ml_priv; |
1038 | max_bufsize = priv->channel[READ]->max_bufsize; | 1040 | max_bufsize = priv->channel[CTCM_READ]->max_bufsize; |
1039 | 1041 | ||
1040 | if (IS_MPC(priv)) { | 1042 | if (IS_MPC(priv)) { |
1041 | if (new_mtu > max_bufsize - TH_HEADER_LENGTH) | 1043 | if (new_mtu > max_bufsize - TH_HEADER_LENGTH) |
@@ -1226,10 +1228,10 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1226 | priv = dev_get_drvdata(&cgdev->dev); | 1228 | priv = dev_get_drvdata(&cgdev->dev); |
1227 | 1229 | ||
1228 | /* Try to extract channel from driver data. */ | 1230 | /* Try to extract channel from driver data. */ |
1229 | if (priv->channel[READ]->cdev == cdev) | 1231 | if (priv->channel[CTCM_READ]->cdev == cdev) |
1230 | ch = priv->channel[READ]; | 1232 | ch = priv->channel[CTCM_READ]; |
1231 | else if (priv->channel[WRITE]->cdev == cdev) | 1233 | else if (priv->channel[CTCM_WRITE]->cdev == cdev) |
1232 | ch = priv->channel[WRITE]; | 1234 | ch = priv->channel[CTCM_WRITE]; |
1233 | else { | 1235 | else { |
1234 | dev_err(&cdev->dev, | 1236 | dev_err(&cdev->dev, |
1235 | "%s: Internal error: Can't determine channel for " | 1237 | "%s: Internal error: Can't determine channel for " |
@@ -1587,13 +1589,13 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1587 | goto out_ccw2; | 1589 | goto out_ccw2; |
1588 | } | 1590 | } |
1589 | 1591 | ||
1590 | for (direction = READ; direction <= WRITE; direction++) { | 1592 | for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) { |
1591 | priv->channel[direction] = | 1593 | priv->channel[direction] = |
1592 | channel_get(type, direction == READ ? read_id : write_id, | 1594 | channel_get(type, direction == CTCM_READ ? |
1593 | direction); | 1595 | read_id : write_id, direction); |
1594 | if (priv->channel[direction] == NULL) { | 1596 | if (priv->channel[direction] == NULL) { |
1595 | if (direction == WRITE) | 1597 | if (direction == CTCM_WRITE) |
1596 | channel_free(priv->channel[READ]); | 1598 | channel_free(priv->channel[CTCM_READ]); |
1597 | goto out_dev; | 1599 | goto out_dev; |
1598 | } | 1600 | } |
1599 | priv->channel[direction]->netdev = dev; | 1601 | priv->channel[direction]->netdev = dev; |
@@ -1617,13 +1619,13 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1617 | 1619 | ||
1618 | dev_info(&dev->dev, | 1620 | dev_info(&dev->dev, |
1619 | "setup OK : r/w = %s/%s, protocol : %d\n", | 1621 | "setup OK : r/w = %s/%s, protocol : %d\n", |
1620 | priv->channel[READ]->id, | 1622 | priv->channel[CTCM_READ]->id, |
1621 | priv->channel[WRITE]->id, priv->protocol); | 1623 | priv->channel[CTCM_WRITE]->id, priv->protocol); |
1622 | 1624 | ||
1623 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, | 1625 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1624 | "setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name, | 1626 | "setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name, |
1625 | priv->channel[READ]->id, | 1627 | priv->channel[CTCM_READ]->id, |
1626 | priv->channel[WRITE]->id, priv->protocol); | 1628 | priv->channel[CTCM_WRITE]->id, priv->protocol); |
1627 | 1629 | ||
1628 | return 0; | 1630 | return 0; |
1629 | out_unregister: | 1631 | out_unregister: |
@@ -1635,10 +1637,10 @@ out_ccw2: | |||
1635 | out_ccw1: | 1637 | out_ccw1: |
1636 | ccw_device_set_offline(cgdev->cdev[0]); | 1638 | ccw_device_set_offline(cgdev->cdev[0]); |
1637 | out_remove_channel2: | 1639 | out_remove_channel2: |
1638 | readc = channel_get(type, read_id, READ); | 1640 | readc = channel_get(type, read_id, CTCM_READ); |
1639 | channel_remove(readc); | 1641 | channel_remove(readc); |
1640 | out_remove_channel1: | 1642 | out_remove_channel1: |
1641 | writec = channel_get(type, write_id, WRITE); | 1643 | writec = channel_get(type, write_id, CTCM_WRITE); |
1642 | channel_remove(writec); | 1644 | channel_remove(writec); |
1643 | out_err_result: | 1645 | out_err_result: |
1644 | return result; | 1646 | return result; |
@@ -1660,19 +1662,19 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev) | |||
1660 | if (!priv) | 1662 | if (!priv) |
1661 | return -ENODEV; | 1663 | return -ENODEV; |
1662 | 1664 | ||
1663 | if (priv->channel[READ]) { | 1665 | if (priv->channel[CTCM_READ]) { |
1664 | dev = priv->channel[READ]->netdev; | 1666 | dev = priv->channel[CTCM_READ]->netdev; |
1665 | CTCM_DBF_DEV(SETUP, dev, ""); | 1667 | CTCM_DBF_DEV(SETUP, dev, ""); |
1666 | /* Close the device */ | 1668 | /* Close the device */ |
1667 | ctcm_close(dev); | 1669 | ctcm_close(dev); |
1668 | dev->flags &= ~IFF_RUNNING; | 1670 | dev->flags &= ~IFF_RUNNING; |
1669 | ctcm_remove_attributes(&cgdev->dev); | 1671 | ctcm_remove_attributes(&cgdev->dev); |
1670 | channel_free(priv->channel[READ]); | 1672 | channel_free(priv->channel[CTCM_READ]); |
1671 | } else | 1673 | } else |
1672 | dev = NULL; | 1674 | dev = NULL; |
1673 | 1675 | ||
1674 | if (priv->channel[WRITE]) | 1676 | if (priv->channel[CTCM_WRITE]) |
1675 | channel_free(priv->channel[WRITE]); | 1677 | channel_free(priv->channel[CTCM_WRITE]); |
1676 | 1678 | ||
1677 | if (dev) { | 1679 | if (dev) { |
1678 | unregister_netdev(dev); | 1680 | unregister_netdev(dev); |
@@ -1685,11 +1687,11 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev) | |||
1685 | ccw_device_set_offline(cgdev->cdev[1]); | 1687 | ccw_device_set_offline(cgdev->cdev[1]); |
1686 | ccw_device_set_offline(cgdev->cdev[0]); | 1688 | ccw_device_set_offline(cgdev->cdev[0]); |
1687 | 1689 | ||
1688 | if (priv->channel[READ]) | 1690 | if (priv->channel[CTCM_READ]) |
1689 | channel_remove(priv->channel[READ]); | 1691 | channel_remove(priv->channel[CTCM_READ]); |
1690 | if (priv->channel[WRITE]) | 1692 | if (priv->channel[CTCM_WRITE]) |
1691 | channel_remove(priv->channel[WRITE]); | 1693 | channel_remove(priv->channel[CTCM_WRITE]); |
1692 | priv->channel[READ] = priv->channel[WRITE] = NULL; | 1694 | priv->channel[CTCM_READ] = priv->channel[CTCM_WRITE] = NULL; |
1693 | 1695 | ||
1694 | return 0; | 1696 | return 0; |
1695 | 1697 | ||
@@ -1720,11 +1722,11 @@ static int ctcm_pm_suspend(struct ccwgroup_device *gdev) | |||
1720 | 1722 | ||
1721 | if (gdev->state == CCWGROUP_OFFLINE) | 1723 | if (gdev->state == CCWGROUP_OFFLINE) |
1722 | return 0; | 1724 | return 0; |
1723 | netif_device_detach(priv->channel[READ]->netdev); | 1725 | netif_device_detach(priv->channel[CTCM_READ]->netdev); |
1724 | ctcm_close(priv->channel[READ]->netdev); | 1726 | ctcm_close(priv->channel[CTCM_READ]->netdev); |
1725 | if (!wait_event_timeout(priv->fsm->wait_q, | 1727 | if (!wait_event_timeout(priv->fsm->wait_q, |
1726 | fsm_getstate(priv->fsm) == DEV_STATE_STOPPED, CTCM_TIME_5_SEC)) { | 1728 | fsm_getstate(priv->fsm) == DEV_STATE_STOPPED, CTCM_TIME_5_SEC)) { |
1727 | netif_device_attach(priv->channel[READ]->netdev); | 1729 | netif_device_attach(priv->channel[CTCM_READ]->netdev); |
1728 | return -EBUSY; | 1730 | return -EBUSY; |
1729 | } | 1731 | } |
1730 | ccw_device_set_offline(gdev->cdev[1]); | 1732 | ccw_device_set_offline(gdev->cdev[1]); |
@@ -1745,9 +1747,9 @@ static int ctcm_pm_resume(struct ccwgroup_device *gdev) | |||
1745 | rc = ccw_device_set_online(gdev->cdev[0]); | 1747 | rc = ccw_device_set_online(gdev->cdev[0]); |
1746 | if (rc) | 1748 | if (rc) |
1747 | goto err_out; | 1749 | goto err_out; |
1748 | ctcm_open(priv->channel[READ]->netdev); | 1750 | ctcm_open(priv->channel[CTCM_READ]->netdev); |
1749 | err_out: | 1751 | err_out: |
1750 | netif_device_attach(priv->channel[READ]->netdev); | 1752 | netif_device_attach(priv->channel[CTCM_READ]->netdev); |
1751 | return rc; | 1753 | return rc; |
1752 | } | 1754 | } |
1753 | 1755 | ||
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index d34fa14f44e7..24d5215eb0c4 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h | |||
@@ -111,8 +111,8 @@ enum ctcm_channel_types { | |||
111 | 111 | ||
112 | #define CTCM_INITIAL_BLOCKLEN 2 | 112 | #define CTCM_INITIAL_BLOCKLEN 2 |
113 | 113 | ||
114 | #define READ 0 | 114 | #define CTCM_READ 0 |
115 | #define WRITE 1 | 115 | #define CTCM_WRITE 1 |
116 | 116 | ||
117 | #define CTCM_ID_SIZE 20+3 | 117 | #define CTCM_ID_SIZE 20+3 |
118 | 118 | ||
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 87c24d2936d6..2861e78773cb 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c | |||
@@ -419,8 +419,8 @@ void ctc_mpc_establish_connectivity(int port_num, | |||
419 | return; | 419 | return; |
420 | priv = dev->ml_priv; | 420 | priv = dev->ml_priv; |
421 | grp = priv->mpcg; | 421 | grp = priv->mpcg; |
422 | rch = priv->channel[READ]; | 422 | rch = priv->channel[CTCM_READ]; |
423 | wch = priv->channel[WRITE]; | 423 | wch = priv->channel[CTCM_WRITE]; |
424 | 424 | ||
425 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO, | 425 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO, |
426 | "%s(%s): state=%s", | 426 | "%s(%s): state=%s", |
@@ -578,7 +578,7 @@ void ctc_mpc_flow_control(int port_num, int flowc) | |||
578 | "%s: %s: flowc = %d", | 578 | "%s: %s: flowc = %d", |
579 | CTCM_FUNTAIL, dev->name, flowc); | 579 | CTCM_FUNTAIL, dev->name, flowc); |
580 | 580 | ||
581 | rch = priv->channel[READ]; | 581 | rch = priv->channel[CTCM_READ]; |
582 | 582 | ||
583 | mpcg_state = fsm_getstate(grp->fsm); | 583 | mpcg_state = fsm_getstate(grp->fsm); |
584 | switch (flowc) { | 584 | switch (flowc) { |
@@ -622,7 +622,7 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo) | |||
622 | struct net_device *dev = rch->netdev; | 622 | struct net_device *dev = rch->netdev; |
623 | struct ctcm_priv *priv = dev->ml_priv; | 623 | struct ctcm_priv *priv = dev->ml_priv; |
624 | struct mpc_group *grp = priv->mpcg; | 624 | struct mpc_group *grp = priv->mpcg; |
625 | struct channel *ch = priv->channel[WRITE]; | 625 | struct channel *ch = priv->channel[CTCM_WRITE]; |
626 | 626 | ||
627 | CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, ch, ch->id); | 627 | CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, ch, ch->id); |
628 | CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH); | 628 | CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH); |
@@ -656,7 +656,7 @@ static void ctcmpc_send_sweep_resp(struct channel *rch) | |||
656 | int rc = 0; | 656 | int rc = 0; |
657 | struct th_sweep *header; | 657 | struct th_sweep *header; |
658 | struct sk_buff *sweep_skb; | 658 | struct sk_buff *sweep_skb; |
659 | struct channel *ch = priv->channel[WRITE]; | 659 | struct channel *ch = priv->channel[CTCM_WRITE]; |
660 | 660 | ||
661 | CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, rch, rch->id); | 661 | CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, rch, rch->id); |
662 | 662 | ||
@@ -712,7 +712,7 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo) | |||
712 | struct net_device *dev = rch->netdev; | 712 | struct net_device *dev = rch->netdev; |
713 | struct ctcm_priv *priv = dev->ml_priv; | 713 | struct ctcm_priv *priv = dev->ml_priv; |
714 | struct mpc_group *grp = priv->mpcg; | 714 | struct mpc_group *grp = priv->mpcg; |
715 | struct channel *ch = priv->channel[WRITE]; | 715 | struct channel *ch = priv->channel[CTCM_WRITE]; |
716 | 716 | ||
717 | if (do_debug) | 717 | if (do_debug) |
718 | CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG, | 718 | CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG, |
@@ -721,8 +721,8 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo) | |||
721 | if (grp->in_sweep == 0) { | 721 | if (grp->in_sweep == 0) { |
722 | grp->in_sweep = 1; | 722 | grp->in_sweep = 1; |
723 | ctcm_test_and_set_busy(dev); | 723 | ctcm_test_and_set_busy(dev); |
724 | grp->sweep_req_pend_num = grp->active_channels[READ]; | 724 | grp->sweep_req_pend_num = grp->active_channels[CTCM_READ]; |
725 | grp->sweep_rsp_pend_num = grp->active_channels[READ]; | 725 | grp->sweep_rsp_pend_num = grp->active_channels[CTCM_READ]; |
726 | } | 726 | } |
727 | 727 | ||
728 | CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH); | 728 | CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH); |
@@ -906,14 +906,14 @@ void mpc_group_ready(unsigned long adev) | |||
906 | fsm_newstate(grp->fsm, MPCG_STATE_READY); | 906 | fsm_newstate(grp->fsm, MPCG_STATE_READY); |
907 | 907 | ||
908 | /* Put up a read on the channel */ | 908 | /* Put up a read on the channel */ |
909 | ch = priv->channel[READ]; | 909 | ch = priv->channel[CTCM_READ]; |
910 | ch->pdu_seq = 0; | 910 | ch->pdu_seq = 0; |
911 | CTCM_PR_DBGDATA("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" , | 911 | CTCM_PR_DBGDATA("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" , |
912 | __func__, ch->pdu_seq); | 912 | __func__, ch->pdu_seq); |
913 | 913 | ||
914 | ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch); | 914 | ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch); |
915 | /* Put the write channel in idle state */ | 915 | /* Put the write channel in idle state */ |
916 | ch = priv->channel[WRITE]; | 916 | ch = priv->channel[CTCM_WRITE]; |
917 | if (ch->collect_len > 0) { | 917 | if (ch->collect_len > 0) { |
918 | spin_lock(&ch->collect_lock); | 918 | spin_lock(&ch->collect_lock); |
919 | ctcm_purge_skb_queue(&ch->collect_queue); | 919 | ctcm_purge_skb_queue(&ch->collect_queue); |
@@ -960,7 +960,8 @@ void mpc_channel_action(struct channel *ch, int direction, int action) | |||
960 | "%s: %i / Grp:%s total_channels=%i, active_channels: " | 960 | "%s: %i / Grp:%s total_channels=%i, active_channels: " |
961 | "read=%i, write=%i\n", __func__, action, | 961 | "read=%i, write=%i\n", __func__, action, |
962 | fsm_getstate_str(grp->fsm), grp->num_channel_paths, | 962 | fsm_getstate_str(grp->fsm), grp->num_channel_paths, |
963 | grp->active_channels[READ], grp->active_channels[WRITE]); | 963 | grp->active_channels[CTCM_READ], |
964 | grp->active_channels[CTCM_WRITE]); | ||
964 | 965 | ||
965 | if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) { | 966 | if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) { |
966 | grp->num_channel_paths++; | 967 | grp->num_channel_paths++; |
@@ -994,10 +995,11 @@ void mpc_channel_action(struct channel *ch, int direction, int action) | |||
994 | grp->xid_skb->data, | 995 | grp->xid_skb->data, |
995 | grp->xid_skb->len); | 996 | grp->xid_skb->len); |
996 | 997 | ||
997 | ch->xid->xid2_dlc_type = ((CHANNEL_DIRECTION(ch->flags) == READ) | 998 | ch->xid->xid2_dlc_type = |
999 | ((CHANNEL_DIRECTION(ch->flags) == CTCM_READ) | ||
998 | ? XID2_READ_SIDE : XID2_WRITE_SIDE); | 1000 | ? XID2_READ_SIDE : XID2_WRITE_SIDE); |
999 | 1001 | ||
1000 | if (CHANNEL_DIRECTION(ch->flags) == WRITE) | 1002 | if (CHANNEL_DIRECTION(ch->flags) == CTCM_WRITE) |
1001 | ch->xid->xid2_buf_len = 0x00; | 1003 | ch->xid->xid2_buf_len = 0x00; |
1002 | 1004 | ||
1003 | ch->xid_skb->data = ch->xid_skb_data; | 1005 | ch->xid_skb->data = ch->xid_skb_data; |
@@ -1006,8 +1008,8 @@ void mpc_channel_action(struct channel *ch, int direction, int action) | |||
1006 | 1008 | ||
1007 | fsm_newstate(ch->fsm, CH_XID0_PENDING); | 1009 | fsm_newstate(ch->fsm, CH_XID0_PENDING); |
1008 | 1010 | ||
1009 | if ((grp->active_channels[READ] > 0) && | 1011 | if ((grp->active_channels[CTCM_READ] > 0) && |
1010 | (grp->active_channels[WRITE] > 0) && | 1012 | (grp->active_channels[CTCM_WRITE] > 0) && |
1011 | (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) { | 1013 | (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) { |
1012 | fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW); | 1014 | fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW); |
1013 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE, | 1015 | CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE, |
@@ -1027,10 +1029,10 @@ void mpc_channel_action(struct channel *ch, int direction, int action) | |||
1027 | if (grp->channels_terminating) | 1029 | if (grp->channels_terminating) |
1028 | goto done; | 1030 | goto done; |
1029 | 1031 | ||
1030 | if (((grp->active_channels[READ] == 0) && | 1032 | if (((grp->active_channels[CTCM_READ] == 0) && |
1031 | (grp->active_channels[WRITE] > 0)) | 1033 | (grp->active_channels[CTCM_WRITE] > 0)) |
1032 | || ((grp->active_channels[WRITE] == 0) && | 1034 | || ((grp->active_channels[CTCM_WRITE] == 0) && |
1033 | (grp->active_channels[READ] > 0))) | 1035 | (grp->active_channels[CTCM_READ] > 0))) |
1034 | fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); | 1036 | fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); |
1035 | } | 1037 | } |
1036 | done: | 1038 | done: |
@@ -1038,7 +1040,8 @@ done: | |||
1038 | "exit %s: %i / Grp:%s total_channels=%i, active_channels: " | 1040 | "exit %s: %i / Grp:%s total_channels=%i, active_channels: " |
1039 | "read=%i, write=%i\n", __func__, action, | 1041 | "read=%i, write=%i\n", __func__, action, |
1040 | fsm_getstate_str(grp->fsm), grp->num_channel_paths, | 1042 | fsm_getstate_str(grp->fsm), grp->num_channel_paths, |
1041 | grp->active_channels[READ], grp->active_channels[WRITE]); | 1043 | grp->active_channels[CTCM_READ], |
1044 | grp->active_channels[CTCM_WRITE]); | ||
1042 | 1045 | ||
1043 | CTCM_PR_DEBUG("exit %s: ch=0x%p id=%s\n", __func__, ch, ch->id); | 1046 | CTCM_PR_DEBUG("exit %s: ch=0x%p id=%s\n", __func__, ch, ch->id); |
1044 | } | 1047 | } |
@@ -1392,8 +1395,8 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) | |||
1392 | (grp->port_persist == 0)) | 1395 | (grp->port_persist == 0)) |
1393 | fsm_deltimer(&priv->restart_timer); | 1396 | fsm_deltimer(&priv->restart_timer); |
1394 | 1397 | ||
1395 | wch = priv->channel[WRITE]; | 1398 | wch = priv->channel[CTCM_WRITE]; |
1396 | rch = priv->channel[READ]; | 1399 | rch = priv->channel[CTCM_READ]; |
1397 | 1400 | ||
1398 | switch (grp->saved_state) { | 1401 | switch (grp->saved_state) { |
1399 | case MPCG_STATE_RESET: | 1402 | case MPCG_STATE_RESET: |
@@ -1480,8 +1483,8 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg) | |||
1480 | 1483 | ||
1481 | priv = dev->ml_priv; | 1484 | priv = dev->ml_priv; |
1482 | grp = priv->mpcg; | 1485 | grp = priv->mpcg; |
1483 | wch = priv->channel[WRITE]; | 1486 | wch = priv->channel[CTCM_WRITE]; |
1484 | rch = priv->channel[READ]; | 1487 | rch = priv->channel[CTCM_READ]; |
1485 | 1488 | ||
1486 | switch (fsm_getstate(grp->fsm)) { | 1489 | switch (fsm_getstate(grp->fsm)) { |
1487 | case MPCG_STATE_XID2INITW: | 1490 | case MPCG_STATE_XID2INITW: |
@@ -1586,7 +1589,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo) | |||
1586 | CTCM_D3_DUMP((char *)xid, XID2_LENGTH); | 1589 | CTCM_D3_DUMP((char *)xid, XID2_LENGTH); |
1587 | 1590 | ||
1588 | /*the received direction should be the opposite of ours */ | 1591 | /*the received direction should be the opposite of ours */ |
1589 | if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE : | 1592 | if (((CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? XID2_WRITE_SIDE : |
1590 | XID2_READ_SIDE) != xid->xid2_dlc_type) { | 1593 | XID2_READ_SIDE) != xid->xid2_dlc_type) { |
1591 | rc = 2; | 1594 | rc = 2; |
1592 | /* XID REJECTED: r/w channel pairing mismatch */ | 1595 | /* XID REJECTED: r/w channel pairing mismatch */ |
@@ -1912,7 +1915,7 @@ static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg) | |||
1912 | if (grp == NULL) | 1915 | if (grp == NULL) |
1913 | return; | 1916 | return; |
1914 | 1917 | ||
1915 | for (direction = READ; direction <= WRITE; direction++) { | 1918 | for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) { |
1916 | struct channel *ch = priv->channel[direction]; | 1919 | struct channel *ch = priv->channel[direction]; |
1917 | struct xid2 *thisxid = ch->xid; | 1920 | struct xid2 *thisxid = ch->xid; |
1918 | ch->xid_skb->data = ch->xid_skb_data; | 1921 | ch->xid_skb->data = ch->xid_skb_data; |
@@ -2152,14 +2155,15 @@ static int mpc_send_qllc_discontact(struct net_device *dev) | |||
2152 | return -ENOMEM; | 2155 | return -ENOMEM; |
2153 | } | 2156 | } |
2154 | 2157 | ||
2155 | *((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq; | 2158 | *((__u32 *)skb_push(skb, 4)) = |
2156 | priv->channel[READ]->pdu_seq++; | 2159 | priv->channel[CTCM_READ]->pdu_seq; |
2160 | priv->channel[CTCM_READ]->pdu_seq++; | ||
2157 | CTCM_PR_DBGDATA("ctcmpc: %s ToDCM_pdu_seq= %08x\n", | 2161 | CTCM_PR_DBGDATA("ctcmpc: %s ToDCM_pdu_seq= %08x\n", |
2158 | __func__, priv->channel[READ]->pdu_seq); | 2162 | __func__, priv->channel[CTCM_READ]->pdu_seq); |
2159 | 2163 | ||
2160 | /* receipt of CC03 resets anticipated sequence number on | 2164 | /* receipt of CC03 resets anticipated sequence number on |
2161 | receiving side */ | 2165 | receiving side */ |
2162 | priv->channel[READ]->pdu_seq = 0x00; | 2166 | priv->channel[CTCM_READ]->pdu_seq = 0x00; |
2163 | skb_reset_mac_header(skb); | 2167 | skb_reset_mac_header(skb); |
2164 | skb->dev = dev; | 2168 | skb->dev = dev; |
2165 | skb->protocol = htons(ETH_P_SNAP); | 2169 | skb->protocol = htons(ETH_P_SNAP); |
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c index 2b24550e865e..8305319b2a84 100644 --- a/drivers/s390/net/ctcm_sysfs.c +++ b/drivers/s390/net/ctcm_sysfs.c | |||
@@ -38,8 +38,8 @@ static ssize_t ctcm_buffer_write(struct device *dev, | |||
38 | int bs1; | 38 | int bs1; |
39 | struct ctcm_priv *priv = dev_get_drvdata(dev); | 39 | struct ctcm_priv *priv = dev_get_drvdata(dev); |
40 | 40 | ||
41 | if (!(priv && priv->channel[READ] && | 41 | ndev = priv->channel[CTCM_READ]->netdev; |
42 | (ndev = priv->channel[READ]->netdev))) { | 42 | if (!(priv && priv->channel[CTCM_READ] && ndev)) { |
43 | CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev"); | 43 | CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev"); |
44 | return -ENODEV; | 44 | return -ENODEV; |
45 | } | 45 | } |
@@ -55,12 +55,12 @@ static ssize_t ctcm_buffer_write(struct device *dev, | |||
55 | (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2))) | 55 | (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2))) |
56 | goto einval; | 56 | goto einval; |
57 | 57 | ||
58 | priv->channel[READ]->max_bufsize = bs1; | 58 | priv->channel[CTCM_READ]->max_bufsize = bs1; |
59 | priv->channel[WRITE]->max_bufsize = bs1; | 59 | priv->channel[CTCM_WRITE]->max_bufsize = bs1; |
60 | if (!(ndev->flags & IFF_RUNNING)) | 60 | if (!(ndev->flags & IFF_RUNNING)) |
61 | ndev->mtu = bs1 - LL_HEADER_LENGTH - 2; | 61 | ndev->mtu = bs1 - LL_HEADER_LENGTH - 2; |
62 | priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; | 62 | priv->channel[CTCM_READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; |
63 | priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; | 63 | priv->channel[CTCM_WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; |
64 | 64 | ||
65 | CTCM_DBF_DEV(SETUP, ndev, buf); | 65 | CTCM_DBF_DEV(SETUP, ndev, buf); |
66 | return count; | 66 | return count; |
@@ -85,9 +85,9 @@ static void ctcm_print_statistics(struct ctcm_priv *priv) | |||
85 | p += sprintf(p, " Device FSM state: %s\n", | 85 | p += sprintf(p, " Device FSM state: %s\n", |
86 | fsm_getstate_str(priv->fsm)); | 86 | fsm_getstate_str(priv->fsm)); |
87 | p += sprintf(p, " RX channel FSM state: %s\n", | 87 | p += sprintf(p, " RX channel FSM state: %s\n", |
88 | fsm_getstate_str(priv->channel[READ]->fsm)); | 88 | fsm_getstate_str(priv->channel[CTCM_READ]->fsm)); |
89 | p += sprintf(p, " TX channel FSM state: %s\n", | 89 | p += sprintf(p, " TX channel FSM state: %s\n", |
90 | fsm_getstate_str(priv->channel[WRITE]->fsm)); | 90 | fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm)); |
91 | p += sprintf(p, " Max. TX buffer used: %ld\n", | 91 | p += sprintf(p, " Max. TX buffer used: %ld\n", |
92 | priv->channel[WRITE]->prof.maxmulti); | 92 | priv->channel[WRITE]->prof.maxmulti); |
93 | p += sprintf(p, " Max. chained SKBs: %ld\n", | 93 | p += sprintf(p, " Max. chained SKBs: %ld\n", |
@@ -102,7 +102,7 @@ static void ctcm_print_statistics(struct ctcm_priv *priv) | |||
102 | priv->channel[WRITE]->prof.tx_time); | 102 | priv->channel[WRITE]->prof.tx_time); |
103 | 103 | ||
104 | printk(KERN_INFO "Statistics for %s:\n%s", | 104 | printk(KERN_INFO "Statistics for %s:\n%s", |
105 | priv->channel[WRITE]->netdev->name, sbuf); | 105 | priv->channel[CTCM_WRITE]->netdev->name, sbuf); |
106 | kfree(sbuf); | 106 | kfree(sbuf); |
107 | return; | 107 | return; |
108 | } | 108 | } |
@@ -125,7 +125,7 @@ static ssize_t stats_write(struct device *dev, struct device_attribute *attr, | |||
125 | return -ENODEV; | 125 | return -ENODEV; |
126 | /* Reset statistics */ | 126 | /* Reset statistics */ |
127 | memset(&priv->channel[WRITE]->prof, 0, | 127 | memset(&priv->channel[WRITE]->prof, 0, |
128 | sizeof(priv->channel[WRITE]->prof)); | 128 | sizeof(priv->channel[CTCM_WRITE]->prof)); |
129 | return count; | 129 | return count; |
130 | } | 130 | } |
131 | 131 | ||
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 103fdf6b0b89..160e7510aca6 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c | |||
@@ -443,7 +443,7 @@ static int kenvctrld(void *__unused) | |||
443 | return 0; | 443 | return 0; |
444 | } | 444 | } |
445 | 445 | ||
446 | static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, | 446 | static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op, |
447 | int temp_idx) | 447 | int temp_idx) |
448 | { | 448 | { |
449 | struct bbc_cpu_temperature *tp; | 449 | struct bbc_cpu_temperature *tp; |
@@ -488,7 +488,7 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, | |||
488 | tp->fan_todo[FAN_CPU] = FAN_SAME; | 488 | tp->fan_todo[FAN_CPU] = FAN_SAME; |
489 | } | 489 | } |
490 | 490 | ||
491 | static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op, | 491 | static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op, |
492 | int fan_idx) | 492 | int fan_idx) |
493 | { | 493 | { |
494 | struct bbc_fan_control *fp; | 494 | struct bbc_fan_control *fp; |
@@ -559,7 +559,7 @@ static void destroy_all_fans(struct bbc_i2c_bus *bp) | |||
559 | 559 | ||
560 | int bbc_envctrl_init(struct bbc_i2c_bus *bp) | 560 | int bbc_envctrl_init(struct bbc_i2c_bus *bp) |
561 | { | 561 | { |
562 | struct of_device *op; | 562 | struct platform_device *op; |
563 | int temp_index = 0; | 563 | int temp_index = 0; |
564 | int fan_index = 0; | 564 | int fan_index = 0; |
565 | int devidx = 0; | 565 | int devidx = 0; |
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 3e89c313e98d..614a5e114a19 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c | |||
@@ -51,7 +51,7 @@ | |||
51 | * The second controller also connects to the smartcard reader, if present. | 51 | * The second controller also connects to the smartcard reader, if present. |
52 | */ | 52 | */ |
53 | 53 | ||
54 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val) | 54 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct platform_device *op, int val) |
55 | { | 55 | { |
56 | int i; | 56 | int i; |
57 | 57 | ||
@@ -66,9 +66,9 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, in | |||
66 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) | 66 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) |
67 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) | 67 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) |
68 | 68 | ||
69 | struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) | 69 | struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) |
70 | { | 70 | { |
71 | struct of_device *op = NULL; | 71 | struct platform_device *op = NULL; |
72 | int curidx = 0, i; | 72 | int curidx = 0, i; |
73 | 73 | ||
74 | for (i = 0; i < NUM_CHILDREN; i++) { | 74 | for (i = 0; i < NUM_CHILDREN; i++) { |
@@ -86,7 +86,7 @@ out: | |||
86 | return NULL; | 86 | return NULL; |
87 | } | 87 | } |
88 | 88 | ||
89 | struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op) | 89 | struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *op) |
90 | { | 90 | { |
91 | struct bbc_i2c_client *client; | 91 | struct bbc_i2c_client *client; |
92 | const u32 *reg; | 92 | const u32 *reg; |
@@ -114,7 +114,7 @@ struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device * | |||
114 | void bbc_i2c_detach(struct bbc_i2c_client *client) | 114 | void bbc_i2c_detach(struct bbc_i2c_client *client) |
115 | { | 115 | { |
116 | struct bbc_i2c_bus *bp = client->bp; | 116 | struct bbc_i2c_bus *bp = client->bp; |
117 | struct of_device *op = client->op; | 117 | struct platform_device *op = client->op; |
118 | 118 | ||
119 | release_device(bp, op); | 119 | release_device(bp, op); |
120 | kfree(client); | 120 | kfree(client); |
@@ -297,7 +297,7 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) | |||
297 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); | 297 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); |
298 | } | 298 | } |
299 | 299 | ||
300 | static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index) | 300 | static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, int index) |
301 | { | 301 | { |
302 | struct bbc_i2c_bus *bp; | 302 | struct bbc_i2c_bus *bp; |
303 | struct device_node *dp; | 303 | struct device_node *dp; |
@@ -330,7 +330,7 @@ static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int inde | |||
330 | for (dp = op->dev.of_node->child; | 330 | for (dp = op->dev.of_node->child; |
331 | dp && entry < 8; | 331 | dp && entry < 8; |
332 | dp = dp->sibling, entry++) { | 332 | dp = dp->sibling, entry++) { |
333 | struct of_device *child_op; | 333 | struct platform_device *child_op; |
334 | 334 | ||
335 | child_op = of_find_device_by_node(dp); | 335 | child_op = of_find_device_by_node(dp); |
336 | bp->devs[entry].device = child_op; | 336 | bp->devs[entry].device = child_op; |
@@ -361,7 +361,7 @@ fail: | |||
361 | extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); | 361 | extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); |
362 | extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); | 362 | extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); |
363 | 363 | ||
364 | static int __devinit bbc_i2c_probe(struct of_device *op, | 364 | static int __devinit bbc_i2c_probe(struct platform_device *op, |
365 | const struct of_device_id *match) | 365 | const struct of_device_id *match) |
366 | { | 366 | { |
367 | struct bbc_i2c_bus *bp; | 367 | struct bbc_i2c_bus *bp; |
@@ -386,7 +386,7 @@ static int __devinit bbc_i2c_probe(struct of_device *op, | |||
386 | return err; | 386 | return err; |
387 | } | 387 | } |
388 | 388 | ||
389 | static int __devexit bbc_i2c_remove(struct of_device *op) | 389 | static int __devexit bbc_i2c_remove(struct platform_device *op) |
390 | { | 390 | { |
391 | struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); | 391 | struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); |
392 | 392 | ||
diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h index 83c4811b7b5e..4b4531066e75 100644 --- a/drivers/sbus/char/bbc_i2c.h +++ b/drivers/sbus/char/bbc_i2c.h | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | struct bbc_i2c_client { | 8 | struct bbc_i2c_client { |
9 | struct bbc_i2c_bus *bp; | 9 | struct bbc_i2c_bus *bp; |
10 | struct of_device *op; | 10 | struct platform_device *op; |
11 | int bus; | 11 | int bus; |
12 | int address; | 12 | int address; |
13 | }; | 13 | }; |
@@ -64,16 +64,16 @@ struct bbc_i2c_bus { | |||
64 | struct list_head temps; | 64 | struct list_head temps; |
65 | struct list_head fans; | 65 | struct list_head fans; |
66 | 66 | ||
67 | struct of_device *op; | 67 | struct platform_device *op; |
68 | struct { | 68 | struct { |
69 | struct of_device *device; | 69 | struct platform_device *device; |
70 | int client_claimed; | 70 | int client_claimed; |
71 | } devs[NUM_CHILDREN]; | 71 | } devs[NUM_CHILDREN]; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | /* Probing and attachment. */ | 74 | /* Probing and attachment. */ |
75 | extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); | 75 | extern struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); |
76 | extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *); | 76 | extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *); |
77 | extern void bbc_i2c_detach(struct bbc_i2c_client *); | 77 | extern void bbc_i2c_detach(struct bbc_i2c_client *); |
78 | 78 | ||
79 | /* Register read/write. NOTE: Blocking! */ | 79 | /* Register read/write. NOTE: Blocking! */ |
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 47db97583ea7..1690e53fb84a 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c | |||
@@ -170,7 +170,7 @@ static struct miscdevice d7s_miscdev = { | |||
170 | .fops = &d7s_fops | 170 | .fops = &d7s_fops |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static int __devinit d7s_probe(struct of_device *op, | 173 | static int __devinit d7s_probe(struct platform_device *op, |
174 | const struct of_device_id *match) | 174 | const struct of_device_id *match) |
175 | { | 175 | { |
176 | struct device_node *opts; | 176 | struct device_node *opts; |
@@ -236,7 +236,7 @@ out_free: | |||
236 | goto out; | 236 | goto out; |
237 | } | 237 | } |
238 | 238 | ||
239 | static int __devexit d7s_remove(struct of_device *op) | 239 | static int __devexit d7s_remove(struct platform_device *op) |
240 | { | 240 | { |
241 | struct d7s *p = dev_get_drvdata(&op->dev); | 241 | struct d7s *p = dev_get_drvdata(&op->dev); |
242 | u8 regs = readb(p->regs); | 242 | u8 regs = readb(p->regs); |
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 3c27f45e2b6d..078e5f4520ef 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c | |||
@@ -1027,7 +1027,7 @@ static int kenvctrld(void *__unused) | |||
1027 | return 0; | 1027 | return 0; |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | static int __devinit envctrl_probe(struct of_device *op, | 1030 | static int __devinit envctrl_probe(struct platform_device *op, |
1031 | const struct of_device_id *match) | 1031 | const struct of_device_id *match) |
1032 | { | 1032 | { |
1033 | struct device_node *dp; | 1033 | struct device_node *dp; |
@@ -1104,7 +1104,7 @@ out_iounmap: | |||
1104 | return err; | 1104 | return err; |
1105 | } | 1105 | } |
1106 | 1106 | ||
1107 | static int __devexit envctrl_remove(struct of_device *op) | 1107 | static int __devexit envctrl_remove(struct platform_device *op) |
1108 | { | 1108 | { |
1109 | int index; | 1109 | int index; |
1110 | 1110 | ||
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 8bb31c584b64..2b4b4b613c48 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c | |||
@@ -160,7 +160,7 @@ static const struct file_operations flash_fops = { | |||
160 | 160 | ||
161 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; | 161 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; |
162 | 162 | ||
163 | static int __devinit flash_probe(struct of_device *op, | 163 | static int __devinit flash_probe(struct platform_device *op, |
164 | const struct of_device_id *match) | 164 | const struct of_device_id *match) |
165 | { | 165 | { |
166 | struct device_node *dp = op->dev.of_node; | 166 | struct device_node *dp = op->dev.of_node; |
@@ -192,7 +192,7 @@ static int __devinit flash_probe(struct of_device *op, | |||
192 | return misc_register(&flash_dev); | 192 | return misc_register(&flash_dev); |
193 | } | 193 | } |
194 | 194 | ||
195 | static int __devexit flash_remove(struct of_device *op) | 195 | static int __devexit flash_remove(struct platform_device *op) |
196 | { | 196 | { |
197 | misc_deregister(&flash_dev); | 197 | misc_deregister(&flash_dev); |
198 | 198 | ||
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 41eb6725ff5f..1b345be5cc02 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c | |||
@@ -348,7 +348,7 @@ static void uctrl_get_external_status(struct uctrl_driver *driver) | |||
348 | 348 | ||
349 | } | 349 | } |
350 | 350 | ||
351 | static int __devinit uctrl_probe(struct of_device *op, | 351 | static int __devinit uctrl_probe(struct platform_device *op, |
352 | const struct of_device_id *match) | 352 | const struct of_device_id *match) |
353 | { | 353 | { |
354 | struct uctrl_driver *p; | 354 | struct uctrl_driver *p; |
@@ -404,7 +404,7 @@ out_free: | |||
404 | goto out; | 404 | goto out; |
405 | } | 405 | } |
406 | 406 | ||
407 | static int __devexit uctrl_remove(struct of_device *op) | 407 | static int __devexit uctrl_remove(struct platform_device *op) |
408 | { | 408 | { |
409 | struct uctrl_driver *p = dev_get_drvdata(&op->dev); | 409 | struct uctrl_driver *p = dev_get_drvdata(&op->dev); |
410 | 410 | ||
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 80dc3ac12cde..89fc1c8af86b 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c | |||
@@ -309,9 +309,6 @@ NCR_700_detect(struct scsi_host_template *tpnt, | |||
309 | hostdata->msgin = memory + MSGIN_OFFSET; | 309 | hostdata->msgin = memory + MSGIN_OFFSET; |
310 | hostdata->msgout = memory + MSGOUT_OFFSET; | 310 | hostdata->msgout = memory + MSGOUT_OFFSET; |
311 | hostdata->status = memory + STATUS_OFFSET; | 311 | hostdata->status = memory + STATUS_OFFSET; |
312 | /* all of these offsets are L1_CACHE_BYTES separated. It is fatal | ||
313 | * if this isn't sufficient separation to avoid dma flushing issues */ | ||
314 | BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); | ||
315 | hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); | 312 | hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); |
316 | hostdata->dev = dev; | 313 | hostdata->dev = dev; |
317 | 314 | ||
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 158284f05732..6466231f338b 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -1853,7 +1853,7 @@ config ZFCP_DIF | |||
1853 | 1853 | ||
1854 | config SCSI_PMCRAID | 1854 | config SCSI_PMCRAID |
1855 | tristate "PMC SIERRA Linux MaxRAID adapter support" | 1855 | tristate "PMC SIERRA Linux MaxRAID adapter support" |
1856 | depends on PCI && SCSI | 1856 | depends on PCI && SCSI && NET |
1857 | ---help--- | 1857 | ---help--- |
1858 | This driver supports the PMC SIERRA MaxRAID adapters. | 1858 | This driver supports the PMC SIERRA MaxRAID adapters. |
1859 | 1859 | ||
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index f92da9fd5f20..5d2f148889ad 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c | |||
@@ -1857,7 +1857,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase | |||
1857 | #endif | 1857 | #endif |
1858 | /* KLL May need eop and parity in 53c400 */ | 1858 | /* KLL May need eop and parity in 53c400 */ |
1859 | if (hostdata->flags & FLAG_NCR53C400) | 1859 | if (hostdata->flags & FLAG_NCR53C400) |
1860 | NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE | MR_MONITOR_BSY); | 1860 | NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | |
1861 | MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | | ||
1862 | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); | ||
1861 | else | 1863 | else |
1862 | NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); | 1864 | NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); |
1863 | #endif /* def REAL_DMA */ | 1865 | #endif /* def REAL_DMA */ |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 04057ab72a8b..84d77fd86e5b 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -352,9 +352,8 @@ static int aac_rx_check_health(struct aac_dev *dev) | |||
352 | pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), | 352 | pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), |
353 | post, paddr); | 353 | post, paddr); |
354 | if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { | 354 | if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { |
355 | ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); | 355 | ret = (hex_to_bin(buffer[2]) << 4) + |
356 | ret <<= 4; | 356 | hex_to_bin(buffer[3]); |
357 | ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); | ||
358 | } | 357 | } |
359 | pci_free_consistent(dev->pdev, 512, buffer, baddr); | 358 | pci_free_consistent(dev->pdev, 512, buffer, baddr); |
360 | return ret; | 359 | return ret; |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 24ac2315c5c7..3b7e83d2dab4 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
@@ -688,9 +688,9 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha) | |||
688 | { | 688 | { |
689 | int i; | 689 | int i; |
690 | struct asd_sas_phy **sas_phys = | 690 | struct asd_sas_phy **sas_phys = |
691 | kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_phy), GFP_KERNEL); | 691 | kcalloc(ASD_MAX_PHYS, sizeof(*sas_phys), GFP_KERNEL); |
692 | struct asd_sas_port **sas_ports = | 692 | struct asd_sas_port **sas_ports = |
693 | kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_port), GFP_KERNEL); | 693 | kcalloc(ASD_MAX_PHYS, sizeof(*sas_ports), GFP_KERNEL); |
694 | 694 | ||
695 | if (!sas_phys || !sas_ports) { | 695 | if (!sas_phys || !sas_ports) { |
696 | kfree(sas_phys); | 696 | kfree(sas_phys); |
diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index f0933d8d1eda..76867b5577fa 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c | |||
@@ -1310,7 +1310,7 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) | |||
1310 | break; | 1310 | break; |
1311 | 1311 | ||
1312 | case BFI_FCPORT_I2H_DISABLE_RSP: | 1312 | case BFI_FCPORT_I2H_DISABLE_RSP: |
1313 | if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) | 1313 | if (fcport->msgtag == i2hmsg.pdisable_rsp->msgtag) |
1314 | bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP); | 1314 | bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP); |
1315 | break; | 1315 | break; |
1316 | 1316 | ||
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 915a29d6c7ad..ca04cc9d332f 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c | |||
@@ -788,6 +788,7 @@ bfad_drv_init(struct bfad_s *bfad) | |||
788 | memset(&driver_info, 0, sizeof(driver_info)); | 788 | memset(&driver_info, 0, sizeof(driver_info)); |
789 | strncpy(driver_info.version, BFAD_DRIVER_VERSION, | 789 | strncpy(driver_info.version, BFAD_DRIVER_VERSION, |
790 | sizeof(driver_info.version) - 1); | 790 | sizeof(driver_info.version) - 1); |
791 | __kernel_param_lock(); | ||
791 | if (host_name) | 792 | if (host_name) |
792 | strncpy(driver_info.host_machine_name, host_name, | 793 | strncpy(driver_info.host_machine_name, host_name, |
793 | sizeof(driver_info.host_machine_name) - 1); | 794 | sizeof(driver_info.host_machine_name) - 1); |
@@ -797,6 +798,7 @@ bfad_drv_init(struct bfad_s *bfad) | |||
797 | if (os_patch) | 798 | if (os_patch) |
798 | strncpy(driver_info.host_os_patch, os_patch, | 799 | strncpy(driver_info.host_os_patch, os_patch, |
799 | sizeof(driver_info.host_os_patch) - 1); | 800 | sizeof(driver_info.host_os_patch) - 1); |
801 | __kernel_param_unlock(); | ||
800 | 802 | ||
801 | strncpy(driver_info.os_device_name, bfad->pci_name, | 803 | strncpy(driver_info.os_device_name, bfad->pci_name, |
802 | sizeof(driver_info.os_device_name - 1)); | 804 | sizeof(driver_info.os_device_name - 1)); |
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 678120b70460..6ef87f6fcdbb 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c | |||
@@ -291,7 +291,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
291 | struct bfa_tskim_s *tskim; | 291 | struct bfa_tskim_s *tskim; |
292 | struct bfad_itnim_s *itnim; | 292 | struct bfad_itnim_s *itnim; |
293 | struct bfa_itnim_s *bfa_itnim; | 293 | struct bfa_itnim_s *bfa_itnim; |
294 | DECLARE_WAIT_QUEUE_HEAD(wq); | 294 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); |
295 | int rc = SUCCESS; | 295 | int rc = SUCCESS; |
296 | unsigned long flags; | 296 | unsigned long flags; |
297 | enum bfi_tskim_status task_status; | 297 | enum bfi_tskim_status task_status; |
@@ -353,7 +353,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd) | |||
353 | struct bfad_itnim_s *itnim; | 353 | struct bfad_itnim_s *itnim; |
354 | unsigned long flags; | 354 | unsigned long flags; |
355 | u32 i, rc, err_cnt = 0; | 355 | u32 i, rc, err_cnt = 0; |
356 | DECLARE_WAIT_QUEUE_HEAD(wq); | 356 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); |
357 | enum bfi_tskim_status task_status; | 357 | enum bfi_tskim_status task_status; |
358 | 358 | ||
359 | spin_lock_irqsave(&bfad->bfad_lock, flags); | 359 | spin_lock_irqsave(&bfad->bfad_lock, flags); |
diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h index 9ade68ad2853..74ea63ce84b7 100644 --- a/drivers/scsi/bfa/include/protocol/fcp.h +++ b/drivers/scsi/bfa/include/protocol/fcp.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #ifndef __FCPPROTO_H__ | 18 | #ifndef __FCPPROTO_H__ |
19 | #define __FCPPROTO_H__ | 19 | #define __FCPPROTO_H__ |
20 | 20 | ||
21 | #include <linux/bitops.h> | ||
21 | #include <protocol/scsi.h> | 22 | #include <protocol/scsi.h> |
22 | 23 | ||
23 | #pragma pack(1) | 24 | #pragma pack(1) |
@@ -102,9 +103,6 @@ enum { | |||
102 | /* | 103 | /* |
103 | * Task management flags field - only one bit shall be set | 104 | * Task management flags field - only one bit shall be set |
104 | */ | 105 | */ |
105 | #ifndef BIT | ||
106 | #define BIT(_x) (1 << (_x)) | ||
107 | #endif | ||
108 | enum fcp_tm_cmnd{ | 106 | enum fcp_tm_cmnd{ |
109 | FCP_TM_ABORT_TASK_SET = BIT(1), | 107 | FCP_TM_ABORT_TASK_SET = BIT(1), |
110 | FCP_TM_CLEAR_TASK_SET = BIT(2), | 108 | FCP_TM_CLEAR_TASK_SET = BIT(2), |
diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index 1e9f7141102b..45a6154ce972 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig | |||
@@ -1,10 +1,11 @@ | |||
1 | config SCSI_BNX2_ISCSI | 1 | config SCSI_BNX2_ISCSI |
2 | tristate "Broadcom NetXtreme II iSCSI support" | 2 | tristate "Broadcom NetXtreme II iSCSI support" |
3 | depends on NET | ||
4 | depends on PCI | ||
3 | select SCSI_ISCSI_ATTRS | 5 | select SCSI_ISCSI_ATTRS |
4 | select NETDEVICES | 6 | select NETDEVICES |
5 | select NETDEV_1000 | 7 | select NETDEV_1000 |
6 | select CNIC | 8 | select CNIC |
7 | depends on PCI | ||
8 | ---help--- | 9 | ---help--- |
9 | This driver supports iSCSI offload for the Broadcom NetXtreme II | 10 | This driver supports iSCSI offload for the Broadcom NetXtreme II |
10 | devices. | 11 | devices. |
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 4799d4391203..d6532187f616 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c | |||
@@ -84,10 +84,16 @@ static const char * vendor_labels[CH_TYPES-4] = { | |||
84 | }; | 84 | }; |
85 | // module_param_string_array(vendor_labels, NULL, 0444); | 85 | // module_param_string_array(vendor_labels, NULL, 0444); |
86 | 86 | ||
87 | #define dprintk(fmt, arg...) if (debug) \ | 87 | #define DPRINTK(fmt, arg...) \ |
88 | printk(KERN_DEBUG "%s: " fmt, ch->name , ## arg) | 88 | do { \ |
89 | #define vprintk(fmt, arg...) if (verbose) \ | 89 | if (debug) \ |
90 | printk(KERN_INFO "%s: " fmt, ch->name , ## arg) | 90 | printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg); \ |
91 | } while (0) | ||
92 | #define VPRINTK(level, fmt, arg...) \ | ||
93 | do { \ | ||
94 | if (verbose) \ | ||
95 | printk(level "%s: " fmt, ch->name, ##arg); \ | ||
96 | } while (0) | ||
91 | 97 | ||
92 | /* ------------------------------------------------------------------- */ | 98 | /* ------------------------------------------------------------------- */ |
93 | 99 | ||
@@ -186,7 +192,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, | |||
186 | retry: | 192 | retry: |
187 | errno = 0; | 193 | errno = 0; |
188 | if (debug) { | 194 | if (debug) { |
189 | dprintk("command: "); | 195 | DPRINTK("command: "); |
190 | __scsi_print_command(cmd); | 196 | __scsi_print_command(cmd); |
191 | } | 197 | } |
192 | 198 | ||
@@ -194,7 +200,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, | |||
194 | buflength, &sshdr, timeout * HZ, | 200 | buflength, &sshdr, timeout * HZ, |
195 | MAX_RETRIES, NULL); | 201 | MAX_RETRIES, NULL); |
196 | 202 | ||
197 | dprintk("result: 0x%x\n",result); | 203 | DPRINTK("result: 0x%x\n",result); |
198 | if (driver_byte(result) & DRIVER_SENSE) { | 204 | if (driver_byte(result) & DRIVER_SENSE) { |
199 | if (debug) | 205 | if (debug) |
200 | scsi_print_sense_hdr(ch->name, &sshdr); | 206 | scsi_print_sense_hdr(ch->name, &sshdr); |
@@ -250,7 +256,7 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) | |||
250 | cmd[9] = 255; | 256 | cmd[9] = 255; |
251 | if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) { | 257 | if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) { |
252 | if (((buffer[16] << 8) | buffer[17]) != elem) { | 258 | if (((buffer[16] << 8) | buffer[17]) != elem) { |
253 | dprintk("asked for element 0x%02x, got 0x%02x\n", | 259 | DPRINTK("asked for element 0x%02x, got 0x%02x\n", |
254 | elem,(buffer[16] << 8) | buffer[17]); | 260 | elem,(buffer[16] << 8) | buffer[17]); |
255 | kfree(buffer); | 261 | kfree(buffer); |
256 | return -EIO; | 262 | return -EIO; |
@@ -259,10 +265,10 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) | |||
259 | } else { | 265 | } else { |
260 | if (ch->voltags) { | 266 | if (ch->voltags) { |
261 | ch->voltags = 0; | 267 | ch->voltags = 0; |
262 | vprintk("device has no volume tag support\n"); | 268 | VPRINTK(KERN_INFO, "device has no volume tag support\n"); |
263 | goto retry; | 269 | goto retry; |
264 | } | 270 | } |
265 | dprintk("READ ELEMENT STATUS for element 0x%x failed\n",elem); | 271 | DPRINTK("READ ELEMENT STATUS for element 0x%x failed\n",elem); |
266 | } | 272 | } |
267 | kfree(buffer); | 273 | kfree(buffer); |
268 | return result; | 274 | return result; |
@@ -274,12 +280,12 @@ ch_init_elem(scsi_changer *ch) | |||
274 | int err; | 280 | int err; |
275 | u_char cmd[6]; | 281 | u_char cmd[6]; |
276 | 282 | ||
277 | vprintk("INITIALIZE ELEMENT STATUS, may take some time ...\n"); | 283 | VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n"); |
278 | memset(cmd,0,sizeof(cmd)); | 284 | memset(cmd,0,sizeof(cmd)); |
279 | cmd[0] = INITIALIZE_ELEMENT_STATUS; | 285 | cmd[0] = INITIALIZE_ELEMENT_STATUS; |
280 | cmd[1] = ch->device->lun << 5; | 286 | cmd[1] = ch->device->lun << 5; |
281 | err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE); | 287 | err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE); |
282 | vprintk("... finished\n"); | 288 | VPRINTK(KERN_INFO, "... finished\n"); |
283 | return err; | 289 | return err; |
284 | } | 290 | } |
285 | 291 | ||
@@ -322,20 +328,20 @@ ch_readconfig(scsi_changer *ch) | |||
322 | (buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19]; | 328 | (buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19]; |
323 | ch->counts[CHET_DT] = | 329 | ch->counts[CHET_DT] = |
324 | (buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21]; | 330 | (buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21]; |
325 | vprintk("type #1 (mt): 0x%x+%d [medium transport]\n", | 331 | VPRINTK(KERN_INFO, "type #1 (mt): 0x%x+%d [medium transport]\n", |
326 | ch->firsts[CHET_MT], | 332 | ch->firsts[CHET_MT], |
327 | ch->counts[CHET_MT]); | 333 | ch->counts[CHET_MT]); |
328 | vprintk("type #2 (st): 0x%x+%d [storage]\n", | 334 | VPRINTK(KERN_INFO, "type #2 (st): 0x%x+%d [storage]\n", |
329 | ch->firsts[CHET_ST], | 335 | ch->firsts[CHET_ST], |
330 | ch->counts[CHET_ST]); | 336 | ch->counts[CHET_ST]); |
331 | vprintk("type #3 (ie): 0x%x+%d [import/export]\n", | 337 | VPRINTK(KERN_INFO, "type #3 (ie): 0x%x+%d [import/export]\n", |
332 | ch->firsts[CHET_IE], | 338 | ch->firsts[CHET_IE], |
333 | ch->counts[CHET_IE]); | 339 | ch->counts[CHET_IE]); |
334 | vprintk("type #4 (dt): 0x%x+%d [data transfer]\n", | 340 | VPRINTK(KERN_INFO, "type #4 (dt): 0x%x+%d [data transfer]\n", |
335 | ch->firsts[CHET_DT], | 341 | ch->firsts[CHET_DT], |
336 | ch->counts[CHET_DT]); | 342 | ch->counts[CHET_DT]); |
337 | } else { | 343 | } else { |
338 | vprintk("reading element address assigment page failed!\n"); | 344 | VPRINTK(KERN_INFO, "reading element address assigment page failed!\n"); |
339 | } | 345 | } |
340 | 346 | ||
341 | /* vendor specific element types */ | 347 | /* vendor specific element types */ |
@@ -346,13 +352,13 @@ ch_readconfig(scsi_changer *ch) | |||
346 | continue; | 352 | continue; |
347 | ch->firsts[CHET_V1+i] = vendor_firsts[i]; | 353 | ch->firsts[CHET_V1+i] = vendor_firsts[i]; |
348 | ch->counts[CHET_V1+i] = vendor_counts[i]; | 354 | ch->counts[CHET_V1+i] = vendor_counts[i]; |
349 | vprintk("type #%d (v%d): 0x%x+%d [%s, vendor specific]\n", | 355 | VPRINTK(KERN_INFO, "type #%d (v%d): 0x%x+%d [%s, vendor specific]\n", |
350 | i+5,i+1,vendor_firsts[i],vendor_counts[i], | 356 | i+5,i+1,vendor_firsts[i],vendor_counts[i], |
351 | vendor_labels[i]); | 357 | vendor_labels[i]); |
352 | } | 358 | } |
353 | 359 | ||
354 | /* look up the devices of the data transfer elements */ | 360 | /* look up the devices of the data transfer elements */ |
355 | ch->dt = kmalloc(ch->counts[CHET_DT]*sizeof(struct scsi_device), | 361 | ch->dt = kcalloc(ch->counts[CHET_DT], sizeof(*ch->dt), |
356 | GFP_KERNEL); | 362 | GFP_KERNEL); |
357 | 363 | ||
358 | if (!ch->dt) { | 364 | if (!ch->dt) { |
@@ -366,21 +372,19 @@ ch_readconfig(scsi_changer *ch) | |||
366 | if (elem < CH_DT_MAX && -1 != dt_id[elem]) { | 372 | if (elem < CH_DT_MAX && -1 != dt_id[elem]) { |
367 | id = dt_id[elem]; | 373 | id = dt_id[elem]; |
368 | lun = dt_lun[elem]; | 374 | lun = dt_lun[elem]; |
369 | vprintk("dt 0x%x: [insmod option] ", | 375 | VPRINTK(KERN_INFO, "dt 0x%x: [insmod option] ", |
370 | elem+ch->firsts[CHET_DT]); | 376 | elem+ch->firsts[CHET_DT]); |
371 | } else if (0 != ch_read_element_status | 377 | } else if (0 != ch_read_element_status |
372 | (ch,elem+ch->firsts[CHET_DT],data)) { | 378 | (ch,elem+ch->firsts[CHET_DT],data)) { |
373 | vprintk("dt 0x%x: READ ELEMENT STATUS failed\n", | 379 | VPRINTK(KERN_INFO, "dt 0x%x: READ ELEMENT STATUS failed\n", |
374 | elem+ch->firsts[CHET_DT]); | 380 | elem+ch->firsts[CHET_DT]); |
375 | } else { | 381 | } else { |
376 | vprintk("dt 0x%x: ",elem+ch->firsts[CHET_DT]); | 382 | VPRINTK(KERN_INFO, "dt 0x%x: ",elem+ch->firsts[CHET_DT]); |
377 | if (data[6] & 0x80) { | 383 | if (data[6] & 0x80) { |
378 | if (verbose) | 384 | VPRINTK(KERN_CONT, "not this SCSI bus\n"); |
379 | printk("not this SCSI bus\n"); | ||
380 | ch->dt[elem] = NULL; | 385 | ch->dt[elem] = NULL; |
381 | } else if (0 == (data[6] & 0x30)) { | 386 | } else if (0 == (data[6] & 0x30)) { |
382 | if (verbose) | 387 | VPRINTK(KERN_CONT, "ID/LUN unknown\n"); |
383 | printk("ID/LUN unknown\n"); | ||
384 | ch->dt[elem] = NULL; | 388 | ch->dt[elem] = NULL; |
385 | } else { | 389 | } else { |
386 | id = ch->device->id; | 390 | id = ch->device->id; |
@@ -390,22 +394,19 @@ ch_readconfig(scsi_changer *ch) | |||
390 | } | 394 | } |
391 | } | 395 | } |
392 | if (-1 != id) { | 396 | if (-1 != id) { |
393 | if (verbose) | 397 | VPRINTK(KERN_CONT, "ID %i, LUN %i, ",id,lun); |
394 | printk("ID %i, LUN %i, ",id,lun); | ||
395 | ch->dt[elem] = | 398 | ch->dt[elem] = |
396 | scsi_device_lookup(ch->device->host, | 399 | scsi_device_lookup(ch->device->host, |
397 | ch->device->channel, | 400 | ch->device->channel, |
398 | id,lun); | 401 | id,lun); |
399 | if (!ch->dt[elem]) { | 402 | if (!ch->dt[elem]) { |
400 | /* should not happen */ | 403 | /* should not happen */ |
401 | if (verbose) | 404 | VPRINTK(KERN_CONT, "Huh? device not found!\n"); |
402 | printk("Huh? device not found!\n"); | ||
403 | } else { | 405 | } else { |
404 | if (verbose) | 406 | VPRINTK(KERN_CONT, "name: %8.8s %16.16s %4.4s\n", |
405 | printk("name: %8.8s %16.16s %4.4s\n", | 407 | ch->dt[elem]->vendor, |
406 | ch->dt[elem]->vendor, | 408 | ch->dt[elem]->model, |
407 | ch->dt[elem]->model, | 409 | ch->dt[elem]->rev); |
408 | ch->dt[elem]->rev); | ||
409 | } | 410 | } |
410 | } | 411 | } |
411 | } | 412 | } |
@@ -422,7 +423,7 @@ ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate) | |||
422 | { | 423 | { |
423 | u_char cmd[10]; | 424 | u_char cmd[10]; |
424 | 425 | ||
425 | dprintk("position: 0x%x\n",elem); | 426 | DPRINTK("position: 0x%x\n",elem); |
426 | if (0 == trans) | 427 | if (0 == trans) |
427 | trans = ch->firsts[CHET_MT]; | 428 | trans = ch->firsts[CHET_MT]; |
428 | memset(cmd,0,sizeof(cmd)); | 429 | memset(cmd,0,sizeof(cmd)); |
@@ -441,7 +442,7 @@ ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate) | |||
441 | { | 442 | { |
442 | u_char cmd[12]; | 443 | u_char cmd[12]; |
443 | 444 | ||
444 | dprintk("move: 0x%x => 0x%x\n",src,dest); | 445 | DPRINTK("move: 0x%x => 0x%x\n",src,dest); |
445 | if (0 == trans) | 446 | if (0 == trans) |
446 | trans = ch->firsts[CHET_MT]; | 447 | trans = ch->firsts[CHET_MT]; |
447 | memset(cmd,0,sizeof(cmd)); | 448 | memset(cmd,0,sizeof(cmd)); |
@@ -463,7 +464,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src, | |||
463 | { | 464 | { |
464 | u_char cmd[12]; | 465 | u_char cmd[12]; |
465 | 466 | ||
466 | dprintk("exchange: 0x%x => 0x%x => 0x%x\n", | 467 | DPRINTK("exchange: 0x%x => 0x%x => 0x%x\n", |
467 | src,dest1,dest2); | 468 | src,dest1,dest2); |
468 | if (0 == trans) | 469 | if (0 == trans) |
469 | trans = ch->firsts[CHET_MT]; | 470 | trans = ch->firsts[CHET_MT]; |
@@ -511,7 +512,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem, | |||
511 | if (!buffer) | 512 | if (!buffer) |
512 | return -ENOMEM; | 513 | return -ENOMEM; |
513 | 514 | ||
514 | dprintk("%s %s voltag: 0x%x => \"%s\"\n", | 515 | DPRINTK("%s %s voltag: 0x%x => \"%s\"\n", |
515 | clear ? "clear" : "set", | 516 | clear ? "clear" : "set", |
516 | alternate ? "alternate" : "primary", | 517 | alternate ? "alternate" : "primary", |
517 | elem, tag); | 518 | elem, tag); |
@@ -550,7 +551,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) | |||
550 | } | 551 | } |
551 | put_user(data[2], dest+i); | 552 | put_user(data[2], dest+i); |
552 | if (data[2] & CESTATUS_EXCEPT) | 553 | if (data[2] & CESTATUS_EXCEPT) |
553 | vprintk("element 0x%x: asc=0x%x, ascq=0x%x\n", | 554 | VPRINTK(KERN_INFO, "element 0x%x: asc=0x%x, ascq=0x%x\n", |
554 | ch->firsts[type]+i, | 555 | ch->firsts[type]+i, |
555 | (int)data[4],(int)data[5]); | 556 | (int)data[4],(int)data[5]); |
556 | retval = ch_read_element_status | 557 | retval = ch_read_element_status |
@@ -660,7 +661,7 @@ static long ch_ioctl(struct file *file, | |||
660 | return -EFAULT; | 661 | return -EFAULT; |
661 | 662 | ||
662 | if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) { | 663 | if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) { |
663 | dprintk("CHIOPOSITION: invalid parameter\n"); | 664 | DPRINTK("CHIOPOSITION: invalid parameter\n"); |
664 | return -EBADSLT; | 665 | return -EBADSLT; |
665 | } | 666 | } |
666 | mutex_lock(&ch->lock); | 667 | mutex_lock(&ch->lock); |
@@ -680,7 +681,7 @@ static long ch_ioctl(struct file *file, | |||
680 | 681 | ||
681 | if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) || | 682 | if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) || |
682 | 0 != ch_checkrange(ch, mv.cm_totype, mv.cm_tounit )) { | 683 | 0 != ch_checkrange(ch, mv.cm_totype, mv.cm_tounit )) { |
683 | dprintk("CHIOMOVE: invalid parameter\n"); | 684 | DPRINTK("CHIOMOVE: invalid parameter\n"); |
684 | return -EBADSLT; | 685 | return -EBADSLT; |
685 | } | 686 | } |
686 | 687 | ||
@@ -703,7 +704,7 @@ static long ch_ioctl(struct file *file, | |||
703 | if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) || | 704 | if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) || |
704 | 0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) || | 705 | 0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) || |
705 | 0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) { | 706 | 0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) { |
706 | dprintk("CHIOEXCHANGE: invalid parameter\n"); | 707 | DPRINTK("CHIOEXCHANGE: invalid parameter\n"); |
707 | return -EBADSLT; | 708 | return -EBADSLT; |
708 | } | 709 | } |
709 | 710 | ||
@@ -796,7 +797,7 @@ static long ch_ioctl(struct file *file, | |||
796 | } | 797 | } |
797 | } else if (ch->voltags) { | 798 | } else if (ch->voltags) { |
798 | ch->voltags = 0; | 799 | ch->voltags = 0; |
799 | vprintk("device has no volume tag support\n"); | 800 | VPRINTK(KERN_INFO, "device has no volume tag support\n"); |
800 | goto voltag_retry; | 801 | goto voltag_retry; |
801 | } | 802 | } |
802 | kfree(buffer); | 803 | kfree(buffer); |
@@ -824,7 +825,7 @@ static long ch_ioctl(struct file *file, | |||
824 | return -EFAULT; | 825 | return -EFAULT; |
825 | 826 | ||
826 | if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) { | 827 | if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) { |
827 | dprintk("CHIOSVOLTAG: invalid parameter\n"); | 828 | DPRINTK("CHIOSVOLTAG: invalid parameter\n"); |
828 | return -EBADSLT; | 829 | return -EBADSLT; |
829 | } | 830 | } |
830 | elem = ch->firsts[csv.csv_type] + csv.csv_unit; | 831 | elem = ch->firsts[csv.csv_type] + csv.csv_unit; |
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index bd977be7544e..54f50b07dac7 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c | |||
@@ -1597,7 +1597,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, | |||
1597 | u32 tag_mask = 1; | 1597 | u32 tag_mask = 1; |
1598 | u8 tag_number = 0; | 1598 | u8 tag_number = 0; |
1599 | while (tag_mask & dcb->tag_mask | 1599 | while (tag_mask & dcb->tag_mask |
1600 | && tag_number <= dcb->max_command) { | 1600 | && tag_number < dcb->max_command) { |
1601 | tag_mask = tag_mask << 1; | 1601 | tag_mask = tag_mask << 1; |
1602 | tag_number++; | 1602 | tag_number++; |
1603 | } | 1603 | } |
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 19338e0ba2c5..cbb20b13b228 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <linux/bitops.h> | ||
24 | #include <scsi/libfc.h> | 25 | #include <scsi/libfc.h> |
25 | #include <scsi/libfcoe.h> | 26 | #include <scsi/libfcoe.h> |
26 | #include "fnic_io.h" | 27 | #include "fnic_io.h" |
@@ -49,7 +50,6 @@ | |||
49 | /* | 50 | /* |
50 | * Tag bits used for special requests. | 51 | * Tag bits used for special requests. |
51 | */ | 52 | */ |
52 | #define BIT(nr) (1UL << (nr)) | ||
53 | #define FNIC_TAG_ABORT BIT(30) /* tag bit indicating abort */ | 53 | #define FNIC_TAG_ABORT BIT(30) /* tag bit indicating abort */ |
54 | #define FNIC_TAG_DEV_RST BIT(29) /* indicates device reset */ | 54 | #define FNIC_TAG_DEV_RST BIT(29) /* indicates device reset */ |
55 | #define FNIC_TAG_MASK (BIT(24) - 1) /* mask for lookup */ | 55 | #define FNIC_TAG_MASK (BIT(24) - 1) /* mask for lookup */ |
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 75585a52c88b..427a56d3117e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c | |||
@@ -285,9 +285,12 @@ static int __init do_DTC3181E_setup(char *str) | |||
285 | int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) | 285 | int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) |
286 | { | 286 | { |
287 | static int current_override = 0; | 287 | static int current_override = 0; |
288 | int count, i; | 288 | int count; |
289 | unsigned int *ports; | 289 | unsigned int *ports; |
290 | #ifndef SCSI_G_NCR5380_MEM | ||
291 | int i; | ||
290 | unsigned long region_size = 16; | 292 | unsigned long region_size = 16; |
293 | #endif | ||
291 | static unsigned int __initdata ncr_53c400a_ports[] = { | 294 | static unsigned int __initdata ncr_53c400a_ports[] = { |
292 | 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 | 295 | 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 |
293 | }; | 296 | }; |
@@ -296,7 +299,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) | |||
296 | }; | 299 | }; |
297 | int flags = 0; | 300 | int flags = 0; |
298 | struct Scsi_Host *instance; | 301 | struct Scsi_Host *instance; |
299 | #ifdef CONFIG_SCSI_G_NCR5380_MEM | 302 | #ifdef SCSI_G_NCR5380_MEM |
300 | unsigned long base; | 303 | unsigned long base; |
301 | void __iomem *iomem; | 304 | void __iomem *iomem; |
302 | #endif | 305 | #endif |
@@ -315,17 +318,15 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) | |||
315 | overrides[0].board = BOARD_NCR53C400A; | 318 | overrides[0].board = BOARD_NCR53C400A; |
316 | else if (dtc_3181e != NCR_NOT_SET) | 319 | else if (dtc_3181e != NCR_NOT_SET) |
317 | overrides[0].board = BOARD_DTC3181E; | 320 | overrides[0].board = BOARD_DTC3181E; |
318 | 321 | #ifndef SCSI_G_NCR5380_MEM | |
319 | if (!current_override && isapnp_present()) { | 322 | if (!current_override && isapnp_present()) { |
320 | struct pnp_dev *dev = NULL; | 323 | struct pnp_dev *dev = NULL; |
321 | count = 0; | 324 | count = 0; |
322 | while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { | 325 | while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { |
323 | if (count >= NO_OVERRIDES) | 326 | if (count >= NO_OVERRIDES) |
324 | break; | 327 | break; |
325 | if (pnp_device_attach(dev) < 0) { | 328 | if (pnp_device_attach(dev) < 0) |
326 | printk(KERN_ERR "dtc436e probe: attach failed\n"); | ||
327 | continue; | 329 | continue; |
328 | } | ||
329 | if (pnp_activate_dev(dev) < 0) { | 330 | if (pnp_activate_dev(dev) < 0) { |
330 | printk(KERN_ERR "dtc436e probe: activate failed\n"); | 331 | printk(KERN_ERR "dtc436e probe: activate failed\n"); |
331 | pnp_device_detach(dev); | 332 | pnp_device_detach(dev); |
@@ -349,7 +350,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) | |||
349 | count++; | 350 | count++; |
350 | } | 351 | } |
351 | } | 352 | } |
352 | 353 | #endif | |
353 | tpnt->proc_name = "g_NCR5380"; | 354 | tpnt->proc_name = "g_NCR5380"; |
354 | 355 | ||
355 | for (count = 0; current_override < NO_OVERRIDES; ++current_override) { | 356 | for (count = 0; current_override < NO_OVERRIDES; ++current_override) { |
@@ -374,7 +375,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) | |||
374 | break; | 375 | break; |
375 | } | 376 | } |
376 | 377 | ||
377 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 378 | #ifndef SCSI_G_NCR5380_MEM |
378 | if (ports) { | 379 | if (ports) { |
379 | /* wakeup sequence for the NCR53C400A and DTC3181E */ | 380 | /* wakeup sequence for the NCR53C400A and DTC3181E */ |
380 | 381 | ||
@@ -436,7 +437,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) | |||
436 | #endif | 437 | #endif |
437 | instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); | 438 | instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); |
438 | if (instance == NULL) { | 439 | if (instance == NULL) { |
439 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 440 | #ifndef SCSI_G_NCR5380_MEM |
440 | release_region(overrides[current_override].NCR5380_map_name, region_size); | 441 | release_region(overrides[current_override].NCR5380_map_name, region_size); |
441 | #else | 442 | #else |
442 | iounmap(iomem); | 443 | iounmap(iomem); |
@@ -446,10 +447,10 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) | |||
446 | } | 447 | } |
447 | 448 | ||
448 | instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; | 449 | instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; |
449 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 450 | #ifndef SCSI_G_NCR5380_MEM |
450 | instance->n_io_port = region_size; | 451 | instance->n_io_port = region_size; |
451 | #else | 452 | #else |
452 | ((struct NCR5380_hostdata *)instance->hostdata).iomem = iomem; | 453 | ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem; |
453 | #endif | 454 | #endif |
454 | 455 | ||
455 | NCR5380_init(instance, flags); | 456 | NCR5380_init(instance, flags); |
@@ -517,10 +518,10 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) | |||
517 | free_irq(instance->irq, instance); | 518 | free_irq(instance->irq, instance); |
518 | NCR5380_exit(instance); | 519 | NCR5380_exit(instance); |
519 | 520 | ||
520 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 521 | #ifndef SCSI_G_NCR5380_MEM |
521 | release_region(instance->NCR5380_instance_name, instance->n_io_port); | 522 | release_region(instance->NCR5380_instance_name, instance->n_io_port); |
522 | #else | 523 | #else |
523 | iounmap(((struct NCR5380_hostdata *)instance->hostdata).iomem); | 524 | iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem); |
524 | release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); | 525 | release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); |
525 | #endif | 526 | #endif |
526 | 527 | ||
@@ -590,14 +591,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, | |||
590 | } | 591 | } |
591 | while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY); | 592 | while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY); |
592 | 593 | ||
593 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 594 | #ifndef SCSI_G_NCR5380_MEM |
594 | { | 595 | { |
595 | int i; | 596 | int i; |
596 | for (i = 0; i < 128; i++) | 597 | for (i = 0; i < 128; i++) |
597 | dst[start + i] = NCR5380_read(C400_HOST_BUFFER); | 598 | dst[start + i] = NCR5380_read(C400_HOST_BUFFER); |
598 | } | 599 | } |
599 | #else | 600 | #else |
600 | /* implies CONFIG_SCSI_G_NCR5380_MEM */ | 601 | /* implies SCSI_G_NCR5380_MEM */ |
601 | memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); | 602 | memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); |
602 | #endif | 603 | #endif |
603 | start += 128; | 604 | start += 128; |
@@ -610,14 +611,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, | |||
610 | // FIXME - no timeout | 611 | // FIXME - no timeout |
611 | } | 612 | } |
612 | 613 | ||
613 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 614 | #ifndef SCSI_G_NCR5380_MEM |
614 | { | 615 | { |
615 | int i; | 616 | int i; |
616 | for (i = 0; i < 128; i++) | 617 | for (i = 0; i < 128; i++) |
617 | dst[start + i] = NCR5380_read(C400_HOST_BUFFER); | 618 | dst[start + i] = NCR5380_read(C400_HOST_BUFFER); |
618 | } | 619 | } |
619 | #else | 620 | #else |
620 | /* implies CONFIG_SCSI_G_NCR5380_MEM */ | 621 | /* implies SCSI_G_NCR5380_MEM */ |
621 | memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); | 622 | memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); |
622 | #endif | 623 | #endif |
623 | start += 128; | 624 | start += 128; |
@@ -676,13 +677,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, | |||
676 | } | 677 | } |
677 | while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) | 678 | while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) |
678 | ; // FIXME - timeout | 679 | ; // FIXME - timeout |
679 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 680 | #ifndef SCSI_G_NCR5380_MEM |
680 | { | 681 | { |
681 | for (i = 0; i < 128; i++) | 682 | for (i = 0; i < 128; i++) |
682 | NCR5380_write(C400_HOST_BUFFER, src[start + i]); | 683 | NCR5380_write(C400_HOST_BUFFER, src[start + i]); |
683 | } | 684 | } |
684 | #else | 685 | #else |
685 | /* implies CONFIG_SCSI_G_NCR5380_MEM */ | 686 | /* implies SCSI_G_NCR5380_MEM */ |
686 | memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); | 687 | memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); |
687 | #endif | 688 | #endif |
688 | start += 128; | 689 | start += 128; |
@@ -692,13 +693,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, | |||
692 | while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) | 693 | while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) |
693 | ; // FIXME - no timeout | 694 | ; // FIXME - no timeout |
694 | 695 | ||
695 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 696 | #ifndef SCSI_G_NCR5380_MEM |
696 | { | 697 | { |
697 | for (i = 0; i < 128; i++) | 698 | for (i = 0; i < 128; i++) |
698 | NCR5380_write(C400_HOST_BUFFER, src[start + i]); | 699 | NCR5380_write(C400_HOST_BUFFER, src[start + i]); |
699 | } | 700 | } |
700 | #else | 701 | #else |
701 | /* implies CONFIG_SCSI_G_NCR5380_MEM */ | 702 | /* implies SCSI_G_NCR5380_MEM */ |
702 | memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); | 703 | memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); |
703 | #endif | 704 | #endif |
704 | start += 128; | 705 | start += 128; |
@@ -938,7 +939,7 @@ module_param(ncr_53c400a, int, 0); | |||
938 | module_param(dtc_3181e, int, 0); | 939 | module_param(dtc_3181e, int, 0); |
939 | MODULE_LICENSE("GPL"); | 940 | MODULE_LICENSE("GPL"); |
940 | 941 | ||
941 | 942 | #ifndef SCSI_G_NCR5380_MEM | |
942 | static struct isapnp_device_id id_table[] __devinitdata = { | 943 | static struct isapnp_device_id id_table[] __devinitdata = { |
943 | { | 944 | { |
944 | ISAPNP_ANY_ID, ISAPNP_ANY_ID, | 945 | ISAPNP_ANY_ID, ISAPNP_ANY_ID, |
@@ -948,7 +949,7 @@ static struct isapnp_device_id id_table[] __devinitdata = { | |||
948 | }; | 949 | }; |
949 | 950 | ||
950 | MODULE_DEVICE_TABLE(isapnp, id_table); | 951 | MODULE_DEVICE_TABLE(isapnp, id_table); |
951 | 952 | #endif | |
952 | 953 | ||
953 | __setup("ncr5380=", do_NCR5380_setup); | 954 | __setup("ncr5380=", do_NCR5380_setup); |
954 | __setup("ncr53c400=", do_NCR53C400_setup); | 955 | __setup("ncr53c400=", do_NCR53C400_setup); |
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index df0b3f69ef63..921764c9ab24 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h | |||
@@ -63,7 +63,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); | |||
63 | #define __STRVAL(x) #x | 63 | #define __STRVAL(x) #x |
64 | #define STRVAL(x) __STRVAL(x) | 64 | #define STRVAL(x) __STRVAL(x) |
65 | 65 | ||
66 | #ifndef CONFIG_SCSI_G_NCR5380_MEM | 66 | #ifndef SCSI_G_NCR5380_MEM |
67 | 67 | ||
68 | #define NCR5380_map_config port | 68 | #define NCR5380_map_config port |
69 | #define NCR5380_map_type int | 69 | #define NCR5380_map_type int |
@@ -91,7 +91,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); | |||
91 | NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) | 91 | NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) |
92 | 92 | ||
93 | #else | 93 | #else |
94 | /* therefore CONFIG_SCSI_G_NCR5380_MEM */ | 94 | /* therefore SCSI_G_NCR5380_MEM */ |
95 | 95 | ||
96 | #define NCR5380_map_config memory | 96 | #define NCR5380_map_config memory |
97 | #define NCR5380_map_type unsigned long | 97 | #define NCR5380_map_type unsigned long |
@@ -114,7 +114,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); | |||
114 | register void __iomem *iomem | 114 | register void __iomem *iomem |
115 | 115 | ||
116 | #define NCR5380_setup(instance) \ | 116 | #define NCR5380_setup(instance) \ |
117 | iomem = (((struct NCR5380_hostdata *)(instance)->hostdata).iomem) | 117 | iomem = (((struct NCR5380_hostdata *)(instance)->hostdata)->iomem) |
118 | 118 | ||
119 | #endif | 119 | #endif |
120 | 120 | ||
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index f672d6213eea..b860d650a563 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c | |||
@@ -4914,7 +4914,7 @@ static int __init gdth_eisa_probe_one(u16 eisa_slot) | |||
4914 | 4914 | ||
4915 | error = scsi_add_host(shp, NULL); | 4915 | error = scsi_add_host(shp, NULL); |
4916 | if (error) | 4916 | if (error) |
4917 | goto out_free_coal_stat; | 4917 | goto out_free_ccb_phys; |
4918 | list_add_tail(&ha->list, &gdth_instances); | 4918 | list_add_tail(&ha->list, &gdth_instances); |
4919 | gdth_timer_init(); | 4919 | gdth_timer_init(); |
4920 | 4920 | ||
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index a7714160fbc3..108797761b95 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c | |||
@@ -2817,7 +2817,6 @@ static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem) | |||
2817 | } | 2817 | } |
2818 | 2818 | ||
2819 | cmnd->result = cblk->tastat | (cblk->hastat << 16); | 2819 | cmnd->result = cblk->tastat | (cblk->hastat << 16); |
2820 | WARN_ON(cmnd == NULL); | ||
2821 | i91u_unmap_scb(host->pci_dev, cmnd); | 2820 | i91u_unmap_scb(host->pci_dev, cmnd); |
2822 | cmnd->scsi_done(cmnd); /* Notify system DONE */ | 2821 | cmnd->scsi_done(cmnd); /* Notify system DONE */ |
2823 | initio_release_scb(host, cblk); /* Release SCB for current channel */ | 2822 | initio_release_scb(host, cblk); /* Release SCB for current channel */ |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 162704cf6a96..ad05b266e950 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/aer.h> | 26 | #include <linux/aer.h> |
27 | #include <linux/gfp.h> | 27 | #include <linux/gfp.h> |
28 | #include <linux/kernel.h> | ||
28 | 29 | ||
29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
30 | #include <scsi/scsi_device.h> | 31 | #include <scsi/scsi_device.h> |
@@ -1795,12 +1796,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, | |||
1795 | 1796 | ||
1796 | /* Validate and store the new name */ | 1797 | /* Validate and store the new name */ |
1797 | for (i=0, j=0; i < 16; i++) { | 1798 | for (i=0, j=0; i < 16; i++) { |
1798 | if ((*buf >= 'a') && (*buf <= 'f')) | 1799 | int value; |
1799 | j = ((j << 4) | ((*buf++ -'a') + 10)); | 1800 | |
1800 | else if ((*buf >= 'A') && (*buf <= 'F')) | 1801 | value = hex_to_bin(*buf++); |
1801 | j = ((j << 4) | ((*buf++ -'A') + 10)); | 1802 | if (value >= 0) |
1802 | else if ((*buf >= '0') && (*buf <= '9')) | 1803 | j = (j << 4) | value; |
1803 | j = ((j << 4) | (*buf++ -'0')); | ||
1804 | else | 1804 | else |
1805 | return -EINVAL; | 1805 | return -EINVAL; |
1806 | if (i % 2) { | 1806 | if (i % 2) { |
@@ -1888,12 +1888,11 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr, | |||
1888 | 1888 | ||
1889 | /* Validate and store the new name */ | 1889 | /* Validate and store the new name */ |
1890 | for (i=0, j=0; i < 16; i++) { | 1890 | for (i=0, j=0; i < 16; i++) { |
1891 | if ((*buf >= 'a') && (*buf <= 'f')) | 1891 | int value; |
1892 | j = ((j << 4) | ((*buf++ -'a') + 10)); | 1892 | |
1893 | else if ((*buf >= 'A') && (*buf <= 'F')) | 1893 | value = hex_to_bin(*buf++); |
1894 | j = ((j << 4) | ((*buf++ -'A') + 10)); | 1894 | if (value >= 0) |
1895 | else if ((*buf >= '0') && (*buf <= '9')) | 1895 | j = (j << 4) | value; |
1896 | j = ((j << 4) | (*buf++ -'0')); | ||
1897 | else | 1896 | else |
1898 | return -EINVAL; | 1897 | return -EINVAL; |
1899 | if (i % 2) { | 1898 | if (i % 2) { |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index d64b7178fa08..278b352ae78d 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
@@ -5868,7 +5868,8 @@ static int osst_probe(struct device *dev) | |||
5868 | } | 5868 | } |
5869 | 5869 | ||
5870 | /* find a free minor number */ | 5870 | /* find a free minor number */ |
5871 | for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++); | 5871 | for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++) |
5872 | ; | ||
5872 | if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)"); | 5873 | if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)"); |
5873 | dev_num = i; | 5874 | dev_num = i; |
5874 | 5875 | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ff2172da7c19..8c80b49ac1c4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -115,8 +115,8 @@ int ql2xmaxqueues = 1; | |||
115 | module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR); | 115 | module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR); |
116 | MODULE_PARM_DESC(ql2xmaxqueues, | 116 | MODULE_PARM_DESC(ql2xmaxqueues, |
117 | "Enables MQ settings " | 117 | "Enables MQ settings " |
118 | "Default is 1 for single queue. Set it to number \ | 118 | "Default is 1 for single queue. Set it to number " |
119 | of queues in MQ mode."); | 119 | "of queues in MQ mode."); |
120 | 120 | ||
121 | int ql2xmultique_tag; | 121 | int ql2xmultique_tag; |
122 | module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR); | 122 | module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR); |
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 53d7ed0dc169..f8c561cf751e 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c | |||
@@ -704,7 +704,7 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) | |||
704 | 704 | ||
705 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) | 705 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) |
706 | { | 706 | { |
707 | struct of_device *op = qpti->op; | 707 | struct platform_device *op = qpti->op; |
708 | 708 | ||
709 | qpti->qregs = of_ioremap(&op->resource[0], 0, | 709 | qpti->qregs = of_ioremap(&op->resource[0], 0, |
710 | resource_size(&op->resource[0]), | 710 | resource_size(&op->resource[0]), |
@@ -727,7 +727,7 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) | |||
727 | 727 | ||
728 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) | 728 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) |
729 | { | 729 | { |
730 | struct of_device *op = qpti->op; | 730 | struct platform_device *op = qpti->op; |
731 | 731 | ||
732 | qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; | 732 | qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; |
733 | 733 | ||
@@ -752,7 +752,7 @@ fail: | |||
752 | 752 | ||
753 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | 753 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) |
754 | { | 754 | { |
755 | struct of_device *op = qpti->op; | 755 | struct platform_device *op = qpti->op; |
756 | struct device_node *dp; | 756 | struct device_node *dp; |
757 | 757 | ||
758 | dp = op->dev.of_node; | 758 | dp = op->dev.of_node; |
@@ -773,7 +773,7 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | |||
773 | 773 | ||
774 | static void qpti_get_bursts(struct qlogicpti *qpti) | 774 | static void qpti_get_bursts(struct qlogicpti *qpti) |
775 | { | 775 | { |
776 | struct of_device *op = qpti->op; | 776 | struct platform_device *op = qpti->op; |
777 | u8 bursts, bmask; | 777 | u8 bursts, bmask; |
778 | 778 | ||
779 | bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); | 779 | bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); |
@@ -806,7 +806,7 @@ static void qpti_get_clock(struct qlogicpti *qpti) | |||
806 | */ | 806 | */ |
807 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) | 807 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) |
808 | { | 808 | { |
809 | struct of_device *op = qpti->op; | 809 | struct platform_device *op = qpti->op; |
810 | 810 | ||
811 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 811 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
812 | qpti->res_cpu = dma_alloc_coherent(&op->dev, | 812 | qpti->res_cpu = dma_alloc_coherent(&op->dev, |
@@ -1290,7 +1290,7 @@ static struct scsi_host_template qpti_template = { | |||
1290 | .use_clustering = ENABLE_CLUSTERING, | 1290 | .use_clustering = ENABLE_CLUSTERING, |
1291 | }; | 1291 | }; |
1292 | 1292 | ||
1293 | static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) | 1293 | static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
1294 | { | 1294 | { |
1295 | struct scsi_host_template *tpnt = match->data; | 1295 | struct scsi_host_template *tpnt = match->data; |
1296 | struct device_node *dp = op->dev.of_node; | 1296 | struct device_node *dp = op->dev.of_node; |
@@ -1401,7 +1401,7 @@ fail_unlink: | |||
1401 | return -ENODEV; | 1401 | return -ENODEV; |
1402 | } | 1402 | } |
1403 | 1403 | ||
1404 | static int __devexit qpti_sbus_remove(struct of_device *op) | 1404 | static int __devexit qpti_sbus_remove(struct platform_device *op) |
1405 | { | 1405 | { |
1406 | struct qlogicpti *qpti = dev_get_drvdata(&op->dev); | 1406 | struct qlogicpti *qpti = dev_get_drvdata(&op->dev); |
1407 | 1407 | ||
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index e3c74d1ee2db..4377e87ee79c 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h | |||
@@ -342,7 +342,7 @@ struct qlogicpti { | |||
342 | u_int req_in_ptr; /* index of next request slot */ | 342 | u_int req_in_ptr; /* index of next request slot */ |
343 | u_int res_out_ptr; /* index of next result slot */ | 343 | u_int res_out_ptr; /* index of next result slot */ |
344 | long send_marker; /* must we send a marker? */ | 344 | long send_marker; /* must we send a marker? */ |
345 | struct of_device *op; | 345 | struct platform_device *op; |
346 | unsigned long __pad; | 346 | unsigned long __pad; |
347 | 347 | ||
348 | int cmd_count[MAX_TARGETS]; | 348 | int cmd_count[MAX_TARGETS]; |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b8de389636f8..9ade720422c6 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1370,12 +1370,6 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) | |||
1370 | 1370 | ||
1371 | blk_start_request(req); | 1371 | blk_start_request(req); |
1372 | 1372 | ||
1373 | if (unlikely(cmd == NULL)) { | ||
1374 | printk(KERN_CRIT "impossible request in %s.\n", | ||
1375 | __func__); | ||
1376 | BUG(); | ||
1377 | } | ||
1378 | |||
1379 | sdev = cmd->device; | 1373 | sdev = cmd->device; |
1380 | starget = scsi_target(sdev); | 1374 | starget = scsi_target(sdev); |
1381 | shost = sdev->host; | 1375 | shost = sdev->host; |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index edb6b362a8fa..d7e470a06180 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/kernel.h> | ||
32 | #include <scsi/scsi_device.h> | 33 | #include <scsi/scsi_device.h> |
33 | #include <scsi/scsi_host.h> | 34 | #include <scsi/scsi_host.h> |
34 | #include <scsi/scsi_transport.h> | 35 | #include <scsi/scsi_transport.h> |
@@ -1730,12 +1731,11 @@ fc_parse_wwn(const char *ns, u64 *nm) | |||
1730 | 1731 | ||
1731 | /* Validate and store the new name */ | 1732 | /* Validate and store the new name */ |
1732 | for (i=0, j=0; i < 16; i++) { | 1733 | for (i=0, j=0; i < 16; i++) { |
1733 | if ((*ns >= 'a') && (*ns <= 'f')) | 1734 | int value; |
1734 | j = ((j << 4) | ((*ns++ -'a') + 10)); | 1735 | |
1735 | else if ((*ns >= 'A') && (*ns <= 'F')) | 1736 | value = hex_to_bin(*ns++); |
1736 | j = ((j << 4) | ((*ns++ -'A') + 10)); | 1737 | if (value >= 0) |
1737 | else if ((*ns >= '0') && (*ns <= '9')) | 1738 | j = (j << 4) | value; |
1738 | j = ((j << 4) | (*ns++ -'0')); | ||
1739 | else | 1739 | else |
1740 | return -EINVAL; | 1740 | return -EINVAL; |
1741 | if (i % 2) { | 1741 | if (i % 2) { |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8e2e893db9e7..2714becc2eaf 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -119,8 +119,8 @@ static DEFINE_IDA(sd_index_ida); | |||
119 | * object after last put) */ | 119 | * object after last put) */ |
120 | static DEFINE_MUTEX(sd_ref_mutex); | 120 | static DEFINE_MUTEX(sd_ref_mutex); |
121 | 121 | ||
122 | struct kmem_cache *sd_cdb_cache; | 122 | static struct kmem_cache *sd_cdb_cache; |
123 | mempool_t *sd_cdb_pool; | 123 | static mempool_t *sd_cdb_pool; |
124 | 124 | ||
125 | static const char *sd_cache_types[] = { | 125 | static const char *sd_cache_types[] = { |
126 | "write through", "none", "write back", | 126 | "write through", "none", "write back", |
@@ -147,7 +147,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, | |||
147 | return -EINVAL; | 147 | return -EINVAL; |
148 | 148 | ||
149 | for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { | 149 | for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { |
150 | const int len = strlen(sd_cache_types[i]); | 150 | len = strlen(sd_cache_types[i]); |
151 | if (strncmp(sd_cache_types[i], buf, len) == 0 && | 151 | if (strncmp(sd_cache_types[i], buf, len) == 0 && |
152 | buf[len] == '\n') { | 152 | buf[len] == '\n') { |
153 | ct = i; | 153 | ct = i; |
@@ -1423,7 +1423,7 @@ sd_spinup_disk(struct scsi_disk *sdkp) | |||
1423 | /* | 1423 | /* |
1424 | * Determine whether disk supports Data Integrity Field. | 1424 | * Determine whether disk supports Data Integrity Field. |
1425 | */ | 1425 | */ |
1426 | void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) | 1426 | static void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) |
1427 | { | 1427 | { |
1428 | struct scsi_device *sdp = sdkp->device; | 1428 | struct scsi_device *sdp = sdkp->device; |
1429 | u8 type; | 1429 | u8 type; |
@@ -1969,7 +1969,7 @@ defaults: | |||
1969 | * The ATO bit indicates whether the DIF application tag is available | 1969 | * The ATO bit indicates whether the DIF application tag is available |
1970 | * for use by the operating system. | 1970 | * for use by the operating system. |
1971 | */ | 1971 | */ |
1972 | void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) | 1972 | static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) |
1973 | { | 1973 | { |
1974 | int res, offset; | 1974 | int res, offset; |
1975 | struct scsi_device *sdp = sdkp->device; | 1975 | struct scsi_device *sdp = sdkp->device; |
@@ -2315,7 +2315,7 @@ static int sd_probe(struct device *dev) | |||
2315 | struct scsi_device *sdp = to_scsi_device(dev); | 2315 | struct scsi_device *sdp = to_scsi_device(dev); |
2316 | struct scsi_disk *sdkp; | 2316 | struct scsi_disk *sdkp; |
2317 | struct gendisk *gd; | 2317 | struct gendisk *gd; |
2318 | u32 index; | 2318 | int index; |
2319 | int error; | 2319 | int error; |
2320 | 2320 | ||
2321 | error = -ENODEV; | 2321 | error = -ENODEV; |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2968c6b83ddb..78d616315d8e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1686,14 +1686,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) | |||
1686 | int len, size = sizeof(struct sg_iovec) * iov_count; | 1686 | int len, size = sizeof(struct sg_iovec) * iov_count; |
1687 | struct iovec *iov; | 1687 | struct iovec *iov; |
1688 | 1688 | ||
1689 | iov = kmalloc(size, GFP_ATOMIC); | 1689 | iov = memdup_user(hp->dxferp, size); |
1690 | if (!iov) | 1690 | if (IS_ERR(iov)) |
1691 | return -ENOMEM; | 1691 | return PTR_ERR(iov); |
1692 | |||
1693 | if (copy_from_user(iov, hp->dxferp, size)) { | ||
1694 | kfree(iov); | ||
1695 | return -EFAULT; | ||
1696 | } | ||
1697 | 1692 | ||
1698 | len = iov_length(iov, iov_count); | 1693 | len = iov_length(iov, iov_count); |
1699 | if (hp->dxfer_len < len) { | 1694 | if (hp->dxfer_len < len) { |
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 89ba6fe02f80..193b37ba1834 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c | |||
@@ -44,7 +44,7 @@ enum dvma_rev { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | static int __devinit esp_sbus_setup_dma(struct esp *esp, | 46 | static int __devinit esp_sbus_setup_dma(struct esp *esp, |
47 | struct of_device *dma_of) | 47 | struct platform_device *dma_of) |
48 | { | 48 | { |
49 | esp->dma = dma_of; | 49 | esp->dma = dma_of; |
50 | 50 | ||
@@ -81,7 +81,7 @@ static int __devinit esp_sbus_setup_dma(struct esp *esp, | |||
81 | 81 | ||
82 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | 82 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) |
83 | { | 83 | { |
84 | struct of_device *op = esp->dev; | 84 | struct platform_device *op = esp->dev; |
85 | struct resource *res; | 85 | struct resource *res; |
86 | 86 | ||
87 | /* On HME, two reg sets exist, first is DVMA, | 87 | /* On HME, two reg sets exist, first is DVMA, |
@@ -101,7 +101,7 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | |||
101 | 101 | ||
102 | static int __devinit esp_sbus_map_command_block(struct esp *esp) | 102 | static int __devinit esp_sbus_map_command_block(struct esp *esp) |
103 | { | 103 | { |
104 | struct of_device *op = esp->dev; | 104 | struct platform_device *op = esp->dev; |
105 | 105 | ||
106 | esp->command_block = dma_alloc_coherent(&op->dev, 16, | 106 | esp->command_block = dma_alloc_coherent(&op->dev, 16, |
107 | &esp->command_block_dma, | 107 | &esp->command_block_dma, |
@@ -114,15 +114,15 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp) | |||
114 | static int __devinit esp_sbus_register_irq(struct esp *esp) | 114 | static int __devinit esp_sbus_register_irq(struct esp *esp) |
115 | { | 115 | { |
116 | struct Scsi_Host *host = esp->host; | 116 | struct Scsi_Host *host = esp->host; |
117 | struct of_device *op = esp->dev; | 117 | struct platform_device *op = esp->dev; |
118 | 118 | ||
119 | host->irq = op->archdata.irqs[0]; | 119 | host->irq = op->archdata.irqs[0]; |
120 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); | 120 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); |
121 | } | 121 | } |
122 | 122 | ||
123 | static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma) | 123 | static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma) |
124 | { | 124 | { |
125 | struct of_device *op = esp->dev; | 125 | struct platform_device *op = esp->dev; |
126 | struct device_node *dp; | 126 | struct device_node *dp; |
127 | 127 | ||
128 | dp = op->dev.of_node; | 128 | dp = op->dev.of_node; |
@@ -144,7 +144,7 @@ done: | |||
144 | 144 | ||
145 | static void __devinit esp_get_differential(struct esp *esp) | 145 | static void __devinit esp_get_differential(struct esp *esp) |
146 | { | 146 | { |
147 | struct of_device *op = esp->dev; | 147 | struct platform_device *op = esp->dev; |
148 | struct device_node *dp; | 148 | struct device_node *dp; |
149 | 149 | ||
150 | dp = op->dev.of_node; | 150 | dp = op->dev.of_node; |
@@ -156,7 +156,7 @@ static void __devinit esp_get_differential(struct esp *esp) | |||
156 | 156 | ||
157 | static void __devinit esp_get_clock_params(struct esp *esp) | 157 | static void __devinit esp_get_clock_params(struct esp *esp) |
158 | { | 158 | { |
159 | struct of_device *op = esp->dev; | 159 | struct platform_device *op = esp->dev; |
160 | struct device_node *bus_dp, *dp; | 160 | struct device_node *bus_dp, *dp; |
161 | int fmhz; | 161 | int fmhz; |
162 | 162 | ||
@@ -170,10 +170,10 @@ static void __devinit esp_get_clock_params(struct esp *esp) | |||
170 | esp->cfreq = fmhz; | 170 | esp->cfreq = fmhz; |
171 | } | 171 | } |
172 | 172 | ||
173 | static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) | 173 | static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of) |
174 | { | 174 | { |
175 | struct device_node *dma_dp = dma_of->dev.of_node; | 175 | struct device_node *dma_dp = dma_of->dev.of_node; |
176 | struct of_device *op = esp->dev; | 176 | struct platform_device *op = esp->dev; |
177 | struct device_node *dp; | 177 | struct device_node *dp; |
178 | u8 bursts, val; | 178 | u8 bursts, val; |
179 | 179 | ||
@@ -195,7 +195,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) | |||
195 | esp->bursts = bursts; | 195 | esp->bursts = bursts; |
196 | } | 196 | } |
197 | 197 | ||
198 | static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) | 198 | static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma) |
199 | { | 199 | { |
200 | esp_get_scsi_id(esp, espdma); | 200 | esp_get_scsi_id(esp, espdma); |
201 | esp_get_differential(esp); | 201 | esp_get_differential(esp); |
@@ -216,7 +216,7 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg) | |||
216 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, | 216 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, |
217 | size_t sz, int dir) | 217 | size_t sz, int dir) |
218 | { | 218 | { |
219 | struct of_device *op = esp->dev; | 219 | struct platform_device *op = esp->dev; |
220 | 220 | ||
221 | return dma_map_single(&op->dev, buf, sz, dir); | 221 | return dma_map_single(&op->dev, buf, sz, dir); |
222 | } | 222 | } |
@@ -224,7 +224,7 @@ static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, | |||
224 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, | 224 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, |
225 | int num_sg, int dir) | 225 | int num_sg, int dir) |
226 | { | 226 | { |
227 | struct of_device *op = esp->dev; | 227 | struct platform_device *op = esp->dev; |
228 | 228 | ||
229 | return dma_map_sg(&op->dev, sg, num_sg, dir); | 229 | return dma_map_sg(&op->dev, sg, num_sg, dir); |
230 | } | 230 | } |
@@ -232,7 +232,7 @@ static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, | |||
232 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, | 232 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, |
233 | size_t sz, int dir) | 233 | size_t sz, int dir) |
234 | { | 234 | { |
235 | struct of_device *op = esp->dev; | 235 | struct platform_device *op = esp->dev; |
236 | 236 | ||
237 | dma_unmap_single(&op->dev, addr, sz, dir); | 237 | dma_unmap_single(&op->dev, addr, sz, dir); |
238 | } | 238 | } |
@@ -240,7 +240,7 @@ static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, | |||
240 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, | 240 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, |
241 | int num_sg, int dir) | 241 | int num_sg, int dir) |
242 | { | 242 | { |
243 | struct of_device *op = esp->dev; | 243 | struct platform_device *op = esp->dev; |
244 | 244 | ||
245 | dma_unmap_sg(&op->dev, sg, num_sg, dir); | 245 | dma_unmap_sg(&op->dev, sg, num_sg, dir); |
246 | } | 246 | } |
@@ -256,7 +256,7 @@ static void sbus_esp_reset_dma(struct esp *esp) | |||
256 | { | 256 | { |
257 | int can_do_burst16, can_do_burst32, can_do_burst64; | 257 | int can_do_burst16, can_do_burst32, can_do_burst64; |
258 | int can_do_sbus64, lim; | 258 | int can_do_sbus64, lim; |
259 | struct of_device *op; | 259 | struct platform_device *op; |
260 | u32 val; | 260 | u32 val; |
261 | 261 | ||
262 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; | 262 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; |
@@ -487,8 +487,8 @@ static const struct esp_driver_ops sbus_esp_ops = { | |||
487 | .dma_error = sbus_esp_dma_error, | 487 | .dma_error = sbus_esp_dma_error, |
488 | }; | 488 | }; |
489 | 489 | ||
490 | static int __devinit esp_sbus_probe_one(struct of_device *op, | 490 | static int __devinit esp_sbus_probe_one(struct platform_device *op, |
491 | struct of_device *espdma, | 491 | struct platform_device *espdma, |
492 | int hme) | 492 | int hme) |
493 | { | 493 | { |
494 | struct scsi_host_template *tpnt = &scsi_esp_template; | 494 | struct scsi_host_template *tpnt = &scsi_esp_template; |
@@ -562,11 +562,11 @@ fail: | |||
562 | return err; | 562 | return err; |
563 | } | 563 | } |
564 | 564 | ||
565 | static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match) | 565 | static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match) |
566 | { | 566 | { |
567 | struct device_node *dma_node = NULL; | 567 | struct device_node *dma_node = NULL; |
568 | struct device_node *dp = op->dev.of_node; | 568 | struct device_node *dp = op->dev.of_node; |
569 | struct of_device *dma_of = NULL; | 569 | struct platform_device *dma_of = NULL; |
570 | int hme = 0; | 570 | int hme = 0; |
571 | 571 | ||
572 | if (dp->parent && | 572 | if (dp->parent && |
@@ -585,10 +585,10 @@ static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device | |||
585 | return esp_sbus_probe_one(op, dma_of, hme); | 585 | return esp_sbus_probe_one(op, dma_of, hme); |
586 | } | 586 | } |
587 | 587 | ||
588 | static int __devexit esp_sbus_remove(struct of_device *op) | 588 | static int __devexit esp_sbus_remove(struct platform_device *op) |
589 | { | 589 | { |
590 | struct esp *esp = dev_get_drvdata(&op->dev); | 590 | struct esp *esp = dev_get_drvdata(&op->dev); |
591 | struct of_device *dma_of = esp->dma; | 591 | struct platform_device *dma_of = esp->dma; |
592 | unsigned int irq = esp->host->irq; | 592 | unsigned int irq = esp->host->irq; |
593 | bool is_hme; | 593 | bool is_hme; |
594 | u32 val; | 594 | u32 val; |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index a22e60c06f48..12900f7083b0 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -536,8 +536,8 @@ config SERIAL_S3C6400 | |||
536 | 536 | ||
537 | config SERIAL_S5PV210 | 537 | config SERIAL_S5PV210 |
538 | tristate "Samsung S5PV210 Serial port support" | 538 | tristate "Samsung S5PV210 Serial port support" |
539 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442) | 539 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_S5PV310) |
540 | select SERIAL_SAMSUNG_UARTS_4 if CPU_S5PV210 | 540 | select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_S5PV310) |
541 | default y | 541 | default y |
542 | help | 542 | help |
543 | Serial port support for Samsung's S5P Family of SoC's | 543 | Serial port support for Samsung's S5P Family of SoC's |
diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c index 0099b8692b60..cc01c650a144 100644 --- a/drivers/serial/apbuart.c +++ b/drivers/serial/apbuart.c | |||
@@ -551,7 +551,7 @@ static struct uart_driver grlib_apbuart_driver = { | |||
551 | /* OF Platform Driver */ | 551 | /* OF Platform Driver */ |
552 | /* ======================================================================== */ | 552 | /* ======================================================================== */ |
553 | 553 | ||
554 | static int __devinit apbuart_probe(struct of_device *op, | 554 | static int __devinit apbuart_probe(struct platform_device *op, |
555 | const struct of_device_id *match) | 555 | const struct of_device_id *match) |
556 | { | 556 | { |
557 | int i = -1; | 557 | int i = -1; |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 6016179db533..f2b8adcc6c92 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -1340,7 +1340,7 @@ static struct uart_driver cpm_reg = { | |||
1340 | 1340 | ||
1341 | static int probe_index; | 1341 | static int probe_index; |
1342 | 1342 | ||
1343 | static int __devinit cpm_uart_probe(struct of_device *ofdev, | 1343 | static int __devinit cpm_uart_probe(struct platform_device *ofdev, |
1344 | const struct of_device_id *match) | 1344 | const struct of_device_id *match) |
1345 | { | 1345 | { |
1346 | int index = probe_index++; | 1346 | int index = probe_index++; |
@@ -1364,7 +1364,7 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev, | |||
1364 | return uart_add_one_port(&cpm_reg, &pinfo->port); | 1364 | return uart_add_one_port(&cpm_reg, &pinfo->port); |
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | static int __devexit cpm_uart_remove(struct of_device *ofdev) | 1367 | static int __devexit cpm_uart_remove(struct platform_device *ofdev) |
1368 | { | 1368 | { |
1369 | struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); | 1369 | struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); |
1370 | return uart_remove_one_port(&cpm_reg, &pinfo->port); | 1370 | return uart_remove_one_port(&cpm_reg, &pinfo->port); |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 1a88b363005c..8dedb266f143 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -1298,7 +1298,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
1298 | }; | 1298 | }; |
1299 | 1299 | ||
1300 | static int __devinit | 1300 | static int __devinit |
1301 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | 1301 | mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match) |
1302 | { | 1302 | { |
1303 | int idx = -1; | 1303 | int idx = -1; |
1304 | unsigned int uartclk; | 1304 | unsigned int uartclk; |
@@ -1369,7 +1369,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | static int | 1371 | static int |
1372 | mpc52xx_uart_of_remove(struct of_device *op) | 1372 | mpc52xx_uart_of_remove(struct platform_device *op) |
1373 | { | 1373 | { |
1374 | struct uart_port *port = dev_get_drvdata(&op->dev); | 1374 | struct uart_port *port = dev_get_drvdata(&op->dev); |
1375 | dev_set_drvdata(&op->dev, NULL); | 1375 | dev_set_drvdata(&op->dev, NULL); |
@@ -1382,7 +1382,7 @@ mpc52xx_uart_of_remove(struct of_device *op) | |||
1382 | 1382 | ||
1383 | #ifdef CONFIG_PM | 1383 | #ifdef CONFIG_PM |
1384 | static int | 1384 | static int |
1385 | mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) | 1385 | mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) |
1386 | { | 1386 | { |
1387 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1387 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); |
1388 | 1388 | ||
@@ -1393,7 +1393,7 @@ mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) | |||
1393 | } | 1393 | } |
1394 | 1394 | ||
1395 | static int | 1395 | static int |
1396 | mpc52xx_uart_of_resume(struct of_device *op) | 1396 | mpc52xx_uart_of_resume(struct platform_device *op) |
1397 | { | 1397 | { |
1398 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1398 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); |
1399 | 1399 | ||
diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c index e65b0d9202a5..de173671e3d0 100644 --- a/drivers/serial/nwpserial.c +++ b/drivers/serial/nwpserial.c | |||
@@ -344,7 +344,7 @@ int nwpserial_register_port(struct uart_port *port) | |||
344 | 344 | ||
345 | mutex_lock(&nwpserial_mutex); | 345 | mutex_lock(&nwpserial_mutex); |
346 | 346 | ||
347 | dn = to_of_device(port->dev)->dev.of_node; | 347 | dn = port->dev->of_node; |
348 | if (dn == NULL) | 348 | if (dn == NULL) |
349 | goto out; | 349 | goto out; |
350 | 350 | ||
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index a48d9080f552..659a695bdad6 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c | |||
@@ -27,7 +27,7 @@ struct of_serial_info { | |||
27 | /* | 27 | /* |
28 | * Fill a struct uart_port for a given device node | 28 | * Fill a struct uart_port for a given device node |
29 | */ | 29 | */ |
30 | static int __devinit of_platform_serial_setup(struct of_device *ofdev, | 30 | static int __devinit of_platform_serial_setup(struct platform_device *ofdev, |
31 | int type, struct uart_port *port) | 31 | int type, struct uart_port *port) |
32 | { | 32 | { |
33 | struct resource resource; | 33 | struct resource resource; |
@@ -80,7 +80,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, | |||
80 | /* | 80 | /* |
81 | * Try to register a serial port | 81 | * Try to register a serial port |
82 | */ | 82 | */ |
83 | static int __devinit of_platform_serial_probe(struct of_device *ofdev, | 83 | static int __devinit of_platform_serial_probe(struct platform_device *ofdev, |
84 | const struct of_device_id *id) | 84 | const struct of_device_id *id) |
85 | { | 85 | { |
86 | struct of_serial_info *info; | 86 | struct of_serial_info *info; |
@@ -134,7 +134,7 @@ out: | |||
134 | /* | 134 | /* |
135 | * Release a line | 135 | * Release a line |
136 | */ | 136 | */ |
137 | static int of_platform_serial_remove(struct of_device *ofdev) | 137 | static int of_platform_serial_remove(struct platform_device *ofdev) |
138 | { | 138 | { |
139 | struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); | 139 | struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); |
140 | switch (info->type) { | 140 | switch (info->type) { |
diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c index 4a789e5361a4..6ebccd70a707 100644 --- a/drivers/serial/s5pv210.c +++ b/drivers/serial/s5pv210.c | |||
@@ -28,8 +28,12 @@ | |||
28 | static int s5pv210_serial_setsource(struct uart_port *port, | 28 | static int s5pv210_serial_setsource(struct uart_port *port, |
29 | struct s3c24xx_uart_clksrc *clk) | 29 | struct s3c24xx_uart_clksrc *clk) |
30 | { | 30 | { |
31 | struct s3c2410_uartcfg *cfg = port->dev->platform_data; | ||
31 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | 32 | unsigned long ucon = rd_regl(port, S3C2410_UCON); |
32 | 33 | ||
34 | if ((cfg->clocks_size) == 1) | ||
35 | return 0; | ||
36 | |||
33 | if (strcmp(clk->name, "pclk") == 0) | 37 | if (strcmp(clk->name, "pclk") == 0) |
34 | ucon &= ~S5PV210_UCON_CLKMASK; | 38 | ucon &= ~S5PV210_UCON_CLKMASK; |
35 | else if (strcmp(clk->name, "uclk1") == 0) | 39 | else if (strcmp(clk->name, "uclk1") == 0) |
@@ -47,10 +51,14 @@ static int s5pv210_serial_setsource(struct uart_port *port, | |||
47 | static int s5pv210_serial_getsource(struct uart_port *port, | 51 | static int s5pv210_serial_getsource(struct uart_port *port, |
48 | struct s3c24xx_uart_clksrc *clk) | 52 | struct s3c24xx_uart_clksrc *clk) |
49 | { | 53 | { |
54 | struct s3c2410_uartcfg *cfg = port->dev->platform_data; | ||
50 | u32 ucon = rd_regl(port, S3C2410_UCON); | 55 | u32 ucon = rd_regl(port, S3C2410_UCON); |
51 | 56 | ||
52 | clk->divisor = 1; | 57 | clk->divisor = 1; |
53 | 58 | ||
59 | if ((cfg->clocks_size) == 1) | ||
60 | return 0; | ||
61 | |||
54 | switch (ucon & S5PV210_UCON_CLKMASK) { | 62 | switch (ucon & S5PV210_UCON_CLKMASK) { |
55 | case S5PV210_UCON_PCLK: | 63 | case S5PV210_UCON_PCLK: |
56 | clk->name = "pclk"; | 64 | clk->name = "pclk"; |
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index a9d6c5626a0a..b1156ba8ad14 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c | |||
@@ -705,8 +705,13 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, | |||
705 | if (ourport->info->has_divslot) { | 705 | if (ourport->info->has_divslot) { |
706 | unsigned int div = ourport->baudclk_rate / baud; | 706 | unsigned int div = ourport->baudclk_rate / baud; |
707 | 707 | ||
708 | udivslot = udivslot_table[div & 15]; | 708 | if (cfg->has_fracval) { |
709 | dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); | 709 | udivslot = (div & 15); |
710 | dbg("fracval = %04x\n", udivslot); | ||
711 | } else { | ||
712 | udivslot = udivslot_table[div & 15]; | ||
713 | dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); | ||
714 | } | ||
710 | } | 715 | } |
711 | 716 | ||
712 | switch (termios->c_cflag & CSIZE) { | 717 | switch (termios->c_cflag & CSIZE) { |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5f90fcd7d107..c291b3add1d2 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -346,6 +346,27 @@ static int scif_rxfill(struct uart_port *port) | |||
346 | return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; | 346 | return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; |
347 | } | 347 | } |
348 | } | 348 | } |
349 | #elif defined(CONFIG_ARCH_SH7372) | ||
350 | static int scif_txfill(struct uart_port *port) | ||
351 | { | ||
352 | if (port->type == PORT_SCIFA) | ||
353 | return sci_in(port, SCFDR) >> 8; | ||
354 | else | ||
355 | return sci_in(port, SCTFDR); | ||
356 | } | ||
357 | |||
358 | static int scif_txroom(struct uart_port *port) | ||
359 | { | ||
360 | return port->fifosize - scif_txfill(port); | ||
361 | } | ||
362 | |||
363 | static int scif_rxfill(struct uart_port *port) | ||
364 | { | ||
365 | if (port->type == PORT_SCIFA) | ||
366 | return sci_in(port, SCFDR) & SCIF_RFDC_MASK; | ||
367 | else | ||
368 | return sci_in(port, SCRFDR); | ||
369 | } | ||
349 | #else | 370 | #else |
350 | static int scif_txfill(struct uart_port *port) | 371 | static int scif_txfill(struct uart_port *port) |
351 | { | 372 | { |
@@ -683,7 +704,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) | |||
683 | u16 ssr = sci_in(port, SCxSR); | 704 | u16 ssr = sci_in(port, SCxSR); |
684 | 705 | ||
685 | /* Disable future Rx interrupts */ | 706 | /* Disable future Rx interrupts */ |
686 | if (port->type == PORT_SCIFA) { | 707 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
687 | disable_irq_nosync(irq); | 708 | disable_irq_nosync(irq); |
688 | scr |= 0x4000; | 709 | scr |= 0x4000; |
689 | } else { | 710 | } else { |
@@ -928,7 +949,7 @@ static void sci_dma_tx_complete(void *arg) | |||
928 | 949 | ||
929 | if (!uart_circ_empty(xmit)) { | 950 | if (!uart_circ_empty(xmit)) { |
930 | schedule_work(&s->work_tx); | 951 | schedule_work(&s->work_tx); |
931 | } else if (port->type == PORT_SCIFA) { | 952 | } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
932 | u16 ctrl = sci_in(port, SCSCR); | 953 | u16 ctrl = sci_in(port, SCSCR); |
933 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); | 954 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); |
934 | } | 955 | } |
@@ -1184,7 +1205,7 @@ static void sci_start_tx(struct uart_port *port) | |||
1184 | unsigned short ctrl; | 1205 | unsigned short ctrl; |
1185 | 1206 | ||
1186 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1207 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
1187 | if (port->type == PORT_SCIFA) { | 1208 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1188 | u16 new, scr = sci_in(port, SCSCR); | 1209 | u16 new, scr = sci_in(port, SCSCR); |
1189 | if (s->chan_tx) | 1210 | if (s->chan_tx) |
1190 | new = scr | 0x8000; | 1211 | new = scr | 0x8000; |
@@ -1197,7 +1218,7 @@ static void sci_start_tx(struct uart_port *port) | |||
1197 | s->cookie_tx < 0) | 1218 | s->cookie_tx < 0) |
1198 | schedule_work(&s->work_tx); | 1219 | schedule_work(&s->work_tx); |
1199 | #endif | 1220 | #endif |
1200 | if (!s->chan_tx || port->type == PORT_SCIFA) { | 1221 | if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1201 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1222 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1202 | ctrl = sci_in(port, SCSCR); | 1223 | ctrl = sci_in(port, SCSCR); |
1203 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); | 1224 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); |
@@ -1210,7 +1231,7 @@ static void sci_stop_tx(struct uart_port *port) | |||
1210 | 1231 | ||
1211 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1232 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1212 | ctrl = sci_in(port, SCSCR); | 1233 | ctrl = sci_in(port, SCSCR); |
1213 | if (port->type == PORT_SCIFA) | 1234 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1214 | ctrl &= ~0x8000; | 1235 | ctrl &= ~0x8000; |
1215 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 1236 | ctrl &= ~SCI_CTRL_FLAGS_TIE; |
1216 | sci_out(port, SCSCR, ctrl); | 1237 | sci_out(port, SCSCR, ctrl); |
@@ -1222,7 +1243,7 @@ static void sci_start_rx(struct uart_port *port) | |||
1222 | 1243 | ||
1223 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | 1244 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ |
1224 | ctrl |= sci_in(port, SCSCR); | 1245 | ctrl |= sci_in(port, SCSCR); |
1225 | if (port->type == PORT_SCIFA) | 1246 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1226 | ctrl &= ~0x4000; | 1247 | ctrl &= ~0x4000; |
1227 | sci_out(port, SCSCR, ctrl); | 1248 | sci_out(port, SCSCR, ctrl); |
1228 | } | 1249 | } |
@@ -1233,7 +1254,7 @@ static void sci_stop_rx(struct uart_port *port) | |||
1233 | 1254 | ||
1234 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ | 1255 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ |
1235 | ctrl = sci_in(port, SCSCR); | 1256 | ctrl = sci_in(port, SCSCR); |
1236 | if (port->type == PORT_SCIFA) | 1257 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1237 | ctrl &= ~0x4000; | 1258 | ctrl &= ~0x4000; |
1238 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); | 1259 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); |
1239 | sci_out(port, SCSCR, ctrl); | 1260 | sci_out(port, SCSCR, ctrl); |
@@ -1271,7 +1292,7 @@ static void rx_timer_fn(unsigned long arg) | |||
1271 | struct uart_port *port = &s->port; | 1292 | struct uart_port *port = &s->port; |
1272 | u16 scr = sci_in(port, SCSCR); | 1293 | u16 scr = sci_in(port, SCSCR); |
1273 | 1294 | ||
1274 | if (port->type == PORT_SCIFA) { | 1295 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1275 | scr &= ~0x4000; | 1296 | scr &= ~0x4000; |
1276 | enable_irq(s->irqs[1]); | 1297 | enable_irq(s->irqs[1]); |
1277 | } | 1298 | } |
@@ -1524,6 +1545,8 @@ static const char *sci_type(struct uart_port *port) | |||
1524 | return "scif"; | 1545 | return "scif"; |
1525 | case PORT_SCIFA: | 1546 | case PORT_SCIFA: |
1526 | return "scifa"; | 1547 | return "scifa"; |
1548 | case PORT_SCIFB: | ||
1549 | return "scifb"; | ||
1527 | } | 1550 | } |
1528 | 1551 | ||
1529 | return NULL; | 1552 | return NULL; |
@@ -1612,6 +1635,9 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1612 | port->line = index; | 1635 | port->line = index; |
1613 | 1636 | ||
1614 | switch (p->type) { | 1637 | switch (p->type) { |
1638 | case PORT_SCIFB: | ||
1639 | port->fifosize = 256; | ||
1640 | break; | ||
1615 | case PORT_SCIFA: | 1641 | case PORT_SCIFA: |
1616 | port->fifosize = 64; | 1642 | port->fifosize = 64; |
1617 | break; | 1643 | break; |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f70c49f915fa..9b52f77a9305 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -322,7 +322,7 @@ | |||
322 | #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ | 322 | #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ |
323 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ | 323 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ |
324 | { \ | 324 | { \ |
325 | if (port->type == PORT_SCIF) { \ | 325 | if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \ |
326 | SCI_IN(scif_size, scif_offset) \ | 326 | SCI_IN(scif_size, scif_offset) \ |
327 | } else { /* PORT_SCI or PORT_SCIFA */ \ | 327 | } else { /* PORT_SCI or PORT_SCIFA */ \ |
328 | SCI_IN(sci_size, sci_offset); \ | 328 | SCI_IN(sci_size, sci_offset); \ |
@@ -330,7 +330,7 @@ | |||
330 | } \ | 330 | } \ |
331 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ | 331 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ |
332 | { \ | 332 | { \ |
333 | if (port->type == PORT_SCIF) { \ | 333 | if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \ |
334 | SCI_OUT(scif_size, scif_offset, value) \ | 334 | SCI_OUT(scif_size, scif_offset, value) \ |
335 | } else { /* PORT_SCI or PORT_SCIFA */ \ | 335 | } else { /* PORT_SCI or PORT_SCIFA */ \ |
336 | SCI_OUT(sci_size, sci_offset, value); \ | 336 | SCI_OUT(sci_size, sci_offset, value); \ |
@@ -384,8 +384,12 @@ | |||
384 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 384 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
385 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 385 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
386 | defined(CONFIG_ARCH_SH7367) || \ | 386 | defined(CONFIG_ARCH_SH7367) || \ |
387 | defined(CONFIG_ARCH_SH7377) || \ | 387 | defined(CONFIG_ARCH_SH7377) |
388 | defined(CONFIG_ARCH_SH7372) | 388 | #define SCIF_FNS(name, scif_offset, scif_size) \ |
389 | CPU_SCIF_FNS(name, scif_offset, scif_size) | ||
390 | #elif defined(CONFIG_ARCH_SH7372) | ||
391 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \ | ||
392 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) | ||
389 | #define SCIF_FNS(name, scif_offset, scif_size) \ | 393 | #define SCIF_FNS(name, scif_offset, scif_size) \ |
390 | CPU_SCIF_FNS(name, scif_offset, scif_size) | 394 | CPU_SCIF_FNS(name, scif_offset, scif_size) |
391 | #else | 395 | #else |
@@ -422,8 +426,7 @@ | |||
422 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 426 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
423 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 427 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
424 | defined(CONFIG_ARCH_SH7367) || \ | 428 | defined(CONFIG_ARCH_SH7367) || \ |
425 | defined(CONFIG_ARCH_SH7377) || \ | 429 | defined(CONFIG_ARCH_SH7377) |
426 | defined(CONFIG_ARCH_SH7372) | ||
427 | 430 | ||
428 | SCIF_FNS(SCSMR, 0x00, 16) | 431 | SCIF_FNS(SCSMR, 0x00, 16) |
429 | SCIF_FNS(SCBRR, 0x04, 8) | 432 | SCIF_FNS(SCBRR, 0x04, 8) |
@@ -436,6 +439,20 @@ SCIF_FNS(SCFDR, 0x1c, 16) | |||
436 | SCIF_FNS(SCxTDR, 0x20, 8) | 439 | SCIF_FNS(SCxTDR, 0x20, 8) |
437 | SCIF_FNS(SCxRDR, 0x24, 8) | 440 | SCIF_FNS(SCxRDR, 0x24, 8) |
438 | SCIF_FNS(SCLSR, 0x00, 0) | 441 | SCIF_FNS(SCLSR, 0x00, 0) |
442 | #elif defined(CONFIG_ARCH_SH7372) | ||
443 | SCIF_FNS(SCSMR, 0x00, 16) | ||
444 | SCIF_FNS(SCBRR, 0x04, 8) | ||
445 | SCIF_FNS(SCSCR, 0x08, 16) | ||
446 | SCIF_FNS(SCTDSR, 0x0c, 16) | ||
447 | SCIF_FNS(SCFER, 0x10, 16) | ||
448 | SCIF_FNS(SCxSR, 0x14, 16) | ||
449 | SCIF_FNS(SCFCR, 0x18, 16) | ||
450 | SCIF_FNS(SCFDR, 0x1c, 16) | ||
451 | SCIF_FNS(SCTFDR, 0x38, 16) | ||
452 | SCIF_FNS(SCRFDR, 0x3c, 16) | ||
453 | SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8) | ||
454 | SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8) | ||
455 | SCIF_FNS(SCLSR, 0x00, 0) | ||
439 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ | 456 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
440 | defined(CONFIG_CPU_SUBTYPE_SH7724) | 457 | defined(CONFIG_CPU_SUBTYPE_SH7724) |
441 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) | 458 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) |
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index a779e22d213e..c9014868297d 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
@@ -519,7 +519,7 @@ static struct console sunhv_console = { | |||
519 | .data = &sunhv_reg, | 519 | .data = &sunhv_reg, |
520 | }; | 520 | }; |
521 | 521 | ||
522 | static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) | 522 | static int __devinit hv_probe(struct platform_device *op, const struct of_device_id *match) |
523 | { | 523 | { |
524 | struct uart_port *port; | 524 | struct uart_port *port; |
525 | unsigned long minor; | 525 | unsigned long minor; |
@@ -598,7 +598,7 @@ out_free_port: | |||
598 | return err; | 598 | return err; |
599 | } | 599 | } |
600 | 600 | ||
601 | static int __devexit hv_remove(struct of_device *dev) | 601 | static int __devexit hv_remove(struct platform_device *dev) |
602 | { | 602 | { |
603 | struct uart_port *port = dev_get_drvdata(&dev->dev); | 603 | struct uart_port *port = dev_get_drvdata(&dev->dev); |
604 | 604 | ||
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 9845fb1cfb1f..5b246b18f42f 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -883,7 +883,7 @@ static int sunsab_console_setup(struct console *con, char *options) | |||
883 | printk("Console: ttyS%d (SAB82532)\n", | 883 | printk("Console: ttyS%d (SAB82532)\n", |
884 | (sunsab_reg.minor - 64) + con->index); | 884 | (sunsab_reg.minor - 64) + con->index); |
885 | 885 | ||
886 | sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); | 886 | sunserial_console_termios(con, up->port.dev->of_node); |
887 | 887 | ||
888 | switch (con->cflag & CBAUD) { | 888 | switch (con->cflag & CBAUD) { |
889 | case B150: baud = 150; break; | 889 | case B150: baud = 150; break; |
@@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void) | |||
954 | #endif | 954 | #endif |
955 | 955 | ||
956 | static int __devinit sunsab_init_one(struct uart_sunsab_port *up, | 956 | static int __devinit sunsab_init_one(struct uart_sunsab_port *up, |
957 | struct of_device *op, | 957 | struct platform_device *op, |
958 | unsigned long offset, | 958 | unsigned long offset, |
959 | int line) | 959 | int line) |
960 | { | 960 | { |
@@ -1006,7 +1006,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, | |||
1006 | return 0; | 1006 | return 0; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | static int __devinit sab_probe(struct of_device *op, const struct of_device_id *match) | 1009 | static int __devinit sab_probe(struct platform_device *op, const struct of_device_id *match) |
1010 | { | 1010 | { |
1011 | static int inst; | 1011 | static int inst; |
1012 | struct uart_sunsab_port *up; | 1012 | struct uart_sunsab_port *up; |
@@ -1062,7 +1062,7 @@ out: | |||
1062 | return err; | 1062 | return err; |
1063 | } | 1063 | } |
1064 | 1064 | ||
1065 | static int __devexit sab_remove(struct of_device *op) | 1065 | static int __devexit sab_remove(struct platform_device *op) |
1066 | { | 1066 | { |
1067 | struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); | 1067 | struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); |
1068 | 1068 | ||
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 3cdf74822db5..551ebfe3ccbb 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
@@ -1200,7 +1200,7 @@ static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up) | |||
1200 | return -ENODEV; | 1200 | return -ENODEV; |
1201 | 1201 | ||
1202 | printk("%s: %s port at %llx, irq %u\n", | 1202 | printk("%s: %s port at %llx, irq %u\n", |
1203 | to_of_device(up->port.dev)->dev.of_node->full_name, | 1203 | up->port.dev->of_node->full_name, |
1204 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", | 1204 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", |
1205 | (unsigned long long) up->port.mapbase, | 1205 | (unsigned long long) up->port.mapbase, |
1206 | up->port.irq); | 1206 | up->port.irq); |
@@ -1352,7 +1352,7 @@ static int __init sunsu_console_setup(struct console *co, char *options) | |||
1352 | spin_lock_init(&port->lock); | 1352 | spin_lock_init(&port->lock); |
1353 | 1353 | ||
1354 | /* Get firmware console settings. */ | 1354 | /* Get firmware console settings. */ |
1355 | sunserial_console_termios(co, to_of_device(port->dev)->dev.of_node); | 1355 | sunserial_console_termios(co, port->dev->of_node); |
1356 | 1356 | ||
1357 | memset(&termios, 0, sizeof(struct ktermios)); | 1357 | memset(&termios, 0, sizeof(struct ktermios)); |
1358 | termios.c_cflag = co->cflag; | 1358 | termios.c_cflag = co->cflag; |
@@ -1406,7 +1406,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp) | |||
1406 | return SU_PORT_PORT; | 1406 | return SU_PORT_PORT; |
1407 | } | 1407 | } |
1408 | 1408 | ||
1409 | static int __devinit su_probe(struct of_device *op, const struct of_device_id *match) | 1409 | static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match) |
1410 | { | 1410 | { |
1411 | static int inst; | 1411 | static int inst; |
1412 | struct device_node *dp = op->dev.of_node; | 1412 | struct device_node *dp = op->dev.of_node; |
@@ -1497,7 +1497,7 @@ out_unmap: | |||
1497 | return err; | 1497 | return err; |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | static int __devexit su_remove(struct of_device *op) | 1500 | static int __devexit su_remove(struct platform_device *op) |
1501 | { | 1501 | { |
1502 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); | 1502 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); |
1503 | bool kbdms = false; | 1503 | bool kbdms = false; |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index d1e6bcb59546..c1967ac1c07f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
@@ -1230,7 +1230,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) | |||
1230 | (sunzilog_reg.minor - 64) + con->index, con->index); | 1230 | (sunzilog_reg.minor - 64) + con->index, con->index); |
1231 | 1231 | ||
1232 | /* Get firmware console settings. */ | 1232 | /* Get firmware console settings. */ |
1233 | sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); | 1233 | sunserial_console_termios(con, up->port.dev->of_node); |
1234 | 1234 | ||
1235 | /* Firmware console speed is limited to 150-->38400 baud so | 1235 | /* Firmware console speed is limited to 150-->38400 baud so |
1236 | * this hackish cflag thing is OK. | 1236 | * this hackish cflag thing is OK. |
@@ -1399,7 +1399,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | |||
1399 | 1399 | ||
1400 | static int zilog_irq = -1; | 1400 | static int zilog_irq = -1; |
1401 | 1401 | ||
1402 | static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) | 1402 | static int __devinit zs_probe(struct platform_device *op, const struct of_device_id *match) |
1403 | { | 1403 | { |
1404 | static int kbm_inst, uart_inst; | 1404 | static int kbm_inst, uart_inst; |
1405 | int inst; | 1405 | int inst; |
@@ -1516,7 +1516,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up) | |||
1516 | uart_remove_one_port(&sunzilog_reg, &up->port); | 1516 | uart_remove_one_port(&sunzilog_reg, &up->port); |
1517 | } | 1517 | } |
1518 | 1518 | ||
1519 | static int __devexit zs_remove(struct of_device *op) | 1519 | static int __devexit zs_remove(struct platform_device *op) |
1520 | { | 1520 | { |
1521 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); | 1521 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); |
1522 | struct zilog_layout __iomem *regs; | 1522 | struct zilog_layout __iomem *regs; |
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index caf085d3a76a..9b03d7b3e456 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c | |||
@@ -584,7 +584,7 @@ static struct platform_driver ulite_platform_driver = { | |||
584 | */ | 584 | */ |
585 | #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) | 585 | #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) |
586 | static int __devinit | 586 | static int __devinit |
587 | ulite_of_probe(struct of_device *op, const struct of_device_id *match) | 587 | ulite_of_probe(struct platform_device *op, const struct of_device_id *match) |
588 | { | 588 | { |
589 | struct resource res; | 589 | struct resource res; |
590 | const unsigned int *id; | 590 | const unsigned int *id; |
@@ -605,7 +605,7 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match) | |||
605 | return ulite_assign(&op->dev, id ? *id : -1, res.start, irq); | 605 | return ulite_assign(&op->dev, id ? *id : -1, res.start, irq); |
606 | } | 606 | } |
607 | 607 | ||
608 | static int __devexit ulite_of_remove(struct of_device *op) | 608 | static int __devexit ulite_of_remove(struct platform_device *op) |
609 | { | 609 | { |
610 | return ulite_release(&op->dev); | 610 | return ulite_release(&op->dev); |
611 | } | 611 | } |
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 907b06f5c447..3f4848e2174a 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c | |||
@@ -1194,7 +1194,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) | |||
1194 | release_firmware(fw); | 1194 | release_firmware(fw); |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | static int ucc_uart_probe(struct of_device *ofdev, | 1197 | static int ucc_uart_probe(struct platform_device *ofdev, |
1198 | const struct of_device_id *match) | 1198 | const struct of_device_id *match) |
1199 | { | 1199 | { |
1200 | struct device_node *np = ofdev->dev.of_node; | 1200 | struct device_node *np = ofdev->dev.of_node; |
@@ -1462,7 +1462,7 @@ static int ucc_uart_probe(struct of_device *ofdev, | |||
1462 | return 0; | 1462 | return 0; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | static int ucc_uart_remove(struct of_device *ofdev) | 1465 | static int ucc_uart_remove(struct platform_device *ofdev) |
1466 | { | 1466 | { |
1467 | struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); | 1467 | struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); |
1468 | 1468 | ||
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 78bb5127abd0..08fc653a825c 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile | |||
@@ -1,9 +1,10 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the SuperH specific drivers. | 2 | # Makefile for the SuperH specific drivers. |
3 | # | 3 | # |
4 | obj-y := clk.o intc.o | ||
5 | |||
4 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 6 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
5 | obj-$(CONFIG_MAPLE) += maple/ | 7 | obj-$(CONFIG_MAPLE) += maple/ |
8 | |||
6 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o | 9 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o |
7 | obj-$(CONFIG_SUPERH) += clk.o | ||
8 | obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o | 10 | obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o |
9 | obj-y += intc.o | ||
diff --git a/drivers/sh/clk-cpg.c b/drivers/sh/clk-cpg.c index f5c80ba9ab1c..8c024b984ed8 100644 --- a/drivers/sh/clk-cpg.c +++ b/drivers/sh/clk-cpg.c | |||
@@ -68,6 +68,39 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) | |||
68 | return clk->freq_table[idx].frequency; | 68 | return clk->freq_table[idx].frequency; |
69 | } | 69 | } |
70 | 70 | ||
71 | static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) | ||
72 | { | ||
73 | struct clk_div_mult_table *table = &sh_clk_div6_table; | ||
74 | u32 value; | ||
75 | int ret, i; | ||
76 | |||
77 | if (!clk->parent_table || !clk->parent_num) | ||
78 | return -EINVAL; | ||
79 | |||
80 | /* Search the parent */ | ||
81 | for (i = 0; i < clk->parent_num; i++) | ||
82 | if (clk->parent_table[i] == parent) | ||
83 | break; | ||
84 | |||
85 | if (i == clk->parent_num) | ||
86 | return -ENODEV; | ||
87 | |||
88 | ret = clk_reparent(clk, parent); | ||
89 | if (ret < 0) | ||
90 | return ret; | ||
91 | |||
92 | value = __raw_readl(clk->enable_reg) & | ||
93 | ~(((1 << clk->src_width) - 1) << clk->src_shift); | ||
94 | |||
95 | __raw_writel(value | (i << clk->src_shift), clk->enable_reg); | ||
96 | |||
97 | /* Rebuild the frequency table */ | ||
98 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
99 | table, &clk->arch_flags); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
71 | static int sh_clk_div6_set_rate(struct clk *clk, | 104 | static int sh_clk_div6_set_rate(struct clk *clk, |
72 | unsigned long rate, int algo_id) | 105 | unsigned long rate, int algo_id) |
73 | { | 106 | { |
@@ -117,7 +150,17 @@ static struct clk_ops sh_clk_div6_clk_ops = { | |||
117 | .disable = sh_clk_div6_disable, | 150 | .disable = sh_clk_div6_disable, |
118 | }; | 151 | }; |
119 | 152 | ||
120 | int __init sh_clk_div6_register(struct clk *clks, int nr) | 153 | static struct clk_ops sh_clk_div6_reparent_clk_ops = { |
154 | .recalc = sh_clk_div6_recalc, | ||
155 | .round_rate = sh_clk_div_round_rate, | ||
156 | .set_rate = sh_clk_div6_set_rate, | ||
157 | .enable = sh_clk_div6_enable, | ||
158 | .disable = sh_clk_div6_disable, | ||
159 | .set_parent = sh_clk_div6_set_parent, | ||
160 | }; | ||
161 | |||
162 | static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, | ||
163 | struct clk_ops *ops) | ||
121 | { | 164 | { |
122 | struct clk *clkp; | 165 | struct clk *clkp; |
123 | void *freq_table; | 166 | void *freq_table; |
@@ -136,7 +179,7 @@ int __init sh_clk_div6_register(struct clk *clks, int nr) | |||
136 | for (k = 0; !ret && (k < nr); k++) { | 179 | for (k = 0; !ret && (k < nr); k++) { |
137 | clkp = clks + k; | 180 | clkp = clks + k; |
138 | 181 | ||
139 | clkp->ops = &sh_clk_div6_clk_ops; | 182 | clkp->ops = ops; |
140 | clkp->id = -1; | 183 | clkp->id = -1; |
141 | clkp->freq_table = freq_table + (k * freq_table_size); | 184 | clkp->freq_table = freq_table + (k * freq_table_size); |
142 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | 185 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; |
@@ -147,6 +190,17 @@ int __init sh_clk_div6_register(struct clk *clks, int nr) | |||
147 | return ret; | 190 | return ret; |
148 | } | 191 | } |
149 | 192 | ||
193 | int __init sh_clk_div6_register(struct clk *clks, int nr) | ||
194 | { | ||
195 | return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops); | ||
196 | } | ||
197 | |||
198 | int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) | ||
199 | { | ||
200 | return sh_clk_div6_register_ops(clks, nr, | ||
201 | &sh_clk_div6_reparent_clk_ops); | ||
202 | } | ||
203 | |||
150 | static unsigned long sh_clk_div4_recalc(struct clk *clk) | 204 | static unsigned long sh_clk_div4_recalc(struct clk *clk) |
151 | { | 205 | { |
152 | struct clk_div4_table *d4t = clk->priv; | 206 | struct clk_div4_table *d4t = clk->priv; |
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c index 10baac3f8ea5..cddbfceb324f 100644 --- a/drivers/spi/mpc512x_psc_spi.c +++ b/drivers/spi/mpc512x_psc_spi.c | |||
@@ -507,7 +507,7 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev) | |||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | static int __init mpc512x_psc_spi_of_probe(struct of_device *op, | 510 | static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, |
511 | const struct of_device_id *match) | 511 | const struct of_device_id *match) |
512 | { | 512 | { |
513 | const u32 *regaddr_p; | 513 | const u32 *regaddr_p; |
@@ -539,7 +539,7 @@ static int __init mpc512x_psc_spi_of_probe(struct of_device *op, | |||
539 | irq_of_parse_and_map(op->dev.of_node, 0), id); | 539 | irq_of_parse_and_map(op->dev.of_node, 0), id); |
540 | } | 540 | } |
541 | 541 | ||
542 | static int __exit mpc512x_psc_spi_of_remove(struct of_device *op) | 542 | static int __exit mpc512x_psc_spi_of_remove(struct platform_device *op) |
543 | { | 543 | { |
544 | return mpc512x_psc_spi_do_remove(&op->dev); | 544 | return mpc512x_psc_spi_do_remove(&op->dev); |
545 | } | 545 | } |
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 66d170147dcc..983fbbfce76e 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c | |||
@@ -465,7 +465,7 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev) | |||
465 | return 0; | 465 | return 0; |
466 | } | 466 | } |
467 | 467 | ||
468 | static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, | 468 | static int __init mpc52xx_psc_spi_of_probe(struct platform_device *op, |
469 | const struct of_device_id *match) | 469 | const struct of_device_id *match) |
470 | { | 470 | { |
471 | const u32 *regaddr_p; | 471 | const u32 *regaddr_p; |
@@ -495,7 +495,7 @@ static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, | |||
495 | irq_of_parse_and_map(op->dev.of_node, 0), id); | 495 | irq_of_parse_and_map(op->dev.of_node, 0), id); |
496 | } | 496 | } |
497 | 497 | ||
498 | static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) | 498 | static int __exit mpc52xx_psc_spi_of_remove(struct platform_device *op) |
499 | { | 499 | { |
500 | return mpc52xx_psc_spi_do_remove(&op->dev); | 500 | return mpc52xx_psc_spi_do_remove(&op->dev); |
501 | } | 501 | } |
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c index 56136ff00e01..ec9f0b1bf864 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/mpc52xx_spi.c | |||
@@ -390,7 +390,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m) | |||
390 | /* | 390 | /* |
391 | * OF Platform Bus Binding | 391 | * OF Platform Bus Binding |
392 | */ | 392 | */ |
393 | static int __devinit mpc52xx_spi_probe(struct of_device *op, | 393 | static int __devinit mpc52xx_spi_probe(struct platform_device *op, |
394 | const struct of_device_id *match) | 394 | const struct of_device_id *match) |
395 | { | 395 | { |
396 | struct spi_master *master; | 396 | struct spi_master *master; |
@@ -530,7 +530,7 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, | |||
530 | return rc; | 530 | return rc; |
531 | } | 531 | } |
532 | 532 | ||
533 | static int __devexit mpc52xx_spi_remove(struct of_device *op) | 533 | static int __devexit mpc52xx_spi_remove(struct platform_device *op) |
534 | { | 534 | { |
535 | struct spi_master *master = dev_get_drvdata(&op->dev); | 535 | struct spi_master *master = dev_get_drvdata(&op->dev); |
536 | struct mpc52xx_spi *ms = spi_master_get_devdata(master); | 536 | struct mpc52xx_spi *ms = spi_master_get_devdata(master); |
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index aad9ae1b9c69..d31b57f7baaf 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c | |||
@@ -1236,7 +1236,7 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev) | |||
1236 | return 0; | 1236 | return 0; |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | static int __devinit of_mpc8xxx_spi_probe(struct of_device *ofdev, | 1239 | static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, |
1240 | const struct of_device_id *ofid) | 1240 | const struct of_device_id *ofid) |
1241 | { | 1241 | { |
1242 | struct device *dev = &ofdev->dev; | 1242 | struct device *dev = &ofdev->dev; |
@@ -1308,7 +1308,7 @@ err_clk: | |||
1308 | return ret; | 1308 | return ret; |
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | static int __devexit of_mpc8xxx_spi_remove(struct of_device *ofdev) | 1311 | static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev) |
1312 | { | 1312 | { |
1313 | int ret; | 1313 | int ret; |
1314 | 1314 | ||
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c index 0f5fa7e2a550..80e172d3e72a 100644 --- a/drivers/spi/spi_ppc4xx.c +++ b/drivers/spi/spi_ppc4xx.c | |||
@@ -388,9 +388,9 @@ static void free_gpios(struct ppc4xx_spi *hw) | |||
388 | } | 388 | } |
389 | 389 | ||
390 | /* | 390 | /* |
391 | * of_device layer stuff... | 391 | * platform_device layer stuff... |
392 | */ | 392 | */ |
393 | static int __init spi_ppc4xx_of_probe(struct of_device *op, | 393 | static int __init spi_ppc4xx_of_probe(struct platform_device *op, |
394 | const struct of_device_id *match) | 394 | const struct of_device_id *match) |
395 | { | 395 | { |
396 | struct ppc4xx_spi *hw; | 396 | struct ppc4xx_spi *hw; |
@@ -565,7 +565,7 @@ free_master: | |||
565 | return ret; | 565 | return ret; |
566 | } | 566 | } |
567 | 567 | ||
568 | static int __exit spi_ppc4xx_of_remove(struct of_device *op) | 568 | static int __exit spi_ppc4xx_of_remove(struct platform_device *op) |
569 | { | 569 | { |
570 | struct spi_master *master = dev_get_drvdata(&op->dev); | 570 | struct spi_master *master = dev_get_drvdata(&op->dev); |
571 | struct ppc4xx_spi *hw = spi_master_get_devdata(master); | 571 | struct ppc4xx_spi *hw = spi_master_get_devdata(master); |
diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c index f53d3f6b9f61..b66c2dbf20a5 100644 --- a/drivers/spi/xilinx_spi_of.c +++ b/drivers/spi/xilinx_spi_of.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "xilinx_spi.h" | 38 | #include "xilinx_spi.h" |
39 | 39 | ||
40 | 40 | ||
41 | static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, | 41 | static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev, |
42 | const struct of_device_id *match) | 42 | const struct of_device_id *match) |
43 | { | 43 | { |
44 | struct spi_master *master; | 44 | struct spi_master *master; |
@@ -84,7 +84,7 @@ static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, | |||
84 | return 0; | 84 | return 0; |
85 | } | 85 | } |
86 | 86 | ||
87 | static int __devexit xilinx_spi_remove(struct of_device *ofdev) | 87 | static int __devexit xilinx_spi_remove(struct platform_device *ofdev) |
88 | { | 88 | { |
89 | xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); | 89 | xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); |
90 | dev_set_drvdata(&ofdev->dev, 0); | 90 | dev_set_drvdata(&ofdev->dev, 0); |
@@ -93,7 +93,7 @@ static int __devexit xilinx_spi_remove(struct of_device *ofdev) | |||
93 | return 0; | 93 | return 0; |
94 | } | 94 | } |
95 | 95 | ||
96 | static int __exit xilinx_spi_of_remove(struct of_device *op) | 96 | static int __exit xilinx_spi_of_remove(struct platform_device *op) |
97 | { | 97 | { |
98 | return xilinx_spi_remove(op); | 98 | return xilinx_spi_remove(op); |
99 | } | 99 | } |
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 49ab9fa9ffa7..ed7457bc24ea 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c | |||
@@ -61,7 +61,7 @@ static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | 63 | ||
64 | static char *ifname = "wlan%d"; | 64 | static char ifname[IFNAMSIZ] = "wlan%d"; |
65 | static int hwseqnum = 0; | 65 | static int hwseqnum = 0; |
66 | static int hwwep = 0; | 66 | static int hwwep = 0; |
67 | static int channels = 0x3fff; | 67 | static int channels = 0x3fff; |
@@ -72,7 +72,7 @@ MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); | |||
72 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards"); | 72 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards"); |
73 | 73 | ||
74 | 74 | ||
75 | module_param(ifname, charp, S_IRUGO|S_IWUSR); | 75 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
76 | module_param(hwseqnum, int, S_IRUGO|S_IWUSR); | 76 | module_param(hwseqnum, int, S_IRUGO|S_IWUSR); |
77 | module_param(hwwep, int, S_IRUGO|S_IWUSR); | 77 | module_param(hwwep, int, S_IRUGO|S_IWUSR); |
78 | module_param(channels, int, S_IRUGO|S_IWUSR); | 78 | module_param(channels, int, S_IRUGO|S_IWUSR); |
@@ -3609,7 +3609,7 @@ static int __devinit rtl8180_pci_probe(struct pci_dev *pdev, | |||
3609 | 3609 | ||
3610 | if (dev_alloc_name(dev, ifname) < 0) { | 3610 | if (dev_alloc_name(dev, ifname) < 0) { |
3611 | DMESG("Oops: devname already taken! Trying wlan%%d...\n"); | 3611 | DMESG("Oops: devname already taken! Trying wlan%%d...\n"); |
3612 | ifname = "wlan%d"; | 3612 | strcpy(ifname, "wlan%d"); |
3613 | dev_alloc_name(dev, ifname); | 3613 | dev_alloc_name(dev, ifname); |
3614 | } | 3614 | } |
3615 | 3615 | ||
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c index 4cd071adf84b..17a806f9ee77 100644 --- a/drivers/staging/rtl8192e/r8192E_core.c +++ b/drivers/staging/rtl8192e/r8192E_core.c | |||
@@ -112,7 +112,7 @@ static const struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = { | |||
112 | {} | 112 | {} |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static char* ifname = "wlan%d"; | 115 | static char ifname[IFNAMSIZ] = "wlan%d"; |
116 | static int hwwep = 1; //default use hw. set 0 to use software security | 116 | static int hwwep = 1; //default use hw. set 0 to use software security |
117 | static int channels = 0x3fff; | 117 | static int channels = 0x3fff; |
118 | 118 | ||
@@ -123,7 +123,7 @@ MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl); | |||
123 | MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); | 123 | MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); |
124 | 124 | ||
125 | 125 | ||
126 | module_param(ifname, charp, S_IRUGO|S_IWUSR ); | 126 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
127 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); | 127 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); |
128 | module_param(hwwep,int, S_IRUGO|S_IWUSR); | 128 | module_param(hwwep,int, S_IRUGO|S_IWUSR); |
129 | module_param(channels,int, S_IRUGO|S_IWUSR); | 129 | module_param(channels,int, S_IRUGO|S_IWUSR); |
@@ -6446,7 +6446,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, | |||
6446 | 6446 | ||
6447 | if (dev_alloc_name(dev, ifname) < 0){ | 6447 | if (dev_alloc_name(dev, ifname) < 0){ |
6448 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); | 6448 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); |
6449 | ifname = "wlan%d"; | 6449 | strcpy(ifname, "wlan%d"); |
6450 | dev_alloc_name(dev, ifname); | 6450 | dev_alloc_name(dev, ifname); |
6451 | } | 6451 | } |
6452 | 6452 | ||
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 6970c97713d8..df5b52baf893 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c | |||
@@ -144,13 +144,13 @@ MODULE_VERSION("V 1.1"); | |||
144 | MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl); | 144 | MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl); |
145 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards"); | 145 | MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards"); |
146 | 146 | ||
147 | static char* ifname = "wlan%d"; | 147 | static char ifname[IFNAMSIZ] = "wlan%d"; |
148 | static int hwwep = 1; //default use hw. set 0 to use software security | 148 | static int hwwep = 1; //default use hw. set 0 to use software security |
149 | static int channels = 0x3fff; | 149 | static int channels = 0x3fff; |
150 | 150 | ||
151 | 151 | ||
152 | 152 | ||
153 | module_param(ifname, charp, S_IRUGO|S_IWUSR ); | 153 | module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); |
154 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); | 154 | //module_param(hwseqnum,int, S_IRUGO|S_IWUSR); |
155 | module_param(hwwep,int, S_IRUGO|S_IWUSR); | 155 | module_param(hwwep,int, S_IRUGO|S_IWUSR); |
156 | module_param(channels,int, S_IRUGO|S_IWUSR); | 156 | module_param(channels,int, S_IRUGO|S_IWUSR); |
@@ -7406,7 +7406,7 @@ static int __devinit rtl8192_usb_probe(struct usb_interface *intf, | |||
7406 | 7406 | ||
7407 | if (dev_alloc_name(dev, ifname) < 0){ | 7407 | if (dev_alloc_name(dev, ifname) < 0){ |
7408 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); | 7408 | RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); |
7409 | ifname = "wlan%d"; | 7409 | strcpy(ifname, "wlan%d"); |
7410 | dev_alloc_name(dev, ifname); | 7410 | dev_alloc_name(dev, ifname); |
7411 | } | 7411 | } |
7412 | 7412 | ||
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 5b3f555e01c9..ea071a5b6eee 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -1577,6 +1577,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | |||
1577 | char file_arr[] = "CMVxy.bin"; | 1577 | char file_arr[] = "CMVxy.bin"; |
1578 | char *file; | 1578 | char *file; |
1579 | 1579 | ||
1580 | kparam_block_sysfs_write(cmv_file); | ||
1580 | /* set proper name corresponding modem version and line type */ | 1581 | /* set proper name corresponding modem version and line type */ |
1581 | if (cmv_file[sc->modem_index] == NULL) { | 1582 | if (cmv_file[sc->modem_index] == NULL) { |
1582 | if (UEA_CHIP_VERSION(sc) == ADI930) | 1583 | if (UEA_CHIP_VERSION(sc) == ADI930) |
@@ -1595,6 +1596,7 @@ static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | |||
1595 | strlcat(cmv_name, file, UEA_FW_NAME_MAX); | 1596 | strlcat(cmv_name, file, UEA_FW_NAME_MAX); |
1596 | if (ver == 2) | 1597 | if (ver == 2) |
1597 | strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX); | 1598 | strlcat(cmv_name, ".v2", UEA_FW_NAME_MAX); |
1599 | kparam_unblock_sysfs_write(cmv_file); | ||
1598 | } | 1600 | } |
1599 | 1601 | ||
1600 | static int request_cmvs_old(struct uea_softc *sc, | 1602 | static int request_cmvs_old(struct uea_softc *sc, |
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 9648b75f0283..a5ea2c1d8c93 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c | |||
@@ -2398,7 +2398,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
2398 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | 2398 | EXPORT_SYMBOL(usb_gadget_unregister_driver); |
2399 | 2399 | ||
2400 | /* udc structure's alloc and setup, include ep-param alloc */ | 2400 | /* udc structure's alloc and setup, include ep-param alloc */ |
2401 | static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev) | 2401 | static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev) |
2402 | { | 2402 | { |
2403 | struct qe_udc *udc; | 2403 | struct qe_udc *udc; |
2404 | struct device_node *np = ofdev->dev.of_node; | 2404 | struct device_node *np = ofdev->dev.of_node; |
@@ -2523,7 +2523,7 @@ static void qe_udc_release(struct device *dev) | |||
2523 | } | 2523 | } |
2524 | 2524 | ||
2525 | /* Driver probe functions */ | 2525 | /* Driver probe functions */ |
2526 | static int __devinit qe_udc_probe(struct of_device *ofdev, | 2526 | static int __devinit qe_udc_probe(struct platform_device *ofdev, |
2527 | const struct of_device_id *match) | 2527 | const struct of_device_id *match) |
2528 | { | 2528 | { |
2529 | struct device_node *np = ofdev->dev.of_node; | 2529 | struct device_node *np = ofdev->dev.of_node; |
@@ -2679,18 +2679,18 @@ err1: | |||
2679 | } | 2679 | } |
2680 | 2680 | ||
2681 | #ifdef CONFIG_PM | 2681 | #ifdef CONFIG_PM |
2682 | static int qe_udc_suspend(struct of_device *dev, pm_message_t state) | 2682 | static int qe_udc_suspend(struct platform_device *dev, pm_message_t state) |
2683 | { | 2683 | { |
2684 | return -ENOTSUPP; | 2684 | return -ENOTSUPP; |
2685 | } | 2685 | } |
2686 | 2686 | ||
2687 | static int qe_udc_resume(struct of_device *dev) | 2687 | static int qe_udc_resume(struct platform_device *dev) |
2688 | { | 2688 | { |
2689 | return -ENOTSUPP; | 2689 | return -ENOTSUPP; |
2690 | } | 2690 | } |
2691 | #endif | 2691 | #endif |
2692 | 2692 | ||
2693 | static int __devexit qe_udc_remove(struct of_device *ofdev) | 2693 | static int __devexit qe_udc_remove(struct platform_device *ofdev) |
2694 | { | 2694 | { |
2695 | struct qe_ep *ep; | 2695 | struct qe_ep *ep; |
2696 | unsigned int size; | 2696 | unsigned int size; |
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 5aec92866ab3..335ee699fd85 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c | |||
@@ -106,7 +106,7 @@ ppc44x_enable_bmt(struct device_node *dn) | |||
106 | 106 | ||
107 | 107 | ||
108 | static int __devinit | 108 | static int __devinit |
109 | ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | 109 | ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) |
110 | { | 110 | { |
111 | struct device_node *dn = op->dev.of_node; | 111 | struct device_node *dn = op->dev.of_node; |
112 | struct usb_hcd *hcd; | 112 | struct usb_hcd *hcd; |
@@ -210,7 +210,7 @@ err_rmr: | |||
210 | } | 210 | } |
211 | 211 | ||
212 | 212 | ||
213 | static int ehci_hcd_ppc_of_remove(struct of_device *op) | 213 | static int ehci_hcd_ppc_of_remove(struct platform_device *op) |
214 | { | 214 | { |
215 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 215 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
216 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 216 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
@@ -253,7 +253,7 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) | |||
253 | } | 253 | } |
254 | 254 | ||
255 | 255 | ||
256 | static int ehci_hcd_ppc_of_shutdown(struct of_device *op) | 256 | static int ehci_hcd_ppc_of_shutdown(struct platform_device *op) |
257 | { | 257 | { |
258 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 258 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
259 | 259 | ||
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 4899f451add9..6c8076ad821d 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c | |||
@@ -140,7 +140,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { | |||
140 | 140 | ||
141 | /** | 141 | /** |
142 | * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller | 142 | * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller |
143 | * @op: pointer to the of_device to which the host controller bound | 143 | * @op: pointer to the platform_device bound to the host controller |
144 | * @match: pointer to of_device_id structure, not used | 144 | * @match: pointer to of_device_id structure, not used |
145 | * | 145 | * |
146 | * This function requests resources and sets up appropriate properties for the | 146 | * This function requests resources and sets up appropriate properties for the |
@@ -149,7 +149,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { | |||
149 | * entry, and sets an appropriate value for hcd->has_tt. | 149 | * entry, and sets an appropriate value for hcd->has_tt. |
150 | */ | 150 | */ |
151 | static int __devinit | 151 | static int __devinit |
152 | ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) | 152 | ehci_hcd_xilinx_of_probe(struct platform_device *op, const struct of_device_id *match) |
153 | { | 153 | { |
154 | struct device_node *dn = op->dev.of_node; | 154 | struct device_node *dn = op->dev.of_node; |
155 | struct usb_hcd *hcd; | 155 | struct usb_hcd *hcd; |
@@ -242,12 +242,12 @@ err_rmr: | |||
242 | 242 | ||
243 | /** | 243 | /** |
244 | * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources | 244 | * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources |
245 | * @op: pointer to of_device structure that is to be removed | 245 | * @op: pointer to platform_device structure that is to be removed |
246 | * | 246 | * |
247 | * Remove the hcd structure, and release resources that has been requested | 247 | * Remove the hcd structure, and release resources that has been requested |
248 | * during probe. | 248 | * during probe. |
249 | */ | 249 | */ |
250 | static int ehci_hcd_xilinx_of_remove(struct of_device *op) | 250 | static int ehci_hcd_xilinx_of_remove(struct platform_device *op) |
251 | { | 251 | { |
252 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 252 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
253 | dev_set_drvdata(&op->dev, NULL); | 253 | dev_set_drvdata(&op->dev, NULL); |
@@ -266,11 +266,11 @@ static int ehci_hcd_xilinx_of_remove(struct of_device *op) | |||
266 | 266 | ||
267 | /** | 267 | /** |
268 | * ehci_hcd_xilinx_of_shutdown - shutdown the hcd | 268 | * ehci_hcd_xilinx_of_shutdown - shutdown the hcd |
269 | * @op: pointer to of_device structure that is to be removed | 269 | * @op: pointer to platform_device structure that is to be removed |
270 | * | 270 | * |
271 | * Properly shutdown the hcd, call driver's shutdown routine. | 271 | * Properly shutdown the hcd, call driver's shutdown routine. |
272 | */ | 272 | */ |
273 | static int ehci_hcd_xilinx_of_shutdown(struct of_device *op) | 273 | static int ehci_hcd_xilinx_of_shutdown(struct platform_device *op) |
274 | { | 274 | { |
275 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 275 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
276 | 276 | ||
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index c7c8392a88b9..20092a27a1e8 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c | |||
@@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = { | |||
561 | .hub_control = fhci_hub_control, | 561 | .hub_control = fhci_hub_control, |
562 | }; | 562 | }; |
563 | 563 | ||
564 | static int __devinit of_fhci_probe(struct of_device *ofdev, | 564 | static int __devinit of_fhci_probe(struct platform_device *ofdev, |
565 | const struct of_device_id *ofid) | 565 | const struct of_device_id *ofid) |
566 | { | 566 | { |
567 | struct device *dev = &ofdev->dev; | 567 | struct device *dev = &ofdev->dev; |
@@ -801,7 +801,7 @@ static int __devexit fhci_remove(struct device *dev) | |||
801 | return 0; | 801 | return 0; |
802 | } | 802 | } |
803 | 803 | ||
804 | static int __devexit of_fhci_remove(struct of_device *ofdev) | 804 | static int __devexit of_fhci_remove(struct platform_device *ofdev) |
805 | { | 805 | { |
806 | return fhci_remove(&ofdev->dev); | 806 | return fhci_remove(&ofdev->dev); |
807 | } | 807 | } |
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index ec85d0c3cc3e..3b28dbfca058 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #ifdef CONFIG_PPC_OF | 29 | #ifdef CONFIG_PPC_OF |
30 | static int of_isp1760_probe(struct of_device *dev, | 30 | static int of_isp1760_probe(struct platform_device *dev, |
31 | const struct of_device_id *match) | 31 | const struct of_device_id *match) |
32 | { | 32 | { |
33 | struct usb_hcd *hcd; | 33 | struct usb_hcd *hcd; |
@@ -95,7 +95,7 @@ release_reg: | |||
95 | return ret; | 95 | return ret; |
96 | } | 96 | } |
97 | 97 | ||
98 | static int of_isp1760_remove(struct of_device *dev) | 98 | static int of_isp1760_remove(struct platform_device *dev) |
99 | { | 99 | { |
100 | struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); | 100 | struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); |
101 | 101 | ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index cd74bbdd007c..653d6a60edb5 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c | |||
@@ -329,7 +329,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) | |||
329 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); | 329 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); |
330 | strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); | 330 | strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); |
331 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, | 331 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, |
332 | normal_i2c); | 332 | normal_i2c, NULL); |
333 | i2c_put_adapter(i2c_adap); | 333 | i2c_put_adapter(i2c_adap); |
334 | if (!isp1301_i2c_client) { | 334 | if (!isp1301_i2c_client) { |
335 | err("failed to connect I2C to ISP1301 USB Transceiver"); | 335 | err("failed to connect I2C to ISP1301 USB Transceiver"); |
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index df165917412a..b2c2dbf08766 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c | |||
@@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { | |||
81 | 81 | ||
82 | 82 | ||
83 | static int __devinit | 83 | static int __devinit |
84 | ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | 84 | ohci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) |
85 | { | 85 | { |
86 | struct device_node *dn = op->dev.of_node; | 86 | struct device_node *dn = op->dev.of_node; |
87 | struct usb_hcd *hcd; | 87 | struct usb_hcd *hcd; |
@@ -183,7 +183,7 @@ err_rmr: | |||
183 | return rv; | 183 | return rv; |
184 | } | 184 | } |
185 | 185 | ||
186 | static int ohci_hcd_ppc_of_remove(struct of_device *op) | 186 | static int ohci_hcd_ppc_of_remove(struct platform_device *op) |
187 | { | 187 | { |
188 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 188 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
189 | dev_set_drvdata(&op->dev, NULL); | 189 | dev_set_drvdata(&op->dev, NULL); |
@@ -201,7 +201,7 @@ static int ohci_hcd_ppc_of_remove(struct of_device *op) | |||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | static int ohci_hcd_ppc_of_shutdown(struct of_device *op) | 204 | static int ohci_hcd_ppc_of_shutdown(struct platform_device *op) |
205 | { | 205 | { |
206 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 206 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
207 | 207 | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index a9ca72f301bf..8b31fdfefc98 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1896,6 +1896,13 @@ config FB_W100 | |||
1896 | 1896 | ||
1897 | If unsure, say N. | 1897 | If unsure, say N. |
1898 | 1898 | ||
1899 | config SH_MIPI_DSI | ||
1900 | tristate | ||
1901 | depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK | ||
1902 | |||
1903 | config SH_LCD_MIPI_DSI | ||
1904 | bool | ||
1905 | |||
1899 | config FB_SH_MOBILE_LCDC | 1906 | config FB_SH_MOBILE_LCDC |
1900 | tristate "SuperH Mobile LCDC framebuffer support" | 1907 | tristate "SuperH Mobile LCDC framebuffer support" |
1901 | depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK | 1908 | depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK |
@@ -1904,9 +1911,17 @@ config FB_SH_MOBILE_LCDC | |||
1904 | select FB_SYS_IMAGEBLIT | 1911 | select FB_SYS_IMAGEBLIT |
1905 | select FB_SYS_FOPS | 1912 | select FB_SYS_FOPS |
1906 | select FB_DEFERRED_IO | 1913 | select FB_DEFERRED_IO |
1914 | select SH_MIPI_DSI if SH_LCD_MIPI_DSI | ||
1907 | ---help--- | 1915 | ---help--- |
1908 | Frame buffer driver for the on-chip SH-Mobile LCD controller. | 1916 | Frame buffer driver for the on-chip SH-Mobile LCD controller. |
1909 | 1917 | ||
1918 | config FB_SH_MOBILE_HDMI | ||
1919 | tristate "SuperH Mobile HDMI controller support" | ||
1920 | depends on FB_SH_MOBILE_LCDC | ||
1921 | select FB_MODE_HELPERS | ||
1922 | ---help--- | ||
1923 | Driver for the on-chip SH-Mobile HDMI controller. | ||
1924 | |||
1910 | config FB_TMIO | 1925 | config FB_TMIO |
1911 | tristate "Toshiba Mobile IO FrameBuffer support" | 1926 | tristate "Toshiba Mobile IO FrameBuffer support" |
1912 | depends on FB && MFD_CORE | 1927 | depends on FB && MFD_CORE |
@@ -1931,7 +1946,7 @@ config FB_TMIO_ACCELL | |||
1931 | 1946 | ||
1932 | config FB_S3C | 1947 | config FB_S3C |
1933 | tristate "Samsung S3C framebuffer support" | 1948 | tristate "Samsung S3C framebuffer support" |
1934 | depends on FB && ARCH_S3C64XX | 1949 | depends on FB && S3C_DEV_FB |
1935 | select FB_CFB_FILLRECT | 1950 | select FB_CFB_FILLRECT |
1936 | select FB_CFB_COPYAREA | 1951 | select FB_CFB_COPYAREA |
1937 | select FB_CFB_IMAGEBLIT | 1952 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index f56a9cae2157..485e8ed1318c 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -123,6 +123,8 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o | |||
123 | obj-$(CONFIG_FB_PS3) += ps3fb.o | 123 | obj-$(CONFIG_FB_PS3) += ps3fb.o |
124 | obj-$(CONFIG_FB_SM501) += sm501fb.o | 124 | obj-$(CONFIG_FB_SM501) += sm501fb.o |
125 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o | 125 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o |
126 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o | ||
127 | obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o | ||
126 | obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o | 128 | obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o |
127 | obj-$(CONFIG_FB_OMAP) += omap/ | 129 | obj-$(CONFIG_FB_OMAP) += omap/ |
128 | obj-y += omap2/ | 130 | obj-y += omap2/ |
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index c7796637bafd..4dc13467281d 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
@@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par, | |||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) | 276 | static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match) |
277 | { | 277 | { |
278 | struct device_node *dp = op->dev.of_node; | 278 | struct device_node *dp = op->dev.of_node; |
279 | struct fb_info *info; | 279 | struct fb_info *info; |
@@ -350,7 +350,7 @@ out_err: | |||
350 | return err; | 350 | return err; |
351 | } | 351 | } |
352 | 352 | ||
353 | static int __devexit bw2_remove(struct of_device *op) | 353 | static int __devexit bw2_remove(struct platform_device *op) |
354 | { | 354 | { |
355 | struct fb_info *info = dev_get_drvdata(&op->dev); | 355 | struct fb_info *info = dev_get_drvdata(&op->dev); |
356 | struct bw2_par *par = info->par; | 356 | struct bw2_par *par = info->par; |
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index d09fde8beb69..24249535ac86 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
@@ -446,7 +446,7 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = { | |||
446 | { .size = 0 } | 446 | { .size = 0 } |
447 | }; | 447 | }; |
448 | 448 | ||
449 | static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, | 449 | static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info, |
450 | struct cg14_par *par) | 450 | struct cg14_par *par) |
451 | { | 451 | { |
452 | if (par->regs) | 452 | if (par->regs) |
@@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, | |||
463 | info->screen_base, info->fix.smem_len); | 463 | info->screen_base, info->fix.smem_len); |
464 | } | 464 | } |
465 | 465 | ||
466 | static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) | 466 | static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match) |
467 | { | 467 | { |
468 | struct device_node *dp = op->dev.of_node; | 468 | struct device_node *dp = op->dev.of_node; |
469 | struct fb_info *info; | 469 | struct fb_info *info; |
@@ -570,7 +570,7 @@ out_err: | |||
570 | return err; | 570 | return err; |
571 | } | 571 | } |
572 | 572 | ||
573 | static int __devexit cg14_remove(struct of_device *op) | 573 | static int __devexit cg14_remove(struct platform_device *op) |
574 | { | 574 | { |
575 | struct fb_info *info = dev_get_drvdata(&op->dev); | 575 | struct fb_info *info = dev_get_drvdata(&op->dev); |
576 | struct cg14_par *par = info->par; | 576 | struct cg14_par *par = info->par; |
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 64aa29809fb9..09c0c3c42482 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c | |||
@@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par) | |||
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
348 | 348 | ||
349 | static int __devinit cg3_probe(struct of_device *op, | 349 | static int __devinit cg3_probe(struct platform_device *op, |
350 | const struct of_device_id *match) | 350 | const struct of_device_id *match) |
351 | { | 351 | { |
352 | struct device_node *dp = op->dev.of_node; | 352 | struct device_node *dp = op->dev.of_node; |
@@ -433,7 +433,7 @@ out_err: | |||
433 | return err; | 433 | return err; |
434 | } | 434 | } |
435 | 435 | ||
436 | static int __devexit cg3_remove(struct of_device *op) | 436 | static int __devexit cg3_remove(struct platform_device *op) |
437 | { | 437 | { |
438 | struct fb_info *info = dev_get_drvdata(&op->dev); | 438 | struct fb_info *info = dev_get_drvdata(&op->dev); |
439 | struct cg3_par *par = info->par; | 439 | struct cg3_par *par = info->par; |
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 2389a719dcc7..2b5a97058b08 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
@@ -718,7 +718,7 @@ static void __devinit cg6_chip_init(struct fb_info *info) | |||
718 | sbus_writel(info->var.yres - 1, &fbc->clipmaxy); | 718 | sbus_writel(info->var.yres - 1, &fbc->clipmaxy); |
719 | } | 719 | } |
720 | 720 | ||
721 | static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, | 721 | static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info, |
722 | struct cg6_par *par) | 722 | struct cg6_par *par) |
723 | { | 723 | { |
724 | if (par->fbc) | 724 | if (par->fbc) |
@@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, | |||
737 | info->fix.smem_len); | 737 | info->fix.smem_len); |
738 | } | 738 | } |
739 | 739 | ||
740 | static int __devinit cg6_probe(struct of_device *op, | 740 | static int __devinit cg6_probe(struct platform_device *op, |
741 | const struct of_device_id *match) | 741 | const struct of_device_id *match) |
742 | { | 742 | { |
743 | struct device_node *dp = op->dev.of_node; | 743 | struct device_node *dp = op->dev.of_node; |
@@ -827,7 +827,7 @@ out_err: | |||
827 | return err; | 827 | return err; |
828 | } | 828 | } |
829 | 829 | ||
830 | static int __devexit cg6_remove(struct of_device *op) | 830 | static int __devexit cg6_remove(struct platform_device *op) |
831 | { | 831 | { |
832 | struct fb_info *info = dev_get_drvdata(&op->dev); | 832 | struct fb_info *info = dev_get_drvdata(&op->dev); |
833 | struct cg6_par *par = info->par; | 833 | struct cg6_par *par = info->par; |
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index af88651b0735..28b1a834906b 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c | |||
@@ -22,7 +22,7 @@ | |||
22 | /* | 22 | /* |
23 | * Accelerated handlers. | 23 | * Accelerated handlers. |
24 | */ | 24 | */ |
25 | static inline void update_attr(u8 *dst, u8 *src, int attribute, | 25 | static void update_attr(u8 *dst, u8 *src, int attribute, |
26 | struct vc_data *vc) | 26 | struct vc_data *vc) |
27 | { | 27 | { |
28 | int i, offset = (vc->vc_font.height < 10) ? 1 : 2; | 28 | int i, offset = (vc->vc_font.height < 10) ? 1 : 2; |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 26bf7cbfecc2..84f842331dfa 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -287,7 +287,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) | |||
287 | !vt_force_oops_output(vc); | 287 | !vt_force_oops_output(vc); |
288 | } | 288 | } |
289 | 289 | ||
290 | static inline int get_color(struct vc_data *vc, struct fb_info *info, | 290 | static int get_color(struct vc_data *vc, struct fb_info *info, |
291 | u16 c, int is_fg) | 291 | u16 c, int is_fg) |
292 | { | 292 | { |
293 | int depth = fb_get_color_depth(&info->var, &info->fix); | 293 | int depth = fb_get_color_depth(&info->var, &info->fix); |
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index d135671d9961..41b32ae23dac 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * Rotation 270 degrees | 22 | * Rotation 270 degrees |
23 | */ | 23 | */ |
24 | 24 | ||
25 | static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, | 25 | static void ccw_update_attr(u8 *dst, u8 *src, int attribute, |
26 | struct vc_data *vc) | 26 | struct vc_data *vc) |
27 | { | 27 | { |
28 | int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; | 28 | int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; |
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index 126110f8454f..6a737827beb1 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * Rotation 90 degrees | 22 | * Rotation 90 degrees |
23 | */ | 23 | */ |
24 | 24 | ||
25 | static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, | 25 | static void cw_update_attr(u8 *dst, u8 *src, int attribute, |
26 | struct vc_data *vc) | 26 | struct vc_data *vc) |
27 | { | 27 | { |
28 | int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; | 28 | int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; |
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 93a3e7381b50..ff0872c0498b 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * Rotation 180 degrees | 22 | * Rotation 180 degrees |
23 | */ | 23 | */ |
24 | 24 | ||
25 | static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, | 25 | static void ud_update_attr(u8 *dst, u8 *src, int attribute, |
26 | struct vc_data *vc) | 26 | struct vc_data *vc) |
27 | { | 27 | { |
28 | int i, offset = (vc->vc_font.height < 10) ? 1 : 2; | 28 | int i, offset = (vc->vc_font.height < 10) ? 1 : 2; |
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 4a56f46af40a..815f84b07933 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | #include <video/vga.h> | 17 | #include <video/vga.h> |
18 | 18 | ||
19 | static struct fb_var_screeninfo efifb_defined __initdata = { | 19 | static struct fb_var_screeninfo efifb_defined __devinitdata = { |
20 | .activate = FB_ACTIVATE_NOW, | 20 | .activate = FB_ACTIVATE_NOW, |
21 | .height = -1, | 21 | .height = -1, |
22 | .width = -1, | 22 | .width = -1, |
@@ -27,7 +27,7 @@ static struct fb_var_screeninfo efifb_defined __initdata = { | |||
27 | .vmode = FB_VMODE_NONINTERLACED, | 27 | .vmode = FB_VMODE_NONINTERLACED, |
28 | }; | 28 | }; |
29 | 29 | ||
30 | static struct fb_fix_screeninfo efifb_fix __initdata = { | 30 | static struct fb_fix_screeninfo efifb_fix __devinitdata = { |
31 | .id = "EFI VGA", | 31 | .id = "EFI VGA", |
32 | .type = FB_TYPE_PACKED_PIXELS, | 32 | .type = FB_TYPE_PACKED_PIXELS, |
33 | .accel = FB_ACCEL_NONE, | 33 | .accel = FB_ACCEL_NONE, |
@@ -59,7 +59,7 @@ static struct efifb_dmi_info { | |||
59 | int stride; | 59 | int stride; |
60 | int width; | 60 | int width; |
61 | int height; | 61 | int height; |
62 | } dmi_list[] = { | 62 | } dmi_list[] __initdata = { |
63 | [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, | 63 | [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, |
64 | [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ | 64 | [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ |
65 | [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, | 65 | [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, |
@@ -83,7 +83,7 @@ static int set_system(const struct dmi_system_id *id); | |||
83 | DMI_MATCH(DMI_PRODUCT_NAME, name) }, \ | 83 | DMI_MATCH(DMI_PRODUCT_NAME, name) }, \ |
84 | &dmi_list[enumid] } | 84 | &dmi_list[enumid] } |
85 | 85 | ||
86 | static struct dmi_system_id __initdata dmi_system_table[] = { | 86 | static const struct dmi_system_id dmi_system_table[] __initconst = { |
87 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17), | 87 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17), |
88 | /* At least one of these two will be right; maybe both? */ | 88 | /* At least one of these two will be right; maybe both? */ |
89 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20), | 89 | EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20), |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 731fce64df9d..b06647517c0e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1362,6 +1362,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) | |||
1362 | vma->vm_pgoff = off >> PAGE_SHIFT; | 1362 | vma->vm_pgoff = off >> PAGE_SHIFT; |
1363 | /* This is an IO map - tell maydump to skip this VMA */ | 1363 | /* This is an IO map - tell maydump to skip this VMA */ |
1364 | vma->vm_flags |= VM_IO | VM_RESERVED; | 1364 | vma->vm_flags |= VM_IO | VM_RESERVED; |
1365 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | ||
1365 | fb_pgprotect(file, vma, off); | 1366 | fb_pgprotect(file, vma, off); |
1366 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | 1367 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, |
1367 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 1368 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) |
@@ -1786,7 +1787,7 @@ static int ofonly __read_mostly; | |||
1786 | int fb_get_options(char *name, char **option) | 1787 | int fb_get_options(char *name, char **option) |
1787 | { | 1788 | { |
1788 | char *opt, *options = NULL; | 1789 | char *opt, *options = NULL; |
1789 | int opt_len, retval = 0; | 1790 | int retval = 0; |
1790 | int name_len = strlen(name), i; | 1791 | int name_len = strlen(name), i; |
1791 | 1792 | ||
1792 | if (name_len && ofonly && strncmp(name, "offb", 4)) | 1793 | if (name_len && ofonly && strncmp(name, "offb", 4)) |
@@ -1796,8 +1797,7 @@ int fb_get_options(char *name, char **option) | |||
1796 | for (i = 0; i < FB_MAX; i++) { | 1797 | for (i = 0; i < FB_MAX; i++) { |
1797 | if (video_options[i] == NULL) | 1798 | if (video_options[i] == NULL) |
1798 | continue; | 1799 | continue; |
1799 | opt_len = strlen(video_options[i]); | 1800 | if (!video_options[i][0]) |
1800 | if (!opt_len) | ||
1801 | continue; | 1801 | continue; |
1802 | opt = video_options[i]; | 1802 | opt = video_options[i]; |
1803 | if (!strncmp(name, opt, name_len) && | 1803 | if (!strncmp(name, opt, name_len) && |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index f6ecfab296d3..6739b2af3bc0 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
@@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info) | |||
893 | info->fix.accel = FB_ACCEL_SUN_CREATOR; | 893 | info->fix.accel = FB_ACCEL_SUN_CREATOR; |
894 | } | 894 | } |
895 | 895 | ||
896 | static int __devinit ffb_probe(struct of_device *op, | 896 | static int __devinit ffb_probe(struct platform_device *op, |
897 | const struct of_device_id *match) | 897 | const struct of_device_id *match) |
898 | { | 898 | { |
899 | struct device_node *dp = op->dev.of_node; | 899 | struct device_node *dp = op->dev.of_node; |
@@ -1023,7 +1023,7 @@ out_err: | |||
1023 | return err; | 1023 | return err; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static int __devexit ffb_remove(struct of_device *op) | 1026 | static int __devexit ffb_remove(struct platform_device *op) |
1027 | { | 1027 | { |
1028 | struct fb_info *info = dev_get_drvdata(&op->dev); | 1028 | struct fb_info *info = dev_get_drvdata(&op->dev); |
1029 | struct ffb_par *par = info->par; | 1029 | struct ffb_par *par = info->par; |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index e38ad2224540..8bbbf08fa3ce 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -1393,7 +1393,7 @@ static void free_irq_local(int irq) | |||
1393 | * Power management hooks. Note that we won't be called from IRQ context, | 1393 | * Power management hooks. Note that we won't be called from IRQ context, |
1394 | * unlike the blank functions above, so we may sleep. | 1394 | * unlike the blank functions above, so we may sleep. |
1395 | */ | 1395 | */ |
1396 | static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) | 1396 | static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state) |
1397 | { | 1397 | { |
1398 | struct fsl_diu_data *machine_data; | 1398 | struct fsl_diu_data *machine_data; |
1399 | 1399 | ||
@@ -1403,7 +1403,7 @@ static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) | |||
1403 | return 0; | 1403 | return 0; |
1404 | } | 1404 | } |
1405 | 1405 | ||
1406 | static int fsl_diu_resume(struct of_device *ofdev) | 1406 | static int fsl_diu_resume(struct platform_device *ofdev) |
1407 | { | 1407 | { |
1408 | struct fsl_diu_data *machine_data; | 1408 | struct fsl_diu_data *machine_data; |
1409 | 1409 | ||
@@ -1487,7 +1487,7 @@ static ssize_t show_monitor(struct device *device, | |||
1487 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); | 1487 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); |
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | static int __devinit fsl_diu_probe(struct of_device *ofdev, | 1490 | static int __devinit fsl_diu_probe(struct platform_device *ofdev, |
1491 | const struct of_device_id *match) | 1491 | const struct of_device_id *match) |
1492 | { | 1492 | { |
1493 | struct device_node *np = ofdev->dev.of_node; | 1493 | struct device_node *np = ofdev->dev.of_node; |
@@ -1667,7 +1667,7 @@ error2: | |||
1667 | } | 1667 | } |
1668 | 1668 | ||
1669 | 1669 | ||
1670 | static int fsl_diu_remove(struct of_device *ofdev) | 1670 | static int fsl_diu_remove(struct platform_device *ofdev) |
1671 | { | 1671 | { |
1672 | struct fsl_diu_data *machine_data; | 1672 | struct fsl_diu_data *machine_data; |
1673 | int i; | 1673 | int i; |
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index 15d200109446..d885c770eb84 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c | |||
@@ -368,7 +368,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par) | |||
368 | return 1; | 368 | return 1; |
369 | } | 369 | } |
370 | 370 | ||
371 | int __init igafb_init(void) | 371 | static int __init igafb_init(void) |
372 | { | 372 | { |
373 | struct fb_info *info; | 373 | struct fb_info *info; |
374 | struct pci_dev *pdev; | 374 | struct pci_dev *pdev; |
@@ -531,6 +531,7 @@ int __init igafb_init(void) | |||
531 | iounmap(info->screen_base); | 531 | iounmap(info->screen_base); |
532 | kfree(par->mmap_map); | 532 | kfree(par->mmap_map); |
533 | kfree(info); | 533 | kfree(info); |
534 | return -ENODEV; | ||
534 | } | 535 | } |
535 | 536 | ||
536 | #ifdef CONFIG_SPARC | 537 | #ifdef CONFIG_SPARC |
@@ -556,7 +557,7 @@ int __init igafb_init(void) | |||
556 | return 0; | 557 | return 0; |
557 | } | 558 | } |
558 | 559 | ||
559 | int __init igafb_setup(char *options) | 560 | static int __init igafb_setup(char *options) |
560 | { | 561 | { |
561 | char *this_opt; | 562 | char *this_opt; |
562 | 563 | ||
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 43f0639b1c10..5c363d026f64 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -40,6 +40,12 @@ | |||
40 | */ | 40 | */ |
41 | #define DEBUG_VAR 1 | 41 | #define DEBUG_VAR 1 |
42 | 42 | ||
43 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ | ||
44 | (defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) && \ | ||
45 | defined(CONFIG_FB_IMX_MODULE)) | ||
46 | #define PWMR_BACKLIGHT_AVAILABLE | ||
47 | #endif | ||
48 | |||
43 | #define DRIVER_NAME "imx-fb" | 49 | #define DRIVER_NAME "imx-fb" |
44 | 50 | ||
45 | #define LCDC_SSA 0x00 | 51 | #define LCDC_SSA 0x00 |
@@ -175,7 +181,9 @@ struct imxfb_info { | |||
175 | 181 | ||
176 | struct imx_fb_videomode *mode; | 182 | struct imx_fb_videomode *mode; |
177 | int num_modes; | 183 | int num_modes; |
184 | #ifdef PWMR_BACKLIGHT_AVAILABLE | ||
178 | struct backlight_device *bl; | 185 | struct backlight_device *bl; |
186 | #endif | ||
179 | 187 | ||
180 | void (*lcd_power)(int); | 188 | void (*lcd_power)(int); |
181 | void (*backlight_power)(int); | 189 | void (*backlight_power)(int); |
@@ -450,8 +458,7 @@ static int imxfb_set_par(struct fb_info *info) | |||
450 | return 0; | 458 | return 0; |
451 | } | 459 | } |
452 | 460 | ||
453 | 461 | #ifdef PWMR_BACKLIGHT_AVAILABLE | |
454 | |||
455 | static int imxfb_bl_get_brightness(struct backlight_device *bl) | 462 | static int imxfb_bl_get_brightness(struct backlight_device *bl) |
456 | { | 463 | { |
457 | struct imxfb_info *fbi = bl_get_data(bl); | 464 | struct imxfb_info *fbi = bl_get_data(bl); |
@@ -516,6 +523,7 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi) | |||
516 | if (fbi->bl) | 523 | if (fbi->bl) |
517 | backlight_device_unregister(fbi->bl); | 524 | backlight_device_unregister(fbi->bl); |
518 | } | 525 | } |
526 | #endif | ||
519 | 527 | ||
520 | static void imxfb_enable_controller(struct imxfb_info *fbi) | 528 | static void imxfb_enable_controller(struct imxfb_info *fbi) |
521 | { | 529 | { |
@@ -647,6 +655,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf | |||
647 | fbi->regs + LCDC_SIZE); | 655 | fbi->regs + LCDC_SIZE); |
648 | 656 | ||
649 | writel(fbi->pcr, fbi->regs + LCDC_PCR); | 657 | writel(fbi->pcr, fbi->regs + LCDC_PCR); |
658 | #ifndef PWMR_BACKLIGHT_AVAILABLE | ||
659 | writel(fbi->pwmr, fbi->regs + LCDC_PWMR); | ||
660 | #endif | ||
650 | writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); | 661 | writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); |
651 | writel(fbi->dmacr, fbi->regs + LCDC_DMACR); | 662 | writel(fbi->dmacr, fbi->regs + LCDC_DMACR); |
652 | 663 | ||
@@ -847,7 +858,9 @@ static int __init imxfb_probe(struct platform_device *pdev) | |||
847 | 858 | ||
848 | imxfb_enable_controller(fbi); | 859 | imxfb_enable_controller(fbi); |
849 | fbi->pdev = pdev; | 860 | fbi->pdev = pdev; |
861 | #ifdef PWMR_BACKLIGHT_AVAILABLE | ||
850 | imxfb_init_backlight(fbi); | 862 | imxfb_init_backlight(fbi); |
863 | #endif | ||
851 | 864 | ||
852 | return 0; | 865 | return 0; |
853 | 866 | ||
@@ -885,7 +898,9 @@ static int __devexit imxfb_remove(struct platform_device *pdev) | |||
885 | 898 | ||
886 | imxfb_disable_controller(fbi); | 899 | imxfb_disable_controller(fbi); |
887 | 900 | ||
901 | #ifdef PWMR_BACKLIGHT_AVAILABLE | ||
888 | imxfb_exit_backlight(fbi); | 902 | imxfb_exit_backlight(fbi); |
903 | #endif | ||
889 | unregister_framebuffer(info); | 904 | unregister_framebuffer(info); |
890 | 905 | ||
891 | pdata = pdev->dev.platform_data; | 906 | pdata = pdev->dev.platform_data; |
diff --git a/drivers/video/leo.c b/drivers/video/leo.c index ad677637ffbb..b599e5e36ced 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c | |||
@@ -529,7 +529,7 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) | |||
529 | var->transp.length = 0; | 529 | var->transp.length = 0; |
530 | } | 530 | } |
531 | 531 | ||
532 | static void leo_unmap_regs(struct of_device *op, struct fb_info *info, | 532 | static void leo_unmap_regs(struct platform_device *op, struct fb_info *info, |
533 | struct leo_par *par) | 533 | struct leo_par *par) |
534 | { | 534 | { |
535 | if (par->lc_ss0_usr) | 535 | if (par->lc_ss0_usr) |
@@ -547,7 +547,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info, | |||
547 | of_iounmap(&op->resource[0], info->screen_base, 0x800000); | 547 | of_iounmap(&op->resource[0], info->screen_base, 0x800000); |
548 | } | 548 | } |
549 | 549 | ||
550 | static int __devinit leo_probe(struct of_device *op, | 550 | static int __devinit leo_probe(struct platform_device *op, |
551 | const struct of_device_id *match) | 551 | const struct of_device_id *match) |
552 | { | 552 | { |
553 | struct device_node *dp = op->dev.of_node; | 553 | struct device_node *dp = op->dev.of_node; |
@@ -637,7 +637,7 @@ out_err: | |||
637 | return err; | 637 | return err; |
638 | } | 638 | } |
639 | 639 | ||
640 | static int __devexit leo_remove(struct of_device *op) | 640 | static int __devexit leo_remove(struct platform_device *op) |
641 | { | 641 | { |
642 | struct fb_info *info = dev_get_drvdata(&op->dev); | 642 | struct fb_info *info = dev_get_drvdata(&op->dev); |
643 | struct leo_par *par = info->par; | 643 | struct leo_par *par = info->par; |
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 403b14445a78..0fb280ead3dc 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c | |||
@@ -191,7 +191,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) { | |||
191 | }; | 191 | }; |
192 | 192 | ||
193 | i2c_new_probed_device(&m2info->maven.adapter, | 193 | i2c_new_probed_device(&m2info->maven.adapter, |
194 | &maven_info, addr_list); | 194 | &maven_info, addr_list, NULL); |
195 | } | 195 | } |
196 | } | 196 | } |
197 | return m2info; | 197 | return m2info; |
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index 4e2b8cc3d460..b1c4374cf940 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c | |||
@@ -550,7 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par) | |||
550 | return 0; | 550 | return 0; |
551 | } | 551 | } |
552 | 552 | ||
553 | static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, | 553 | static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev, |
554 | const struct of_device_id *id) | 554 | const struct of_device_id *id) |
555 | { | 555 | { |
556 | struct device_node *np = ofdev->dev.of_node; | 556 | struct device_node *np = ofdev->dev.of_node; |
@@ -669,7 +669,7 @@ fbrel: | |||
669 | return ret; | 669 | return ret; |
670 | } | 670 | } |
671 | 671 | ||
672 | static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) | 672 | static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev) |
673 | { | 673 | { |
674 | struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); | 674 | struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); |
675 | struct mb862xxfb_par *par = fbi->par; | 675 | struct mb862xxfb_par *par = fbi->par; |
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c index c1ff271017a9..7c316c34dfca 100644 --- a/drivers/video/msm/mddi.c +++ b/drivers/video/msm/mddi.c | |||
@@ -187,10 +187,8 @@ static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask); | |||
187 | 187 | ||
188 | static void mddi_handle_rev_data_avail(struct mddi_info *mddi) | 188 | static void mddi_handle_rev_data_avail(struct mddi_info *mddi) |
189 | { | 189 | { |
190 | union mddi_rev *rev = mddi->rev_data; | ||
191 | uint32_t rev_data_count; | 190 | uint32_t rev_data_count; |
192 | uint32_t rev_crc_err_count; | 191 | uint32_t rev_crc_err_count; |
193 | int i; | ||
194 | struct reg_read_info *ri; | 192 | struct reg_read_info *ri; |
195 | size_t prev_offset; | 193 | size_t prev_offset; |
196 | uint16_t length; | 194 | uint16_t length; |
@@ -670,7 +668,7 @@ static int __init mddi_rev_data_setup(struct mddi_info *mddi) | |||
670 | return 0; | 668 | return 0; |
671 | } | 669 | } |
672 | 670 | ||
673 | static int __init mddi_probe(struct platform_device *pdev) | 671 | static int __devinit mddi_probe(struct platform_device *pdev) |
674 | { | 672 | { |
675 | struct msm_mddi_platform_data *pdata = pdev->dev.platform_data; | 673 | struct msm_mddi_platform_data *pdata = pdev->dev.platform_data; |
676 | struct mddi_info *mddi = &mddi_info[pdev->id]; | 674 | struct mddi_info *mddi = &mddi_info[pdev->id]; |
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index 19c01c6208e8..3c28db03ad39 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c | |||
@@ -258,7 +258,6 @@ int get_img(struct mdp_img *img, struct fb_info *info, | |||
258 | { | 258 | { |
259 | int put_needed, ret = 0; | 259 | int put_needed, ret = 0; |
260 | struct file *file; | 260 | struct file *file; |
261 | unsigned long vstart; | ||
262 | 261 | ||
263 | file = fget_light(img->memory_id, &put_needed); | 262 | file = fget_light(img->memory_id, &put_needed); |
264 | if (file == NULL) | 263 | if (file == NULL) |
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 688b055abab2..b6c3fc2db632 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c | |||
@@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no | |||
249 | info->fix.accel = FB_ACCEL_SUN_CGTHREE; | 249 | info->fix.accel = FB_ACCEL_SUN_CGTHREE; |
250 | } | 250 | } |
251 | 251 | ||
252 | static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) | 252 | static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match) |
253 | { | 253 | { |
254 | struct device_node *dp = op->dev.of_node; | 254 | struct device_node *dp = op->dev.of_node; |
255 | struct fb_info *info; | 255 | struct fb_info *info; |
@@ -326,7 +326,7 @@ out_err: | |||
326 | return err; | 326 | return err; |
327 | } | 327 | } |
328 | 328 | ||
329 | static int __devexit p9100_remove(struct of_device *op) | 329 | static int __devexit p9100_remove(struct platform_device *op) |
330 | { | 330 | { |
331 | struct fb_info *info = dev_get_drvdata(&op->dev); | 331 | struct fb_info *info = dev_get_drvdata(&op->dev); |
332 | struct p9100_par *par = info->par; | 332 | struct p9100_par *par = info->par; |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 72a1f4c04732..a50e1977b316 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -533,7 +533,7 @@ static int __init platinumfb_setup(char *options) | |||
533 | #define invalidate_cache(addr) | 533 | #define invalidate_cache(addr) |
534 | #endif | 534 | #endif |
535 | 535 | ||
536 | static int __devinit platinumfb_probe(struct of_device* odev, | 536 | static int __devinit platinumfb_probe(struct platform_device* odev, |
537 | const struct of_device_id *match) | 537 | const struct of_device_id *match) |
538 | { | 538 | { |
539 | struct device_node *dp = odev->dev.of_node; | 539 | struct device_node *dp = odev->dev.of_node; |
@@ -646,7 +646,7 @@ static int __devinit platinumfb_probe(struct of_device* odev, | |||
646 | return rc; | 646 | return rc; |
647 | } | 647 | } |
648 | 648 | ||
649 | static int __devexit platinumfb_remove(struct of_device* odev) | 649 | static int __devexit platinumfb_remove(struct platform_device* odev) |
650 | { | 650 | { |
651 | struct fb_info *info = dev_get_drvdata(&odev->dev); | 651 | struct fb_info *info = dev_get_drvdata(&odev->dev); |
652 | struct fb_info_platinum *pinfo = info->par; | 652 | struct fb_info_platinum *pinfo = info->par; |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 9682ecc60e12..f9aca9d13d1b 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* linux/drivers/video/s3c-fb.c | 1 | /* linux/drivers/video/s3c-fb.c |
2 | * | 2 | * |
3 | * Copyright 2008 Openmoko Inc. | 3 | * Copyright 2008 Openmoko Inc. |
4 | * Copyright 2008 Simtec Electronics | 4 | * Copyright 2008-2010 Simtec Electronics |
5 | * Ben Dooks <ben@simtec.co.uk> | 5 | * Ben Dooks <ben@simtec.co.uk> |
6 | * http://armlinux.simtec.co.uk/ | 6 | * http://armlinux.simtec.co.uk/ |
7 | * | 7 | * |
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software FoundatIon. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
@@ -21,9 +21,11 @@ | |||
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/fb.h> | 22 | #include <linux/fb.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/interrupt.h> | ||
24 | 26 | ||
25 | #include <mach/map.h> | 27 | #include <mach/map.h> |
26 | #include <mach/regs-fb.h> | 28 | #include <plat/regs-fb-v4.h> |
27 | #include <plat/fb.h> | 29 | #include <plat/fb.h> |
28 | 30 | ||
29 | /* This driver will export a number of framebuffer interfaces depending | 31 | /* This driver will export a number of framebuffer interfaces depending |
@@ -36,9 +38,9 @@ | |||
36 | * output timings and as the control for the output power-down state. | 38 | * output timings and as the control for the output power-down state. |
37 | */ | 39 | */ |
38 | 40 | ||
39 | /* note, some of the functions that get called are derived from including | 41 | /* note, the previous use of <mach/regs-fb.h> to get platform specific data |
40 | * <mach/regs-fb.h> as they are specific to the architecture that the code | 42 | * has been replaced by using the platform device name to pick the correct |
41 | * is being built for. | 43 | * configuration data for the system. |
42 | */ | 44 | */ |
43 | 45 | ||
44 | #ifdef CONFIG_FB_S3C_DEBUG_REGWRITE | 46 | #ifdef CONFIG_FB_S3C_DEBUG_REGWRITE |
@@ -48,13 +50,108 @@ | |||
48 | __raw_writel(v, r); } while(0) | 50 | __raw_writel(v, r); } while(0) |
49 | #endif /* FB_S3C_DEBUG_REGWRITE */ | 51 | #endif /* FB_S3C_DEBUG_REGWRITE */ |
50 | 52 | ||
53 | /* irq_flags bits */ | ||
54 | #define S3C_FB_VSYNC_IRQ_EN 0 | ||
55 | |||
56 | #define VSYNC_TIMEOUT_MSEC 50 | ||
57 | |||
51 | struct s3c_fb; | 58 | struct s3c_fb; |
52 | 59 | ||
60 | #define VALID_BPP(x) (1 << ((x) - 1)) | ||
61 | |||
62 | #define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride)) | ||
63 | #define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00) | ||
64 | #define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04) | ||
65 | #define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08) | ||
66 | #define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C) | ||
67 | |||
68 | /** | ||
69 | * struct s3c_fb_variant - fb variant information | ||
70 | * @is_2443: Set if S3C2443/S3C2416 style hardware. | ||
71 | * @nr_windows: The number of windows. | ||
72 | * @vidtcon: The base for the VIDTCONx registers | ||
73 | * @wincon: The base for the WINxCON registers. | ||
74 | * @winmap: The base for the WINxMAP registers. | ||
75 | * @keycon: The abse for the WxKEYCON registers. | ||
76 | * @buf_start: Offset of buffer start registers. | ||
77 | * @buf_size: Offset of buffer size registers. | ||
78 | * @buf_end: Offset of buffer end registers. | ||
79 | * @osd: The base for the OSD registers. | ||
80 | * @palette: Address of palette memory, or 0 if none. | ||
81 | * @has_prtcon: Set if has PRTCON register. | ||
82 | * @has_shadowcon: Set if has SHADOWCON register. | ||
83 | */ | ||
84 | struct s3c_fb_variant { | ||
85 | unsigned int is_2443:1; | ||
86 | unsigned short nr_windows; | ||
87 | unsigned short vidtcon; | ||
88 | unsigned short wincon; | ||
89 | unsigned short winmap; | ||
90 | unsigned short keycon; | ||
91 | unsigned short buf_start; | ||
92 | unsigned short buf_end; | ||
93 | unsigned short buf_size; | ||
94 | unsigned short osd; | ||
95 | unsigned short osd_stride; | ||
96 | unsigned short palette[S3C_FB_MAX_WIN]; | ||
97 | |||
98 | unsigned int has_prtcon:1; | ||
99 | unsigned int has_shadowcon:1; | ||
100 | }; | ||
101 | |||
102 | /** | ||
103 | * struct s3c_fb_win_variant | ||
104 | * @has_osd_c: Set if has OSD C register. | ||
105 | * @has_osd_d: Set if has OSD D register. | ||
106 | * @has_osd_alpha: Set if can change alpha transparency for a window. | ||
107 | * @palette_sz: Size of palette in entries. | ||
108 | * @palette_16bpp: Set if palette is 16bits wide. | ||
109 | * @osd_size_off: If != 0, supports setting up OSD for a window; the appropriate | ||
110 | * register is located at the given offset from OSD_BASE. | ||
111 | * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel. | ||
112 | * | ||
113 | * valid_bpp bit x is set if (x+1)BPP is supported. | ||
114 | */ | ||
115 | struct s3c_fb_win_variant { | ||
116 | unsigned int has_osd_c:1; | ||
117 | unsigned int has_osd_d:1; | ||
118 | unsigned int has_osd_alpha:1; | ||
119 | unsigned int palette_16bpp:1; | ||
120 | unsigned short osd_size_off; | ||
121 | unsigned short palette_sz; | ||
122 | u32 valid_bpp; | ||
123 | }; | ||
124 | |||
125 | /** | ||
126 | * struct s3c_fb_driverdata - per-device type driver data for init time. | ||
127 | * @variant: The variant information for this driver. | ||
128 | * @win: The window information for each window. | ||
129 | */ | ||
130 | struct s3c_fb_driverdata { | ||
131 | struct s3c_fb_variant variant; | ||
132 | struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN]; | ||
133 | }; | ||
134 | |||
135 | /** | ||
136 | * struct s3c_fb_palette - palette information | ||
137 | * @r: Red bitfield. | ||
138 | * @g: Green bitfield. | ||
139 | * @b: Blue bitfield. | ||
140 | * @a: Alpha bitfield. | ||
141 | */ | ||
142 | struct s3c_fb_palette { | ||
143 | struct fb_bitfield r; | ||
144 | struct fb_bitfield g; | ||
145 | struct fb_bitfield b; | ||
146 | struct fb_bitfield a; | ||
147 | }; | ||
148 | |||
53 | /** | 149 | /** |
54 | * struct s3c_fb_win - per window private data for each framebuffer. | 150 | * struct s3c_fb_win - per window private data for each framebuffer. |
55 | * @windata: The platform data supplied for the window configuration. | 151 | * @windata: The platform data supplied for the window configuration. |
56 | * @parent: The hardware that this window is part of. | 152 | * @parent: The hardware that this window is part of. |
57 | * @fbinfo: Pointer pack to the framebuffer info for this window. | 153 | * @fbinfo: Pointer pack to the framebuffer info for this window. |
154 | * @varint: The variant information for this window. | ||
58 | * @palette_buffer: Buffer/cache to hold palette entries. | 155 | * @palette_buffer: Buffer/cache to hold palette entries. |
59 | * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/ | 156 | * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/ |
60 | * @index: The window number of this window. | 157 | * @index: The window number of this window. |
@@ -65,6 +162,7 @@ struct s3c_fb_win { | |||
65 | struct s3c_fb *parent; | 162 | struct s3c_fb *parent; |
66 | struct fb_info *fbinfo; | 163 | struct fb_info *fbinfo; |
67 | struct s3c_fb_palette palette; | 164 | struct s3c_fb_palette palette; |
165 | struct s3c_fb_win_variant variant; | ||
68 | 166 | ||
69 | u32 *palette_buffer; | 167 | u32 *palette_buffer; |
70 | u32 pseudo_palette[16]; | 168 | u32 pseudo_palette[16]; |
@@ -72,37 +170,54 @@ struct s3c_fb_win { | |||
72 | }; | 170 | }; |
73 | 171 | ||
74 | /** | 172 | /** |
173 | * struct s3c_fb_vsync - vsync information | ||
174 | * @wait: a queue for processes waiting for vsync | ||
175 | * @count: vsync interrupt count | ||
176 | */ | ||
177 | struct s3c_fb_vsync { | ||
178 | wait_queue_head_t wait; | ||
179 | unsigned int count; | ||
180 | }; | ||
181 | |||
182 | /** | ||
75 | * struct s3c_fb - overall hardware state of the hardware | 183 | * struct s3c_fb - overall hardware state of the hardware |
76 | * @dev: The device that we bound to, for printing, etc. | 184 | * @dev: The device that we bound to, for printing, etc. |
77 | * @regs_res: The resource we claimed for the IO registers. | 185 | * @regs_res: The resource we claimed for the IO registers. |
78 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. | 186 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. |
79 | * @regs: The mapped hardware registers. | 187 | * @regs: The mapped hardware registers. |
188 | * @variant: Variant information for this hardware. | ||
80 | * @enabled: A bitmask of enabled hardware windows. | 189 | * @enabled: A bitmask of enabled hardware windows. |
81 | * @pdata: The platform configuration data passed with the device. | 190 | * @pdata: The platform configuration data passed with the device. |
82 | * @windows: The hardware windows that have been claimed. | 191 | * @windows: The hardware windows that have been claimed. |
192 | * @irq_no: IRQ line number | ||
193 | * @irq_flags: irq flags | ||
194 | * @vsync_info: VSYNC-related information (count, queues...) | ||
83 | */ | 195 | */ |
84 | struct s3c_fb { | 196 | struct s3c_fb { |
85 | struct device *dev; | 197 | struct device *dev; |
86 | struct resource *regs_res; | 198 | struct resource *regs_res; |
87 | struct clk *bus_clk; | 199 | struct clk *bus_clk; |
88 | void __iomem *regs; | 200 | void __iomem *regs; |
201 | struct s3c_fb_variant variant; | ||
89 | 202 | ||
90 | unsigned char enabled; | 203 | unsigned char enabled; |
91 | 204 | ||
92 | struct s3c_fb_platdata *pdata; | 205 | struct s3c_fb_platdata *pdata; |
93 | struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; | 206 | struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; |
207 | |||
208 | int irq_no; | ||
209 | unsigned long irq_flags; | ||
210 | struct s3c_fb_vsync vsync_info; | ||
94 | }; | 211 | }; |
95 | 212 | ||
96 | /** | 213 | /** |
97 | * s3c_fb_win_has_palette() - determine if a mode has a palette | 214 | * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode. |
98 | * @win: The window number being queried. | 215 | * @win: The device window. |
99 | * @bpp: The number of bits per pixel to test. | 216 | * @bpp: The bit depth. |
100 | * | ||
101 | * Work out if the given window supports palletised data at the specified bpp. | ||
102 | */ | 217 | */ |
103 | static int s3c_fb_win_has_palette(unsigned int win, unsigned int bpp) | 218 | static bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp) |
104 | { | 219 | { |
105 | return s3c_fb_win_pal_size(win) <= (1 << bpp); | 220 | return win->variant.valid_bpp & VALID_BPP(bpp); |
106 | } | 221 | } |
107 | 222 | ||
108 | /** | 223 | /** |
@@ -125,7 +240,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
125 | var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); | 240 | var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); |
126 | var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); | 241 | var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); |
127 | 242 | ||
128 | if (!s3c_fb_validate_win_bpp(win->index, var->bits_per_pixel)) { | 243 | if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) { |
129 | dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", | 244 | dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", |
130 | win->index, var->bits_per_pixel); | 245 | win->index, var->bits_per_pixel); |
131 | return -EINVAL; | 246 | return -EINVAL; |
@@ -140,7 +255,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
140 | case 2: | 255 | case 2: |
141 | case 4: | 256 | case 4: |
142 | case 8: | 257 | case 8: |
143 | if (!s3c_fb_win_has_palette(win->index, var->bits_per_pixel)) { | 258 | if (sfb->variant.palette[win->index] != 0) { |
144 | /* non palletised, A:1,R:2,G:3,B:2 mode */ | 259 | /* non palletised, A:1,R:2,G:3,B:2 mode */ |
145 | var->red.offset = 4; | 260 | var->red.offset = 4; |
146 | var->green.offset = 2; | 261 | var->green.offset = 2; |
@@ -255,6 +370,66 @@ static int s3c_fb_align_word(unsigned int bpp, unsigned int pix) | |||
255 | } | 370 | } |
256 | 371 | ||
257 | /** | 372 | /** |
373 | * vidosd_set_size() - set OSD size for a window | ||
374 | * | ||
375 | * @win: the window to set OSD size for | ||
376 | * @size: OSD size register value | ||
377 | */ | ||
378 | static void vidosd_set_size(struct s3c_fb_win *win, u32 size) | ||
379 | { | ||
380 | struct s3c_fb *sfb = win->parent; | ||
381 | |||
382 | /* OSD can be set up if osd_size_off != 0 for this window */ | ||
383 | if (win->variant.osd_size_off) | ||
384 | writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant) | ||
385 | + win->variant.osd_size_off); | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * vidosd_set_alpha() - set alpha transparency for a window | ||
390 | * | ||
391 | * @win: the window to set OSD size for | ||
392 | * @alpha: alpha register value | ||
393 | */ | ||
394 | static void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha) | ||
395 | { | ||
396 | struct s3c_fb *sfb = win->parent; | ||
397 | |||
398 | if (win->variant.has_osd_alpha) | ||
399 | writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant)); | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * shadow_protect_win() - disable updating values from shadow registers at vsync | ||
404 | * | ||
405 | * @win: window to protect registers for | ||
406 | * @protect: 1 to protect (disable updates) | ||
407 | */ | ||
408 | static void shadow_protect_win(struct s3c_fb_win *win, bool protect) | ||
409 | { | ||
410 | struct s3c_fb *sfb = win->parent; | ||
411 | u32 reg; | ||
412 | |||
413 | if (protect) { | ||
414 | if (sfb->variant.has_prtcon) { | ||
415 | writel(PRTCON_PROTECT, sfb->regs + PRTCON); | ||
416 | } else if (sfb->variant.has_shadowcon) { | ||
417 | reg = readl(sfb->regs + SHADOWCON); | ||
418 | writel(reg | SHADOWCON_WINx_PROTECT(win->index), | ||
419 | sfb->regs + SHADOWCON); | ||
420 | } | ||
421 | } else { | ||
422 | if (sfb->variant.has_prtcon) { | ||
423 | writel(0, sfb->regs + PRTCON); | ||
424 | } else if (sfb->variant.has_shadowcon) { | ||
425 | reg = readl(sfb->regs + SHADOWCON); | ||
426 | writel(reg & ~SHADOWCON_WINx_PROTECT(win->index), | ||
427 | sfb->regs + SHADOWCON); | ||
428 | } | ||
429 | } | ||
430 | } | ||
431 | |||
432 | /** | ||
258 | * s3c_fb_set_par() - framebuffer request to set new framebuffer state. | 433 | * s3c_fb_set_par() - framebuffer request to set new framebuffer state. |
259 | * @info: The framebuffer to change. | 434 | * @info: The framebuffer to change. |
260 | * | 435 | * |
@@ -266,14 +441,17 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
266 | struct s3c_fb_win *win = info->par; | 441 | struct s3c_fb_win *win = info->par; |
267 | struct s3c_fb *sfb = win->parent; | 442 | struct s3c_fb *sfb = win->parent; |
268 | void __iomem *regs = sfb->regs; | 443 | void __iomem *regs = sfb->regs; |
444 | void __iomem *buf = regs; | ||
269 | int win_no = win->index; | 445 | int win_no = win->index; |
270 | u32 osdc_data = 0; | 446 | u32 alpha = 0; |
271 | u32 data; | 447 | u32 data; |
272 | u32 pagewidth; | 448 | u32 pagewidth; |
273 | int clkdiv; | 449 | int clkdiv; |
274 | 450 | ||
275 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); | 451 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); |
276 | 452 | ||
453 | shadow_protect_win(win, 1); | ||
454 | |||
277 | switch (var->bits_per_pixel) { | 455 | switch (var->bits_per_pixel) { |
278 | case 32: | 456 | case 32: |
279 | case 24: | 457 | case 24: |
@@ -282,7 +460,7 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
282 | info->fix.visual = FB_VISUAL_TRUECOLOR; | 460 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
283 | break; | 461 | break; |
284 | case 8: | 462 | case 8: |
285 | if (s3c_fb_win_has_palette(win_no, 8)) | 463 | if (win->variant.palette_sz >= 256) |
286 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | 464 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
287 | else | 465 | else |
288 | info->fix.visual = FB_VISUAL_TRUECOLOR; | 466 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
@@ -297,12 +475,15 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
297 | 475 | ||
298 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; | 476 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; |
299 | 477 | ||
478 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; | ||
479 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; | ||
480 | |||
300 | /* disable the window whilst we update it */ | 481 | /* disable the window whilst we update it */ |
301 | writel(0, regs + WINCON(win_no)); | 482 | writel(0, regs + WINCON(win_no)); |
302 | 483 | ||
303 | /* use window 0 as the basis for the lcd output timings */ | 484 | /* use platform specified window as the basis for the lcd timings */ |
304 | 485 | ||
305 | if (win_no == 0) { | 486 | if (win_no == sfb->pdata->default_win) { |
306 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); | 487 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); |
307 | 488 | ||
308 | data = sfb->pdata->vidcon0; | 489 | data = sfb->pdata->vidcon0; |
@@ -315,6 +496,9 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
315 | 496 | ||
316 | /* write the timing data to the panel */ | 497 | /* write the timing data to the panel */ |
317 | 498 | ||
499 | if (sfb->variant.is_2443) | ||
500 | data |= (1 << 5); | ||
501 | |||
318 | data |= VIDCON0_ENVID | VIDCON0_ENVID_F; | 502 | data |= VIDCON0_ENVID | VIDCON0_ENVID_F; |
319 | writel(data, regs + VIDCON0); | 503 | writel(data, regs + VIDCON0); |
320 | 504 | ||
@@ -322,53 +506,54 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
322 | VIDTCON0_VFPD(var->lower_margin - 1) | | 506 | VIDTCON0_VFPD(var->lower_margin - 1) | |
323 | VIDTCON0_VSPW(var->vsync_len - 1); | 507 | VIDTCON0_VSPW(var->vsync_len - 1); |
324 | 508 | ||
325 | writel(data, regs + VIDTCON0); | 509 | writel(data, regs + sfb->variant.vidtcon); |
326 | 510 | ||
327 | data = VIDTCON1_HBPD(var->left_margin - 1) | | 511 | data = VIDTCON1_HBPD(var->left_margin - 1) | |
328 | VIDTCON1_HFPD(var->right_margin - 1) | | 512 | VIDTCON1_HFPD(var->right_margin - 1) | |
329 | VIDTCON1_HSPW(var->hsync_len - 1); | 513 | VIDTCON1_HSPW(var->hsync_len - 1); |
330 | 514 | ||
331 | writel(data, regs + VIDTCON1); | 515 | /* VIDTCON1 */ |
516 | writel(data, regs + sfb->variant.vidtcon + 4); | ||
332 | 517 | ||
333 | data = VIDTCON2_LINEVAL(var->yres - 1) | | 518 | data = VIDTCON2_LINEVAL(var->yres - 1) | |
334 | VIDTCON2_HOZVAL(var->xres - 1); | 519 | VIDTCON2_HOZVAL(var->xres - 1); |
335 | writel(data, regs + VIDTCON2); | 520 | writel(data, regs +sfb->variant.vidtcon + 8 ); |
336 | } | 521 | } |
337 | 522 | ||
338 | /* write the buffer address */ | 523 | /* write the buffer address */ |
339 | 524 | ||
340 | writel(info->fix.smem_start, regs + VIDW_BUF_START(win_no)); | 525 | /* start and end registers stride is 8 */ |
526 | buf = regs + win_no * 8; | ||
527 | |||
528 | writel(info->fix.smem_start, buf + sfb->variant.buf_start); | ||
341 | 529 | ||
342 | data = info->fix.smem_start + info->fix.line_length * var->yres; | 530 | data = info->fix.smem_start + info->fix.line_length * var->yres; |
343 | writel(data, regs + VIDW_BUF_END(win_no)); | 531 | writel(data, buf + sfb->variant.buf_end); |
344 | 532 | ||
345 | pagewidth = (var->xres * var->bits_per_pixel) >> 3; | 533 | pagewidth = (var->xres * var->bits_per_pixel) >> 3; |
346 | data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | | 534 | data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | |
347 | VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); | 535 | VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); |
348 | writel(data, regs + VIDW_BUF_SIZE(win_no)); | 536 | writel(data, regs + sfb->variant.buf_size + (win_no * 4)); |
349 | 537 | ||
350 | /* write 'OSD' registers to control position of framebuffer */ | 538 | /* write 'OSD' registers to control position of framebuffer */ |
351 | 539 | ||
352 | data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); | 540 | data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); |
353 | writel(data, regs + VIDOSD_A(win_no)); | 541 | writel(data, regs + VIDOSD_A(win_no, sfb->variant)); |
354 | 542 | ||
355 | data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, | 543 | data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, |
356 | var->xres - 1)) | | 544 | var->xres - 1)) | |
357 | VIDOSDxB_BOTRIGHT_Y(var->yres - 1); | 545 | VIDOSDxB_BOTRIGHT_Y(var->yres - 1); |
358 | 546 | ||
359 | writel(data, regs + VIDOSD_B(win_no)); | 547 | writel(data, regs + VIDOSD_B(win_no, sfb->variant)); |
360 | 548 | ||
361 | data = var->xres * var->yres; | 549 | data = var->xres * var->yres; |
362 | 550 | ||
363 | osdc_data = VIDISD14C_ALPHA1_R(0xf) | | 551 | alpha = VIDISD14C_ALPHA1_R(0xf) | |
364 | VIDISD14C_ALPHA1_G(0xf) | | 552 | VIDISD14C_ALPHA1_G(0xf) | |
365 | VIDISD14C_ALPHA1_B(0xf); | 553 | VIDISD14C_ALPHA1_B(0xf); |
366 | 554 | ||
367 | if (s3c_fb_has_osd_d(win_no)) { | 555 | vidosd_set_alpha(win, alpha); |
368 | writel(data, regs + VIDOSD_D(win_no)); | 556 | vidosd_set_size(win, data); |
369 | writel(osdc_data, regs + VIDOSD_C(win_no)); | ||
370 | } else | ||
371 | writel(data, regs + VIDOSD_C(win_no)); | ||
372 | 557 | ||
373 | data = WINCONx_ENWIN; | 558 | data = WINCONx_ENWIN; |
374 | 559 | ||
@@ -424,13 +609,15 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
424 | else | 609 | else |
425 | data |= WINCON0_BPPMODE_24BPP_888; | 610 | data |= WINCON0_BPPMODE_24BPP_888; |
426 | 611 | ||
612 | data |= WINCONx_WSWP; | ||
427 | data |= WINCONx_BURSTLEN_16WORD; | 613 | data |= WINCONx_BURSTLEN_16WORD; |
428 | break; | 614 | break; |
429 | } | 615 | } |
430 | 616 | ||
431 | /* It has no color key control register for window0 */ | 617 | /* Enable the colour keying for the window below this one */ |
432 | if (win_no > 0) { | 618 | if (win_no > 0) { |
433 | u32 keycon0_data = 0, keycon1_data = 0; | 619 | u32 keycon0_data = 0, keycon1_data = 0; |
620 | void __iomem *keycon = regs + sfb->variant.keycon; | ||
434 | 621 | ||
435 | keycon0_data = ~(WxKEYCON0_KEYBL_EN | | 622 | keycon0_data = ~(WxKEYCON0_KEYBL_EN | |
436 | WxKEYCON0_KEYEN_F | | 623 | WxKEYCON0_KEYEN_F | |
@@ -438,12 +625,23 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
438 | 625 | ||
439 | keycon1_data = WxKEYCON1_COLVAL(0xffffff); | 626 | keycon1_data = WxKEYCON1_COLVAL(0xffffff); |
440 | 627 | ||
441 | writel(keycon0_data, regs + WxKEYCONy(win_no-1, 0)); | 628 | keycon += (win_no - 1) * 8; |
442 | writel(keycon1_data, regs + WxKEYCONy(win_no-1, 1)); | 629 | |
630 | writel(keycon0_data, keycon + WKEYCON0); | ||
631 | writel(keycon1_data, keycon + WKEYCON1); | ||
632 | } | ||
633 | |||
634 | writel(data, regs + sfb->variant.wincon + (win_no * 4)); | ||
635 | writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); | ||
636 | |||
637 | /* Enable DMA channel for this window */ | ||
638 | if (sfb->variant.has_shadowcon) { | ||
639 | data = readl(sfb->regs + SHADOWCON); | ||
640 | data |= SHADOWCON_CHx_ENABLE(win_no); | ||
641 | writel(data, sfb->regs + SHADOWCON); | ||
443 | } | 642 | } |
444 | 643 | ||
445 | writel(data, regs + WINCON(win_no)); | 644 | shadow_protect_win(win, 0); |
446 | writel(0x0, regs + WINxMAP(win_no)); | ||
447 | 645 | ||
448 | return 0; | 646 | return 0; |
449 | } | 647 | } |
@@ -470,7 +668,7 @@ static void s3c_fb_update_palette(struct s3c_fb *sfb, | |||
470 | void __iomem *palreg; | 668 | void __iomem *palreg; |
471 | u32 palcon; | 669 | u32 palcon; |
472 | 670 | ||
473 | palreg = sfb->regs + s3c_fb_pal_reg(win->index, reg); | 671 | palreg = sfb->regs + sfb->variant.palette[win->index]; |
474 | 672 | ||
475 | dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", | 673 | dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", |
476 | __func__, win->index, reg, palreg, value); | 674 | __func__, win->index, reg, palreg, value); |
@@ -480,10 +678,10 @@ static void s3c_fb_update_palette(struct s3c_fb *sfb, | |||
480 | palcon = readl(sfb->regs + WPALCON); | 678 | palcon = readl(sfb->regs + WPALCON); |
481 | writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); | 679 | writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); |
482 | 680 | ||
483 | if (s3c_fb_pal_is16(win->index)) | 681 | if (win->variant.palette_16bpp) |
484 | writew(value, palreg); | 682 | writew(value, palreg + (reg * 2)); |
485 | else | 683 | else |
486 | writel(value, palreg); | 684 | writel(value, palreg + (reg * 4)); |
487 | 685 | ||
488 | writel(palcon, sfb->regs + WPALCON); | 686 | writel(palcon, sfb->regs + WPALCON); |
489 | } | 687 | } |
@@ -532,7 +730,7 @@ static int s3c_fb_setcolreg(unsigned regno, | |||
532 | break; | 730 | break; |
533 | 731 | ||
534 | case FB_VISUAL_PSEUDOCOLOR: | 732 | case FB_VISUAL_PSEUDOCOLOR: |
535 | if (regno < s3c_fb_win_pal_size(win->index)) { | 733 | if (regno < win->variant.palette_sz) { |
536 | val = chan_to_field(red, &win->palette.r); | 734 | val = chan_to_field(red, &win->palette.r); |
537 | val |= chan_to_field(green, &win->palette.g); | 735 | val |= chan_to_field(green, &win->palette.g); |
538 | val |= chan_to_field(blue, &win->palette.b); | 736 | val |= chan_to_field(blue, &win->palette.b); |
@@ -591,7 +789,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
591 | 789 | ||
592 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); | 790 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); |
593 | 791 | ||
594 | wincon = readl(sfb->regs + WINCON(index)); | 792 | wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4)); |
595 | 793 | ||
596 | switch (blank_mode) { | 794 | switch (blank_mode) { |
597 | case FB_BLANK_POWERDOWN: | 795 | case FB_BLANK_POWERDOWN: |
@@ -602,11 +800,11 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
602 | case FB_BLANK_NORMAL: | 800 | case FB_BLANK_NORMAL: |
603 | /* disable the DMA and display 0x0 (black) */ | 801 | /* disable the DMA and display 0x0 (black) */ |
604 | writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), | 802 | writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), |
605 | sfb->regs + WINxMAP(index)); | 803 | sfb->regs + sfb->variant.winmap + (index * 4)); |
606 | break; | 804 | break; |
607 | 805 | ||
608 | case FB_BLANK_UNBLANK: | 806 | case FB_BLANK_UNBLANK: |
609 | writel(0x0, sfb->regs + WINxMAP(index)); | 807 | writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4)); |
610 | wincon |= WINCONx_ENWIN; | 808 | wincon |= WINCONx_ENWIN; |
611 | sfb->enabled |= (1 << index); | 809 | sfb->enabled |= (1 << index); |
612 | break; | 810 | break; |
@@ -617,7 +815,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
617 | return 1; | 815 | return 1; |
618 | } | 816 | } |
619 | 817 | ||
620 | writel(wincon, sfb->regs + WINCON(index)); | 818 | writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); |
621 | 819 | ||
622 | /* Check the enabled state to see if we need to be running the | 820 | /* Check the enabled state to see if we need to be running the |
623 | * main LCD interface, as if there are no active windows then | 821 | * main LCD interface, as if there are no active windows then |
@@ -636,12 +834,185 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) | |||
636 | /* we're stuck with this until we can do something about overriding | 834 | /* we're stuck with this until we can do something about overriding |
637 | * the power control using the blanking event for a single fb. | 835 | * the power control using the blanking event for a single fb. |
638 | */ | 836 | */ |
639 | if (index == 0) | 837 | if (index == sfb->pdata->default_win) |
640 | s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); | 838 | s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); |
641 | 839 | ||
642 | return 0; | 840 | return 0; |
643 | } | 841 | } |
644 | 842 | ||
843 | /** | ||
844 | * s3c_fb_pan_display() - Pan the display. | ||
845 | * | ||
846 | * Note that the offsets can be written to the device at any time, as their | ||
847 | * values are latched at each vsync automatically. This also means that only | ||
848 | * the last call to this function will have any effect on next vsync, but | ||
849 | * there is no need to sleep waiting for it to prevent tearing. | ||
850 | * | ||
851 | * @var: The screen information to verify. | ||
852 | * @info: The framebuffer device. | ||
853 | */ | ||
854 | static int s3c_fb_pan_display(struct fb_var_screeninfo *var, | ||
855 | struct fb_info *info) | ||
856 | { | ||
857 | struct s3c_fb_win *win = info->par; | ||
858 | struct s3c_fb *sfb = win->parent; | ||
859 | void __iomem *buf = sfb->regs + win->index * 8; | ||
860 | unsigned int start_boff, end_boff; | ||
861 | |||
862 | /* Offset in bytes to the start of the displayed area */ | ||
863 | start_boff = var->yoffset * info->fix.line_length; | ||
864 | /* X offset depends on the current bpp */ | ||
865 | if (info->var.bits_per_pixel >= 8) { | ||
866 | start_boff += var->xoffset * (info->var.bits_per_pixel >> 3); | ||
867 | } else { | ||
868 | switch (info->var.bits_per_pixel) { | ||
869 | case 4: | ||
870 | start_boff += var->xoffset >> 1; | ||
871 | break; | ||
872 | case 2: | ||
873 | start_boff += var->xoffset >> 2; | ||
874 | break; | ||
875 | case 1: | ||
876 | start_boff += var->xoffset >> 3; | ||
877 | break; | ||
878 | default: | ||
879 | dev_err(sfb->dev, "invalid bpp\n"); | ||
880 | return -EINVAL; | ||
881 | } | ||
882 | } | ||
883 | /* Offset in bytes to the end of the displayed area */ | ||
884 | end_boff = start_boff + var->yres * info->fix.line_length; | ||
885 | |||
886 | /* Temporarily turn off per-vsync update from shadow registers until | ||
887 | * both start and end addresses are updated to prevent corruption */ | ||
888 | shadow_protect_win(win, 1); | ||
889 | |||
890 | writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start); | ||
891 | writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end); | ||
892 | |||
893 | shadow_protect_win(win, 0); | ||
894 | |||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | /** | ||
899 | * s3c_fb_enable_irq() - enable framebuffer interrupts | ||
900 | * @sfb: main hardware state | ||
901 | */ | ||
902 | static void s3c_fb_enable_irq(struct s3c_fb *sfb) | ||
903 | { | ||
904 | void __iomem *regs = sfb->regs; | ||
905 | u32 irq_ctrl_reg; | ||
906 | |||
907 | if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) { | ||
908 | /* IRQ disabled, enable it */ | ||
909 | irq_ctrl_reg = readl(regs + VIDINTCON0); | ||
910 | |||
911 | irq_ctrl_reg |= VIDINTCON0_INT_ENABLE; | ||
912 | irq_ctrl_reg |= VIDINTCON0_INT_FRAME; | ||
913 | |||
914 | irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK; | ||
915 | irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC; | ||
916 | irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK; | ||
917 | irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE; | ||
918 | |||
919 | writel(irq_ctrl_reg, regs + VIDINTCON0); | ||
920 | } | ||
921 | } | ||
922 | |||
923 | /** | ||
924 | * s3c_fb_disable_irq() - disable framebuffer interrupts | ||
925 | * @sfb: main hardware state | ||
926 | */ | ||
927 | static void s3c_fb_disable_irq(struct s3c_fb *sfb) | ||
928 | { | ||
929 | void __iomem *regs = sfb->regs; | ||
930 | u32 irq_ctrl_reg; | ||
931 | |||
932 | if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) { | ||
933 | /* IRQ enabled, disable it */ | ||
934 | irq_ctrl_reg = readl(regs + VIDINTCON0); | ||
935 | |||
936 | irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME; | ||
937 | irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE; | ||
938 | |||
939 | writel(irq_ctrl_reg, regs + VIDINTCON0); | ||
940 | } | ||
941 | } | ||
942 | |||
943 | static irqreturn_t s3c_fb_irq(int irq, void *dev_id) | ||
944 | { | ||
945 | struct s3c_fb *sfb = dev_id; | ||
946 | void __iomem *regs = sfb->regs; | ||
947 | u32 irq_sts_reg; | ||
948 | |||
949 | irq_sts_reg = readl(regs + VIDINTCON1); | ||
950 | |||
951 | if (irq_sts_reg & VIDINTCON1_INT_FRAME) { | ||
952 | |||
953 | /* VSYNC interrupt, accept it */ | ||
954 | writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1); | ||
955 | |||
956 | sfb->vsync_info.count++; | ||
957 | wake_up_interruptible(&sfb->vsync_info.wait); | ||
958 | } | ||
959 | |||
960 | /* We only support waiting for VSYNC for now, so it's safe | ||
961 | * to always disable irqs here. | ||
962 | */ | ||
963 | s3c_fb_disable_irq(sfb); | ||
964 | |||
965 | return IRQ_HANDLED; | ||
966 | } | ||
967 | |||
968 | /** | ||
969 | * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout | ||
970 | * @sfb: main hardware state | ||
971 | * @crtc: head index. | ||
972 | */ | ||
973 | static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc) | ||
974 | { | ||
975 | unsigned long count; | ||
976 | int ret; | ||
977 | |||
978 | if (crtc != 0) | ||
979 | return -ENODEV; | ||
980 | |||
981 | count = sfb->vsync_info.count; | ||
982 | s3c_fb_enable_irq(sfb); | ||
983 | ret = wait_event_interruptible_timeout(sfb->vsync_info.wait, | ||
984 | count != sfb->vsync_info.count, | ||
985 | msecs_to_jiffies(VSYNC_TIMEOUT_MSEC)); | ||
986 | if (ret == 0) | ||
987 | return -ETIMEDOUT; | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | |||
992 | static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd, | ||
993 | unsigned long arg) | ||
994 | { | ||
995 | struct s3c_fb_win *win = info->par; | ||
996 | struct s3c_fb *sfb = win->parent; | ||
997 | int ret; | ||
998 | u32 crtc; | ||
999 | |||
1000 | switch (cmd) { | ||
1001 | case FBIO_WAITFORVSYNC: | ||
1002 | if (get_user(crtc, (u32 __user *)arg)) { | ||
1003 | ret = -EFAULT; | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | ret = s3c_fb_wait_for_vsync(sfb, crtc); | ||
1008 | break; | ||
1009 | default: | ||
1010 | ret = -ENOTTY; | ||
1011 | } | ||
1012 | |||
1013 | return ret; | ||
1014 | } | ||
1015 | |||
645 | static struct fb_ops s3c_fb_ops = { | 1016 | static struct fb_ops s3c_fb_ops = { |
646 | .owner = THIS_MODULE, | 1017 | .owner = THIS_MODULE, |
647 | .fb_check_var = s3c_fb_check_var, | 1018 | .fb_check_var = s3c_fb_check_var, |
@@ -651,9 +1022,33 @@ static struct fb_ops s3c_fb_ops = { | |||
651 | .fb_fillrect = cfb_fillrect, | 1022 | .fb_fillrect = cfb_fillrect, |
652 | .fb_copyarea = cfb_copyarea, | 1023 | .fb_copyarea = cfb_copyarea, |
653 | .fb_imageblit = cfb_imageblit, | 1024 | .fb_imageblit = cfb_imageblit, |
1025 | .fb_pan_display = s3c_fb_pan_display, | ||
1026 | .fb_ioctl = s3c_fb_ioctl, | ||
654 | }; | 1027 | }; |
655 | 1028 | ||
656 | /** | 1029 | /** |
1030 | * s3c_fb_missing_pixclock() - calculates pixel clock | ||
1031 | * @mode: The video mode to change. | ||
1032 | * | ||
1033 | * Calculate the pixel clock when none has been given through platform data. | ||
1034 | */ | ||
1035 | static void __devinit s3c_fb_missing_pixclock(struct fb_videomode *mode) | ||
1036 | { | ||
1037 | u64 pixclk = 1000000000000ULL; | ||
1038 | u32 div; | ||
1039 | |||
1040 | div = mode->left_margin + mode->hsync_len + mode->right_margin + | ||
1041 | mode->xres; | ||
1042 | div *= mode->upper_margin + mode->vsync_len + mode->lower_margin + | ||
1043 | mode->yres; | ||
1044 | div *= mode->refresh ? : 60; | ||
1045 | |||
1046 | do_div(pixclk, div); | ||
1047 | |||
1048 | mode->pixclock = pixclk; | ||
1049 | } | ||
1050 | |||
1051 | /** | ||
657 | * s3c_fb_alloc_memory() - allocate display memory for framebuffer window | 1052 | * s3c_fb_alloc_memory() - allocate display memory for framebuffer window |
658 | * @sfb: The base resources for the hardware. | 1053 | * @sfb: The base resources for the hardware. |
659 | * @win: The window to initialise memory for. | 1054 | * @win: The window to initialise memory for. |
@@ -711,7 +1106,8 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win) | |||
711 | { | 1106 | { |
712 | struct fb_info *fbi = win->fbinfo; | 1107 | struct fb_info *fbi = win->fbinfo; |
713 | 1108 | ||
714 | dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), | 1109 | if (fbi->screen_base) |
1110 | dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), | ||
715 | fbi->screen_base, fbi->fix.smem_start); | 1111 | fbi->screen_base, fbi->fix.smem_start); |
716 | } | 1112 | } |
717 | 1113 | ||
@@ -724,9 +1120,18 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win) | |||
724 | */ | 1120 | */ |
725 | static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) | 1121 | static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) |
726 | { | 1122 | { |
1123 | u32 data; | ||
1124 | |||
727 | if (win->fbinfo) { | 1125 | if (win->fbinfo) { |
1126 | if (sfb->variant.has_shadowcon) { | ||
1127 | data = readl(sfb->regs + SHADOWCON); | ||
1128 | data &= ~SHADOWCON_CHx_ENABLE(win->index); | ||
1129 | data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index); | ||
1130 | writel(data, sfb->regs + SHADOWCON); | ||
1131 | } | ||
728 | unregister_framebuffer(win->fbinfo); | 1132 | unregister_framebuffer(win->fbinfo); |
729 | fb_dealloc_cmap(&win->fbinfo->cmap); | 1133 | if (win->fbinfo->cmap.len) |
1134 | fb_dealloc_cmap(&win->fbinfo->cmap); | ||
730 | s3c_fb_free_memory(sfb, win); | 1135 | s3c_fb_free_memory(sfb, win); |
731 | framebuffer_release(win->fbinfo); | 1136 | framebuffer_release(win->fbinfo); |
732 | } | 1137 | } |
@@ -735,12 +1140,14 @@ static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) | |||
735 | /** | 1140 | /** |
736 | * s3c_fb_probe_win() - register an hardware window | 1141 | * s3c_fb_probe_win() - register an hardware window |
737 | * @sfb: The base resources for the hardware | 1142 | * @sfb: The base resources for the hardware |
1143 | * @variant: The variant information for this window. | ||
738 | * @res: Pointer to where to place the resultant window. | 1144 | * @res: Pointer to where to place the resultant window. |
739 | * | 1145 | * |
740 | * Allocate and do the basic initialisation for one of the hardware's graphics | 1146 | * Allocate and do the basic initialisation for one of the hardware's graphics |
741 | * windows. | 1147 | * windows. |
742 | */ | 1148 | */ |
743 | static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | 1149 | static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, |
1150 | struct s3c_fb_win_variant *variant, | ||
744 | struct s3c_fb_win **res) | 1151 | struct s3c_fb_win **res) |
745 | { | 1152 | { |
746 | struct fb_var_screeninfo *var; | 1153 | struct fb_var_screeninfo *var; |
@@ -751,9 +1158,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
751 | int palette_size; | 1158 | int palette_size; |
752 | int ret; | 1159 | int ret; |
753 | 1160 | ||
754 | dev_dbg(sfb->dev, "probing window %d\n", win_no); | 1161 | dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant); |
1162 | |||
1163 | init_waitqueue_head(&sfb->vsync_info.wait); | ||
755 | 1164 | ||
756 | palette_size = s3c_fb_win_pal_size(win_no); | 1165 | palette_size = variant->palette_sz * 4; |
757 | 1166 | ||
758 | fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + | 1167 | fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + |
759 | palette_size * sizeof(u32), sfb->dev); | 1168 | palette_size * sizeof(u32), sfb->dev); |
@@ -770,7 +1179,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
770 | WARN_ON(windata->win_mode.yres == 0); | 1179 | WARN_ON(windata->win_mode.yres == 0); |
771 | 1180 | ||
772 | win = fbinfo->par; | 1181 | win = fbinfo->par; |
1182 | *res = win; | ||
773 | var = &fbinfo->var; | 1183 | var = &fbinfo->var; |
1184 | win->variant = *variant; | ||
774 | win->fbinfo = fbinfo; | 1185 | win->fbinfo = fbinfo; |
775 | win->parent = sfb; | 1186 | win->parent = sfb; |
776 | win->windata = windata; | 1187 | win->windata = windata; |
@@ -784,7 +1195,24 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
784 | } | 1195 | } |
785 | 1196 | ||
786 | /* setup the r/b/g positions for the window's palette */ | 1197 | /* setup the r/b/g positions for the window's palette */ |
787 | s3c_fb_init_palette(win_no, &win->palette); | 1198 | if (win->variant.palette_16bpp) { |
1199 | /* Set RGB 5:6:5 as default */ | ||
1200 | win->palette.r.offset = 11; | ||
1201 | win->palette.r.length = 5; | ||
1202 | win->palette.g.offset = 5; | ||
1203 | win->palette.g.length = 6; | ||
1204 | win->palette.b.offset = 0; | ||
1205 | win->palette.b.length = 5; | ||
1206 | |||
1207 | } else { | ||
1208 | /* Set 8bpp or 8bpp and 1bit alpha */ | ||
1209 | win->palette.r.offset = 16; | ||
1210 | win->palette.r.length = 8; | ||
1211 | win->palette.g.offset = 8; | ||
1212 | win->palette.g.length = 8; | ||
1213 | win->palette.b.offset = 0; | ||
1214 | win->palette.b.length = 8; | ||
1215 | } | ||
788 | 1216 | ||
789 | /* setup the initial video mode from the window */ | 1217 | /* setup the initial video mode from the window */ |
790 | fb_videomode_to_var(&fbinfo->var, initmode); | 1218 | fb_videomode_to_var(&fbinfo->var, initmode); |
@@ -808,7 +1236,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
808 | 1236 | ||
809 | /* create initial colour map */ | 1237 | /* create initial colour map */ |
810 | 1238 | ||
811 | ret = fb_alloc_cmap(&fbinfo->cmap, s3c_fb_win_pal_size(win_no), 1); | 1239 | ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1); |
812 | if (ret == 0) | 1240 | if (ret == 0) |
813 | fb_set_cmap(&fbinfo->cmap, fbinfo); | 1241 | fb_set_cmap(&fbinfo->cmap, fbinfo); |
814 | else | 1242 | else |
@@ -826,7 +1254,6 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
826 | return ret; | 1254 | return ret; |
827 | } | 1255 | } |
828 | 1256 | ||
829 | *res = win; | ||
830 | dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); | 1257 | dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); |
831 | 1258 | ||
832 | return 0; | 1259 | return 0; |
@@ -842,18 +1269,19 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
842 | static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) | 1269 | static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) |
843 | { | 1270 | { |
844 | void __iomem *regs = sfb->regs; | 1271 | void __iomem *regs = sfb->regs; |
845 | 1272 | u32 reg; | |
846 | writel(0, regs + WINCON(win)); | 1273 | |
847 | writel(0xffffff, regs + WxKEYCONy(win, 0)); | 1274 | writel(0, regs + sfb->variant.wincon + (win * 4)); |
848 | writel(0xffffff, regs + WxKEYCONy(win, 1)); | 1275 | writel(0, regs + VIDOSD_A(win, sfb->variant)); |
849 | 1276 | writel(0, regs + VIDOSD_B(win, sfb->variant)); | |
850 | writel(0, regs + VIDOSD_A(win)); | 1277 | writel(0, regs + VIDOSD_C(win, sfb->variant)); |
851 | writel(0, regs + VIDOSD_B(win)); | 1278 | reg = readl(regs + SHADOWCON); |
852 | writel(0, regs + VIDOSD_C(win)); | 1279 | writel(reg & ~SHADOWCON_WINx_PROTECT(win), regs + SHADOWCON); |
853 | } | 1280 | } |
854 | 1281 | ||
855 | static int __devinit s3c_fb_probe(struct platform_device *pdev) | 1282 | static int __devinit s3c_fb_probe(struct platform_device *pdev) |
856 | { | 1283 | { |
1284 | struct s3c_fb_driverdata *fbdrv; | ||
857 | struct device *dev = &pdev->dev; | 1285 | struct device *dev = &pdev->dev; |
858 | struct s3c_fb_platdata *pd; | 1286 | struct s3c_fb_platdata *pd; |
859 | struct s3c_fb *sfb; | 1287 | struct s3c_fb *sfb; |
@@ -861,6 +1289,13 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
861 | int win; | 1289 | int win; |
862 | int ret = 0; | 1290 | int ret = 0; |
863 | 1291 | ||
1292 | fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data; | ||
1293 | |||
1294 | if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) { | ||
1295 | dev_err(dev, "too many windows, cannot attach\n"); | ||
1296 | return -EINVAL; | ||
1297 | } | ||
1298 | |||
864 | pd = pdev->dev.platform_data; | 1299 | pd = pdev->dev.platform_data; |
865 | if (!pd) { | 1300 | if (!pd) { |
866 | dev_err(dev, "no platform data specified\n"); | 1301 | dev_err(dev, "no platform data specified\n"); |
@@ -873,8 +1308,11 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
873 | return -ENOMEM; | 1308 | return -ENOMEM; |
874 | } | 1309 | } |
875 | 1310 | ||
1311 | dev_dbg(dev, "allocate new framebuffer %p\n", sfb); | ||
1312 | |||
876 | sfb->dev = dev; | 1313 | sfb->dev = dev; |
877 | sfb->pdata = pd; | 1314 | sfb->pdata = pd; |
1315 | sfb->variant = fbdrv->variant; | ||
878 | 1316 | ||
879 | sfb->bus_clk = clk_get(dev, "lcd"); | 1317 | sfb->bus_clk = clk_get(dev, "lcd"); |
880 | if (IS_ERR(sfb->bus_clk)) { | 1318 | if (IS_ERR(sfb->bus_clk)) { |
@@ -906,6 +1344,20 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
906 | goto err_req_region; | 1344 | goto err_req_region; |
907 | } | 1345 | } |
908 | 1346 | ||
1347 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
1348 | if (!res) { | ||
1349 | dev_err(dev, "failed to acquire irq resource\n"); | ||
1350 | ret = -ENOENT; | ||
1351 | goto err_ioremap; | ||
1352 | } | ||
1353 | sfb->irq_no = res->start; | ||
1354 | ret = request_irq(sfb->irq_no, s3c_fb_irq, | ||
1355 | 0, "s3c_fb", sfb); | ||
1356 | if (ret) { | ||
1357 | dev_err(dev, "irq request failed\n"); | ||
1358 | goto err_ioremap; | ||
1359 | } | ||
1360 | |||
909 | dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); | 1361 | dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); |
910 | 1362 | ||
911 | /* setup gpio and output polarity controls */ | 1363 | /* setup gpio and output polarity controls */ |
@@ -916,21 +1368,34 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
916 | 1368 | ||
917 | /* zero all windows before we do anything */ | 1369 | /* zero all windows before we do anything */ |
918 | 1370 | ||
919 | for (win = 0; win < S3C_FB_MAX_WIN; win++) | 1371 | for (win = 0; win < fbdrv->variant.nr_windows; win++) |
920 | s3c_fb_clear_win(sfb, win); | 1372 | s3c_fb_clear_win(sfb, win); |
921 | 1373 | ||
1374 | /* initialise colour key controls */ | ||
1375 | for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) { | ||
1376 | void __iomem *regs = sfb->regs + sfb->variant.keycon; | ||
1377 | |||
1378 | regs += (win * 8); | ||
1379 | writel(0xffffff, regs + WKEYCON0); | ||
1380 | writel(0xffffff, regs + WKEYCON1); | ||
1381 | } | ||
1382 | |||
922 | /* we have the register setup, start allocating framebuffers */ | 1383 | /* we have the register setup, start allocating framebuffers */ |
923 | 1384 | ||
924 | for (win = 0; win < S3C_FB_MAX_WIN; win++) { | 1385 | for (win = 0; win < fbdrv->variant.nr_windows; win++) { |
925 | if (!pd->win[win]) | 1386 | if (!pd->win[win]) |
926 | continue; | 1387 | continue; |
927 | 1388 | ||
928 | ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]); | 1389 | if (!pd->win[win]->win_mode.pixclock) |
1390 | s3c_fb_missing_pixclock(&pd->win[win]->win_mode); | ||
1391 | |||
1392 | ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], | ||
1393 | &sfb->windows[win]); | ||
929 | if (ret < 0) { | 1394 | if (ret < 0) { |
930 | dev_err(dev, "failed to create window %d\n", win); | 1395 | dev_err(dev, "failed to create window %d\n", win); |
931 | for (; win >= 0; win--) | 1396 | for (; win >= 0; win--) |
932 | s3c_fb_release_win(sfb, sfb->windows[win]); | 1397 | s3c_fb_release_win(sfb, sfb->windows[win]); |
933 | goto err_ioremap; | 1398 | goto err_irq; |
934 | } | 1399 | } |
935 | } | 1400 | } |
936 | 1401 | ||
@@ -938,6 +1403,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
938 | 1403 | ||
939 | return 0; | 1404 | return 0; |
940 | 1405 | ||
1406 | err_irq: | ||
1407 | free_irq(sfb->irq_no, sfb); | ||
1408 | |||
941 | err_ioremap: | 1409 | err_ioremap: |
942 | iounmap(sfb->regs); | 1410 | iounmap(sfb->regs); |
943 | 1411 | ||
@@ -970,6 +1438,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) | |||
970 | if (sfb->windows[win]) | 1438 | if (sfb->windows[win]) |
971 | s3c_fb_release_win(sfb, sfb->windows[win]); | 1439 | s3c_fb_release_win(sfb, sfb->windows[win]); |
972 | 1440 | ||
1441 | free_irq(sfb->irq_no, sfb); | ||
1442 | |||
973 | iounmap(sfb->regs); | 1443 | iounmap(sfb->regs); |
974 | 1444 | ||
975 | clk_disable(sfb->bus_clk); | 1445 | clk_disable(sfb->bus_clk); |
@@ -1016,9 +1486,17 @@ static int s3c_fb_resume(struct platform_device *pdev) | |||
1016 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1486 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
1017 | 1487 | ||
1018 | /* zero all windows before we do anything */ | 1488 | /* zero all windows before we do anything */ |
1019 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) | 1489 | for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++) |
1020 | s3c_fb_clear_win(sfb, win_no); | 1490 | s3c_fb_clear_win(sfb, win_no); |
1021 | 1491 | ||
1492 | for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { | ||
1493 | void __iomem *regs = sfb->regs + sfb->variant.keycon; | ||
1494 | |||
1495 | regs += (win_no * 8); | ||
1496 | writel(0xffffff, regs + WKEYCON0); | ||
1497 | writel(0xffffff, regs + WKEYCON1); | ||
1498 | } | ||
1499 | |||
1022 | /* restore framebuffers */ | 1500 | /* restore framebuffers */ |
1023 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { | 1501 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { |
1024 | win = sfb->windows[win_no]; | 1502 | win = sfb->windows[win_no]; |
@@ -1036,11 +1514,208 @@ static int s3c_fb_resume(struct platform_device *pdev) | |||
1036 | #define s3c_fb_resume NULL | 1514 | #define s3c_fb_resume NULL |
1037 | #endif | 1515 | #endif |
1038 | 1516 | ||
1517 | |||
1518 | #define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4)) | ||
1519 | #define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8)) | ||
1520 | |||
1521 | static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = { | ||
1522 | [0] = { | ||
1523 | .has_osd_c = 1, | ||
1524 | .osd_size_off = 0x8, | ||
1525 | .palette_sz = 256, | ||
1526 | .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24), | ||
1527 | }, | ||
1528 | [1] = { | ||
1529 | .has_osd_c = 1, | ||
1530 | .has_osd_d = 1, | ||
1531 | .osd_size_off = 0x12, | ||
1532 | .has_osd_alpha = 1, | ||
1533 | .palette_sz = 256, | ||
1534 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | | ||
1535 | VALID_BPP(18) | VALID_BPP(19) | | ||
1536 | VALID_BPP(24) | VALID_BPP(25)), | ||
1537 | }, | ||
1538 | [2] = { | ||
1539 | .has_osd_c = 1, | ||
1540 | .has_osd_d = 1, | ||
1541 | .osd_size_off = 0x12, | ||
1542 | .has_osd_alpha = 1, | ||
1543 | .palette_sz = 16, | ||
1544 | .palette_16bpp = 1, | ||
1545 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | | ||
1546 | VALID_BPP(18) | VALID_BPP(19) | | ||
1547 | VALID_BPP(24) | VALID_BPP(25)), | ||
1548 | }, | ||
1549 | [3] = { | ||
1550 | .has_osd_c = 1, | ||
1551 | .has_osd_alpha = 1, | ||
1552 | .palette_sz = 16, | ||
1553 | .palette_16bpp = 1, | ||
1554 | .valid_bpp = (VALID_BPP124 | VALID_BPP(16) | | ||
1555 | VALID_BPP(18) | VALID_BPP(19) | | ||
1556 | VALID_BPP(24) | VALID_BPP(25)), | ||
1557 | }, | ||
1558 | [4] = { | ||
1559 | .has_osd_c = 1, | ||
1560 | .has_osd_alpha = 1, | ||
1561 | .palette_sz = 4, | ||
1562 | .palette_16bpp = 1, | ||
1563 | .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) | | ||
1564 | VALID_BPP(16) | VALID_BPP(18) | | ||
1565 | VALID_BPP(24) | VALID_BPP(25)), | ||
1566 | }, | ||
1567 | }; | ||
1568 | |||
1569 | static struct s3c_fb_driverdata s3c_fb_data_64xx = { | ||
1570 | .variant = { | ||
1571 | .nr_windows = 5, | ||
1572 | .vidtcon = VIDTCON0, | ||
1573 | .wincon = WINCON(0), | ||
1574 | .winmap = WINxMAP(0), | ||
1575 | .keycon = WKEYCON, | ||
1576 | .osd = VIDOSD_BASE, | ||
1577 | .osd_stride = 16, | ||
1578 | .buf_start = VIDW_BUF_START(0), | ||
1579 | .buf_size = VIDW_BUF_SIZE(0), | ||
1580 | .buf_end = VIDW_BUF_END(0), | ||
1581 | |||
1582 | .palette = { | ||
1583 | [0] = 0x400, | ||
1584 | [1] = 0x800, | ||
1585 | [2] = 0x300, | ||
1586 | [3] = 0x320, | ||
1587 | [4] = 0x340, | ||
1588 | }, | ||
1589 | |||
1590 | .has_prtcon = 1, | ||
1591 | }, | ||
1592 | .win[0] = &s3c_fb_data_64xx_wins[0], | ||
1593 | .win[1] = &s3c_fb_data_64xx_wins[1], | ||
1594 | .win[2] = &s3c_fb_data_64xx_wins[2], | ||
1595 | .win[3] = &s3c_fb_data_64xx_wins[3], | ||
1596 | .win[4] = &s3c_fb_data_64xx_wins[4], | ||
1597 | }; | ||
1598 | |||
1599 | static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = { | ||
1600 | .variant = { | ||
1601 | .nr_windows = 5, | ||
1602 | .vidtcon = VIDTCON0, | ||
1603 | .wincon = WINCON(0), | ||
1604 | .winmap = WINxMAP(0), | ||
1605 | .keycon = WKEYCON, | ||
1606 | .osd = VIDOSD_BASE, | ||
1607 | .osd_stride = 16, | ||
1608 | .buf_start = VIDW_BUF_START(0), | ||
1609 | .buf_size = VIDW_BUF_SIZE(0), | ||
1610 | .buf_end = VIDW_BUF_END(0), | ||
1611 | |||
1612 | .palette = { | ||
1613 | [0] = 0x2400, | ||
1614 | [1] = 0x2800, | ||
1615 | [2] = 0x2c00, | ||
1616 | [3] = 0x3000, | ||
1617 | [4] = 0x3400, | ||
1618 | }, | ||
1619 | |||
1620 | .has_prtcon = 1, | ||
1621 | }, | ||
1622 | .win[0] = &s3c_fb_data_64xx_wins[0], | ||
1623 | .win[1] = &s3c_fb_data_64xx_wins[1], | ||
1624 | .win[2] = &s3c_fb_data_64xx_wins[2], | ||
1625 | .win[3] = &s3c_fb_data_64xx_wins[3], | ||
1626 | .win[4] = &s3c_fb_data_64xx_wins[4], | ||
1627 | }; | ||
1628 | |||
1629 | static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = { | ||
1630 | .variant = { | ||
1631 | .nr_windows = 5, | ||
1632 | .vidtcon = VIDTCON0, | ||
1633 | .wincon = WINCON(0), | ||
1634 | .winmap = WINxMAP(0), | ||
1635 | .keycon = WKEYCON, | ||
1636 | .osd = VIDOSD_BASE, | ||
1637 | .osd_stride = 16, | ||
1638 | .buf_start = VIDW_BUF_START(0), | ||
1639 | .buf_size = VIDW_BUF_SIZE(0), | ||
1640 | .buf_end = VIDW_BUF_END(0), | ||
1641 | |||
1642 | .palette = { | ||
1643 | [0] = 0x2400, | ||
1644 | [1] = 0x2800, | ||
1645 | [2] = 0x2c00, | ||
1646 | [3] = 0x3000, | ||
1647 | [4] = 0x3400, | ||
1648 | }, | ||
1649 | |||
1650 | .has_shadowcon = 1, | ||
1651 | }, | ||
1652 | .win[0] = &s3c_fb_data_64xx_wins[0], | ||
1653 | .win[1] = &s3c_fb_data_64xx_wins[1], | ||
1654 | .win[2] = &s3c_fb_data_64xx_wins[2], | ||
1655 | .win[3] = &s3c_fb_data_64xx_wins[3], | ||
1656 | .win[4] = &s3c_fb_data_64xx_wins[4], | ||
1657 | }; | ||
1658 | |||
1659 | /* S3C2443/S3C2416 style hardware */ | ||
1660 | static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = { | ||
1661 | .variant = { | ||
1662 | .nr_windows = 2, | ||
1663 | .is_2443 = 1, | ||
1664 | |||
1665 | .vidtcon = 0x08, | ||
1666 | .wincon = 0x14, | ||
1667 | .winmap = 0xd0, | ||
1668 | .keycon = 0xb0, | ||
1669 | .osd = 0x28, | ||
1670 | .osd_stride = 12, | ||
1671 | .buf_start = 0x64, | ||
1672 | .buf_size = 0x94, | ||
1673 | .buf_end = 0x7c, | ||
1674 | |||
1675 | .palette = { | ||
1676 | [0] = 0x400, | ||
1677 | [1] = 0x800, | ||
1678 | }, | ||
1679 | }, | ||
1680 | .win[0] = &(struct s3c_fb_win_variant) { | ||
1681 | .palette_sz = 256, | ||
1682 | .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24), | ||
1683 | }, | ||
1684 | .win[1] = &(struct s3c_fb_win_variant) { | ||
1685 | .has_osd_c = 1, | ||
1686 | .has_osd_alpha = 1, | ||
1687 | .palette_sz = 256, | ||
1688 | .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | | ||
1689 | VALID_BPP(18) | VALID_BPP(19) | | ||
1690 | VALID_BPP(24) | VALID_BPP(25) | | ||
1691 | VALID_BPP(28)), | ||
1692 | }, | ||
1693 | }; | ||
1694 | |||
1695 | static struct platform_device_id s3c_fb_driver_ids[] = { | ||
1696 | { | ||
1697 | .name = "s3c-fb", | ||
1698 | .driver_data = (unsigned long)&s3c_fb_data_64xx, | ||
1699 | }, { | ||
1700 | .name = "s5pc100-fb", | ||
1701 | .driver_data = (unsigned long)&s3c_fb_data_s5pc100, | ||
1702 | }, { | ||
1703 | .name = "s5pv210-fb", | ||
1704 | .driver_data = (unsigned long)&s3c_fb_data_s5pv210, | ||
1705 | }, { | ||
1706 | .name = "s3c2443-fb", | ||
1707 | .driver_data = (unsigned long)&s3c_fb_data_s3c2443, | ||
1708 | }, | ||
1709 | {}, | ||
1710 | }; | ||
1711 | MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); | ||
1712 | |||
1039 | static struct platform_driver s3c_fb_driver = { | 1713 | static struct platform_driver s3c_fb_driver = { |
1040 | .probe = s3c_fb_probe, | 1714 | .probe = s3c_fb_probe, |
1041 | .remove = __devexit_p(s3c_fb_remove), | 1715 | .remove = __devexit_p(s3c_fb_remove), |
1042 | .suspend = s3c_fb_suspend, | 1716 | .suspend = s3c_fb_suspend, |
1043 | .resume = s3c_fb_resume, | 1717 | .resume = s3c_fb_resume, |
1718 | .id_table = s3c_fb_driver_ids, | ||
1044 | .driver = { | 1719 | .driver = { |
1045 | .name = "s3c-fb", | 1720 | .name = "s3c-fb", |
1046 | .owner = THIS_MODULE, | 1721 | .owner = THIS_MODULE, |
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c new file mode 100644 index 000000000000..5699ce0c1780 --- /dev/null +++ b/drivers/video/sh_mipi_dsi.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * Renesas SH-mobile MIPI DSI support | ||
3 | * | ||
4 | * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
5 | * | ||
6 | * This is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of version 2 of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/types.h> | ||
19 | |||
20 | #include <video/mipi_display.h> | ||
21 | #include <video/sh_mipi_dsi.h> | ||
22 | #include <video/sh_mobile_lcdc.h> | ||
23 | |||
24 | #define CMTSRTCTR 0x80d0 | ||
25 | #define CMTSRTREQ 0x8070 | ||
26 | |||
27 | #define DSIINTE 0x0060 | ||
28 | |||
29 | /* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ | ||
30 | #define MAX_SH_MIPI_DSI 2 | ||
31 | |||
32 | struct sh_mipi { | ||
33 | void __iomem *base; | ||
34 | struct clk *dsit_clk; | ||
35 | struct clk *dsip_clk; | ||
36 | }; | ||
37 | |||
38 | static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; | ||
39 | |||
40 | /* Protect the above array */ | ||
41 | static DEFINE_MUTEX(array_lock); | ||
42 | |||
43 | static struct sh_mipi *sh_mipi_by_handle(int handle) | ||
44 | { | ||
45 | if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0) | ||
46 | return NULL; | ||
47 | |||
48 | return mipi_dsi[handle]; | ||
49 | } | ||
50 | |||
51 | static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd, | ||
52 | u8 cmd, u8 param) | ||
53 | { | ||
54 | u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8); | ||
55 | int cnt = 100; | ||
56 | |||
57 | /* transmit a short packet to LCD panel */ | ||
58 | iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */ | ||
59 | iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */ | ||
60 | |||
61 | while ((ioread32(mipi->base + 0x8070) & 1) && --cnt) | ||
62 | udelay(1); | ||
63 | |||
64 | return cnt ? 0 : -ETIMEDOUT; | ||
65 | } | ||
66 | |||
67 | #define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \ | ||
68 | -EINVAL : (c) - 1) | ||
69 | |||
70 | static int sh_mipi_dcs(int handle, u8 cmd) | ||
71 | { | ||
72 | struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); | ||
73 | if (!mipi) | ||
74 | return -ENODEV; | ||
75 | return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0); | ||
76 | } | ||
77 | |||
78 | static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param) | ||
79 | { | ||
80 | struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); | ||
81 | if (!mipi) | ||
82 | return -ENODEV; | ||
83 | return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd, | ||
84 | param); | ||
85 | } | ||
86 | |||
87 | static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable) | ||
88 | { | ||
89 | /* | ||
90 | * enable LCDC data tx, transition to LPS after completion of each HS | ||
91 | * packet | ||
92 | */ | ||
93 | iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */ | ||
94 | } | ||
95 | |||
96 | static void sh_mipi_shutdown(struct platform_device *pdev) | ||
97 | { | ||
98 | struct sh_mipi *mipi = platform_get_drvdata(pdev); | ||
99 | |||
100 | sh_mipi_dsi_enable(mipi, false); | ||
101 | } | ||
102 | |||
103 | static void mipi_display_on(void *arg, struct fb_info *info) | ||
104 | { | ||
105 | struct sh_mipi *mipi = arg; | ||
106 | |||
107 | sh_mipi_dsi_enable(mipi, true); | ||
108 | } | ||
109 | |||
110 | static void mipi_display_off(void *arg) | ||
111 | { | ||
112 | struct sh_mipi *mipi = arg; | ||
113 | |||
114 | sh_mipi_dsi_enable(mipi, false); | ||
115 | } | ||
116 | |||
117 | static int __init sh_mipi_setup(struct sh_mipi *mipi, | ||
118 | struct sh_mipi_dsi_info *pdata) | ||
119 | { | ||
120 | void __iomem *base = mipi->base; | ||
121 | struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; | ||
122 | u32 pctype, datatype, pixfmt; | ||
123 | u32 linelength; | ||
124 | bool yuv; | ||
125 | |||
126 | /* Select data format */ | ||
127 | switch (pdata->data_format) { | ||
128 | case MIPI_RGB888: | ||
129 | pctype = 0; | ||
130 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | ||
131 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
132 | linelength = ch->lcd_cfg.xres * 3; | ||
133 | yuv = false; | ||
134 | break; | ||
135 | case MIPI_RGB565: | ||
136 | pctype = 1; | ||
137 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | ||
138 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
139 | linelength = ch->lcd_cfg.xres * 2; | ||
140 | yuv = false; | ||
141 | break; | ||
142 | case MIPI_RGB666_LP: | ||
143 | pctype = 2; | ||
144 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | ||
145 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
146 | linelength = ch->lcd_cfg.xres * 3; | ||
147 | yuv = false; | ||
148 | break; | ||
149 | case MIPI_RGB666: | ||
150 | pctype = 3; | ||
151 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | ||
152 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | ||
153 | linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; | ||
154 | yuv = false; | ||
155 | break; | ||
156 | case MIPI_BGR888: | ||
157 | pctype = 8; | ||
158 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | ||
159 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
160 | linelength = ch->lcd_cfg.xres * 3; | ||
161 | yuv = false; | ||
162 | break; | ||
163 | case MIPI_BGR565: | ||
164 | pctype = 9; | ||
165 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | ||
166 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
167 | linelength = ch->lcd_cfg.xres * 2; | ||
168 | yuv = false; | ||
169 | break; | ||
170 | case MIPI_BGR666_LP: | ||
171 | pctype = 0xa; | ||
172 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | ||
173 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
174 | linelength = ch->lcd_cfg.xres * 3; | ||
175 | yuv = false; | ||
176 | break; | ||
177 | case MIPI_BGR666: | ||
178 | pctype = 0xb; | ||
179 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | ||
180 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | ||
181 | linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; | ||
182 | yuv = false; | ||
183 | break; | ||
184 | case MIPI_YUYV: | ||
185 | pctype = 4; | ||
186 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | ||
187 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
188 | linelength = ch->lcd_cfg.xres * 2; | ||
189 | yuv = true; | ||
190 | break; | ||
191 | case MIPI_UYVY: | ||
192 | pctype = 5; | ||
193 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | ||
194 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
195 | linelength = ch->lcd_cfg.xres * 2; | ||
196 | yuv = true; | ||
197 | break; | ||
198 | case MIPI_YUV420_L: | ||
199 | pctype = 6; | ||
200 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | ||
201 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | ||
202 | linelength = (ch->lcd_cfg.xres * 12 + 7) / 8; | ||
203 | yuv = true; | ||
204 | break; | ||
205 | case MIPI_YUV420: | ||
206 | pctype = 7; | ||
207 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | ||
208 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | ||
209 | /* Length of U/V line */ | ||
210 | linelength = (ch->lcd_cfg.xres + 1) / 2; | ||
211 | yuv = true; | ||
212 | break; | ||
213 | default: | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | if ((yuv && ch->interface_type != YUV422) || | ||
218 | (!yuv && ch->interface_type != RGB24)) | ||
219 | return -EINVAL; | ||
220 | |||
221 | /* reset DSI link */ | ||
222 | iowrite32(0x00000001, base); /* SYSCTRL */ | ||
223 | /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ | ||
224 | udelay(50); | ||
225 | iowrite32(0x00000000, base); /* SYSCTRL */ | ||
226 | |||
227 | /* setup DSI link */ | ||
228 | |||
229 | /* | ||
230 | * Default = ULPS enable | | ||
231 | * Contention detection enabled | | ||
232 | * EoT packet transmission enable | | ||
233 | * CRC check enable | | ||
234 | * ECC check enable | ||
235 | * additionally enable first two lanes | ||
236 | */ | ||
237 | iowrite32(0x00003703, base + 0x04); /* SYSCONF */ | ||
238 | /* | ||
239 | * T_wakeup = 0x7000 | ||
240 | * T_hs-trail = 3 | ||
241 | * T_hs-prepare = 3 | ||
242 | * T_clk-trail = 3 | ||
243 | * T_clk-prepare = 2 | ||
244 | */ | ||
245 | iowrite32(0x70003332, base + 0x08); /* TIMSET */ | ||
246 | /* no responses requested */ | ||
247 | iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */ | ||
248 | /* request response to packets of type 0x28 */ | ||
249 | iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */ | ||
250 | /* High-speed transmission timeout, default 0xffffffff */ | ||
251 | iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */ | ||
252 | /* LP reception timeout, default 0xffffffff */ | ||
253 | iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */ | ||
254 | /* Turn-around timeout, default 0xffffffff */ | ||
255 | iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */ | ||
256 | /* Peripheral reset timeout, default 0xffffffff */ | ||
257 | iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */ | ||
258 | /* Enable timeout counters */ | ||
259 | iowrite32(0x00000f00, base + 0x30); /* DSICTRL */ | ||
260 | /* Interrupts not used, disable all */ | ||
261 | iowrite32(0, base + DSIINTE); | ||
262 | /* DSI-Tx bias on */ | ||
263 | iowrite32(0x00000001, base + 0x70); /* PHYCTRL */ | ||
264 | udelay(200); | ||
265 | /* Deassert resets, power on, set multiplier */ | ||
266 | iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */ | ||
267 | |||
268 | /* setup l-bridge */ | ||
269 | |||
270 | /* | ||
271 | * Enable transmission of all packets, | ||
272 | * transmit LPS after each HS packet completion | ||
273 | */ | ||
274 | iowrite32(0x00000006, base + 0x8000); /* DTCTR */ | ||
275 | /* VSYNC width = 2 (<< 17) */ | ||
276 | iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */ | ||
277 | /* | ||
278 | * Non-burst mode with sync pulses: VSE and HSE are output, | ||
279 | * HSA period allowed, no commands in LP | ||
280 | */ | ||
281 | iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ | ||
282 | /* | ||
283 | * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see | ||
284 | * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default | ||
285 | * (unused, since VMCTR2[HSABM] = 0) | ||
286 | */ | ||
287 | iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ | ||
288 | |||
289 | msleep(5); | ||
290 | |||
291 | /* setup LCD panel */ | ||
292 | |||
293 | /* cf. drivers/video/omap/lcd_mipid.c */ | ||
294 | sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE); | ||
295 | msleep(120); | ||
296 | /* | ||
297 | * [7] - Page Address Mode | ||
298 | * [6] - Column Address Mode | ||
299 | * [5] - Page / Column Address Mode | ||
300 | * [4] - Display Device Line Refresh Order | ||
301 | * [3] - RGB/BGR Order | ||
302 | * [2] - Display Data Latch Data Order | ||
303 | * [1] - Flip Horizontal | ||
304 | * [0] - Flip Vertical | ||
305 | */ | ||
306 | sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00); | ||
307 | /* cf. set_data_lines() */ | ||
308 | sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT, | ||
309 | pixfmt << 4); | ||
310 | sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int __init sh_mipi_probe(struct platform_device *pdev) | ||
316 | { | ||
317 | struct sh_mipi *mipi; | ||
318 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; | ||
319 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
320 | unsigned long rate, f_current; | ||
321 | int idx = pdev->id, ret; | ||
322 | char dsip_clk[] = "dsi.p_clk"; | ||
323 | |||
324 | if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) | ||
325 | return -ENODEV; | ||
326 | |||
327 | mutex_lock(&array_lock); | ||
328 | if (idx < 0) | ||
329 | for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++) | ||
330 | ; | ||
331 | |||
332 | if (idx == ARRAY_SIZE(mipi_dsi)) { | ||
333 | ret = -EBUSY; | ||
334 | goto efindslot; | ||
335 | } | ||
336 | |||
337 | mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); | ||
338 | if (!mipi) { | ||
339 | ret = -ENOMEM; | ||
340 | goto ealloc; | ||
341 | } | ||
342 | |||
343 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | ||
344 | dev_err(&pdev->dev, "MIPI register region already claimed\n"); | ||
345 | ret = -EBUSY; | ||
346 | goto ereqreg; | ||
347 | } | ||
348 | |||
349 | mipi->base = ioremap(res->start, resource_size(res)); | ||
350 | if (!mipi->base) { | ||
351 | ret = -ENOMEM; | ||
352 | goto emap; | ||
353 | } | ||
354 | |||
355 | mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); | ||
356 | if (IS_ERR(mipi->dsit_clk)) { | ||
357 | ret = PTR_ERR(mipi->dsit_clk); | ||
358 | goto eclktget; | ||
359 | } | ||
360 | |||
361 | f_current = clk_get_rate(mipi->dsit_clk); | ||
362 | /* 80MHz required by the datasheet */ | ||
363 | rate = clk_round_rate(mipi->dsit_clk, 80000000); | ||
364 | if (rate > 0 && rate != f_current) | ||
365 | ret = clk_set_rate(mipi->dsit_clk, rate); | ||
366 | else | ||
367 | ret = rate; | ||
368 | if (ret < 0) | ||
369 | goto esettrate; | ||
370 | |||
371 | dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); | ||
372 | |||
373 | sprintf(dsip_clk, "dsi%1.1dp_clk", idx); | ||
374 | mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk); | ||
375 | if (IS_ERR(mipi->dsip_clk)) { | ||
376 | ret = PTR_ERR(mipi->dsip_clk); | ||
377 | goto eclkpget; | ||
378 | } | ||
379 | |||
380 | f_current = clk_get_rate(mipi->dsip_clk); | ||
381 | /* Between 10 and 50MHz */ | ||
382 | rate = clk_round_rate(mipi->dsip_clk, 24000000); | ||
383 | if (rate > 0 && rate != f_current) | ||
384 | ret = clk_set_rate(mipi->dsip_clk, rate); | ||
385 | else | ||
386 | ret = rate; | ||
387 | if (ret < 0) | ||
388 | goto esetprate; | ||
389 | |||
390 | dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate); | ||
391 | |||
392 | msleep(10); | ||
393 | |||
394 | ret = clk_enable(mipi->dsit_clk); | ||
395 | if (ret < 0) | ||
396 | goto eclkton; | ||
397 | |||
398 | ret = clk_enable(mipi->dsip_clk); | ||
399 | if (ret < 0) | ||
400 | goto eclkpon; | ||
401 | |||
402 | mipi_dsi[idx] = mipi; | ||
403 | |||
404 | ret = sh_mipi_setup(mipi, pdata); | ||
405 | if (ret < 0) | ||
406 | goto emipisetup; | ||
407 | |||
408 | mutex_unlock(&array_lock); | ||
409 | platform_set_drvdata(pdev, mipi); | ||
410 | |||
411 | /* Set up LCDC callbacks */ | ||
412 | pdata->lcd_chan->board_cfg.board_data = mipi; | ||
413 | pdata->lcd_chan->board_cfg.display_on = mipi_display_on; | ||
414 | pdata->lcd_chan->board_cfg.display_off = mipi_display_off; | ||
415 | |||
416 | return 0; | ||
417 | |||
418 | emipisetup: | ||
419 | mipi_dsi[idx] = NULL; | ||
420 | clk_disable(mipi->dsip_clk); | ||
421 | eclkpon: | ||
422 | clk_disable(mipi->dsit_clk); | ||
423 | eclkton: | ||
424 | esetprate: | ||
425 | clk_put(mipi->dsip_clk); | ||
426 | eclkpget: | ||
427 | esettrate: | ||
428 | clk_put(mipi->dsit_clk); | ||
429 | eclktget: | ||
430 | iounmap(mipi->base); | ||
431 | emap: | ||
432 | release_mem_region(res->start, resource_size(res)); | ||
433 | ereqreg: | ||
434 | kfree(mipi); | ||
435 | ealloc: | ||
436 | efindslot: | ||
437 | mutex_unlock(&array_lock); | ||
438 | |||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | static int __exit sh_mipi_remove(struct platform_device *pdev) | ||
443 | { | ||
444 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; | ||
445 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
446 | struct sh_mipi *mipi = platform_get_drvdata(pdev); | ||
447 | int i, ret; | ||
448 | |||
449 | mutex_lock(&array_lock); | ||
450 | |||
451 | for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++) | ||
452 | ; | ||
453 | |||
454 | if (i == ARRAY_SIZE(mipi_dsi)) { | ||
455 | ret = -EINVAL; | ||
456 | } else { | ||
457 | ret = 0; | ||
458 | mipi_dsi[i] = NULL; | ||
459 | } | ||
460 | |||
461 | mutex_unlock(&array_lock); | ||
462 | |||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | |||
466 | pdata->lcd_chan->board_cfg.display_on = NULL; | ||
467 | pdata->lcd_chan->board_cfg.display_off = NULL; | ||
468 | pdata->lcd_chan->board_cfg.board_data = NULL; | ||
469 | |||
470 | clk_disable(mipi->dsip_clk); | ||
471 | clk_disable(mipi->dsit_clk); | ||
472 | clk_put(mipi->dsit_clk); | ||
473 | clk_put(mipi->dsip_clk); | ||
474 | iounmap(mipi->base); | ||
475 | if (res) | ||
476 | release_mem_region(res->start, resource_size(res)); | ||
477 | platform_set_drvdata(pdev, NULL); | ||
478 | kfree(mipi); | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static struct platform_driver sh_mipi_driver = { | ||
484 | .remove = __exit_p(sh_mipi_remove), | ||
485 | .shutdown = sh_mipi_shutdown, | ||
486 | .driver = { | ||
487 | .name = "sh-mipi-dsi", | ||
488 | }, | ||
489 | }; | ||
490 | |||
491 | static int __init sh_mipi_init(void) | ||
492 | { | ||
493 | return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe); | ||
494 | } | ||
495 | module_init(sh_mipi_init); | ||
496 | |||
497 | static void __exit sh_mipi_exit(void) | ||
498 | { | ||
499 | platform_driver_unregister(&sh_mipi_driver); | ||
500 | } | ||
501 | module_exit(sh_mipi_exit); | ||
502 | |||
503 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
504 | MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver"); | ||
505 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c new file mode 100644 index 000000000000..2fde08cc66bf --- /dev/null +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -0,0 +1,1028 @@ | |||
1 | /* | ||
2 | * SH-Mobile High-Definition Multimedia Interface (HDMI) driver | ||
3 | * for SLISHDMI13T and SLIPHDMIT IP cores | ||
4 | * | ||
5 | * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
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/clk.h> | ||
13 | #include <linux/console.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/pm_runtime.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #include <video/sh_mobile_hdmi.h> | ||
27 | #include <video/sh_mobile_lcdc.h> | ||
28 | |||
29 | #define HDMI_SYSTEM_CTRL 0x00 /* System control */ | ||
30 | #define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, | ||
31 | bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ | ||
32 | #define HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8 0x02 /* bits 15..8 of 20-bit N for Audio Clock Regeneration packet */ | ||
33 | #define HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0 0x03 /* bits 7..0 of 20-bit N for Audio Clock Regeneration packet */ | ||
34 | #define HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS 0x04 /* SPDIF audio sampling frequency, | ||
35 | bits 19..16 of Internal CTS */ | ||
36 | #define HDMI_INTERNAL_CTS_15_8 0x05 /* bits 15..8 of Internal CTS */ | ||
37 | #define HDMI_INTERNAL_CTS_7_0 0x06 /* bits 7..0 of Internal CTS */ | ||
38 | #define HDMI_EXTERNAL_CTS_19_16 0x07 /* External CTS */ | ||
39 | #define HDMI_EXTERNAL_CTS_15_8 0x08 /* External CTS */ | ||
40 | #define HDMI_EXTERNAL_CTS_7_0 0x09 /* External CTS */ | ||
41 | #define HDMI_AUDIO_SETTING_1 0x0A /* Audio setting.1 */ | ||
42 | #define HDMI_AUDIO_SETTING_2 0x0B /* Audio setting.2 */ | ||
43 | #define HDMI_I2S_AUDIO_SET 0x0C /* I2S audio setting */ | ||
44 | #define HDMI_DSD_AUDIO_SET 0x0D /* DSD audio setting */ | ||
45 | #define HDMI_DEBUG_MONITOR_1 0x0E /* Debug monitor.1 */ | ||
46 | #define HDMI_DEBUG_MONITOR_2 0x0F /* Debug monitor.2 */ | ||
47 | #define HDMI_I2S_INPUT_PIN_SWAP 0x10 /* I2S input pin swap */ | ||
48 | #define HDMI_AUDIO_STATUS_BITS_SETTING_1 0x11 /* Audio status bits setting.1 */ | ||
49 | #define HDMI_AUDIO_STATUS_BITS_SETTING_2 0x12 /* Audio status bits setting.2 */ | ||
50 | #define HDMI_CATEGORY_CODE 0x13 /* Category code */ | ||
51 | #define HDMI_SOURCE_NUM_AUDIO_WORD_LEN 0x14 /* Source number/Audio word length */ | ||
52 | #define HDMI_AUDIO_VIDEO_SETTING_1 0x15 /* Audio/Video setting.1 */ | ||
53 | #define HDMI_VIDEO_SETTING_1 0x16 /* Video setting.1 */ | ||
54 | #define HDMI_DEEP_COLOR_MODES 0x17 /* Deep Color Modes */ | ||
55 | |||
56 | /* 12 16- and 10-bit Color space conversion parameters: 0x18..0x2f */ | ||
57 | #define HDMI_COLOR_SPACE_CONVERSION_PARAMETERS 0x18 | ||
58 | |||
59 | #define HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS 0x30 /* External video parameter settings */ | ||
60 | #define HDMI_EXTERNAL_H_TOTAL_7_0 0x31 /* External horizontal total (LSB) */ | ||
61 | #define HDMI_EXTERNAL_H_TOTAL_11_8 0x32 /* External horizontal total (MSB) */ | ||
62 | #define HDMI_EXTERNAL_H_BLANK_7_0 0x33 /* External horizontal blank (LSB) */ | ||
63 | #define HDMI_EXTERNAL_H_BLANK_9_8 0x34 /* External horizontal blank (MSB) */ | ||
64 | #define HDMI_EXTERNAL_H_DELAY_7_0 0x35 /* External horizontal delay (LSB) */ | ||
65 | #define HDMI_EXTERNAL_H_DELAY_9_8 0x36 /* External horizontal delay (MSB) */ | ||
66 | #define HDMI_EXTERNAL_H_DURATION_7_0 0x37 /* External horizontal duration (LSB) */ | ||
67 | #define HDMI_EXTERNAL_H_DURATION_9_8 0x38 /* External horizontal duration (MSB) */ | ||
68 | #define HDMI_EXTERNAL_V_TOTAL_7_0 0x39 /* External vertical total (LSB) */ | ||
69 | #define HDMI_EXTERNAL_V_TOTAL_9_8 0x3A /* External vertical total (MSB) */ | ||
70 | #define HDMI_AUDIO_VIDEO_SETTING_2 0x3B /* Audio/Video setting.2 */ | ||
71 | #define HDMI_EXTERNAL_V_BLANK 0x3D /* External vertical blank */ | ||
72 | #define HDMI_EXTERNAL_V_DELAY 0x3E /* External vertical delay */ | ||
73 | #define HDMI_EXTERNAL_V_DURATION 0x3F /* External vertical duration */ | ||
74 | #define HDMI_CTRL_PKT_MANUAL_SEND_CONTROL 0x40 /* Control packet manual send control */ | ||
75 | #define HDMI_CTRL_PKT_AUTO_SEND 0x41 /* Control packet auto send with VSYNC control */ | ||
76 | #define HDMI_AUTO_CHECKSUM_OPTION 0x42 /* Auto checksum option */ | ||
77 | #define HDMI_VIDEO_SETTING_2 0x45 /* Video setting.2 */ | ||
78 | #define HDMI_OUTPUT_OPTION 0x46 /* Output option */ | ||
79 | #define HDMI_SLIPHDMIT_PARAM_OPTION 0x51 /* SLIPHDMIT parameter option */ | ||
80 | #define HDMI_HSYNC_PMENT_AT_EMB_7_0 0x52 /* HSYNC placement at embedded sync (LSB) */ | ||
81 | #define HDMI_HSYNC_PMENT_AT_EMB_15_8 0x53 /* HSYNC placement at embedded sync (MSB) */ | ||
82 | #define HDMI_VSYNC_PMENT_AT_EMB_7_0 0x54 /* VSYNC placement at embedded sync (LSB) */ | ||
83 | #define HDMI_VSYNC_PMENT_AT_EMB_14_8 0x55 /* VSYNC placement at embedded sync (MSB) */ | ||
84 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_1 0x56 /* SLIPHDMIT parameter settings.1 */ | ||
85 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_2 0x57 /* SLIPHDMIT parameter settings.2 */ | ||
86 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_3 0x58 /* SLIPHDMIT parameter settings.3 */ | ||
87 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_5 0x59 /* SLIPHDMIT parameter settings.5 */ | ||
88 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_6 0x5A /* SLIPHDMIT parameter settings.6 */ | ||
89 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_7 0x5B /* SLIPHDMIT parameter settings.7 */ | ||
90 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_8 0x5C /* SLIPHDMIT parameter settings.8 */ | ||
91 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_9 0x5D /* SLIPHDMIT parameter settings.9 */ | ||
92 | #define HDMI_SLIPHDMIT_PARAM_SETTINGS_10 0x5E /* SLIPHDMIT parameter settings.10 */ | ||
93 | #define HDMI_CTRL_PKT_BUF_INDEX 0x5F /* Control packet buffer index */ | ||
94 | #define HDMI_CTRL_PKT_BUF_ACCESS_HB0 0x60 /* Control packet data buffer access window - HB0 */ | ||
95 | #define HDMI_CTRL_PKT_BUF_ACCESS_HB1 0x61 /* Control packet data buffer access window - HB1 */ | ||
96 | #define HDMI_CTRL_PKT_BUF_ACCESS_HB2 0x62 /* Control packet data buffer access window - HB2 */ | ||
97 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB0 0x63 /* Control packet data buffer access window - PB0 */ | ||
98 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB1 0x64 /* Control packet data buffer access window - PB1 */ | ||
99 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB2 0x65 /* Control packet data buffer access window - PB2 */ | ||
100 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB3 0x66 /* Control packet data buffer access window - PB3 */ | ||
101 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB4 0x67 /* Control packet data buffer access window - PB4 */ | ||
102 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB5 0x68 /* Control packet data buffer access window - PB5 */ | ||
103 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB6 0x69 /* Control packet data buffer access window - PB6 */ | ||
104 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB7 0x6A /* Control packet data buffer access window - PB7 */ | ||
105 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB8 0x6B /* Control packet data buffer access window - PB8 */ | ||
106 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB9 0x6C /* Control packet data buffer access window - PB9 */ | ||
107 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB10 0x6D /* Control packet data buffer access window - PB10 */ | ||
108 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB11 0x6E /* Control packet data buffer access window - PB11 */ | ||
109 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB12 0x6F /* Control packet data buffer access window - PB12 */ | ||
110 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB13 0x70 /* Control packet data buffer access window - PB13 */ | ||
111 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB14 0x71 /* Control packet data buffer access window - PB14 */ | ||
112 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB15 0x72 /* Control packet data buffer access window - PB15 */ | ||
113 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB16 0x73 /* Control packet data buffer access window - PB16 */ | ||
114 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB17 0x74 /* Control packet data buffer access window - PB17 */ | ||
115 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB18 0x75 /* Control packet data buffer access window - PB18 */ | ||
116 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB19 0x76 /* Control packet data buffer access window - PB19 */ | ||
117 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB20 0x77 /* Control packet data buffer access window - PB20 */ | ||
118 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB21 0x78 /* Control packet data buffer access window - PB21 */ | ||
119 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB22 0x79 /* Control packet data buffer access window - PB22 */ | ||
120 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB23 0x7A /* Control packet data buffer access window - PB23 */ | ||
121 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB24 0x7B /* Control packet data buffer access window - PB24 */ | ||
122 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB25 0x7C /* Control packet data buffer access window - PB25 */ | ||
123 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB26 0x7D /* Control packet data buffer access window - PB26 */ | ||
124 | #define HDMI_CTRL_PKT_BUF_ACCESS_PB27 0x7E /* Control packet data buffer access window - PB27 */ | ||
125 | #define HDMI_EDID_KSV_FIFO_ACCESS_WINDOW 0x80 /* EDID/KSV FIFO access window */ | ||
126 | #define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_7_0 0x81 /* DDC bus access frequency control (LSB) */ | ||
127 | #define HDMI_DDC_BUS_ACCESS_FREQ_CTRL_15_8 0x82 /* DDC bus access frequency control (MSB) */ | ||
128 | #define HDMI_INTERRUPT_MASK_1 0x92 /* Interrupt mask.1 */ | ||
129 | #define HDMI_INTERRUPT_MASK_2 0x93 /* Interrupt mask.2 */ | ||
130 | #define HDMI_INTERRUPT_STATUS_1 0x94 /* Interrupt status.1 */ | ||
131 | #define HDMI_INTERRUPT_STATUS_2 0x95 /* Interrupt status.2 */ | ||
132 | #define HDMI_INTERRUPT_MASK_3 0x96 /* Interrupt mask.3 */ | ||
133 | #define HDMI_INTERRUPT_MASK_4 0x97 /* Interrupt mask.4 */ | ||
134 | #define HDMI_INTERRUPT_STATUS_3 0x98 /* Interrupt status.3 */ | ||
135 | #define HDMI_INTERRUPT_STATUS_4 0x99 /* Interrupt status.4 */ | ||
136 | #define HDMI_SOFTWARE_HDCP_CONTROL_1 0x9A /* Software HDCP control.1 */ | ||
137 | #define HDMI_FRAME_COUNTER 0x9C /* Frame counter */ | ||
138 | #define HDMI_FRAME_COUNTER_FOR_RI_CHECK 0x9D /* Frame counter for Ri check */ | ||
139 | #define HDMI_HDCP_CONTROL 0xAF /* HDCP control */ | ||
140 | #define HDMI_RI_FRAME_COUNT_REGISTER 0xB2 /* Ri frame count register */ | ||
141 | #define HDMI_DDC_BUS_CONTROL 0xB7 /* DDC bus control */ | ||
142 | #define HDMI_HDCP_STATUS 0xB8 /* HDCP status */ | ||
143 | #define HDMI_SHA0 0xB9 /* sha0 */ | ||
144 | #define HDMI_SHA1 0xBA /* sha1 */ | ||
145 | #define HDMI_SHA2 0xBB /* sha2 */ | ||
146 | #define HDMI_SHA3 0xBC /* sha3 */ | ||
147 | #define HDMI_SHA4 0xBD /* sha4 */ | ||
148 | #define HDMI_BCAPS_READ 0xBE /* BCAPS read / debug */ | ||
149 | #define HDMI_AKSV_BKSV_7_0_MONITOR 0xBF /* AKSV/BKSV[7:0] monitor */ | ||
150 | #define HDMI_AKSV_BKSV_15_8_MONITOR 0xC0 /* AKSV/BKSV[15:8] monitor */ | ||
151 | #define HDMI_AKSV_BKSV_23_16_MONITOR 0xC1 /* AKSV/BKSV[23:16] monitor */ | ||
152 | #define HDMI_AKSV_BKSV_31_24_MONITOR 0xC2 /* AKSV/BKSV[31:24] monitor */ | ||
153 | #define HDMI_AKSV_BKSV_39_32_MONITOR 0xC3 /* AKSV/BKSV[39:32] monitor */ | ||
154 | #define HDMI_EDID_SEGMENT_POINTER 0xC4 /* EDID segment pointer */ | ||
155 | #define HDMI_EDID_WORD_ADDRESS 0xC5 /* EDID word address */ | ||
156 | #define HDMI_EDID_DATA_FIFO_ADDRESS 0xC6 /* EDID data FIFO address */ | ||
157 | #define HDMI_NUM_OF_HDMI_DEVICES 0xC7 /* Number of HDMI devices */ | ||
158 | #define HDMI_HDCP_ERROR_CODE 0xC8 /* HDCP error code */ | ||
159 | #define HDMI_100MS_TIMER_SET 0xC9 /* 100ms timer setting */ | ||
160 | #define HDMI_5SEC_TIMER_SET 0xCA /* 5sec timer setting */ | ||
161 | #define HDMI_RI_READ_COUNT 0xCB /* Ri read count */ | ||
162 | #define HDMI_AN_SEED 0xCC /* An seed */ | ||
163 | #define HDMI_MAX_NUM_OF_RCIVRS_ALLOWED 0xCD /* Maximum number of receivers allowed */ | ||
164 | #define HDMI_HDCP_MEMORY_ACCESS_CONTROL_1 0xCE /* HDCP memory access control.1 */ | ||
165 | #define HDMI_HDCP_MEMORY_ACCESS_CONTROL_2 0xCF /* HDCP memory access control.2 */ | ||
166 | #define HDMI_HDCP_CONTROL_2 0xD0 /* HDCP Control 2 */ | ||
167 | #define HDMI_HDCP_KEY_MEMORY_CONTROL 0xD2 /* HDCP Key Memory Control */ | ||
168 | #define HDMI_COLOR_SPACE_CONV_CONFIG_1 0xD3 /* Color space conversion configuration.1 */ | ||
169 | #define HDMI_VIDEO_SETTING_3 0xD4 /* Video setting.3 */ | ||
170 | #define HDMI_RI_7_0 0xD5 /* Ri[7:0] */ | ||
171 | #define HDMI_RI_15_8 0xD6 /* Ri[15:8] */ | ||
172 | #define HDMI_PJ 0xD7 /* Pj */ | ||
173 | #define HDMI_SHA_RD 0xD8 /* sha_rd */ | ||
174 | #define HDMI_RI_7_0_SAVED 0xD9 /* Ri[7:0] saved */ | ||
175 | #define HDMI_RI_15_8_SAVED 0xDA /* Ri[15:8] saved */ | ||
176 | #define HDMI_PJ_SAVED 0xDB /* Pj saved */ | ||
177 | #define HDMI_NUM_OF_DEVICES 0xDC /* Number of devices */ | ||
178 | #define HDMI_HOT_PLUG_MSENS_STATUS 0xDF /* Hot plug/MSENS status */ | ||
179 | #define HDMI_BCAPS_WRITE 0xE0 /* bcaps */ | ||
180 | #define HDMI_BSTAT_7_0 0xE1 /* bstat[7:0] */ | ||
181 | #define HDMI_BSTAT_15_8 0xE2 /* bstat[15:8] */ | ||
182 | #define HDMI_BKSV_7_0 0xE3 /* bksv[7:0] */ | ||
183 | #define HDMI_BKSV_15_8 0xE4 /* bksv[15:8] */ | ||
184 | #define HDMI_BKSV_23_16 0xE5 /* bksv[23:16] */ | ||
185 | #define HDMI_BKSV_31_24 0xE6 /* bksv[31:24] */ | ||
186 | #define HDMI_BKSV_39_32 0xE7 /* bksv[39:32] */ | ||
187 | #define HDMI_AN_7_0 0xE8 /* An[7:0] */ | ||
188 | #define HDMI_AN_15_8 0xE9 /* An [15:8] */ | ||
189 | #define HDMI_AN_23_16 0xEA /* An [23:16] */ | ||
190 | #define HDMI_AN_31_24 0xEB /* An [31:24] */ | ||
191 | #define HDMI_AN_39_32 0xEC /* An [39:32] */ | ||
192 | #define HDMI_AN_47_40 0xED /* An [47:40] */ | ||
193 | #define HDMI_AN_55_48 0xEE /* An [55:48] */ | ||
194 | #define HDMI_AN_63_56 0xEF /* An [63:56] */ | ||
195 | #define HDMI_PRODUCT_ID 0xF0 /* Product ID */ | ||
196 | #define HDMI_REVISION_ID 0xF1 /* Revision ID */ | ||
197 | #define HDMI_TEST_MODE 0xFE /* Test mode */ | ||
198 | |||
199 | enum hotplug_state { | ||
200 | HDMI_HOTPLUG_DISCONNECTED, | ||
201 | HDMI_HOTPLUG_CONNECTED, | ||
202 | HDMI_HOTPLUG_EDID_DONE, | ||
203 | }; | ||
204 | |||
205 | struct sh_hdmi { | ||
206 | void __iomem *base; | ||
207 | enum hotplug_state hp_state; | ||
208 | struct clk *hdmi_clk; | ||
209 | struct device *dev; | ||
210 | struct fb_info *info; | ||
211 | struct delayed_work edid_work; | ||
212 | struct fb_var_screeninfo var; | ||
213 | }; | ||
214 | |||
215 | static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) | ||
216 | { | ||
217 | iowrite8(data, hdmi->base + reg); | ||
218 | } | ||
219 | |||
220 | static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) | ||
221 | { | ||
222 | return ioread8(hdmi->base + reg); | ||
223 | } | ||
224 | |||
225 | /* External video parameter settings */ | ||
226 | static void hdmi_external_video_param(struct sh_hdmi *hdmi) | ||
227 | { | ||
228 | struct fb_var_screeninfo *var = &hdmi->var; | ||
229 | u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; | ||
230 | u8 sync = 0; | ||
231 | |||
232 | htotal = var->xres + var->right_margin + var->left_margin + var->hsync_len; | ||
233 | |||
234 | hdelay = var->hsync_len + var->left_margin; | ||
235 | hblank = var->right_margin + hdelay; | ||
236 | |||
237 | /* | ||
238 | * Vertical timing looks a bit different in Figure 18, | ||
239 | * but let's try the same first by setting offset = 0 | ||
240 | */ | ||
241 | vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; | ||
242 | |||
243 | vdelay = var->vsync_len + var->upper_margin; | ||
244 | vblank = var->lower_margin + vdelay; | ||
245 | voffset = min(var->upper_margin / 2, 6U); | ||
246 | |||
247 | /* | ||
248 | * [3]: VSYNC polarity: Positive | ||
249 | * [2]: HSYNC polarity: Positive | ||
250 | * [1]: Interlace/Progressive: Progressive | ||
251 | * [0]: External video settings enable: used. | ||
252 | */ | ||
253 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) | ||
254 | sync |= 4; | ||
255 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | ||
256 | sync |= 8; | ||
257 | |||
258 | pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", | ||
259 | htotal, hblank, hdelay, var->hsync_len, | ||
260 | vtotal, vblank, vdelay, var->vsync_len, sync); | ||
261 | |||
262 | hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); | ||
263 | |||
264 | hdmi_write(hdmi, htotal, HDMI_EXTERNAL_H_TOTAL_7_0); | ||
265 | hdmi_write(hdmi, htotal >> 8, HDMI_EXTERNAL_H_TOTAL_11_8); | ||
266 | |||
267 | hdmi_write(hdmi, hblank, HDMI_EXTERNAL_H_BLANK_7_0); | ||
268 | hdmi_write(hdmi, hblank >> 8, HDMI_EXTERNAL_H_BLANK_9_8); | ||
269 | |||
270 | hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0); | ||
271 | hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8); | ||
272 | |||
273 | hdmi_write(hdmi, var->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0); | ||
274 | hdmi_write(hdmi, var->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8); | ||
275 | |||
276 | hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0); | ||
277 | hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8); | ||
278 | |||
279 | hdmi_write(hdmi, vblank, HDMI_EXTERNAL_V_BLANK); | ||
280 | |||
281 | hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY); | ||
282 | |||
283 | hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); | ||
284 | |||
285 | /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */ | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * sh_hdmi_video_config() | ||
290 | */ | ||
291 | static void sh_hdmi_video_config(struct sh_hdmi *hdmi) | ||
292 | { | ||
293 | /* | ||
294 | * [7:4]: Audio sampling frequency: 48kHz | ||
295 | * [3:1]: Input video format: RGB and YCbCr 4:4:4 (Y on Green) | ||
296 | * [0]: Internal/External DE select: internal | ||
297 | */ | ||
298 | hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1); | ||
299 | |||
300 | /* | ||
301 | * [7:6]: Video output format: RGB 4:4:4 | ||
302 | * [5:4]: Input video data width: 8 bit | ||
303 | * [3:1]: EAV/SAV location: channel 1 | ||
304 | * [0]: Video input color space: RGB | ||
305 | */ | ||
306 | hdmi_write(hdmi, 0x34, HDMI_VIDEO_SETTING_1); | ||
307 | |||
308 | /* | ||
309 | * [7:6]: Together with bit [6] of HDMI_AUDIO_VIDEO_SETTING_2, which is | ||
310 | * left at 0 by default, this configures 24bpp and sets the Color Depth | ||
311 | * (CD) field in the General Control Packet | ||
312 | */ | ||
313 | hdmi_write(hdmi, 0x20, HDMI_DEEP_COLOR_MODES); | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * sh_hdmi_audio_config() | ||
318 | */ | ||
319 | static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) | ||
320 | { | ||
321 | /* | ||
322 | * [7:4] L/R data swap control | ||
323 | * [3:0] appropriate N[19:16] | ||
324 | */ | ||
325 | hdmi_write(hdmi, 0x00, HDMI_L_R_DATA_SWAP_CTRL_RPKT); | ||
326 | /* appropriate N[15:8] */ | ||
327 | hdmi_write(hdmi, 0x18, HDMI_20_BIT_N_FOR_AUDIO_RPKT_15_8); | ||
328 | /* appropriate N[7:0] */ | ||
329 | hdmi_write(hdmi, 0x00, HDMI_20_BIT_N_FOR_AUDIO_RPKT_7_0); | ||
330 | |||
331 | /* [7:4] 48 kHz SPDIF not used */ | ||
332 | hdmi_write(hdmi, 0x20, HDMI_SPDIF_AUDIO_SAMP_FREQ_CTS); | ||
333 | |||
334 | /* | ||
335 | * [6:5] set required down sampling rate if required | ||
336 | * [4:3] set required audio source | ||
337 | */ | ||
338 | hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1); | ||
339 | |||
340 | /* [3:0] set sending channel number for channel status */ | ||
341 | hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); | ||
342 | |||
343 | /* | ||
344 | * [5:2] set valid I2S source input pin | ||
345 | * [1:0] set input I2S source mode | ||
346 | */ | ||
347 | hdmi_write(hdmi, 0x04, HDMI_I2S_AUDIO_SET); | ||
348 | |||
349 | /* [7:4] set valid DSD source input pin */ | ||
350 | hdmi_write(hdmi, 0x00, HDMI_DSD_AUDIO_SET); | ||
351 | |||
352 | /* [7:0] set appropriate I2S input pin swap settings if required */ | ||
353 | hdmi_write(hdmi, 0x00, HDMI_I2S_INPUT_PIN_SWAP); | ||
354 | |||
355 | /* | ||
356 | * [7] set validity bit for channel status | ||
357 | * [3:0] set original sample frequency for channel status | ||
358 | */ | ||
359 | hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_1); | ||
360 | |||
361 | /* | ||
362 | * [7] set value for channel status | ||
363 | * [6] set value for channel status | ||
364 | * [5] set copyright bit for channel status | ||
365 | * [4:2] set additional information for channel status | ||
366 | * [1:0] set clock accuracy for channel status | ||
367 | */ | ||
368 | hdmi_write(hdmi, 0x00, HDMI_AUDIO_STATUS_BITS_SETTING_2); | ||
369 | |||
370 | /* [7:0] set category code for channel status */ | ||
371 | hdmi_write(hdmi, 0x00, HDMI_CATEGORY_CODE); | ||
372 | |||
373 | /* | ||
374 | * [7:4] set source number for channel status | ||
375 | * [3:0] set word length for channel status | ||
376 | */ | ||
377 | hdmi_write(hdmi, 0x00, HDMI_SOURCE_NUM_AUDIO_WORD_LEN); | ||
378 | |||
379 | /* [7:4] set sample frequency for channel status */ | ||
380 | hdmi_write(hdmi, 0x20, HDMI_AUDIO_VIDEO_SETTING_1); | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * sh_hdmi_phy_config() | ||
385 | */ | ||
386 | static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) | ||
387 | { | ||
388 | /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ | ||
389 | hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); | ||
390 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); | ||
391 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); | ||
392 | /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ | ||
393 | hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); | ||
394 | hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); | ||
395 | hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); | ||
396 | hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); | ||
397 | hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); | ||
398 | hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); | ||
399 | } | ||
400 | |||
401 | /** | ||
402 | * sh_hdmi_avi_infoframe_setup() - Auxiliary Video Information InfoFrame CONTROL PACKET | ||
403 | */ | ||
404 | static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) | ||
405 | { | ||
406 | /* AVI InfoFrame */ | ||
407 | hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); | ||
408 | |||
409 | /* Packet Type = 0x82 */ | ||
410 | hdmi_write(hdmi, 0x82, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
411 | |||
412 | /* Version = 0x02 */ | ||
413 | hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
414 | |||
415 | /* Length = 13 (0x0D) */ | ||
416 | hdmi_write(hdmi, 0x0D, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
417 | |||
418 | /* N. A. Checksum */ | ||
419 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0); | ||
420 | |||
421 | /* | ||
422 | * Y = RGB | ||
423 | * A0 = No Data | ||
424 | * B = Bar Data not valid | ||
425 | * S = No Data | ||
426 | */ | ||
427 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); | ||
428 | |||
429 | /* | ||
430 | * C = No Data | ||
431 | * M = 16:9 Picture Aspect Ratio | ||
432 | * R = Same as picture aspect ratio | ||
433 | */ | ||
434 | hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); | ||
435 | |||
436 | /* | ||
437 | * ITC = No Data | ||
438 | * EC = xvYCC601 | ||
439 | * Q = Default (depends on video format) | ||
440 | * SC = No Known non_uniform Scaling | ||
441 | */ | ||
442 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3); | ||
443 | |||
444 | /* | ||
445 | * VIC = 1280 x 720p: ignored if external config is used | ||
446 | * Send 2 for 720 x 480p, 16 for 1080p | ||
447 | */ | ||
448 | hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4); | ||
449 | |||
450 | /* PR = No Repetition */ | ||
451 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); | ||
452 | |||
453 | /* Line Number of End of Top Bar (lower 8 bits) */ | ||
454 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6); | ||
455 | |||
456 | /* Line Number of End of Top Bar (upper 8 bits) */ | ||
457 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7); | ||
458 | |||
459 | /* Line Number of Start of Bottom Bar (lower 8 bits) */ | ||
460 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8); | ||
461 | |||
462 | /* Line Number of Start of Bottom Bar (upper 8 bits) */ | ||
463 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9); | ||
464 | |||
465 | /* Pixel Number of End of Left Bar (lower 8 bits) */ | ||
466 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10); | ||
467 | |||
468 | /* Pixel Number of End of Left Bar (upper 8 bits) */ | ||
469 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB11); | ||
470 | |||
471 | /* Pixel Number of Start of Right Bar (lower 8 bits) */ | ||
472 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB12); | ||
473 | |||
474 | /* Pixel Number of Start of Right Bar (upper 8 bits) */ | ||
475 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB13); | ||
476 | } | ||
477 | |||
478 | /** | ||
479 | * sh_hdmi_audio_infoframe_setup() - Audio InfoFrame of CONTROL PACKET | ||
480 | */ | ||
481 | static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi) | ||
482 | { | ||
483 | /* Audio InfoFrame */ | ||
484 | hdmi_write(hdmi, 0x08, HDMI_CTRL_PKT_BUF_INDEX); | ||
485 | |||
486 | /* Packet Type = 0x84 */ | ||
487 | hdmi_write(hdmi, 0x84, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
488 | |||
489 | /* Version Number = 0x01 */ | ||
490 | hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
491 | |||
492 | /* 0 Length = 10 (0x0A) */ | ||
493 | hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
494 | |||
495 | /* n. a. Checksum */ | ||
496 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0); | ||
497 | |||
498 | /* Audio Channel Count = Refer to Stream Header */ | ||
499 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); | ||
500 | |||
501 | /* Refer to Stream Header */ | ||
502 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB2); | ||
503 | |||
504 | /* Format depends on coding type (i.e. CT0...CT3) */ | ||
505 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3); | ||
506 | |||
507 | /* Speaker Channel Allocation = Front Right + Front Left */ | ||
508 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB4); | ||
509 | |||
510 | /* Level Shift Value = 0 dB, Down - mix is permitted or no information */ | ||
511 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); | ||
512 | |||
513 | /* Reserved (0) */ | ||
514 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB6); | ||
515 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB7); | ||
516 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB8); | ||
517 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB9); | ||
518 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB10); | ||
519 | } | ||
520 | |||
521 | /** | ||
522 | * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET | ||
523 | */ | ||
524 | static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi) | ||
525 | { | ||
526 | int i; | ||
527 | |||
528 | /* Gamut Metadata Packet */ | ||
529 | hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX); | ||
530 | |||
531 | /* Packet Type = 0x0A */ | ||
532 | hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
533 | /* Gamut Packet is not used, so default value */ | ||
534 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
535 | /* Gamut Packet is not used, so default value */ | ||
536 | hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
537 | |||
538 | /* GBD bytes 0 through 27 */ | ||
539 | for (i = 0; i <= 27; i++) | ||
540 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */ | ||
541 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP) | ||
546 | */ | ||
547 | static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi) | ||
548 | { | ||
549 | int i; | ||
550 | |||
551 | /* Audio Content Protection Packet (ACP) */ | ||
552 | hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX); | ||
553 | |||
554 | /* Packet Type = 0x04 */ | ||
555 | hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
556 | /* ACP_Type */ | ||
557 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
558 | /* Reserved (0) */ | ||
559 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
560 | |||
561 | /* GBD bytes 0 through 27 */ | ||
562 | for (i = 0; i <= 27; i++) | ||
563 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */ | ||
564 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
565 | } | ||
566 | |||
567 | /** | ||
568 | * sh_hdmi_isrc1_setup() - ISRC1 Packet | ||
569 | */ | ||
570 | static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi) | ||
571 | { | ||
572 | int i; | ||
573 | |||
574 | /* ISRC1 Packet */ | ||
575 | hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX); | ||
576 | |||
577 | /* Packet Type = 0x05 */ | ||
578 | hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
579 | /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */ | ||
580 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
581 | /* Reserved (0) */ | ||
582 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
583 | |||
584 | /* PB0 UPC_EAN_ISRC_0-15 */ | ||
585 | /* Bytes PB16-PB27 shall be set to a value of 0. */ | ||
586 | for (i = 0; i <= 27; i++) | ||
587 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */ | ||
588 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * sh_hdmi_isrc2_setup() - ISRC2 Packet | ||
593 | */ | ||
594 | static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi) | ||
595 | { | ||
596 | int i; | ||
597 | |||
598 | /* ISRC2 Packet */ | ||
599 | hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX); | ||
600 | |||
601 | /* HB0 Packet Type = 0x06 */ | ||
602 | hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
603 | /* Reserved (0) */ | ||
604 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
605 | /* Reserved (0) */ | ||
606 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
607 | |||
608 | /* PB0 UPC_EAN_ISRC_16-31 */ | ||
609 | /* Bytes PB16-PB27 shall be set to a value of 0. */ | ||
610 | for (i = 0; i <= 27; i++) | ||
611 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */ | ||
612 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * sh_hdmi_configure() - Initialise HDMI for output | ||
617 | */ | ||
618 | static void sh_hdmi_configure(struct sh_hdmi *hdmi) | ||
619 | { | ||
620 | /* Configure video format */ | ||
621 | sh_hdmi_video_config(hdmi); | ||
622 | |||
623 | /* Configure audio format */ | ||
624 | sh_hdmi_audio_config(hdmi); | ||
625 | |||
626 | /* Configure PHY */ | ||
627 | sh_hdmi_phy_config(hdmi); | ||
628 | |||
629 | /* Auxiliary Video Information (AVI) InfoFrame */ | ||
630 | sh_hdmi_avi_infoframe_setup(hdmi); | ||
631 | |||
632 | /* Audio InfoFrame */ | ||
633 | sh_hdmi_audio_infoframe_setup(hdmi); | ||
634 | |||
635 | /* Gamut Metadata packet */ | ||
636 | sh_hdmi_gamut_metadata_setup(hdmi); | ||
637 | |||
638 | /* Audio Content Protection (ACP) Packet */ | ||
639 | sh_hdmi_acp_setup(hdmi); | ||
640 | |||
641 | /* ISRC1 Packet */ | ||
642 | sh_hdmi_isrc1_setup(hdmi); | ||
643 | |||
644 | /* ISRC2 Packet */ | ||
645 | sh_hdmi_isrc2_setup(hdmi); | ||
646 | |||
647 | /* | ||
648 | * Control packet auto send with VSYNC control: auto send | ||
649 | * General control, Gamut metadata, ISRC, and ACP packets | ||
650 | */ | ||
651 | hdmi_write(hdmi, 0x8E, HDMI_CTRL_PKT_AUTO_SEND); | ||
652 | |||
653 | /* FIXME */ | ||
654 | msleep(10); | ||
655 | |||
656 | /* PS mode b->d, reset PLLA and PLLB */ | ||
657 | hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL); | ||
658 | |||
659 | udelay(10); | ||
660 | |||
661 | hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); | ||
662 | } | ||
663 | |||
664 | static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) | ||
665 | { | ||
666 | struct fb_var_screeninfo *var = &hdmi->var; | ||
667 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | ||
668 | struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; | ||
669 | unsigned long height = var->height, width = var->width; | ||
670 | int i; | ||
671 | u8 edid[128]; | ||
672 | |||
673 | /* Read EDID */ | ||
674 | pr_debug("Read back EDID code:"); | ||
675 | for (i = 0; i < 128; i++) { | ||
676 | edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); | ||
677 | #ifdef DEBUG | ||
678 | if ((i % 16) == 0) { | ||
679 | printk(KERN_CONT "\n"); | ||
680 | printk(KERN_DEBUG "%02X | %02X", i, edid[i]); | ||
681 | } else { | ||
682 | printk(KERN_CONT " %02X", edid[i]); | ||
683 | } | ||
684 | #endif | ||
685 | } | ||
686 | #ifdef DEBUG | ||
687 | printk(KERN_CONT "\n"); | ||
688 | #endif | ||
689 | fb_parse_edid(edid, var); | ||
690 | pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", | ||
691 | var->left_margin, var->xres, var->right_margin, var->hsync_len, | ||
692 | var->upper_margin, var->yres, var->lower_margin, var->vsync_len, | ||
693 | PICOS2KHZ(var->pixclock)); | ||
694 | |||
695 | /* FIXME: Use user-provided configuration instead of EDID */ | ||
696 | var->width = width; | ||
697 | var->xres = lcd_cfg->xres; | ||
698 | var->xres_virtual = lcd_cfg->xres; | ||
699 | var->left_margin = lcd_cfg->left_margin; | ||
700 | var->right_margin = lcd_cfg->right_margin; | ||
701 | var->hsync_len = lcd_cfg->hsync_len; | ||
702 | var->height = height; | ||
703 | var->yres = lcd_cfg->yres; | ||
704 | var->yres_virtual = lcd_cfg->yres * 2; | ||
705 | var->upper_margin = lcd_cfg->upper_margin; | ||
706 | var->lower_margin = lcd_cfg->lower_margin; | ||
707 | var->vsync_len = lcd_cfg->vsync_len; | ||
708 | var->sync = lcd_cfg->sync; | ||
709 | var->pixclock = lcd_cfg->pixclock; | ||
710 | |||
711 | hdmi_external_video_param(hdmi); | ||
712 | } | ||
713 | |||
714 | static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) | ||
715 | { | ||
716 | struct sh_hdmi *hdmi = dev_id; | ||
717 | u8 status1, status2, mask1, mask2; | ||
718 | |||
719 | /* mode_b and PLLA and PLLB reset */ | ||
720 | hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL); | ||
721 | |||
722 | /* How long shall reset be held? */ | ||
723 | udelay(10); | ||
724 | |||
725 | /* mode_b and PLLA and PLLB reset release */ | ||
726 | hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL); | ||
727 | |||
728 | status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1); | ||
729 | status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2); | ||
730 | |||
731 | mask1 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_1); | ||
732 | mask2 = hdmi_read(hdmi, HDMI_INTERRUPT_MASK_2); | ||
733 | |||
734 | /* Correct would be to ack only set bits, but the datasheet requires 0xff */ | ||
735 | hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_1); | ||
736 | hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); | ||
737 | |||
738 | if (printk_ratelimit()) | ||
739 | pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", | ||
740 | irq, status1, mask1, status2, mask2); | ||
741 | |||
742 | if (!((status1 & mask1) | (status2 & mask2))) { | ||
743 | return IRQ_NONE; | ||
744 | } else if (status1 & 0xc0) { | ||
745 | u8 msens; | ||
746 | |||
747 | /* Datasheet specifies 10ms... */ | ||
748 | udelay(500); | ||
749 | |||
750 | msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); | ||
751 | pr_debug("MSENS 0x%x\n", msens); | ||
752 | /* Check, if hot plug & MSENS pin status are both high */ | ||
753 | if ((msens & 0xC0) == 0xC0) { | ||
754 | /* Display plug in */ | ||
755 | hdmi->hp_state = HDMI_HOTPLUG_CONNECTED; | ||
756 | |||
757 | /* Set EDID word address */ | ||
758 | hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); | ||
759 | /* Set EDID segment pointer */ | ||
760 | hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER); | ||
761 | /* Enable EDID interrupt */ | ||
762 | hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1); | ||
763 | } else if (!(status1 & 0x80)) { | ||
764 | /* Display unplug, beware multiple interrupts */ | ||
765 | if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) | ||
766 | schedule_delayed_work(&hdmi->edid_work, 0); | ||
767 | |||
768 | hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; | ||
769 | /* display_off will switch back to mode_a */ | ||
770 | } | ||
771 | } else if (status1 & 2) { | ||
772 | /* EDID error interrupt: retry */ | ||
773 | /* Set EDID word address */ | ||
774 | hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); | ||
775 | /* Set EDID segment pointer */ | ||
776 | hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER); | ||
777 | } else if (status1 & 4) { | ||
778 | /* Disable EDID interrupt */ | ||
779 | hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1); | ||
780 | hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; | ||
781 | schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10)); | ||
782 | } | ||
783 | |||
784 | return IRQ_HANDLED; | ||
785 | } | ||
786 | |||
787 | static void hdmi_display_on(void *arg, struct fb_info *info) | ||
788 | { | ||
789 | struct sh_hdmi *hdmi = arg; | ||
790 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | ||
791 | |||
792 | if (info->var.xres != 1280 || info->var.yres != 720) { | ||
793 | dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n", | ||
794 | info->var.xres, info->var.yres); | ||
795 | return; | ||
796 | } | ||
797 | |||
798 | pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state); | ||
799 | /* | ||
800 | * FIXME: not a good place to store fb_info. And we cannot nullify it | ||
801 | * even on monitor disconnect. What should the lifecycle be? | ||
802 | */ | ||
803 | hdmi->info = info; | ||
804 | switch (hdmi->hp_state) { | ||
805 | case HDMI_HOTPLUG_EDID_DONE: | ||
806 | /* PS mode d->e. All functions are active */ | ||
807 | hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); | ||
808 | pr_debug("HDMI running\n"); | ||
809 | break; | ||
810 | case HDMI_HOTPLUG_DISCONNECTED: | ||
811 | info->state = FBINFO_STATE_SUSPENDED; | ||
812 | default: | ||
813 | hdmi->var = info->var; | ||
814 | } | ||
815 | } | ||
816 | |||
817 | static void hdmi_display_off(void *arg) | ||
818 | { | ||
819 | struct sh_hdmi *hdmi = arg; | ||
820 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | ||
821 | |||
822 | pr_debug("%s(%p)\n", __func__, pdata->lcd_dev); | ||
823 | /* PS mode e->a */ | ||
824 | hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); | ||
825 | } | ||
826 | |||
827 | /* Hotplug interrupt occurred, read EDID */ | ||
828 | static void edid_work_fn(struct work_struct *work) | ||
829 | { | ||
830 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); | ||
831 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | ||
832 | |||
833 | pr_debug("%s(%p): begin, hotplug status %d\n", __func__, | ||
834 | pdata->lcd_dev, hdmi->hp_state); | ||
835 | |||
836 | if (!pdata->lcd_dev) | ||
837 | return; | ||
838 | |||
839 | if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { | ||
840 | pm_runtime_get_sync(hdmi->dev); | ||
841 | /* A device has been plugged in */ | ||
842 | sh_hdmi_read_edid(hdmi); | ||
843 | msleep(10); | ||
844 | sh_hdmi_configure(hdmi); | ||
845 | /* Switched to another (d) power-save mode */ | ||
846 | msleep(10); | ||
847 | |||
848 | if (!hdmi->info) | ||
849 | return; | ||
850 | |||
851 | acquire_console_sem(); | ||
852 | |||
853 | /* HDMI plug in */ | ||
854 | hdmi->info->var = hdmi->var; | ||
855 | if (hdmi->info->state != FBINFO_STATE_RUNNING) | ||
856 | fb_set_suspend(hdmi->info, 0); | ||
857 | else | ||
858 | hdmi_display_on(hdmi, hdmi->info); | ||
859 | |||
860 | release_console_sem(); | ||
861 | } else { | ||
862 | if (!hdmi->info) | ||
863 | return; | ||
864 | |||
865 | acquire_console_sem(); | ||
866 | |||
867 | /* HDMI disconnect */ | ||
868 | fb_set_suspend(hdmi->info, 1); | ||
869 | |||
870 | release_console_sem(); | ||
871 | pm_runtime_put(hdmi->dev); | ||
872 | } | ||
873 | |||
874 | pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev); | ||
875 | } | ||
876 | |||
877 | static int __init sh_hdmi_probe(struct platform_device *pdev) | ||
878 | { | ||
879 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; | ||
880 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
881 | int irq = platform_get_irq(pdev, 0), ret; | ||
882 | struct sh_hdmi *hdmi; | ||
883 | long rate; | ||
884 | |||
885 | if (!res || !pdata || irq < 0) | ||
886 | return -ENODEV; | ||
887 | |||
888 | hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); | ||
889 | if (!hdmi) { | ||
890 | dev_err(&pdev->dev, "Cannot allocate device data\n"); | ||
891 | return -ENOMEM; | ||
892 | } | ||
893 | |||
894 | hdmi->dev = &pdev->dev; | ||
895 | |||
896 | hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); | ||
897 | if (IS_ERR(hdmi->hdmi_clk)) { | ||
898 | ret = PTR_ERR(hdmi->hdmi_clk); | ||
899 | dev_err(&pdev->dev, "Unable to get clock: %d\n", ret); | ||
900 | goto egetclk; | ||
901 | } | ||
902 | |||
903 | rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; | ||
904 | |||
905 | rate = clk_round_rate(hdmi->hdmi_clk, rate); | ||
906 | if (rate < 0) { | ||
907 | ret = rate; | ||
908 | dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate); | ||
909 | goto erate; | ||
910 | } | ||
911 | |||
912 | ret = clk_set_rate(hdmi->hdmi_clk, rate); | ||
913 | if (ret < 0) { | ||
914 | dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret); | ||
915 | goto erate; | ||
916 | } | ||
917 | |||
918 | pr_debug("HDMI set frequency %lu\n", rate); | ||
919 | |||
920 | ret = clk_enable(hdmi->hdmi_clk); | ||
921 | if (ret < 0) { | ||
922 | dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret); | ||
923 | goto eclkenable; | ||
924 | } | ||
925 | |||
926 | dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); | ||
927 | |||
928 | if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { | ||
929 | dev_err(&pdev->dev, "HDMI register region already claimed\n"); | ||
930 | ret = -EBUSY; | ||
931 | goto ereqreg; | ||
932 | } | ||
933 | |||
934 | hdmi->base = ioremap(res->start, resource_size(res)); | ||
935 | if (!hdmi->base) { | ||
936 | dev_err(&pdev->dev, "HDMI register region already claimed\n"); | ||
937 | ret = -ENOMEM; | ||
938 | goto emap; | ||
939 | } | ||
940 | |||
941 | platform_set_drvdata(pdev, hdmi); | ||
942 | |||
943 | #if 1 | ||
944 | /* Product and revision IDs are 0 in sh-mobile version */ | ||
945 | dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", | ||
946 | hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); | ||
947 | #endif | ||
948 | |||
949 | /* Set up LCDC callbacks */ | ||
950 | pdata->lcd_chan->board_cfg.board_data = hdmi; | ||
951 | pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; | ||
952 | pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; | ||
953 | |||
954 | INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); | ||
955 | |||
956 | pm_runtime_enable(&pdev->dev); | ||
957 | pm_runtime_resume(&pdev->dev); | ||
958 | |||
959 | ret = request_irq(irq, sh_hdmi_hotplug, 0, | ||
960 | dev_name(&pdev->dev), hdmi); | ||
961 | if (ret < 0) { | ||
962 | dev_err(&pdev->dev, "Unable to request irq: %d\n", ret); | ||
963 | goto ereqirq; | ||
964 | } | ||
965 | |||
966 | return 0; | ||
967 | |||
968 | ereqirq: | ||
969 | pm_runtime_disable(&pdev->dev); | ||
970 | iounmap(hdmi->base); | ||
971 | emap: | ||
972 | release_mem_region(res->start, resource_size(res)); | ||
973 | ereqreg: | ||
974 | clk_disable(hdmi->hdmi_clk); | ||
975 | eclkenable: | ||
976 | erate: | ||
977 | clk_put(hdmi->hdmi_clk); | ||
978 | egetclk: | ||
979 | kfree(hdmi); | ||
980 | |||
981 | return ret; | ||
982 | } | ||
983 | |||
984 | static int __exit sh_hdmi_remove(struct platform_device *pdev) | ||
985 | { | ||
986 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; | ||
987 | struct sh_hdmi *hdmi = platform_get_drvdata(pdev); | ||
988 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
989 | int irq = platform_get_irq(pdev, 0); | ||
990 | |||
991 | pdata->lcd_chan->board_cfg.display_on = NULL; | ||
992 | pdata->lcd_chan->board_cfg.display_off = NULL; | ||
993 | pdata->lcd_chan->board_cfg.board_data = NULL; | ||
994 | |||
995 | free_irq(irq, hdmi); | ||
996 | pm_runtime_disable(&pdev->dev); | ||
997 | cancel_delayed_work_sync(&hdmi->edid_work); | ||
998 | clk_disable(hdmi->hdmi_clk); | ||
999 | clk_put(hdmi->hdmi_clk); | ||
1000 | iounmap(hdmi->base); | ||
1001 | release_mem_region(res->start, resource_size(res)); | ||
1002 | kfree(hdmi); | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | static struct platform_driver sh_hdmi_driver = { | ||
1008 | .remove = __exit_p(sh_hdmi_remove), | ||
1009 | .driver = { | ||
1010 | .name = "sh-mobile-hdmi", | ||
1011 | }, | ||
1012 | }; | ||
1013 | |||
1014 | static int __init sh_hdmi_init(void) | ||
1015 | { | ||
1016 | return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe); | ||
1017 | } | ||
1018 | module_init(sh_hdmi_init); | ||
1019 | |||
1020 | static void __exit sh_hdmi_exit(void) | ||
1021 | { | ||
1022 | platform_driver_unregister(&sh_hdmi_driver); | ||
1023 | } | ||
1024 | module_exit(sh_hdmi_exit); | ||
1025 | |||
1026 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
1027 | MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver"); | ||
1028 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 12c451a711e9..d72075a9f01c 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -56,6 +56,7 @@ static int lcdc_shared_regs[] = { | |||
56 | /* per-channel registers */ | 56 | /* per-channel registers */ |
57 | enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, | 57 | enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, |
58 | LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, | 58 | LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, |
59 | LDHAJR, | ||
59 | NR_CH_REGS }; | 60 | NR_CH_REGS }; |
60 | 61 | ||
61 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { | 62 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { |
@@ -74,6 +75,7 @@ static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { | |||
74 | [LDVLNR] = 0x450, | 75 | [LDVLNR] = 0x450, |
75 | [LDVSYNR] = 0x454, | 76 | [LDVSYNR] = 0x454, |
76 | [LDPMR] = 0x460, | 77 | [LDPMR] = 0x460, |
78 | [LDHAJR] = 0x4a0, | ||
77 | }; | 79 | }; |
78 | 80 | ||
79 | static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { | 81 | static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { |
@@ -137,6 +139,7 @@ struct sh_mobile_lcdc_priv { | |||
137 | struct clk *dot_clk; | 139 | struct clk *dot_clk; |
138 | unsigned long lddckr; | 140 | unsigned long lddckr; |
139 | struct sh_mobile_lcdc_chan ch[2]; | 141 | struct sh_mobile_lcdc_chan ch[2]; |
142 | struct notifier_block notifier; | ||
140 | unsigned long saved_shared_regs[NR_SHARED_REGS]; | 143 | unsigned long saved_shared_regs[NR_SHARED_REGS]; |
141 | int started; | 144 | int started; |
142 | }; | 145 | }; |
@@ -404,6 +407,56 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, | |||
404 | lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ | 407 | lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ |
405 | } | 408 | } |
406 | 409 | ||
410 | static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | ||
411 | { | ||
412 | struct fb_var_screeninfo *var = &ch->info->var; | ||
413 | unsigned long h_total, hsync_pos; | ||
414 | u32 tmp; | ||
415 | |||
416 | tmp = ch->ldmt1r_value; | ||
417 | tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28; | ||
418 | tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27; | ||
419 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0; | ||
420 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0; | ||
421 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0; | ||
422 | tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0; | ||
423 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0; | ||
424 | lcdc_write_chan(ch, LDMT1R, tmp); | ||
425 | |||
426 | /* setup SYS bus */ | ||
427 | lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r); | ||
428 | lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); | ||
429 | |||
430 | /* horizontal configuration */ | ||
431 | h_total = var->xres + var->hsync_len + | ||
432 | var->left_margin + var->right_margin; | ||
433 | tmp = h_total / 8; /* HTCN */ | ||
434 | tmp |= (var->xres / 8) << 16; /* HDCN */ | ||
435 | lcdc_write_chan(ch, LDHCNR, tmp); | ||
436 | |||
437 | hsync_pos = var->xres + var->right_margin; | ||
438 | tmp = hsync_pos / 8; /* HSYNP */ | ||
439 | tmp |= (var->hsync_len / 8) << 16; /* HSYNW */ | ||
440 | lcdc_write_chan(ch, LDHSYNR, tmp); | ||
441 | |||
442 | /* vertical configuration */ | ||
443 | tmp = var->yres + var->vsync_len + | ||
444 | var->upper_margin + var->lower_margin; /* VTLN */ | ||
445 | tmp |= var->yres << 16; /* VDLN */ | ||
446 | lcdc_write_chan(ch, LDVLNR, tmp); | ||
447 | |||
448 | tmp = var->yres + var->lower_margin; /* VSYNP */ | ||
449 | tmp |= var->vsync_len << 16; /* VSYNW */ | ||
450 | lcdc_write_chan(ch, LDVSYNR, tmp); | ||
451 | |||
452 | /* Adjust horizontal synchronisation for HDMI */ | ||
453 | tmp = ((var->xres & 7) << 24) | | ||
454 | ((h_total & 7) << 16) | | ||
455 | ((var->hsync_len & 7) << 8) | | ||
456 | hsync_pos; | ||
457 | lcdc_write_chan(ch, LDHAJR, tmp); | ||
458 | } | ||
459 | |||
407 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | 460 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) |
408 | { | 461 | { |
409 | struct sh_mobile_lcdc_chan *ch; | 462 | struct sh_mobile_lcdc_chan *ch; |
@@ -470,49 +523,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
470 | if (!ch->enabled) | 523 | if (!ch->enabled) |
471 | continue; | 524 | continue; |
472 | 525 | ||
473 | tmp = ch->ldmt1r_value; | 526 | sh_mobile_lcdc_geometry(ch); |
474 | tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28; | ||
475 | tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27; | ||
476 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0; | ||
477 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0; | ||
478 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0; | ||
479 | tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0; | ||
480 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0; | ||
481 | lcdc_write_chan(ch, LDMT1R, tmp); | ||
482 | |||
483 | /* setup SYS bus */ | ||
484 | lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r); | ||
485 | lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); | ||
486 | |||
487 | /* horizontal configuration */ | ||
488 | tmp = lcd_cfg->xres + lcd_cfg->hsync_len; | ||
489 | tmp += lcd_cfg->left_margin; | ||
490 | tmp += lcd_cfg->right_margin; | ||
491 | tmp /= 8; /* HTCN */ | ||
492 | tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */ | ||
493 | lcdc_write_chan(ch, LDHCNR, tmp); | ||
494 | |||
495 | tmp = lcd_cfg->xres; | ||
496 | tmp += lcd_cfg->right_margin; | ||
497 | tmp /= 8; /* HSYNP */ | ||
498 | tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */ | ||
499 | lcdc_write_chan(ch, LDHSYNR, tmp); | ||
500 | 527 | ||
501 | /* power supply */ | 528 | /* power supply */ |
502 | lcdc_write_chan(ch, LDPMR, 0); | 529 | lcdc_write_chan(ch, LDPMR, 0); |
503 | 530 | ||
504 | /* vertical configuration */ | ||
505 | tmp = lcd_cfg->yres + lcd_cfg->vsync_len; | ||
506 | tmp += lcd_cfg->upper_margin; | ||
507 | tmp += lcd_cfg->lower_margin; /* VTLN */ | ||
508 | tmp |= lcd_cfg->yres << 16; /* VDLN */ | ||
509 | lcdc_write_chan(ch, LDVLNR, tmp); | ||
510 | |||
511 | tmp = lcd_cfg->yres; | ||
512 | tmp += lcd_cfg->lower_margin; /* VSYNP */ | ||
513 | tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */ | ||
514 | lcdc_write_chan(ch, LDVSYNR, tmp); | ||
515 | |||
516 | board_cfg = &ch->cfg.board_cfg; | 531 | board_cfg = &ch->cfg.board_cfg; |
517 | if (board_cfg->setup_sys) | 532 | if (board_cfg->setup_sys) |
518 | ret = board_cfg->setup_sys(board_cfg->board_data, ch, | 533 | ret = board_cfg->setup_sys(board_cfg->board_data, ch, |
@@ -577,7 +592,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
577 | 592 | ||
578 | board_cfg = &ch->cfg.board_cfg; | 593 | board_cfg = &ch->cfg.board_cfg; |
579 | if (board_cfg->display_on) | 594 | if (board_cfg->display_on) |
580 | board_cfg->display_on(board_cfg->board_data); | 595 | board_cfg->display_on(board_cfg->board_data, ch->info); |
581 | } | 596 | } |
582 | 597 | ||
583 | return 0; | 598 | return 0; |
@@ -943,6 +958,62 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { | |||
943 | .runtime_resume = sh_mobile_lcdc_runtime_resume, | 958 | .runtime_resume = sh_mobile_lcdc_runtime_resume, |
944 | }; | 959 | }; |
945 | 960 | ||
961 | static int sh_mobile_lcdc_notify(struct notifier_block *nb, | ||
962 | unsigned long action, void *data) | ||
963 | { | ||
964 | struct fb_event *event = data; | ||
965 | struct fb_info *info = event->info; | ||
966 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
967 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; | ||
968 | struct fb_var_screeninfo *var; | ||
969 | |||
970 | if (&ch->lcdc->notifier != nb) | ||
971 | return 0; | ||
972 | |||
973 | dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", | ||
974 | __func__, action, event->data); | ||
975 | |||
976 | switch(action) { | ||
977 | case FB_EVENT_SUSPEND: | ||
978 | if (board_cfg->display_off) | ||
979 | board_cfg->display_off(board_cfg->board_data); | ||
980 | pm_runtime_put(info->device); | ||
981 | break; | ||
982 | case FB_EVENT_RESUME: | ||
983 | var = &info->var; | ||
984 | |||
985 | /* HDMI must be enabled before LCDC configuration */ | ||
986 | if (board_cfg->display_on) | ||
987 | board_cfg->display_on(board_cfg->board_data, ch->info); | ||
988 | |||
989 | /* Check if the new display is not in our modelist */ | ||
990 | if (ch->info->modelist.next && | ||
991 | !fb_match_mode(var, &ch->info->modelist)) { | ||
992 | struct fb_videomode mode; | ||
993 | int ret; | ||
994 | |||
995 | /* Can we handle this display? */ | ||
996 | if (var->xres > ch->cfg.lcd_cfg.xres || | ||
997 | var->yres > ch->cfg.lcd_cfg.yres) | ||
998 | return -ENOMEM; | ||
999 | |||
1000 | /* Add to the modelist */ | ||
1001 | fb_var_to_videomode(&mode, var); | ||
1002 | ret = fb_add_videomode(&mode, &ch->info->modelist); | ||
1003 | if (ret < 0) | ||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | pm_runtime_get_sync(info->device); | ||
1008 | |||
1009 | sh_mobile_lcdc_geometry(ch); | ||
1010 | |||
1011 | break; | ||
1012 | } | ||
1013 | |||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
946 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); | 1017 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); |
947 | 1018 | ||
948 | static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | 1019 | static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) |
@@ -1020,15 +1091,19 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1020 | goto err1; | 1091 | goto err1; |
1021 | } | 1092 | } |
1022 | 1093 | ||
1094 | priv->base = ioremap_nocache(res->start, resource_size(res)); | ||
1095 | if (!priv->base) | ||
1096 | goto err1; | ||
1097 | |||
1023 | error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv); | 1098 | error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv); |
1024 | if (error) { | 1099 | if (error) { |
1025 | dev_err(&pdev->dev, "unable to setup clocks\n"); | 1100 | dev_err(&pdev->dev, "unable to setup clocks\n"); |
1026 | goto err1; | 1101 | goto err1; |
1027 | } | 1102 | } |
1028 | 1103 | ||
1029 | priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1); | ||
1030 | |||
1031 | for (i = 0; i < j; i++) { | 1104 | for (i = 0; i < j; i++) { |
1105 | struct fb_var_screeninfo *var; | ||
1106 | struct fb_videomode *lcd_cfg; | ||
1032 | cfg = &priv->ch[i].cfg; | 1107 | cfg = &priv->ch[i].cfg; |
1033 | 1108 | ||
1034 | priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); | 1109 | priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); |
@@ -1039,22 +1114,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1039 | } | 1114 | } |
1040 | 1115 | ||
1041 | info = priv->ch[i].info; | 1116 | info = priv->ch[i].info; |
1117 | var = &info->var; | ||
1118 | lcd_cfg = &cfg->lcd_cfg; | ||
1042 | info->fbops = &sh_mobile_lcdc_ops; | 1119 | info->fbops = &sh_mobile_lcdc_ops; |
1043 | info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; | 1120 | var->xres = var->xres_virtual = lcd_cfg->xres; |
1044 | info->var.yres = cfg->lcd_cfg.yres; | 1121 | var->yres = lcd_cfg->yres; |
1045 | /* Default Y virtual resolution is 2x panel size */ | 1122 | /* Default Y virtual resolution is 2x panel size */ |
1046 | info->var.yres_virtual = info->var.yres * 2; | 1123 | var->yres_virtual = var->yres * 2; |
1047 | info->var.width = cfg->lcd_size_cfg.width; | 1124 | var->width = cfg->lcd_size_cfg.width; |
1048 | info->var.height = cfg->lcd_size_cfg.height; | 1125 | var->height = cfg->lcd_size_cfg.height; |
1049 | info->var.activate = FB_ACTIVATE_NOW; | 1126 | var->activate = FB_ACTIVATE_NOW; |
1050 | error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp); | 1127 | var->left_margin = lcd_cfg->left_margin; |
1128 | var->right_margin = lcd_cfg->right_margin; | ||
1129 | var->upper_margin = lcd_cfg->upper_margin; | ||
1130 | var->lower_margin = lcd_cfg->lower_margin; | ||
1131 | var->hsync_len = lcd_cfg->hsync_len; | ||
1132 | var->vsync_len = lcd_cfg->vsync_len; | ||
1133 | var->sync = lcd_cfg->sync; | ||
1134 | var->pixclock = lcd_cfg->pixclock; | ||
1135 | |||
1136 | error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); | ||
1051 | if (error) | 1137 | if (error) |
1052 | break; | 1138 | break; |
1053 | 1139 | ||
1054 | info->fix = sh_mobile_lcdc_fix; | 1140 | info->fix = sh_mobile_lcdc_fix; |
1055 | info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8); | 1141 | info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8); |
1056 | info->fix.smem_len = info->fix.line_length * | 1142 | info->fix.smem_len = info->fix.line_length * |
1057 | info->var.yres_virtual; | 1143 | var->yres_virtual; |
1058 | 1144 | ||
1059 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, | 1145 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, |
1060 | &priv->ch[i].dma_handle, GFP_KERNEL); | 1146 | &priv->ch[i].dma_handle, GFP_KERNEL); |
@@ -1119,10 +1205,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1119 | ch->cfg.bpp); | 1205 | ch->cfg.bpp); |
1120 | 1206 | ||
1121 | /* deferred io mode: disable clock to save power */ | 1207 | /* deferred io mode: disable clock to save power */ |
1122 | if (info->fbdefio) | 1208 | if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED) |
1123 | sh_mobile_lcdc_clk_off(priv); | 1209 | sh_mobile_lcdc_clk_off(priv); |
1124 | } | 1210 | } |
1125 | 1211 | ||
1212 | /* Failure ignored */ | ||
1213 | priv->notifier.notifier_call = sh_mobile_lcdc_notify; | ||
1214 | fb_register_client(&priv->notifier); | ||
1215 | |||
1126 | return 0; | 1216 | return 0; |
1127 | err1: | 1217 | err1: |
1128 | sh_mobile_lcdc_remove(pdev); | 1218 | sh_mobile_lcdc_remove(pdev); |
@@ -1136,6 +1226,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) | |||
1136 | struct fb_info *info; | 1226 | struct fb_info *info; |
1137 | int i; | 1227 | int i; |
1138 | 1228 | ||
1229 | fb_unregister_client(&priv->notifier); | ||
1230 | |||
1139 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | 1231 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) |
1140 | if (priv->ch[i].info && priv->ch[i].info->dev) | 1232 | if (priv->ch[i].info && priv->ch[i].info->dev) |
1141 | unregister_framebuffer(priv->ch[i].info); | 1233 | unregister_framebuffer(priv->ch[i].info); |
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index 7288934c0d49..5dbe06af2226 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c | |||
@@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp) | |||
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | static int __devinit gfb_probe(struct of_device *op, | 114 | static int __devinit gfb_probe(struct platform_device *op, |
115 | const struct of_device_id *match) | 115 | const struct of_device_id *match) |
116 | { | 116 | { |
117 | struct device_node *dp = op->dev.of_node; | 117 | struct device_node *dp = op->dev.of_node; |
@@ -172,7 +172,7 @@ err_out: | |||
172 | return err; | 172 | return err; |
173 | } | 173 | } |
174 | 174 | ||
175 | static int __devexit gfb_remove(struct of_device *op) | 175 | static int __devexit gfb_remove(struct platform_device *op) |
176 | { | 176 | { |
177 | struct fb_info *info = dev_get_drvdata(&op->dev); | 177 | struct fb_info *info = dev_get_drvdata(&op->dev); |
178 | struct gfb_info *gp = info->par; | 178 | struct gfb_info *gp = info->par; |
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index f375e0db6776..77ad27955cf0 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
@@ -342,7 +342,7 @@ tcx_init_fix(struct fb_info *info, int linebytes) | |||
342 | info->fix.accel = FB_ACCEL_SUN_TCX; | 342 | info->fix.accel = FB_ACCEL_SUN_TCX; |
343 | } | 343 | } |
344 | 344 | ||
345 | static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, | 345 | static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info, |
346 | struct tcx_par *par) | 346 | struct tcx_par *par) |
347 | { | 347 | { |
348 | if (par->tec) | 348 | if (par->tec) |
@@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, | |||
362 | info->screen_base, info->fix.smem_len); | 362 | info->screen_base, info->fix.smem_len); |
363 | } | 363 | } |
364 | 364 | ||
365 | static int __devinit tcx_probe(struct of_device *op, | 365 | static int __devinit tcx_probe(struct platform_device *op, |
366 | const struct of_device_id *match) | 366 | const struct of_device_id *match) |
367 | { | 367 | { |
368 | struct device_node *dp = op->dev.of_node; | 368 | struct device_node *dp = op->dev.of_node; |
@@ -486,7 +486,7 @@ out_err: | |||
486 | return err; | 486 | return err; |
487 | } | 487 | } |
488 | 488 | ||
489 | static int __devexit tcx_remove(struct of_device *op) | 489 | static int __devexit tcx_remove(struct platform_device *op) |
490 | { | 490 | { |
491 | struct fb_info *info = dev_get_drvdata(&op->dev); | 491 | struct fb_info *info = dev_get_drvdata(&op->dev); |
492 | struct tcx_par *par = info->par; | 492 | struct tcx_par *par = info->par; |
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 7b8839ebf3c4..52ec0959d462 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -1977,8 +1977,7 @@ static void __devexit uvesafb_exit(void) | |||
1977 | 1977 | ||
1978 | module_exit(uvesafb_exit); | 1978 | module_exit(uvesafb_exit); |
1979 | 1979 | ||
1980 | #define param_get_scroll NULL | 1980 | static int param_set_scroll(const char *val, const struct kernel_param *kp) |
1981 | static int param_set_scroll(const char *val, struct kernel_param *kp) | ||
1982 | { | 1981 | { |
1983 | ypan = 0; | 1982 | ypan = 0; |
1984 | 1983 | ||
@@ -1993,7 +1992,9 @@ static int param_set_scroll(const char *val, struct kernel_param *kp) | |||
1993 | 1992 | ||
1994 | return 0; | 1993 | return 0; |
1995 | } | 1994 | } |
1996 | 1995 | static struct kernel_param_ops param_ops_scroll = { | |
1996 | .set = param_set_scroll, | ||
1997 | }; | ||
1997 | #define param_check_scroll(name, p) __param_check(name, p, void) | 1998 | #define param_check_scroll(name, p) __param_check(name, p, void) |
1998 | 1999 | ||
1999 | module_param_named(scroll, ypan, scroll, 0); | 2000 | module_param_named(scroll, ypan, scroll, 0); |
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index d31dc96f838a..85d76ec4c63e 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
@@ -726,7 +726,9 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
726 | 726 | ||
727 | /* Prepare startup mode */ | 727 | /* Prepare startup mode */ |
728 | 728 | ||
729 | kparam_block_sysfs_write(mode_option); | ||
729 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 730 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); |
731 | kparam_unblock_sysfs_write(mode_option); | ||
730 | if (! ((rc == 1) || (rc == 2))) { | 732 | if (! ((rc == 1) || (rc == 2))) { |
731 | rc = -EINVAL; | 733 | rc = -EINVAL; |
732 | dev_err(info->device, "mode %s not found\n", mode_option); | 734 | dev_err(info->device, "mode %s not found\n", mode_option); |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 29b5daacc217..0c9ce88e95e8 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -397,7 +397,7 @@ static int xilinxfb_release(struct device *dev) | |||
397 | */ | 397 | */ |
398 | 398 | ||
399 | static int __devinit | 399 | static int __devinit |
400 | xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) | 400 | xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match) |
401 | { | 401 | { |
402 | const u32 *prop; | 402 | const u32 *prop; |
403 | u32 *p; | 403 | u32 *p; |
@@ -477,7 +477,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) | |||
477 | return -ENODEV; | 477 | return -ENODEV; |
478 | } | 478 | } |
479 | 479 | ||
480 | static int __devexit xilinxfb_of_remove(struct of_device *op) | 480 | static int __devexit xilinxfb_of_remove(struct platform_device *op) |
481 | { | 481 | { |
482 | return xilinxfb_release(&op->dev); | 482 | return xilinxfb_release(&op->dev); |
483 | } | 483 | } |
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 30a2512fd52e..566343b3c131 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c | |||
@@ -526,7 +526,7 @@ static const struct file_operations cpwd_fops = { | |||
526 | .release = cpwd_release, | 526 | .release = cpwd_release, |
527 | }; | 527 | }; |
528 | 528 | ||
529 | static int __devinit cpwd_probe(struct of_device *op, | 529 | static int __devinit cpwd_probe(struct platform_device *op, |
530 | const struct of_device_id *match) | 530 | const struct of_device_id *match) |
531 | { | 531 | { |
532 | struct device_node *options; | 532 | struct device_node *options; |
@@ -639,7 +639,7 @@ out_free: | |||
639 | goto out; | 639 | goto out; |
640 | } | 640 | } |
641 | 641 | ||
642 | static int __devexit cpwd_remove(struct of_device *op) | 642 | static int __devexit cpwd_remove(struct platform_device *op) |
643 | { | 643 | { |
644 | struct cpwd *p = dev_get_drvdata(&op->dev); | 644 | struct cpwd *p = dev_get_drvdata(&op->dev); |
645 | int i; | 645 | int i; |
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 1df284f9c2a1..9c21d19043a6 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c | |||
@@ -260,7 +260,7 @@ static struct miscdevice gef_wdt_miscdev = { | |||
260 | }; | 260 | }; |
261 | 261 | ||
262 | 262 | ||
263 | static int __devinit gef_wdt_probe(struct of_device *dev, | 263 | static int __devinit gef_wdt_probe(struct platform_device *dev, |
264 | const struct of_device_id *match) | 264 | const struct of_device_id *match) |
265 | { | 265 | { |
266 | int timeout = 10; | 266 | int timeout = 10; |
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 4cda64dd309c..8fa213cdb499 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c | |||
@@ -185,7 +185,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = { | |||
185 | .fops = &mpc8xxx_wdt_fops, | 185 | .fops = &mpc8xxx_wdt_fops, |
186 | }; | 186 | }; |
187 | 187 | ||
188 | static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, | 188 | static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev, |
189 | const struct of_device_id *match) | 189 | const struct of_device_id *match) |
190 | { | 190 | { |
191 | int ret; | 191 | int ret; |
@@ -238,7 +238,7 @@ err_unmap: | |||
238 | return ret; | 238 | return ret; |
239 | } | 239 | } |
240 | 240 | ||
241 | static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) | 241 | static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev) |
242 | { | 242 | { |
243 | mpc8xxx_wdt_pr_warn("watchdog removed"); | 243 | mpc8xxx_wdt_pr_warn("watchdog removed"); |
244 | del_timer_sync(&wdt_timer); | 244 | del_timer_sync(&wdt_timer); |
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 4082b4ace1fc..3faee1ae64bd 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c | |||
@@ -172,7 +172,7 @@ static struct miscdevice riowd_miscdev = { | |||
172 | .fops = &riowd_fops | 172 | .fops = &riowd_fops |
173 | }; | 173 | }; |
174 | 174 | ||
175 | static int __devinit riowd_probe(struct of_device *op, | 175 | static int __devinit riowd_probe(struct platform_device *op, |
176 | const struct of_device_id *match) | 176 | const struct of_device_id *match) |
177 | { | 177 | { |
178 | struct riowd *p; | 178 | struct riowd *p; |
@@ -219,7 +219,7 @@ out: | |||
219 | return err; | 219 | return err; |
220 | } | 220 | } |
221 | 221 | ||
222 | static int __devexit riowd_remove(struct of_device *op) | 222 | static int __devexit riowd_remove(struct platform_device *op) |
223 | { | 223 | { |
224 | struct riowd *p = dev_get_drvdata(&op->dev); | 224 | struct riowd *p = dev_get_drvdata(&op->dev); |
225 | 225 | ||
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 0a8826936639..60d71e9abe9f 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
@@ -71,4 +71,9 @@ config XEN_PLATFORM_PCI | |||
71 | initializing xenbus and grant_table when running in a Xen HVM | 71 | initializing xenbus and grant_table when running in a Xen HVM |
72 | domain. As a consequence this driver is required to run any Xen PV | 72 | domain. As a consequence this driver is required to run any Xen PV |
73 | frontend on Xen HVM. | 73 | frontend on Xen HVM. |
74 | |||
75 | config SWIOTLB_XEN | ||
76 | def_bool y | ||
77 | depends on SWIOTLB | ||
78 | |||
74 | endmenu | 79 | endmenu |
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index e392fb776af3..fcaf838f54be 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o | |||
11 | obj-$(CONFIG_XENFS) += xenfs/ | 11 | obj-$(CONFIG_XENFS) += xenfs/ |
12 | obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o | 12 | obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o |
13 | obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o | 13 | obj-$(CONFIG_XEN_PLATFORM_PCI) += platform-pci.o |
14 | obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o | ||
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 1a0d8c2a0354..500290b150bb 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -85,13 +85,6 @@ static struct sys_device balloon_sysdev; | |||
85 | 85 | ||
86 | static int register_balloon(struct sys_device *sysdev); | 86 | static int register_balloon(struct sys_device *sysdev); |
87 | 87 | ||
88 | /* | ||
89 | * Protects atomic reservation decrease/increase against concurrent increases. | ||
90 | * Also protects non-atomic updates of current_pages and driver_pages, and | ||
91 | * balloon lists. | ||
92 | */ | ||
93 | static DEFINE_SPINLOCK(balloon_lock); | ||
94 | |||
95 | static struct balloon_stats balloon_stats; | 88 | static struct balloon_stats balloon_stats; |
96 | 89 | ||
97 | /* We increase/decrease in batches which fit in a page */ | 90 | /* We increase/decrease in batches which fit in a page */ |
@@ -210,7 +203,7 @@ static int increase_reservation(unsigned long nr_pages) | |||
210 | if (nr_pages > ARRAY_SIZE(frame_list)) | 203 | if (nr_pages > ARRAY_SIZE(frame_list)) |
211 | nr_pages = ARRAY_SIZE(frame_list); | 204 | nr_pages = ARRAY_SIZE(frame_list); |
212 | 205 | ||
213 | spin_lock_irqsave(&balloon_lock, flags); | 206 | spin_lock_irqsave(&xen_reservation_lock, flags); |
214 | 207 | ||
215 | page = balloon_first_page(); | 208 | page = balloon_first_page(); |
216 | for (i = 0; i < nr_pages; i++) { | 209 | for (i = 0; i < nr_pages; i++) { |
@@ -254,7 +247,7 @@ static int increase_reservation(unsigned long nr_pages) | |||
254 | balloon_stats.current_pages += rc; | 247 | balloon_stats.current_pages += rc; |
255 | 248 | ||
256 | out: | 249 | out: |
257 | spin_unlock_irqrestore(&balloon_lock, flags); | 250 | spin_unlock_irqrestore(&xen_reservation_lock, flags); |
258 | 251 | ||
259 | return rc < 0 ? rc : rc != nr_pages; | 252 | return rc < 0 ? rc : rc != nr_pages; |
260 | } | 253 | } |
@@ -299,7 +292,7 @@ static int decrease_reservation(unsigned long nr_pages) | |||
299 | kmap_flush_unused(); | 292 | kmap_flush_unused(); |
300 | flush_tlb_all(); | 293 | flush_tlb_all(); |
301 | 294 | ||
302 | spin_lock_irqsave(&balloon_lock, flags); | 295 | spin_lock_irqsave(&xen_reservation_lock, flags); |
303 | 296 | ||
304 | /* No more mappings: invalidate P2M and add to balloon. */ | 297 | /* No more mappings: invalidate P2M and add to balloon. */ |
305 | for (i = 0; i < nr_pages; i++) { | 298 | for (i = 0; i < nr_pages; i++) { |
@@ -315,7 +308,7 @@ static int decrease_reservation(unsigned long nr_pages) | |||
315 | 308 | ||
316 | balloon_stats.current_pages -= nr_pages; | 309 | balloon_stats.current_pages -= nr_pages; |
317 | 310 | ||
318 | spin_unlock_irqrestore(&balloon_lock, flags); | 311 | spin_unlock_irqrestore(&xen_reservation_lock, flags); |
319 | 312 | ||
320 | return need_sleep; | 313 | return need_sleep; |
321 | } | 314 | } |
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c new file mode 100644 index 000000000000..54469c3eeacd --- /dev/null +++ b/drivers/xen/swiotlb-xen.c | |||
@@ -0,0 +1,515 @@ | |||
1 | /* | ||
2 | * Copyright 2010 | ||
3 | * by Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | ||
4 | * | ||
5 | * This code provides a IOMMU for Xen PV guests with PCI passthrough. | ||
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 v2.0 as published by | ||
9 | * the Free Software Foundation | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * PV guests under Xen are running in an non-contiguous memory architecture. | ||
17 | * | ||
18 | * When PCI pass-through is utilized, this necessitates an IOMMU for | ||
19 | * translating bus (DMA) to virtual and vice-versa and also providing a | ||
20 | * mechanism to have contiguous pages for device drivers operations (say DMA | ||
21 | * operations). | ||
22 | * | ||
23 | * Specifically, under Xen the Linux idea of pages is an illusion. It | ||
24 | * assumes that pages start at zero and go up to the available memory. To | ||
25 | * help with that, the Linux Xen MMU provides a lookup mechanism to | ||
26 | * translate the page frame numbers (PFN) to machine frame numbers (MFN) | ||
27 | * and vice-versa. The MFN are the "real" frame numbers. Furthermore | ||
28 | * memory is not contiguous. Xen hypervisor stitches memory for guests | ||
29 | * from different pools, which means there is no guarantee that PFN==MFN | ||
30 | * and PFN+1==MFN+1. Lastly with Xen 4.0, pages (in debug mode) are | ||
31 | * allocated in descending order (high to low), meaning the guest might | ||
32 | * never get any MFN's under the 4GB mark. | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | #include <linux/bootmem.h> | ||
37 | #include <linux/dma-mapping.h> | ||
38 | #include <xen/swiotlb-xen.h> | ||
39 | #include <xen/page.h> | ||
40 | #include <xen/xen-ops.h> | ||
41 | /* | ||
42 | * Used to do a quick range check in swiotlb_tbl_unmap_single and | ||
43 | * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this | ||
44 | * API. | ||
45 | */ | ||
46 | |||
47 | static char *xen_io_tlb_start, *xen_io_tlb_end; | ||
48 | static unsigned long xen_io_tlb_nslabs; | ||
49 | /* | ||
50 | * Quick lookup value of the bus address of the IOTLB. | ||
51 | */ | ||
52 | |||
53 | u64 start_dma_addr; | ||
54 | |||
55 | static dma_addr_t xen_phys_to_bus(phys_addr_t paddr) | ||
56 | { | ||
57 | return phys_to_machine(XPADDR(paddr)).maddr;; | ||
58 | } | ||
59 | |||
60 | static phys_addr_t xen_bus_to_phys(dma_addr_t baddr) | ||
61 | { | ||
62 | return machine_to_phys(XMADDR(baddr)).paddr; | ||
63 | } | ||
64 | |||
65 | static dma_addr_t xen_virt_to_bus(void *address) | ||
66 | { | ||
67 | return xen_phys_to_bus(virt_to_phys(address)); | ||
68 | } | ||
69 | |||
70 | static int check_pages_physically_contiguous(unsigned long pfn, | ||
71 | unsigned int offset, | ||
72 | size_t length) | ||
73 | { | ||
74 | unsigned long next_mfn; | ||
75 | int i; | ||
76 | int nr_pages; | ||
77 | |||
78 | next_mfn = pfn_to_mfn(pfn); | ||
79 | nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT; | ||
80 | |||
81 | for (i = 1; i < nr_pages; i++) { | ||
82 | if (pfn_to_mfn(++pfn) != ++next_mfn) | ||
83 | return 0; | ||
84 | } | ||
85 | return 1; | ||
86 | } | ||
87 | |||
88 | static int range_straddles_page_boundary(phys_addr_t p, size_t size) | ||
89 | { | ||
90 | unsigned long pfn = PFN_DOWN(p); | ||
91 | unsigned int offset = p & ~PAGE_MASK; | ||
92 | |||
93 | if (offset + size <= PAGE_SIZE) | ||
94 | return 0; | ||
95 | if (check_pages_physically_contiguous(pfn, offset, size)) | ||
96 | return 0; | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | static int is_xen_swiotlb_buffer(dma_addr_t dma_addr) | ||
101 | { | ||
102 | unsigned long mfn = PFN_DOWN(dma_addr); | ||
103 | unsigned long pfn = mfn_to_local_pfn(mfn); | ||
104 | phys_addr_t paddr; | ||
105 | |||
106 | /* If the address is outside our domain, it CAN | ||
107 | * have the same virtual address as another address | ||
108 | * in our domain. Therefore _only_ check address within our domain. | ||
109 | */ | ||
110 | if (pfn_valid(pfn)) { | ||
111 | paddr = PFN_PHYS(pfn); | ||
112 | return paddr >= virt_to_phys(xen_io_tlb_start) && | ||
113 | paddr < virt_to_phys(xen_io_tlb_end); | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int max_dma_bits = 32; | ||
119 | |||
120 | static int | ||
121 | xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) | ||
122 | { | ||
123 | int i, rc; | ||
124 | int dma_bits; | ||
125 | |||
126 | dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT; | ||
127 | |||
128 | i = 0; | ||
129 | do { | ||
130 | int slabs = min(nslabs - i, (unsigned long)IO_TLB_SEGSIZE); | ||
131 | |||
132 | do { | ||
133 | rc = xen_create_contiguous_region( | ||
134 | (unsigned long)buf + (i << IO_TLB_SHIFT), | ||
135 | get_order(slabs << IO_TLB_SHIFT), | ||
136 | dma_bits); | ||
137 | } while (rc && dma_bits++ < max_dma_bits); | ||
138 | if (rc) | ||
139 | return rc; | ||
140 | |||
141 | i += slabs; | ||
142 | } while (i < nslabs); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | void __init xen_swiotlb_init(int verbose) | ||
147 | { | ||
148 | unsigned long bytes; | ||
149 | int rc; | ||
150 | |||
151 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); | ||
152 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); | ||
153 | |||
154 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; | ||
155 | |||
156 | /* | ||
157 | * Get IO TLB memory from any location. | ||
158 | */ | ||
159 | xen_io_tlb_start = alloc_bootmem(bytes); | ||
160 | if (!xen_io_tlb_start) | ||
161 | panic("Cannot allocate SWIOTLB buffer"); | ||
162 | |||
163 | xen_io_tlb_end = xen_io_tlb_start + bytes; | ||
164 | /* | ||
165 | * And replace that memory with pages under 4GB. | ||
166 | */ | ||
167 | rc = xen_swiotlb_fixup(xen_io_tlb_start, | ||
168 | bytes, | ||
169 | xen_io_tlb_nslabs); | ||
170 | if (rc) | ||
171 | goto error; | ||
172 | |||
173 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); | ||
174 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | ||
175 | |||
176 | return; | ||
177 | error: | ||
178 | panic("DMA(%d): Failed to exchange pages allocated for DMA with Xen! "\ | ||
179 | "We either don't have the permission or you do not have enough"\ | ||
180 | "free memory under 4GB!\n", rc); | ||
181 | } | ||
182 | |||
183 | void * | ||
184 | xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | ||
185 | dma_addr_t *dma_handle, gfp_t flags) | ||
186 | { | ||
187 | void *ret; | ||
188 | int order = get_order(size); | ||
189 | u64 dma_mask = DMA_BIT_MASK(32); | ||
190 | unsigned long vstart; | ||
191 | |||
192 | /* | ||
193 | * Ignore region specifiers - the kernel's ideas of | ||
194 | * pseudo-phys memory layout has nothing to do with the | ||
195 | * machine physical layout. We can't allocate highmem | ||
196 | * because we can't return a pointer to it. | ||
197 | */ | ||
198 | flags &= ~(__GFP_DMA | __GFP_HIGHMEM); | ||
199 | |||
200 | if (dma_alloc_from_coherent(hwdev, size, dma_handle, &ret)) | ||
201 | return ret; | ||
202 | |||
203 | vstart = __get_free_pages(flags, order); | ||
204 | ret = (void *)vstart; | ||
205 | |||
206 | if (hwdev && hwdev->coherent_dma_mask) | ||
207 | dma_mask = dma_alloc_coherent_mask(hwdev, flags); | ||
208 | |||
209 | if (ret) { | ||
210 | if (xen_create_contiguous_region(vstart, order, | ||
211 | fls64(dma_mask)) != 0) { | ||
212 | free_pages(vstart, order); | ||
213 | return NULL; | ||
214 | } | ||
215 | memset(ret, 0, size); | ||
216 | *dma_handle = virt_to_machine(ret).maddr; | ||
217 | } | ||
218 | return ret; | ||
219 | } | ||
220 | EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent); | ||
221 | |||
222 | void | ||
223 | xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, | ||
224 | dma_addr_t dev_addr) | ||
225 | { | ||
226 | int order = get_order(size); | ||
227 | |||
228 | if (dma_release_from_coherent(hwdev, order, vaddr)) | ||
229 | return; | ||
230 | |||
231 | xen_destroy_contiguous_region((unsigned long)vaddr, order); | ||
232 | free_pages((unsigned long)vaddr, order); | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent); | ||
235 | |||
236 | |||
237 | /* | ||
238 | * Map a single buffer of the indicated size for DMA in streaming mode. The | ||
239 | * physical address to use is returned. | ||
240 | * | ||
241 | * Once the device is given the dma address, the device owns this memory until | ||
242 | * either xen_swiotlb_unmap_page or xen_swiotlb_dma_sync_single is performed. | ||
243 | */ | ||
244 | dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, | ||
245 | unsigned long offset, size_t size, | ||
246 | enum dma_data_direction dir, | ||
247 | struct dma_attrs *attrs) | ||
248 | { | ||
249 | phys_addr_t phys = page_to_phys(page) + offset; | ||
250 | dma_addr_t dev_addr = xen_phys_to_bus(phys); | ||
251 | void *map; | ||
252 | |||
253 | BUG_ON(dir == DMA_NONE); | ||
254 | /* | ||
255 | * If the address happens to be in the device's DMA window, | ||
256 | * we can safely return the device addr and not worry about bounce | ||
257 | * buffering it. | ||
258 | */ | ||
259 | if (dma_capable(dev, dev_addr, size) && | ||
260 | !range_straddles_page_boundary(phys, size) && !swiotlb_force) | ||
261 | return dev_addr; | ||
262 | |||
263 | /* | ||
264 | * Oh well, have to allocate and map a bounce buffer. | ||
265 | */ | ||
266 | map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir); | ||
267 | if (!map) | ||
268 | return DMA_ERROR_CODE; | ||
269 | |||
270 | dev_addr = xen_virt_to_bus(map); | ||
271 | |||
272 | /* | ||
273 | * Ensure that the address returned is DMA'ble | ||
274 | */ | ||
275 | if (!dma_capable(dev, dev_addr, size)) | ||
276 | panic("map_single: bounce buffer is not DMA'ble"); | ||
277 | |||
278 | return dev_addr; | ||
279 | } | ||
280 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_page); | ||
281 | |||
282 | /* | ||
283 | * Unmap a single streaming mode DMA translation. The dma_addr and size must | ||
284 | * match what was provided for in a previous xen_swiotlb_map_page call. All | ||
285 | * other usages are undefined. | ||
286 | * | ||
287 | * After this call, reads by the cpu to the buffer are guaranteed to see | ||
288 | * whatever the device wrote there. | ||
289 | */ | ||
290 | static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr, | ||
291 | size_t size, enum dma_data_direction dir) | ||
292 | { | ||
293 | phys_addr_t paddr = xen_bus_to_phys(dev_addr); | ||
294 | |||
295 | BUG_ON(dir == DMA_NONE); | ||
296 | |||
297 | /* NOTE: We use dev_addr here, not paddr! */ | ||
298 | if (is_xen_swiotlb_buffer(dev_addr)) { | ||
299 | swiotlb_tbl_unmap_single(hwdev, phys_to_virt(paddr), size, dir); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | if (dir != DMA_FROM_DEVICE) | ||
304 | return; | ||
305 | |||
306 | /* | ||
307 | * phys_to_virt doesn't work with hihgmem page but we could | ||
308 | * call dma_mark_clean() with hihgmem page here. However, we | ||
309 | * are fine since dma_mark_clean() is null on POWERPC. We can | ||
310 | * make dma_mark_clean() take a physical address if necessary. | ||
311 | */ | ||
312 | dma_mark_clean(phys_to_virt(paddr), size); | ||
313 | } | ||
314 | |||
315 | void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, | ||
316 | size_t size, enum dma_data_direction dir, | ||
317 | struct dma_attrs *attrs) | ||
318 | { | ||
319 | xen_unmap_single(hwdev, dev_addr, size, dir); | ||
320 | } | ||
321 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_page); | ||
322 | |||
323 | /* | ||
324 | * Make physical memory consistent for a single streaming mode DMA translation | ||
325 | * after a transfer. | ||
326 | * | ||
327 | * If you perform a xen_swiotlb_map_page() but wish to interrogate the buffer | ||
328 | * using the cpu, yet do not wish to teardown the dma mapping, you must | ||
329 | * call this function before doing so. At the next point you give the dma | ||
330 | * address back to the card, you must first perform a | ||
331 | * xen_swiotlb_dma_sync_for_device, and then the device again owns the buffer | ||
332 | */ | ||
333 | static void | ||
334 | xen_swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, | ||
335 | size_t size, enum dma_data_direction dir, | ||
336 | enum dma_sync_target target) | ||
337 | { | ||
338 | phys_addr_t paddr = xen_bus_to_phys(dev_addr); | ||
339 | |||
340 | BUG_ON(dir == DMA_NONE); | ||
341 | |||
342 | /* NOTE: We use dev_addr here, not paddr! */ | ||
343 | if (is_xen_swiotlb_buffer(dev_addr)) { | ||
344 | swiotlb_tbl_sync_single(hwdev, phys_to_virt(paddr), size, dir, | ||
345 | target); | ||
346 | return; | ||
347 | } | ||
348 | |||
349 | if (dir != DMA_FROM_DEVICE) | ||
350 | return; | ||
351 | |||
352 | dma_mark_clean(phys_to_virt(paddr), size); | ||
353 | } | ||
354 | |||
355 | void | ||
356 | xen_swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr, | ||
357 | size_t size, enum dma_data_direction dir) | ||
358 | { | ||
359 | xen_swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_CPU); | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_single_for_cpu); | ||
362 | |||
363 | void | ||
364 | xen_swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr, | ||
365 | size_t size, enum dma_data_direction dir) | ||
366 | { | ||
367 | xen_swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_DEVICE); | ||
368 | } | ||
369 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_single_for_device); | ||
370 | |||
371 | /* | ||
372 | * Map a set of buffers described by scatterlist in streaming mode for DMA. | ||
373 | * This is the scatter-gather version of the above xen_swiotlb_map_page | ||
374 | * interface. Here the scatter gather list elements are each tagged with the | ||
375 | * appropriate dma address and length. They are obtained via | ||
376 | * sg_dma_{address,length}(SG). | ||
377 | * | ||
378 | * NOTE: An implementation may be able to use a smaller number of | ||
379 | * DMA address/length pairs than there are SG table elements. | ||
380 | * (for example via virtual mapping capabilities) | ||
381 | * The routine returns the number of addr/length pairs actually | ||
382 | * used, at most nents. | ||
383 | * | ||
384 | * Device ownership issues as mentioned above for xen_swiotlb_map_page are the | ||
385 | * same here. | ||
386 | */ | ||
387 | int | ||
388 | xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | ||
389 | int nelems, enum dma_data_direction dir, | ||
390 | struct dma_attrs *attrs) | ||
391 | { | ||
392 | struct scatterlist *sg; | ||
393 | int i; | ||
394 | |||
395 | BUG_ON(dir == DMA_NONE); | ||
396 | |||
397 | for_each_sg(sgl, sg, nelems, i) { | ||
398 | phys_addr_t paddr = sg_phys(sg); | ||
399 | dma_addr_t dev_addr = xen_phys_to_bus(paddr); | ||
400 | |||
401 | if (swiotlb_force || | ||
402 | !dma_capable(hwdev, dev_addr, sg->length) || | ||
403 | range_straddles_page_boundary(paddr, sg->length)) { | ||
404 | void *map = swiotlb_tbl_map_single(hwdev, | ||
405 | start_dma_addr, | ||
406 | sg_phys(sg), | ||
407 | sg->length, dir); | ||
408 | if (!map) { | ||
409 | /* Don't panic here, we expect map_sg users | ||
410 | to do proper error handling. */ | ||
411 | xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir, | ||
412 | attrs); | ||
413 | sgl[0].dma_length = 0; | ||
414 | return DMA_ERROR_CODE; | ||
415 | } | ||
416 | sg->dma_address = xen_virt_to_bus(map); | ||
417 | } else | ||
418 | sg->dma_address = dev_addr; | ||
419 | sg->dma_length = sg->length; | ||
420 | } | ||
421 | return nelems; | ||
422 | } | ||
423 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs); | ||
424 | |||
425 | int | ||
426 | xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | ||
427 | enum dma_data_direction dir) | ||
428 | { | ||
429 | return xen_swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL); | ||
430 | } | ||
431 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg); | ||
432 | |||
433 | /* | ||
434 | * Unmap a set of streaming mode DMA translations. Again, cpu read rules | ||
435 | * concerning calls here are the same as for swiotlb_unmap_page() above. | ||
436 | */ | ||
437 | void | ||
438 | xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | ||
439 | int nelems, enum dma_data_direction dir, | ||
440 | struct dma_attrs *attrs) | ||
441 | { | ||
442 | struct scatterlist *sg; | ||
443 | int i; | ||
444 | |||
445 | BUG_ON(dir == DMA_NONE); | ||
446 | |||
447 | for_each_sg(sgl, sg, nelems, i) | ||
448 | xen_unmap_single(hwdev, sg->dma_address, sg->dma_length, dir); | ||
449 | |||
450 | } | ||
451 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs); | ||
452 | |||
453 | void | ||
454 | xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | ||
455 | enum dma_data_direction dir) | ||
456 | { | ||
457 | return xen_swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL); | ||
458 | } | ||
459 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg); | ||
460 | |||
461 | /* | ||
462 | * Make physical memory consistent for a set of streaming mode DMA translations | ||
463 | * after a transfer. | ||
464 | * | ||
465 | * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules | ||
466 | * and usage. | ||
467 | */ | ||
468 | static void | ||
469 | xen_swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl, | ||
470 | int nelems, enum dma_data_direction dir, | ||
471 | enum dma_sync_target target) | ||
472 | { | ||
473 | struct scatterlist *sg; | ||
474 | int i; | ||
475 | |||
476 | for_each_sg(sgl, sg, nelems, i) | ||
477 | xen_swiotlb_sync_single(hwdev, sg->dma_address, | ||
478 | sg->dma_length, dir, target); | ||
479 | } | ||
480 | |||
481 | void | ||
482 | xen_swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, | ||
483 | int nelems, enum dma_data_direction dir) | ||
484 | { | ||
485 | xen_swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_CPU); | ||
486 | } | ||
487 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_sg_for_cpu); | ||
488 | |||
489 | void | ||
490 | xen_swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, | ||
491 | int nelems, enum dma_data_direction dir) | ||
492 | { | ||
493 | xen_swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); | ||
494 | } | ||
495 | EXPORT_SYMBOL_GPL(xen_swiotlb_sync_sg_for_device); | ||
496 | |||
497 | int | ||
498 | xen_swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr) | ||
499 | { | ||
500 | return !dma_addr; | ||
501 | } | ||
502 | EXPORT_SYMBOL_GPL(xen_swiotlb_dma_mapping_error); | ||
503 | |||
504 | /* | ||
505 | * Return whether the given device DMA address mask can be supported | ||
506 | * properly. For example, if your device can only drive the low 24-bits | ||
507 | * during bus mastering, then you would pass 0x00ffffff as the mask to | ||
508 | * this function. | ||
509 | */ | ||
510 | int | ||
511 | xen_swiotlb_dma_supported(struct device *hwdev, u64 mask) | ||
512 | { | ||
513 | return xen_virt_to_bus(xen_io_tlb_end - 1) <= mask; | ||
514 | } | ||
515 | EXPORT_SYMBOL_GPL(xen_swiotlb_dma_supported); | ||