Skip to content

Commit

Permalink
beaglebone: add support for Towertech TT3201 CAN cape
Browse files Browse the repository at this point in the history
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
  • Loading branch information
Alessandro Zummo authored and koenkooi committed Mar 1, 2012
1 parent 72ef842 commit 821ef0a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 19 deletions.
54 changes: 53 additions & 1 deletion arch/arm/mach-omap2/board-am335xevm.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <linux/pwm_backlight.h>
#include <linux/pwm/pwm.h>
#include <linux/w1-gpio.h>
#include <linux/can/platform/mcp251x.h>

/* LCD controller is similar to DA850 */
#include <video/da8xx-fb.h>
Expand Down Expand Up @@ -829,6 +830,15 @@ static struct pinmux_config d_can_ia_pin_mux[] = {
{NULL, 0},
};

static struct pinmux_config tt3201_pin_mux[] = {
{"uart1_rxd.d_can1_tx", OMAP_MUX_MODE2 | AM33XX_PIN_OUTPUT },
{"uart1_txd.d_can1_rx", OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP },
{"mcasp0_fsr.gpio3_19", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT_PULLUP },
{"mcasp0_ahclkx.gpio3_21", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT_PULLUP },
{"ecap0_in_pwm0_out.spi1_cs1", OMAP_MUX_MODE2 | AM33XX_PIN_OUTPUT_PULLUP },
{NULL, 0},
};

/* Module pin mux for uart2 */
static struct pinmux_config uart2_pin_mux[] = {
{"spi0_sclk.uart2_rxd", OMAP_MUX_MODE1 | AM33XX_SLEWCTRL_SLOW |
Expand Down Expand Up @@ -1788,6 +1798,44 @@ static void i2c1_init(int evm_id, int profile)
return;
}

static struct mcp251x_platform_data mcp251x_info = {
.oscillator_frequency = 16000000,
};

static struct spi_board_info tt3201_spi_info[] = {
{
.modalias = "mcp2515",
.max_speed_hz = 10000000,
.bus_num = 2,
.chip_select = 0,
.mode = SPI_MODE_0,
.platform_data = &mcp251x_info,
},
{
.modalias = "mcp2515",
.max_speed_hz = 10000000,
.bus_num = 2,
.chip_select = 1,
.mode = SPI_MODE_0,
.platform_data = &mcp251x_info,
},
};

static void tt3201_init(int evm_id, int profile)
{
pr_info("TowerTech TT3201 CAN Cape\n");

setup_pin_mux(spi1_pin_mux);
setup_pin_mux(tt3201_pin_mux);

tt3201_spi_info[0].irq = gpio_to_irq(GPIO_TO_PIN(3, 19));
tt3201_spi_info[1].irq = gpio_to_irq(GPIO_TO_PIN(3, 21));

spi_register_board_info(tt3201_spi_info,
ARRAY_SIZE(tt3201_spi_info));

am33xx_d_can_init(1);
}
static void beaglebone_cape_setup(struct memory_accessor *mem_acc, void *context)
{
capecount++;
Expand Down Expand Up @@ -1835,7 +1883,11 @@ static void beaglebone_cape_setup(struct memory_accessor *mem_acc, void *context
beaglebone_tsadcpins_free = 0;
}


if (!strncmp("TT3201-001", cape_config.partnumber, 10)) {
pr_info("BeagleBone cape: initializing CAN cape\n");
tt3201_init(0,0);
}

if ((capecount > 3) && (beaglebone_tsadcpins_free == 1)) {
pr_info("BeagleBone cape: exporting ADC pins to sysfs\n");
bone_tsc_init(0,0);
Expand Down
8 changes: 4 additions & 4 deletions arch/arm/mach-omap2/mux33xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,16 +312,16 @@ static struct omap_mux __initdata am33xx_muxmodes[] = {
"uart0_txd", "spi1_cs1", "d_can0_rx", "i2c2_scl",
NULL, NULL, NULL, "gpio1_11"),
_AM33XX_MUXENTRY(UART1_CTSN, 0,
"uart1_ctsn", NULL, NULL, "i2c2_sda",
"uart1_ctsn", NULL, "d_can0_tx", "i2c2_sda",
"spi1_cs0", NULL, NULL, "gpio0_12"),
_AM33XX_MUXENTRY(UART1_RTSN, 0,
"uart1_rtsn", NULL, NULL, "i2c2_scl",
"uart1_rtsn", NULL, "d_can0_rx", "i2c2_scl",
"spi1_cs1", NULL, NULL, "gpio0_13"),
_AM33XX_MUXENTRY(UART1_RXD, 0,
"uart1_rxd", "mmc1_sdwp", NULL, "i2c1_sda",
"uart1_rxd", "mmc1_sdwp", "d_can1_tx", "i2c1_sda",
NULL, "pr1_uart0_rxd_mux1", NULL, "gpio0_14"),
_AM33XX_MUXENTRY(UART1_TXD, 0,
"uart1_txd", "mmc2_sdwp", NULL, "i2c1_scl",
"uart1_txd", "mmc2_sdwp", "d_can1_rx", "i2c1_scl",
NULL, "pr1_uart0_txd_mux1", NULL, "gpio0_15"),
_AM33XX_MUXENTRY(I2C0_SDA, 0,
"i2c0_sda", NULL, NULL, NULL,
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/can/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,15 +392,15 @@ void can_restart(unsigned long data)
stats->rx_bytes += cf->can_dlc;

restart:
dev_dbg(dev->dev.parent, "restarted\n");
netdev_dbg(dev, "restarted\n");
priv->can_stats.restarts++;

/* Now restart the device */
err = priv->do_set_mode(dev, CAN_MODE_START);

netif_carrier_on(dev);
if (err)
dev_err(dev->dev.parent, "Error %d during restart", err);
netdev_err(dev, "error %d during restart", err);
}

int can_restart_now(struct net_device *dev)
Expand Down Expand Up @@ -433,7 +433,7 @@ void can_bus_off(struct net_device *dev)
{
struct can_priv *priv = netdev_priv(dev);

dev_dbg(dev->dev.parent, "bus-off\n");
netdev_dbg(dev, "bus-off\n");

netif_carrier_off(dev);
priv->can_stats.bus_off++;
Expand Down Expand Up @@ -545,7 +545,7 @@ int open_candev(struct net_device *dev)
struct can_priv *priv = netdev_priv(dev);

if (!priv->bittiming.tq && !priv->bittiming.bitrate) {
dev_err(dev->dev.parent, "bit-timing not yet defined\n");
netdev_err(dev, "bit-timing not yet defined\n");
return -EINVAL;
}

Expand Down
47 changes: 37 additions & 10 deletions drivers/net/can/mcp251x.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@
# define CANCTRL_REQOP_LOOPBACK 0x40
# define CANCTRL_REQOP_SLEEP 0x20
# define CANCTRL_REQOP_NORMAL 0x00
# define CANCTRL_OSM 0x08
# define CANCTRL_ABAT 0x10
# define CANCTRL_OSM 0x08
# define CANCTRL_CLKEN 0x04
#define TEC 0x1c
#define REC 0x1d
#define CNF1 0x2a
Expand Down Expand Up @@ -287,7 +288,7 @@ static void mcp251x_clean(struct net_device *net)
/*
* Note about handling of error return of mcp251x_spi_trans: accessing
* registers via SPI is not really different conceptually than using
* normal I/O assembler instructions, although it's much more
* normal I/O assembly instructions, although it's much more
* complicated from a practical POV. So it's not advisable to always
* check the return value of this function. Imagine that every
* read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
Expand Down Expand Up @@ -490,7 +491,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)

static void mcp251x_hw_sleep(struct spi_device *spi)
{
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
// mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
}

static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
Expand Down Expand Up @@ -547,13 +548,16 @@ static int mcp251x_set_normal_mode(struct spi_device *spi)

if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
/* Put device into loopback mode */
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK);
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK | CANCTRL_CLKEN);
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
/* Put device into listen-only mode */
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY);
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY | CANCTRL_CLKEN);
} else {
/* Put device into normal mode */
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL | CANCTRL_CLKEN);

netdev_info(priv->net, "CANCTRL: 0x%02x\n",
mcp251x_read_reg(spi, CANCTRL));

/* Wait for the device to enter normal mode */
timeout = jiffies + HZ;
Expand Down Expand Up @@ -585,11 +589,15 @@ static int mcp251x_do_set_bittiming(struct net_device *net)
(bt->prop_seg - 1));
mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK,
(bt->phase_seg2 - 1));
dev_info(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n",

netdev_info(net, "CNF: 0x%02x 0x%02x 0x%02x\n",
mcp251x_read_reg(spi, CNF1),
mcp251x_read_reg(spi, CNF2),
mcp251x_read_reg(spi, CNF3));

netdev_info(net, "CANCTRL: 0x%02x\n",
mcp251x_read_reg(spi, CANCTRL));

return 0;
}

Expand All @@ -600,6 +608,7 @@ static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,

mcp251x_write_reg(spi, RXBCTRL(0),
RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1);

mcp251x_write_reg(spi, RXBCTRL(1),
RXBCTRL_RXM0 | RXBCTRL_RXM1);
return 0;
Expand Down Expand Up @@ -728,7 +737,9 @@ static void mcp251x_tx_work_handler(struct work_struct *ws)
mutex_lock(&priv->mcp_lock);
if (priv->tx_skb) {
if (priv->can.state == CAN_STATE_BUS_OFF) {

mcp251x_clean(net);

} else {
frame = (struct can_frame *)priv->tx_skb->data;

Expand Down Expand Up @@ -827,21 +838,37 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)

/* Update can state */
if (eflag & EFLG_TXBO) {

netdev_err(net, "err: bus off\n");

new_state = CAN_STATE_BUS_OFF;
can_id |= CAN_ERR_BUSOFF;
} else if (eflag & EFLG_TXEP) {

netdev_err(net, "err: txep\n");

new_state = CAN_STATE_ERROR_PASSIVE;
can_id |= CAN_ERR_CRTL;
data1 |= CAN_ERR_CRTL_TX_PASSIVE;

} else if (eflag & EFLG_RXEP) {

netdev_err(net, "err: rxep\n");

new_state = CAN_STATE_ERROR_PASSIVE;
can_id |= CAN_ERR_CRTL;
data1 |= CAN_ERR_CRTL_RX_PASSIVE;
} else if (eflag & EFLG_TXWAR) {

netdev_err(net, "err: txwar\n");

new_state = CAN_STATE_ERROR_WARNING;
can_id |= CAN_ERR_CRTL;
data1 |= CAN_ERR_CRTL_TX_WARNING;
} else if (eflag & EFLG_RXWAR) {

netdev_err(net, "err: rxwar\n");

new_state = CAN_STATE_ERROR_WARNING;
can_id |= CAN_ERR_CRTL;
data1 |= CAN_ERR_CRTL_RX_WARNING;
Expand Down Expand Up @@ -918,7 +945,7 @@ static int mcp251x_open(struct net_device *net)

ret = open_candev(net);
if (ret) {
dev_err(&spi->dev, "unable to set initial baudrate!\n");
netdev_err(net, "failed to open can device\n");
return ret;
}

Expand All @@ -934,7 +961,7 @@ static int mcp251x_open(struct net_device *net)
pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
DEVICE_NAME, priv);
if (ret) {
dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
netdev_err(net, "failed to acquire irq %d\n", spi->irq);
if (pdata->transceiver_enable)
pdata->transceiver_enable(0);
close_candev(net);
Expand Down Expand Up @@ -1071,7 +1098,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)

ret = register_candev(net);
if (!ret) {
dev_info(&spi->dev, "probed\n");
netdev_info(priv->net, "probed\n");
return ret;
}
error_probe:
Expand Down

0 comments on commit 821ef0a

Please sign in to comment.