brintos

brintos / linux-shallow public Read only

0
0
Text · 15.6 KiB · 8a04714 Raw
653 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2014-2015 Hisilicon Limited.4 */5 6#include <linux/acpi.h>7#include <linux/errno.h>8#include <linux/etherdevice.h>9#include <linux/init.h>10#include <linux/kernel.h>11#include <linux/mfd/syscon.h>12#include <linux/module.h>13#include <linux/mutex.h>14#include <linux/netdevice.h>15#include <linux/of_address.h>16#include <linux/of.h>17#include <linux/of_mdio.h>18#include <linux/of_platform.h>19#include <linux/phy.h>20#include <linux/platform_device.h>21#include <linux/regmap.h>22 23#define MDIO_DRV_NAME "Hi-HNS_MDIO"24#define MDIO_BUS_NAME "Hisilicon MII Bus"25 26#define MDIO_TIMEOUT			100000027 28struct hns_mdio_sc_reg {29	u16 mdio_clk_en;30	u16 mdio_clk_dis;31	u16 mdio_reset_req;32	u16 mdio_reset_dreq;33	u16 mdio_clk_st;34	u16 mdio_reset_st;35};36 37struct hns_mdio_device {38	u8 __iomem *vbase;		/* mdio reg base address */39	struct regmap *subctrl_vbase;40	struct hns_mdio_sc_reg sc_reg;41};42 43/* mdio reg */44#define MDIO_COMMAND_REG		0x045#define MDIO_ADDR_REG			0x446#define MDIO_WDATA_REG			0x847#define MDIO_RDATA_REG			0xc48#define MDIO_STA_REG			0x1049 50/* cfg phy bit map */51#define MDIO_CMD_DEVAD_M	0x1f52#define MDIO_CMD_DEVAD_S	053#define MDIO_CMD_PRTAD_M	0x1f54#define MDIO_CMD_PRTAD_S	555#define MDIO_CMD_OP_S		1056#define MDIO_CMD_ST_S		1257#define MDIO_CMD_START_B	1458 59#define MDIO_ADDR_DATA_M	0xffff60#define MDIO_ADDR_DATA_S	061 62#define MDIO_WDATA_DATA_M	0xffff63#define MDIO_WDATA_DATA_S	064 65#define MDIO_RDATA_DATA_M	0xffff66#define MDIO_RDATA_DATA_S	067 68#define MDIO_STATE_STA_B	069 70enum mdio_st_clause {71	MDIO_ST_CLAUSE_45 = 0,72	MDIO_ST_CLAUSE_2273};74 75enum mdio_c22_op_seq {76	MDIO_C22_WRITE = 1,77	MDIO_C22_READ = 278};79 80enum mdio_c45_op_seq {81	MDIO_C45_WRITE_ADDR = 0,82	MDIO_C45_WRITE_DATA,83	MDIO_C45_READ_INCREMENT,84	MDIO_C45_READ85};86 87/* peri subctrl reg */88#define MDIO_SC_CLK_EN		0x33889#define MDIO_SC_CLK_DIS		0x33C90#define MDIO_SC_RESET_REQ	0xA3891#define MDIO_SC_RESET_DREQ	0xA3C92#define MDIO_SC_CLK_ST		0x531C93#define MDIO_SC_RESET_ST	0x5A1C94 95static void mdio_write_reg(u8 __iomem *base, u32 reg, u32 value)96{97	writel_relaxed(value, base + reg);98}99 100#define MDIO_WRITE_REG(a, reg, value) \101	mdio_write_reg((a)->vbase, (reg), (value))102 103static u32 mdio_read_reg(u8 __iomem *base, u32 reg)104{105	return readl_relaxed(base + reg);106}107 108#define mdio_set_field(origin, mask, shift, val) \109	do { \110		(origin) &= (~((mask) << (shift))); \111		(origin) |= (((val) & (mask)) << (shift)); \112	} while (0)113 114#define mdio_get_field(origin, mask, shift) (((origin) >> (shift)) & (mask))115 116static void mdio_set_reg_field(u8 __iomem *base, u32 reg, u32 mask, u32 shift,117			       u32 val)118{119	u32 origin = mdio_read_reg(base, reg);120 121	mdio_set_field(origin, mask, shift, val);122	mdio_write_reg(base, reg, origin);123}124 125#define MDIO_SET_REG_FIELD(dev, reg, mask, shift, val) \126	mdio_set_reg_field((dev)->vbase, (reg), (mask), (shift), (val))127 128static u32 mdio_get_reg_field(u8 __iomem *base, u32 reg, u32 mask, u32 shift)129{130	u32 origin;131 132	origin = mdio_read_reg(base, reg);133	return mdio_get_field(origin, mask, shift);134}135 136#define MDIO_GET_REG_FIELD(dev, reg, mask, shift) \137		mdio_get_reg_field((dev)->vbase, (reg), (mask), (shift))138 139#define MDIO_GET_REG_BIT(dev, reg, bit) \140		mdio_get_reg_field((dev)->vbase, (reg), 0x1ull, (bit))141 142#define MDIO_CHECK_SET_ST	1143#define MDIO_CHECK_CLR_ST	0144 145static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev,146				 u32 cfg_reg, u32 set_val,147				 u32 st_reg, u32 st_msk, u8 check_st)148{149	u32 time_cnt;150	u32 reg_value;151	int ret;152 153	regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val);154 155	for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) {156		ret = regmap_read(mdio_dev->subctrl_vbase, st_reg, &reg_value);157		if (ret)158			return ret;159 160		reg_value &= st_msk;161		if ((!!check_st) == (!!reg_value))162			break;163	}164 165	if ((!!check_st) != (!!reg_value))166		return -EBUSY;167 168	return 0;169}170 171static int hns_mdio_wait_ready(struct mii_bus *bus)172{173	struct hns_mdio_device *mdio_dev = bus->priv;174	u32 cmd_reg_value;175	int i;176 177	/* waiting for MDIO_COMMAND_REG's mdio_start==0 */178	/* after that can do read or write*/179	for (i = 0; i < MDIO_TIMEOUT; i++) {180		cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev,181						 MDIO_COMMAND_REG,182						 MDIO_CMD_START_B);183		if (!cmd_reg_value)184			break;185	}186	if ((i == MDIO_TIMEOUT) && cmd_reg_value)187		return -ETIMEDOUT;188 189	return 0;190}191 192static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,193			       u8 is_c45, u8 op, u8 phy_id, u16 cmd)194{195	u32 cmd_reg_value;196	u8 st = is_c45 ? MDIO_ST_CLAUSE_45 : MDIO_ST_CLAUSE_22;197 198	cmd_reg_value = st << MDIO_CMD_ST_S;199	cmd_reg_value |= op << MDIO_CMD_OP_S;200	cmd_reg_value |=201		(phy_id & MDIO_CMD_PRTAD_M) << MDIO_CMD_PRTAD_S;202	cmd_reg_value |= (cmd & MDIO_CMD_DEVAD_M) << MDIO_CMD_DEVAD_S;203	cmd_reg_value |= 1 << MDIO_CMD_START_B;204 205	MDIO_WRITE_REG(mdio_dev, MDIO_COMMAND_REG, cmd_reg_value);206}207 208/**209 * hns_mdio_write_c22 - access phy register210 * @bus: mdio bus211 * @phy_id: phy id212 * @regnum: register num213 * @data: register value214 *215 * Return 0 on success, negative on failure216 */217static int hns_mdio_write_c22(struct mii_bus *bus,218			      int phy_id, int regnum, u16 data)219{220	struct hns_mdio_device *mdio_dev = bus->priv;221	u16 reg = (u16)(regnum & 0xffff);222	u16 cmd_reg_cfg;223	int ret;224	u8 op;225 226	dev_dbg(&bus->dev, "mdio write %s,base is %p\n",227		bus->id, mdio_dev->vbase);228	dev_dbg(&bus->dev, "phy id=%d, reg=%#x, write data=%d\n",229		phy_id, reg, data);230 231	/* wait for ready */232	ret = hns_mdio_wait_ready(bus);233	if (ret) {234		dev_err(&bus->dev, "MDIO bus is busy\n");235		return ret;236	}237 238	cmd_reg_cfg = reg;239	op = MDIO_C22_WRITE;240 241	MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,242			   MDIO_WDATA_DATA_S, data);243 244	hns_mdio_cmd_write(mdio_dev, false, op, phy_id, cmd_reg_cfg);245 246	return 0;247}248 249/**250 * hns_mdio_write_c45 - access phy register251 * @bus: mdio bus252 * @phy_id: phy id253 * @devad: device address to read254 * @regnum: register num255 * @data: register value256 *257 * Return 0 on success, negative on failure258 */259static int hns_mdio_write_c45(struct mii_bus *bus, int phy_id, int devad,260			      int regnum, u16 data)261{262	struct hns_mdio_device *mdio_dev = bus->priv;263	u16 reg = (u16)(regnum & 0xffff);264	u16 cmd_reg_cfg;265	int ret;266	u8 op;267 268	dev_dbg(&bus->dev, "mdio write %s,base is %p\n",269		bus->id, mdio_dev->vbase);270	dev_dbg(&bus->dev, "phy id=%d, devad=%d, reg=%#x, write data=%d\n",271		phy_id, devad, reg, data);272 273	/* wait for ready */274	ret = hns_mdio_wait_ready(bus);275	if (ret) {276		dev_err(&bus->dev, "MDIO bus is busy\n");277		return ret;278	}279 280	/* config the cmd-reg to write addr*/281	MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,282			   MDIO_ADDR_DATA_S, reg);283 284	hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_WRITE_ADDR, phy_id, devad);285 286	/* check for read or write opt is finished */287	ret = hns_mdio_wait_ready(bus);288	if (ret) {289		dev_err(&bus->dev, "MDIO bus is busy\n");290		return ret;291	}292 293	/* config the data needed writing */294	cmd_reg_cfg = devad;295	op = MDIO_C45_WRITE_DATA;296 297	MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,298			   MDIO_WDATA_DATA_S, data);299 300	hns_mdio_cmd_write(mdio_dev, true, op, phy_id, cmd_reg_cfg);301 302	return 0;303}304 305/**306 * hns_mdio_read_c22 - access phy register307 * @bus: mdio bus308 * @phy_id: phy id309 * @regnum: register num310 *311 * Return phy register value312 */313static int hns_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)314{315	struct hns_mdio_device *mdio_dev = bus->priv;316	u16 reg = (u16)(regnum & 0xffff);317	u16 reg_val;318	int ret;319 320	dev_dbg(&bus->dev, "mdio read %s,base is %p\n",321		bus->id, mdio_dev->vbase);322	dev_dbg(&bus->dev, "phy id=%d, reg=%#x!\n", phy_id, reg);323 324	/* Step 1: wait for ready */325	ret = hns_mdio_wait_ready(bus);326	if (ret) {327		dev_err(&bus->dev, "MDIO bus is busy\n");328		return ret;329	}330 331	hns_mdio_cmd_write(mdio_dev, false, MDIO_C22_READ, phy_id, reg);332 333	/* Step 2: waiting for MDIO_COMMAND_REG 's mdio_start==0,*/334	/* check for read or write opt is finished */335	ret = hns_mdio_wait_ready(bus);336	if (ret) {337		dev_err(&bus->dev, "MDIO bus is busy\n");338		return ret;339	}340 341	reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);342	if (reg_val) {343		dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");344		return -EBUSY;345	}346 347	/* Step 3; get out data*/348	reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,349					  MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);350 351	return reg_val;352}353 354/**355 * hns_mdio_read_c45 - access phy register356 * @bus: mdio bus357 * @phy_id: phy id358 * @devad: device address to read359 * @regnum: register num360 *361 * Return phy register value362 */363static int hns_mdio_read_c45(struct mii_bus *bus, int phy_id, int devad,364			     int regnum)365{366	struct hns_mdio_device *mdio_dev = bus->priv;367	u16 reg = (u16)(regnum & 0xffff);368	u16 reg_val;369	int ret;370 371	dev_dbg(&bus->dev, "mdio read %s,base is %p\n",372		bus->id, mdio_dev->vbase);373	dev_dbg(&bus->dev, "phy id=%d, devad=%d, reg=%#x!\n",374		phy_id, devad, reg);375 376	/* Step 1: wait for ready */377	ret = hns_mdio_wait_ready(bus);378	if (ret) {379		dev_err(&bus->dev, "MDIO bus is busy\n");380		return ret;381	}382 383	MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,384			   MDIO_ADDR_DATA_S, reg);385 386	/* Step 2; config the cmd-reg to write addr*/387	hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_WRITE_ADDR, phy_id, devad);388 389	/* Step 3: check for read or write opt is finished */390	ret = hns_mdio_wait_ready(bus);391	if (ret) {392		dev_err(&bus->dev, "MDIO bus is busy\n");393		return ret;394	}395 396	hns_mdio_cmd_write(mdio_dev, true, MDIO_C45_READ, phy_id, devad);397 398	/* Step 5: waiting for MDIO_COMMAND_REG 's mdio_start==0,*/399	/* check for read or write opt is finished */400	ret = hns_mdio_wait_ready(bus);401	if (ret) {402		dev_err(&bus->dev, "MDIO bus is busy\n");403		return ret;404	}405 406	reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);407	if (reg_val) {408		dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");409		return -EBUSY;410	}411 412	/* Step 6; get out data*/413	reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,414					  MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);415 416	return reg_val;417}418 419/**420 * hns_mdio_reset - reset mdio bus421 * @bus: mdio bus422 *423 * Return 0 on success, negative on failure424 */425static int hns_mdio_reset(struct mii_bus *bus)426{427	struct hns_mdio_device *mdio_dev = bus->priv;428	const struct hns_mdio_sc_reg *sc_reg;429	int ret;430 431	if (dev_of_node(bus->parent)) {432		if (!mdio_dev->subctrl_vbase) {433			dev_err(&bus->dev, "mdio sys ctl reg has not mapped\n");434			return -ENODEV;435		}436 437		sc_reg = &mdio_dev->sc_reg;438		/* 1. reset req, and read reset st check */439		ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_req,440					    0x1, sc_reg->mdio_reset_st, 0x1,441					    MDIO_CHECK_SET_ST);442		if (ret) {443			dev_err(&bus->dev, "MDIO reset fail\n");444			return ret;445		}446 447		/* 2. dis clk, and read clk st check */448		ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_dis,449					    0x1, sc_reg->mdio_clk_st, 0x1,450					    MDIO_CHECK_CLR_ST);451		if (ret) {452			dev_err(&bus->dev, "MDIO dis clk fail\n");453			return ret;454		}455 456		/* 3. reset dreq, and read reset st check */457		ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_dreq,458					    0x1, sc_reg->mdio_reset_st, 0x1,459					    MDIO_CHECK_CLR_ST);460		if (ret) {461			dev_err(&bus->dev, "MDIO dis clk fail\n");462			return ret;463		}464 465		/* 4. en clk, and read clk st check */466		ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_en,467					    0x1, sc_reg->mdio_clk_st, 0x1,468					    MDIO_CHECK_SET_ST);469		if (ret)470			dev_err(&bus->dev, "MDIO en clk fail\n");471	} else if (is_acpi_node(bus->parent->fwnode)) {472		acpi_status s;473 474		s = acpi_evaluate_object(ACPI_HANDLE(bus->parent),475					 "_RST", NULL, NULL);476		if (ACPI_FAILURE(s)) {477			dev_err(&bus->dev, "Reset failed, return:%#x\n", s);478			ret = -EBUSY;479		} else {480			ret = 0;481		}482	} else {483		dev_err(&bus->dev, "Can not get cfg data from DT or ACPI\n");484		ret = -ENXIO;485	}486	return ret;487}488 489/**490 * hns_mdio_probe - probe mdio device491 * @pdev: mdio platform device492 *493 * Return 0 on success, negative on failure494 */495static int hns_mdio_probe(struct platform_device *pdev)496{497	struct hns_mdio_device *mdio_dev;498	struct mii_bus *new_bus;499	int ret;500 501	if (!pdev) {502		dev_err(NULL, "pdev is NULL!\r\n");503		return -ENODEV;504	}505 506	mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL);507	if (!mdio_dev)508		return -ENOMEM;509 510	new_bus = devm_mdiobus_alloc(&pdev->dev);511	if (!new_bus) {512		dev_err(&pdev->dev, "mdiobus_alloc fail!\n");513		return -ENOMEM;514	}515 516	new_bus->name = MDIO_BUS_NAME;517	new_bus->read = hns_mdio_read_c22;518	new_bus->write = hns_mdio_write_c22;519	new_bus->read_c45 = hns_mdio_read_c45;520	new_bus->write_c45 = hns_mdio_write_c45;521	new_bus->reset = hns_mdio_reset;522	new_bus->priv = mdio_dev;523	new_bus->parent = &pdev->dev;524 525	mdio_dev->vbase = devm_platform_ioremap_resource(pdev, 0);526	if (IS_ERR(mdio_dev->vbase)) {527		ret = PTR_ERR(mdio_dev->vbase);528		return ret;529	}530 531	platform_set_drvdata(pdev, new_bus);532	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%s", "Mii",533		 dev_name(&pdev->dev));534	if (dev_of_node(&pdev->dev)) {535		struct of_phandle_args reg_args;536 537		ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,538						       "subctrl-vbase",539						       4,540						       0,541						       &reg_args);542		if (!ret) {543			mdio_dev->subctrl_vbase =544				syscon_node_to_regmap(reg_args.np);545			if (IS_ERR(mdio_dev->subctrl_vbase)) {546				dev_warn(&pdev->dev, "syscon_node_to_regmap error\n");547				mdio_dev->subctrl_vbase = NULL;548			} else {549				if (reg_args.args_count == 4) {550					mdio_dev->sc_reg.mdio_clk_en =551						(u16)reg_args.args[0];552					mdio_dev->sc_reg.mdio_clk_dis =553						(u16)reg_args.args[0] + 4;554					mdio_dev->sc_reg.mdio_reset_req =555						(u16)reg_args.args[1];556					mdio_dev->sc_reg.mdio_reset_dreq =557						(u16)reg_args.args[1] + 4;558					mdio_dev->sc_reg.mdio_clk_st =559						(u16)reg_args.args[2];560					mdio_dev->sc_reg.mdio_reset_st =561						(u16)reg_args.args[3];562				} else {563					/* for compatible */564					mdio_dev->sc_reg.mdio_clk_en =565						MDIO_SC_CLK_EN;566					mdio_dev->sc_reg.mdio_clk_dis =567						MDIO_SC_CLK_DIS;568					mdio_dev->sc_reg.mdio_reset_req =569						MDIO_SC_RESET_REQ;570					mdio_dev->sc_reg.mdio_reset_dreq =571						MDIO_SC_RESET_DREQ;572					mdio_dev->sc_reg.mdio_clk_st =573						MDIO_SC_CLK_ST;574					mdio_dev->sc_reg.mdio_reset_st =575						MDIO_SC_RESET_ST;576				}577			}578			of_node_put(reg_args.np);579		} else {580			dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret);581			mdio_dev->subctrl_vbase = NULL;582		}583 584		ret = of_mdiobus_register(new_bus, pdev->dev.of_node);585	} else if (is_acpi_node(pdev->dev.fwnode)) {586		/* Clear all the IRQ properties */587		memset(new_bus->irq, PHY_POLL, 4 * PHY_MAX_ADDR);588 589		/* Mask out all PHYs from auto probing. */590		new_bus->phy_mask = ~0;591 592		/* Register the MDIO bus */593		ret = mdiobus_register(new_bus);594	} else {595		dev_err(&pdev->dev, "Can not get cfg data from DT or ACPI\n");596		ret = -ENXIO;597	}598 599	if (ret) {600		dev_err(&pdev->dev, "Cannot register as MDIO bus!\n");601		platform_set_drvdata(pdev, NULL);602		return ret;603	}604 605	return 0;606}607 608/**609 * hns_mdio_remove - remove mdio device610 * @pdev: mdio platform device611 *612 * Return 0 on success, negative on failure613 */614static void hns_mdio_remove(struct platform_device *pdev)615{616	struct mii_bus *bus;617 618	bus = platform_get_drvdata(pdev);619 620	mdiobus_unregister(bus);621	platform_set_drvdata(pdev, NULL);622}623 624static const struct of_device_id hns_mdio_match[] = {625	{.compatible = "hisilicon,mdio"},626	{.compatible = "hisilicon,hns-mdio"},627	{}628};629MODULE_DEVICE_TABLE(of, hns_mdio_match);630 631static const struct acpi_device_id hns_mdio_acpi_match[] = {632	{ "HISI0141", 0 },633	{ },634};635MODULE_DEVICE_TABLE(acpi, hns_mdio_acpi_match);636 637static struct platform_driver hns_mdio_driver = {638	.probe = hns_mdio_probe,639	.remove_new = hns_mdio_remove,640	.driver = {641		   .name = MDIO_DRV_NAME,642		   .of_match_table = hns_mdio_match,643		   .acpi_match_table = ACPI_PTR(hns_mdio_acpi_match),644		   },645};646 647module_platform_driver(hns_mdio_driver);648 649MODULE_LICENSE("GPL");650MODULE_AUTHOR("Huawei Tech. Co., Ltd.");651MODULE_DESCRIPTION("Hisilicon HNS MDIO driver");652MODULE_ALIAS("platform:" MDIO_DRV_NAME);653