aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--include/linux/can/platform/sja1000.h32
4 files changed, 207 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);
diff --git a/include/linux/can/platform/sja1000.h b/include/linux/can/platform/sja1000.h
new file mode 100644
index 000000000000..37966e630ff5
--- /dev/null
+++ b/include/linux/can/platform/sja1000.h
@@ -0,0 +1,32 @@
1#ifndef _CAN_PLATFORM_SJA1000_H_
2#define _CAN_PLATFORM_SJA1000_H_
3
4/* clock divider register */
5#define CDR_CLKOUT_MASK 0x07
6#define CDR_CLK_OFF 0x08 /* Clock off (CLKOUT pin) */
7#define CDR_RXINPEN 0x20 /* TX1 output is RX irq output */
8#define CDR_CBP 0x40 /* CAN input comparator bypass */
9#define CDR_PELICAN 0x80 /* PeliCAN mode */
10
11/* output control register */
12#define OCR_MODE_BIPHASE 0x00
13#define OCR_MODE_TEST 0x01
14#define OCR_MODE_NORMAL 0x02
15#define OCR_MODE_CLOCK 0x03
16#define OCR_TX0_INVERT 0x04
17#define OCR_TX0_PULLDOWN 0x08
18#define OCR_TX0_PULLUP 0x10
19#define OCR_TX0_PUSHPULL 0x18
20#define OCR_TX1_INVERT 0x20
21#define OCR_TX1_PULLDOWN 0x40
22#define OCR_TX1_PULLUP 0x80
23#define OCR_TX1_PUSHPULL 0xc0
24
25struct sja1000_platform_data {
26 u32 clock; /* CAN bus oscillator frequency in Hz */
27
28 u8 ocr; /* output control register */
29 u8 cdr; /* clock divider register */
30};
31
32#endif /* !_CAN_PLATFORM_SJA1000_H_ */