Commit 50c01fc355c6a97c511d58411f9bc0e4b8fc4659

Authored by Jamie Iles
Committed by Grant Likely
1 parent 76d9cc454a

spi/dw_spi: don't treat NULL clk as an error

clk_get() returns a struct clk cookie to the driver and some platforms
may return NULL if they only support a single clock.  clk_get() has only
failed if it returns a ERR_PTR() encoded pointer.

Signed-off-by: Jamie Iles <jamie@jamieiles.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

Showing 1 changed file with 3 additions and 2 deletions Inline Diff

drivers/spi/dw_spi_mmio.c
1 /* 1 /*
2 * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core 2 * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core
3 * 3 *
4 * Copyright (c) 2010, Octasic semiconductor. 4 * Copyright (c) 2010, Octasic semiconductor.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation. 8 * version 2, as published by the Free Software Foundation.
9 */ 9 */
10 10
11 #include <linux/clk.h> 11 #include <linux/clk.h>
12 #include <linux/err.h>
12 #include <linux/interrupt.h> 13 #include <linux/interrupt.h>
13 #include <linux/platform_device.h> 14 #include <linux/platform_device.h>
14 #include <linux/slab.h> 15 #include <linux/slab.h>
15 #include <linux/spi/dw_spi.h> 16 #include <linux/spi/dw_spi.h>
16 #include <linux/spi/spi.h> 17 #include <linux/spi/spi.h>
17 18
18 #define DRIVER_NAME "dw_spi_mmio" 19 #define DRIVER_NAME "dw_spi_mmio"
19 20
20 struct dw_spi_mmio { 21 struct dw_spi_mmio {
21 struct dw_spi dws; 22 struct dw_spi dws;
22 struct clk *clk; 23 struct clk *clk;
23 }; 24 };
24 25
25 static int __devinit dw_spi_mmio_probe(struct platform_device *pdev) 26 static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
26 { 27 {
27 struct dw_spi_mmio *dwsmmio; 28 struct dw_spi_mmio *dwsmmio;
28 struct dw_spi *dws; 29 struct dw_spi *dws;
29 struct resource *mem, *ioarea; 30 struct resource *mem, *ioarea;
30 int ret; 31 int ret;
31 32
32 dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL); 33 dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
33 if (!dwsmmio) { 34 if (!dwsmmio) {
34 ret = -ENOMEM; 35 ret = -ENOMEM;
35 goto err_end; 36 goto err_end;
36 } 37 }
37 38
38 dws = &dwsmmio->dws; 39 dws = &dwsmmio->dws;
39 40
40 /* Get basic io resource and map it */ 41 /* Get basic io resource and map it */
41 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 42 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42 if (!mem) { 43 if (!mem) {
43 dev_err(&pdev->dev, "no mem resource?\n"); 44 dev_err(&pdev->dev, "no mem resource?\n");
44 ret = -EINVAL; 45 ret = -EINVAL;
45 goto err_kfree; 46 goto err_kfree;
46 } 47 }
47 48
48 ioarea = request_mem_region(mem->start, resource_size(mem), 49 ioarea = request_mem_region(mem->start, resource_size(mem),
49 pdev->name); 50 pdev->name);
50 if (!ioarea) { 51 if (!ioarea) {
51 dev_err(&pdev->dev, "SPI region already claimed\n"); 52 dev_err(&pdev->dev, "SPI region already claimed\n");
52 ret = -EBUSY; 53 ret = -EBUSY;
53 goto err_kfree; 54 goto err_kfree;
54 } 55 }
55 56
56 dws->regs = ioremap_nocache(mem->start, resource_size(mem)); 57 dws->regs = ioremap_nocache(mem->start, resource_size(mem));
57 if (!dws->regs) { 58 if (!dws->regs) {
58 dev_err(&pdev->dev, "SPI region already mapped\n"); 59 dev_err(&pdev->dev, "SPI region already mapped\n");
59 ret = -ENOMEM; 60 ret = -ENOMEM;
60 goto err_release_reg; 61 goto err_release_reg;
61 } 62 }
62 63
63 dws->irq = platform_get_irq(pdev, 0); 64 dws->irq = platform_get_irq(pdev, 0);
64 if (dws->irq < 0) { 65 if (dws->irq < 0) {
65 dev_err(&pdev->dev, "no irq resource?\n"); 66 dev_err(&pdev->dev, "no irq resource?\n");
66 ret = dws->irq; /* -ENXIO */ 67 ret = dws->irq; /* -ENXIO */
67 goto err_unmap; 68 goto err_unmap;
68 } 69 }
69 70
70 dwsmmio->clk = clk_get(&pdev->dev, NULL); 71 dwsmmio->clk = clk_get(&pdev->dev, NULL);
71 if (!dwsmmio->clk) { 72 if (IS_ERR(dwsmmio->clk)) {
72 ret = -ENODEV; 73 ret = PTR_ERR(dwsmmio->clk);
73 goto err_irq; 74 goto err_irq;
74 } 75 }
75 clk_enable(dwsmmio->clk); 76 clk_enable(dwsmmio->clk);
76 77
77 dws->parent_dev = &pdev->dev; 78 dws->parent_dev = &pdev->dev;
78 dws->bus_num = 0; 79 dws->bus_num = 0;
79 dws->num_cs = 4; 80 dws->num_cs = 4;
80 dws->max_freq = clk_get_rate(dwsmmio->clk); 81 dws->max_freq = clk_get_rate(dwsmmio->clk);
81 82
82 ret = dw_spi_add_host(dws); 83 ret = dw_spi_add_host(dws);
83 if (ret) 84 if (ret)
84 goto err_clk; 85 goto err_clk;
85 86
86 platform_set_drvdata(pdev, dwsmmio); 87 platform_set_drvdata(pdev, dwsmmio);
87 return 0; 88 return 0;
88 89
89 err_clk: 90 err_clk:
90 clk_disable(dwsmmio->clk); 91 clk_disable(dwsmmio->clk);
91 clk_put(dwsmmio->clk); 92 clk_put(dwsmmio->clk);
92 dwsmmio->clk = NULL; 93 dwsmmio->clk = NULL;
93 err_irq: 94 err_irq:
94 free_irq(dws->irq, dws); 95 free_irq(dws->irq, dws);
95 err_unmap: 96 err_unmap:
96 iounmap(dws->regs); 97 iounmap(dws->regs);
97 err_release_reg: 98 err_release_reg:
98 release_mem_region(mem->start, resource_size(mem)); 99 release_mem_region(mem->start, resource_size(mem));
99 err_kfree: 100 err_kfree:
100 kfree(dwsmmio); 101 kfree(dwsmmio);
101 err_end: 102 err_end:
102 return ret; 103 return ret;
103 } 104 }
104 105
105 static int __devexit dw_spi_mmio_remove(struct platform_device *pdev) 106 static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
106 { 107 {
107 struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev); 108 struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
108 struct resource *mem; 109 struct resource *mem;
109 110
110 platform_set_drvdata(pdev, NULL); 111 platform_set_drvdata(pdev, NULL);
111 112
112 clk_disable(dwsmmio->clk); 113 clk_disable(dwsmmio->clk);
113 clk_put(dwsmmio->clk); 114 clk_put(dwsmmio->clk);
114 dwsmmio->clk = NULL; 115 dwsmmio->clk = NULL;
115 116
116 free_irq(dwsmmio->dws.irq, &dwsmmio->dws); 117 free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
117 dw_spi_remove_host(&dwsmmio->dws); 118 dw_spi_remove_host(&dwsmmio->dws);
118 iounmap(dwsmmio->dws.regs); 119 iounmap(dwsmmio->dws.regs);
119 kfree(dwsmmio); 120 kfree(dwsmmio);
120 121
121 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 122 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
122 release_mem_region(mem->start, resource_size(mem)); 123 release_mem_region(mem->start, resource_size(mem));
123 return 0; 124 return 0;
124 } 125 }
125 126
126 static struct platform_driver dw_spi_mmio_driver = { 127 static struct platform_driver dw_spi_mmio_driver = {
127 .remove = __devexit_p(dw_spi_mmio_remove), 128 .remove = __devexit_p(dw_spi_mmio_remove),
128 .driver = { 129 .driver = {
129 .name = DRIVER_NAME, 130 .name = DRIVER_NAME,
130 .owner = THIS_MODULE, 131 .owner = THIS_MODULE,
131 }, 132 },
132 }; 133 };
133 134
134 static int __init dw_spi_mmio_init(void) 135 static int __init dw_spi_mmio_init(void)
135 { 136 {
136 return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe); 137 return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe);
137 } 138 }
138 module_init(dw_spi_mmio_init); 139 module_init(dw_spi_mmio_init);
139 140
140 static void __exit dw_spi_mmio_exit(void) 141 static void __exit dw_spi_mmio_exit(void)
141 { 142 {
142 platform_driver_unregister(&dw_spi_mmio_driver); 143 platform_driver_unregister(&dw_spi_mmio_driver);
143 } 144 }
144 module_exit(dw_spi_mmio_exit); 145 module_exit(dw_spi_mmio_exit);
145 146
146 MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>"); 147 MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
147 MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core"); 148 MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
148 MODULE_LICENSE("GPL v2"); 149 MODULE_LICENSE("GPL v2");
149 150