From c50c0878952f22583bc4d8699a5b8e722f8baa1a Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Thu, 29 Aug 2013 14:34:38 -0700 Subject: [PATCH 2/3] mvf: fixed flexcan driver and added support for flexcan0 and flexcan1 Clock changes originally from a patch by Ashutosh Singh Signed-off-by: Johnathan Feuerstein Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/clock.c | 171 +++++++++++++++++++++++++++ arch/arm/mach-mvf/crm_regs.h | 16 ++- arch/arm/plat-mxc/devices/platform-flexcan.c | 9 ++ arch/arm/plat-mxc/include/mach/iomux-mvf.h | 13 +- arch/arm/plat-mxc/include/mach/mvf.h | 5 +- drivers/net/can/flexcan.c | 54 +++++---- 6 files changed, 238 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 4964509..7e1ad7a 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1700,6 +1700,173 @@ static struct clk i2c_clk[] = { }, }; +static int _clk_can0_root_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCDR2) | MXC_CCM_CSCDR2_CAN0_EN; + __raw_writel(reg, MXC_CCM_CSCDR2); + + return 0; +} + +static void _clk_can0_root_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCDR2) & ~MXC_CCM_CSCDR2_CAN0_EN; + __raw_writel(reg, MXC_CCM_CSCDR2); +} + +static int _clk_can0_root_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + int mux; + + mux = _get_mux(parent, &osc_clk, &ipg_clk, NULL, NULL, NULL); + reg = __raw_readl(CAN0_CTRL1) & ~CAN_CTRL_CLKSRC; + reg |= mux << CAN_CTRL_CLKSRC_OFFSET; + __raw_writel(reg, CAN0_CTRL1); + + return 0; +} + +static struct clk can0_clk_root = { + __INIT_CLK_DEBUG(can0_clk_root) + .id = 0, + .parent = &ipg_clk, + .enable = _clk_can0_root_enable, + .disable = _clk_can0_root_disable, + .set_parent = _clk_can0_root_set_parent, +}; + +static struct clk can0_clk[] = { + { + __INIT_CLK_DEBUG(can0_clk_0) + .id = 0, + .parent = &can0_clk_root, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &can0_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + __INIT_CLK_DEBUG(can0_clk_1) + .id = 1, + .parent = &can0_clk_root, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &can0_clk[2], + }, + { + __INIT_CLK_DEBUG(can0_clk_2) + .id = 2, + .parent = &can0_clk_root, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &can0_clk[3], + }, + { + __INIT_CLK_DEBUG(can0_clk_3) + .id = 4, + .parent = &can0_clk_root, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + +static int _clk_can1_root_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCDR2) | MXC_CCM_CSCDR2_CAN1_EN; + __raw_writel(reg, MXC_CCM_CSCDR2); + + return 0; +} + +static void _clk_can1_root_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCDR2) & ~MXC_CCM_CSCDR2_CAN1_EN; + __raw_writel(reg, MXC_CCM_CSCDR2); +} + +static int _clk_can1_root_set_parent(struct clk *clk, struct clk *parent) +{ + + u32 reg; + int mux; + + mux = _get_mux(parent, &osc_clk, &ipg_clk, NULL, NULL, NULL); + reg = __raw_readl(CAN1_CTRL1) & ~CAN_CTRL_CLKSRC; + reg |= mux << CAN_CTRL_CLKSRC_OFFSET; + __raw_writel(reg, CAN1_CTRL1); + + return 0; +} + +static struct clk can1_clk_root = { + __INIT_CLK_DEBUG(can1_root_clk) + .parent = &ipg_clk, + .enable = _clk_can1_root_enable, + .disable = _clk_can1_root_disable, + .set_parent = _clk_can1_root_set_parent, +}; + +static struct clk can1_clk[] = { + { + __INIT_CLK_DEBUG(can1_clk_0) + .id = 0, + .parent = &can1_clk_root, + .enable_reg = MXC_CCM_CCGR9, + .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &can1_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + __INIT_CLK_DEBUG(can1_clk_1) + .id = 1, + .parent = &can1_clk_root, + .enable_reg = MXC_CCM_CCGR9, + .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &can1_clk[2], + }, + { + __INIT_CLK_DEBUG(can1_clk_2) + .id = 2, + .parent = &can1_clk_root, + .enable_reg = MXC_CCM_CCGR9, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &can1_clk[3], + }, + { + __INIT_CLK_DEBUG(can1_clk_3) + .id = 3, + .parent = &can1_clk_root, + .enable_reg = MXC_CCM_CCGR9, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + + static struct clk wdt_clk[] = { { __INIT_CLK_DEBUG(wdt_clk) @@ -1944,6 +2111,10 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "mvf-uart.1", uart_clk[0]), _REGISTER_CLOCK(NULL, "mvf-uart.2", uart_clk[0]), _REGISTER_CLOCK(NULL, "mvf-uart.3", uart_clk[0]), + _REGISTER_CLOCK(NULL, "can0_root_clk", can0_clk_root), + _REGISTER_CLOCK(NULL, "can1_root_clk", can1_clk_root), + _REGISTER_CLOCK("mvf-flexcan.0", NULL, can0_clk[0]), + _REGISTER_CLOCK("mvf-flexcan.1", NULL, can1_clk[0]), _REGISTER_CLOCK("mvf-dspi.0", NULL, dspi_clk[0]), _REGISTER_CLOCK("pit", NULL, pit_clk), _REGISTER_CLOCK("fec.0", NULL, enet_clk[0]), diff --git a/arch/arm/mach-mvf/crm_regs.h b/arch/arm/mach-mvf/crm_regs.h index 4cfc789..954b725 100644 --- a/arch/arm/mach-mvf/crm_regs.h +++ b/arch/arm/mach-mvf/crm_regs.h @@ -38,6 +38,16 @@ #define DDRMC_MDMISC_DDR_TYPE_MASK (0x7 << 8) #define DDRMC_MDMISC_DDR_TYPE_OFFSET (8) +/* CAN */ +#define MXC_CAN0_BASE MVF_IO_ADDRESS(MVF_CAN0_BASE_ADDR) +#define CAN0_CTRL1 (MXC_CAN0_BASE + 0x4) + +#define MXC_CAN1_BASE MVF_IO_ADDRESS(MVF_CAN1_BASE_ADDR) +#define CAN1_CTRL1 (MXC_CAN1_BASE + 0x4) + +#define CAN_CTRL_CLKSRC (1 << 13) +#define CAN_CTRL_CLKSRC_OFFSET (13) + /* PLLs */ #define MXC_PLL_BASE MVF_IO_ADDRESS(ANADIG_BASE_ADDR) #define PLL1_SYS_BASE_ADDR (MXC_PLL_BASE + 0x270) @@ -185,9 +195,9 @@ #define MXC_CCM_BASE MVF_IO_ADDRESS(MVF_CCM_BASE_ADDR) -#define MVF_I2S0_BASE MVF_IO_ADDRESS(MVF_I2S0_BASE_ADDR) -#define MVF_I2S0_TCR2 (MVF_I2S0_BASE + 0xF008) -#define MVF_I2S0_RCR2 (MVF_I2S0_BASE + 0xF088) +#define MVF_SAI0_BASE MVF_IO_ADDRESS(MVF_SAI0_BASE_ADDR) +#define MVF_SAI0_TCR2 (MVF_SAI0_BASE + 0x08) +#define MVF_SAI0_RCR2 (MVF_SAI0_BASE + 0x88) /* Register addresses of CCM*/ #define MXC_CCM_CCR (MXC_CCM_BASE + 0x00) diff --git a/arch/arm/plat-mxc/devices/platform-flexcan.c b/arch/arm/plat-mxc/devices/platform-flexcan.c index d660237..e7ebf4c 100644 --- a/arch/arm/plat-mxc/devices/platform-flexcan.c +++ b/arch/arm/plat-mxc/devices/platform-flexcan.c @@ -47,6 +47,15 @@ const struct imx_flexcan_data imx6q_flexcan_data[] __initconst = { }; #endif /* ifdef CONFIG_SOC_IMX6Q*/ +#ifdef CONFIG_SOC_MVFA5 +const struct imx_flexcan_data mvf_flexcan_data[] __initconst = { +#define mvf_flexcan_data_entry(_id, _hwid) \ + imx_flexcan_data_entry(MVF, "mvf-flexcan", _id, _hwid, SZ_16K) + mvf_flexcan_data_entry(0, 0), + mvf_flexcan_data_entry(1, 1), +}; +#endif /* ifdef CONFIG_SOC_MVFA5*/ + struct platform_device *__init imx_add_flexcan( const struct imx_flexcan_data *data, const struct flexcan_platform_data *pdata) diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h index be40145..0a78736 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h @@ -46,6 +46,9 @@ typedef enum iomux_config { #define MVF600_ENET_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ PAD_CTL_DSE_50ohm) +#define MVF600_CAN_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_20ohm) + #define MVF600_I2C_PAD_CTRL (PAD_CTL_DSE_50ohm | PAD_CTL_PUS_47K_UP | \ PAD_CTL_SPEED_HIGH | PAD_CTL_ODE) @@ -108,15 +111,17 @@ typedef enum iomux_config { MVF600_I2C_PAD_CTRL | PAD_CTL_OBE_IBE_ENABLE) /*CAN0*/ #define MVF600_PAD36_PTB14__CAN0_RX \ - IOMUX_PAD(0x0090, 0x0090, 1, 0x0000, 0, 0) + IOMUX_PAD(0x0090, 0x0090, 1, 0x0000, 0, MVF600_CAN_PAD_CTRL \ + | PAD_CTL_IBE_ENABLE) #define MVF600_PAD37_PTB15__CAN0_TX \ - IOMUX_PAD(0x0094, 0x0094, 1, 0x0000, 0, 0) + IOMUX_PAD(0x0094, 0x0094, 1, 0x0000, 0, MVF600_CAN_PAD_CTRL) /*CAN1*/ #define MVF600_PAD38_PTB16__CAN1_RX \ - IOMUX_PAD(0x0098, 0x0098, 1, 0x0000, 0, 0) + IOMUX_PAD(0x0098, 0x0098, 1, 0x0000, 0, MVF600_CAN_PAD_CTRL \ + | PAD_CTL_IBE_ENABLE) #define MVF600_PAD39_PTB17__CAN1_TX \ - IOMUX_PAD(0x009C, 0x009C, 1, 0x0000, 0, 0) + IOMUX_PAD(0x009C, 0x009C, 1, 0x0000, 0, MVF600_CAN_PAD_CTRL) /*DSPI0*/ #define MVF600_PAD41_PTB19__DSPI0_PCS0 \ diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h index fb0e5eb..63da619 100644 --- a/arch/arm/plat-mxc/include/mach/mvf.h +++ b/arch/arm/plat-mxc/include/mach/mvf.h @@ -124,8 +124,7 @@ #define MVF_DMA0TCD_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00019000) #define MVF_SEMA4_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0001D000) #define MVF_FLEXBUS_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0001E000) -#define MVF_I2S0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00020000) -#define MVF_FLEXCAN0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00021000) +#define MVF_CAN0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00020000) #define MVF_DMAMUX0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00024000) #define MVF_DMAMUX1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00025000) #define MVF_UART0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00027000) @@ -237,7 +236,7 @@ #define MVF_OPENVG_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000CF000) #define MVF_MAC0_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000D0000) #define MVF_MAC1_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000D1000) -#define MVF_FLEXCAN1_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000D4000) +#define MVF_CAN1_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000D4000) #define MVF_DCU1_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000D8000) #define MVF_NFC_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000E0000) #define MVF_I2C2_BASE_ADDR (MVF_AIPS1_BASE_ADDR - 0x80000 + 0x000E6000) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 27dcf75..6ba571d 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -252,11 +252,16 @@ static int flexcan_get_berr_counter(const struct net_device *dev, { const struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->base; + + clk_enable(priv->clk); + u32 reg = readl(®s->ecr); bec->txerr = (reg >> 0) & 0xff; bec->rxerr = (reg >> 8) & 0xff; + clk_disable(priv->clk); + return 0; } @@ -691,27 +696,8 @@ static int flexcan_chip_start(struct net_device *dev) goto out; } - flexcan_set_bittiming(dev); - /* - * MCR - * - * enable freeze - * enable fifo - * halt now - * only supervisor access - * enable warning int - * choose format C - * enable self wakeup - * - */ - reg_mcr = readl(®s->mcr); - reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | - FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | - FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_WAK_MSK | - FLEXCAN_MCR_SLF_WAK; - dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr); - writel(reg_mcr, ®s->mcr); + flexcan_set_bittiming(dev); /* * CTRL @@ -749,6 +735,26 @@ static int flexcan_chip_start(struct net_device *dev) writel(FLEXCAN_MB_CNT_CODE(0x4), ®s->cantxfg[i].can_ctrl); } + /* + * MCR + * + * enable freeze + * enable fifo + * halt now + * only supervisor access + * enable warning int + * choose format C + * enable self wakeup + * + */ + reg_mcr = readl(®s->mcr); + reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | + FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | + FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_WAK_MSK | + FLEXCAN_MCR_SLF_WAK; + dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr); + writel(reg_mcr, ®s->mcr); + /* acceptance mask/acceptance code (accept everything) */ writel(0x0, ®s->rxgmask); writel(0x0, ®s->rx14mask); @@ -892,7 +898,12 @@ static int __devinit register_flexcandev(struct net_device *dev) /* select "bus clock", chip must be disabled */ flexcan_chip_disable(priv); reg = readl(®s->ctrl); + reg |= FLEXCAN_CTRL_CLK_SRC; + + /* FIXME: fix the clock setup so this delay is not required */ + udelay(1); + writel(reg, ®s->ctrl); flexcan_chip_enable(priv); @@ -947,6 +958,9 @@ static struct platform_device_id flexcan_devtype[] = { }, { .name = "imx6q-flexcan", .driver_data = FLEXCAN_VER_10_0_12, + }, { + .name = "mvf-flexcan", + .driver_data = FLEXCAN_VER_10_0_12, }, }; -- 1.8.3.4