Blame view

kernel/linux-imx6_3.14.28/arch/arm/mach-omap2/am35xx-emac.c 3.22 KB
6b13f685e   김민수   BSP 최초 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  /*
   * 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 "omap_device.h"
  #include "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);
  	if (IS_ERR(pdev)) {
  		WARN(1, "Can't build omap_device for %s:%s.
  ",
  		     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
  ");
  		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
  ");
  		return;
  	}
  
  	oh = omap_hwmod_lookup("davinci_emac");
  	if (!oh) {
  		pr_err("Could not find davinci_emac hwmod
  ");
  		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
  ");
  		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 */
  }