c_can_pci.c revision ccbc5357db3098c57176945f677b0af37f5e87e6
1/*
2 * PCI bus driver for Bosch C_CAN/D_CAN controller
3 *
4 * Copyright (C) 2012 Federico Vaga <federico.vaga@gmail.com>
5 *
6 * Borrowed from c_can_platform.c
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/netdevice.h>
16#include <linux/pci.h>
17
18#include <linux/can/dev.h>
19
20#include "c_can.h"
21
22#define PCI_DEVICE_ID_PCH_CAN	0x8818
23#define PCH_PCI_SOFT_RESET	0x01fc
24
25enum c_can_pci_reg_align {
26	C_CAN_REG_ALIGN_16,
27	C_CAN_REG_ALIGN_32,
28	C_CAN_REG_32,
29};
30
31struct c_can_pci_data {
32	/* Specify if is C_CAN or D_CAN */
33	enum c_can_dev_id type;
34	/* Set the register alignment in the memory */
35	enum c_can_pci_reg_align reg_align;
36	/* Set the frequency */
37	unsigned int freq;
38	/* PCI bar number */
39	int bar;
40	/* Callback for reset */
41	void (*init)(const struct c_can_priv *priv, bool enable);
42};
43
44/*
45 * 16-bit c_can registers can be arranged differently in the memory
46 * architecture of different implementations. For example: 16-bit
47 * registers can be aligned to a 16-bit boundary or 32-bit boundary etc.
48 * Handle the same by providing a common read/write interface.
49 */
50static u16 c_can_pci_read_reg_aligned_to_16bit(const struct c_can_priv *priv,
51						enum reg index)
52{
53	return readw(priv->base + priv->regs[index]);
54}
55
56static void c_can_pci_write_reg_aligned_to_16bit(const struct c_can_priv *priv,
57						enum reg index, u16 val)
58{
59	writew(val, priv->base + priv->regs[index]);
60}
61
62static u16 c_can_pci_read_reg_aligned_to_32bit(const struct c_can_priv *priv,
63						enum reg index)
64{
65	return readw(priv->base + 2 * priv->regs[index]);
66}
67
68static void c_can_pci_write_reg_aligned_to_32bit(const struct c_can_priv *priv,
69						enum reg index, u16 val)
70{
71	writew(val, priv->base + 2 * priv->regs[index]);
72}
73
74static u16 c_can_pci_read_reg_32bit(const struct c_can_priv *priv,
75				    enum reg index)
76{
77	return (u16)ioread32(priv->base + 2 * priv->regs[index]);
78}
79
80static void c_can_pci_write_reg_32bit(const struct c_can_priv *priv,
81				      enum reg index, u16 val)
82{
83	iowrite32((u32)val, priv->base + 2 * priv->regs[index]);
84}
85
86static u32 c_can_pci_read_reg32(const struct c_can_priv *priv, enum reg index)
87{
88	u32 val;
89
90	val = priv->read_reg(priv, index);
91	val |= ((u32) priv->read_reg(priv, index + 1)) << 16;
92
93	return val;
94}
95
96static void c_can_pci_write_reg32(const struct c_can_priv *priv, enum reg index,
97		u32 val)
98{
99	priv->write_reg(priv, index + 1, val >> 16);
100	priv->write_reg(priv, index, val);
101}
102
103static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable)
104{
105	if (enable) {
106		u32 __iomem *addr = priv->base + PCH_PCI_SOFT_RESET;
107
108		/* write to sw reset register */
109		iowrite32(1, addr);
110		iowrite32(0, addr);
111	}
112}
113
114static int c_can_pci_probe(struct pci_dev *pdev,
115			   const struct pci_device_id *ent)
116{
117	struct c_can_pci_data *c_can_pci_data = (void *)ent->driver_data;
118	struct c_can_priv *priv;
119	struct net_device *dev;
120	void __iomem *addr;
121	int ret;
122
123	ret = pci_enable_device(pdev);
124	if (ret) {
125		dev_err(&pdev->dev, "pci_enable_device FAILED\n");
126		goto out;
127	}
128
129	ret = pci_request_regions(pdev, KBUILD_MODNAME);
130	if (ret) {
131		dev_err(&pdev->dev, "pci_request_regions FAILED\n");
132		goto out_disable_device;
133	}
134
135	ret = pci_enable_msi(pdev);
136	if (!ret) {
137		dev_info(&pdev->dev, "MSI enabled\n");
138		pci_set_master(pdev);
139	}
140
141	addr = pci_iomap(pdev, c_can_pci_data->bar,
142			 pci_resource_len(pdev, c_can_pci_data->bar));
143	if (!addr) {
144		dev_err(&pdev->dev,
145			"device has no PCI memory resources, "
146			"failing adapter\n");
147		ret = -ENOMEM;
148		goto out_release_regions;
149	}
150
151	/* allocate the c_can device */
152	dev = alloc_c_can_dev();
153	if (!dev) {
154		ret = -ENOMEM;
155		goto out_iounmap;
156	}
157
158	priv = netdev_priv(dev);
159	pci_set_drvdata(pdev, dev);
160	SET_NETDEV_DEV(dev, &pdev->dev);
161
162	dev->irq = pdev->irq;
163	priv->base = addr;
164
165	if (!c_can_pci_data->freq) {
166		dev_err(&pdev->dev, "no clock frequency defined\n");
167		ret = -ENODEV;
168		goto out_free_c_can;
169	} else {
170		priv->can.clock.freq = c_can_pci_data->freq;
171	}
172
173	/* Configure CAN type */
174	switch (c_can_pci_data->type) {
175	case BOSCH_C_CAN:
176		priv->regs = reg_map_c_can;
177		break;
178	case BOSCH_D_CAN:
179		priv->regs = reg_map_d_can;
180		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
181		break;
182	default:
183		ret = -EINVAL;
184		goto out_free_c_can;
185	}
186
187	priv->type = c_can_pci_data->type;
188
189	/* Configure access to registers */
190	switch (c_can_pci_data->reg_align) {
191	case C_CAN_REG_ALIGN_32:
192		priv->read_reg = c_can_pci_read_reg_aligned_to_32bit;
193		priv->write_reg = c_can_pci_write_reg_aligned_to_32bit;
194		break;
195	case C_CAN_REG_ALIGN_16:
196		priv->read_reg = c_can_pci_read_reg_aligned_to_16bit;
197		priv->write_reg = c_can_pci_write_reg_aligned_to_16bit;
198		break;
199	case C_CAN_REG_32:
200		priv->read_reg = c_can_pci_read_reg_32bit;
201		priv->write_reg = c_can_pci_write_reg_32bit;
202		break;
203	default:
204		ret = -EINVAL;
205		goto out_free_c_can;
206	}
207	priv->read_reg32 = c_can_pci_read_reg32;
208	priv->write_reg32 = c_can_pci_write_reg32;
209
210	priv->raminit = c_can_pci_data->init;
211
212	ret = register_c_can_dev(dev);
213	if (ret) {
214		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
215			KBUILD_MODNAME, ret);
216		goto out_free_c_can;
217	}
218
219	dev_dbg(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
220		 KBUILD_MODNAME, priv->regs, dev->irq);
221
222	return 0;
223
224out_free_c_can:
225	free_c_can_dev(dev);
226out_iounmap:
227	pci_iounmap(pdev, addr);
228out_release_regions:
229	pci_disable_msi(pdev);
230	pci_clear_master(pdev);
231	pci_release_regions(pdev);
232out_disable_device:
233	pci_disable_device(pdev);
234out:
235	return ret;
236}
237
238static void c_can_pci_remove(struct pci_dev *pdev)
239{
240	struct net_device *dev = pci_get_drvdata(pdev);
241	struct c_can_priv *priv = netdev_priv(dev);
242
243	unregister_c_can_dev(dev);
244
245	free_c_can_dev(dev);
246
247	pci_iounmap(pdev, priv->base);
248	pci_disable_msi(pdev);
249	pci_clear_master(pdev);
250	pci_release_regions(pdev);
251	pci_disable_device(pdev);
252}
253
254static struct c_can_pci_data c_can_sta2x11= {
255	.type = BOSCH_C_CAN,
256	.reg_align = C_CAN_REG_ALIGN_32,
257	.freq = 52000000, /* 52 Mhz */
258	.bar = 0,
259};
260
261static struct c_can_pci_data c_can_pch = {
262	.type = BOSCH_C_CAN,
263	.reg_align = C_CAN_REG_32,
264	.freq = 50000000, /* 50 MHz */
265	.init = c_can_pci_reset_pch,
266	.bar = 1,
267};
268
269#define C_CAN_ID(_vend, _dev, _driverdata) {		\
270	PCI_DEVICE(_vend, _dev),			\
271	.driver_data = (unsigned long)&_driverdata,	\
272}
273static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
274	C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
275		 c_can_sta2x11),
276	C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN,
277		 c_can_pch),
278	{},
279};
280static struct pci_driver c_can_pci_driver = {
281	.name = KBUILD_MODNAME,
282	.id_table = c_can_pci_tbl,
283	.probe = c_can_pci_probe,
284	.remove = c_can_pci_remove,
285};
286
287module_pci_driver(c_can_pci_driver);
288
289MODULE_AUTHOR("Federico Vaga <federico.vaga@gmail.com>");
290MODULE_LICENSE("GPL v2");
291MODULE_DESCRIPTION("PCI CAN bus driver for Bosch C_CAN/D_CAN controller");
292MODULE_DEVICE_TABLE(pci, c_can_pci_tbl);
293