Commit 66425a7f authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-3.19-20141117' of git://gitorious.org/linux-can/linux-can-next

Marc Kleine-Budde says:

====================
this is a pull request of 9 patches for net-next/master.

All 9 patches are by Roger Quadros and update the c_can platform
driver. First by improving the initialization sequence of the message
RAM, making use of syscon/regmap. In the later patches support for
various TI SoCs is added.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 970efef4 f2bf2589
...@@ -4,6 +4,8 @@ Bosch C_CAN/D_CAN controller Device Tree Bindings ...@@ -4,6 +4,8 @@ Bosch C_CAN/D_CAN controller Device Tree Bindings
Required properties: Required properties:
- compatible : Should be "bosch,c_can" for C_CAN controllers and - compatible : Should be "bosch,c_can" for C_CAN controllers and
"bosch,d_can" for D_CAN controllers. "bosch,d_can" for D_CAN controllers.
Can be "ti,dra7-d_can", "ti,am3352-d_can" or
"ti,am4372-d_can".
- reg : physical base address and size of the C_CAN/D_CAN - reg : physical base address and size of the C_CAN/D_CAN
registers map registers map
- interrupts : property with a value describing the interrupt - interrupts : property with a value describing the interrupt
...@@ -12,6 +14,9 @@ Required properties: ...@@ -12,6 +14,9 @@ Required properties:
Optional properties: Optional properties:
- ti,hwmods : Must be "d_can<n>" or "c_can<n>", n being the - ti,hwmods : Must be "d_can<n>" or "c_can<n>", n being the
instance number instance number
- syscon-raminit : Handle to system control region that contains the
RAMINIT register, register offset to the RAMINIT
register and the CAN instance number (0 offset).
Note: "ti,hwmods" field is used to fetch the base address and irq Note: "ti,hwmods" field is used to fetch the base address and irq
resources from TI, omap hwmod data base during device registration. resources from TI, omap hwmod data base during device registration.
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
#include <linux/can.h> #include <linux/can.h>
#include <linux/can/dev.h> #include <linux/can/dev.h>
...@@ -603,6 +604,8 @@ static int c_can_start(struct net_device *dev) ...@@ -603,6 +604,8 @@ static int c_can_start(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* activate pins */
pinctrl_pm_select_default_state(dev->dev.parent);
return 0; return 0;
} }
...@@ -611,6 +614,9 @@ static void c_can_stop(struct net_device *dev) ...@@ -611,6 +614,9 @@ static void c_can_stop(struct net_device *dev)
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
c_can_irq_control(priv, false); c_can_irq_control(priv, false);
/* deactivate pins */
pinctrl_pm_select_sleep_state(dev->dev.parent);
priv->can.state = CAN_STATE_STOPPED; priv->can.state = CAN_STATE_STOPPED;
} }
...@@ -1244,6 +1250,13 @@ int register_c_can_dev(struct net_device *dev) ...@@ -1244,6 +1250,13 @@ int register_c_can_dev(struct net_device *dev)
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
int err; int err;
/* Deactivate pins to prevent DRA7 DCAN IP from being
* stuck in transition when module is disabled.
* Pins are activated in c_can_start() and deactivated
* in c_can_stop()
*/
pinctrl_pm_select_sleep_state(dev->dev.parent);
c_can_pm_runtime_enable(priv); c_can_pm_runtime_enable(priv);
dev->flags |= IFF_ECHO; /* we support local echo */ dev->flags |= IFF_ECHO; /* we support local echo */
......
...@@ -169,6 +169,28 @@ enum c_can_dev_id { ...@@ -169,6 +169,28 @@ enum c_can_dev_id {
BOSCH_D_CAN, BOSCH_D_CAN,
}; };
struct raminit_bits {
u8 start;
u8 done;
};
struct c_can_driver_data {
enum c_can_dev_id id;
/* RAMINIT register description. Optional. */
const struct raminit_bits *raminit_bits; /* Array of START/DONE bit positions */
u8 raminit_num; /* Number of CAN instances on the SoC */
bool raminit_pulse; /* If set, sets and clears START bit (pulse) */
};
/* Out of band RAMINIT register access via syscon regmap */
struct c_can_raminit {
struct regmap *syscon; /* for raminit ctrl. reg. access */
unsigned int reg; /* register index within syscon */
struct raminit_bits bits;
bool needs_pulse;
};
/* c_can private data structure */ /* c_can private data structure */
struct c_can_priv { struct c_can_priv {
struct can_priv can; /* must be the first member */ struct can_priv can; /* must be the first member */
...@@ -186,8 +208,7 @@ struct c_can_priv { ...@@ -186,8 +208,7 @@ struct c_can_priv {
const u16 *regs; const u16 *regs;
void *priv; /* for board-specific data */ void *priv; /* for board-specific data */
enum c_can_dev_id type; enum c_can_dev_id type;
u32 __iomem *raminit_ctrlreg; struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */
int instance;
void (*raminit) (const struct c_can_priv *priv, bool enable); void (*raminit) (const struct c_can_priv *priv, bool enable);
u32 comm_rcv_high; u32 comm_rcv_high;
u32 rxmasked; u32 rxmasked;
......
...@@ -32,14 +32,13 @@ ...@@ -32,14 +32,13 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/can/dev.h> #include <linux/can/dev.h>
#include "c_can.h" #include "c_can.h"
#define CAN_RAMINIT_START_MASK(i) (0x001 << (i))
#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i))
#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i))
#define DCAN_RAM_INIT_BIT (1 << 3) #define DCAN_RAM_INIT_BIT (1 << 3)
static DEFINE_SPINLOCK(raminit_lock); static DEFINE_SPINLOCK(raminit_lock);
/* /*
...@@ -72,39 +71,63 @@ static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv, ...@@ -72,39 +71,63 @@ static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]); writew(val, priv->base + 2 * priv->regs[index]);
} }
static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask, static void c_can_hw_raminit_wait_syscon(const struct c_can_priv *priv,
u32 val) u32 mask, u32 val)
{ {
const struct c_can_raminit *raminit = &priv->raminit_sys;
int timeout = 0;
u32 ctrl = 0;
/* We look only at the bits of our instance. */ /* We look only at the bits of our instance. */
val &= mask; val &= mask;
while ((readl(priv->raminit_ctrlreg) & mask) != val) do {
udelay(1); udelay(1);
timeout++;
regmap_read(raminit->syscon, raminit->reg, &ctrl);
if (timeout == 1000) {
dev_err(&priv->dev->dev, "%s: time out\n", __func__);
break;
}
} while ((ctrl & mask) != val);
} }
static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable) static void c_can_hw_raminit_syscon(const struct c_can_priv *priv, bool enable)
{ {
u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance); const struct c_can_raminit *raminit = &priv->raminit_sys;
u32 ctrl; u32 ctrl = 0;
u32 mask;
spin_lock(&raminit_lock); spin_lock(&raminit_lock);
ctrl = readl(priv->raminit_ctrlreg); mask = 1 << raminit->bits.start | 1 << raminit->bits.done;
regmap_read(raminit->syscon, raminit->reg, &ctrl);
/* We clear the done and start bit first. The start bit is /* We clear the done and start bit first. The start bit is
* looking at the 0 -> transition, but is not self clearing; * looking at the 0 -> transition, but is not self clearing;
* And we clear the init done bit as well. * And we clear the init done bit as well.
* NOTE: DONE must be written with 1 to clear it.
*/ */
ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance); ctrl &= ~(1 << raminit->bits.start);
ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); ctrl |= 1 << raminit->bits.done;
writel(ctrl, priv->raminit_ctrlreg); regmap_write(raminit->syscon, raminit->reg, ctrl);
ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance);
c_can_hw_raminit_wait_ti(priv, mask, ctrl); ctrl &= ~(1 << raminit->bits.done);
c_can_hw_raminit_wait_syscon(priv, mask, ctrl);
if (enable) { if (enable) {
/* Set start bit and wait for the done bit. */ /* Set start bit and wait for the done bit. */
ctrl |= CAN_RAMINIT_START_MASK(priv->instance); ctrl |= 1 << raminit->bits.start;
writel(ctrl, priv->raminit_ctrlreg); regmap_write(raminit->syscon, raminit->reg, ctrl);
ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
c_can_hw_raminit_wait_ti(priv, mask, ctrl); /* clear START bit if start pulse is needed */
if (raminit->needs_pulse) {
ctrl &= ~(1 << raminit->bits.start);
regmap_write(raminit->syscon, raminit->reg, ctrl);
}
ctrl |= 1 << raminit->bits.done;
c_can_hw_raminit_wait_syscon(priv, mask, ctrl);
} }
spin_unlock(&raminit_lock); spin_unlock(&raminit_lock);
} }
...@@ -159,26 +182,60 @@ static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) ...@@ -159,26 +182,60 @@ static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
} }
} }
static const struct c_can_driver_data c_can_drvdata = {
.id = BOSCH_C_CAN,
};
static const struct c_can_driver_data d_can_drvdata = {
.id = BOSCH_D_CAN,
};
static const struct raminit_bits dra7_raminit_bits[] = {
[0] = { .start = 3, .done = 1, },
[1] = { .start = 5, .done = 2, },
};
static const struct c_can_driver_data dra7_dcan_drvdata = {
.id = BOSCH_D_CAN,
.raminit_num = ARRAY_SIZE(dra7_raminit_bits),
.raminit_bits = dra7_raminit_bits,
.raminit_pulse = true,
};
static const struct raminit_bits am3352_raminit_bits[] = {
[0] = { .start = 0, .done = 8, },
[1] = { .start = 1, .done = 9, },
};
static const struct c_can_driver_data am3352_dcan_drvdata = {
.id = BOSCH_D_CAN,
.raminit_num = ARRAY_SIZE(am3352_raminit_bits),
.raminit_bits = am3352_raminit_bits,
};
static struct platform_device_id c_can_id_table[] = { static struct platform_device_id c_can_id_table[] = {
[BOSCH_C_CAN_PLATFORM] = { {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.driver_data = BOSCH_C_CAN, .driver_data = (kernel_ulong_t)&c_can_drvdata,
}, },
[BOSCH_C_CAN] = { {
.name = "c_can", .name = "c_can",
.driver_data = BOSCH_C_CAN, .driver_data = (kernel_ulong_t)&c_can_drvdata,
}, },
[BOSCH_D_CAN] = { {
.name = "d_can", .name = "d_can",
.driver_data = BOSCH_D_CAN, .driver_data = (kernel_ulong_t)&d_can_drvdata,
}, { },
} { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(platform, c_can_id_table); MODULE_DEVICE_TABLE(platform, c_can_id_table);
static const struct of_device_id c_can_of_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,c_can", .data = &c_can_drvdata },
{ .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] }, { .compatible = "bosch,d_can", .data = &d_can_drvdata },
{ .compatible = "ti,dra7-d_can", .data = &dra7_dcan_drvdata },
{ .compatible = "ti,am3352-d_can", .data = &am3352_dcan_drvdata },
{ .compatible = "ti,am4372-d_can", .data = &am3352_dcan_drvdata },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, c_can_of_table); MODULE_DEVICE_TABLE(of, c_can_of_table);
...@@ -190,21 +247,20 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -190,21 +247,20 @@ static int c_can_plat_probe(struct platform_device *pdev)
struct net_device *dev; struct net_device *dev;
struct c_can_priv *priv; struct c_can_priv *priv;
const struct of_device_id *match; const struct of_device_id *match;
const struct platform_device_id *id; struct resource *mem;
struct resource *mem, *res;
int irq; int irq;
struct clk *clk; struct clk *clk;
const struct c_can_driver_data *drvdata;
if (pdev->dev.of_node) { struct device_node *np = pdev->dev.of_node;
match = of_match_device(c_can_of_table, &pdev->dev);
if (!match) { match = of_match_device(c_can_of_table, &pdev->dev);
dev_err(&pdev->dev, "Failed to find matching dt id\n"); if (match) {
ret = -EINVAL; drvdata = match->data;
goto exit; } else if (pdev->id_entry->driver_data) {
} drvdata = (struct c_can_driver_data *)
id = match->data; platform_get_device_id(pdev)->driver_data;
} else { } else {
id = platform_get_device_id(pdev); return -ENODEV;
} }
/* get the appropriate clk */ /* get the appropriate clk */
...@@ -236,7 +292,7 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -236,7 +292,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
} }
priv = netdev_priv(dev); priv = netdev_priv(dev);
switch (id->driver_data) { switch (drvdata->id) {
case BOSCH_C_CAN: case BOSCH_C_CAN:
priv->regs = reg_map_c_can; priv->regs = reg_map_c_can;
switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) { switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
...@@ -263,27 +319,50 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -263,27 +319,50 @@ static int c_can_plat_probe(struct platform_device *pdev)
priv->read_reg32 = d_can_plat_read_reg32; priv->read_reg32 = d_can_plat_read_reg32;
priv->write_reg32 = d_can_plat_write_reg32; priv->write_reg32 = d_can_plat_write_reg32;
if (pdev->dev.of_node) /* Check if we need custom RAMINIT via syscon. Mostly for TI
priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can"); * platforms. Only supported with DT boot.
else
priv->instance = pdev->id;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
/* Not all D_CAN modules have a separate register for the D_CAN
* RAM initialization. Use default RAM init bit in D_CAN module
* if not specified in DT.
*/ */
if (!res) { if (np && of_property_read_bool(np, "syscon-raminit")) {
u32 id;
struct c_can_raminit *raminit = &priv->raminit_sys;
ret = -EINVAL;
raminit->syscon = syscon_regmap_lookup_by_phandle(np,
"syscon-raminit");
if (IS_ERR(raminit->syscon)) {
/* can fail with -EPROBE_DEFER */
ret = PTR_ERR(raminit->syscon);
free_c_can_dev(dev);
return ret;
}
if (of_property_read_u32_index(np, "syscon-raminit", 1,
&raminit->reg)) {
dev_err(&pdev->dev,
"couldn't get the RAMINIT reg. offset!\n");
goto exit_free_device;
}
if (of_property_read_u32_index(np, "syscon-raminit", 2,
&id)) {
dev_err(&pdev->dev,
"couldn't get the CAN instance ID\n");
goto exit_free_device;
}
if (id >= drvdata->raminit_num) {
dev_err(&pdev->dev,
"Invalid CAN instance ID\n");
goto exit_free_device;
}
raminit->bits = drvdata->raminit_bits[id];
raminit->needs_pulse = drvdata->raminit_pulse;
priv->raminit = c_can_hw_raminit_syscon;
} else {
priv->raminit = c_can_hw_raminit; priv->raminit = c_can_hw_raminit;
break;
} }
priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start,
resource_size(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_ti;
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
...@@ -295,7 +374,7 @@ static int c_can_plat_probe(struct platform_device *pdev) ...@@ -295,7 +374,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
priv->device = &pdev->dev; priv->device = &pdev->dev;
priv->can.clock.freq = clk_get_rate(clk); priv->can.clock.freq = clk_get_rate(clk);
priv->priv = clk; priv->priv = clk;
priv->type = id->driver_data; priv->type = drvdata->id;
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment