Lines Matching +full:dw +full:- +full:xpcs
1 // SPDX-License-Identifier: GPL-2.0
3 * Synopsys DesignWare XPCS platform device driver
15 #include <linux/pcs/pcs-xpcs.h>
22 #include "pcs-xpcs.h"
62 ret = pm_runtime_resume_and_get(&pxpcs->pdev->dev); in xpcs_mmio_read_reg_indirect()
66 switch (pxpcs->reg_width) { in xpcs_mmio_read_reg_indirect()
68 writel(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 2)); in xpcs_mmio_read_reg_indirect()
69 ret = readl(pxpcs->reg_base + (ofs << 2)); in xpcs_mmio_read_reg_indirect()
72 writew(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 1)); in xpcs_mmio_read_reg_indirect()
73 ret = readw(pxpcs->reg_base + (ofs << 1)); in xpcs_mmio_read_reg_indirect()
77 pm_runtime_put(&pxpcs->pdev->dev); in xpcs_mmio_read_reg_indirect()
93 ret = pm_runtime_resume_and_get(&pxpcs->pdev->dev); in xpcs_mmio_write_reg_indirect()
97 switch (pxpcs->reg_width) { in xpcs_mmio_write_reg_indirect()
99 writel(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 2)); in xpcs_mmio_write_reg_indirect()
100 writel(val, pxpcs->reg_base + (ofs << 2)); in xpcs_mmio_write_reg_indirect()
103 writew(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 1)); in xpcs_mmio_write_reg_indirect()
104 writew(val, pxpcs->reg_base + (ofs << 1)); in xpcs_mmio_write_reg_indirect()
108 pm_runtime_put(&pxpcs->pdev->dev); in xpcs_mmio_write_reg_indirect()
121 ret = pm_runtime_resume_and_get(&pxpcs->pdev->dev); in xpcs_mmio_read_reg_direct()
125 switch (pxpcs->reg_width) { in xpcs_mmio_read_reg_direct()
127 ret = readl(pxpcs->reg_base + (csr << 2)); in xpcs_mmio_read_reg_direct()
130 ret = readw(pxpcs->reg_base + (csr << 1)); in xpcs_mmio_read_reg_direct()
134 pm_runtime_put(&pxpcs->pdev->dev); in xpcs_mmio_read_reg_direct()
147 ret = pm_runtime_resume_and_get(&pxpcs->pdev->dev); in xpcs_mmio_write_reg_direct()
151 switch (pxpcs->reg_width) { in xpcs_mmio_write_reg_direct()
153 writel(val, pxpcs->reg_base + (csr << 2)); in xpcs_mmio_write_reg_direct()
156 writew(val, pxpcs->reg_base + (csr << 1)); in xpcs_mmio_write_reg_direct()
160 pm_runtime_put(&pxpcs->pdev->dev); in xpcs_mmio_write_reg_direct()
167 struct dw_xpcs_plat *pxpcs = bus->priv; in xpcs_mmio_read_c22()
170 return -ENODEV; in xpcs_mmio_read_c22()
172 if (pxpcs->reg_indir) in xpcs_mmio_read_c22()
180 struct dw_xpcs_plat *pxpcs = bus->priv; in xpcs_mmio_write_c22()
183 return -ENODEV; in xpcs_mmio_write_c22()
185 if (pxpcs->reg_indir) in xpcs_mmio_write_c22()
193 struct dw_xpcs_plat *pxpcs = bus->priv; in xpcs_mmio_read_c45()
196 return -ENODEV; in xpcs_mmio_read_c45()
198 if (pxpcs->reg_indir) in xpcs_mmio_read_c45()
207 struct dw_xpcs_plat *pxpcs = bus->priv; in xpcs_mmio_write_c45()
210 return -ENODEV; in xpcs_mmio_write_c45()
212 if (pxpcs->reg_indir) in xpcs_mmio_write_c45()
222 pxpcs = devm_kzalloc(&pdev->dev, sizeof(*pxpcs), GFP_KERNEL); in xpcs_plat_create_data()
224 return ERR_PTR(-ENOMEM); in xpcs_plat_create_data()
226 pxpcs->pdev = pdev; in xpcs_plat_create_data()
228 dev_set_drvdata(&pdev->dev, pxpcs); in xpcs_plat_create_data()
235 struct platform_device *pdev = pxpcs->pdev; in xpcs_plat_init_res()
236 struct device *dev = &pdev->dev; in xpcs_plat_init_res()
240 if (!device_property_read_u32(dev, "reg-io-width", &pxpcs->reg_width)) { in xpcs_plat_init_res()
241 if (pxpcs->reg_width != 2 && pxpcs->reg_width != 4) { in xpcs_plat_init_res()
242 dev_err(dev, "Invalid reg-space data width\n"); in xpcs_plat_init_res()
243 return -EINVAL; in xpcs_plat_init_res()
246 pxpcs->reg_width = 2; in xpcs_plat_init_res()
252 dev_err(dev, "No reg-space found\n"); in xpcs_plat_init_res()
253 return -EINVAL; in xpcs_plat_init_res()
256 if (!strcmp(res->name, "indirect")) in xpcs_plat_init_res()
257 pxpcs->reg_indir = true; in xpcs_plat_init_res()
259 if (pxpcs->reg_indir) in xpcs_plat_init_res()
260 spc_size = pxpcs->reg_width * SZ_256; in xpcs_plat_init_res()
262 spc_size = pxpcs->reg_width * SZ_2M; in xpcs_plat_init_res()
265 dev_err(dev, "Invalid reg-space size\n"); in xpcs_plat_init_res()
266 return -EINVAL; in xpcs_plat_init_res()
269 pxpcs->reg_base = devm_ioremap_resource(dev, res); in xpcs_plat_init_res()
270 if (IS_ERR(pxpcs->reg_base)) { in xpcs_plat_init_res()
271 dev_err(dev, "Failed to map reg-space\n"); in xpcs_plat_init_res()
272 return PTR_ERR(pxpcs->reg_base); in xpcs_plat_init_res()
280 struct device *dev = &pxpcs->pdev->dev; in xpcs_plat_init_clk()
283 pxpcs->cclk = devm_clk_get(dev, "csr"); in xpcs_plat_init_clk()
284 if (IS_ERR(pxpcs->cclk)) in xpcs_plat_init_clk()
285 return dev_err_probe(dev, PTR_ERR(pxpcs->cclk), in xpcs_plat_init_clk()
291 dev_err(dev, "Failed to enable runtime-PM\n"); in xpcs_plat_init_clk()
300 struct device *dev = &pxpcs->pdev->dev; in xpcs_plat_init_bus()
301 static atomic_t id = ATOMIC_INIT(-1); in xpcs_plat_init_bus()
304 pxpcs->bus = devm_mdiobus_alloc_size(dev, 0); in xpcs_plat_init_bus()
305 if (!pxpcs->bus) in xpcs_plat_init_bus()
306 return -ENOMEM; in xpcs_plat_init_bus()
308 pxpcs->bus->name = "DW XPCS MCI/APB3"; in xpcs_plat_init_bus()
309 pxpcs->bus->read = xpcs_mmio_read_c22; in xpcs_plat_init_bus()
310 pxpcs->bus->write = xpcs_mmio_write_c22; in xpcs_plat_init_bus()
311 pxpcs->bus->read_c45 = xpcs_mmio_read_c45; in xpcs_plat_init_bus()
312 pxpcs->bus->write_c45 = xpcs_mmio_write_c45; in xpcs_plat_init_bus()
313 pxpcs->bus->phy_mask = ~0; in xpcs_plat_init_bus()
314 pxpcs->bus->parent = dev; in xpcs_plat_init_bus()
315 pxpcs->bus->priv = pxpcs; in xpcs_plat_init_bus()
317 snprintf(pxpcs->bus->id, MII_BUS_ID_SIZE, in xpcs_plat_init_bus()
318 "dwxpcs-%x", atomic_inc_return(&id)); in xpcs_plat_init_bus()
320 /* MDIO-bus here serves as just a back-end engine abstracting out in xpcs_plat_init_bus()
321 * the MDIO and MCI/APB3 IO interfaces utilized for the DW XPCS CSRs in xpcs_plat_init_bus()
324 ret = devm_mdiobus_register(dev, pxpcs->bus); in xpcs_plat_init_bus()
333 /* Note there is no need in the next function antagonist because the MDIO-bus
334 * de-registration will effectively remove and destroy all the MDIO-devices
339 struct device *dev = &pxpcs->pdev->dev; in xpcs_plat_init_dev()
343 /* There is a single memory-mapped DW XPCS device */ in xpcs_plat_init_dev()
344 mdiodev = mdio_device_create(pxpcs->bus, 0); in xpcs_plat_init_dev()
348 /* Associate the FW-node with the device structure so it can be looked in xpcs_plat_init_dev()
349 * up later. Make sure DD-core is aware of the OF-node being re-used. in xpcs_plat_init_dev()
351 device_set_node(&mdiodev->dev, fwnode_handle_get(dev_fwnode(dev))); in xpcs_plat_init_dev()
352 mdiodev->dev.of_node_reused = true; in xpcs_plat_init_dev()
354 /* Pass the data further so the DW XPCS driver core could use it */ in xpcs_plat_init_dev()
355 mdiodev->dev.platform_data = (void *)device_get_match_data(dev); in xpcs_plat_init_dev()
366 mdiodev->dev.platform_data = NULL; in xpcs_plat_init_dev()
368 fwnode_handle_put(dev_fwnode(&mdiodev->dev)); in xpcs_plat_init_dev()
369 device_set_node(&mdiodev->dev, NULL); in xpcs_plat_init_dev()
408 clk_disable_unprepare(pxpcs->cclk); in xpcs_plat_pm_runtime_suspend()
417 return clk_prepare_enable(pxpcs->cclk); in xpcs_plat_pm_runtime_resume()
436 { .compatible = "snps,dw-xpcs", .data = &xpcs_generic },
437 { .compatible = "snps,dw-xpcs-gen1-3g", .data = &xpcs_pma_gen1_3g },
438 { .compatible = "snps,dw-xpcs-gen2-3g", .data = &xpcs_pma_gen2_3g },
439 { .compatible = "snps,dw-xpcs-gen2-6g", .data = &xpcs_pma_gen2_6g },
440 { .compatible = "snps,dw-xpcs-gen4-3g", .data = &xpcs_pma_gen4_3g },
441 { .compatible = "snps,dw-xpcs-gen4-6g", .data = &xpcs_pma_gen4_6g },
442 { .compatible = "snps,dw-xpcs-gen5-10g", .data = &xpcs_pma_gen5_10g },
443 { .compatible = "snps,dw-xpcs-gen5-12g", .data = &xpcs_pma_gen5_12g },
458 MODULE_DESCRIPTION("Synopsys DesignWare XPCS platform device driver");
459 MODULE_AUTHOR("Signed-off-by: Serge Semin <fancer.lancer@gmail.com>");