]> rtime.felk.cvut.cz Git - socketcan-devel.git/blob - patch-series/net-2.6.29/06-sja1000-platform-driver.patch
Prelimary quilt patch stack for including the device drivers interface
[socketcan-devel.git] / patch-series / net-2.6.29 / 06-sja1000-platform-driver.patch
1 [PATCH 6/9] Socket-CAN: SJA1000: generic platform bus driver
2
3 This driver adds support for the SJA1000 chips connected to the
4 "platform bus", which can be found on various embedded systems.
5
6 Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
7 Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
8 Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
9 Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
10 ---
11  drivers/net/can/Kconfig                    |   10 +
12  drivers/net/can/sja1000/Makefile           |    1 
13  drivers/net/can/sja1000/sja1000_platform.c |  169 +++++++++++++++++++++++++++++
14  include/linux/can/platform/sja1000.h       |   32 +++++
15  4 files changed, 212 insertions(+)
16
17 Index: net-next-2.6/drivers/net/can/sja1000/sja1000_platform.c
18 ===================================================================
19 --- /dev/null
20 +++ net-next-2.6/drivers/net/can/sja1000/sja1000_platform.c
21 @@ -0,0 +1,169 @@
22 +/*
23 + * Copyright (C) 2005 Sascha Hauer, Pengutronix
24 + * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
25 + *
26 + * This program is free software; you can redistribute it and/or modify
27 + * it under the terms of the version 2 of the GNU General Public License
28 + * as published by the Free Software Foundation
29 + *
30 + * This program is distributed in the hope that it will be useful,
31 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 + * GNU General Public License for more details.
34 + *
35 + * You should have received a copy of the GNU General Public License
36 + * along with this program; if not, write to the Free Software
37 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
38 + */
39 +
40 +#include <linux/kernel.h>
41 +#include <linux/module.h>
42 +#include <linux/interrupt.h>
43 +#include <linux/netdevice.h>
44 +#include <linux/delay.h>
45 +#include <linux/pci.h>
46 +#include <linux/platform_device.h>
47 +#include <linux/irq.h>
48 +#include <linux/can.h>
49 +#include <linux/can/dev.h>
50 +#include <linux/can/platform/sja1000.h>
51 +#include <linux/io.h>
52 +
53 +#include "sja1000.h"
54 +
55 +#define DRV_NAME "sja1000_platform"
56 +
57 +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
58 +MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
59 +MODULE_LICENSE("GPL v2");
60 +
61 +static u8 sp_read_reg(struct net_device *dev, int reg)
62 +{
63 +       return ioread8((void __iomem *)(dev->base_addr + reg));
64 +}
65 +
66 +static void sp_write_reg(struct net_device *dev, int reg, u8 val)
67 +{
68 +       iowrite8(val, (void __iomem *)(dev->base_addr + reg));
69 +}
70 +
71 +static int sp_probe(struct platform_device *pdev)
72 +{
73 +       int err, irq;
74 +       void __iomem *addr;
75 +       struct net_device *dev;
76 +       struct sja1000_priv *priv;
77 +       struct resource *res_mem, *res_irq;
78 +       struct sja1000_platform_data *pdata;
79 +
80 +       pdata = pdev->dev.platform_data;
81 +       if (!pdata) {
82 +               dev_err(&pdev->dev, "No platform data provided!\n");
83 +               err = -ENODEV;
84 +               goto exit;
85 +       }
86 +
87 +       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
88 +       res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
89 +       if (!res_mem || !res_irq) {
90 +               err = -ENODEV;
91 +               goto exit;
92 +       }
93 +
94 +       if (!request_mem_region(res_mem->start,
95 +                               res_mem->end - res_mem->start + 1,
96 +                               DRV_NAME)) {
97 +               err = -EBUSY;
98 +               goto exit;
99 +       }
100 +
101 +       addr = ioremap_nocache(res_mem->start,
102 +                              res_mem->end - res_mem->start + 1);
103 +       if (!addr) {
104 +               err = -ENOMEM;
105 +               goto exit_release;
106 +       }
107 +
108 +       irq = res_irq->start;
109 +       if (res_irq->flags & IRQF_TRIGGER_MASK)
110 +               set_irq_type(irq, res_irq->flags & IRQF_TRIGGER_MASK);
111 +
112 +       dev = alloc_sja1000dev(0);
113 +       if (!dev) {
114 +               err = -ENOMEM;
115 +               goto exit_iounmap;
116 +       }
117 +       priv = netdev_priv(dev);
118 +
119 +       priv->read_reg = sp_read_reg;
120 +       priv->write_reg = sp_write_reg;
121 +       priv->can.bittiming.clock = pdata->clock;
122 +       priv->ocr = pdata->ocr;
123 +       priv->cdr = pdata->cdr;
124 +
125 +       dev->irq = irq;
126 +       dev->base_addr = (unsigned long)addr;
127 +
128 +       dev_set_drvdata(&pdev->dev, dev);
129 +       SET_NETDEV_DEV(dev, &pdev->dev);
130 +
131 +       err = register_sja1000dev(dev);
132 +       if (err) {
133 +               dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
134 +                       DRV_NAME, err);
135 +               goto exit_free;
136 +       }
137 +
138 +       dev_info(&pdev->dev, "%s device registered (base_addr=%#lx, irq=%d)\n",
139 +                DRV_NAME, dev->base_addr, dev->irq);
140 +       return 0;
141 +
142 + exit_free:
143 +       free_sja1000dev(dev);
144 + exit_iounmap:
145 +       iounmap(addr);
146 + exit_release:
147 +       release_mem_region(res_mem->start, res_mem->end - res_mem->start + 1);
148 + exit:
149 +       return err;
150 +}
151 +
152 +static int sp_remove(struct platform_device *pdev)
153 +{
154 +       struct net_device *dev = dev_get_drvdata(&pdev->dev);
155 +       struct resource *res;
156 +
157 +       unregister_sja1000dev(dev);
158 +       dev_set_drvdata(&pdev->dev, NULL);
159 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
160 +       release_mem_region(res->start, res->end - res->start + 1);
161 +
162 +       if (dev->base_addr)
163 +               iounmap((void __iomem *)dev->base_addr);
164 +
165 +       free_sja1000dev(dev);
166 +
167 +       return 0;
168 +}
169 +
170 +static struct platform_driver sp_driver = {
171 +       .probe = sp_probe,
172 +       .remove = sp_remove,
173 +       .driver = {
174 +               .name = DRV_NAME,
175 +               .owner = THIS_MODULE,
176 +       },
177 +};
178 +
179 +static int __init sp_init(void)
180 +{
181 +       return platform_driver_register(&sp_driver);
182 +}
183 +
184 +static void __exit sp_exit(void)
185 +{
186 +       platform_driver_unregister(&sp_driver);
187 +}
188 +
189 +module_init(sp_init);
190 +module_exit(sp_exit);
191 Index: net-next-2.6/include/linux/can/platform/sja1000.h
192 ===================================================================
193 --- /dev/null
194 +++ net-next-2.6/include/linux/can/platform/sja1000.h
195 @@ -0,0 +1,32 @@
196 +#ifndef _CAN_PLATFORM_SJA1000_H_
197 +#define _CAN_PLATFORM_SJA1000_H_
198 +
199 +/* clock divider register */
200 +#define CDR_CLKOUT_MASK 0x07
201 +#define CDR_CLK_OFF    0x08 /* Clock off (CLKOUT pin) */
202 +#define CDR_RXINPEN    0x20 /* TX1 output is RX irq output */
203 +#define CDR_CBP                0x40 /* CAN input comparator bypass */
204 +#define CDR_PELICAN    0x80 /* PeliCAN mode */
205 +
206 +/* output control register */
207 +#define OCR_MODE_BIPHASE  0x00
208 +#define OCR_MODE_TEST     0x01
209 +#define OCR_MODE_NORMAL   0x02
210 +#define OCR_MODE_CLOCK    0x03
211 +#define OCR_TX0_INVERT    0x04
212 +#define OCR_TX0_PULLDOWN  0x08
213 +#define OCR_TX0_PULLUP    0x10
214 +#define OCR_TX0_PUSHPULL  0x18
215 +#define OCR_TX1_INVERT    0x20
216 +#define OCR_TX1_PULLDOWN  0x40
217 +#define OCR_TX1_PULLUP    0x80
218 +#define OCR_TX1_PUSHPULL  0xc0
219 +
220 +struct sja1000_platform_data {
221 +       u32 clock;      /* CAN bus oscillator frequency in Hz */
222 +
223 +       u8 ocr;         /* output control register */
224 +       u8 cdr;         /* clock divider register */
225 +};
226 +
227 +#endif /* !_CAN_PLATFORM_SJA1000_H_ */
228 Index: net-next-2.6/drivers/net/can/Kconfig
229 ===================================================================
230 --- net-next-2.6.orig/drivers/net/can/Kconfig
231 +++ net-next-2.6/drivers/net/can/Kconfig
232 @@ -46,4 +46,14 @@ config CAN_SJA1000
233           It can send and receive any kinds of CAN frames (SFF/EFF/RTR)
234           with a single (simple) filter setup.
235  
236 +config CAN_SJA1000_PLATFORM
237 +       depends on CAN_SJA1000
238 +       tristate "Generic Platform Bus based SJA1000 driver"
239 +       ---help---
240 +         This driver adds support for the SJA1000 chips connected to
241 +         the "platform bus" (Linux abstraction for directly to the
242 +         processor attached devices).  Which can be found on various
243 +         boards from Phytec (http://www.phytec.de) like the PCM027,
244 +         PCM038.
245 +
246  endmenu
247 Index: net-next-2.6/drivers/net/can/sja1000/Makefile
248 ===================================================================
249 --- net-next-2.6.orig/drivers/net/can/sja1000/Makefile
250 +++ net-next-2.6/drivers/net/can/sja1000/Makefile
251 @@ -3,5 +3,6 @@
252  #
253  
254  obj-$(CONFIG_CAN_SJA1000) += sja1000.o
255 +obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
256  
257  ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG