[BACK]Return to rk_gmac.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / arm / rockchip

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/arch/arm/rockchip/rk_gmac.c between version 1.3 and 1.3.4.1

version 1.3, 2018/06/19 23:43:11 version 1.3.4.1, 2019/06/10 22:05:55
Line 47  __KERNEL_RCSID(0, "$NetBSD$");
Line 47  __KERNEL_RCSID(0, "$NetBSD$");
 #include <dev/ic/dwc_gmac_reg.h>  #include <dev/ic/dwc_gmac_reg.h>
   
 #include <dev/fdt/fdtvar.h>  #include <dev/fdt/fdtvar.h>
   #include <dev/fdt/syscon.h>
   
   #define RK_GMAC_TXDLY_DEFAULT   0x30
   #define RK_GMAC_RXDLY_DEFAULT   0x10
   
   enum rk_gmac_type {
           GMAC_RK3328 = 1,
           GMAC_RK3399
   };
   
   static const struct of_compat_data compat_data[] = {
           { "rockchip,rk3328-gmac",       GMAC_RK3328 },
           { "rockchip,rk3399-gmac",       GMAC_RK3399 },
           { NULL }
   };
   
   struct rk_gmac_softc {
           struct dwc_gmac_softc   sc_base;
           struct syscon           *sc_syscon;
           enum rk_gmac_type       sc_type;
   };
   
   /*
    * RK3328 specific
    */
   
 #define RK3328_GRF_MAC_CON0     0x0900  #define RK3328_GRF_MAC_CON0     0x0900
 #define  RK3328_GRF_MAC_CON0_RXDLY      __BITS(13,7)  #define  RK3328_GRF_MAC_CON0_RXDLY      __BITS(13,7)
Line 63  __KERNEL_RCSID(0, "$NetBSD$");
Line 88  __KERNEL_RCSID(0, "$NetBSD$");
 #define  RK3328_GRF_MAC_CON1_RXDLY_EN   __BIT(1)  #define  RK3328_GRF_MAC_CON1_RXDLY_EN   __BIT(1)
 #define  RK3328_GRF_MAC_CON1_TXDLY_EN   __BIT(0)  #define  RK3328_GRF_MAC_CON1_TXDLY_EN   __BIT(0)
   
 #define RK_GMAC_TXDLY_DEFAULT   0x30  
 #define RK_GMAC_RXDLY_DEFAULT   0x10  
   
 static const char * compatible[] = {  
         "rockchip,rk3328-gmac",  
         NULL  
 };  
   
 struct rk_gmac_softc {  
         struct dwc_gmac_softc   sc_base;  
         bus_space_handle_t      sc_grf_bsh;  
 };  
   
 static int  
 rk_gmac_reset(const int phandle)  
 {  
         struct fdtbus_gpio_pin *pin_reset;  
         const u_int *reset_delay_us;  
         bool reset_active_low;  
         int len;  
   
         if (!of_hasprop(phandle, "snps,reset-gpio"))  
                 return 0;  
   
         pin_reset = fdtbus_gpio_acquire(phandle, "snps,reset-gpio", GPIO_PIN_OUTPUT);  
         if (pin_reset == NULL)  
                 return ENOENT;  
   
         reset_delay_us = fdtbus_get_prop(phandle, "snps,reset-delays-us", &len);  
         if (reset_delay_us == NULL || len != 12)  
                 return ENXIO;  
   
         reset_active_low = of_hasprop(phandle, "snps,reset-active-low");  
   
         fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0);  
         delay(be32toh(reset_delay_us[0]));  
         fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 0 : 1);  
         delay(be32toh(reset_delay_us[1]));  
         fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0);  
         delay(be32toh(reset_delay_us[2]));  
   
         return 0;  
 }  
   
 static int  
 rk_gmac_intr(void *arg)  
 {  
         return dwc_gmac_intr(arg);  
 }  
   
 static void  static void
 rk3328_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay)  rk3328_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay)
 {  {
         struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;          struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
         uint32_t write_mask, write_val;          uint32_t write_mask, write_val;
   
           syscon_lock(rk_sc->sc_syscon);
   
         write_mask = (RK3328_GRF_MAC_CON1_MODE | RK3328_GRF_MAC_CON1_SEL) << 16;          write_mask = (RK3328_GRF_MAC_CON1_MODE | RK3328_GRF_MAC_CON1_SEL) << 16;
         write_val = __SHIFTIN(RK3328_GRF_MAC_CON1_SEL_RGMII, RK3328_GRF_MAC_CON1_SEL);          write_val = __SHIFTIN(RK3328_GRF_MAC_CON1_SEL_RGMII, RK3328_GRF_MAC_CON1_SEL);
         bus_space_write_4(sc->sc_bst, rk_sc->sc_grf_bsh, RK3328_GRF_MAC_CON1,          syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON1, write_mask | write_val);
             write_mask | write_val);  
   
 #if notyet  #if notyet
         write_mask = (RK3328_GRF_MAC_CON0_TXDLY | RK3328_GRF_MAC_CON0_RXDLY) << 16;          write_mask = (RK3328_GRF_MAC_CON0_TXDLY | RK3328_GRF_MAC_CON0_RXDLY) << 16;
         write_val = __SHIFTIN(tx_delay, RK3328_GRF_MAC_CON0_TXDLY) |          write_val = __SHIFTIN(tx_delay, RK3328_GRF_MAC_CON0_TXDLY) |
                     __SHIFTIN(rx_delay, RK3328_GRF_MAC_CON0_RXDLY);                      __SHIFTIN(rx_delay, RK3328_GRF_MAC_CON0_RXDLY);
         bus_space_write_4(sc->sc_bst, rk_sc->sc_grf_bsh, RK3328_GRF_MAC_CON0,          syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON0, write_mask | write_val);
             write_mask | write_val);  
   
         write_mask = (RK3328_GRF_MAC_CON1_RXDLY_EN | RK3328_GRF_MAC_CON1_TXDLY_EN) << 16;          write_mask = (RK3328_GRF_MAC_CON1_RXDLY_EN | RK3328_GRF_MAC_CON1_TXDLY_EN) << 16;
         write_val = RK3328_GRF_MAC_CON1_RXDLY_EN | RK3328_GRF_MAC_CON1_TXDLY_EN;          write_val = RK3328_GRF_MAC_CON1_RXDLY_EN | RK3328_GRF_MAC_CON1_TXDLY_EN;
         bus_space_write_4(sc->sc_bst, rk_sc->sc_grf_bsh, RK3328_GRF_MAC_CON1,          syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON1, write_mask | write_val);
             write_mask | write_val);  
 #endif  #endif
   
           syscon_unlock(rk_sc->sc_syscon);
 }  }
   
 static void  static void
 rk3328_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed)  rk3328_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed)
 {  {
         struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;          struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
   #if 0
         u_int clksel;          u_int clksel;
   
         switch (speed) {          switch (speed) {
Line 155  rk3328_gmac_set_speed_rgmii(struct dwc_g
Line 132  rk3328_gmac_set_speed_rgmii(struct dwc_g
                 clksel = RK3328_GRF_MAC_CON1_CLKSEL_125M;                  clksel = RK3328_GRF_MAC_CON1_CLKSEL_125M;
                 break;                  break;
         }          }
   #endif
   
         bus_space_write_4(sc->sc_bst, rk_sc->sc_grf_bsh, RK3328_GRF_MAC_CON1,          syscon_lock(rk_sc->sc_syscon);
           syscon_write_4(rk_sc->sc_syscon, RK3328_GRF_MAC_CON1,
             (RK3328_GRF_MAC_CON1_CLKSEL << 16) |              (RK3328_GRF_MAC_CON1_CLKSEL << 16) |
             __SHIFTIN(RK3328_GRF_MAC_CON1_CLKSEL_125M, RK3328_GRF_MAC_CON1_CLKSEL));              __SHIFTIN(RK3328_GRF_MAC_CON1_CLKSEL_125M, RK3328_GRF_MAC_CON1_CLKSEL));
           syscon_unlock(rk_sc->sc_syscon);
   }
   
   /*
    * RK3399 specific
    */
   
   #define RK3399_GRF_SOC_CON5             0x0c214
   #define  RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL  __BITS(11,9)
   #define  RK3399_GRF_SOC_CON5_GMAC_FLOWCTRL      __BIT(8)
   #define  RK3399_GRF_SOC_CON5_GMAC_SPEED         __BIT(7)
   #define  RK3399_GRF_SOC_CON5_RMII_MODE          __BIT(6)
   #define  RK3399_GRF_SOC_CON5_GMAC_CLK_SEL       __BITS(5,4)
   #define   RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_125M 0
   #define   RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_25M  3
   #define   RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_2_5M 2
   #define  RK3399_GRF_SOC_CON5_RMII_CLK_SEL       __BIT(3)
   #define RK3399_GRF_SOC_CON6             0x0c218
   #define  RK3399_GRF_SOC_CON6_GMAC_RXCLK_DLY_ENA __BIT(15)
   #define  RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG __BITS(14,8)
   #define  RK3399_GRF_SOC_CON6_GMAC_TXCLK_DLY_ENA __BIT(7)
   #define  RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG __BITS(6,0)
   
   static void
   rk3399_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay)
   {
           struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
   
           const uint32_t con5_mask =
               (RK3399_GRF_SOC_CON5_RMII_MODE | RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL) << 16;
           const uint32_t con5 = __SHIFTIN(1, RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL);
   
   #if notyet
           const uint32_t con6_mask =
               (RK3399_GRF_SOC_CON6_GMAC_RXCLK_DLY_ENA |
                   RK3399_GRF_SOC_CON6_GMAC_TXCLK_DLY_ENA |
                   RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG |
                   RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG) << 16;
           const uint32_t con6 =
               (tx_delay ? RK3399_GRF_SOC_CON6_GMAC_TXCLK_DLY_ENA : 0) |
               (rx_delay ? RK3399_GRF_SOC_CON6_GMAC_RXCLK_DLY_ENA : 0) |
               __SHIFTIN(rx_delay, RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG) |
               __SHIFTIN(tx_delay, RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG);
   #endif
   
           syscon_lock(rk_sc->sc_syscon);
           syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON5, con5 | con5_mask);
   #if notyet
           syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON6, con6 | con6_mask);
   #endif
           syscon_unlock(rk_sc->sc_syscon);
   }
   
   static void
   rk3399_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed)
   {
           struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc;
           u_int clksel;
   
           switch (speed) {
           case IFM_10_T:
                   clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_2_5M;
                   break;
           case IFM_100_TX:
                   clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_25M;
                   break;
           default:
                   clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_125M;
                   break;
           }
   
           const uint32_t con5_mask =
               RK3399_GRF_SOC_CON5_GMAC_CLK_SEL << 16;
           const uint32_t con5 =
               __SHIFTIN(clksel, RK3399_GRF_SOC_CON5_GMAC_CLK_SEL);
   
           syscon_lock(rk_sc->sc_syscon);
           syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON5, con5 | con5_mask);
           syscon_unlock(rk_sc->sc_syscon);
   }
   
   static int
   rk_gmac_reset(const int phandle)
   {
           struct fdtbus_gpio_pin *pin_reset;
           const u_int *reset_delay_us;
           bool reset_active_low;
           int len;
   
           if (!of_hasprop(phandle, "snps,reset-gpio"))
                   return 0;
   
           pin_reset = fdtbus_gpio_acquire(phandle, "snps,reset-gpio", GPIO_PIN_OUTPUT);
           if (pin_reset == NULL)
                   return ENOENT;
   
           reset_delay_us = fdtbus_get_prop(phandle, "snps,reset-delays-us", &len);
           if (reset_delay_us == NULL || len != 12)
                   return ENXIO;
   
           reset_active_low = of_hasprop(phandle, "snps,reset-active-low");
   
           fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0);
           delay(be32toh(reset_delay_us[0]));
           fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 0 : 1);
           delay(be32toh(reset_delay_us[1]));
           fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0);
           delay(be32toh(reset_delay_us[2]));
   
           return 0;
   }
   
   static int
   rk_gmac_intr(void *arg)
   {
           return dwc_gmac_intr(arg);
 }  }
   
 static int  static int
Line 228  rk_gmac_match(device_t parent, cfdata_t 
Line 323  rk_gmac_match(device_t parent, cfdata_t 
 {  {
         struct fdt_attach_args * const faa = aux;          struct fdt_attach_args * const faa = aux;
   
         return of_match_compatible(faa->faa_phandle, compatible);          return of_match_compat_data(faa->faa_phandle, compat_data);
 }  }
   
 static void  static void
Line 240  rk_gmac_attach(device_t parent, device_t
Line 335  rk_gmac_attach(device_t parent, device_t
         const int phandle = faa->faa_phandle;          const int phandle = faa->faa_phandle;
         const char *phy_mode;          const char *phy_mode;
         char intrstr[128];          char intrstr[128];
         bus_addr_t addr, grf_addr;          bus_addr_t addr;
         bus_size_t size, grf_size;          bus_size_t size;
         u_int tx_delay, rx_delay;          u_int tx_delay, rx_delay;
   
         if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {          if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
Line 249  rk_gmac_attach(device_t parent, device_t
Line 344  rk_gmac_attach(device_t parent, device_t
                 return;                  return;
         }          }
   
         const int grf_phandle = fdtbus_get_phandle(phandle, "rockchip,grf");          rk_sc->sc_type = of_search_compatible(phandle, compat_data)->data;
         if (grf_phandle == -1) {  
                 aprint_error(": couldn't get grf phandle\n");          rk_sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf");
                 return;          if (rk_sc->sc_syscon == NULL) {
         }                  aprint_error(": couldn't get grf syscon\n");
         if (fdtbus_get_reg(grf_phandle, 0, &grf_addr, &grf_size) != 0) {  
                 aprint_error(": couldn't get grf registers\n");  
                 return;  
         }  
         if (bus_space_map(faa->faa_bst, grf_addr, grf_size, 0, &rk_sc->sc_grf_bsh) != 0) {  
                 aprint_error(": couldn't map grf registers\n");  
                 return;                  return;
         }          }
   
Line 288  rk_gmac_attach(device_t parent, device_t
Line 377  rk_gmac_attach(device_t parent, device_t
         if (rk_gmac_reset(phandle) != 0)          if (rk_gmac_reset(phandle) != 0)
                 aprint_error_dev(self, "PHY reset failed\n");                  aprint_error_dev(self, "PHY reset failed\n");
   
           /* Rock64 seems to need more time for the reset to complete */
           delay(100000);
   
 #if notyet  #if notyet
         if (of_hasprop(phandle, "snps,force_thresh_dma_mode"))          if (of_hasprop(phandle, "snps,force_thresh_dma_mode"))
                 sc->sc_flags |= DWC_GMAC_FORCE_THRESH_DMA_MODE;                  sc->sc_flags |= DWC_GMAC_FORCE_THRESH_DMA_MODE;
Line 299  rk_gmac_attach(device_t parent, device_t
Line 391  rk_gmac_attach(device_t parent, device_t
                 return;                  return;
         }          }
   
         if (strcmp(phy_mode, "rgmii") == 0) {          switch (rk_sc->sc_type) {
                 rk3328_gmac_set_mode_rgmii(sc, tx_delay, rx_delay);          case GMAC_RK3328:
                   if (strcmp(phy_mode, "rgmii") == 0) {
                 sc->sc_set_speed = rk3328_gmac_set_speed_rgmii;                          rk3328_gmac_set_mode_rgmii(sc, tx_delay, rx_delay);
         } else {  
                 aprint_error(": unsupported phy-mode '%s'\n", phy_mode);                          sc->sc_set_speed = rk3328_gmac_set_speed_rgmii;
                 return;                  } else {
                           aprint_error(": unsupported phy-mode '%s'\n", phy_mode);
                           return;
                   }
                   break;
           case GMAC_RK3399:
                   if (strcmp(phy_mode, "rgmii") == 0) {
                           rk3399_gmac_set_mode_rgmii(sc, tx_delay, rx_delay);
   
                           sc->sc_set_speed = rk3399_gmac_set_speed_rgmii;
                   } else {
                           aprint_error(": unsupported phy-mode '%s'\n", phy_mode);
                           return;
                   }
                   break;
         }          }
   
         aprint_naive("\n");          aprint_naive("\n");
         aprint_normal(": GMAC\n");          aprint_normal(": GMAC\n");
   
           if (dwc_gmac_attach(sc, MII_PHY_ANY, GMAC_MII_CLK_150_250M_DIV102) != 0)
                   return;
   
         if (fdtbus_intr_establish(phandle, 0, IPL_NET, 0, rk_gmac_intr, sc) == NULL) {          if (fdtbus_intr_establish(phandle, 0, IPL_NET, 0, rk_gmac_intr, sc) == NULL) {
                 aprint_error_dev(self, "failed to establish interrupt on %s\n", intrstr);                  aprint_error_dev(self, "failed to establish interrupt on %s\n", intrstr);
                 return;                  return;
         }          }
         aprint_normal_dev(self, "interrupting on %s\n", intrstr);          aprint_normal_dev(self, "interrupting on %s\n", intrstr);
   
         dwc_gmac_attach(sc, GMAC_MII_CLK_150_250M_DIV102);  
 }  }
   
 CFATTACH_DECL_NEW(rk_gmac, sizeof(struct rk_gmac_softc),  CFATTACH_DECL_NEW(rk_gmac, sizeof(struct rk_gmac_softc),

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.3.4.1

CVSweb <webmaster@jp.NetBSD.org>