diff options
author | Igal Liberman <igal.liberman@freescale.com> | 2016-03-21 17:08:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-22 15:58:05 -0400 |
commit | 6e9bdc7271ac8e2af58a2c9a87551d9bd49337a1 (patch) | |
tree | e6de1e304c14b71f150b377f44383b0cac11cf0a | |
parent | ad0ea1989cc4d5905941d0a9e62c63ad6d859cef (diff) |
fsl/fman: Workaround for Errata A-007273
Errata A-007273 (For FMan V3 devices only):
FMan soft reset is not finished properly if one
of the Ethernet MAC clocks is disabled
Workaround:
Re-enable all disabled MAC clocks through the DCFG_CCSR_DEVDISR2
register prior to issuing an FMAN soft reset.
Re-disable the MAC clocks after the FMAN soft reset is done.
Signed-off-by: Igal Liberman <igal.liberman@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/freescale/fman/fman.c | 104 |
1 files changed, 88 insertions, 16 deletions
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c index 79a210aaf0bb..ea83712a6d62 100644 --- a/drivers/net/ethernet/freescale/fman/fman.c +++ b/drivers/net/ethernet/freescale/fman/fman.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "fman.h" | 35 | #include "fman.h" |
36 | #include "fman_muram.h" | 36 | #include "fman_muram.h" |
37 | 37 | ||
38 | #include <linux/fsl/guts.h> | ||
38 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
39 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
40 | #include <linux/module.h> | 41 | #include <linux/module.h> |
@@ -1871,6 +1872,90 @@ err_fm_state: | |||
1871 | return -EINVAL; | 1872 | return -EINVAL; |
1872 | } | 1873 | } |
1873 | 1874 | ||
1875 | static int fman_reset(struct fman *fman) | ||
1876 | { | ||
1877 | u32 count; | ||
1878 | int err = 0; | ||
1879 | |||
1880 | if (fman->state->rev_info.major < 6) { | ||
1881 | iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc); | ||
1882 | /* Wait for reset completion */ | ||
1883 | count = 100; | ||
1884 | do { | ||
1885 | udelay(1); | ||
1886 | } while (((ioread32be(&fman->fpm_regs->fm_rstc)) & | ||
1887 | FPM_RSTC_FM_RESET) && --count); | ||
1888 | if (count == 0) | ||
1889 | err = -EBUSY; | ||
1890 | |||
1891 | goto _return; | ||
1892 | } else { | ||
1893 | struct device_node *guts_node; | ||
1894 | struct ccsr_guts __iomem *guts_regs; | ||
1895 | u32 devdisr2, reg; | ||
1896 | |||
1897 | /* Errata A007273 */ | ||
1898 | guts_node = | ||
1899 | of_find_compatible_node(NULL, NULL, | ||
1900 | "fsl,qoriq-device-config-2.0"); | ||
1901 | if (!guts_node) { | ||
1902 | dev_err(fman->dev, "%s: Couldn't find guts node\n", | ||
1903 | __func__); | ||
1904 | goto guts_node; | ||
1905 | } | ||
1906 | |||
1907 | guts_regs = of_iomap(guts_node, 0); | ||
1908 | if (!guts_regs) { | ||
1909 | dev_err(fman->dev, "%s: Couldn't map %s regs\n", | ||
1910 | __func__, guts_node->full_name); | ||
1911 | goto guts_regs; | ||
1912 | } | ||
1913 | #define FMAN1_ALL_MACS_MASK 0xFCC00000 | ||
1914 | #define FMAN2_ALL_MACS_MASK 0x000FCC00 | ||
1915 | /* Read current state */ | ||
1916 | devdisr2 = ioread32be(&guts_regs->devdisr2); | ||
1917 | if (fman->dts_params.id == 0) | ||
1918 | reg = devdisr2 & ~FMAN1_ALL_MACS_MASK; | ||
1919 | else | ||
1920 | reg = devdisr2 & ~FMAN2_ALL_MACS_MASK; | ||
1921 | |||
1922 | /* Enable all MACs */ | ||
1923 | iowrite32be(reg, &guts_regs->devdisr2); | ||
1924 | |||
1925 | /* Perform FMan reset */ | ||
1926 | iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc); | ||
1927 | |||
1928 | /* Wait for reset completion */ | ||
1929 | count = 100; | ||
1930 | do { | ||
1931 | udelay(1); | ||
1932 | } while (((ioread32be(&fman->fpm_regs->fm_rstc)) & | ||
1933 | FPM_RSTC_FM_RESET) && --count); | ||
1934 | if (count == 0) { | ||
1935 | iounmap(guts_regs); | ||
1936 | of_node_put(guts_node); | ||
1937 | err = -EBUSY; | ||
1938 | goto _return; | ||
1939 | } | ||
1940 | |||
1941 | /* Restore devdisr2 value */ | ||
1942 | iowrite32be(devdisr2, &guts_regs->devdisr2); | ||
1943 | |||
1944 | iounmap(guts_regs); | ||
1945 | of_node_put(guts_node); | ||
1946 | |||
1947 | goto _return; | ||
1948 | |||
1949 | guts_regs: | ||
1950 | of_node_put(guts_node); | ||
1951 | guts_node: | ||
1952 | dev_dbg(fman->dev, "%s: Didn't perform FManV3 reset due to Errata A007273!\n", | ||
1953 | __func__); | ||
1954 | } | ||
1955 | _return: | ||
1956 | return err; | ||
1957 | } | ||
1958 | |||
1874 | static int fman_init(struct fman *fman) | 1959 | static int fman_init(struct fman *fman) |
1875 | { | 1960 | { |
1876 | struct fman_cfg *cfg = NULL; | 1961 | struct fman_cfg *cfg = NULL; |
@@ -1914,22 +1999,9 @@ static int fman_init(struct fman *fman) | |||
1914 | fman->liodn_base[i] = liodn_base; | 1999 | fman->liodn_base[i] = liodn_base; |
1915 | } | 2000 | } |
1916 | 2001 | ||
1917 | /* FMan Reset (supported only for FMan V2) */ | 2002 | err = fman_reset(fman); |
1918 | if (fman->state->rev_info.major >= 6) { | 2003 | if (err) |
1919 | /* Errata A007273 */ | 2004 | return err; |
1920 | dev_dbg(fman->dev, "%s: FManV3 reset is not supported!\n", | ||
1921 | __func__); | ||
1922 | } else { | ||
1923 | iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc); | ||
1924 | /* Wait for reset completion */ | ||
1925 | count = 100; | ||
1926 | do { | ||
1927 | udelay(1); | ||
1928 | } while (((ioread32be(&fman->fpm_regs->fm_rstc)) & | ||
1929 | FPM_RSTC_FM_RESET) && --count); | ||
1930 | if (count == 0) | ||
1931 | return -EBUSY; | ||
1932 | } | ||
1933 | 2005 | ||
1934 | if (ioread32be(&fman->qmi_regs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY) { | 2006 | if (ioread32be(&fman->qmi_regs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY) { |
1935 | resume(fman->fpm_regs); | 2007 | resume(fman->fpm_regs); |