Messages in this thread | | | Date | Tue, 15 Aug 2023 15:37:26 +0530 | Subject | Re: [PATCH v4 3/5] net: ti: icss-iep: Add IEP driver | From | "Anwar, Md Danish" <> |
| |
Hi Roger,
On 8/15/2023 3:11 PM, Roger Quadros wrote: > Hi Danish, > > On 14/08/2023 13:08, MD Danish Anwar wrote: >> From: Roger Quadros <rogerq@ti.com> >> >> Add a driver for Industrial Ethernet Peripheral (IEP) block of PRUSS to >> support timestamping of ethernet packets and thus support PTP and PPS >> for PRU ethernet ports. >> >> Signed-off-by: Roger Quadros <rogerq@ti.com> >> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com> >> Signed-off-by: Murali Karicheri <m-karicheri2@ti.com> >> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> >> Signed-off-by: MD Danish Anwar <danishanwar@ti.com> >> --- >> drivers/net/ethernet/ti/Kconfig | 11 + >> drivers/net/ethernet/ti/Makefile | 1 + >> drivers/net/ethernet/ti/icssg/icss_iep.c | 921 +++++++++++++++++++++++ >> drivers/net/ethernet/ti/icssg/icss_iep.h | 38 + >> 4 files changed, 971 insertions(+) >> create mode 100644 drivers/net/ethernet/ti/icssg/icss_iep.c >> create mode 100644 drivers/net/ethernet/ti/icssg/icss_iep.h >> >> diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig >> index 63e510b6860f..1af5a90720ec 100644 >> --- a/drivers/net/ethernet/ti/Kconfig >> +++ b/drivers/net/ethernet/ti/Kconfig >> @@ -196,4 +196,15 @@ config TI_ICSSG_PRUETH >> to support the Ethernet operation. Currently, it supports Ethernet >> with 1G and 100M link speed. >> >> +config TI_ICSS_IEP >> + tristate "TI PRU ICSS IEP driver" >> + depends on TI_PRUSS >> + default TI_PRUSS >> + help >> + This driver enables support for the PRU-ICSS Industrial Ethernet >> + Peripheral within a PRU-ICSS subsystem present on various TI SoCs. >> + >> + To compile this driver as a module, choose M here. The module >> + will be called icss_iep. >> + >> endif # NET_VENDOR_TI >> diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile >> index 9176d79c36e1..34fd7a716ba6 100644 >> --- a/drivers/net/ethernet/ti/Makefile >> +++ b/drivers/net/ethernet/ti/Makefile >> @@ -38,3 +38,4 @@ icssg-prueth-y := k3-cppi-desc-pool.o \ >> icssg/icssg_mii_cfg.o \ >> icssg/icssg_stats.o \ >> icssg/icssg_ethtool.o >> +obj-$(CONFIG_TI_ICSS_IEP) += icssg/icss_iep.o >> diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c >> new file mode 100644 >> index 000000000000..d123b8ba3f31 >> --- /dev/null >> +++ b/drivers/net/ethernet/ti/icssg/icss_iep.c >> @@ -0,0 +1,921 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> + >> +/* Texas Instruments ICSSG Industrial Ethernet Peripheral (IEP) Driver >> + * >> + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com >> + * >> + */ >> + >> +#include <linux/bitops.h> >> +#include <linux/clk.h> >> +#include <linux/err.h> >> +#include <linux/io.h> >> +#include <linux/module.h> >> +#include <linux/of.h> >> +#include <linux/of_platform.h> >> +#include <linux/platform_device.h> >> +#include <linux/timekeeping.h> >> +#include <linux/interrupt.h> >> +#include <linux/of_irq.h> >> + >> +#include "icss_iep.h" >> + >> +#define IEP_MAX_DEF_INC 0xf >> +#define IEP_MAX_COMPEN_INC 0xfff >> +#define IEP_MAX_COMPEN_COUNT 0xffffff >> + >> +#define IEP_GLOBAL_CFG_CNT_ENABLE BIT(0) >> +#define IEP_GLOBAL_CFG_DEFAULT_INC_MASK GENMASK(7, 4) >> +#define IEP_GLOBAL_CFG_DEFAULT_INC_SHIFT 4 >> +#define IEP_GLOBAL_CFG_COMPEN_INC_MASK GENMASK(19, 8) >> +#define IEP_GLOBAL_CFG_COMPEN_INC_SHIFT 8 >> + >> +#define IEP_GLOBAL_STATUS_CNT_OVF BIT(0) >> + >> +#define IEP_CMP_CFG_SHADOW_EN BIT(17) >> +#define IEP_CMP_CFG_CMP0_RST_CNT_EN BIT(0) >> +#define IEP_CMP_CFG_CMP_EN(cmp) (GENMASK(16, 1) & (1 << ((cmp) + 1))) >> + >> +#define IEP_CMP_STATUS(cmp) (1 << (cmp)) >> + >> +#define IEP_SYNC_CTRL_SYNC_EN BIT(0) >> +#define IEP_SYNC_CTRL_SYNC_N_EN(n) (GENMASK(2, 1) & (BIT(1) << (n))) >> + >> +#define IEP_MIN_CMP 0 >> +#define IEP_MAX_CMP 15 >> + >> +#define ICSS_IEP_64BIT_COUNTER_SUPPORT BIT(0) >> +#define ICSS_IEP_SLOW_COMPEN_REG_SUPPORT BIT(1) >> +#define ICSS_IEP_SHADOW_MODE_SUPPORT BIT(2) >> + >> +#define LATCH_INDEX(ts_index) ((ts_index) + 6) >> +#define IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(n) BIT(LATCH_INDEX(n)) >> +#define IEP_CAP_CFG_CAP_ASYNC_EN(n) BIT(LATCH_INDEX(n) + 10) >> + >> +enum { >> + ICSS_IEP_GLOBAL_CFG_REG, >> + ICSS_IEP_GLOBAL_STATUS_REG, >> + ICSS_IEP_COMPEN_REG, >> + ICSS_IEP_SLOW_COMPEN_REG, >> + ICSS_IEP_COUNT_REG0, >> + ICSS_IEP_COUNT_REG1, >> + ICSS_IEP_CAPTURE_CFG_REG, >> + ICSS_IEP_CAPTURE_STAT_REG, >> + >> + ICSS_IEP_CAP6_RISE_REG0, >> + ICSS_IEP_CAP6_RISE_REG1, >> + >> + ICSS_IEP_CAP7_RISE_REG0, >> + ICSS_IEP_CAP7_RISE_REG1, >> + >> + ICSS_IEP_CMP_CFG_REG, >> + ICSS_IEP_CMP_STAT_REG, >> + ICSS_IEP_CMP0_REG0, >> + ICSS_IEP_CMP0_REG1, >> + ICSS_IEP_CMP1_REG0, >> + ICSS_IEP_CMP1_REG1, >> + >> + ICSS_IEP_CMP8_REG0, >> + ICSS_IEP_CMP8_REG1, >> + ICSS_IEP_SYNC_CTRL_REG, >> + ICSS_IEP_SYNC0_STAT_REG, >> + ICSS_IEP_SYNC1_STAT_REG, >> + ICSS_IEP_SYNC_PWIDTH_REG, >> + ICSS_IEP_SYNC0_PERIOD_REG, >> + ICSS_IEP_SYNC1_DELAY_REG, >> + ICSS_IEP_SYNC_START_REG, >> + ICSS_IEP_MAX_REGS, >> +}; >> + >> +/** >> + * struct icss_iep_plat_data - Plat data to handle SoC variants >> + * @config: Regmap configuration data >> + * @reg_offs: register offsets to capture offset differences across SoCs >> + * @flags: Flags to represent IEP properties >> + */ >> +struct icss_iep_plat_data { >> + struct regmap_config *config; >> + u32 reg_offs[ICSS_IEP_MAX_REGS]; >> + u32 flags; >> +}; >> + >> +struct icss_iep { >> + struct device *dev; >> + void __iomem *base; >> + const struct icss_iep_plat_data *plat_data; >> + struct regmap *map; >> + struct device_node *client_np; >> + unsigned long refclk_freq; >> + int clk_tick_time; /* one refclk tick time in ns */ >> + struct ptp_clock_info ptp_info; >> + struct ptp_clock *ptp_clock; >> + struct mutex ptp_clk_mutex; /* PHC access serializer */ >> + spinlock_t irq_lock; /* CMP IRQ vs icss_iep_ptp_enable access */ >> + u32 def_inc; >> + s16 slow_cmp_inc; >> + u32 slow_cmp_count; >> + const struct icss_iep_clockops *ops; >> + void *clockops_data; >> + u32 cycle_time_ns; >> + u32 perout_enabled; >> + bool pps_enabled; >> + int cap_cmp_irq; >> + u64 period; >> + u32 latch_enable; >> +}; >> + > > Where is the comment you agreed to add on why we are using readl/writel > instead of regmap in certain areas? >
We agreed to add comment on why we are using readl/writel instead of regmap in the documentation of the readl / writel helper APIs (icss_iep_readl / writel ). But Andrew asked me to drop those helper APIs, so I dropped them. Now no helper APIs are there and we are directly using readl / writel in total 8 places. Previously with the helper APIs, there was a way to document the use of readl / writel before the declaration of heper APIs. Now with no helper APIs, I couldn't find a good place to add this documentation as all 8 instances using readl / writel seems similar. So I dropped it.
>> +/** >> + * icss_iep_get_count_hi() - Get the upper 32 bit IEP counter >> + * @iep: Pointer to structure representing IEP. >> + * >> + * Return: upper 32 bit IEP counter >> + */ >> +int icss_iep_get_count_hi(struct icss_iep *iep) >> +{ >> + u32 val = 0; >> + >> + if (iep && (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)) >> + val = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); >> + >> + return val; >> +} >> +EXPORT_SYMBOL_GPL(icss_iep_get_count_hi); >> + >> +/** >> + * icss_iep_get_count_low() - Get the lower 32 bit IEP counter >> + * @iep: Pointer to structure representing IEP. >> + * >> + * Return: lower 32 bit IEP counter >> + */ >> +int icss_iep_get_count_low(struct icss_iep *iep) >> +{ >> + u32 val = 0; >> + >> + if (iep) >> + val = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); >> + >> + return val; >> +} >> +EXPORT_SYMBOL_GPL(icss_iep_get_count_low); >> + >> +/** >> + * icss_iep_get_ptp_clock_idx() - Get PTP clock index using IEP driver >> + * @iep: Pointer to structure representing IEP. >> + * >> + * Return: PTP clock index, -1 if not registered >> + */ >> +int icss_iep_get_ptp_clock_idx(struct icss_iep *iep) >> +{ >> + if (!iep || !iep->ptp_clock) >> + return -1; >> + return ptp_clock_index(iep->ptp_clock); >> +} >> +EXPORT_SYMBOL_GPL(icss_iep_get_ptp_clock_idx); >> + >> +static void icss_iep_set_counter(struct icss_iep *iep, u64 ns) >> +{ >> + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) >> + writel(upper_32_bits(ns), iep->base + >> + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); >> + writel(upper_32_bits(ns), iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); >> +} >> + >> +static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns); >> + >> +static void icss_iep_settime(struct icss_iep *iep, u64 ns) >> +{ >> + unsigned long flags; >> + >> + if (iep->ops && iep->ops->settime) { >> + iep->ops->settime(iep->clockops_data, ns); >> + return; >> + } >> + >> + spin_lock_irqsave(&iep->irq_lock, flags); >> + if (iep->pps_enabled || iep->perout_enabled) >> + writel(0, iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); >> + >> + icss_iep_set_counter(iep, ns); >> + >> + if (iep->pps_enabled || iep->perout_enabled) { >> + icss_iep_update_to_next_boundary(iep, ns); >> + writel(IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN, >> + iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); >> + } >> + spin_unlock_irqrestore(&iep->irq_lock, flags); >> +} >> + >> +static u64 icss_iep_gettime(struct icss_iep *iep, >> + struct ptp_system_timestamp *sts) >> +{ >> + u32 ts_hi = 0, ts_lo; >> + unsigned long flags; >> + >> + if (iep->ops && iep->ops->gettime) >> + return iep->ops->gettime(iep->clockops_data, sts); >> + >> + /* use local_irq_x() to make it work for both RT/non-RT */ >> + local_irq_save(flags); >> + >> + /* no need to play with hi-lo, hi is latched when lo is read */ >> + ptp_read_system_prets(sts); >> + ts_lo = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); >> + ptp_read_system_postts(sts); >> + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) >> + ts_hi = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); >> + >> + local_irq_restore(flags); >> + >> + return (u64)ts_lo | (u64)ts_hi << 32; >> +} >> + >> +static void icss_iep_enable(struct icss_iep *iep) >> +{ >> + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, >> + IEP_GLOBAL_CFG_CNT_ENABLE, >> + IEP_GLOBAL_CFG_CNT_ENABLE); >> +} >> + > <snip> >
-- Thanks and Regards, Md Danish Anwar
| |