Until now, the MDIO bus will have the hardware default bus frequency. Read the desired frequency of the bus from the device tree and configure it.
Unified · Split
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/bitops.h> | 9 | #include <linux/bitops.h> |
| 10 | #include <linux/clk.h> | ||
| 10 | #include <linux/io.h> | 11 | #include <linux/io.h> |
| 11 | #include <linux/iopoll.h> | 12 | #include <linux/iopoll.h> |
| 12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| @@ -30,6 +31,8 @@ · 17 unmodified lines | |||
| 30 | #define MSCC_MIIM_CMD_VLD BIT(31) | 31 | #define MSCC_MIIM_CMD_VLD BIT(31) |
| 31 | #define MSCC_MIIM_REG_DATA 0xC | 32 | #define MSCC_MIIM_REG_DATA 0xC |
| 32 | #define MSCC_MIIM_DATA_ERROR (BIT(16) | BIT(17)) | 33 | #define MSCC_MIIM_DATA_ERROR (BIT(16) | BIT(17)) |
| 34 | #define MSCC_MIIM_REG_CFG 0x10 | ||
| 35 | #define MSCC_MIIM_CFG_PRESCALE_MASK GENMASK(7, 0) | ||
| 33 | 36 | ||
| 34 | #define MSCC_PHY_REG_PHY_CFG 0x0 | 37 | #define MSCC_PHY_REG_PHY_CFG 0x0 |
| 35 | #define PHY_CFG_PHY_ENA (BIT(0) | BIT(1) | BIT(2) | BIT(3)) | 38 | #define PHY_CFG_PHY_ENA (BIT(0) | BIT(1) | BIT(2) | BIT(3)) |
| @@ -50,6 +53,8 @@ struct mscc_miim_dev { · 14 unmodified lines | |||
| 50 | int mii_status_offset; | 53 | int mii_status_offset; |
| 51 | struct regmap *phy_regs; | 54 | struct regmap *phy_regs; |
| 52 | const struct mscc_miim_info *info; | 55 | const struct mscc_miim_info *info; |
| 56 | struct clk *clk; | ||
| 57 | u32 bus_freq; | ||
| 53 | }; | 58 | }; |
| 54 | 59 | ||
| 55 | /* When high resolution timers aren't built-in: we can't use usleep_range() as | 60 | /* When high resolution timers aren't built-in: we can't use usleep_range() as |
| @@ -235,9 +240,32 @@ int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, const char *name, · 179 unmodified lines | |||
| 235 | } | 240 | } |
| 236 | EXPORT_SYMBOL(mscc_miim_setup); | 241 | EXPORT_SYMBOL(mscc_miim_setup); |
| 237 | 242 | ||
| 243 | static int mscc_miim_clk_set(struct mii_bus *bus) | ||
| 244 | { | ||
| 245 | struct mscc_miim_dev *miim = bus->priv; | ||
| 246 | unsigned long rate; | ||
| 247 | u32 div; | ||
| 248 | |||
| 249 | /* Keep the current settings */ | ||
| 250 | if (!miim->bus_freq) | ||
| 251 | return 0; | ||
| 252 | |||
| 253 | rate = clk_get_rate(miim->clk); | ||
| 254 | |||
| 255 | div = DIV_ROUND_UP(rate, 2 * miim->bus_freq) - 1; | ||
| 256 | if (div == 0 || div & ~MSCC_MIIM_CFG_PRESCALE_MASK) { | ||
| 257 | dev_err(&bus->dev, "Incorrect MDIO clock frequency\n"); | ||
| 258 | return -EINVAL; | ||
| 259 | } | ||
| 260 | |||
| 261 | return regmap_update_bits(miim->regs, MSCC_MIIM_REG_CFG, | ||
| 262 | MSCC_MIIM_CFG_PRESCALE_MASK, div); | ||
| 263 | } | ||
| 264 | |||
| 238 | static int mscc_miim_probe(struct platform_device *pdev) | 265 | static int mscc_miim_probe(struct platform_device *pdev) |
| 239 | { | 266 | { |
| 240 | struct regmap *mii_regmap, *phy_regmap = NULL; | 267 | struct regmap *mii_regmap, *phy_regmap = NULL; |
| 268 | struct device_node *np = pdev->dev.of_node; | ||
| 241 | void __iomem *regs, *phy_regs; | 269 | void __iomem *regs, *phy_regs; |
| 242 | struct mscc_miim_dev *miim; | 270 | struct mscc_miim_dev *miim; |
| 243 | struct resource *res; | 271 | struct resource *res; |
| @@ -288,21 +316,47 @@ static int mscc_miim_probe(struct platform_device *pdev) · 44 unmodified lines | |||
| 288 | if (!miim->info) | 316 | if (!miim->info) |
| 289 | return -EINVAL; | 317 | return -EINVAL; |
| 290 | 318 | ||
| 291 | ret = of_mdiobus_register(bus, pdev->dev.of_node); | 319 | miim->clk = devm_clk_get_optional(&pdev->dev, NULL); |
| 320 | if (IS_ERR(miim->clk)) | ||
| 321 | return PTR_ERR(miim->clk); | ||
| 322 | |||
| 323 | of_property_read_u32(np, "clock-frequency", &miim->bus_freq); | ||
| 324 | |||
| 325 | if (miim->bus_freq && !miim->clk) { | ||
| 326 | dev_err(&pdev->dev, | ||
| 327 | "cannot use clock-frequency without a clock\n"); | ||
| 328 | return -EINVAL; | ||
| 329 | } | ||
| 330 | |||
| 331 | ret = clk_prepare_enable(miim->clk); | ||
| 332 | if (ret) | ||
| 333 | return ret; | ||
| 334 | |||
| 335 | ret = mscc_miim_clk_set(bus); | ||
| 336 | if (ret) | ||
| 337 | goto out_disable_clk; | ||
| 338 | |||
| 339 | ret = of_mdiobus_register(bus, np); | ||
| 292 | if (ret < 0) { | 340 | if (ret < 0) { |
| 293 | dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); | 341 | dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); |
| 294 | return ret; | 342 | goto out_disable_clk; |
| 295 | } | 343 | } |
| 296 | 344 | ||
| 297 | platform_set_drvdata(pdev, bus); | 345 | platform_set_drvdata(pdev, bus); |
| 298 | 346 | ||
| 299 | return 0; | 347 | return 0; |
| 348 | |||
| 349 | out_disable_clk: | ||
| 350 | clk_disable_unprepare(miim->clk); | ||
| 351 | return ret; | ||
| 300 | } | 352 | } |
| 301 | 353 | ||
| 302 | static int mscc_miim_remove(struct platform_device *pdev) | 354 | static int mscc_miim_remove(struct platform_device *pdev) |
| 303 | { | 355 | { |
| 304 | struct mii_bus *bus = platform_get_drvdata(pdev); | 356 | struct mii_bus *bus = platform_get_drvdata(pdev); |
| 357 | struct mscc_miim_dev *miim = bus->priv; | ||
| 305 | 358 | ||
| 359 | clk_disable_unprepare(miim->clk); | ||
| 306 | mdiobus_unregister(bus); | 360 | mdiobus_unregister(bus); |
| 307 | 361 | ||
| 308 | return 0; | 362 | return 0; |