summaryrefslogtreecommitdiff
path: root/drivers/net/can/c_can
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can/c_can')
-rw-r--r--drivers/net/can/c_can/c_can.c12
-rw-r--r--drivers/net/can/c_can/c_can.h3
-rw-r--r--drivers/net/can/c_can/c_can_pci.c8
-rw-r--r--drivers/net/can/c_can/c_can_platform.c36
4 files changed, 51 insertions, 8 deletions
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index e5180dfddba5..5233b8f58d77 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -233,6 +233,12 @@ static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv)
pm_runtime_put_sync(priv->device);
}
+static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
+{
+ if (priv->raminit)
+ priv->raminit(priv, enable);
+}
+
static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
{
return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
@@ -1090,6 +1096,7 @@ static int c_can_open(struct net_device *dev)
struct c_can_priv *priv = netdev_priv(dev);
c_can_pm_runtime_get_sync(priv);
+ c_can_reset_ram(priv, true);
/* open the can device */
err = open_candev(dev);
@@ -1118,6 +1125,7 @@ static int c_can_open(struct net_device *dev)
exit_irq_fail:
close_candev(dev);
exit_open_fail:
+ c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
return err;
}
@@ -1131,6 +1139,8 @@ static int c_can_close(struct net_device *dev)
c_can_stop(dev);
free_irq(dev->irq, dev);
close_candev(dev);
+
+ c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
return 0;
@@ -1188,6 +1198,7 @@ int c_can_power_down(struct net_device *dev)
c_can_stop(dev);
+ c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
return 0;
@@ -1206,6 +1217,7 @@ int c_can_power_up(struct net_device *dev)
WARN_ON(priv->type != BOSCH_D_CAN);
c_can_pm_runtime_get_sync(priv);
+ c_can_reset_ram(priv, true);
/* Clear PDR and INIT bits */
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index e5ed41dafa1b..d2e1c21b143f 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -169,6 +169,9 @@ struct c_can_priv {
void *priv; /* for board-specific data */
u16 irqstatus;
enum c_can_dev_id type;
+ u32 __iomem *raminit_ctrlreg;
+ unsigned int instance;
+ void (*raminit) (const struct c_can_priv *priv, bool enable);
};
struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 3d7830bcd2bf..b374be7891a2 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -63,8 +63,8 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]);
}
-static int __devinit c_can_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int c_can_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct c_can_pci_data *c_can_pci_data = (void *)ent->driver_data;
struct c_can_priv *priv;
@@ -174,7 +174,7 @@ out:
return ret;
}
-static void __devexit c_can_pci_remove(struct pci_dev *pdev)
+static void c_can_pci_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev);
@@ -210,7 +210,7 @@ static struct pci_driver c_can_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = c_can_pci_tbl,
.probe = c_can_pci_probe,
- .remove = __devexit_p(c_can_pci_remove),
+ .remove = c_can_pci_remove,
};
module_pci_driver(c_can_pci_driver);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index ee1416132aba..d63b91904f82 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -38,6 +38,8 @@
#include "c_can.h"
+#define CAN_RAMINIT_START_MASK(i) (1 << (i))
+
/*
* 16-bit c_can registers can be arranged differently in the memory
* architecture of different implementations. For example: 16-bit
@@ -68,6 +70,18 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]);
}
+static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
+{
+ u32 val;
+
+ val = readl(priv->raminit_ctrlreg);
+ if (enable)
+ val |= CAN_RAMINIT_START_MASK(priv->instance);
+ else
+ val &= ~CAN_RAMINIT_START_MASK(priv->instance);
+ writel(val, priv->raminit_ctrlreg);
+}
+
static struct platform_device_id c_can_id_table[] = {
[BOSCH_C_CAN_PLATFORM] = {
.name = KBUILD_MODNAME,
@@ -83,14 +97,16 @@ static struct platform_device_id c_can_id_table[] = {
}, {
}
};
+MODULE_DEVICE_TABLE(platform, c_can_id_table);
static const struct of_device_id c_can_of_table[] = {
{ .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] },
{ .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, c_can_of_table);
-static int __devinit c_can_plat_probe(struct platform_device *pdev)
+static int c_can_plat_probe(struct platform_device *pdev)
{
int ret;
void __iomem *addr;
@@ -99,7 +115,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
const struct of_device_id *match;
const struct platform_device_id *id;
struct pinctrl *pinctrl;
- struct resource *mem;
+ struct resource *mem, *res;
int irq;
struct clk *clk;
@@ -178,6 +194,18 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
+
+ if (pdev->dev.of_node)
+ priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can");
+ else
+ priv->instance = pdev->id;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->raminit_ctrlreg = devm_request_and_ioremap(&pdev->dev, res);
+ if (!priv->raminit_ctrlreg || priv->instance < 0)
+ dev_info(&pdev->dev, "control memory is not used for raminit\n");
+ else
+ priv->raminit = c_can_hw_raminit;
break;
default:
ret = -EINVAL;
@@ -220,7 +248,7 @@ exit:
return ret;
}
-static int __devexit c_can_plat_remove(struct platform_device *pdev)
+static int c_can_plat_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev);
@@ -306,7 +334,7 @@ static struct platform_driver c_can_plat_driver = {
.of_match_table = of_match_ptr(c_can_of_table),
},
.probe = c_can_plat_probe,
- .remove = __devexit_p(c_can_plat_remove),
+ .remove = c_can_plat_remove,
.suspend = c_can_suspend,
.resume = c_can_resume,
.id_table = c_can_id_table,