aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/can/sja1000
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can/sja1000')
-rw-r--r--drivers/net/can/sja1000/Kconfig28
-rw-r--r--drivers/net/can/sja1000/Makefile1
-rw-r--r--drivers/net/can/sja1000/ems_pci.c12
-rw-r--r--drivers/net/can/sja1000/ems_pcmcia.c20
-rw-r--r--drivers/net/can/sja1000/kvaser_pci.c9
-rw-r--r--drivers/net/can/sja1000/peak_pci.c27
-rw-r--r--drivers/net/can/sja1000/peak_pcmcia.c23
-rw-r--r--drivers/net/can/sja1000/plx_pci.c41
-rw-r--r--drivers/net/can/sja1000/sja1000.c168
-rw-r--r--drivers/net/can/sja1000/sja1000.h68
-rw-r--r--drivers/net/can/sja1000/sja1000_isa.c24
-rw-r--r--drivers/net/can/sja1000/sja1000_of_platform.c225
-rw-r--r--drivers/net/can/sja1000/sja1000_platform.c202
13 files changed, 353 insertions, 495 deletions
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 92f73c708a3..1e65cb6c259 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -1,6 +1,6 @@
menuconfig CAN_SJA1000
tristate "Philips/NXP SJA1000 devices"
- depends on CAN_DEV && HAS_IOMEM
+ depends on HAS_IOMEM
if CAN_SJA1000
@@ -17,16 +17,9 @@ config CAN_SJA1000_PLATFORM
the "platform bus" (Linux abstraction for directly to the
processor attached devices). Which can be found on various
boards from Phytec (http://www.phytec.de) like the PCM027,
- PCM038.
-
-config CAN_SJA1000_OF_PLATFORM
- tristate "Generic OF Platform Bus based SJA1000 driver"
- depends on OF
- ---help---
- This driver adds support for the SJA1000 chips connected to
- the OpenFirmware "platform bus" found on embedded systems with
- OpenFirmware bindings, e.g. if you have a PowerPC based system
- you may want to enable this option.
+ PCM038. It also provides the OpenFirmware "platform bus" found
+ on embedded systems with OpenFirmware bindings, e.g. if you
+ have a PowerPC based system you may want to enable this option.
config CAN_EMS_PCMCIA
tristate "EMS CPC-CARD Card"
@@ -46,6 +39,7 @@ config CAN_EMS_PCI
config CAN_PEAK_PCMCIA
tristate "PEAK PCAN-PC Card"
depends on PCMCIA
+ depends on HAS_IOPORT_MAP
---help---
This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels)
from PEAK-System (http://www.peak-system.com). To compile this
@@ -99,11 +93,11 @@ config CAN_TSCAN1
tristate "TS-CAN1 PC104 boards"
depends on ISA
help
- This driver is for Technologic Systems' TSCAN-1 PC104 boards.
- http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1
- The driver supports multiple boards and automatically configures them:
- PLD IO base addresses are read from jumpers JP1 and JP2,
- IRQ numbers are read from jumpers JP4 and JP5,
- SJA1000 IO base addresses are chosen heuristically (first that works).
+ This driver is for Technologic Systems' TSCAN-1 PC104 boards.
+ http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1
+ The driver supports multiple boards and automatically configures them:
+ PLD IO base addresses are read from jumpers JP1 and JP2,
+ IRQ numbers are read from jumpers JP4 and JP5,
+ SJA1000 IO base addresses are chosen heuristically (first that works).
endif
diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile
index b3d05cbfec3..531d5fcc97e 100644
--- a/drivers/net/can/sja1000/Makefile
+++ b/drivers/net/can/sja1000/Makefile
@@ -5,7 +5,6 @@
obj-$(CONFIG_CAN_SJA1000) += sja1000.o
obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o
obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
-obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o
obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c
index 036a326836b..fd13dbf07d9 100644
--- a/drivers/net/can/sja1000/ems_pci.c
+++ b/drivers/net/can/sja1000/ems_pci.c
@@ -13,8 +13,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
@@ -168,12 +167,12 @@ static inline int ems_pci_check_chan(const struct sja1000_priv *priv)
unsigned char res;
/* Make sure SJA1000 is in reset mode */
- priv->write_reg(priv, REG_MOD, 1);
+ priv->write_reg(priv, SJA1000_MOD, 1);
- priv->write_reg(priv, REG_CDR, CDR_PELICAN);
+ priv->write_reg(priv, SJA1000_CDR, CDR_PELICAN);
/* read reset-values */
- res = priv->read_reg(priv, REG_CDR);
+ res = priv->read_reg(priv, SJA1000_CDR);
if (res == CDR_PELICAN)
return 1;
@@ -207,7 +206,6 @@ static void ems_pci_del_card(struct pci_dev *pdev)
kfree(card);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
}
static void ems_pci_card_reset(struct ems_pci_card *card)
@@ -238,7 +236,6 @@ static int ems_pci_add_card(struct pci_dev *pdev,
/* Allocating card structures to hold addresses, ... */
card = kzalloc(sizeof(struct ems_pci_card), GFP_KERNEL);
if (card == NULL) {
- dev_err(&pdev->dev, "Unable to allocate memory\n");
pci_disable_device(pdev);
return -ENOMEM;
}
@@ -326,6 +323,7 @@ static int ems_pci_add_card(struct pci_dev *pdev,
priv->cdr = EMS_PCI_CDR;
SET_NETDEV_DEV(dev, &pdev->dev);
+ dev->dev_id = i;
if (card->version == 1)
/* reset int flag of pita */
diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c
index 5c2f3fbbf5a..381de998d2f 100644
--- a/drivers/net/can/sja1000/ems_pcmcia.c
+++ b/drivers/net/can/sja1000/ems_pcmcia.c
@@ -126,11 +126,11 @@ static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
{
/* Make sure SJA1000 is in reset mode */
- ems_pcmcia_write_reg(priv, REG_MOD, 1);
- ems_pcmcia_write_reg(priv, REG_CDR, CDR_PELICAN);
+ ems_pcmcia_write_reg(priv, SJA1000_MOD, 1);
+ ems_pcmcia_write_reg(priv, SJA1000_CDR, CDR_PELICAN);
/* read reset-values */
- if (ems_pcmcia_read_reg(priv, REG_CDR) == CDR_PELICAN)
+ if (ems_pcmcia_read_reg(priv, SJA1000_CDR) == CDR_PELICAN)
return 1;
return 0;
@@ -211,6 +211,7 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
priv = netdev_priv(dev);
priv->priv = card;
SET_NETDEV_DEV(dev, &pdev->dev);
+ dev->dev_id = i;
priv->irq_flags = IRQF_SHARED;
dev->irq = pdev->irq;
@@ -316,15 +317,4 @@ static struct pcmcia_driver ems_pcmcia_driver = {
.remove = ems_pcmcia_remove,
.id_table = ems_pcmcia_tbl,
};
-
-static int __init ems_pcmcia_init(void)
-{
- return pcmcia_register_driver(&ems_pcmcia_driver);
-}
-module_init(ems_pcmcia_init);
-
-static void __exit ems_pcmcia_exit(void)
-{
- pcmcia_unregister_driver(&ems_pcmcia_driver);
-}
-module_exit(ems_pcmcia_exit);
+module_pcmcia_driver(ems_pcmcia_driver);
diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c
index 37b0381f532..23b8e1324e2 100644
--- a/drivers/net/can/sja1000/kvaser_pci.c
+++ b/drivers/net/can/sja1000/kvaser_pci.c
@@ -26,8 +26,7 @@
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
@@ -159,9 +158,9 @@ static int number_of_sja1000_chip(void __iomem *base_addr)
for (i = 0; i < MAX_NO_OF_CHANNELS; i++) {
/* reset chip */
iowrite8(MOD_RM, base_addr +
- (i * KVASER_PCI_PORT_BYTES) + REG_MOD);
+ (i * KVASER_PCI_PORT_BYTES) + SJA1000_MOD);
status = ioread8(base_addr +
- (i * KVASER_PCI_PORT_BYTES) + REG_MOD);
+ (i * KVASER_PCI_PORT_BYTES) + SJA1000_MOD);
/* check reset bit */
if (!(status & MOD_RM))
break;
@@ -271,6 +270,7 @@ static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
priv->reg_base, board->conf_addr, dev->irq);
SET_NETDEV_DEV(dev, &pdev->dev);
+ dev->dev_id = channel;
/* Register SJA1000 device */
err = register_sja1000dev(dev);
@@ -387,7 +387,6 @@ static void kvaser_pci_remove_one(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
}
static struct pci_driver kvaser_pci_driver = {
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index d84888f03d9..564933ae218 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -339,8 +339,7 @@ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s)
*/
static void peak_pciec_start_led_work(struct peak_pciec_card *card)
{
- if (!delayed_work_pending(&card->led_work))
- schedule_delayed_work(&card->led_work, HZ);
+ schedule_delayed_work(&card->led_work, HZ);
}
/*
@@ -403,7 +402,7 @@ static void peak_pciec_write_reg(const struct sja1000_priv *priv,
int c = (priv->reg_base - card->reg_base) / PEAK_PCI_CHAN_SIZE;
/* sja1000 register changes control the leds state */
- if (port == REG_MOD)
+ if (port == SJA1000_MOD)
switch (val) {
case MOD_RM:
/* Reset Mode: set led on */
@@ -451,11 +450,8 @@ static int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev)
} else {
/* create the bit banging I2C adapter structure */
card = kzalloc(sizeof(struct peak_pciec_card), GFP_KERNEL);
- if (!card) {
- dev_err(&pdev->dev,
- "failed allocating memory for i2c chip\n");
+ if (!card)
return -ENOMEM;
- }
card->cfg_base = chan->cfg_base;
card->reg_base = priv->reg_base;
@@ -555,7 +551,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct sja1000_priv *priv;
struct peak_pci_chan *chan;
- struct net_device *dev;
+ struct net_device *dev, *prev_dev;
void __iomem *cfg_base, *reg_base;
u16 sub_sys_id, icr;
int i, err, channels;
@@ -646,6 +642,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
icr |= chan->icr_mask;
SET_NETDEV_DEV(dev, &pdev->dev);
+ dev->dev_id = i;
/* Create chain of SJA1000 devices */
chan->prev_dev = pci_get_drvdata(pdev);
@@ -691,11 +688,13 @@ failure_remove_channels:
writew(0x0, cfg_base + PITA_ICR + 2);
chan = NULL;
- for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
- unregister_sja1000dev(dev);
- free_sja1000dev(dev);
+ for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
priv = netdev_priv(dev);
chan = priv->priv;
+ prev_dev = chan->prev_dev;
+
+ unregister_sja1000dev(dev);
+ free_sja1000dev(dev);
}
/* free any PCIeC resources too */
@@ -729,10 +728,12 @@ static void peak_pci_remove(struct pci_dev *pdev)
/* Loop over all registered devices */
while (1) {
+ struct net_device *prev_dev = chan->prev_dev;
+
dev_info(&pdev->dev, "removing device %s\n", dev->name);
unregister_sja1000dev(dev);
free_sja1000dev(dev);
- dev = chan->prev_dev;
+ dev = prev_dev;
if (!dev) {
/* do that only for first channel */
@@ -748,8 +749,6 @@ static void peak_pci_remove(struct pci_dev *pdev)
pci_iounmap(pdev, cfg_base);
pci_release_regions(pdev);
pci_disable_device(pdev);
-
- pci_set_drvdata(pdev, NULL);
}
static struct pci_driver peak_pci_driver = {
diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
index f1175142b0a..dd56133cc46 100644
--- a/drivers/net/can/sja1000/peak_pcmcia.c
+++ b/drivers/net/can/sja1000/peak_pcmcia.c
@@ -196,7 +196,7 @@ static void pcan_write_canreg(const struct sja1000_priv *priv, int port, u8 v)
int c = (priv->reg_base - card->ioport_addr) / PCC_CHAN_SIZE;
/* sja1000 register changes control the leds state */
- if (port == REG_MOD)
+ if (port == SJA1000_MOD)
switch (v) {
case MOD_RM:
/* Reset Mode: set led on */
@@ -509,11 +509,11 @@ static void pcan_free_channels(struct pcan_pccard *card)
static inline int pcan_channel_present(struct sja1000_priv *priv)
{
/* make sure SJA1000 is in reset mode */
- pcan_write_canreg(priv, REG_MOD, 1);
- pcan_write_canreg(priv, REG_CDR, CDR_PELICAN);
+ pcan_write_canreg(priv, SJA1000_MOD, 1);
+ pcan_write_canreg(priv, SJA1000_CDR, CDR_PELICAN);
/* read reset-values */
- if (pcan_read_canreg(priv, REG_CDR) == CDR_PELICAN)
+ if (pcan_read_canreg(priv, SJA1000_CDR) == CDR_PELICAN)
return 1;
return 0;
@@ -550,6 +550,7 @@ static int pcan_add_channels(struct pcan_pccard *card)
priv = netdev_priv(netdev);
priv->priv = card;
SET_NETDEV_DEV(netdev, &pdev->dev);
+ netdev->dev_id = i;
priv->irq_flags = IRQF_SHARED;
netdev->irq = pdev->irq;
@@ -660,7 +661,6 @@ static int pcan_probe(struct pcmcia_device *pdev)
card = kzalloc(sizeof(struct pcan_pccard), GFP_KERNEL);
if (!card) {
- dev_err(&pdev->dev, "couldn't allocate card memory\n");
err = -ENOMEM;
goto probe_err_2;
}
@@ -741,15 +741,4 @@ static struct pcmcia_driver pcan_driver = {
.remove = pcan_remove,
.id_table = pcan_table,
};
-
-static int __init pcan_init(void)
-{
- return pcmcia_register_driver(&pcan_driver);
-}
-module_init(pcan_init);
-
-static void __exit pcan_exit(void)
-{
- pcmcia_unregister_driver(&pcan_driver);
-}
-module_exit(pcan_exit);
+module_pcmcia_driver(pcan_driver);
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index 11d1062a944..ec39b7cb228 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
@@ -45,7 +44,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
"esd CAN-PCI/PMC/266, "
"esd CAN-PCIe/2000, "
"Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
- "IXXAT PC-I 04/PCI")
+ "IXXAT PC-I 04/PCI, "
+ "ELCUS CAN-200-PCI")
MODULE_LICENSE("GPL v2");
#define PLX_PCI_MAX_CHAN 2
@@ -123,6 +123,11 @@ struct plx_pci_card {
#define ESD_PCI_SUB_SYS_ID_PCIE2000 0x0200
#define ESD_PCI_SUB_SYS_ID_PCI104200 0x0501
+#define CAN200PCI_DEVICE_ID 0x9030
+#define CAN200PCI_VENDOR_ID 0x10b5
+#define CAN200PCI_SUB_DEVICE_ID 0x0301
+#define CAN200PCI_SUB_VENDOR_ID 0xe1c5
+
#define IXXAT_PCI_VENDOR_ID 0x10b5
#define IXXAT_PCI_DEVICE_ID 0x9050
#define IXXAT_PCI_SUB_SYS_ID 0x2540
@@ -234,6 +239,14 @@ static struct plx_pci_card_info plx_pci_card_info_cti = {
/* based on PLX9030 */
};
+static struct plx_pci_card_info plx_pci_card_info_elcus = {
+ "Eclus CAN-200-PCI", 2,
+ PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+ {1, 0x00, 0x00}, { {2, 0x00, 0x80}, {3, 0x00, 0x80} },
+ &plx_pci_reset_common
+ /* based on PLX9030 */
+};
+
static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
{
/* Adlink PCI-7841/cPCI-7841 */
@@ -319,6 +332,13 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
0, 0,
(kernel_ulong_t)&plx_pci_card_info_cti
},
+ {
+ /* Elcus CAN-200-PCI */
+ CAN200PCI_VENDOR_ID, CAN200PCI_DEVICE_ID,
+ CAN200PCI_SUB_VENDOR_ID, CAN200PCI_SUB_DEVICE_ID,
+ 0, 0,
+ (kernel_ulong_t)&plx_pci_card_info_elcus
+ },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
@@ -348,20 +368,20 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
*/
if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) ==
REG_CR_BASICCAN_INITIAL &&
- (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) &&
- (priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL))
+ (priv->read_reg(priv, SJA1000_SR) == REG_SR_BASICCAN_INITIAL) &&
+ (priv->read_reg(priv, SJA1000_IR) == REG_IR_BASICCAN_INITIAL))
flag = 1;
/* Bring the SJA1000 into the PeliCAN mode*/
- priv->write_reg(priv, REG_CDR, CDR_PELICAN);
+ priv->write_reg(priv, SJA1000_CDR, CDR_PELICAN);
/*
* Check registers after reset in the PeliCAN mode.
* See states on p. 23 of the Datasheet.
*/
- if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL &&
- priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL &&
- priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL)
+ if (priv->read_reg(priv, SJA1000_MOD) == REG_MOD_PELICAN_INITIAL &&
+ priv->read_reg(priv, SJA1000_SR) == REG_SR_PELICAN_INITIAL &&
+ priv->read_reg(priv, SJA1000_IR) == REG_IR_PELICAN_INITIAL)
return flag;
return 0;
@@ -477,7 +497,6 @@ static void plx_pci_del_card(struct pci_dev *pdev)
kfree(card);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
}
/*
@@ -508,7 +527,6 @@ static int plx_pci_add_card(struct pci_dev *pdev,
/* Allocate card structures to hold addresses, ... */
card = kzalloc(sizeof(*card), GFP_KERNEL);
if (!card) {
- dev_err(&pdev->dev, "Unable to allocate memory\n");
pci_disable_device(pdev);
return -ENOMEM;
}
@@ -569,6 +587,7 @@ static int plx_pci_add_card(struct pci_dev *pdev,
priv->cdr = ci->cdr;
SET_NETDEV_DEV(dev, &pdev->dev);
+ dev->dev_id = i;
/* Register SJA1000 device */
err = register_sja1000dev(dev);
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 83ee11eca0e..f31499a32d7 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -60,6 +60,7 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
+#include <linux/can/led.h>
#include "sja1000.h"
@@ -90,14 +91,14 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
* the write_reg() operation - especially on SMP systems.
*/
spin_lock_irqsave(&priv->cmdreg_lock, flags);
- priv->write_reg(priv, REG_CMR, val);
- priv->read_reg(priv, REG_SR);
+ priv->write_reg(priv, SJA1000_CMR, val);
+ priv->read_reg(priv, SJA1000_SR);
spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
}
static int sja1000_is_absent(struct sja1000_priv *priv)
{
- return (priv->read_reg(priv, REG_MOD) == 0xFF);
+ return (priv->read_reg(priv, SJA1000_MOD) == 0xFF);
}
static int sja1000_probe_chip(struct net_device *dev)
@@ -105,8 +106,7 @@ static int sja1000_probe_chip(struct net_device *dev)
struct sja1000_priv *priv = netdev_priv(dev);
if (priv->reg_base && sja1000_is_absent(priv)) {
- printk(KERN_INFO "%s: probing @0x%lX failed\n",
- DRV_NAME, dev->base_addr);
+ netdev_err(dev, "probing failed\n");
return 0;
}
return -1;
@@ -115,11 +115,11 @@ static int sja1000_probe_chip(struct net_device *dev)
static void set_reset_mode(struct net_device *dev)
{
struct sja1000_priv *priv = netdev_priv(dev);
- unsigned char status = priv->read_reg(priv, REG_MOD);
+ unsigned char status = priv->read_reg(priv, SJA1000_MOD);
int i;
/* disable interrupts */
- priv->write_reg(priv, REG_IER, IRQ_OFF);
+ priv->write_reg(priv, SJA1000_IER, IRQ_OFF);
for (i = 0; i < 100; i++) {
/* check reset bit */
@@ -128,9 +128,10 @@ static void set_reset_mode(struct net_device *dev)
return;
}
- priv->write_reg(priv, REG_MOD, MOD_RM); /* reset chip */
+ /* reset chip */
+ priv->write_reg(priv, SJA1000_MOD, MOD_RM);
udelay(10);
- status = priv->read_reg(priv, REG_MOD);
+ status = priv->read_reg(priv, SJA1000_MOD);
}
netdev_err(dev, "setting SJA1000 into reset mode failed!\n");
@@ -139,7 +140,7 @@ static void set_reset_mode(struct net_device *dev)
static void set_normal_mode(struct net_device *dev)
{
struct sja1000_priv *priv = netdev_priv(dev);
- unsigned char status = priv->read_reg(priv, REG_MOD);
+ unsigned char status = priv->read_reg(priv, SJA1000_MOD);
int i;
for (i = 0; i < 100; i++) {
@@ -148,22 +149,22 @@ static void set_normal_mode(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* enable interrupts */
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
- priv->write_reg(priv, REG_IER, IRQ_ALL);
+ priv->write_reg(priv, SJA1000_IER, IRQ_ALL);
else
- priv->write_reg(priv, REG_IER,
+ priv->write_reg(priv, SJA1000_IER,
IRQ_ALL & ~IRQ_BEI);
return;
}
/* set chip to normal mode */
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
- priv->write_reg(priv, REG_MOD, MOD_LOM);
+ priv->write_reg(priv, SJA1000_MOD, MOD_LOM);
else
- priv->write_reg(priv, REG_MOD, 0x00);
+ priv->write_reg(priv, SJA1000_MOD, 0x00);
udelay(10);
- status = priv->read_reg(priv, REG_MOD);
+ status = priv->read_reg(priv, SJA1000_MOD);
}
netdev_err(dev, "setting SJA1000 into normal mode failed!\n");
@@ -178,9 +179,9 @@ static void sja1000_start(struct net_device *dev)
set_reset_mode(dev);
/* Clear error counters and error code capture */
- priv->write_reg(priv, REG_TXERR, 0x0);
- priv->write_reg(priv, REG_RXERR, 0x0);
- priv->read_reg(priv, REG_ECC);
+ priv->write_reg(priv, SJA1000_TXERR, 0x0);
+ priv->write_reg(priv, SJA1000_RXERR, 0x0);
+ priv->read_reg(priv, SJA1000_ECC);
/* leave reset mode */
set_normal_mode(dev);
@@ -216,8 +217,8 @@ static int sja1000_set_bittiming(struct net_device *dev)
netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
- priv->write_reg(priv, REG_BTR0, btr0);
- priv->write_reg(priv, REG_BTR1, btr1);
+ priv->write_reg(priv, SJA1000_BTR0, btr0);
+ priv->write_reg(priv, SJA1000_BTR1, btr1);
return 0;
}
@@ -227,8 +228,8 @@ static int sja1000_get_berr_counter(const struct net_device *dev,
{
struct sja1000_priv *priv = netdev_priv(dev);
- bec->txerr = priv->read_reg(priv, REG_TXERR);
- bec->rxerr = priv->read_reg(priv, REG_RXERR);
+ bec->txerr = priv->read_reg(priv, SJA1000_TXERR);
+ bec->rxerr = priv->read_reg(priv, SJA1000_RXERR);
return 0;
}
@@ -246,20 +247,20 @@ static void chipset_init(struct net_device *dev)
struct sja1000_priv *priv = netdev_priv(dev);
/* set clock divider and output control register */
- priv->write_reg(priv, REG_CDR, priv->cdr | CDR_PELICAN);
+ priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
/* set acceptance filter (accept all) */
- priv->write_reg(priv, REG_ACCC0, 0x00);
- priv->write_reg(priv, REG_ACCC1, 0x00);
- priv->write_reg(priv, REG_ACCC2, 0x00);
- priv->write_reg(priv, REG_ACCC3, 0x00);
+ priv->write_reg(priv, SJA1000_ACCC0, 0x00);
+ priv->write_reg(priv, SJA1000_ACCC1, 0x00);
+ priv->write_reg(priv, SJA1000_ACCC2, 0x00);
+ priv->write_reg(priv, SJA1000_ACCC3, 0x00);
- priv->write_reg(priv, REG_ACCM0, 0xFF);
- priv->write_reg(priv, REG_ACCM1, 0xFF);
- priv->write_reg(priv, REG_ACCM2, 0xFF);
- priv->write_reg(priv, REG_ACCM3, 0xFF);
+ priv->write_reg(priv, SJA1000_ACCM0, 0xFF);
+ priv->write_reg(priv, SJA1000_ACCM1, 0xFF);
+ priv->write_reg(priv, SJA1000_ACCM2, 0xFF);
+ priv->write_reg(priv, SJA1000_ACCM3, 0xFF);
- priv->write_reg(priv, REG_OCR, priv->ocr | OCR_MODE_NORMAL);
+ priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL);
}
/*
@@ -288,21 +289,21 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
id = cf->can_id;
if (id & CAN_RTR_FLAG)
- fi |= FI_RTR;
+ fi |= SJA1000_FI_RTR;
if (id & CAN_EFF_FLAG) {
- fi |= FI_FF;
- dreg = EFF_BUF;
- priv->write_reg(priv, REG_FI, fi);
- priv->write_reg(priv, REG_ID1, (id & 0x1fe00000) >> (5 + 16));
- priv->write_reg(priv, REG_ID2, (id & 0x001fe000) >> (5 + 8));
- priv->write_reg(priv, REG_ID3, (id & 0x00001fe0) >> 5);
- priv->write_reg(priv, REG_ID4, (id & 0x0000001f) << 3);
+ fi |= SJA1000_FI_FF;
+ dreg = SJA1000_EFF_BUF;
+ priv->write_reg(priv, SJA1000_FI, fi);
+ priv->write_reg(priv, SJA1000_ID1, (id & 0x1fe00000) >> 21);
+ priv->write_reg(priv, SJA1000_ID2, (id & 0x001fe000) >> 13);
+ priv->write_reg(priv, SJA1000_ID3, (id & 0x00001fe0) >> 5);
+ priv->write_reg(priv, SJA1000_ID4, (id & 0x0000001f) << 3);
} else {
- dreg = SFF_BUF;
- priv->write_reg(priv, REG_FI, fi);
- priv->write_reg(priv, REG_ID1, (id & 0x000007f8) >> 3);
- priv->write_reg(priv, REG_ID2, (id & 0x00000007) << 5);
+ dreg = SJA1000_SFF_BUF;
+ priv->write_reg(priv, SJA1000_FI, fi);
+ priv->write_reg(priv, SJA1000_ID1, (id & 0x000007f8) >> 3);
+ priv->write_reg(priv, SJA1000_ID2, (id & 0x00000007) << 5);
}
for (i = 0; i < dlc; i++)
@@ -334,25 +335,25 @@ static void sja1000_rx(struct net_device *dev)
if (skb == NULL)
return;
- fi = priv->read_reg(priv, REG_FI);
+ fi = priv->read_reg(priv, SJA1000_FI);
- if (fi & FI_FF) {
+ if (fi & SJA1000_FI_FF) {
/* extended frame format (EFF) */
- dreg = EFF_BUF;
- id = (priv->read_reg(priv, REG_ID1) << (5 + 16))
- | (priv->read_reg(priv, REG_ID2) << (5 + 8))
- | (priv->read_reg(priv, REG_ID3) << 5)
- | (priv->read_reg(priv, REG_ID4) >> 3);
+ dreg = SJA1000_EFF_BUF;
+ id = (priv->read_reg(priv, SJA1000_ID1) << 21)
+ | (priv->read_reg(priv, SJA1000_ID2) << 13)
+ | (priv->read_reg(priv, SJA1000_ID3) << 5)
+ | (priv->read_reg(priv, SJA1000_ID4) >> 3);
id |= CAN_EFF_FLAG;
} else {
/* standard frame format (SFF) */
- dreg = SFF_BUF;
- id = (priv->read_reg(priv, REG_ID1) << 3)
- | (priv->read_reg(priv, REG_ID2) >> 5);
+ dreg = SJA1000_SFF_BUF;
+ id = (priv->read_reg(priv, SJA1000_ID1) << 3)
+ | (priv->read_reg(priv, SJA1000_ID2) >> 5);
}
cf->can_dlc = get_can_dlc(fi & 0x0F);
- if (fi & FI_RTR) {
+ if (fi & SJA1000_FI_RTR) {
id |= CAN_RTR_FLAG;
} else {
for (i = 0; i < cf->can_dlc; i++)
@@ -368,6 +369,8 @@ static void sja1000_rx(struct net_device *dev)
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+
+ can_led_event(dev, CAN_LED_EVENT_RX);
}
static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
@@ -411,7 +414,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
priv->can.can_stats.bus_error++;
stats->rx_errors++;
- ecc = priv->read_reg(priv, REG_ECC);
+ ecc = priv->read_reg(priv, SJA1000_ECC);
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
@@ -445,7 +448,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
if (isrc & IRQ_ALI) {
/* arbitration lost interrupt */
netdev_dbg(dev, "arbitration lost interrupt\n");
- alc = priv->read_reg(priv, REG_ALC);
+ alc = priv->read_reg(priv, SJA1000_ALC);
priv->can.can_stats.arbitration_lost++;
stats->tx_errors++;
cf->can_id |= CAN_ERR_LOSTARB;
@@ -454,8 +457,8 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
state == CAN_STATE_ERROR_PASSIVE)) {
- uint8_t rxerr = priv->read_reg(priv, REG_RXERR);
- uint8_t txerr = priv->read_reg(priv, REG_TXERR);
+ uint8_t rxerr = priv->read_reg(priv, SJA1000_RXERR);
+ uint8_t txerr = priv->read_reg(priv, SJA1000_TXERR);
cf->can_id |= CAN_ERR_CRTL;
if (state == CAN_STATE_ERROR_WARNING) {
priv->can.can_stats.error_warning++;
@@ -490,19 +493,20 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
uint8_t isrc, status;
int n = 0;
- /* Shared interrupts and IRQ off? */
- if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
- return IRQ_NONE;
-
if (priv->pre_irq)
priv->pre_irq(priv);
- while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
- n++;
- status = priv->read_reg(priv, REG_SR);
+ /* Shared interrupts and IRQ off? */
+ if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
+ goto out;
+
+ while ((isrc = priv->read_reg(priv, SJA1000_IR)) &&
+ (n < SJA1000_MAX_IRQ)) {
+
+ status = priv->read_reg(priv, SJA1000_SR);
/* check for absent controller due to hw unplug */
if (status == 0xFF && sja1000_is_absent(priv))
- return IRQ_NONE;
+ goto out;
if (isrc & IRQ_WUI)
netdev_warn(dev, "wakeup interrupt\n");
@@ -516,20 +520,21 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
} else {
/* transmission complete */
stats->tx_bytes +=
- priv->read_reg(priv, REG_FI) & 0xf;
+ priv->read_reg(priv, SJA1000_FI) & 0xf;
stats->tx_packets++;
can_get_echo_skb(dev, 0);
}
netif_wake_queue(dev);
+ can_led_event(dev, CAN_LED_EVENT_TX);
}
if (isrc & IRQ_RI) {
/* receive interrupt */
while (status & SR_RBS) {
sja1000_rx(dev);
- status = priv->read_reg(priv, REG_SR);
+ status = priv->read_reg(priv, SJA1000_SR);
/* check for absent controller */
if (status == 0xFF && sja1000_is_absent(priv))
- return IRQ_NONE;
+ goto out;
}
}
if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
@@ -537,8 +542,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
if (sja1000_err(dev, isrc, status))
break;
}
+ n++;
}
-
+out:
if (priv->post_irq)
priv->post_irq(priv);
@@ -575,6 +581,8 @@ static int sja1000_open(struct net_device *dev)
/* init and start chi */
sja1000_start(dev);
+ can_led_event(dev, CAN_LED_EVENT_OPEN);
+
netif_start_queue(dev);
return 0;
@@ -592,6 +600,8 @@ static int sja1000_close(struct net_device *dev)
close_candev(dev);
+ can_led_event(dev, CAN_LED_EVENT_STOP);
+
return 0;
}
@@ -632,13 +642,16 @@ void free_sja1000dev(struct net_device *dev)
EXPORT_SYMBOL_GPL(free_sja1000dev);
static const struct net_device_ops sja1000_netdev_ops = {
- .ndo_open = sja1000_open,
- .ndo_stop = sja1000_close,
- .ndo_start_xmit = sja1000_start_xmit,
+ .ndo_open = sja1000_open,
+ .ndo_stop = sja1000_close,
+ .ndo_start_xmit = sja1000_start_xmit,
+ .ndo_change_mtu = can_change_mtu,
};
int register_sja1000dev(struct net_device *dev)
{
+ int ret;
+
if (!sja1000_probe_chip(dev))
return -ENODEV;
@@ -648,7 +661,12 @@ int register_sja1000dev(struct net_device *dev)
set_reset_mode(dev);
chipset_init(dev);
- return register_candev(dev);
+ ret = register_candev(dev);
+
+ if (!ret)
+ devm_can_led_init(dev);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(register_sja1000dev);
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index afa99847a51..9d46398f815 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -54,46 +54,46 @@
#define SJA1000_MAX_IRQ 20 /* max. number of interrupts handled in ISR */
/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
-#define REG_MOD 0x00
-#define REG_CMR 0x01
-#define REG_SR 0x02
-#define REG_IR 0x03
-#define REG_IER 0x04
-#define REG_ALC 0x0B
-#define REG_ECC 0x0C
-#define REG_EWL 0x0D
-#define REG_RXERR 0x0E
-#define REG_TXERR 0x0F
-#define REG_ACCC0 0x10
-#define REG_ACCC1 0x11
-#define REG_ACCC2 0x12
-#define REG_ACCC3 0x13
-#define REG_ACCM0 0x14
-#define REG_ACCM1 0x15
-#define REG_ACCM2 0x16
-#define REG_ACCM3 0x17
-#define REG_RMC 0x1D
-#define REG_RBSA 0x1E
+#define SJA1000_MOD 0x00
+#define SJA1000_CMR 0x01
+#define SJA1000_SR 0x02
+#define SJA1000_IR 0x03
+#define SJA1000_IER 0x04
+#define SJA1000_ALC 0x0B
+#define SJA1000_ECC 0x0C
+#define SJA1000_EWL 0x0D
+#define SJA1000_RXERR 0x0E
+#define SJA1000_TXERR 0x0F
+#define SJA1000_ACCC0 0x10
+#define SJA1000_ACCC1 0x11
+#define SJA1000_ACCC2 0x12
+#define SJA1000_ACCC3 0x13
+#define SJA1000_ACCM0 0x14
+#define SJA1000_ACCM1 0x15
+#define SJA1000_ACCM2 0x16
+#define SJA1000_ACCM3 0x17
+#define SJA1000_RMC 0x1D
+#define SJA1000_RBSA 0x1E
/* Common registers - manual section 6.5 */
-#define REG_BTR0 0x06
-#define REG_BTR1 0x07
-#define REG_OCR 0x08
-#define REG_CDR 0x1F
+#define SJA1000_BTR0 0x06
+#define SJA1000_BTR1 0x07
+#define SJA1000_OCR 0x08
+#define SJA1000_CDR 0x1F
-#define REG_FI 0x10
-#define SFF_BUF 0x13
-#define EFF_BUF 0x15
+#define SJA1000_FI 0x10
+#define SJA1000_SFF_BUF 0x13
+#define SJA1000_EFF_BUF 0x15
-#define FI_FF 0x80
-#define FI_RTR 0x40
+#define SJA1000_FI_FF 0x80
+#define SJA1000_FI_RTR 0x40
-#define REG_ID1 0x11
-#define REG_ID2 0x12
-#define REG_ID3 0x13
-#define REG_ID4 0x14
+#define SJA1000_ID1 0x11
+#define SJA1000_ID2 0x12
+#define SJA1000_ID3 0x13
+#define SJA1000_ID4 0x14
-#define CAN_RAM 0x20
+#define SJA1000_CAN_RAM 0x20
/* mode register */
#define MOD_RM 0x01
diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c
index 5c8da466148..014695d7e6a 100644
--- a/drivers/net/can/sja1000/sja1000_isa.c
+++ b/drivers/net/can/sja1000/sja1000_isa.c
@@ -11,8 +11,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
@@ -47,6 +46,7 @@ static int clk[MAXDEV];
static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+static spinlock_t indirect_lock[MAXDEV]; /* lock for indirect access mode */
module_param_array(port, ulong, NULL, S_IRUGO);
MODULE_PARM_DESC(port, "I/O port number");
@@ -102,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,
static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
int reg)
{
- unsigned long base = (unsigned long)priv->reg_base;
+ unsigned long flags, base = (unsigned long)priv->reg_base;
+ u8 readval;
+ spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
outb(reg, base);
- return inb(base + 1);
+ readval = inb(base + 1);
+ spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
+
+ return readval;
}
static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
int reg, u8 val)
{
- unsigned long base = (unsigned long)priv->reg_base;
+ unsigned long flags, base = (unsigned long)priv->reg_base;
+ spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
outb(reg, base);
outb(val, base + 1);
+ spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
}
static int sja1000_isa_probe(struct platform_device *pdev)
@@ -170,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
if (iosize == SJA1000_IOSIZE_INDIRECT) {
priv->read_reg = sja1000_isa_port_read_reg_indirect;
priv->write_reg = sja1000_isa_port_write_reg_indirect;
+ spin_lock_init(&indirect_lock[idx]);
} else {
priv->read_reg = sja1000_isa_port_read_reg;
priv->write_reg = sja1000_isa_port_write_reg;
@@ -197,8 +205,9 @@ static int sja1000_isa_probe(struct platform_device *pdev)
else
priv->cdr = CDR_DEFAULT;
- dev_set_drvdata(&pdev->dev, dev);
+ platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
+ dev->dev_id = idx;
err = register_sja1000dev(dev);
if (err) {
@@ -225,12 +234,11 @@ static int sja1000_isa_probe(struct platform_device *pdev)
static int sja1000_isa_remove(struct platform_device *pdev)
{
- struct net_device *dev = dev_get_drvdata(&pdev->dev);
+ struct net_device *dev = platform_get_drvdata(pdev);
struct sja1000_priv *priv = netdev_priv(dev);
int idx = pdev->id;
unregister_sja1000dev(dev);
- dev_set_drvdata(&pdev->dev, NULL);
if (mem[idx]) {
iounmap(priv->reg_base);
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
deleted file mode 100644
index 6433b81256c..00000000000
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Driver for SJA1000 CAN controllers on the OpenFirmware platform bus
- *
- * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the version 2 of the GNU General Public License
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This is a generic driver for SJA1000 chips on the OpenFirmware platform
- * bus found on embedded PowerPC systems. You need a SJA1000 CAN node
- * definition in your flattened device tree source (DTS) file similar to:
- *
- * can@3,100 {
- * compatible = "nxp,sja1000";
- * reg = <3 0x100 0x80>;
- * interrupts = <2 0>;
- * interrupt-parent = <&mpic>;
- * nxp,external-clock-frequency = <16000000>;
- * };
- *
- * See "Documentation/devicetree/bindings/net/can/sja1000.txt" for further
- * information.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/can/dev.h>
-
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <asm/prom.h>
-
-#include "sja1000.h"
-
-#define DRV_NAME "sja1000_of_platform"
-
-MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
-MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the OF platform bus");
-MODULE_LICENSE("GPL v2");
-
-#define SJA1000_OFP_CAN_CLOCK (16000000 / 2)
-
-#define SJA1000_OFP_OCR OCR_TX0_PULLDOWN
-#define SJA1000_OFP_CDR (CDR_CBP | CDR_CLK_OFF)
-
-static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg)
-{
- return ioread8(priv->reg_base + reg);
-}
-
-static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
- int reg, u8 val)
-{
- iowrite8(val, priv->reg_base + reg);
-}
-
-static int sja1000_ofp_remove(struct platform_device *ofdev)
-{
- struct net_device *dev = dev_get_drvdata(&ofdev->dev);
- struct sja1000_priv *priv = netdev_priv(dev);
- struct device_node *np = ofdev->dev.of_node;
- struct resource res;
-
- dev_set_drvdata(&ofdev->dev, NULL);
-
- unregister_sja1000dev(dev);
- free_sja1000dev(dev);
- iounmap(priv->reg_base);
- irq_dispose_mapping(dev->irq);
-
- of_address_to_resource(np, 0, &res);
- release_mem_region(res.start, resource_size(&res));
-
- return 0;
-}
-
-static int sja1000_ofp_probe(struct platform_device *ofdev)
-{
- struct device_node *np = ofdev->dev.of_node;
- struct net_device *dev;
- struct sja1000_priv *priv;
- struct resource res;
- const u32 *prop;
- int err, irq, res_size, prop_size;
- void __iomem *base;
-
- err = of_address_to_resource(np, 0, &res);
- if (err) {
- dev_err(&ofdev->dev, "invalid address\n");
- return err;
- }
-
- res_size = resource_size(&res);
-
- if (!request_mem_region(res.start, res_size, DRV_NAME)) {
- dev_err(&ofdev->dev, "couldn't request %pR\n", &res);
- return -EBUSY;
- }
-
- base = ioremap_nocache(res.start, res_size);
- if (!base) {
- dev_err(&ofdev->dev, "couldn't ioremap %pR\n", &res);
- err = -ENOMEM;
- goto exit_release_mem;
- }
-
- irq = irq_of_parse_and_map(np, 0);
- if (irq == 0) {
- dev_err(&ofdev->dev, "no irq found\n");
- err = -ENODEV;
- goto exit_unmap_mem;
- }
-
- dev = alloc_sja1000dev(0);
- if (!dev) {
- err = -ENOMEM;
- goto exit_dispose_irq;
- }
-
- priv = netdev_priv(dev);
-
- priv->read_reg = sja1000_ofp_read_reg;
- priv->write_reg = sja1000_ofp_write_reg;
-
- prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->can.clock.freq = *prop / 2;
- else
- priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
-
- prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= *prop & OCR_MODE_MASK;
- else
- priv->ocr |= OCR_MODE_NORMAL; /* default */
-
- prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
- else
- priv->ocr |= OCR_TX0_PULLDOWN; /* default */
-
- prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)) && *prop) {
- u32 divider = priv->can.clock.freq * 2 / *prop;
-
- if (divider > 1)
- priv->cdr |= divider / 2 - 1;
- else
- priv->cdr |= CDR_CLKOUT_MASK;
- } else {
- priv->cdr |= CDR_CLK_OFF; /* default */
- }
-
- prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
- if (!prop)
- priv->cdr |= CDR_CBP; /* default */
-
- priv->irq_flags = IRQF_SHARED;
- priv->reg_base = base;
-
- dev->irq = irq;
-
- dev_info(&ofdev->dev,
- "reg_base=0x%p irq=%d clock=%d ocr=0x%02x cdr=0x%02x\n",
- priv->reg_base, dev->irq, priv->can.clock.freq,
- priv->ocr, priv->cdr);
-
- dev_set_drvdata(&ofdev->dev, dev);
- SET_NETDEV_DEV(dev, &ofdev->dev);
-
- err = register_sja1000dev(dev);
- if (err) {
- dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
- DRV_NAME, err);
- goto exit_free_sja1000;
- }
-
- return 0;
-
-exit_free_sja1000:
- free_sja1000dev(dev);
-exit_dispose_irq:
- irq_dispose_mapping(irq);
-exit_unmap_mem:
- iounmap(base);
-exit_release_mem:
- release_mem_region(res.start, res_size);
-
- return err;
-}
-
-static struct of_device_id sja1000_ofp_table[] = {
- {.compatible = "nxp,sja1000"},
- {},
-};
-MODULE_DEVICE_TABLE(of, sja1000_ofp_table);
-
-static struct platform_driver sja1000_ofp_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = DRV_NAME,
- .of_match_table = sja1000_ofp_table,
- },
- .probe = sja1000_ofp_probe,
- .remove = sja1000_ofp_remove,
-};
-
-module_platform_driver(sja1000_ofp_driver);
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 21619bb5b86..95a844a7ee7 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -12,8 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
@@ -27,12 +26,16 @@
#include <linux/can/dev.h>
#include <linux/can/platform/sja1000.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
#include "sja1000.h"
#define DRV_NAME "sja1000_platform"
+#define SP_CAN_CLOCK (16000000 / 2)
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_LICENSE("GPL v2");
@@ -67,59 +70,16 @@ static void sp_write_reg32(const struct sja1000_priv *priv, int reg, u8 val)
iowrite8(val, priv->reg_base + reg * 4);
}
-static int sp_probe(struct platform_device *pdev)
+static void sp_populate(struct sja1000_priv *priv,
+ struct sja1000_platform_data *pdata,
+ unsigned long resource_mem_flags)
{
- int err;
- void __iomem *addr;
- struct net_device *dev;
- struct sja1000_priv *priv;
- struct resource *res_mem, *res_irq;
- struct sja1000_platform_data *pdata;
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "No platform data provided!\n");
- err = -ENODEV;
- goto exit;
- }
-
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_mem || !res_irq) {
- err = -ENODEV;
- goto exit;
- }
-
- if (!request_mem_region(res_mem->start, resource_size(res_mem),
- DRV_NAME)) {
- err = -EBUSY;
- goto exit;
- }
-
- addr = ioremap_nocache(res_mem->start, resource_size(res_mem));
- if (!addr) {
- err = -ENOMEM;
- goto exit_release;
- }
-
- dev = alloc_sja1000dev(0);
- if (!dev) {
- err = -ENOMEM;
- goto exit_iounmap;
- }
- priv = netdev_priv(dev);
-
- dev->irq = res_irq->start;
- priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
- if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE)
- priv->irq_flags |= IRQF_SHARED;
- priv->reg_base = addr;
/* The CAN clock frequency is half the oscillator clock frequency */
priv->can.clock.freq = pdata->osc_freq / 2;
priv->ocr = pdata->ocr;
priv->cdr = pdata->cdr;
- switch (res_mem->flags & IORESOURCE_MEM_TYPE_MASK) {
+ switch (resource_mem_flags & IORESOURCE_MEM_TYPE_MASK) {
case IORESOURCE_MEM_32BIT:
priv->read_reg = sp_read_reg32;
priv->write_reg = sp_write_reg32;
@@ -134,8 +94,126 @@ static int sp_probe(struct platform_device *pdev)
priv->write_reg = sp_write_reg8;
break;
}
+}
+
+static void sp_populate_of(struct sja1000_priv *priv, struct device_node *of)
+{
+ int err;
+ u32 prop;
+
+ err = of_property_read_u32(of, "reg-io-width", &prop);
+ if (err)
+ prop = 1; /* 8 bit is default */
+
+ switch (prop) {
+ case 4:
+ priv->read_reg = sp_read_reg32;
+ priv->write_reg = sp_write_reg32;
+ break;
+ case 2:
+ priv->read_reg = sp_read_reg16;
+ priv->write_reg = sp_write_reg16;
+ break;
+ case 1: /* fallthrough */
+ default:
+ priv->read_reg = sp_read_reg8;
+ priv->write_reg = sp_write_reg8;
+ }
- dev_set_drvdata(&pdev->dev, dev);
+ err = of_property_read_u32(of, "nxp,external-clock-frequency", &prop);
+ if (!err)
+ priv->can.clock.freq = prop / 2;
+ else
+ priv->can.clock.freq = SP_CAN_CLOCK; /* default */
+
+ err = of_property_read_u32(of, "nxp,tx-output-mode", &prop);
+ if (!err)
+ priv->ocr |= prop & OCR_MODE_MASK;
+ else
+ priv->ocr |= OCR_MODE_NORMAL; /* default */
+
+ err = of_property_read_u32(of, "nxp,tx-output-config", &prop);
+ if (!err)
+ priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+ else
+ priv->ocr |= OCR_TX0_PULLDOWN; /* default */
+
+ err = of_property_read_u32(of, "nxp,clock-out-frequency", &prop);
+ if (!err && prop) {
+ u32 divider = priv->can.clock.freq * 2 / prop;
+
+ if (divider > 1)
+ priv->cdr |= divider / 2 - 1;
+ else
+ priv->cdr |= CDR_CLKOUT_MASK;
+ } else {
+ priv->cdr |= CDR_CLK_OFF; /* default */
+ }
+
+ if (!of_property_read_bool(of, "nxp,no-comparator-bypass"))
+ priv->cdr |= CDR_CBP; /* default */
+}
+
+static int sp_probe(struct platform_device *pdev)
+{
+ int err, irq = 0;
+ void __iomem *addr;
+ struct net_device *dev;
+ struct sja1000_priv *priv;
+ struct resource *res_mem, *res_irq = NULL;
+ struct sja1000_platform_data *pdata;
+ struct device_node *of = pdev->dev.of_node;
+
+ pdata = dev_get_platdata(&pdev->dev);
+ if (!pdata && !of) {
+ dev_err(&pdev->dev, "No platform data provided!\n");
+ return -ENODEV;
+ }
+
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res_mem)
+ return -ENODEV;
+
+ if (!devm_request_mem_region(&pdev->dev, res_mem->start,
+ resource_size(res_mem), DRV_NAME))
+ return -EBUSY;
+
+ addr = devm_ioremap_nocache(&pdev->dev, res_mem->start,
+ resource_size(res_mem));
+ if (!addr)
+ return -ENOMEM;
+
+ if (of)
+ irq = irq_of_parse_and_map(of, 0);
+ else
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!irq && !res_irq)
+ return -ENODEV;
+
+ dev = alloc_sja1000dev(0);
+ if (!dev)
+ return -ENOMEM;
+ priv = netdev_priv(dev);
+
+ if (res_irq) {
+ irq = res_irq->start;
+ priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
+ if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE)
+ priv->irq_flags |= IRQF_SHARED;
+ } else {
+ priv->irq_flags = IRQF_SHARED;
+ }
+
+ dev->irq = irq;
+ priv->reg_base = addr;
+
+ if (of)
+ sp_populate_of(priv, of);
+ else
+ sp_populate(priv, pdata, res_mem->flags);
+
+ platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
err = register_sja1000dev(dev);
@@ -151,40 +229,32 @@ static int sp_probe(struct platform_device *pdev)
exit_free:
free_sja1000dev(dev);
- exit_iounmap:
- iounmap(addr);
- exit_release:
- release_mem_region(res_mem->start, resource_size(res_mem));
- exit:
return err;
}
static int sp_remove(struct platform_device *pdev)
{
- struct net_device *dev = dev_get_drvdata(&pdev->dev);
- struct sja1000_priv *priv = netdev_priv(dev);
- struct resource *res;
+ struct net_device *dev = platform_get_drvdata(pdev);
unregister_sja1000dev(dev);
- dev_set_drvdata(&pdev->dev, NULL);
-
- if (priv->reg_base)
- iounmap(priv->reg_base);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
free_sja1000dev(dev);
return 0;
}
+static struct of_device_id sp_of_table[] = {
+ {.compatible = "nxp,sja1000"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, sp_of_table);
+
static struct platform_driver sp_driver = {
.probe = sp_probe,
.remove = sp_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = sp_of_table,
},
};