xref: /openbmc/linux/drivers/net/can/sja1000/peak_pci.c (revision 29830406415c227a54af429d7b300aabd4754237)
138034518SWolfgang Grandegger /*
238034518SWolfgang Grandegger  * Copyright (C) 2007, 2011 Wolfgang Grandegger <wg@grandegger.com>
338034518SWolfgang Grandegger  *
438034518SWolfgang Grandegger  * Derived from the PCAN project file driver/src/pcan_pci.c:
538034518SWolfgang Grandegger  *
638034518SWolfgang Grandegger  * Copyright (C) 2001-2006  PEAK System-Technik GmbH
738034518SWolfgang Grandegger  *
838034518SWolfgang Grandegger  * This program is free software; you can redistribute it and/or modify
938034518SWolfgang Grandegger  * it under the terms of the version 2 of the GNU General Public License
1038034518SWolfgang Grandegger  * as published by the Free Software Foundation
1138034518SWolfgang Grandegger  *
1238034518SWolfgang Grandegger  * This program is distributed in the hope that it will be useful,
1338034518SWolfgang Grandegger  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1438034518SWolfgang Grandegger  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1538034518SWolfgang Grandegger  * GNU General Public License for more details.
1638034518SWolfgang Grandegger  *
1738034518SWolfgang Grandegger  * You should have received a copy of the GNU General Public License
1838034518SWolfgang Grandegger  * along with this program; if not, write to the Free Software Foundation,
1938034518SWolfgang Grandegger  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2038034518SWolfgang Grandegger  */
2138034518SWolfgang Grandegger 
2238034518SWolfgang Grandegger #include <linux/kernel.h>
2338034518SWolfgang Grandegger #include <linux/module.h>
2438034518SWolfgang Grandegger #include <linux/interrupt.h>
2538034518SWolfgang Grandegger #include <linux/netdevice.h>
2638034518SWolfgang Grandegger #include <linux/delay.h>
2738034518SWolfgang Grandegger #include <linux/pci.h>
2838034518SWolfgang Grandegger #include <linux/io.h>
2938034518SWolfgang Grandegger #include <linux/can.h>
3038034518SWolfgang Grandegger #include <linux/can/dev.h>
3138034518SWolfgang Grandegger 
3238034518SWolfgang Grandegger #include "sja1000.h"
3338034518SWolfgang Grandegger 
3438034518SWolfgang Grandegger MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
3538034518SWolfgang Grandegger MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI/PCIe cards");
3638034518SWolfgang Grandegger MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe CAN card");
3738034518SWolfgang Grandegger MODULE_LICENSE("GPL v2");
3838034518SWolfgang Grandegger 
3938034518SWolfgang Grandegger #define DRV_NAME  "peak_pci"
4038034518SWolfgang Grandegger 
4138034518SWolfgang Grandegger struct peak_pci_chan {
4238034518SWolfgang Grandegger 	void __iomem *cfg_base;		/* Common for all channels */
43*29830406SStephane Grosjean 	struct net_device *prev_dev;	/* Chain of network devices */
4438034518SWolfgang Grandegger 	u16 icr_mask;			/* Interrupt mask for fast ack */
4538034518SWolfgang Grandegger };
4638034518SWolfgang Grandegger 
4738034518SWolfgang Grandegger #define PEAK_PCI_CAN_CLOCK	(16000000 / 2)
4838034518SWolfgang Grandegger 
4938034518SWolfgang Grandegger #define PEAK_PCI_CDR		(CDR_CBP | CDR_CLKOUT_MASK)
5038034518SWolfgang Grandegger #define PEAK_PCI_OCR		OCR_TX0_PUSHPULL
5138034518SWolfgang Grandegger 
5238034518SWolfgang Grandegger /*
5338034518SWolfgang Grandegger  * Important PITA registers
5438034518SWolfgang Grandegger  */
5538034518SWolfgang Grandegger #define PITA_ICR		0x00	/* Interrupt control register */
5638034518SWolfgang Grandegger #define PITA_GPIOICR		0x18	/* GPIO interface control register */
5738034518SWolfgang Grandegger #define PITA_MISC		0x1C	/* Miscellaneous register */
5838034518SWolfgang Grandegger 
5938034518SWolfgang Grandegger #define PEAK_PCI_CFG_SIZE	0x1000	/* Size of the config PCI bar */
6038034518SWolfgang Grandegger #define PEAK_PCI_CHAN_SIZE	0x0400	/* Size used by the channel */
6138034518SWolfgang Grandegger 
6238034518SWolfgang Grandegger #define PEAK_PCI_VENDOR_ID	0x001C	/* The PCI device and vendor IDs */
6338034518SWolfgang Grandegger #define PEAK_PCI_DEVICE_ID	0x0001	/* for PCI/PCIe slot cards */
6438034518SWolfgang Grandegger 
6538034518SWolfgang Grandegger static const u16 peak_pci_icr_masks[] = {0x02, 0x01, 0x40, 0x80};
6638034518SWolfgang Grandegger 
6738034518SWolfgang Grandegger static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
6838034518SWolfgang Grandegger 	{PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
6938034518SWolfgang Grandegger 	{0,}
7038034518SWolfgang Grandegger };
7138034518SWolfgang Grandegger 
7238034518SWolfgang Grandegger MODULE_DEVICE_TABLE(pci, peak_pci_tbl);
7338034518SWolfgang Grandegger 
7438034518SWolfgang Grandegger static u8 peak_pci_read_reg(const struct sja1000_priv *priv, int port)
7538034518SWolfgang Grandegger {
7638034518SWolfgang Grandegger 	return readb(priv->reg_base + (port << 2));
7738034518SWolfgang Grandegger }
7838034518SWolfgang Grandegger 
7938034518SWolfgang Grandegger static void peak_pci_write_reg(const struct sja1000_priv *priv,
8038034518SWolfgang Grandegger 			       int port, u8 val)
8138034518SWolfgang Grandegger {
8238034518SWolfgang Grandegger 	writeb(val, priv->reg_base + (port << 2));
8338034518SWolfgang Grandegger }
8438034518SWolfgang Grandegger 
8538034518SWolfgang Grandegger static void peak_pci_post_irq(const struct sja1000_priv *priv)
8638034518SWolfgang Grandegger {
8738034518SWolfgang Grandegger 	struct peak_pci_chan *chan = priv->priv;
8838034518SWolfgang Grandegger 	u16 icr;
8938034518SWolfgang Grandegger 
9038034518SWolfgang Grandegger 	/* Select and clear in PITA stored interrupt */
9138034518SWolfgang Grandegger 	icr = readw(chan->cfg_base + PITA_ICR);
9238034518SWolfgang Grandegger 	if (icr & chan->icr_mask)
9338034518SWolfgang Grandegger 		writew(chan->icr_mask, chan->cfg_base + PITA_ICR);
9438034518SWolfgang Grandegger }
9538034518SWolfgang Grandegger 
9638034518SWolfgang Grandegger static int __devinit peak_pci_probe(struct pci_dev *pdev,
9738034518SWolfgang Grandegger 				    const struct pci_device_id *ent)
9838034518SWolfgang Grandegger {
9938034518SWolfgang Grandegger 	struct sja1000_priv *priv;
10038034518SWolfgang Grandegger 	struct peak_pci_chan *chan;
101*29830406SStephane Grosjean 	struct net_device *dev;
10238034518SWolfgang Grandegger 	void __iomem *cfg_base, *reg_base;
10338034518SWolfgang Grandegger 	u16 sub_sys_id, icr;
10438034518SWolfgang Grandegger 	int i, err, channels;
10538034518SWolfgang Grandegger 
10638034518SWolfgang Grandegger 	err = pci_enable_device(pdev);
10738034518SWolfgang Grandegger 	if (err)
10838034518SWolfgang Grandegger 		return err;
10938034518SWolfgang Grandegger 
11038034518SWolfgang Grandegger 	err = pci_request_regions(pdev, DRV_NAME);
11138034518SWolfgang Grandegger 	if (err)
11238034518SWolfgang Grandegger 		goto failure_disable_pci;
11338034518SWolfgang Grandegger 
11438034518SWolfgang Grandegger 	err = pci_read_config_word(pdev, 0x2e, &sub_sys_id);
11538034518SWolfgang Grandegger 	if (err)
11638034518SWolfgang Grandegger 		goto failure_release_regions;
11738034518SWolfgang Grandegger 
11838034518SWolfgang Grandegger 	dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n",
11938034518SWolfgang Grandegger 		pdev->vendor, pdev->device, sub_sys_id);
12038034518SWolfgang Grandegger 
12138034518SWolfgang Grandegger 	err = pci_write_config_word(pdev, 0x44, 0);
12238034518SWolfgang Grandegger 	if (err)
12338034518SWolfgang Grandegger 		goto failure_release_regions;
12438034518SWolfgang Grandegger 
12538034518SWolfgang Grandegger 	if (sub_sys_id >= 12)
12638034518SWolfgang Grandegger 		channels = 4;
12738034518SWolfgang Grandegger 	else if (sub_sys_id >= 10)
12838034518SWolfgang Grandegger 		channels = 3;
12938034518SWolfgang Grandegger 	else if (sub_sys_id >= 4)
13038034518SWolfgang Grandegger 		channels = 2;
13138034518SWolfgang Grandegger 	else
13238034518SWolfgang Grandegger 		channels = 1;
13338034518SWolfgang Grandegger 
13438034518SWolfgang Grandegger 	cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE);
13538034518SWolfgang Grandegger 	if (!cfg_base) {
13638034518SWolfgang Grandegger 		dev_err(&pdev->dev, "failed to map PCI resource #0\n");
13738034518SWolfgang Grandegger 		goto failure_release_regions;
13838034518SWolfgang Grandegger 	}
13938034518SWolfgang Grandegger 
14038034518SWolfgang Grandegger 	reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels);
14138034518SWolfgang Grandegger 	if (!reg_base) {
14238034518SWolfgang Grandegger 		dev_err(&pdev->dev, "failed to map PCI resource #1\n");
14338034518SWolfgang Grandegger 		goto failure_unmap_cfg_base;
14438034518SWolfgang Grandegger 	}
14538034518SWolfgang Grandegger 
14638034518SWolfgang Grandegger 	/* Set GPIO control register */
14738034518SWolfgang Grandegger 	writew(0x0005, cfg_base + PITA_GPIOICR + 2);
14838034518SWolfgang Grandegger 	/* Enable all channels of this card */
14938034518SWolfgang Grandegger 	writeb(0x00, cfg_base + PITA_GPIOICR);
15038034518SWolfgang Grandegger 	/* Toggle reset */
15138034518SWolfgang Grandegger 	writeb(0x05, cfg_base + PITA_MISC + 3);
15238034518SWolfgang Grandegger 	mdelay(5);
15338034518SWolfgang Grandegger 	/* Leave parport mux mode */
15438034518SWolfgang Grandegger 	writeb(0x04, cfg_base + PITA_MISC + 3);
15538034518SWolfgang Grandegger 
15638034518SWolfgang Grandegger 	icr = readw(cfg_base + PITA_ICR + 2);
15738034518SWolfgang Grandegger 
15838034518SWolfgang Grandegger 	for (i = 0; i < channels; i++) {
15938034518SWolfgang Grandegger 		dev = alloc_sja1000dev(sizeof(struct peak_pci_chan));
16038034518SWolfgang Grandegger 		if (!dev) {
16138034518SWolfgang Grandegger 			err = -ENOMEM;
16238034518SWolfgang Grandegger 			goto failure_remove_channels;
16338034518SWolfgang Grandegger 		}
16438034518SWolfgang Grandegger 
16538034518SWolfgang Grandegger 		priv = netdev_priv(dev);
16638034518SWolfgang Grandegger 		chan = priv->priv;
16738034518SWolfgang Grandegger 
16838034518SWolfgang Grandegger 		chan->cfg_base = cfg_base;
16938034518SWolfgang Grandegger 		priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE;
17038034518SWolfgang Grandegger 
17138034518SWolfgang Grandegger 		priv->read_reg = peak_pci_read_reg;
17238034518SWolfgang Grandegger 		priv->write_reg = peak_pci_write_reg;
17338034518SWolfgang Grandegger 		priv->post_irq = peak_pci_post_irq;
17438034518SWolfgang Grandegger 
17538034518SWolfgang Grandegger 		priv->can.clock.freq = PEAK_PCI_CAN_CLOCK;
17638034518SWolfgang Grandegger 		priv->ocr = PEAK_PCI_OCR;
17738034518SWolfgang Grandegger 		priv->cdr = PEAK_PCI_CDR;
17838034518SWolfgang Grandegger 		/* Neither a slave nor a single device distributes the clock */
17938034518SWolfgang Grandegger 		if (channels == 1 || i > 0)
18038034518SWolfgang Grandegger 			priv->cdr |= CDR_CLK_OFF;
18138034518SWolfgang Grandegger 
18238034518SWolfgang Grandegger 		/* Setup interrupt handling */
18338034518SWolfgang Grandegger 		priv->irq_flags = IRQF_SHARED;
18438034518SWolfgang Grandegger 		dev->irq = pdev->irq;
18538034518SWolfgang Grandegger 
18638034518SWolfgang Grandegger 		chan->icr_mask = peak_pci_icr_masks[i];
18738034518SWolfgang Grandegger 		icr |= chan->icr_mask;
18838034518SWolfgang Grandegger 
18938034518SWolfgang Grandegger 		SET_NETDEV_DEV(dev, &pdev->dev);
19038034518SWolfgang Grandegger 
19138034518SWolfgang Grandegger 		err = register_sja1000dev(dev);
19238034518SWolfgang Grandegger 		if (err) {
19338034518SWolfgang Grandegger 			dev_err(&pdev->dev, "failed to register device\n");
19438034518SWolfgang Grandegger 			free_sja1000dev(dev);
19538034518SWolfgang Grandegger 			goto failure_remove_channels;
19638034518SWolfgang Grandegger 		}
19738034518SWolfgang Grandegger 
19838034518SWolfgang Grandegger 		/* Create chain of SJA1000 devices */
199*29830406SStephane Grosjean 		chan->prev_dev = pci_get_drvdata(pdev);
200*29830406SStephane Grosjean 		pci_set_drvdata(pdev, dev);
20138034518SWolfgang Grandegger 
20238034518SWolfgang Grandegger 		dev_info(&pdev->dev,
20338034518SWolfgang Grandegger 			 "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
20438034518SWolfgang Grandegger 			 dev->name, priv->reg_base, chan->cfg_base, dev->irq);
20538034518SWolfgang Grandegger 	}
20638034518SWolfgang Grandegger 
20738034518SWolfgang Grandegger 	/* Enable interrupts */
20838034518SWolfgang Grandegger 	writew(icr, cfg_base + PITA_ICR + 2);
20938034518SWolfgang Grandegger 
21038034518SWolfgang Grandegger 	return 0;
21138034518SWolfgang Grandegger 
21238034518SWolfgang Grandegger failure_remove_channels:
21338034518SWolfgang Grandegger 	/* Disable interrupts */
21438034518SWolfgang Grandegger 	writew(0x0, cfg_base + PITA_ICR + 2);
21538034518SWolfgang Grandegger 
216*29830406SStephane Grosjean 	for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
21738034518SWolfgang Grandegger 		unregister_sja1000dev(dev);
21838034518SWolfgang Grandegger 		free_sja1000dev(dev);
21938034518SWolfgang Grandegger 		priv = netdev_priv(dev);
22038034518SWolfgang Grandegger 		chan = priv->priv;
22138034518SWolfgang Grandegger 	}
22238034518SWolfgang Grandegger 
22338034518SWolfgang Grandegger 	pci_iounmap(pdev, reg_base);
22438034518SWolfgang Grandegger 
22538034518SWolfgang Grandegger failure_unmap_cfg_base:
22638034518SWolfgang Grandegger 	pci_iounmap(pdev, cfg_base);
22738034518SWolfgang Grandegger 
22838034518SWolfgang Grandegger failure_release_regions:
22938034518SWolfgang Grandegger 	pci_release_regions(pdev);
23038034518SWolfgang Grandegger 
23138034518SWolfgang Grandegger failure_disable_pci:
23238034518SWolfgang Grandegger 	pci_disable_device(pdev);
23338034518SWolfgang Grandegger 
23438034518SWolfgang Grandegger 	return err;
23538034518SWolfgang Grandegger }
23638034518SWolfgang Grandegger 
23738034518SWolfgang Grandegger static void __devexit peak_pci_remove(struct pci_dev *pdev)
23838034518SWolfgang Grandegger {
239*29830406SStephane Grosjean 	struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
24038034518SWolfgang Grandegger 	struct sja1000_priv *priv = netdev_priv(dev);
24138034518SWolfgang Grandegger 	struct peak_pci_chan *chan = priv->priv;
24238034518SWolfgang Grandegger 	void __iomem *cfg_base = chan->cfg_base;
24338034518SWolfgang Grandegger 	void __iomem *reg_base = priv->reg_base;
24438034518SWolfgang Grandegger 
24538034518SWolfgang Grandegger 	/* Disable interrupts */
24638034518SWolfgang Grandegger 	writew(0x0, cfg_base + PITA_ICR + 2);
24738034518SWolfgang Grandegger 
24838034518SWolfgang Grandegger 	/* Loop over all registered devices */
24938034518SWolfgang Grandegger 	while (1) {
25038034518SWolfgang Grandegger 		dev_info(&pdev->dev, "removing device %s\n", dev->name);
25138034518SWolfgang Grandegger 		unregister_sja1000dev(dev);
25238034518SWolfgang Grandegger 		free_sja1000dev(dev);
253*29830406SStephane Grosjean 		dev = chan->prev_dev;
25438034518SWolfgang Grandegger 		if (!dev)
25538034518SWolfgang Grandegger 			break;
25638034518SWolfgang Grandegger 		priv = netdev_priv(dev);
25738034518SWolfgang Grandegger 		chan = priv->priv;
25838034518SWolfgang Grandegger 	}
25938034518SWolfgang Grandegger 
26038034518SWolfgang Grandegger 	pci_iounmap(pdev, reg_base);
26138034518SWolfgang Grandegger 	pci_iounmap(pdev, cfg_base);
26238034518SWolfgang Grandegger 	pci_release_regions(pdev);
26338034518SWolfgang Grandegger 	pci_disable_device(pdev);
26438034518SWolfgang Grandegger 
26538034518SWolfgang Grandegger 	pci_set_drvdata(pdev, NULL);
26638034518SWolfgang Grandegger }
26738034518SWolfgang Grandegger 
26838034518SWolfgang Grandegger static struct pci_driver peak_pci_driver = {
26938034518SWolfgang Grandegger 	.name = DRV_NAME,
27038034518SWolfgang Grandegger 	.id_table = peak_pci_tbl,
27138034518SWolfgang Grandegger 	.probe = peak_pci_probe,
27238034518SWolfgang Grandegger 	.remove = __devexit_p(peak_pci_remove),
27338034518SWolfgang Grandegger };
27438034518SWolfgang Grandegger 
27538034518SWolfgang Grandegger static int __init peak_pci_init(void)
27638034518SWolfgang Grandegger {
27738034518SWolfgang Grandegger 	return pci_register_driver(&peak_pci_driver);
27838034518SWolfgang Grandegger }
27938034518SWolfgang Grandegger module_init(peak_pci_init);
28038034518SWolfgang Grandegger 
28138034518SWolfgang Grandegger static void __exit peak_pci_exit(void)
28238034518SWolfgang Grandegger {
28338034518SWolfgang Grandegger 	pci_unregister_driver(&peak_pci_driver);
28438034518SWolfgang Grandegger }
28538034518SWolfgang Grandegger module_exit(peak_pci_exit);
286