xref: /OK3568_Linux_fs/kernel/drivers/net/can/sja1000/ems_pcmcia.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2008 Sebastian Haas (initial chardev implementation)
4*4882a593Smuzhiyun  * Copyright (C) 2010 Markus Plessing <plessing@ems-wuensche.com>
5*4882a593Smuzhiyun  * Rework for mainline by Oliver Hartkopp <socketcan@hartkopp.net>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/netdevice.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <pcmcia/cistpl.h>
15*4882a593Smuzhiyun #include <pcmcia/ds.h>
16*4882a593Smuzhiyun #include <linux/can.h>
17*4882a593Smuzhiyun #include <linux/can/dev.h>
18*4882a593Smuzhiyun #include "sja1000.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define DRV_NAME "ems_pcmcia"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun MODULE_AUTHOR("Markus Plessing <plessing@ems-wuensche.com>");
23*4882a593Smuzhiyun MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-CARD cards");
24*4882a593Smuzhiyun MODULE_SUPPORTED_DEVICE("EMS CPC-CARD CAN card");
25*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define EMS_PCMCIA_MAX_CHAN 2
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct ems_pcmcia_card {
30*4882a593Smuzhiyun 	int channels;
31*4882a593Smuzhiyun 	struct pcmcia_device *pcmcia_dev;
32*4882a593Smuzhiyun 	struct net_device *net_dev[EMS_PCMCIA_MAX_CHAN];
33*4882a593Smuzhiyun 	void __iomem *base_addr;
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define EMS_PCMCIA_CAN_CLOCK (16000000 / 2)
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /*
39*4882a593Smuzhiyun  * The board configuration is probably following:
40*4882a593Smuzhiyun  * RX1 is connected to ground.
41*4882a593Smuzhiyun  * TX1 is not connected.
42*4882a593Smuzhiyun  * CLKO is not connected.
43*4882a593Smuzhiyun  * Setting the OCR register to 0xDA is a good idea.
44*4882a593Smuzhiyun  * This means  normal output mode , push-pull and the correct polarity.
45*4882a593Smuzhiyun  */
46*4882a593Smuzhiyun #define EMS_PCMCIA_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun  * In the CDR register, you should set CBP to 1.
50*4882a593Smuzhiyun  * You will probably also want to set the clock divider value to 7
51*4882a593Smuzhiyun  * (meaning direct oscillator output) because the second SJA1000 chip
52*4882a593Smuzhiyun  * is driven by the first one CLKOUT output.
53*4882a593Smuzhiyun  */
54*4882a593Smuzhiyun #define EMS_PCMCIA_CDR (CDR_CBP | CDR_CLKOUT_MASK)
55*4882a593Smuzhiyun #define EMS_PCMCIA_MEM_SIZE 4096 /* Size of the remapped io-memory */
56*4882a593Smuzhiyun #define EMS_PCMCIA_CAN_BASE_OFFSET 0x100 /* Offset where controllers starts */
57*4882a593Smuzhiyun #define EMS_PCMCIA_CAN_CTRL_SIZE 0x80 /* Memory size for each controller */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define EMS_CMD_RESET 0x00 /* Perform a reset of the card */
60*4882a593Smuzhiyun #define EMS_CMD_MAP   0x03 /* Map CAN controllers into card' memory */
61*4882a593Smuzhiyun #define EMS_CMD_UMAP  0x02 /* Unmap CAN controllers from card' memory */
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static struct pcmcia_device_id ems_pcmcia_tbl[] = {
64*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID123("EMS_T_W", "CPC-Card", "V2.0", 0xeab1ea23,
65*4882a593Smuzhiyun 				 0xa338573f, 0xe4575800),
66*4882a593Smuzhiyun 	PCMCIA_DEVICE_NULL,
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pcmcia, ems_pcmcia_tbl);
70*4882a593Smuzhiyun 
ems_pcmcia_read_reg(const struct sja1000_priv * priv,int port)71*4882a593Smuzhiyun static u8 ems_pcmcia_read_reg(const struct sja1000_priv *priv, int port)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	return readb(priv->reg_base + port);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
ems_pcmcia_write_reg(const struct sja1000_priv * priv,int port,u8 val)76*4882a593Smuzhiyun static void ems_pcmcia_write_reg(const struct sja1000_priv *priv, int port,
77*4882a593Smuzhiyun 				 u8 val)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	writeb(val, priv->reg_base + port);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
ems_pcmcia_interrupt(int irq,void * dev_id)82*4882a593Smuzhiyun static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	struct ems_pcmcia_card *card = dev_id;
85*4882a593Smuzhiyun 	struct net_device *dev;
86*4882a593Smuzhiyun 	irqreturn_t retval = IRQ_NONE;
87*4882a593Smuzhiyun 	int i, again;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	/* Card not present */
90*4882a593Smuzhiyun 	if (readw(card->base_addr) != 0xAA55)
91*4882a593Smuzhiyun 		return IRQ_HANDLED;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	do {
94*4882a593Smuzhiyun 		again = 0;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 		/* Check interrupt for each channel */
97*4882a593Smuzhiyun 		for (i = 0; i < card->channels; i++) {
98*4882a593Smuzhiyun 			dev = card->net_dev[i];
99*4882a593Smuzhiyun 			if (!dev)
100*4882a593Smuzhiyun 				continue;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 			if (sja1000_interrupt(irq, dev) == IRQ_HANDLED)
103*4882a593Smuzhiyun 				again = 1;
104*4882a593Smuzhiyun 		}
105*4882a593Smuzhiyun 		/* At least one channel handled the interrupt */
106*4882a593Smuzhiyun 		if (again)
107*4882a593Smuzhiyun 			retval = IRQ_HANDLED;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	} while (again);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	return retval;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun /*
115*4882a593Smuzhiyun  * Check if a CAN controller is present at the specified location
116*4882a593Smuzhiyun  * by trying to set 'em into the PeliCAN mode
117*4882a593Smuzhiyun  */
ems_pcmcia_check_chan(struct sja1000_priv * priv)118*4882a593Smuzhiyun static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	/* Make sure SJA1000 is in reset mode */
121*4882a593Smuzhiyun 	ems_pcmcia_write_reg(priv, SJA1000_MOD, 1);
122*4882a593Smuzhiyun 	ems_pcmcia_write_reg(priv, SJA1000_CDR, CDR_PELICAN);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	/* read reset-values */
125*4882a593Smuzhiyun 	if (ems_pcmcia_read_reg(priv, SJA1000_CDR) == CDR_PELICAN)
126*4882a593Smuzhiyun 		return 1;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	return 0;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
ems_pcmcia_del_card(struct pcmcia_device * pdev)131*4882a593Smuzhiyun static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	struct ems_pcmcia_card *card = pdev->priv;
134*4882a593Smuzhiyun 	struct net_device *dev;
135*4882a593Smuzhiyun 	int i;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	free_irq(pdev->irq, card);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	for (i = 0; i < card->channels; i++) {
140*4882a593Smuzhiyun 		dev = card->net_dev[i];
141*4882a593Smuzhiyun 		if (!dev)
142*4882a593Smuzhiyun 			continue;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 		printk(KERN_INFO "%s: removing %s on channel #%d\n",
145*4882a593Smuzhiyun 		       DRV_NAME, dev->name, i);
146*4882a593Smuzhiyun 		unregister_sja1000dev(dev);
147*4882a593Smuzhiyun 		free_sja1000dev(dev);
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	writeb(EMS_CMD_UMAP, card->base_addr);
151*4882a593Smuzhiyun 	iounmap(card->base_addr);
152*4882a593Smuzhiyun 	kfree(card);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	pdev->priv = NULL;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun /*
158*4882a593Smuzhiyun  * Probe PCI device for EMS CAN signature and register each available
159*4882a593Smuzhiyun  * CAN channel to SJA1000 Socket-CAN subsystem.
160*4882a593Smuzhiyun  */
ems_pcmcia_add_card(struct pcmcia_device * pdev,unsigned long base)161*4882a593Smuzhiyun static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	struct sja1000_priv *priv;
164*4882a593Smuzhiyun 	struct net_device *dev;
165*4882a593Smuzhiyun 	struct ems_pcmcia_card *card;
166*4882a593Smuzhiyun 	int err, i;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	/* Allocating card structures to hold addresses, ... */
169*4882a593Smuzhiyun 	card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL);
170*4882a593Smuzhiyun 	if (!card)
171*4882a593Smuzhiyun 		return -ENOMEM;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	pdev->priv = card;
174*4882a593Smuzhiyun 	card->channels = 0;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE);
177*4882a593Smuzhiyun 	if (!card->base_addr) {
178*4882a593Smuzhiyun 		err = -ENOMEM;
179*4882a593Smuzhiyun 		goto failure_cleanup;
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	/* Check for unique EMS CAN signature */
183*4882a593Smuzhiyun 	if (readw(card->base_addr) != 0xAA55) {
184*4882a593Smuzhiyun 		err = -ENODEV;
185*4882a593Smuzhiyun 		goto failure_cleanup;
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* Request board reset */
189*4882a593Smuzhiyun 	writeb(EMS_CMD_RESET, card->base_addr);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	/* Make sure CAN controllers are mapped into card's memory space */
192*4882a593Smuzhiyun 	writeb(EMS_CMD_MAP, card->base_addr);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	/* Detect available channels */
195*4882a593Smuzhiyun 	for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
196*4882a593Smuzhiyun 		dev = alloc_sja1000dev(0);
197*4882a593Smuzhiyun 		if (!dev) {
198*4882a593Smuzhiyun 			err = -ENOMEM;
199*4882a593Smuzhiyun 			goto failure_cleanup;
200*4882a593Smuzhiyun 		}
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 		card->net_dev[i] = dev;
203*4882a593Smuzhiyun 		priv = netdev_priv(dev);
204*4882a593Smuzhiyun 		priv->priv = card;
205*4882a593Smuzhiyun 		SET_NETDEV_DEV(dev, &pdev->dev);
206*4882a593Smuzhiyun 		dev->dev_id = i;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 		priv->irq_flags = IRQF_SHARED;
209*4882a593Smuzhiyun 		dev->irq = pdev->irq;
210*4882a593Smuzhiyun 		priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET +
211*4882a593Smuzhiyun 			(i * EMS_PCMCIA_CAN_CTRL_SIZE);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 		/* Check if channel is present */
214*4882a593Smuzhiyun 		if (ems_pcmcia_check_chan(priv)) {
215*4882a593Smuzhiyun 			priv->read_reg  = ems_pcmcia_read_reg;
216*4882a593Smuzhiyun 			priv->write_reg = ems_pcmcia_write_reg;
217*4882a593Smuzhiyun 			priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK;
218*4882a593Smuzhiyun 			priv->ocr = EMS_PCMCIA_OCR;
219*4882a593Smuzhiyun 			priv->cdr = EMS_PCMCIA_CDR;
220*4882a593Smuzhiyun 			priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 			/* Register SJA1000 device */
223*4882a593Smuzhiyun 			err = register_sja1000dev(dev);
224*4882a593Smuzhiyun 			if (err) {
225*4882a593Smuzhiyun 				free_sja1000dev(dev);
226*4882a593Smuzhiyun 				goto failure_cleanup;
227*4882a593Smuzhiyun 			}
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 			card->channels++;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 			printk(KERN_INFO "%s: registered %s on channel "
232*4882a593Smuzhiyun 			       "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name,
233*4882a593Smuzhiyun 			       i, priv->reg_base, dev->irq);
234*4882a593Smuzhiyun 		} else
235*4882a593Smuzhiyun 			free_sja1000dev(dev);
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	if (!card->channels) {
239*4882a593Smuzhiyun 		err = -ENODEV;
240*4882a593Smuzhiyun 		goto failure_cleanup;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
244*4882a593Smuzhiyun 			  DRV_NAME, card);
245*4882a593Smuzhiyun 	if (!err)
246*4882a593Smuzhiyun 		return 0;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun failure_cleanup:
249*4882a593Smuzhiyun 	ems_pcmcia_del_card(pdev);
250*4882a593Smuzhiyun 	return err;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun  * Setup PCMCIA socket and probe for EMS CPC-CARD
255*4882a593Smuzhiyun  */
ems_pcmcia_probe(struct pcmcia_device * dev)256*4882a593Smuzhiyun static int ems_pcmcia_probe(struct pcmcia_device *dev)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	int csval;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	/* General socket configuration */
261*4882a593Smuzhiyun 	dev->config_flags |= CONF_ENABLE_IRQ;
262*4882a593Smuzhiyun 	dev->config_index = 1;
263*4882a593Smuzhiyun 	dev->config_regs = PRESENT_OPTION;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	/* The io structure describes IO port mapping */
266*4882a593Smuzhiyun 	dev->resource[0]->end = 16;
267*4882a593Smuzhiyun 	dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
268*4882a593Smuzhiyun 	dev->resource[1]->end = 16;
269*4882a593Smuzhiyun 	dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
270*4882a593Smuzhiyun 	dev->io_lines = 5;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	/* Allocate a memory window */
273*4882a593Smuzhiyun 	dev->resource[2]->flags =
274*4882a593Smuzhiyun 		(WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE);
275*4882a593Smuzhiyun 	dev->resource[2]->start = dev->resource[2]->end = 0;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	csval = pcmcia_request_window(dev, dev->resource[2], 0);
278*4882a593Smuzhiyun 	if (csval) {
279*4882a593Smuzhiyun 		dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n",
280*4882a593Smuzhiyun 			csval);
281*4882a593Smuzhiyun 		return 0;
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base);
285*4882a593Smuzhiyun 	if (csval) {
286*4882a593Smuzhiyun 		dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n",
287*4882a593Smuzhiyun 			csval);
288*4882a593Smuzhiyun 		return 0;
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	csval = pcmcia_enable_device(dev);
292*4882a593Smuzhiyun 	if (csval) {
293*4882a593Smuzhiyun 		dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n",
294*4882a593Smuzhiyun 			csval);
295*4882a593Smuzhiyun 		return 0;
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	ems_pcmcia_add_card(dev, dev->resource[2]->start);
299*4882a593Smuzhiyun 	return 0;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun /*
303*4882a593Smuzhiyun  * Release claimed resources
304*4882a593Smuzhiyun  */
ems_pcmcia_remove(struct pcmcia_device * dev)305*4882a593Smuzhiyun static void ems_pcmcia_remove(struct pcmcia_device *dev)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	ems_pcmcia_del_card(dev);
308*4882a593Smuzhiyun 	pcmcia_disable_device(dev);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun static struct pcmcia_driver ems_pcmcia_driver = {
312*4882a593Smuzhiyun 	.name = DRV_NAME,
313*4882a593Smuzhiyun 	.probe = ems_pcmcia_probe,
314*4882a593Smuzhiyun 	.remove = ems_pcmcia_remove,
315*4882a593Smuzhiyun 	.id_table = ems_pcmcia_tbl,
316*4882a593Smuzhiyun };
317*4882a593Smuzhiyun module_pcmcia_driver(ems_pcmcia_driver);
318