aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorWolfgang Grandegger <wg@grandegger.com>2009-05-15 19:39:31 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-18 18:41:42 -0400
commitf534e52f091a7b9f51fb6726710bdf731b663e94 (patch)
treef1faad4e595abf44eae5a4942401f1fac14f1494 /drivers/net/can
parent429da1cc841bc9f2e762fd7272fc2b80314b890a (diff)
can: SJA1000 generic platform bus driver
This driver adds support for the SJA1000 chips connected to the "platform bus", which can be found on various embedded systems. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Wolfgang Grandegger <wg@grandegger.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/Kconfig10
-rw-r--r--drivers/net/can/sja1000/Makefile1
-rw-r--r--drivers/net/can/sja1000/sja1000_platform.c164
3 files changed, 175 insertions, 0 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index c7e5ce339ead..8fe79741d3ca 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -41,6 +41,16 @@ config CAN_SJA1000
41 ---help--- 41 ---help---
42 Driver for the SJA1000 CAN controllers from Philips or NXP 42 Driver for the SJA1000 CAN controllers from Philips or NXP
43 43
44config CAN_SJA1000_PLATFORM
45 depends on CAN_SJA1000
46 tristate "Generic Platform Bus based SJA1000 driver"
47 ---help---
48 This driver adds support for the SJA1000 chips connected to
49 the "platform bus" (Linux abstraction for directly to the
50 processor attached devices). Which can be found on various
51 boards from Phytec (http://www.phytec.de) like the PCM027,
52 PCM038.
53
44config CAN_DEBUG_DEVICES 54config CAN_DEBUG_DEVICES
45 bool "CAN devices debugging messages" 55 bool "CAN devices debugging messages"
46 depends on CAN 56 depends on CAN
diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile
index 893ab2cfe244..5115cc90ab51 100644
--- a/drivers/net/can/sja1000/Makefile
+++ b/drivers/net/can/sja1000/Makefile
@@ -3,5 +3,6 @@
3# 3#
4 4
5obj-$(CONFIG_CAN_SJA1000) += sja1000.o 5obj-$(CONFIG_CAN_SJA1000) += sja1000.o
6obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
6 7
7ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG 8ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
new file mode 100644
index 000000000000..8017229d6fd6
--- /dev/null
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -0,0 +1,164 @@
1/*
2 * Copyright (C) 2005 Sascha Hauer, Pengutronix
3 * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the version 2 of the GNU General Public License
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/interrupt.h>
22#include <linux/netdevice.h>
23#include <linux/delay.h>
24#include <linux/pci.h>
25#include <linux/platform_device.h>
26#include <linux/irq.h>
27#include <linux/can.h>
28#include <linux/can/dev.h>
29#include <linux/can/platform/sja1000.h>
30#include <linux/io.h>
31
32#include "sja1000.h"
33
34#define DRV_NAME "sja1000_platform"
35
36MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
37MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
38MODULE_LICENSE("GPL v2");
39
40static u8 sp_read_reg(const struct net_device *dev, int reg)
41{
42 return ioread8((void __iomem *)(dev->base_addr + reg));
43}
44
45static void sp_write_reg(const struct net_device *dev, int reg, u8 val)
46{
47 iowrite8(val, (void __iomem *)(dev->base_addr + reg));
48}
49
50static int sp_probe(struct platform_device *pdev)
51{
52 int err;
53 void __iomem *addr;
54 struct net_device *dev;
55 struct sja1000_priv *priv;
56 struct resource *res_mem, *res_irq;
57 struct sja1000_platform_data *pdata;
58
59 pdata = pdev->dev.platform_data;
60 if (!pdata) {
61 dev_err(&pdev->dev, "No platform data provided!\n");
62 err = -ENODEV;
63 goto exit;
64 }
65
66 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
67 res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
68 if (!res_mem || !res_irq) {
69 err = -ENODEV;
70 goto exit;
71 }
72
73 if (!request_mem_region(res_mem->start, resource_size(res_mem),
74 DRV_NAME)) {
75 err = -EBUSY;
76 goto exit;
77 }
78
79 addr = ioremap_nocache(res_mem->start, resource_size(res_mem));
80 if (!addr) {
81 err = -ENOMEM;
82 goto exit_release;
83 }
84
85 dev = alloc_sja1000dev(0);
86 if (!dev) {
87 err = -ENOMEM;
88 goto exit_iounmap;
89 }
90 priv = netdev_priv(dev);
91
92 dev->base_addr = (unsigned long)addr;
93 dev->irq = res_irq->start;
94 priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
95 priv->read_reg = sp_read_reg;
96 priv->write_reg = sp_write_reg;
97 priv->can.clock.freq = pdata->clock;
98 priv->ocr = pdata->ocr;
99 priv->cdr = pdata->cdr;
100
101 dev_set_drvdata(&pdev->dev, dev);
102 SET_NETDEV_DEV(dev, &pdev->dev);
103
104 err = register_sja1000dev(dev);
105 if (err) {
106 dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
107 DRV_NAME, err);
108 goto exit_free;
109 }
110
111 dev_info(&pdev->dev, "%s device registered (base_addr=%#lx, irq=%d)\n",
112 DRV_NAME, dev->base_addr, dev->irq);
113 return 0;
114
115 exit_free:
116 free_sja1000dev(dev);
117 exit_iounmap:
118 iounmap(addr);
119 exit_release:
120 release_mem_region(res_mem->start, resource_size(res_mem));
121 exit:
122 return err;
123}
124
125static int sp_remove(struct platform_device *pdev)
126{
127 struct net_device *dev = dev_get_drvdata(&pdev->dev);
128 struct resource *res;
129
130 unregister_sja1000dev(dev);
131 dev_set_drvdata(&pdev->dev, NULL);
132
133 if (dev->base_addr)
134 iounmap((void __iomem *)dev->base_addr);
135
136 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
137 release_mem_region(res->start, resource_size(res));
138
139 free_sja1000dev(dev);
140
141 return 0;
142}
143
144static struct platform_driver sp_driver = {
145 .probe = sp_probe,
146 .remove = sp_remove,
147 .driver = {
148 .name = DRV_NAME,
149 .owner = THIS_MODULE,
150 },
151};
152
153static int __init sp_init(void)
154{
155 return platform_driver_register(&sp_driver);
156}
157
158static void __exit sp_exit(void)
159{
160 platform_driver_unregister(&sp_driver);
161}
162
163module_init(sp_init);
164module_exit(sp_exit);