Commit 3e24a65f authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'stmmac-cleanup'

Joachim Eastwood says:

====================
stmmac clean up for 4.3 part2

This patch set creates proper probe functions in the remaining
dwmac-* drivers, lets the drivers manage their own of match data
structure, and cleans up some of the drivers a bit. Note that
should be no functional change in any of the drivers.

First patch from Fengguang fixes a Coccinelle that was found after
the previous patch set when into next.

Probe functions are best placed just above the platform_driver
struct since it usually needs to call other functions in the
driver but this requires some code movement in the drivers. To
keep the conversion itself easier to review the code movement is
done in separate patches. This creates some extra churn but I
think it's worth it in this case.

As only a couple of drivers actually needs to use of match data
this pushed down from stmmac_platform and into the drivers. This
also makes it possible for drivers to have their own match data
structure. dwmac-rk benefits most from this.

After each driver has it's own probe function and manages it's
own match data the setup/free hooks and common match data struct
are removed.

Sorry for the slightly largish patch set this time around.

Since I can only test the core changes on my platform and not the
specific dwmac-drivers I greatly appreciate if people could test
this on their respective platforms. I did spend quite a bit of
time visually checking all these patches, but nothing beats real
hardware testing. Thanks!

Patch set based on net-next can also be picked up from here:
https://github.com/manabian/linux-lpc.git stmmac_4.3_part2

For those who want to have a look at all the patches for
v4.3 a branch based on Linus master can be found here:
https://github.com/manabian/linux-lpc.git stmmac_4.2

Previous parts can be found here:
http://www.spinics.net/lists/netdev/msg328997.html
http://www.spinics.net/lists/netdev/msg329932.html
http://www.spinics.net/lists/netdev/msg336097.html


====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6d85d0e3 16b1adbb
......@@ -135,8 +135,6 @@ struct plat_stmmacenet_data {
int maxmtu;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
void *(*setup)(struct platform_device *pdev);
void (*free)(struct platform_device *pdev, void *priv);
int (*init)(struct platform_device *pdev, void *priv);
void (*exit)(struct platform_device *pdev, void *priv);
void *bsp_priv;
......@@ -177,12 +175,10 @@ Where:
o bus_setup: perform HW setup of the bus. For example, on some ST platforms
this field is used to configure the AMBA bridge to generate more
efficient STBus traffic.
o setup/init/exit: callbacks used for calling a custom initialization;
o init/exit: callbacks used for calling a custom initialization;
this is sometime necessary on some platforms (e.g. ST boxes)
where the HW needs to have set some PIO lines or system cfg
registers. setup should return a pointer to private data,
which will be stored in bsp_priv, and then passed to init and
exit callbacks. init/exit callbacks should not use or modify
registers. init/exit callbacks should not use or modify
platform data.
o bsp_priv: another private pointer.
......@@ -274,8 +270,6 @@ capability register can replace what has been passed from the platform.
Please see the following document:
Documentation/devicetree/bindings/net/stmmac.txt
and the stmmac_of_data structure inside the include/linux/stmmac.h header file.
4.11) This is a summary of the content of some relevant files:
o stmmac_main.c: to implement the main network device driver;
o stmmac_mdio.c: to provide mdio functions;
......
......@@ -16,6 +16,46 @@
#include "stmmac.h"
#include "stmmac_platform.h"
static int dwmac_generic_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
int ret;
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
return ret;
if (pdev->dev.of_node) {
plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
if (IS_ERR(plat_dat)) {
dev_err(&pdev->dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
} else {
plat_dat = dev_get_platdata(&pdev->dev);
if (!plat_dat) {
dev_err(&pdev->dev, "no platform data provided\n");
return -EINVAL;
}
/* Set default value for multicast hash bins */
plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
/* Set default value for unicast filter entries */
plat_dat->unicast_filter_entries = 1;
}
/* Custom initialisation (if needed) */
if (plat_dat->init) {
ret = plat_dat->init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
}
return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
}
static const struct of_device_id dwmac_generic_match[] = {
{ .compatible = "st,spear600-gmac"},
{ .compatible = "snps,dwmac-3.610"},
......@@ -27,7 +67,7 @@ static const struct of_device_id dwmac_generic_match[] = {
MODULE_DEVICE_TABLE(of, dwmac_generic_match);
static struct platform_driver dwmac_generic_driver = {
.probe = stmmac_pltfr_probe,
.probe = dwmac_generic_probe,
.remove = stmmac_pltfr_remove,
.driver = {
.name = STMMAC_RESOURCE_NAME,
......
......@@ -248,23 +248,40 @@ static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
return NULL;
}
static void *ipq806x_gmac_setup(struct platform_device *pdev)
static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
{
struct ipq806x_gmac *gmac = priv;
ipq806x_gmac_set_speed(gmac, speed);
}
static int ipq806x_gmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
struct device *dev = &pdev->dev;
struct ipq806x_gmac *gmac;
int val;
void *err;
val = stmmac_get_platform_resources(pdev, &stmmac_res);
if (val)
return val;
plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
if (IS_ERR(plat_dat))
return PTR_ERR(plat_dat);
gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
if (!gmac)
return ERR_PTR(-ENOMEM);
return -ENOMEM;
gmac->pdev = pdev;
err = ipq806x_gmac_of_parse(gmac);
if (err) {
if (IS_ERR(err)) {
dev_err(dev, "device tree parsing error\n");
return err;
return PTR_ERR(err);
}
regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
......@@ -285,7 +302,7 @@ static void *ipq806x_gmac_setup(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
phy_modes(gmac->phy_mode));
return NULL;
return -EINVAL;
}
regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
......@@ -304,7 +321,7 @@ static void *ipq806x_gmac_setup(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
phy_modes(gmac->phy_mode));
return NULL;
return -EINVAL;
}
regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
......@@ -327,30 +344,21 @@ static void *ipq806x_gmac_setup(struct platform_device *pdev)
0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
}
return gmac;
}
plat_dat->has_gmac = true;
plat_dat->bsp_priv = gmac;
plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
{
struct ipq806x_gmac *gmac = priv;
ipq806x_gmac_set_speed(gmac, speed);
return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
}
static const struct stmmac_of_data ipq806x_gmac_data = {
.has_gmac = 1,
.setup = ipq806x_gmac_setup,
.fix_mac_speed = ipq806x_gmac_fix_mac_speed,
};
static const struct of_device_id ipq806x_gmac_dwmac_match[] = {
{ .compatible = "qcom,ipq806x-gmac", .data = &ipq806x_gmac_data },
{ .compatible = "qcom,ipq806x-gmac" },
{ }
};
MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match);
static struct platform_driver ipq806x_gmac_dwmac_driver = {
.probe = stmmac_pltfr_probe,
.probe = ipq806x_gmac_probe,
.remove = stmmac_pltfr_remove,
.driver = {
.name = "ipq806x-gmac-dwmac",
......
......@@ -46,7 +46,7 @@ struct rk_priv_data {
struct platform_device *pdev;
int phy_iface;
struct regulator *regulator;
struct rk_gmac_ops *ops;
const struct rk_gmac_ops *ops;
bool clk_enabled;
bool clock_input;
......@@ -177,7 +177,7 @@ static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
}
}
struct rk_gmac_ops rk3288_ops = {
static const struct rk_gmac_ops rk3288_ops = {
.set_to_rgmii = rk3288_set_to_rgmii,
.set_to_rmii = rk3288_set_to_rmii,
.set_rgmii_speed = rk3288_set_rgmii_speed,
......@@ -289,7 +289,7 @@ static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
}
}
struct rk_gmac_ops rk3368_ops = {
static const struct rk_gmac_ops rk3368_ops = {
.set_to_rgmii = rk3368_set_to_rgmii,
.set_to_rmii = rk3368_set_to_rmii,
.set_rgmii_speed = rk3368_set_rgmii_speed,
......@@ -448,7 +448,7 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
}
static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
struct rk_gmac_ops *ops)
const struct rk_gmac_ops *ops)
{
struct rk_priv_data *bsp_priv;
struct device *dev = &pdev->dev;
......@@ -529,16 +529,6 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
return bsp_priv;
}
static void *rk3288_gmac_setup(struct platform_device *pdev)
{
return rk_gmac_setup(pdev, &rk3288_ops);
}
static void *rk3368_gmac_setup(struct platform_device *pdev)
{
return rk_gmac_setup(pdev, &rk3368_ops);
}
static int rk_gmac_init(struct platform_device *pdev, void *priv)
{
struct rk_priv_data *bsp_priv = priv;
......@@ -576,31 +566,52 @@ static void rk_fix_speed(void *priv, unsigned int speed)
dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
}
static const struct stmmac_of_data rk3288_gmac_data = {
.has_gmac = 1,
.fix_mac_speed = rk_fix_speed,
.setup = rk3288_gmac_setup,
.init = rk_gmac_init,
.exit = rk_gmac_exit,
};
static int rk_gmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
const struct rk_gmac_ops *data;
int ret;
static const struct stmmac_of_data rk3368_gmac_data = {
.has_gmac = 1,
.fix_mac_speed = rk_fix_speed,
.setup = rk3368_gmac_setup,
.init = rk_gmac_init,
.exit = rk_gmac_exit,
};
data = of_device_get_match_data(&pdev->dev);
if (!data) {
dev_err(&pdev->dev, "no of match data provided\n");
return -EINVAL;
}
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
return ret;
plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
if (IS_ERR(plat_dat))
return PTR_ERR(plat_dat);
plat_dat->has_gmac = true;
plat_dat->init = rk_gmac_init;
plat_dat->exit = rk_gmac_exit;
plat_dat->fix_mac_speed = rk_fix_speed;
plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
if (IS_ERR(plat_dat->bsp_priv))
return PTR_ERR(plat_dat->bsp_priv);
ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
}
static const struct of_device_id rk_gmac_dwmac_match[] = {
{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_gmac_data},
{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_gmac_data},
{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
{ }
};
MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
static struct platform_driver rk_gmac_dwmac_driver = {
.probe = stmmac_pltfr_probe,
.probe = rk_gmac_probe,
.remove = stmmac_pltfr_remove,
.driver = {
.name = "rk_gmac-dwmac",
......
......@@ -175,31 +175,6 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
return 0;
}
static void *socfpga_dwmac_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
struct socfpga_dwmac *dwmac;
dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return ERR_PTR(-ENOMEM);
ret = socfpga_dwmac_parse_data(dwmac, dev);
if (ret) {
dev_err(dev, "Unable to parse OF data\n");
return ERR_PTR(ret);
}
ret = socfpga_dwmac_setup(dwmac);
if (ret) {
dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
return ERR_PTR(ret);
}
return dwmac;
}
static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv)
{
struct socfpga_dwmac *dwmac = priv;
......@@ -257,21 +232,58 @@ static int socfpga_dwmac_init(struct platform_device *pdev, void *priv)
return ret;
}
static const struct stmmac_of_data socfpga_gmac_data = {
.setup = socfpga_dwmac_probe,
.init = socfpga_dwmac_init,
.exit = socfpga_dwmac_exit,
.fix_mac_speed = socfpga_dwmac_fix_mac_speed,
};
static int socfpga_dwmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
struct device *dev = &pdev->dev;
int ret;
struct socfpga_dwmac *dwmac;
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
return ret;
plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
if (IS_ERR(plat_dat))
return PTR_ERR(plat_dat);
dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return -ENOMEM;
ret = socfpga_dwmac_parse_data(dwmac, dev);
if (ret) {
dev_err(dev, "Unable to parse OF data\n");
return ret;
}
ret = socfpga_dwmac_setup(dwmac);
if (ret) {
dev_err(dev, "couldn't setup SoC glue (%d)\n", ret);
return ret;
}
plat_dat->bsp_priv = dwmac;
plat_dat->init = socfpga_dwmac_init;
plat_dat->exit = socfpga_dwmac_exit;
plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
ret = socfpga_dwmac_init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
}
static const struct of_device_id socfpga_dwmac_match[] = {
{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
{ .compatible = "altr,socfpga-stmmac" },
{ }
};
MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
static struct platform_driver socfpga_dwmac_driver = {
.probe = stmmac_pltfr_probe,
.probe = socfpga_dwmac_probe,
.remove = stmmac_pltfr_remove,
.driver = {
.name = "socfpga-dwmac",
......
......@@ -21,6 +21,7 @@
#include <linux/regmap.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_net.h>
#include "stmmac_platform.h"
......@@ -128,6 +129,11 @@ struct sti_dwmac {
struct device *dev;
struct regmap *regmap;
u32 speed;
void (*fix_retime_src)(void *priv, unsigned int speed);
};
struct sti_dwmac_of_data {
void (*fix_retime_src)(void *priv, unsigned int speed);
};
static u32 phy_intf_sels[] = {
......@@ -222,8 +228,9 @@ static void stid127_fix_retime_src(void *priv, u32 spd)
regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val);
}
static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac)
static int sti_dwmac_init(struct platform_device *pdev, void *priv)
{
struct sti_dwmac *dwmac = priv;
struct regmap *regmap = dwmac->regmap;
int iface = dwmac->interface;
struct device *dev = dwmac->dev;
......@@ -241,28 +248,8 @@ static void sti_dwmac_ctrl_init(struct sti_dwmac *dwmac)
val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
regmap_update_bits(regmap, reg, ENMII_MASK, val);
}
static int stix4xx_init(struct platform_device *pdev, void *priv)
{
struct sti_dwmac *dwmac = priv;
u32 spd = dwmac->speed;
sti_dwmac_ctrl_init(dwmac);
stih4xx_fix_retime_src(priv, spd);
return 0;
}
static int stid127_init(struct platform_device *pdev, void *priv)
{
struct sti_dwmac *dwmac = priv;
u32 spd = dwmac->speed;
sti_dwmac_ctrl_init(dwmac);
stid127_fix_retime_src(priv, spd);
dwmac->fix_retime_src(priv, dwmac->speed);
return 0;
}
......@@ -334,36 +321,58 @@ static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
return 0;
}
static void *sti_dwmac_setup(struct platform_device *pdev)
static int sti_dwmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
const struct sti_dwmac_of_data *data;
struct stmmac_resources stmmac_res;
struct sti_dwmac *dwmac;
int ret;
data = of_device_get_match_data(&pdev->dev);
if (!data) {
dev_err(&pdev->dev, "No OF match data provided\n");
return -EINVAL;
}
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
return ret;
plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
if (IS_ERR(plat_dat))
return PTR_ERR(plat_dat);
dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
if (!dwmac)
return ERR_PTR(-ENOMEM);
return -ENOMEM;
ret = sti_dwmac_parse_data(dwmac, pdev);
if (ret) {
dev_err(&pdev->dev, "Unable to parse OF data\n");
return ERR_PTR(ret);
return ret;
}
return dwmac;
dwmac->fix_retime_src = data->fix_retime_src;
plat_dat->bsp_priv = dwmac;
plat_dat->init = sti_dwmac_init;
plat_dat->exit = sti_dwmac_exit;
plat_dat->fix_mac_speed = data->fix_retime_src;
ret = sti_dwmac_init(pdev, plat_dat->bsp_priv);
if (ret)
return ret;
return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
}
static const struct stmmac_of_data stih4xx_dwmac_data = {
.fix_mac_speed = stih4xx_fix_retime_src,
.setup = sti_dwmac_setup,
.init = stix4xx_init,
.exit = sti_dwmac_exit,
static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
.fix_retime_src = stih4xx_fix_retime_src,
};
static const struct stmmac_of_data stid127_dwmac_data = {
.fix_mac_speed = stid127_fix_retime_src,
.setup = sti_dwmac_setup,
.init = stid127_init,
.exit = sti_dwmac_exit,
static const struct sti_dwmac_of_data stid127_dwmac_data = {
.fix_retime_src = stid127_fix_retime_src,
};
static const struct of_device_id sti_dwmac_match[] = {
......@@ -376,7 +385,7 @@ static const struct of_device_id sti_dwmac_match[] = {
MODULE_DEVICE_TABLE(of, sti_dwmac_match);
static struct platform_driver sti_dwmac_driver = {
.probe = stmmac_pltfr_probe,
.probe = sti_dwmac_probe,
.remove = stmmac_pltfr_remove,
.driver = {
.name = "sti-dwmac",
......
......@@ -33,35 +33,6 @@ struct sunxi_priv_data {
struct regulator *regulator;
};
static void *sun7i_gmac_setup(struct platform_device *pdev)
{
struct sunxi_priv_data *gmac;
struct device *dev = &pdev->dev;
gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
if (!gmac)
return ERR_PTR(-ENOMEM);
gmac->interface = of_get_phy_mode(dev->of_node);
gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
if (IS_ERR(gmac->tx_clk)) {
dev_err(dev, "could not get tx clock\n");
return gmac->tx_clk;
}
/* Optional regulator for PHY */
gmac->regulator = devm_regulator_get_optional(dev, "phy");
if (IS_ERR(gmac->regulator)) {
if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER);
dev_info(dev, "no regulator found\n");
gmac->regulator = NULL;
}
return gmac;
}
#define SUN7I_GMAC_GMII_RGMII_RATE 125000000
#define SUN7I_GMAC_MII_RATE 25000000
......@@ -132,25 +103,67 @@ static void sun7i_fix_speed(void *priv, unsigned int speed)
}
}
/* of_data specifying hardware features and callbacks.
* hardware features were copied from Allwinner drivers. */
static const struct stmmac_of_data sun7i_gmac_data = {
.has_gmac = 1,
.tx_coe = 1,
.fix_mac_speed = sun7i_fix_speed,
.setup = sun7i_gmac_setup,
.init = sun7i_gmac_init,
.exit = sun7i_gmac_exit,