mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
31ba88083f
Add hwmod support for the EMAC (and MDIO) ethernet controller that's on the am35x family of SoC's. Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> [paul@pwsan.com: updated subject line; updated to apply on v3.5-rc4; added comments to hwmod data regarding IPSS] Signed-off-by: Paul Walmsley <paul@pwsan.com>
116 lines
3.2 KiB
C
116 lines
3.2 KiB
C
/*
|
|
* Copyright (C) 2011 Ilya Yanok, Emcraft Systems
|
|
*
|
|
* Based on mach-omap2/board-am3517evm.c
|
|
* Copyright (C) 2009 Texas Instruments Incorporated
|
|
* Author: Ranjith Lohithakshan <ranjithl@ti.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
|
* whether express or implied; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/err.h>
|
|
#include <linux/davinci_emac.h>
|
|
#include <asm/system.h>
|
|
#include <plat/omap_device.h>
|
|
#include <mach/am35xx.h>
|
|
#include "control.h"
|
|
#include "am35xx-emac.h"
|
|
|
|
static void am35xx_enable_emac_int(void)
|
|
{
|
|
u32 v;
|
|
|
|
v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
|
|
v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR |
|
|
AM35XX_CPGMAC_C0_MISC_PULSE_CLR | AM35XX_CPGMAC_C0_RX_THRESH_CLR);
|
|
omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR);
|
|
omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */
|
|
}
|
|
|
|
static void am35xx_disable_emac_int(void)
|
|
{
|
|
u32 v;
|
|
|
|
v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
|
|
v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR);
|
|
omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR);
|
|
omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */
|
|
}
|
|
|
|
static struct emac_platform_data am35xx_emac_pdata = {
|
|
.ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET,
|
|
.ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET,
|
|
.ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET,
|
|
.ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE,
|
|
.hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR,
|
|
.version = EMAC_VERSION_2,
|
|
.interrupt_enable = am35xx_enable_emac_int,
|
|
.interrupt_disable = am35xx_disable_emac_int,
|
|
};
|
|
|
|
static struct mdio_platform_data am35xx_mdio_pdata;
|
|
|
|
static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh,
|
|
void *pdata, int pdata_len)
|
|
{
|
|
struct platform_device *pdev;
|
|
|
|
pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len,
|
|
NULL, 0, false);
|
|
if (IS_ERR(pdev)) {
|
|
WARN(1, "Can't build omap_device for %s:%s.\n",
|
|
oh->class->name, oh->name);
|
|
return PTR_ERR(pdev);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en)
|
|
{
|
|
struct omap_hwmod *oh;
|
|
u32 v;
|
|
int ret;
|
|
|
|
oh = omap_hwmod_lookup("davinci_mdio");
|
|
if (!oh) {
|
|
pr_err("Could not find davinci_mdio hwmod\n");
|
|
return;
|
|
}
|
|
|
|
am35xx_mdio_pdata.bus_freq = mdio_bus_freq;
|
|
|
|
ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata,
|
|
sizeof(am35xx_mdio_pdata));
|
|
if (ret) {
|
|
pr_err("Could not build davinci_mdio hwmod device\n");
|
|
return;
|
|
}
|
|
|
|
oh = omap_hwmod_lookup("davinci_emac");
|
|
if (!oh) {
|
|
pr_err("Could not find davinci_emac hwmod\n");
|
|
return;
|
|
}
|
|
|
|
am35xx_emac_pdata.rmii_en = rmii_en;
|
|
|
|
ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata,
|
|
sizeof(am35xx_emac_pdata));
|
|
if (ret) {
|
|
pr_err("Could not build davinci_emac hwmod device\n");
|
|
return;
|
|
}
|
|
|
|
v = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
|
|
v &= ~AM35XX_CPGMACSS_SW_RST;
|
|
omap_ctrl_writel(v, AM35XX_CONTROL_IP_SW_RESET);
|
|
omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */
|
|
}
|