Changeset 24139


Ignore:
Timestamp:
2010-11-25T12:57:57+01:00 (7 years ago)
Author:
florian
Message:

[ar7] handle new revisions of vlynq wrt reset sequence, patch from sn9

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/ar7/patches-2.6.32/160-vlynq_try_remote_first.patch

    r23745 r24139  
    1 --- a/drivers/vlynq/vlynq.c 
    2 +++ b/drivers/vlynq/vlynq.c 
    3 @@ -514,9 +514,14 @@ static int __vlynq_enable_device(struct 
    4                                 !__vlynq_try_external(dev)) 
    5                                 return 0; 
     1Index: linux-2.6.32.26/drivers/vlynq/vlynq.c 
     2=================================================================== 
     3--- linux-2.6.32.26.orig/drivers/vlynq/vlynq.c  2010-11-24 13:01:20.459985351 -0800 
     4+++ linux-2.6.32.26/drivers/vlynq/vlynq.c       2010-11-24 13:01:43.537494084 -0800 
     5@@ -103,6 +103,12 @@ 
     6 } 
     7 #endif 
     8  
     9+u32 __vlynq_rev_reg(struct vlynq_regs *regs) 
     10+{ 
     11+       return readl(&regs->revision); 
     12+} 
     13+EXPORT_SYMBOL(__vlynq_rev_reg); 
     14+ 
     15 /* Check the VLYNQ link status with a given device */ 
     16 static int vlynq_linked(struct vlynq_device *dev) 
     17 { 
     18@@ -117,20 +123,43 @@ 
     19        return 0; 
     20 } 
     21  
     22+static volatile int vlynq_delay_value_new = 0; 
     23+ 
     24+static void vlynq_delay_wait(u32 count) 
     25+{ 
     26+       /* Code adopted from original vlynq driver */ 
     27+       int i = 0; 
     28+       volatile int *ptr = &vlynq_delay_value_new; 
     29+       *ptr = 0; 
     30+ 
     31+       /* We are assuming that the each cycle takes about 
     32+        * 23 assembly instructions. */ 
     33+       for(i = 0; i < (count + 23)/23; i++) 
     34+               *ptr = *ptr + 1; 
     35+} 
     36+ 
     37 static void vlynq_reset(struct vlynq_device *dev) 
     38 { 
     39+       u32 rtm = readl(&dev->local->revision); 
     40+ 
     41+       if (rtm < 0x00010200) 
     42+               return; 
     43+ 
     44+       rtm = rtm < 0x00010205 || readl(&dev->local->status) & 0x800 == 0 ? 
     45+                       0 : 0x600000; 
     46+ 
     47        writel(readl(&dev->local->control) | VLYNQ_CTRL_RESET, 
     48                        &dev->local->control); 
     49  
     50        /* Wait for the devices to finish resetting */ 
     51-       msleep(5); 
     52+       vlynq_delay_wait(0xffffff); 
     53  
     54        /* Remove reset bit */ 
     55-       writel(readl(&dev->local->control) & ~VLYNQ_CTRL_RESET, 
     56+       writel(readl(&dev->local->control) & ~VLYNQ_CTRL_RESET | rtm, 
     57                        &dev->local->control); 
     58  
     59        /* Give some time for the devices to settle */ 
     60-       msleep(5); 
     61+       vlynq_delay_wait(0xffffff); 
     62 } 
     63  
     64 static void vlynq_irq_unmask(unsigned int irq) 
     65@@ -379,6 +408,62 @@ 
     66 } 
     67 EXPORT_SYMBOL(vlynq_unregister_driver); 
     68  
     69+enum vlynq_clk_src { 
     70+       vlynq_clk_external, 
     71+       vlynq_clk_local, 
     72+       vlynq_clk_remote, 
     73+       vlynq_clk_invalid, 
     74+}; 
     75+ 
     76+static int __vlynq_set_clocks(struct vlynq_device *dev, 
     77+                               enum vlynq_clk_src clk_dir, 
     78+                               int lclk_div, int rclk_div) 
     79+{ 
     80+       u32 reg; 
     81+ 
     82+       if (clk_dir == vlynq_clk_invalid) { 
     83+               printk(KERN_ERR "%s: attempt to set invalid clocking\n", 
     84+                               dev_name(&dev->dev)); 
     85+               return -EINVAL; 
     86+       } 
     87+ 
     88+       printk(KERN_INFO "%s: local VLYNQ protocol rev. is 0x%08x\n", 
     89+                       dev_name(&dev->dev), readl(&dev->local->revision)); 
     90+ 
     91+       reg = readl(&dev->local->control); 
     92+       if (readl(&dev->local->revision) < 0x00010205) { 
     93+               if (clk_dir & vlynq_clk_local) 
     94+                       reg |= VLYNQ_CTRL_CLOCK_INT; 
     95+               else 
     96+                       reg &= ~VLYNQ_CTRL_CLOCK_INT; 
     97+       } 
     98+       reg &= ~VLYNQ_CTRL_CLOCK_MASK; 
     99+       reg |= VLYNQ_CTRL_CLOCK_DIV(lclk_div); 
     100+       writel(reg, &dev->local->control); 
     101+ 
     102+       if (!vlynq_linked(dev)) 
     103+               return -ENODEV; 
     104+ 
     105+       printk(KERN_INFO "%s: remote VLYNQ protocol rev. is 0x%08x\n", 
     106+                       dev_name(&dev->dev), readl(&dev->remote->revision)); 
     107+ 
     108+       reg = readl(&dev->remote->control); 
     109+       if (readl(&dev->remote->revision) < 0x00010205) { 
     110+               if (clk_dir & vlynq_clk_remote) 
     111+                       reg |= VLYNQ_CTRL_CLOCK_INT; 
     112+               else 
     113+                       reg &= ~VLYNQ_CTRL_CLOCK_INT; 
     114+       } 
     115+       reg &= ~VLYNQ_CTRL_CLOCK_MASK; 
     116+       reg |= VLYNQ_CTRL_CLOCK_DIV(rclk_div); 
     117+       writel(reg, &dev->remote->control); 
     118+ 
     119+       if (!vlynq_linked(dev)) 
     120+               return -ENODEV; 
     121+ 
     122+       return 0; 
     123+} 
     124+ 
     125 /* 
     126  * A VLYNQ remote device can clock the VLYNQ bus master 
     127  * using a dedicated clock line. In that case, both the 
     128@@ -392,29 +477,15 @@ 
     129        int i; 
     130  
     131        vlynq_reset(dev); 
     132-       for (i = dev->dev_id ? vlynq_rdiv2 : vlynq_rdiv8; dev->dev_id ? 
     133-                       i <= vlynq_rdiv8 : i >= vlynq_rdiv2; 
     134-               dev->dev_id ? i++ : i--) { 
     135- 
     136+       for (i = 0; i <= 7; i++) { 
     137                if (!vlynq_linked(dev)) 
     138                        break; 
     139  
     140-               writel((readl(&dev->remote->control) & 
     141-                               ~VLYNQ_CTRL_CLOCK_MASK) | 
     142-                               VLYNQ_CTRL_CLOCK_INT | 
     143-                               VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), 
     144-                               &dev->remote->control); 
     145-               writel((readl(&dev->local->control) 
     146-                               & ~(VLYNQ_CTRL_CLOCK_INT | 
     147-                               VLYNQ_CTRL_CLOCK_MASK)) | 
     148-                               VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), 
     149-                               &dev->local->control); 
     150- 
     151-               if (vlynq_linked(dev)) { 
     152+               if (!__vlynq_set_clocks(dev, vlynq_clk_remote, i, i)) { 
     153                        printk(KERN_DEBUG 
     154-                               "%s: using remote clock divisor %d\n", 
     155-                               dev_name(&dev->dev), i - vlynq_rdiv1 + 1); 
     156-                       dev->divisor = i; 
     157+                                       "%s: using remote clock divisor %d\n", 
     158+                                       dev_name(&dev->dev), i + 1); 
     159+                       dev->divisor = i + vlynq_rdiv1; 
     160                        return 0; 
    6161                } else { 
     162                        vlynq_reset(dev); 
     163@@ -437,21 +508,12 @@ 
     164  
     165        vlynq_reset(dev); 
     166  
     167-       for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ? 
     168-                       i <= vlynq_ldiv8 : i >= vlynq_ldiv2; 
     169-               dev->dev_id ? i++ : i--) { 
     170- 
     171-               writel((readl(&dev->local->control) & 
     172-                               ~VLYNQ_CTRL_CLOCK_MASK) | 
     173-                               VLYNQ_CTRL_CLOCK_INT | 
     174-                               VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1), 
     175-                               &dev->local->control); 
     176- 
     177-               if (vlynq_linked(dev)) { 
     178+       for (i = 0; i <= 7; i++) { 
     179+               if (!__vlynq_set_clocks(dev, vlynq_clk_local, i, 0)) { 
     180                        printk(KERN_DEBUG 
     181-                               "%s: using local clock divisor %d\n", 
     182-                               dev_name(&dev->dev), i - vlynq_ldiv1 + 1); 
     183-                       dev->divisor = i; 
     184+                                       "%s: using local clock divisor %d\n", 
     185+                                       dev_name(&dev->dev), i + 1); 
     186+                       dev->divisor = i + vlynq_ldiv1; 
     187                        return 0; 
     188                } else { 
     189                        vlynq_reset(dev); 
     190@@ -473,18 +535,10 @@ 
     191        if (!vlynq_linked(dev)) 
     192                return -ENODEV; 
     193  
     194-       writel((readl(&dev->remote->control) & 
     195-                       ~VLYNQ_CTRL_CLOCK_INT), 
     196-                       &dev->remote->control); 
     197- 
     198-       writel((readl(&dev->local->control) & 
     199-                       ~VLYNQ_CTRL_CLOCK_INT), 
     200-                       &dev->local->control); 
     201- 
     202-       if (vlynq_linked(dev)) { 
     203+       if (!__vlynq_set_clocks(dev, vlynq_clk_external, 0, 0)) { 
     204                printk(KERN_DEBUG "%s: using external clock\n", 
     205-                       dev_name(&dev->dev)); 
     206-                       dev->divisor = vlynq_div_external; 
     207+                               dev_name(&dev->dev)); 
     208+                               dev->divisor = vlynq_div_external; 
     209                return 0; 
     210        } 
     211  
     212@@ -507,18 +561,9 @@ 
     213                 * generation negotiated by hardware. 
     214                 * Check which device is generating clocks and perform setup 
     215                 * accordingly */ 
     216-               if (vlynq_linked(dev) && readl(&dev->remote->control) & 
     217-                  VLYNQ_CTRL_CLOCK_INT) { 
     218-                       if (!__vlynq_try_remote(dev) || 
     219-                               !__vlynq_try_local(dev)  || 
     220-                               !__vlynq_try_external(dev)) 
     221-                               return 0; 
     222-               } else { 
    7223-                       if (!__vlynq_try_external(dev) || 
    8224-                               !__vlynq_try_local(dev)    || 
    9225-                               !__vlynq_try_remote(dev)) 
    10 +            /* XXX: I don't really know what difference it makes, if the order 
    11 +             * of the following calls is changed, but at least in this order 
    12 +             * my fritzbox doesn't hang at startup as in 
    13 +             * https://dev.openwrt.org/ticket/7324 
    14 +             */ 
    15 +                       if (!__vlynq_try_remote(dev) || 
    16 +                               !__vlynq_try_local(dev)  || 
    17 +                               !__vlynq_try_external(dev)) 
    18                                 return 0; 
     226-                               return 0; 
     227-               } 
     228+               if (!__vlynq_try_remote(dev) || !__vlynq_try_local(dev) || 
     229+                                               !__vlynq_try_external(dev)) 
     230+                       return 0; 
     231                break; 
     232        case vlynq_ldiv1: 
     233        case vlynq_ldiv2: 
     234@@ -528,15 +573,12 @@ 
     235        case vlynq_ldiv6: 
     236        case vlynq_ldiv7: 
     237        case vlynq_ldiv8: 
     238-               writel(VLYNQ_CTRL_CLOCK_INT | 
     239-                       VLYNQ_CTRL_CLOCK_DIV(dev->divisor - 
     240-                       vlynq_ldiv1), &dev->local->control); 
     241-               writel(0, &dev->remote->control); 
     242-               if (vlynq_linked(dev)) { 
     243+               if (!__vlynq_set_clocks(dev, vlynq_clk_local, dev->divisor - 
     244+                               vlynq_ldiv1, 0)) { 
     245                        printk(KERN_DEBUG 
     246-                               "%s: using local clock divisor %d\n", 
     247-                               dev_name(&dev->dev), 
     248-                               dev->divisor - vlynq_ldiv1 + 1); 
     249+                                       "%s: using local clock divisor %d\n", 
     250+                                       dev_name(&dev->dev), 
     251+                                       dev->divisor - vlynq_ldiv1 + 1); 
     252                        return 0; 
    19253                } 
    20254                break; 
     255@@ -548,15 +590,12 @@ 
     256        case vlynq_rdiv6: 
     257        case vlynq_rdiv7: 
     258        case vlynq_rdiv8: 
     259-               writel(0, &dev->local->control); 
     260-               writel(VLYNQ_CTRL_CLOCK_INT | 
     261-                       VLYNQ_CTRL_CLOCK_DIV(dev->divisor - 
     262-                       vlynq_rdiv1), &dev->remote->control); 
     263-               if (vlynq_linked(dev)) { 
     264+               if (!__vlynq_set_clocks(dev, vlynq_clk_remote, 0, 
     265+                               dev->divisor - vlynq_rdiv1)) { 
     266                        printk(KERN_DEBUG 
     267-                               "%s: using remote clock divisor %d\n", 
     268-                               dev_name(&dev->dev), 
     269-                               dev->divisor - vlynq_rdiv1 + 1); 
     270+                                       "%s: using remote clock divisor %d\n", 
     271+                                       dev_name(&dev->dev), 
     272+                                       dev->divisor - vlynq_rdiv1 + 1); 
     273                        return 0; 
     274                } 
     275                break; 
     276@@ -732,13 +771,13 @@ 
     277        platform_set_drvdata(pdev, dev); 
     278  
     279        printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n", 
     280-              dev_name(&dev->dev), (void *)dev->regs_start, dev->irq, 
     281-              (void *)dev->mem_start); 
     282+                       dev_name(&dev->dev), (void *)dev->regs_start, 
     283+                       dev->irq, (void *)dev->mem_start); 
     284  
     285-       dev->dev_id = 0; 
     286        dev->divisor = vlynq_div_auto; 
     287-       result = __vlynq_enable_device(dev); 
     288-       if (result == 0) { 
     289+       if (__vlynq_enable_device(dev)) 
     290+               dev->dev_id = 0; 
     291+       else { 
     292                dev->dev_id = readl(&dev->remote->chip); 
     293                ((struct plat_vlynq_ops *)(dev->dev.platform_data))->off(dev); 
     294        } 
     295Index: linux-2.6.32.26/include/linux/vlynq.h 
     296=================================================================== 
     297--- linux-2.6.32.26.orig/include/linux/vlynq.h  2010-11-24 13:07:33.297487888 -0800 
     298+++ linux-2.6.32.26/include/linux/vlynq.h       2010-11-24 13:08:44.107488596 -0800 
     299@@ -98,6 +98,7 @@ 
     300  
     301 extern struct bus_type vlynq_bus_type; 
     302  
     303+extern u32 __vlynq_rev_reg(struct vlynq_regs *regs); 
     304 extern int __vlynq_register_driver(struct vlynq_driver *driver, 
     305                                   struct module *owner); 
     306  
Note: See TracChangeset for help on using the changeset viewer.