import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / usb11 / mt8127 / musbfsh_mt65xx.c
1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/init.h>
4 #include <linux/platform_device.h>
5 #include <linux/dma-mapping.h>
6 #include "musbfsh_core.h"
7 #include "musbfsh_mt65xx.h"
8 #include "mach/emi_mpu.h"
9 #define FRA (48)
10 #define PARA (25)
11 bool musbfsh_power = false;
12 // unsigned char __iomem *usb11_phy_addr = (unsigned char __iomem*)USB11_PHY_ADDR;
13
14 struct mt_usb11_glue {
15 struct device *dev;
16 struct platform_device *musbfsh;
17 };
18
19 void usb11_hs_slew_rate_cal(void){
20
21 unsigned long data;
22 unsigned long x;
23 unsigned char value;
24 unsigned long start_time, timeout;
25 unsigned int timeout_flag = 0;
26 //4 s1:enable usb ring oscillator.
27 USB11PHY_WRITE8(0x15,0x80);
28
29 //4 s2:wait 1us.
30 udelay(1);
31
32 //4 s3:enable free run clock
33 USB11PHY_WRITE8 (0xf00-0x900+0x11,0x01);
34 //4 s4:setting cyclecnt.
35 USB11PHY_WRITE8 (0xf00-0x900+0x01,0x04);
36 //4 s5:enable frequency meter
37 USB11PHY_SET8 (0xf00-0x900+0x03,0x05);
38
39 //4 s6:wait for frequency valid.
40 start_time = jiffies;
41 timeout = jiffies + 3 * HZ;
42 while(!(USB11PHY_READ8(0xf00-0x900+0x10)&0x1)){
43 if(time_after(jiffies, timeout)){
44 timeout_flag = 1;
45 break;
46 }
47 }
48
49 //4 s7: read result.
50 if(timeout_flag){
51 printk("[USBPHY] Slew Rate Calibration: Timeout\n");
52 value = 0x4;
53 }
54 else{
55 data = USB11PHY_READ32 (0xf00-0x900+0x0c);
56 x = ((1024*FRA*PARA)/data);
57 value = (unsigned char)(x/1000);
58 if((x-value*1000)/100>=5)
59 value += 1;
60 // printk("[USB11PHY]slew calibration:FM_OUT =%d, x=%d,value=%d\n",data,x,value);
61 }
62
63 //4 s8: disable Frequency and run clock.
64 USB11PHY_CLR8 (0xf00-0x900+0x03,0x05);//disable frequency meter
65 USB11PHY_CLR8 (0xf00-0x900+0x11,0x01);//disable free run clock
66
67 //4 s9:
68 USB11PHY_WRITE8(0x15,value<<4);
69
70 //4 s10:disable usb ring oscillator.
71 USB11PHY_CLR8(0x15,0x80);
72 }
73
74
75 void mt65xx_usb11_phy_poweron(void)
76 {
77 INFO("mt65xx_usb11_phy_poweron++\r\n");
78
79 enable_pll(UNIVPLL, "USB11");
80 //udelay(100); // PHY power stable time
81 #if 0
82 /* reverse preloader's sin @mt6575_usbphy.c */
83 USB11PHY_CLR8(U1PHTCR2+3, force_usb11_avalid | force_usb11_bvalid | force_usb11_sessend | force_usb11_vbusvalid);
84 USB11PHY_CLR8(U1PHTCR2+2, RG_USB11_AVALID | RG_USB11_BVALID | RG_USB11_SESSEND | RG_USB11_VBUSVALID);
85 USB11PHY_CLR8(U1PHYCR1+2, force_usb11_en_fs_ls_rcv | force_usb11_en_fs_ls_tx);
86 /**************************************/
87
88 USB11PHY_SET8(U1PHYCR0+1, RG_USB11_FSLS_ENBGRI);
89
90 USB11PHY_SET8(U1PHTCR2+3, force_usb11_avalid | force_usb11_sessend | force_usb11_vbusvalid);
91 USB11PHY_SET8(U1PHTCR2+2, RG_USB11_AVALID | RG_USB11_VBUSVALID);
92 USB11PHY_CLR8(U1PHTCR2+2, RG_USB11_SESSEND);
93 #endif
94
95
96 #if 0
97 //HQA LOOPBACK TEST. <FS>
98 USB11PHY_CLR8(0x1a, 0x80);
99 USB11PHY_CLR8(0x68, 0x08);
100
101 USB11PHY_CLR8(0x68, 0x03);
102 USB11PHY_SET8(0x68, 0x10);
103
104 USB11PHY_SET8(0x68, 0x04);
105 USB11PHY_CLR8(0x69, 0x03);
106 USB11PHY_CLR8(0x69, 0x3C);
107
108 USB11PHY_SET8(0x68, 0x80);
109
110 USB11PHY_SET8(0x6a, 0x04);
111 USB11PHY_SET8(0x6a, 0x01);
112 USB11PHY_SET8(0x6a, 0x08);
113 USB11PHY_SET8(0x6a, 0x02);
114
115 USB11PHY_SET8(0x6a, 0x40);
116 USB11PHY_SET8(0x6a, 0x80);
117 USB11PHY_SET8(0x6a, 0x30);
118
119 USB11PHY_SET8(0x68, 0x08);
120 udelay(50);
121
122 USB11PHY_SET8(0x63, 0x02);
123 udelay(1);
124
125 USB11PHY_SET8(0x63, 0x02);
126 USB11PHY_SET8(0x63, 0x04);
127 USB11PHY_CLR8(0x63, 0x08);
128
129 #endif
130
131
132
133 #if 0
134 //HQA LOOPBACK TEST. <HS>
135 USB11PHY_CLR8(0x1a, 0x80);
136 USB11PHY_CLR8(0x68, 0x08);
137
138 USB11PHY_CLR8(0x68, 0x03);
139 USB11PHY_CLR8(0x68, 0x30);
140
141 USB11PHY_CLR8(0x68, 0x04);
142 USB11PHY_CLR8(0x69, 0x03);
143 USB11PHY_CLR8(0x69, 0x3C);
144
145 USB11PHY_CLR8(0x68, 0xC0);
146
147 USB11PHY_SET8(0x6a, 0x04);
148 USB11PHY_SET8(0x6a, 0x01);
149 USB11PHY_SET8(0x6a, 0x08);
150 USB11PHY_SET8(0x6a, 0x02);
151
152 USB11PHY_SET8(0x6a, 0x40);
153 USB11PHY_SET8(0x6a, 0x80);
154 USB11PHY_SET8(0x6a, 0x30);
155
156 USB11PHY_SET8(0x68, 0x08);
157 udelay(50);
158
159 USB11PHY_SET8(0x63, 0x02);
160 udelay(1);
161
162 USB11PHY_SET8(0x63, 0x02);
163 USB11PHY_SET8(0x63, 0x04);
164 USB11PHY_CLR8(0x63, 0x08);
165
166 usb11_hs_slew_rate_cal();
167
168 #endif
169
170 udelay(50);
171
172 USB11PHY_CLR8(0x6b, 0x04);
173 USB11PHY_CLR8(0x6e, 0x01);
174
175 USB11PHY_CLR8(0x1a, 0x80);
176
177 /* remove in MT6588 ?????
178 USBPHY_CLR8(0x02, 0x7f);
179 USBPHY_SET8(0x02, 0x09);
180 USBPHY_CLR8(0x22, 0x03);
181 */
182
183 USB11PHY_CLR8(0x6a, 0x04);
184 //USBPHY_SET8(0x1b, 0x08);
185
186 //force VBUS Valid
187 USB11PHY_SET8(0x6C, 0x2C);
188 USB11PHY_SET8(0x6D, 0x3C);
189 #if 1 //joson
190 /* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X */
191 USB11PHY_SET8(0x6c, 0x10);
192 USB11PHY_CLR8(0x6c, 0x2e);
193 USB11PHY_SET8(0x6d, 0x3e);
194
195 /* wait */
196 msleep(5);
197 /* restart session */
198
199 /* USB MAC ONand Host Mode*/
200 /* VBUSVALID=1, AVALID=1, BVALID=1, SESSEND=0, IDDIG=0 */
201 USB11PHY_CLR8(0x6c, 0x10);
202 USB11PHY_SET8(0x6c, 0x2c);
203 USB11PHY_SET8(0x6d, 0x3e);
204 #endif
205 udelay(800);
206
207 }
208
209 void mt65xx_usb11_phy_savecurrent(void)
210 {
211 INFO("mt65xx_usb11_phy_savecurrent++\r\n");
212
213 #if 0
214 USB11PHY_SET8(U1PHTCR2+3, force_usb11_avalid | force_usb11_sessend | force_usb11_vbusvalid);
215 USB11PHY_CLR8(U1PHTCR2+2, RG_USB11_AVALID | RG_USB11_VBUSVALID);
216 USB11PHY_SET8(U1PHTCR2+2, RG_USB11_SESSEND);
217
218 USB11PHY_CLR8(U1PHYCR0+1, RG_USB11_FSLS_ENBGRI);
219
220 USB11PHY_SET8(U1PHYCR1+2, force_usb11_en_fs_ls_rcv | force_usb11_en_fs_ls_tx);
221 USB11PHY_CLR8(U1PHYCR1+3, RG_USB11_EN_FS_LS_RCV | RG_USB11_EN_FS_LS_TX);
222 #endif
223
224 //4 1. swtich to USB function. (system register, force ip into usb mode.
225 USB11PHY_CLR8(0x6b, 0x04);
226 USB11PHY_CLR8(0x6e, 0x01);
227
228 //4 2. release force suspendm.
229 USB11PHY_CLR8(0x6a, 0x04);
230 //4 3. RG_DPPULLDOWN./RG_DMPULLDOWN.
231 USB11PHY_SET8(0x68, 0xc0);
232 //4 4. RG_XCVRSEL[1:0] =2'b01.
233 USB11PHY_CLR8(0x68, 0x30);
234 USB11PHY_SET8(0x68, 0x10);
235 //4 5. RG_TERMSEL = 1'b1
236 USB11PHY_SET8(0x68, 0x04);
237 //4 6. RG_DATAIN[3:0]=4'b0000
238 USB11PHY_CLR8(0x69, 0x3c);
239 //4 7.force_dp_pulldown, force_dm_pulldown, force_xcversel,force_termsel.
240 USB11PHY_SET8(0x6a, 0xba);
241
242 //4 8.RG_USB20_BC11_SW_EN 1'b0
243 USB11PHY_CLR8(0x1a, 0x80);
244 //4 9.RG_USB20_OTG_VBUSSCMP_EN 1'b0
245 USB11PHY_CLR8(0x1a, 0x10);
246 //4 10. delay 800us.
247 udelay(800);
248 //4 11. rg_usb20_pll_stable = 1
249 USB11PHY_SET8(0x63, 0x02);
250
251 udelay(1);
252 //4 12. force suspendm = 1.
253 USB11PHY_SET8(0x6a, 0x04);
254
255 USB11PHY_CLR8(0x6C, 0x2C);
256 USB11PHY_SET8(0x6C, 0x10);
257 USB11PHY_CLR8(0x6D, 0x3C);
258
259 //4 13. wait 1us
260 udelay(1);
261 //4 14. turn off internal 48Mhz PLL.
262 disable_pll(UNIVPLL, "USB11");
263 }
264
265 void mt65xx_usb11_phy_recover(void)
266 {
267 INFO("mt65xx_usb11_phy_recover++\r\n");
268
269 //4 1. turn on USB reference clock.
270 enable_pll(UNIVPLL, "USB11");
271
272 #if 0
273 USB11PHY_SET8(U1PHTCR2+3, force_usb11_avalid | force_usb11_sessend | force_usb11_vbusvalid);
274 USB11PHY_SET8(U1PHTCR2+2, RG_USB11_AVALID | RG_USB11_VBUSVALID);
275 USB11PHY_CLR8(U1PHTCR2+2, RG_USB11_SESSEND);
276
277 USB11PHY_CLR8(U1PHYCR1+2, force_usb11_en_fs_ls_rcv | force_usb11_en_fs_ls_tx);
278 USB11PHY_CLR8(U1PHYCR1+3, RG_USB11_EN_FS_LS_RCV | RG_USB11_EN_FS_LS_TX);
279
280 USB11PHY_SET8(U1PHYCR0+1, RG_USB11_FSLS_ENBGRI);
281
282 udelay(100);
283 #endif
284
285 //4 2. wait 50 usec.
286 udelay(50);
287 //4 3. force_uart_en = 1'b0
288 USB11PHY_CLR8(0x6b, 0x04);
289 //4 4. RG_UART_EN = 1'b0
290 USB11PHY_CLR8(0x6e, 0x1);
291 //4 5. force_uart_en = 1'b0
292 USB11PHY_CLR8(0x6a, 0x04);
293
294 //4 6. RG_DPPULLDOWN = 1'b0
295 USB11PHY_CLR8(0x68, 0x40);
296 //4 7. RG_DMPULLDOWN = 1'b0
297 USB11PHY_CLR8(0x68, 0x80);
298 //4 8. RG_XCVRSEL = 2'b00
299 USB11PHY_CLR8(0x68, 0x30);
300 //4 9. RG_TERMSEL = 1'b0
301 USB11PHY_CLR8(0x68, 0x04);
302 //4 10. RG_DATAIN[3:0] = 4'b0000
303 USB11PHY_CLR8(0x69, 0x3c);
304
305 //4 11. force_dp_pulldown = 1b'0
306 USB11PHY_CLR8(0x6a, 0x10);
307 //4 12. force_dm_pulldown = 1b'0
308 USB11PHY_CLR8(0x6a, 0x20);
309 //4 13. force_xcversel = 1b'0
310 USB11PHY_CLR8(0x6a, 0x08);
311 //4 14. force_termsel = 1b'0
312 USB11PHY_CLR8(0x6a, 0x02);
313 //4 15. force_datain = 1b'0
314 USB11PHY_CLR8(0x6a, 0x80);
315
316 //4 16. RG_USB20_BC11_SW_EN 1'b0
317 USB11PHY_CLR8(0x1a, 0x80);
318 //4 17. RG_USB20_OTG_VBUSSCMP_EN 1'b1
319 USB11PHY_SET8(0x1a, 0x10);
320
321 USB11PHY_SET8(0x6C, 0x2C);
322 USB11PHY_SET8(0x6D, 0x3C);
323 //<4> 18. wait 800 usec.
324 udelay(800);
325
326 usb11_hs_slew_rate_cal();
327 }
328
329 static bool clock_enabled = false;
330
331 void mt65xx_usb11_clock_enable(bool enable)
332 {
333 INFO("mt65xx_usb11_clock_enable++\r\n");
334 if(enable){
335 if(clock_enabled)//already enable
336 return;
337 else{
338 enable_clock(MT_CG_PERI_USB0, "PERI_USB"); //mt8127 PERI_USB1 dependence PERI_USB0
339 enable_clock (MT_CG_PERI_USB1, "USB11");
340 clock_enabled = true;
341 }
342 }
343 else{
344 if(!clock_enabled)//already disabled.
345 return;
346 else{
347 disable_clock (MT_CG_PERI_USB1, "USB11");
348 disable_clock (MT_CG_PERI_USB0, "PERI_USB"); //mt8127 PERI_USB1 dependence PERI_USB0
349 clock_enabled = false;
350 }
351 }
352 return;
353 }
354
355
356 void mt_usb11_poweron(struct musbfsh *musbfsh,int on){
357 static bool recover = false;
358 INFO("mt65xx_usb11_poweron++\r\n");
359 if(on){
360 if(musbfsh_power) {
361
362 } else{
363 mt65xx_usb11_clock_enable (true);
364 if(!recover){
365 //mt65xx_usb11_phy_poweron();
366 mt65xx_usb11_phy_recover();
367 recover = true;
368 } else {
369 mt65xx_usb11_phy_recover();
370 }
371 musbfsh_power = true;
372 }
373 } else{
374 if(!musbfsh_power) {
375
376 } else{
377 mt65xx_usb11_phy_savecurrent();
378 mt65xx_usb11_clock_enable(false);
379 musbfsh_power = false;
380 }
381 }
382
383 }
384
385 void mt_usb11_set_vbus(struct musbfsh *musbfsh, int is_on)
386 {
387 INFO("is_on=%d\n",is_on);
388 #if 0
389 // mt_set_gpio_mode(GPIO67,0);//should set GPIO_OTG_DRVVBUS_PIN as gpio mode.
390 mt_set_gpio_dir(GPIO_OTG_DRVVBUS_PIN,GPIO_DIR_OUT);
391 if(is_on){
392 if(oned)
393 return;
394 else{
395 mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN,GPIO_OUT_ONE);
396 oned = 1;
397 }
398 } else {
399 if(!oned)
400 return;
401 else{
402 mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN,GPIO_OUT_ZERO);
403 oned = 0;
404 }
405 }
406 #endif
407 }
408
409 void musbfs_check_mpu_violation(u32 addr, int wr_vio)
410 {
411 void __iomem *mregs = (void *)USB_BASE;
412
413 printk(KERN_CRIT "MUSB checks EMI MPU violation.\n");
414 printk(KERN_CRIT "addr = 0x%x, %s violation.\n", addr, wr_vio? "Write": "Read");
415 printk(KERN_CRIT "POWER = 0x%x,DEVCTL= 0x%x.\n", musbfsh_readb(mregs, MUSBFSH_POWER),musbfsh_readb((void __iomem *)USB11_BASE,MUSBFSH_DEVCTL));
416 printk(KERN_CRIT "DMA_CNTLch0 0x%04x,DMA_ADDRch0 0x%08x,DMA_COUNTch0 0x%08x \n",musbfsh_readw(mregs, 0x204),musbfsh_readl(mregs,0x208),musbfsh_readl(mregs,0x20C));
417 printk(KERN_CRIT "DMA_CNTLch1 0x%04x,DMA_ADDRch1 0x%08x,DMA_COUNTch1 0x%08x \n",musbfsh_readw(mregs, 0x214),musbfsh_readl(mregs,0x218),musbfsh_readl(mregs,0x21C));
418 printk(KERN_CRIT "DMA_CNTLch2 0x%04x,DMA_ADDRch2 0x%08x,DMA_COUNTch2 0x%08x \n",musbfsh_readw(mregs, 0x224),musbfsh_readl(mregs,0x228),musbfsh_readl(mregs,0x22C));
419 printk(KERN_CRIT "DMA_CNTLch3 0x%04x,DMA_ADDRch3 0x%08x,DMA_COUNTch3 0x%08x \n",musbfsh_readw(mregs, 0x234),musbfsh_readl(mregs,0x238),musbfsh_readl(mregs,0x23C));
420 printk(KERN_CRIT "DMA_CNTLch4 0x%04x,DMA_ADDRch4 0x%08x,DMA_COUNTch4 0x%08x \n",musbfsh_readw(mregs, 0x244),musbfsh_readl(mregs,0x248),musbfsh_readl(mregs,0x24C));
421 printk(KERN_CRIT "DMA_CNTLch5 0x%04x,DMA_ADDRch5 0x%08x,DMA_COUNTch5 0x%08x \n",musbfsh_readw(mregs, 0x254),musbfsh_readl(mregs,0x258),musbfsh_readl(mregs,0x25C));
422 printk(KERN_CRIT "DMA_CNTLch6 0x%04x,DMA_ADDRch6 0x%08x,DMA_COUNTch6 0x%08x \n",musbfsh_readw(mregs, 0x264),musbfsh_readl(mregs,0x268),musbfsh_readl(mregs,0x26C));
423 printk(KERN_CRIT "DMA_CNTLch7 0x%04x,DMA_ADDRch7 0x%08x,DMA_COUNTch7 0x%08x \n",musbfsh_readw(mregs, 0x274),musbfsh_readl(mregs,0x278),musbfsh_readl(mregs,0x27C));
424 }
425
426 int mt_usb11_init(struct musbfsh *musbfsh)
427 {
428 INFO("++\n");
429 if(!musbfsh){
430 ERR("musbfsh_platform_init,error,musbfsh is NULL");
431 return -1;
432 }
433 hwPowerOn(MT65XX_POWER_LDO_VUSB, VOL_3300, "USB11"); // don't need to power on PHY for every resume
434 mt_usb11_poweron(musbfsh,true);
435 // emi_mpu_notifier_register(MST_ID_MMPERI_2, musbfs_check_mpu_violation);
436 return 0;
437 }
438
439 int mt_usb11_exit(struct musbfsh *musbfsh)
440 {
441 INFO("++\n");
442 mt_usb11_poweron(musbfsh,false);
443 // put it here because we can't shutdown PHY power during suspend
444 hwPowerDown(MT65XX_POWER_LDO_VUSB, "USB11");
445 return 0;
446 }
447
448 void musbfsh_hcd_release (struct device *dev)
449 {
450 INFO("musbfsh_hcd_release++,dev = 0x%08X.\n", (uint32_t)dev);
451 }
452
453 static const struct musbfsh_platform_ops mt_usb11_ops = {
454 .init = mt_usb11_init,
455 .exit = mt_usb11_exit,
456 .set_vbus = mt_usb11_set_vbus,
457 .set_power = mt_usb11_poweron,
458 };
459
460 static u64 mt_usb11_dmamask = DMA_BIT_MASK(32);
461
462 static int __init mt_usb11_probe(struct platform_device *pdev)
463 {
464 struct musbfsh_hdrc_platform_data *pdata = pdev->dev.platform_data;
465 struct platform_device *musbfsh;
466 struct mt_usb11_glue *glue;
467 int ret = -ENOMEM;
468 int musbfshid;
469
470 glue = kzalloc(sizeof(*glue), GFP_KERNEL);
471 if (!glue) {
472 dev_err(&pdev->dev, "failed to allocate glue context\n");
473 goto err0;
474 }
475
476 /* get the musbfsh id */
477 musbfshid = musbfsh_get_id(&pdev->dev, GFP_KERNEL);
478 if (musbfshid < 0) {
479 dev_err(&pdev->dev, "failed to allocate musbfsh id\n");
480 ret = -ENOMEM;
481 goto err1;
482 }
483
484 musbfsh = platform_device_alloc("musbfsh-hdrc", musbfshid);
485 if (!musbfsh) {
486 dev_err(&pdev->dev, "failed to allocate musb device\n");
487 goto err2;
488 }
489
490 musbfsh->id = musbfshid;
491 musbfsh->dev.parent = &pdev->dev;
492 musbfsh->dev.dma_mask = &mt_usb11_dmamask;
493 musbfsh->dev.coherent_dma_mask = mt_usb11_dmamask;
494
495 glue->dev = &pdev->dev;
496 glue->musbfsh = musbfsh;
497
498 pdata->platform_ops = &mt_usb11_ops;
499
500 platform_set_drvdata(pdev, glue);
501
502 ret = platform_device_add_resources(musbfsh, pdev->resource,
503 pdev->num_resources);
504 if (ret) {
505 dev_err(&pdev->dev, "failed to add resources\n");
506 goto err3;
507 }
508
509 ret = platform_device_add_data(musbfsh, pdata, sizeof(*pdata));
510 if (ret) {
511 dev_err(&pdev->dev, "failed to add platform_data\n");
512 goto err3;
513 }
514
515 ret = platform_device_add(musbfsh);
516
517 if (ret) {
518 dev_err(&pdev->dev, "failed to register musbfsh device\n");
519 goto err3;
520 }
521
522 return 0;
523
524 err3:
525 platform_device_put(musbfsh);
526
527 err2:
528 musbfsh_put_id(&pdev->dev, musbfshid);
529
530 err1:
531 kfree(glue);
532
533 err0:
534 return ret;
535 }
536
537 static int __exit mt_usb_remove(struct platform_device *pdev)
538 {
539 struct mt_usb11_glue *glue = platform_get_drvdata(pdev);
540
541 musbfsh_put_id(&pdev->dev, glue->musbfsh->id);
542 platform_device_del(glue->musbfsh);
543 platform_device_put(glue->musbfsh);
544 kfree(glue);
545
546 return 0;
547 }
548
549 static struct platform_driver mt_usb11_driver = {
550 .remove = __exit_p(mt_usb_remove),
551 .probe = mt_usb11_probe,
552 .driver = {
553 .name = "mt_usb11",
554 },
555 };
556
557 static int __init usb11_init(void)
558 {
559 return platform_driver_register(&mt_usb11_driver);
560 }
561 subsys_initcall(usb11_init);
562
563 static void __exit usb11_exit(void)
564 {
565 platform_driver_unregister(&mt_usb11_driver);
566 }
567 module_exit(usb11_exit)
568
569
570
571