summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml7
-rw-r--r--drivers/net/pcs/pcs-rzn1-miic.c105
2 files changed, 109 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml b/Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml
index 3adbcf56d2be..f9d39114e667 100644
--- a/Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml
+++ b/Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml
@@ -86,6 +86,13 @@ patternProperties:
and include/dt-bindings/net/renesas,r9a09g077-pcs-miic.h for RZ/N2H, RZ/T2H SoCs.
$ref: /schemas/types.yaml#/definitions/uint32
+ renesas,miic-phy-link-active-low:
+ type: boolean
+ description: Indicates that the PHY-link signal provided by the Ethernet switch,
+ EtherCAT, or SERCOS3 interface is active low. When present, this property
+ sets the corresponding signal polarity to active low. When omitted, the signal
+ defaults to active high.
+
required:
- reg
- renesas,miic-input
diff --git a/drivers/net/pcs/pcs-rzn1-miic.c b/drivers/net/pcs/pcs-rzn1-miic.c
index 885f17c32643..8d7f82c1df2f 100644
--- a/drivers/net/pcs/pcs-rzn1-miic.c
+++ b/drivers/net/pcs/pcs-rzn1-miic.c
@@ -28,6 +28,8 @@
#define MIIC_MODCTRL 0x8
+#define MIIC_PHY_LINK 0x14
+
#define MIIC_CONVCTRL(port) (0x100 + (port) * 4)
#define MIIC_CONVCTRL_CONV_SPEED GENMASK(1, 0)
@@ -178,12 +180,23 @@ static const char * const rzt2h_reset_ids[] = {
};
/**
+ * struct miic_phy_link_cfg - MIIC PHY_LINK configuration
+ * @mask: Mask of phy_link bits
+ * @val: Value of phy_link bits
+ */
+struct miic_phy_link_cfg {
+ u32 mask;
+ u32 val;
+};
+
+/**
* struct miic - MII converter structure
* @base: base address of the MII converter
* @dev: Device associated to the MII converter
* @lock: Lock used for read-modify-write access
* @rsts: Reset controls for the MII converter
* @of_data: Pointer to OF data
+ * @link_cfg: MIIC PHY_LINK configuration
*/
struct miic {
void __iomem *base;
@@ -191,6 +204,12 @@ struct miic {
spinlock_t lock;
struct reset_control_bulk_data rsts[MIIC_MAX_NUM_RSTS];
const struct miic_of_data *of_data;
+ struct miic_phy_link_cfg link_cfg;
+};
+
+enum miic_type {
+ MIIC_TYPE_RZN1,
+ MIIC_TYPE_RZT2H,
};
/**
@@ -210,6 +229,7 @@ struct miic {
* @init_unlock_lock_regs: Flag to indicate if registers need to be unlocked
* before access.
* @miic_write: Function pointer to write a value to a MIIC register
+ * @type: Type of MIIC
*/
struct miic_of_data {
struct modctrl_match *match_table;
@@ -226,6 +246,7 @@ struct miic_of_data {
u8 reset_count;
bool init_unlock_lock_regs;
void (*miic_write)(struct miic *miic, int offset, u32 value);
+ enum miic_type type;
};
/**
@@ -581,10 +602,79 @@ static int miic_match_dt_conf(struct miic *miic, s8 *dt_val, u32 *mode_cfg)
return -EINVAL;
}
+static void miic_configure_phy_link(struct miic *miic, u32 conf,
+ u32 port, bool active_low)
+{
+ bool polarity_active_high;
+ u32 mask, shift;
+
+ /* determine shift and polarity for this conf */
+ if (miic->of_data->type == MIIC_TYPE_RZN1) {
+ switch (conf) {
+ /* switch ports => bits [3:0] (shift 0), active when low */
+ case MIIC_SWITCH_PORTA:
+ case MIIC_SWITCH_PORTB:
+ case MIIC_SWITCH_PORTC:
+ case MIIC_SWITCH_PORTD:
+ shift = 0;
+ polarity_active_high = false;
+ break;
+
+ /* EtherCAT ports => bits [7:4] (shift 4), active when high */
+ case MIIC_ETHERCAT_PORTA:
+ case MIIC_ETHERCAT_PORTB:
+ case MIIC_ETHERCAT_PORTC:
+ shift = 4;
+ polarity_active_high = true;
+ break;
+
+ /* Sercos ports => bits [11:8] (shift 8), active when high */
+ case MIIC_SERCOS_PORTA:
+ case MIIC_SERCOS_PORTB:
+ shift = 8;
+ polarity_active_high = true;
+ break;
+
+ default:
+ return;
+ }
+ } else {
+ switch (conf) {
+ /* ETHSW ports => bits [3:0] (shift 0), active when low */
+ case ETHSS_ETHSW_PORT0:
+ case ETHSS_ETHSW_PORT1:
+ case ETHSS_ETHSW_PORT2:
+ shift = 0;
+ polarity_active_high = false;
+ break;
+
+ /* ESC ports => bits [7:4] (shift 4), active when high */
+ case ETHSS_ESC_PORT0:
+ case ETHSS_ESC_PORT1:
+ case ETHSS_ESC_PORT2:
+ shift = 4;
+ polarity_active_high = true;
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ mask = BIT(port + shift);
+
+ miic->link_cfg.mask |= mask;
+ if (polarity_active_high != active_low)
+ miic->link_cfg.val |= mask;
+ else
+ miic->link_cfg.val &= ~mask;
+}
+
static int miic_parse_dt(struct miic *miic, u32 *mode_cfg)
{
struct device_node *np = miic->dev->of_node;
struct device_node *conv;
+ bool active_low;
int port, ret;
s8 *dt_val;
u32 conf;
@@ -603,10 +693,15 @@ static int miic_parse_dt(struct miic *miic, u32 *mode_cfg)
if (of_property_read_u32(conv, "reg", &port))
continue;
+ if (of_property_read_u32(conv, "renesas,miic-input", &conf))
+ continue;
+
/* Adjust for 0 based index */
- port += !miic->of_data->miic_port_start;
- if (of_property_read_u32(conv, "renesas,miic-input", &conf) == 0)
- dt_val[port] = conf;
+ dt_val[port + !miic->of_data->miic_port_start] = conf;
+
+ active_low = of_property_read_bool(conv, "renesas,miic-phy-link-active-low");
+
+ miic_configure_phy_link(miic, conf, port, active_low);
}
ret = miic_match_dt_conf(miic, dt_val, mode_cfg);
@@ -696,6 +791,8 @@ static int miic_probe(struct platform_device *pdev)
if (ret)
goto disable_runtime_pm;
+ miic_reg_rmw(miic, MIIC_PHY_LINK, miic->link_cfg.mask, miic->link_cfg.val);
+
/* miic_create() relies on that fact that data are attached to the
* platform device to determine if the driver is ready so this needs to
* be the last thing to be done after everything is initialized
@@ -729,6 +826,7 @@ static struct miic_of_data rzn1_miic_of_data = {
.sw_mode_mask = GENMASK(4, 0),
.init_unlock_lock_regs = true,
.miic_write = miic_reg_writel_unlocked,
+ .type = MIIC_TYPE_RZN1,
};
static struct miic_of_data rzt2h_miic_of_data = {
@@ -745,6 +843,7 @@ static struct miic_of_data rzt2h_miic_of_data = {
.reset_ids = rzt2h_reset_ids,
.reset_count = ARRAY_SIZE(rzt2h_reset_ids),
.miic_write = miic_reg_writel_locked,
+ .type = MIIC_TYPE_RZT2H,
};
static const struct of_device_id miic_of_mtable[] = {