Commit 4a986617 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-dsa-mv88e6xxx-add-support-for-MV88E6220'

Hubert Feurstein says:

====================
net: dsa: mv88e6xxx: add support for MV88E6220

This patch series adds support for the MV88E6220 chip to the mv88e6xxx driver.
The MV88E6220 is almost the same as MV88E6250 except that the ports 2-4 are
not routed to pins.

Furthermore, PTP support is added to the MV88E6250 family.

v2:
 - insert all 6220 entries in correct numerical order
 - introduce invalid_port_mask
 - move ptp_cc_mult* to ptp_ops and restored original ptp_adjfine code
 - added Andrews Reviewed-By to patch 2 and 4
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3cc6e44b 71509614
...@@ -22,7 +22,7 @@ which is at a different MDIO base address in different switch families. ...@@ -22,7 +22,7 @@ which is at a different MDIO base address in different switch families.
- "marvell,mv88e6190" : Switch has base address 0x00. Use with models: - "marvell,mv88e6190" : Switch has base address 0x00. Use with models:
6190, 6190X, 6191, 6290, 6390, 6390X 6190, 6190X, 6191, 6290, 6390, 6390X
- "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model: - "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model:
6250 6220, 6250
Required properties: Required properties:
- compatible : Should be one of "marvell,mv88e6085", - compatible : Should be one of "marvell,mv88e6085",
......
This diff is collapsed.
...@@ -57,6 +57,7 @@ enum mv88e6xxx_model { ...@@ -57,6 +57,7 @@ enum mv88e6xxx_model {
MV88E6190, MV88E6190,
MV88E6190X, MV88E6190X,
MV88E6191, MV88E6191,
MV88E6220,
MV88E6240, MV88E6240,
MV88E6250, MV88E6250,
MV88E6290, MV88E6290,
...@@ -77,7 +78,7 @@ enum mv88e6xxx_family { ...@@ -77,7 +78,7 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
MV88E6XXX_FAMILY_6250, /* 6250 */ MV88E6XXX_FAMILY_6250, /* 6220 6250 */
MV88E6XXX_FAMILY_6320, /* 6320 6321 */ MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6341, /* 6141 6341 */ MV88E6XXX_FAMILY_6341, /* 6141 6341 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
...@@ -105,6 +106,11 @@ struct mv88e6xxx_info { ...@@ -105,6 +106,11 @@ struct mv88e6xxx_info {
unsigned int g2_irqs; unsigned int g2_irqs;
bool pvt; bool pvt;
/* Mark certain ports as invalid. This is required for example for the
* MV88E6220 (which is in general a MV88E6250 with 7 ports) but the
* ports 2-4 are not routet to pins.
*/
unsigned int invalid_port_mask;
/* Multi-chip Addressing Mode. /* Multi-chip Addressing Mode.
* Some chips respond to only 2 registers of its own SMI device address * Some chips respond to only 2 registers of its own SMI device address
* when it is non-zero, and use indirect access to internal registers. * when it is non-zero, and use indirect access to internal registers.
...@@ -389,6 +395,7 @@ struct mv88e6xxx_ops { ...@@ -389,6 +395,7 @@ struct mv88e6xxx_ops {
u8 out); u8 out);
int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port); int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port);
int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port); int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port);
int (*port_setup_message_port)(struct mv88e6xxx_chip *chip, int port);
/* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc. /* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
* Some chips allow this to be configured on specific ports. * Some chips allow this to be configured on specific ports.
...@@ -532,6 +539,10 @@ struct mv88e6xxx_ptp_ops { ...@@ -532,6 +539,10 @@ struct mv88e6xxx_ptp_ops {
int arr1_sts_reg; int arr1_sts_reg;
int dep_sts_reg; int dep_sts_reg;
u32 rx_filters; u32 rx_filters;
u32 cc_shift;
u32 cc_mult;
u32 cc_mult_num;
u32 cc_mult_dem;
}; };
#define STATS_TYPE_PORT BIT(0) #define STATS_TYPE_PORT BIT(0)
...@@ -570,6 +581,11 @@ static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip) ...@@ -570,6 +581,11 @@ static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip)
return chip->info->num_gpio; return chip->info->num_gpio;
} }
static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int port)
{
return (chip->info->invalid_port_mask & BIT(port)) != 0;
}
int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
......
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6190 0x1900 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6190 0x1900
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
......
...@@ -15,11 +15,31 @@ ...@@ -15,11 +15,31 @@
#include "hwtstamp.h" #include "hwtstamp.h"
#include "ptp.h" #include "ptp.h"
/* Raw timestamps are in units of 8-ns clock periods. */ #define MV88E6XXX_MAX_ADJ_PPB 1000000
#define CC_SHIFT 28
#define CC_MULT (8 << CC_SHIFT) /* Family MV88E6250:
#define CC_MULT_NUM (1 << 9) * Raw timestamps are in units of 10-ns clock periods.
#define CC_MULT_DEM 15625ULL *
* clkadj = scaled_ppm * 10*2^28 / (10^6 * 2^16)
* simplifies to
* clkadj = scaled_ppm * 2^7 / 5^5
*/
#define MV88E6250_CC_SHIFT 28
#define MV88E6250_CC_MULT (10 << MV88E6250_CC_SHIFT)
#define MV88E6250_CC_MULT_NUM (1 << 7)
#define MV88E6250_CC_MULT_DEM 3125ULL
/* Other families:
* Raw timestamps are in units of 8-ns clock periods.
*
* clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16)
* simplifies to
* clkadj = scaled_ppm * 2^9 / 5^6
*/
#define MV88E6XXX_CC_SHIFT 28
#define MV88E6XXX_CC_MULT (8 << MV88E6XXX_CC_SHIFT)
#define MV88E6XXX_CC_MULT_NUM (1 << 9)
#define MV88E6XXX_CC_MULT_DEM 15625ULL
#define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100) #define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
...@@ -179,6 +199,7 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly) ...@@ -179,6 +199,7 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly)
static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{ {
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp); struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
int neg_adj = 0; int neg_adj = 0;
u32 diff, mult; u32 diff, mult;
u64 adj; u64 adj;
...@@ -187,10 +208,11 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) ...@@ -187,10 +208,11 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
neg_adj = 1; neg_adj = 1;
scaled_ppm = -scaled_ppm; scaled_ppm = -scaled_ppm;
} }
mult = CC_MULT;
adj = CC_MULT_NUM; mult = ptp_ops->cc_mult;
adj = ptp_ops->cc_mult_num;
adj *= scaled_ppm; adj *= scaled_ppm;
diff = div_u64(adj, CC_MULT_DEM); diff = div_u64(adj, ptp_ops->cc_mult_dem);
mv88e6xxx_reg_lock(chip); mv88e6xxx_reg_lock(chip);
...@@ -310,7 +332,27 @@ static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin, ...@@ -310,7 +332,27 @@ static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
return 0; return 0;
} }
const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = { const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
.clock_read = mv88e6165_ptp_clock_read,
.global_enable = mv88e6165_global_enable,
.global_disable = mv88e6165_global_disable,
.arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS,
.arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS,
.dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS,
.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
.cc_shift = MV88E6XXX_CC_SHIFT,
.cc_mult = MV88E6XXX_CC_MULT,
.cc_mult_num = MV88E6XXX_CC_MULT_NUM,
.cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
};
const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
.clock_read = mv88e6352_ptp_clock_read, .clock_read = mv88e6352_ptp_clock_read,
.ptp_enable = mv88e6352_ptp_enable, .ptp_enable = mv88e6352_ptp_enable,
.ptp_verify = mv88e6352_ptp_verify, .ptp_verify = mv88e6352_ptp_verify,
...@@ -331,22 +373,37 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = { ...@@ -331,22 +373,37 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
.cc_shift = MV88E6250_CC_SHIFT,
.cc_mult = MV88E6250_CC_MULT,
.cc_mult_num = MV88E6250_CC_MULT_NUM,
.cc_mult_dem = MV88E6250_CC_MULT_DEM,
}; };
const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = { const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
.clock_read = mv88e6165_ptp_clock_read, .clock_read = mv88e6352_ptp_clock_read,
.global_enable = mv88e6165_global_enable, .ptp_enable = mv88e6352_ptp_enable,
.global_disable = mv88e6165_global_disable, .ptp_verify = mv88e6352_ptp_verify,
.arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS, .event_work = mv88e6352_tai_event_work,
.arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS, .port_enable = mv88e6352_hwtstamp_port_enable,
.dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS, .port_disable = mv88e6352_hwtstamp_port_disable,
.n_ext_ts = 1,
.arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS,
.arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS,
.dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS,
.rx_filters = (1 << HWTSTAMP_FILTER_NONE) | .rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
.cc_shift = MV88E6XXX_CC_SHIFT,
.cc_mult = MV88E6XXX_CC_MULT,
.cc_mult_num = MV88E6XXX_CC_MULT_NUM,
.cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
}; };
static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc) static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
...@@ -384,8 +441,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) ...@@ -384,8 +441,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc)); memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
chip->tstamp_cc.read = mv88e6xxx_ptp_clock_read; chip->tstamp_cc.read = mv88e6xxx_ptp_clock_read;
chip->tstamp_cc.mask = CYCLECOUNTER_MASK(32); chip->tstamp_cc.mask = CYCLECOUNTER_MASK(32);
chip->tstamp_cc.mult = CC_MULT; chip->tstamp_cc.mult = ptp_ops->cc_mult;
chip->tstamp_cc.shift = CC_SHIFT; chip->tstamp_cc.shift = ptp_ops->cc_shift;
timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc, timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
ktime_to_ns(ktime_get_real())); ktime_to_ns(ktime_get_real()));
...@@ -397,7 +454,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) ...@@ -397,7 +454,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
chip->ptp_clock_info.owner = THIS_MODULE; chip->ptp_clock_info.owner = THIS_MODULE;
snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name), snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
"%s", dev_name(chip->dev)); "%s", dev_name(chip->dev));
chip->ptp_clock_info.max_adj = 1000000;
chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts; chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts;
chip->ptp_clock_info.n_per_out = 0; chip->ptp_clock_info.n_per_out = 0;
...@@ -413,6 +469,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) ...@@ -413,6 +469,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
} }
chip->ptp_clock_info.pin_config = chip->pin_config; chip->ptp_clock_info.pin_config = chip->pin_config;
chip->ptp_clock_info.max_adj = MV88E6XXX_MAX_ADJ_PPB;
chip->ptp_clock_info.adjfine = mv88e6xxx_ptp_adjfine; chip->ptp_clock_info.adjfine = mv88e6xxx_ptp_adjfine;
chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime; chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime;
chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime; chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime;
......
...@@ -148,8 +148,9 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip); ...@@ -148,8 +148,9 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
#define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip, \ #define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip, \
ptp_clock_info) ptp_clock_info)
extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops;
extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops; extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops;
extern const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops;
extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops;
#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */ #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
...@@ -167,8 +168,9 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip) ...@@ -167,8 +168,9 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
{ {
} }
static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {};
static const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {}; static const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {};
static const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {};
static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {};
#endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */ #endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment