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