Skip to content

Commit 44dd5ef

Browse files
committed
Merge branch 'Support-programmable-pins-for-Ocelot-PTP-driver'
Yangbo Lu says: ==================== Support programmable pins for Ocelot PTP driver The Ocelot PTP clock driver had been embedded into ocelot.c driver. It had supported basic gettime64/settime64/adjtime/adjfine functions by now which were used by both Ocelot switch and Felix switch. This patch-set is to move current ptp clock code out of ocelot.c driver maintaining as a single ocelot_ptp.c driver, and to implement 4 programmable pins with only PTP_PF_PEROUT function for now. The PTP_PF_EXTTS function will be supported in the future, and it should be implemented separately for Felix and Ocelot, because of different hardware interrupt implementation in them. Changes for v2: - Put PTP driver under drivers/net/ethernet/mscc/. - Dropped MAINTAINERS patch. Kept original maintaining. - Initialized PTP separately in ocelot/felix platforms. - Supported PPS case in programmable pin. - Supported disabling pin function since deadlock is fixed by Richard. - Returned -EBUSY if not finding pin available. Changes for v3: - Re-sent. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 5921105 + 5287be4 commit 44dd5ef

File tree

10 files changed

+417
-214
lines changed

10 files changed

+417
-214
lines changed

drivers/net/dsa/ocelot/felix.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <soc/mscc/ocelot_sys.h>
88
#include <soc/mscc/ocelot_dev.h>
99
#include <soc/mscc/ocelot_ana.h>
10+
#include <soc/mscc/ocelot_ptp.h>
1011
#include <soc/mscc/ocelot.h>
1112
#include <linux/packing.h>
1213
#include <linux/module.h>
@@ -494,6 +495,23 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
494495
return 0;
495496
}
496497

498+
static struct ptp_clock_info ocelot_ptp_clock_info = {
499+
.owner = THIS_MODULE,
500+
.name = "felix ptp",
501+
.max_adj = 0x7fffffff,
502+
.n_alarm = 0,
503+
.n_ext_ts = 0,
504+
.n_per_out = OCELOT_PTP_PINS_NUM,
505+
.n_pins = OCELOT_PTP_PINS_NUM,
506+
.pps = 0,
507+
.gettime64 = ocelot_ptp_gettime64,
508+
.settime64 = ocelot_ptp_settime64,
509+
.adjtime = ocelot_ptp_adjtime,
510+
.adjfine = ocelot_ptp_adjfine,
511+
.verify = ocelot_ptp_verify,
512+
.enable = ocelot_ptp_enable,
513+
};
514+
497515
/* Hardware initialization done here so that we can allocate structures with
498516
* devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
499517
* us to allocate structures twice (leak memory) and map PCI memory twice
@@ -510,6 +528,14 @@ static int felix_setup(struct dsa_switch *ds)
510528
return err;
511529

512530
ocelot_init(ocelot);
531+
if (ocelot->ptp) {
532+
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
533+
if (err) {
534+
dev_err(ocelot->dev,
535+
"Timestamp initialization failed\n");
536+
ocelot->ptp = 0;
537+
}
538+
}
513539

514540
for (port = 0; port < ds->num_ports; port++) {
515541
ocelot_init_port(ocelot, port);
@@ -548,6 +574,7 @@ static void felix_teardown(struct dsa_switch *ds)
548574
if (felix->info->mdio_bus_free)
549575
felix->info->mdio_bus_free(ocelot);
550576

577+
ocelot_deinit_timestamp(ocelot);
551578
/* stop workqueue thread */
552579
ocelot_deinit(ocelot);
553580
}

drivers/net/dsa/ocelot/felix_vsc9959.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ static const u32 vsc9959_ptp_regmap[] = {
313313
REG(PTP_PIN_TOD_SEC_MSB, 0x000004),
314314
REG(PTP_PIN_TOD_SEC_LSB, 0x000008),
315315
REG(PTP_PIN_TOD_NSEC, 0x00000c),
316+
REG(PTP_PIN_WF_HIGH_PERIOD, 0x000014),
317+
REG(PTP_PIN_WF_LOW_PERIOD, 0x000018),
316318
REG(PTP_CFG_MISC, 0x0000a0),
317319
REG(PTP_CLK_CFG_ADJ_CFG, 0x0000a4),
318320
REG(PTP_CLK_CFG_ADJ_FREQ, 0x0000a8),

drivers/net/ethernet/mscc/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# SPDX-License-Identifier: (GPL-2.0 OR MIT)
22
obj-$(CONFIG_MSCC_OCELOT_SWITCH) += mscc_ocelot_common.o
33
mscc_ocelot_common-y := ocelot.o ocelot_io.o
4-
mscc_ocelot_common-y += ocelot_regs.o ocelot_tc.o ocelot_police.o ocelot_ace.o ocelot_flower.o
4+
mscc_ocelot_common-y += ocelot_regs.o ocelot_tc.o ocelot_police.o ocelot_ace.o ocelot_flower.o ocelot_ptp.o
55
obj-$(CONFIG_MSCC_OCELOT_SWITCH_OCELOT) += ocelot_board.o

drivers/net/ethernet/mscc/ocelot.c

Lines changed: 6 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <linux/module.h>
1515
#include <linux/netdevice.h>
1616
#include <linux/phy.h>
17-
#include <linux/ptp_clock_kernel.h>
1817
#include <linux/skbuff.h>
1918
#include <linux/iopoll.h>
2019
#include <net/arp.h>
@@ -1350,6 +1349,12 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port,
13501349
{
13511350
info->phc_index = ocelot->ptp_clock ?
13521351
ptp_clock_index(ocelot->ptp_clock) : -1;
1352+
if (info->phc_index == -1) {
1353+
info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
1354+
SOF_TIMESTAMPING_RX_SOFTWARE |
1355+
SOF_TIMESTAMPING_SOFTWARE;
1356+
return 0;
1357+
}
13531358
info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
13541359
SOF_TIMESTAMPING_RX_SOFTWARE |
13551360
SOF_TIMESTAMPING_SOFTWARE |
@@ -1991,200 +1996,6 @@ struct notifier_block ocelot_switchdev_blocking_nb __read_mostly = {
19911996
};
19921997
EXPORT_SYMBOL(ocelot_switchdev_blocking_nb);
19931998

1994-
int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
1995-
{
1996-
struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
1997-
unsigned long flags;
1998-
time64_t s;
1999-
u32 val;
2000-
s64 ns;
2001-
2002-
spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
2003-
2004-
val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
2005-
val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
2006-
val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
2007-
ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
2008-
2009-
s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff;
2010-
s <<= 32;
2011-
s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
2012-
ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
2013-
2014-
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
2015-
2016-
/* Deal with negative values */
2017-
if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
2018-
s--;
2019-
ns &= 0xf;
2020-
ns += 999999984;
2021-
}
2022-
2023-
set_normalized_timespec64(ts, s, ns);
2024-
return 0;
2025-
}
2026-
EXPORT_SYMBOL(ocelot_ptp_gettime64);
2027-
2028-
static int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
2029-
const struct timespec64 *ts)
2030-
{
2031-
struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
2032-
unsigned long flags;
2033-
u32 val;
2034-
2035-
spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
2036-
2037-
val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
2038-
val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
2039-
val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
2040-
2041-
ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
2042-
2043-
ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
2044-
TOD_ACC_PIN);
2045-
ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
2046-
TOD_ACC_PIN);
2047-
ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
2048-
2049-
val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
2050-
val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
2051-
val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
2052-
2053-
ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
2054-
2055-
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
2056-
return 0;
2057-
}
2058-
2059-
static int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
2060-
{
2061-
if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
2062-
struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
2063-
unsigned long flags;
2064-
u32 val;
2065-
2066-
spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
2067-
2068-
val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
2069-
val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
2070-
val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
2071-
2072-
ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
2073-
2074-
ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
2075-
ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
2076-
ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
2077-
2078-
val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
2079-
val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
2080-
val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
2081-
2082-
ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
2083-
2084-
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
2085-
} else {
2086-
/* Fall back using ocelot_ptp_settime64 which is not exact. */
2087-
struct timespec64 ts;
2088-
u64 now;
2089-
2090-
ocelot_ptp_gettime64(ptp, &ts);
2091-
2092-
now = ktime_to_ns(timespec64_to_ktime(ts));
2093-
ts = ns_to_timespec64(now + delta);
2094-
2095-
ocelot_ptp_settime64(ptp, &ts);
2096-
}
2097-
return 0;
2098-
}
2099-
2100-
static int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
2101-
{
2102-
struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
2103-
u32 unit = 0, direction = 0;
2104-
unsigned long flags;
2105-
u64 adj = 0;
2106-
2107-
spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
2108-
2109-
if (!scaled_ppm)
2110-
goto disable_adj;
2111-
2112-
if (scaled_ppm < 0) {
2113-
direction = PTP_CFG_CLK_ADJ_CFG_DIR;
2114-
scaled_ppm = -scaled_ppm;
2115-
}
2116-
2117-
adj = PSEC_PER_SEC << 16;
2118-
do_div(adj, scaled_ppm);
2119-
do_div(adj, 1000);
2120-
2121-
/* If the adjustment value is too large, use ns instead */
2122-
if (adj >= (1L << 30)) {
2123-
unit = PTP_CFG_CLK_ADJ_FREQ_NS;
2124-
do_div(adj, 1000);
2125-
}
2126-
2127-
/* Still too big */
2128-
if (adj >= (1L << 30))
2129-
goto disable_adj;
2130-
2131-
ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
2132-
ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
2133-
PTP_CLK_CFG_ADJ_CFG);
2134-
2135-
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
2136-
return 0;
2137-
2138-
disable_adj:
2139-
ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
2140-
2141-
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
2142-
return 0;
2143-
}
2144-
2145-
static struct ptp_clock_info ocelot_ptp_clock_info = {
2146-
.owner = THIS_MODULE,
2147-
.name = "ocelot ptp",
2148-
.max_adj = 0x7fffffff,
2149-
.n_alarm = 0,
2150-
.n_ext_ts = 0,
2151-
.n_per_out = 0,
2152-
.n_pins = 0,
2153-
.pps = 0,
2154-
.gettime64 = ocelot_ptp_gettime64,
2155-
.settime64 = ocelot_ptp_settime64,
2156-
.adjtime = ocelot_ptp_adjtime,
2157-
.adjfine = ocelot_ptp_adjfine,
2158-
};
2159-
2160-
static int ocelot_init_timestamp(struct ocelot *ocelot)
2161-
{
2162-
struct ptp_clock *ptp_clock;
2163-
2164-
ocelot->ptp_info = ocelot_ptp_clock_info;
2165-
ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
2166-
if (IS_ERR(ptp_clock))
2167-
return PTR_ERR(ptp_clock);
2168-
/* Check if PHC support is missing at the configuration level */
2169-
if (!ptp_clock)
2170-
return 0;
2171-
2172-
ocelot->ptp_clock = ptp_clock;
2173-
2174-
ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
2175-
ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
2176-
ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
2177-
2178-
ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
2179-
2180-
/* There is no device reconfiguration, PTP Rx stamping is always
2181-
* enabled.
2182-
*/
2183-
ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
2184-
2185-
return 0;
2186-
}
2187-
21881999
/* Configure the maximum SDU (L2 payload) on RX to the value specified in @sdu.
21892000
* The length of VLAN tags is accounted for automatically via DEV_MAC_TAGS_CFG.
21902001
* In the special case that it's the NPI port that we're configuring, the
@@ -2530,15 +2341,6 @@ int ocelot_init(struct ocelot *ocelot)
25302341
queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
25312342
OCELOT_STATS_CHECK_DELAY);
25322343

2533-
if (ocelot->ptp) {
2534-
ret = ocelot_init_timestamp(ocelot);
2535-
if (ret) {
2536-
dev_err(ocelot->dev,
2537-
"Timestamp initialization failed\n");
2538-
return ret;
2539-
}
2540-
}
2541-
25422344
return 0;
25432345
}
25442346
EXPORT_SYMBOL(ocelot_init);
@@ -2551,8 +2353,6 @@ void ocelot_deinit(struct ocelot *ocelot)
25512353
cancel_delayed_work(&ocelot->stats_work);
25522354
destroy_workqueue(ocelot->stats_queue);
25532355
mutex_destroy(&ocelot->stats_lock);
2554-
if (ocelot->ptp_clock)
2555-
ptp_clock_unregister(ocelot->ptp_clock);
25562356

25572357
for (i = 0; i < ocelot->num_phys_ports; i++) {
25582358
port = ocelot->ports[i];

drivers/net/ethernet/mscc/ocelot.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,17 @@
1515
#include <linux/phy.h>
1616
#include <linux/phy/phy.h>
1717
#include <linux/platform_device.h>
18-
#include <linux/ptp_clock_kernel.h>
1918
#include <linux/regmap.h>
2019

2120
#include <soc/mscc/ocelot_qsys.h>
2221
#include <soc/mscc/ocelot_sys.h>
2322
#include <soc/mscc/ocelot_dev.h>
2423
#include <soc/mscc/ocelot_ana.h>
24+
#include <soc/mscc/ocelot_ptp.h>
2525
#include <soc/mscc/ocelot.h>
2626
#include "ocelot_rew.h"
2727
#include "ocelot_qs.h"
2828
#include "ocelot_tc.h"
29-
#include "ocelot_ptp.h"
3029

3130
#define OCELOT_BUFFER_CELL_SZ 60
3231

drivers/net/ethernet/mscc/ocelot_board.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,23 @@ static const struct vcap_props vsc7514_vcap_props[] = {
366366
},
367367
};
368368

369+
static struct ptp_clock_info ocelot_ptp_clock_info = {
370+
.owner = THIS_MODULE,
371+
.name = "ocelot ptp",
372+
.max_adj = 0x7fffffff,
373+
.n_alarm = 0,
374+
.n_ext_ts = 0,
375+
.n_per_out = OCELOT_PTP_PINS_NUM,
376+
.n_pins = OCELOT_PTP_PINS_NUM,
377+
.pps = 0,
378+
.gettime64 = ocelot_ptp_gettime64,
379+
.settime64 = ocelot_ptp_settime64,
380+
.adjtime = ocelot_ptp_adjtime,
381+
.adjfine = ocelot_ptp_adjfine,
382+
.verify = ocelot_ptp_verify,
383+
.enable = ocelot_ptp_enable,
384+
};
385+
369386
static int mscc_ocelot_probe(struct platform_device *pdev)
370387
{
371388
struct device_node *np = pdev->dev.of_node;
@@ -469,6 +486,15 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
469486
ocelot->vcap = vsc7514_vcap_props;
470487

471488
ocelot_init(ocelot);
489+
if (ocelot->ptp) {
490+
err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
491+
if (err) {
492+
dev_err(ocelot->dev,
493+
"Timestamp initialization failed\n");
494+
ocelot->ptp = 0;
495+
}
496+
}
497+
472498
/* No NPI port */
473499
ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
474500
OCELOT_TAG_PREFIX_NONE);
@@ -574,6 +600,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
574600
{
575601
struct ocelot *ocelot = platform_get_drvdata(pdev);
576602

603+
ocelot_deinit_timestamp(ocelot);
577604
ocelot_deinit(ocelot);
578605
unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
579606
unregister_switchdev_notifier(&ocelot_switchdev_nb);

0 commit comments

Comments
 (0)