df0873e67e59ac791147ddc432ce19f4bbf77f47
[openwrt/svn-archive/archive.git] / target / linux / ramips / files / drivers / net / ramips_esw.c
1 #include <linux/ioport.h>
2
3 #include <rt305x_regs.h>
4 #include <rt305x_esw_platform.h>
5
6 #define RT305X_ESW_REG_FCT0 0x08
7 #define RT305X_ESW_REG_PFC1 0x14
8 #define RT305X_ESW_REG_PVIDC(_n) (0x48 + 4 * (_n))
9 #define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
10 #define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
11 #define RT305X_ESW_REG_FPA 0x84
12 #define RT305X_ESW_REG_SOCPC 0x8c
13 #define RT305X_ESW_REG_POC1 0x90
14 #define RT305X_ESW_REG_POC2 0x94
15 #define RT305X_ESW_REG_POC3 0x98
16 #define RT305X_ESW_REG_SGC 0x9c
17 #define RT305X_ESW_REG_PCR0 0xc0
18 #define RT305X_ESW_REG_PCR1 0xc4
19 #define RT305X_ESW_REG_FPA2 0xc8
20 #define RT305X_ESW_REG_FCT2 0xcc
21 #define RT305X_ESW_REG_SGC2 0xe4
22
23 #define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
24 #define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
25 #define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
26
27 #define RT305X_ESW_PCR1_WT_DONE BIT(0)
28
29 #define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
30
31 struct rt305x_esw {
32 void __iomem *base;
33 struct rt305x_esw_platform_data *pdata;
34 };
35
36 static inline void
37 ramips_esw_wr(struct rt305x_esw *esw, u32 val, unsigned reg)
38 {
39 __raw_writel(val, esw->base + reg);
40 }
41
42 static inline u32
43 ramips_esw_rr(struct rt305x_esw *esw, unsigned reg)
44 {
45 return __raw_readl(esw->base + reg);
46 }
47
48 u32
49 mii_mgr_write(struct rt305x_esw *esw, u32 phy_addr, u32 phy_register,
50 u32 write_data)
51 {
52 unsigned long volatile t_start = jiffies;
53 int ret = 0;
54
55 while(1)
56 {
57 if (!(ramips_esw_rr(esw, RT305X_ESW_REG_PCR1) &
58 RT305X_ESW_PCR1_WT_DONE))
59 break;
60 if(time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT))
61 {
62 ret = 1;
63 goto out;
64 }
65 }
66
67 write_data &= 0xffff;
68 ramips_esw_wr(esw,
69 (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) |
70 (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) |
71 (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD,
72 RT305X_ESW_REG_PCR0);
73
74 t_start = jiffies;
75 while(1)
76 {
77 if (ramips_esw_rr(esw, RT305X_ESW_REG_PCR1) &
78 RT305X_ESW_PCR1_WT_DONE)
79 break;
80 if(time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT))
81 {
82 ret = 1;
83 break;
84 }
85 }
86 out:
87 if(ret)
88 printk(KERN_ERR "ramips_eth: MDIO timeout\n");
89 return ret;
90 }
91
92 static void
93 rt305x_esw_hw_init(struct rt305x_esw *esw)
94 {
95 int i;
96
97 /* vodoo from original driver */
98 ramips_esw_wr(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
99 ramips_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2);
100 ramips_esw_wr(esw, 0x00405555, RT305X_ESW_REG_PFC1);
101 ramips_esw_wr(esw, 0x00002001, RT305X_ESW_REG_VLANI(0));
102 ramips_esw_wr(esw, 0x00007f7f, RT305X_ESW_REG_POC1);
103 ramips_esw_wr(esw, 0x00007f3f, RT305X_ESW_REG_POC3);
104 ramips_esw_wr(esw, 0x00d6500c, RT305X_ESW_REG_FCT2);
105 ramips_esw_wr(esw, 0x0008a301, RT305X_ESW_REG_SGC);
106 ramips_esw_wr(esw, 0x02404040, RT305X_ESW_REG_SOCPC);
107 ramips_esw_wr(esw, 0x00001002, RT305X_ESW_REG_PVIDC(2));
108 ramips_esw_wr(esw, 0x3f502b28, RT305X_ESW_REG_FPA2);
109 ramips_esw_wr(esw, 0x00000000, RT305X_ESW_REG_FPA);
110
111 mii_mgr_write(esw, 0, 31, 0x8000);
112 for(i = 0; i < 5; i++)
113 {
114 mii_mgr_write(esw, i, 0, 0x3100); //TX10 waveform coefficient
115 mii_mgr_write(esw, i, 26, 0x1601); //TX10 waveform coefficient
116 mii_mgr_write(esw, i, 29, 0x7058); //TX100/TX10 AD/DA current bias
117 mii_mgr_write(esw, i, 30, 0x0018); //TX100 slew rate control
118 }
119 /* PHY IOT */
120 mii_mgr_write(esw, 0, 31, 0x0); //select global register
121 mii_mgr_write(esw, 0, 22, 0x052f); //tune TP_IDL tail and head waveform
122 mii_mgr_write(esw, 0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
123 mii_mgr_write(esw, 0, 18, 0x40ba); //set squelch amplitude to higher threshold
124 mii_mgr_write(esw, 0, 14, 0x65); //longer TP_IDL tail length
125 mii_mgr_write(esw, 0, 31, 0x8000); //select local register
126
127 /* set default vlan */
128 ramips_esw_wr(esw, 0x2001, RT305X_ESW_REG_VLANI(0));
129 ramips_esw_wr(esw, 0x504f, RT305X_ESW_REG_VMSC(0));
130 }
131
132 static int
133 rt305x_esw_probe(struct platform_device *pdev)
134 {
135 struct rt305x_esw_platform_data *pdata;
136 struct rt305x_esw *esw;
137 struct resource *res;
138 int err;
139
140 pdata = pdev->dev.platform_data;
141 if (!pdata)
142 return -EINVAL;
143
144 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
145 if (!res) {
146 dev_err(&pdev->dev, "no memory resource found\n");
147 return -ENOMEM;
148 }
149
150 esw = kzalloc(sizeof (struct rt305x_esw), GFP_KERNEL);
151 if (!esw) {
152 dev_err(&pdev->dev, "no memory for private data\n");
153 return -ENOMEM;
154 }
155
156 esw->base = ioremap(res->start, resource_size(res));
157 if (!esw->base) {
158 dev_err(&pdev->dev, "ioremap failed\n");
159 err = -ENOMEM;
160 goto free_esw;
161 }
162
163 platform_set_drvdata(pdev, esw);
164
165 esw->pdata = pdata;
166 rt305x_esw_hw_init(esw);
167
168 return 0;
169
170 free_esw:
171 kfree(esw);
172 return err;
173 }
174
175 static int
176 rt305x_esw_remove(struct platform_device *pdev)
177 {
178 struct rt305x_esw *esw;
179
180 esw = platform_get_drvdata(pdev);
181 if (esw) {
182 platform_set_drvdata(pdev, NULL);
183 iounmap(esw->base);
184 kfree(esw);
185 }
186
187 return 0;
188 }
189
190 static struct platform_driver rt305x_esw_driver = {
191 .probe = rt305x_esw_probe,
192 .remove = rt305x_esw_remove,
193 .driver = {
194 .name = "rt305x-esw",
195 .owner = THIS_MODULE,
196 },
197 };
198
199 static int __init
200 rt305x_esw_init(void)
201 {
202 return platform_driver_register(&rt305x_esw_driver);
203 }
204
205 static void __exit
206 rt305x_esw_exit(void)
207 {
208 platform_driver_unregister(&rt305x_esw_driver);
209 }