brintos

brintos / linux-shallow public Read only

0
0
Text · 28.2 KiB · b2b5f6b Raw
1218 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Marvell 88E6xxx Switch Global 2 Registers support4 *5 * Copyright (c) 2008 Marvell Semiconductor6 *7 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.8 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>9 */10 11#include <linux/bitfield.h>12#include <linux/interrupt.h>13#include <linux/irqdomain.h>14 15#include "chip.h"16#include "global1.h" /* for MV88E6XXX_G1_STS_IRQ_DEVICE */17#include "global2.h"18 19int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)20{21	return mv88e6xxx_read(chip, chip->info->global2_addr, reg, val);22}23 24int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)25{26	return mv88e6xxx_write(chip, chip->info->global2_addr, reg, val);27}28 29int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, int30			  bit, int val)31{32	return mv88e6xxx_wait_bit(chip, chip->info->global2_addr, reg,33				  bit, val);34}35 36/* Offset 0x00: Interrupt Source Register */37 38static int mv88e6xxx_g2_int_source(struct mv88e6xxx_chip *chip, u16 *src)39{40	/* Read (and clear most of) the Interrupt Source bits */41	return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_INT_SRC, src);42}43 44/* Offset 0x01: Interrupt Mask Register */45 46static int mv88e6xxx_g2_int_mask(struct mv88e6xxx_chip *chip, u16 mask)47{48	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_INT_MASK, mask);49}50 51/* Offset 0x02: Management Enable 2x */52 53static int mv88e6xxx_g2_mgmt_enable_2x(struct mv88e6xxx_chip *chip, u16 en2x)54{55	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, en2x);56}57 58/* Offset 0x03: Management Enable 0x */59 60static int mv88e6xxx_g2_mgmt_enable_0x(struct mv88e6xxx_chip *chip, u16 en0x)61{62	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X, en0x);63}64 65/* Offset 0x05: Switch Management Register */66 67static int mv88e6xxx_g2_switch_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip,68					     bool enable)69{70	u16 val;71	int err;72 73	err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SWITCH_MGMT, &val);74	if (err)75		return err;76 77	if (enable)78		val |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU;79	else80		val &= ~MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU;81 82	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, val);83}84 85int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)86{87	int err;88 89	/* Consider the frames with reserved multicast destination90	 * addresses matching 01:80:c2:00:00:0x as MGMT.91	 */92	err = mv88e6xxx_g2_mgmt_enable_0x(chip, 0xffff);93	if (err)94		return err;95 96	return mv88e6xxx_g2_switch_mgmt_rsvd2cpu(chip, true);97}98 99int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)100{101	int err;102 103	/* Consider the frames with reserved multicast destination104	 * addresses matching 01:80:c2:00:00:2x as MGMT.105	 */106	err = mv88e6xxx_g2_mgmt_enable_2x(chip, 0xffff);107	if (err)108		return err;109 110	return mv88e6185_g2_mgmt_rsvd2cpu(chip);111}112 113/* Offset 0x06: Device Mapping Table register */114 115int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,116				      int port)117{118	u16 val = (target << 8) | (port & 0x1f);119	/* Modern chips use 5 bits to define a device mapping port,120	 * but bit 4 is reserved on older chips, so it is safe to use.121	 */122 123	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_DEVICE_MAPPING,124				  MV88E6XXX_G2_DEVICE_MAPPING_UPDATE | val);125}126 127/* Offset 0x07: Trunk Mask Table register */128 129int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,130				  bool hash, u16 mask)131{132	u16 val = (num << 12) | (mask & mv88e6xxx_port_mask(chip));133 134	if (hash)135		val |= MV88E6XXX_G2_TRUNK_MASK_HASH;136 137	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MASK,138				  MV88E6XXX_G2_TRUNK_MASK_UPDATE | val);139}140 141/* Offset 0x08: Trunk Mapping Table register */142 143int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,144				     u16 map)145{146	const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;147	u16 val = (id << 11) | (map & port_mask);148 149	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_TRUNK_MAPPING,150				  MV88E6XXX_G2_TRUNK_MAPPING_UPDATE | val);151}152 153int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip)154{155	const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;156	int i, err;157 158	/* Clear all eight possible Trunk Mask vectors */159	for (i = 0; i < 8; ++i) {160		err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);161		if (err)162			return err;163	}164 165	/* Clear all sixteen possible Trunk ID routing vectors */166	for (i = 0; i < 16; ++i) {167		err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);168		if (err)169			return err;170	}171 172	return 0;173}174 175/* Offset 0x09: Ingress Rate Command register176 * Offset 0x0A: Ingress Rate Data register177 */178 179static int mv88e6xxx_g2_irl_wait(struct mv88e6xxx_chip *chip)180{181	int bit = __bf_shf(MV88E6XXX_G2_IRL_CMD_BUSY);182 183	return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_IRL_CMD, bit, 0);184}185 186static int mv88e6xxx_g2_irl_op(struct mv88e6xxx_chip *chip, u16 op, int port,187			       int res, int reg)188{189	int err;190 191	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_IRL_CMD,192				 MV88E6XXX_G2_IRL_CMD_BUSY | op | (port << 8) |193				 (res << 5) | reg);194	if (err)195		return err;196 197	return mv88e6xxx_g2_irl_wait(chip);198}199 200int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)201{202	return mv88e6xxx_g2_irl_op(chip, MV88E6352_G2_IRL_CMD_OP_INIT_ALL, port,203				   0, 0);204}205 206int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port)207{208	return mv88e6xxx_g2_irl_op(chip, MV88E6390_G2_IRL_CMD_OP_INIT_ALL, port,209				   0, 0);210}211 212/* Offset 0x0B: Cross-chip Port VLAN (Addr) Register213 * Offset 0x0C: Cross-chip Port VLAN Data Register214 */215 216static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip)217{218	int bit = __bf_shf(MV88E6XXX_G2_PVT_ADDR_BUSY);219 220	return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_PVT_ADDR, bit, 0);221}222 223static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev,224			       int src_port, u16 op)225{226	int err;227 228	/* 9-bit Cross-chip PVT pointer: with MV88E6XXX_G2_MISC_5_BIT_PORT229	 * cleared, source device is 5-bit, source port is 4-bit.230	 */231	op |= MV88E6XXX_G2_PVT_ADDR_BUSY;232	op |= (src_dev & 0x1f) << 4;233	op |= (src_port & 0xf);234 235	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_ADDR, op);236	if (err)237		return err;238 239	return mv88e6xxx_g2_pvt_op_wait(chip);240}241 242int mv88e6xxx_g2_pvt_read(struct mv88e6xxx_chip *chip, int src_dev,243			  int src_port, u16 *data)244{245	int err;246 247	err = mv88e6xxx_g2_pvt_op_wait(chip);248	if (err)249		return err;250 251	err = mv88e6xxx_g2_pvt_op(chip, src_dev, src_port,252				  MV88E6XXX_G2_PVT_ADDR_OP_READ);253	if (err)254		return err;255 256	return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_PVT_DATA, data);257}258 259int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev,260			   int src_port, u16 data)261{262	int err;263 264	err = mv88e6xxx_g2_pvt_op_wait(chip);265	if (err)266		return err;267 268	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_DATA, data);269	if (err)270		return err;271 272	return mv88e6xxx_g2_pvt_op(chip, src_dev, src_port,273				   MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN);274}275 276/* Offset 0x0D: Switch MAC/WoL/WoF register */277 278static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,279					 unsigned int pointer, u8 data)280{281	u16 val = (pointer << 8) | data;282 283	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MAC,284				  MV88E6XXX_G2_SWITCH_MAC_UPDATE | val);285}286 287int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)288{289	int i, err;290 291	for (i = 0; i < 6; i++) {292		err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);293		if (err)294			break;295	}296 297	return err;298}299 300/* Offset 0x0E: ATU Statistics */301 302int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin)303{304	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_ATU_STATS,305				  kind | bin);306}307 308int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats)309{310	return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_ATU_STATS, stats);311}312 313/* Offset 0x0F: Priority Override Table */314 315static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,316				  u8 data)317{318	u16 val = (pointer << 8) | (data & 0x7);319 320	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PRIO_OVERRIDE,321				  MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE | val);322}323 324int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)325{326	int i, err;327 328	/* Clear all sixteen possible Priority Override entries */329	for (i = 0; i < 16; i++) {330		err = mv88e6xxx_g2_pot_write(chip, i, 0);331		if (err)332			break;333	}334 335	return err;336}337 338/* Offset 0x14: EEPROM Command339 * Offset 0x15: EEPROM Data (for 16-bit data access)340 * Offset 0x15: EEPROM Addr (for 8-bit data access)341 */342 343int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)344{345	int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY);346	int err;347 348	err = mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0);349	if (err)350		return err;351 352	bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_RUNNING);353 354	return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_EEPROM_CMD, bit, 0);355}356 357static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)358{359	int err;360 361	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_EEPROM_CMD,362				 MV88E6XXX_G2_EEPROM_CMD_BUSY | cmd);363	if (err)364		return err;365 366	return mv88e6xxx_g2_eeprom_wait(chip);367}368 369static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip,370				     u16 addr, u8 *data)371{372	u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ;373	int err;374 375	err = mv88e6xxx_g2_eeprom_wait(chip);376	if (err)377		return err;378 379	err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);380	if (err)381		return err;382 383	err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);384	if (err)385		return err;386 387	err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &cmd);388	if (err)389		return err;390 391	*data = cmd & 0xff;392 393	return 0;394}395 396static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip,397				      u16 addr, u8 data)398{399	u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE |400		MV88E6XXX_G2_EEPROM_CMD_WRITE_EN;401	int err;402 403	err = mv88e6xxx_g2_eeprom_wait(chip);404	if (err)405		return err;406 407	err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);408	if (err)409		return err;410 411	return mv88e6xxx_g2_eeprom_cmd(chip, cmd | data);412}413 414static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,415				      u8 addr, u16 *data)416{417	u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ | addr;418	int err;419 420	err = mv88e6xxx_g2_eeprom_wait(chip);421	if (err)422		return err;423 424	err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);425	if (err)426		return err;427 428	return mv88e6xxx_g2_read(chip, MV88E6352_G2_EEPROM_DATA, data);429}430 431static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,432				       u8 addr, u16 data)433{434	u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE | addr;435	int err;436 437	err = mv88e6xxx_g2_eeprom_wait(chip);438	if (err)439		return err;440 441	err = mv88e6xxx_g2_write(chip, MV88E6352_G2_EEPROM_DATA, data);442	if (err)443		return err;444 445	return mv88e6xxx_g2_eeprom_cmd(chip, cmd);446}447 448int mv88e6xxx_g2_get_eeprom8(struct mv88e6xxx_chip *chip,449			     struct ethtool_eeprom *eeprom, u8 *data)450{451	unsigned int offset = eeprom->offset;452	unsigned int len = eeprom->len;453	int err;454 455	eeprom->len = 0;456 457	while (len) {458		err = mv88e6xxx_g2_eeprom_read8(chip, offset, data);459		if (err)460			return err;461 462		eeprom->len++;463		offset++;464		data++;465		len--;466	}467 468	return 0;469}470 471int mv88e6xxx_g2_set_eeprom8(struct mv88e6xxx_chip *chip,472			     struct ethtool_eeprom *eeprom, u8 *data)473{474	unsigned int offset = eeprom->offset;475	unsigned int len = eeprom->len;476	int err;477 478	eeprom->len = 0;479 480	while (len) {481		err = mv88e6xxx_g2_eeprom_write8(chip, offset, *data);482		if (err)483			return err;484 485		eeprom->len++;486		offset++;487		data++;488		len--;489	}490 491	return 0;492}493 494int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,495			      struct ethtool_eeprom *eeprom, u8 *data)496{497	unsigned int offset = eeprom->offset;498	unsigned int len = eeprom->len;499	u16 val;500	int err;501 502	eeprom->len = 0;503 504	if (offset & 1) {505		err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);506		if (err)507			return err;508 509		*data++ = (val >> 8) & 0xff;510 511		offset++;512		len--;513		eeprom->len++;514	}515 516	while (len >= 2) {517		err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);518		if (err)519			return err;520 521		*data++ = val & 0xff;522		*data++ = (val >> 8) & 0xff;523 524		offset += 2;525		len -= 2;526		eeprom->len += 2;527	}528 529	if (len) {530		err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);531		if (err)532			return err;533 534		*data++ = val & 0xff;535 536		offset++;537		len--;538		eeprom->len++;539	}540 541	return 0;542}543 544int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,545			      struct ethtool_eeprom *eeprom, u8 *data)546{547	unsigned int offset = eeprom->offset;548	unsigned int len = eeprom->len;549	u16 val;550	int err;551 552	/* Ensure the RO WriteEn bit is set */553	err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &val);554	if (err)555		return err;556 557	if (!(val & MV88E6XXX_G2_EEPROM_CMD_WRITE_EN))558		return -EROFS;559 560	eeprom->len = 0;561 562	if (offset & 1) {563		err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);564		if (err)565			return err;566 567		val = (*data++ << 8) | (val & 0xff);568 569		err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);570		if (err)571			return err;572 573		offset++;574		len--;575		eeprom->len++;576	}577 578	while (len >= 2) {579		val = *data++;580		val |= *data++ << 8;581 582		err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);583		if (err)584			return err;585 586		offset += 2;587		len -= 2;588		eeprom->len += 2;589	}590 591	if (len) {592		err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);593		if (err)594			return err;595 596		val = (val & 0xff00) | *data++;597 598		err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);599		if (err)600			return err;601 602		offset++;603		len--;604		eeprom->len++;605	}606 607	return 0;608}609 610/* Offset 0x18: SMI PHY Command Register611 * Offset 0x19: SMI PHY Data Register612 */613 614static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)615{616	int bit = __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_BUSY);617 618	return mv88e6xxx_g2_wait_bit(chip, MV88E6XXX_G2_SMI_PHY_CMD, bit, 0);619}620 621static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)622{623	int err;624 625	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_CMD,626				 MV88E6XXX_G2_SMI_PHY_CMD_BUSY | cmd);627	if (err)628		return err;629 630	return mv88e6xxx_g2_smi_phy_wait(chip);631}632 633static int mv88e6xxx_g2_smi_phy_access(struct mv88e6xxx_chip *chip,634				       bool external, bool c45, u16 op, int dev,635				       int reg)636{637	u16 cmd = op;638 639	if (external)640		cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_EXTERNAL;641	else642		cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_INTERNAL; /* empty mask */643 644	if (c45)645		cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_45; /* empty mask */646	else647		cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_22;648 649	dev <<= __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK);650	cmd |= dev & MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK;651	cmd |= reg & MV88E6XXX_G2_SMI_PHY_CMD_REG_ADDR_MASK;652 653	return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);654}655 656static int mv88e6xxx_g2_smi_phy_access_c22(struct mv88e6xxx_chip *chip,657					   bool external, u16 op, int dev,658					   int reg)659{660	return mv88e6xxx_g2_smi_phy_access(chip, external, false, op, dev, reg);661}662 663/* IEEE 802.3 Clause 22 Read Data Register */664static int mv88e6xxx_g2_smi_phy_read_data_c22(struct mv88e6xxx_chip *chip,665					      bool external, int dev, int reg,666					      u16 *data)667{668	u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_READ_DATA;669	int err;670 671	err = mv88e6xxx_g2_smi_phy_wait(chip);672	if (err)673		return err;674 675	err = mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);676	if (err)677		return err;678 679	return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);680}681 682/* IEEE 802.3 Clause 22 Write Data Register */683static int mv88e6xxx_g2_smi_phy_write_data_c22(struct mv88e6xxx_chip *chip,684					       bool external, int dev, int reg,685					       u16 data)686{687	u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_WRITE_DATA;688	int err;689 690	err = mv88e6xxx_g2_smi_phy_wait(chip);691	if (err)692		return err;693 694	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);695	if (err)696		return err;697 698	return mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);699}700 701static int mv88e6xxx_g2_smi_phy_access_c45(struct mv88e6xxx_chip *chip,702					   bool external, u16 op, int port,703					   int dev)704{705	return mv88e6xxx_g2_smi_phy_access(chip, external, true, op, port, dev);706}707 708/* IEEE 802.3 Clause 45 Write Address Register */709static int mv88e6xxx_g2_smi_phy_write_addr_c45(struct mv88e6xxx_chip *chip,710					       bool external, int port, int dev,711					       int addr)712{713	u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_ADDR;714	int err;715 716	err = mv88e6xxx_g2_smi_phy_wait(chip);717	if (err)718		return err;719 720	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, addr);721	if (err)722		return err;723 724	return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);725}726 727/* IEEE 802.3 Clause 45 Read Data Register */728static int mv88e6xxx_g2_smi_phy_read_data_c45(struct mv88e6xxx_chip *chip,729					      bool external, int port, int dev,730					      u16 *data)731{732	u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_READ_DATA;733	int err;734 735	err = mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);736	if (err)737		return err;738 739	return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);740}741 742static int _mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,743					  bool external, int port, int devad,744					  int reg, u16 *data)745{746	int err;747 748	err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, devad,749						  reg);750	if (err)751		return err;752 753	return mv88e6xxx_g2_smi_phy_read_data_c45(chip, external, port, devad,754						  data);755}756 757/* IEEE 802.3 Clause 45 Write Data Register */758static int mv88e6xxx_g2_smi_phy_write_data_c45(struct mv88e6xxx_chip *chip,759					       bool external, int port, int dev,760					       u16 data)761{762	u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_DATA;763	int err;764 765	err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);766	if (err)767		return err;768 769	return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev);770}771 772static int _mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,773					   bool external, int port, int devad,774					   int reg, u16 data)775{776	int err;777 778	err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, devad,779						  reg);780	if (err)781		return err;782 783	return mv88e6xxx_g2_smi_phy_write_data_c45(chip, external, port, devad,784						   data);785}786 787int mv88e6xxx_g2_smi_phy_read_c22(struct mv88e6xxx_chip *chip,788				  struct mii_bus *bus,789				  int addr, int reg, u16 *val)790{791	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;792	bool external = mdio_bus->external;793 794	return mv88e6xxx_g2_smi_phy_read_data_c22(chip, external, addr, reg,795						  val);796}797 798int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip,799				  struct mii_bus *bus, int addr, int devad,800				  int reg, u16 *val)801{802	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;803	bool external = mdio_bus->external;804 805	return _mv88e6xxx_g2_smi_phy_read_c45(chip, external, addr, devad, reg,806					      val);807}808 809int mv88e6xxx_g2_smi_phy_write_c22(struct mv88e6xxx_chip *chip,810				   struct mii_bus *bus, int addr, int reg,811				   u16 val)812{813	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;814	bool external = mdio_bus->external;815 816	return mv88e6xxx_g2_smi_phy_write_data_c22(chip, external, addr, reg,817						   val);818}819 820int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip,821				   struct mii_bus *bus, int addr, int devad,822				   int reg, u16 val)823{824	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;825	bool external = mdio_bus->external;826 827	return _mv88e6xxx_g2_smi_phy_write_c45(chip, external, addr, devad, reg,828					       val);829}830 831/* Offset 0x1B: Watchdog Control */832static int mv88e6097_watchdog_action(struct mv88e6xxx_chip *chip, int irq)833{834	u16 reg;835 836	mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, &reg);837 838	dev_info(chip->dev, "Watchdog event: 0x%04x", reg);839 840	return IRQ_HANDLED;841}842 843static void mv88e6097_watchdog_free(struct mv88e6xxx_chip *chip)844{845	u16 reg;846 847	mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, &reg);848 849	reg &= ~(MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |850		 MV88E6352_G2_WDOG_CTL_QC_ENABLE);851 852	mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL, reg);853}854 855static int mv88e6097_watchdog_setup(struct mv88e6xxx_chip *chip)856{857	return mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL,858				  MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |859				  MV88E6352_G2_WDOG_CTL_QC_ENABLE |860				  MV88E6352_G2_WDOG_CTL_SWRESET);861}862 863const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {864	.irq_action = mv88e6097_watchdog_action,865	.irq_setup = mv88e6097_watchdog_setup,866	.irq_free = mv88e6097_watchdog_free,867};868 869static void mv88e6250_watchdog_free(struct mv88e6xxx_chip *chip)870{871	u16 reg;872 873	mv88e6xxx_g2_read(chip, MV88E6250_G2_WDOG_CTL, &reg);874 875	reg &= ~(MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |876		 MV88E6250_G2_WDOG_CTL_QC_ENABLE);877 878	mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL, reg);879}880 881static int mv88e6250_watchdog_setup(struct mv88e6xxx_chip *chip)882{883	return mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL,884				  MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |885				  MV88E6250_G2_WDOG_CTL_QC_ENABLE |886				  MV88E6250_G2_WDOG_CTL_SWRESET);887}888 889const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {890	.irq_action = mv88e6097_watchdog_action,891	.irq_setup = mv88e6250_watchdog_setup,892	.irq_free = mv88e6250_watchdog_free,893};894 895static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)896{897	return mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,898				  MV88E6390_G2_WDOG_CTL_UPDATE |899				  MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE |900				  MV88E6390_G2_WDOG_CTL_CUT_THROUGH |901				  MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER |902				  MV88E6390_G2_WDOG_CTL_EGRESS |903				  MV88E6390_G2_WDOG_CTL_FORCE_IRQ);904}905 906static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)907{908	u16 reg;909 910	mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,911			   MV88E6390_G2_WDOG_CTL_PTR_EVENT);912	mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, &reg);913 914	dev_info(chip->dev, "Watchdog event: 0x%04x",915		 reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);916 917	mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,918			   MV88E6390_G2_WDOG_CTL_PTR_HISTORY);919	mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, &reg);920 921	dev_info(chip->dev, "Watchdog history: 0x%04x",922		 reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);923 924	/* Trigger a software reset to try to recover the switch */925	if (chip->info->ops->reset)926		chip->info->ops->reset(chip);927 928	mv88e6390_watchdog_setup(chip);929 930	return IRQ_HANDLED;931}932 933static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip)934{935	mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,936			   MV88E6390_G2_WDOG_CTL_UPDATE |937			   MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE);938}939 940const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {941	.irq_action = mv88e6390_watchdog_action,942	.irq_setup = mv88e6390_watchdog_setup,943	.irq_free = mv88e6390_watchdog_free,944};945 946static int mv88e6393x_watchdog_action(struct mv88e6xxx_chip *chip, int irq)947{948	mv88e6390_watchdog_action(chip, irq);949 950	/* Fix for clearing the force WD event bit.951	 * Unreleased erratum on mv88e6393x.952	 */953	mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,954			   MV88E6390_G2_WDOG_CTL_UPDATE |955			   MV88E6390_G2_WDOG_CTL_PTR_EVENT);956 957	return IRQ_HANDLED;958}959 960const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops = {961	.irq_action = mv88e6393x_watchdog_action,962	.irq_setup = mv88e6390_watchdog_setup,963	.irq_free = mv88e6390_watchdog_free,964};965 966static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)967{968	struct mv88e6xxx_chip *chip = dev_id;969	irqreturn_t ret = IRQ_NONE;970 971	mv88e6xxx_reg_lock(chip);972	if (chip->info->ops->watchdog_ops->irq_action)973		ret = chip->info->ops->watchdog_ops->irq_action(chip, irq);974	mv88e6xxx_reg_unlock(chip);975 976	return ret;977}978 979static void mv88e6xxx_g2_watchdog_free(struct mv88e6xxx_chip *chip)980{981	mv88e6xxx_reg_lock(chip);982	if (chip->info->ops->watchdog_ops->irq_free)983		chip->info->ops->watchdog_ops->irq_free(chip);984	mv88e6xxx_reg_unlock(chip);985 986	free_irq(chip->watchdog_irq, chip);987	irq_dispose_mapping(chip->watchdog_irq);988}989 990static int mv88e6xxx_g2_watchdog_setup(struct mv88e6xxx_chip *chip)991{992	int err;993 994	chip->watchdog_irq = irq_find_mapping(chip->g2_irq.domain,995					      MV88E6XXX_G2_INT_SOURCE_WATCHDOG);996	if (chip->watchdog_irq < 0)997		return chip->watchdog_irq;998 999	snprintf(chip->watchdog_irq_name, sizeof(chip->watchdog_irq_name),1000		 "mv88e6xxx-%s-watchdog", dev_name(chip->dev));1001 1002	err = request_threaded_irq(chip->watchdog_irq, NULL,1003				   mv88e6xxx_g2_watchdog_thread_fn,1004				   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,1005				   chip->watchdog_irq_name, chip);1006	if (err)1007		return err;1008 1009	mv88e6xxx_reg_lock(chip);1010	if (chip->info->ops->watchdog_ops->irq_setup)1011		err = chip->info->ops->watchdog_ops->irq_setup(chip);1012	mv88e6xxx_reg_unlock(chip);1013 1014	return err;1015}1016 1017/* Offset 0x1D: Misc Register */1018 1019static int mv88e6xxx_g2_misc_5_bit_port(struct mv88e6xxx_chip *chip,1020					bool port_5_bit)1021{1022	u16 val;1023	int err;1024 1025	err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_MISC, &val);1026	if (err)1027		return err;1028 1029	if (port_5_bit)1030		val |= MV88E6XXX_G2_MISC_5_BIT_PORT;1031	else1032		val &= ~MV88E6XXX_G2_MISC_5_BIT_PORT;1033 1034	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MISC, val);1035}1036 1037int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)1038{1039	return mv88e6xxx_g2_misc_5_bit_port(chip, false);1040}1041 1042static void mv88e6xxx_g2_irq_mask(struct irq_data *d)1043{1044	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);1045	unsigned int n = d->hwirq;1046 1047	chip->g2_irq.masked |= (1 << n);1048}1049 1050static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)1051{1052	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);1053	unsigned int n = d->hwirq;1054 1055	chip->g2_irq.masked &= ~(1 << n);1056}1057 1058static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)1059{1060	struct mv88e6xxx_chip *chip = dev_id;1061	unsigned int nhandled = 0;1062	unsigned int sub_irq;1063	unsigned int n;1064	int err;1065	u16 reg;1066 1067	mv88e6xxx_reg_lock(chip);1068	err = mv88e6xxx_g2_int_source(chip, &reg);1069	mv88e6xxx_reg_unlock(chip);1070	if (err)1071		goto out;1072 1073	for (n = 0; n < 16; ++n) {1074		if (reg & (1 << n)) {1075			sub_irq = irq_find_mapping(chip->g2_irq.domain, n);1076			handle_nested_irq(sub_irq);1077			++nhandled;1078		}1079	}1080out:1081	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);1082}1083 1084static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)1085{1086	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);1087 1088	mv88e6xxx_reg_lock(chip);1089}1090 1091static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)1092{1093	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);1094	int err;1095 1096	err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked);1097	if (err)1098		dev_err(chip->dev, "failed to mask interrupts\n");1099 1100	mv88e6xxx_reg_unlock(chip);1101}1102 1103static const struct irq_chip mv88e6xxx_g2_irq_chip = {1104	.name			= "mv88e6xxx-g2",1105	.irq_mask		= mv88e6xxx_g2_irq_mask,1106	.irq_unmask		= mv88e6xxx_g2_irq_unmask,1107	.irq_bus_lock		= mv88e6xxx_g2_irq_bus_lock,1108	.irq_bus_sync_unlock	= mv88e6xxx_g2_irq_bus_sync_unlock,1109};1110 1111static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,1112				       unsigned int irq,1113				       irq_hw_number_t hwirq)1114{1115	struct mv88e6xxx_chip *chip = d->host_data;1116 1117	irq_set_chip_data(irq, d->host_data);1118	irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);1119	irq_set_noprobe(irq);1120 1121	return 0;1122}1123 1124static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {1125	.map	= mv88e6xxx_g2_irq_domain_map,1126	.xlate	= irq_domain_xlate_twocell,1127};1128 1129void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)1130{1131	int irq, virq;1132 1133	mv88e6xxx_g2_watchdog_free(chip);1134 1135	free_irq(chip->device_irq, chip);1136	irq_dispose_mapping(chip->device_irq);1137 1138	for (irq = 0; irq < 16; irq++) {1139		virq = irq_find_mapping(chip->g2_irq.domain, irq);1140		irq_dispose_mapping(virq);1141	}1142 1143	irq_domain_remove(chip->g2_irq.domain);1144}1145 1146int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)1147{1148	int err, irq, virq;1149 1150	chip->g2_irq.masked = ~0;1151	mv88e6xxx_reg_lock(chip);1152	err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked);1153	mv88e6xxx_reg_unlock(chip);1154	if (err)1155		return err;1156 1157	chip->g2_irq.domain = irq_domain_add_simple(1158		chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);1159	if (!chip->g2_irq.domain)1160		return -ENOMEM;1161 1162	for (irq = 0; irq < 16; irq++)1163		irq_create_mapping(chip->g2_irq.domain, irq);1164 1165	chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;1166 1167	chip->device_irq = irq_find_mapping(chip->g1_irq.domain,1168					    MV88E6XXX_G1_STS_IRQ_DEVICE);1169	if (chip->device_irq < 0) {1170		err = chip->device_irq;1171		goto out;1172	}1173 1174	snprintf(chip->device_irq_name, sizeof(chip->device_irq_name),1175		 "mv88e6xxx-%s-g2", dev_name(chip->dev));1176 1177	err = request_threaded_irq(chip->device_irq, NULL,1178				   mv88e6xxx_g2_irq_thread_fn,1179				   IRQF_ONESHOT, chip->device_irq_name, chip);1180	if (err)1181		goto out;1182 1183	return mv88e6xxx_g2_watchdog_setup(chip);1184 1185out:1186	for (irq = 0; irq < 16; irq++) {1187		virq = irq_find_mapping(chip->g2_irq.domain, irq);1188		irq_dispose_mapping(virq);1189	}1190 1191	irq_domain_remove(chip->g2_irq.domain);1192 1193	return err;1194}1195 1196int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip,1197				struct mii_bus *bus)1198{1199	int phy_start = chip->info->internal_phys_offset;1200	int phy_end = chip->info->internal_phys_offset +1201		      chip->info->num_internal_phys;1202	int phy, irq;1203 1204	for (phy = phy_start; phy < phy_end; phy++) {1205		irq = irq_find_mapping(chip->g2_irq.domain, phy);1206		if (irq < 0)1207			return irq;1208 1209		bus->irq[chip->info->phy_base_addr + phy] = irq;1210	}1211	return 0;1212}1213 1214void mv88e6xxx_g2_irq_mdio_free(struct mv88e6xxx_chip *chip,1215				struct mii_bus *bus)1216{1217}1218