Commit 91d0a48a authored by David S. Miller's avatar David S. Miller

Merge branch 'Reuse-ptp_qoriq-driver-for-dpaa2-ptp'

Yangbo Lu says:

====================
Reuse ptp_qoriq driver for dpaa2-ptp

Although dpaa2-ptp.c driver is a fsl_mc_driver which
is using MC APIs for register accessing, it's same IP
block with eTSEC/DPAA/ENETC 1588 timer.
This patch-set is to convert to reuse ptp_qoriq driver by
using register ioremap and dropping related MC APIs.
However the interrupts could only be handled by MC which
fires MSIs to ARM cores. So the interrupt enabling and
handling still rely on MC APIs. MC APIs for interrupt
and PPS event support are also added by this patch-set.

---
Changes for v2:
	- Allowed to compile with COMPILE_TEST.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 930cfe0f 28c67157
...@@ -4,7 +4,8 @@ General Properties: ...@@ -4,7 +4,8 @@ General Properties:
- compatible Should be "fsl,etsec-ptp" for eTSEC - compatible Should be "fsl,etsec-ptp" for eTSEC
Should be "fsl,fman-ptp-timer" for DPAA FMan Should be "fsl,fman-ptp-timer" for DPAA FMan
Should be "fsl,enetc-ptp" for ENETC Should be "fsl,dpaa2-ptp" for DPAA2
Should be "fsl,enetc-ptp" for ENETC
- reg Offset and length of the register set for the device - reg Offset and length of the register set for the device
- interrupts There should be at least two interrupts. Some devices - interrupts There should be at least two interrupts. Some devices
have as many as four PTP related interrupts. have as many as four PTP related interrupts.
......
...@@ -4922,13 +4922,6 @@ L: linux-kernel@vger.kernel.org ...@@ -4922,13 +4922,6 @@ L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
F: drivers/staging/fsl-dpaa2/ethsw F: drivers/staging/fsl-dpaa2/ethsw
DPAA2 PTP CLOCK DRIVER
M: Yangbo Lu <yangbo.lu@nxp.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp*
F: drivers/net/ethernet/freescale/dpaa2/dprtc*
DPT_I2O SCSI RAID DRIVER DPT_I2O SCSI RAID DRIVER
M: Adaptec OEM Raid Solutions <aacraid@microsemi.com> M: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
L: linux-scsi@vger.kernel.org L: linux-scsi@vger.kernel.org
...@@ -6371,6 +6364,8 @@ FREESCALE QORIQ PTP CLOCK DRIVER ...@@ -6371,6 +6364,8 @@ FREESCALE QORIQ PTP CLOCK DRIVER
M: Yangbo Lu <yangbo.lu@nxp.com> M: Yangbo Lu <yangbo.lu@nxp.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp*
F: drivers/net/ethernet/freescale/dpaa2/dprtc*
F: drivers/net/ethernet/freescale/enetc/enetc_ptp.c F: drivers/net/ethernet/freescale/enetc/enetc_ptp.c
F: drivers/ptp/ptp_qoriq.c F: drivers/ptp/ptp_qoriq.c
F: drivers/ptp/ptp_qoriq_debugfs.c F: drivers/ptp/ptp_qoriq_debugfs.c
......
...@@ -609,6 +609,14 @@ smmu: iommu@5000000 { ...@@ -609,6 +609,14 @@ smmu: iommu@5000000 {
<GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>; <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
}; };
ptp-timer@8b95000 {
compatible = "fsl,dpaa2-ptp";
reg = <0x0 0x8b95000 0x0 0x100>;
clocks = <&clockgen 4 0>;
little-endian;
fsl,extts-fifo;
};
cluster1_core0_watchdog: wdt@c000000 { cluster1_core0_watchdog: wdt@c000000 {
compatible = "arm,sp805-wdt", "arm,primecell"; compatible = "arm,sp805-wdt", "arm,primecell";
reg = <0x0 0xc000000 0x0 0x1000>; reg = <0x0 0xc000000 0x0 0x1000>;
......
...@@ -321,6 +321,14 @@ sec_jr3: jr@40000 { ...@@ -321,6 +321,14 @@ sec_jr3: jr@40000 {
}; };
}; };
ptp-timer@8b95000 {
compatible = "fsl,dpaa2-ptp";
reg = <0x0 0x8b95000 0x0 0x100>;
clocks = <&clockgen 4 1>;
little-endian;
fsl,extts-fifo;
};
fsl_mc: fsl-mc@80c000000 { fsl_mc: fsl-mc@80c000000 {
compatible = "fsl,qoriq-mc"; compatible = "fsl,qoriq-mc";
reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */
......
...@@ -848,6 +848,14 @@ smmu: iommu@5000000 { ...@@ -848,6 +848,14 @@ smmu: iommu@5000000 {
dma-coherent; dma-coherent;
}; };
ptp-timer@8b95000 {
compatible = "fsl,dpaa2-ptp";
reg = <0x0 0x8b95000 0x0 0x100>;
clocks = <&clockgen 4 1>;
little-endian;
fsl,extts-fifo;
};
fsl_mc: fsl-mc@80c000000 { fsl_mc: fsl-mc@80c000000 {
compatible = "fsl,qoriq-mc"; compatible = "fsl,qoriq-mc";
reg = <0x00000008 0x0c000000 0 0x40>, reg = <0x00000008 0x0c000000 0 0x40>,
......
...@@ -10,8 +10,7 @@ config FSL_DPAA2_ETH ...@@ -10,8 +10,7 @@ config FSL_DPAA2_ETH
config FSL_DPAA2_PTP_CLOCK config FSL_DPAA2_PTP_CLOCK
tristate "Freescale DPAA2 PTP Clock" tristate "Freescale DPAA2 PTP Clock"
depends on FSL_DPAA2_ETH depends on FSL_DPAA2_ETH && PTP_1588_CLOCK_QORIQ
imply PTP_1588_CLOCK
default y default y
help help
This driver adds support for using the DPAA2 1588 timer module This driver adds support for using the DPAA2 1588 timer module
......
...@@ -5,114 +5,58 @@ ...@@ -5,114 +5,58 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/of.h>
#include <linux/ptp_clock_kernel.h> #include <linux/of_address.h>
#include <linux/msi.h>
#include <linux/fsl/mc.h> #include <linux/fsl/mc.h>
#include <linux/fsl/ptp_qoriq.h>
#include "dpaa2-ptp.h" #include "dpaa2-ptp.h"
struct ptp_dpaa2_priv { static int dpaa2_ptp_enable(struct ptp_clock_info *ptp,
struct fsl_mc_device *ptp_mc_dev; struct ptp_clock_request *rq, int on)
struct ptp_clock *clock;
struct ptp_clock_info caps;
u32 freq_comp;
};
/* PTP clock operations */
static int ptp_dpaa2_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
{ {
struct ptp_dpaa2_priv *ptp_dpaa2 = struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
container_of(ptp, struct ptp_dpaa2_priv, caps); struct fsl_mc_device *mc_dev;
struct fsl_mc_device *mc_dev = ptp_dpaa2->ptp_mc_dev; struct device *dev;
struct device *dev = &mc_dev->dev; u32 mask = 0;
u64 adj; u32 bit;
u32 diff, tmr_add; int err;
int neg_adj = 0;
int err = 0;
if (ppb < 0) {
neg_adj = 1;
ppb = -ppb;
}
tmr_add = ptp_dpaa2->freq_comp;
adj = tmr_add;
adj *= ppb;
diff = div_u64(adj, 1000000000ULL);
tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
err = dprtc_set_freq_compensation(mc_dev->mc_io, 0, dev = ptp_qoriq->dev;
mc_dev->mc_handle, tmr_add); mc_dev = to_fsl_mc_device(dev);
if (err)
dev_err(dev, "dprtc_set_freq_compensation err %d\n", err);
return err;
}
static int ptp_dpaa2_adjtime(struct ptp_clock_info *ptp, s64 delta) switch (rq->type) {
{ case PTP_CLK_REQ_PPS:
struct ptp_dpaa2_priv *ptp_dpaa2 = bit = DPRTC_EVENT_PPS;
container_of(ptp, struct ptp_dpaa2_priv, caps); break;
struct fsl_mc_device *mc_dev = ptp_dpaa2->ptp_mc_dev; default:
struct device *dev = &mc_dev->dev; return -EOPNOTSUPP;
s64 now; }
int err = 0;
err = dprtc_get_time(mc_dev->mc_io, 0, mc_dev->mc_handle, &now); err = dprtc_get_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
if (err) { DPRTC_IRQ_INDEX, &mask);
dev_err(dev, "dprtc_get_time err %d\n", err); if (err < 0) {
dev_err(dev, "dprtc_get_irq_mask(): %d\n", err);
return err; return err;
} }
now += delta; if (on)
mask |= bit;
else
mask &= ~bit;
err = dprtc_set_time(mc_dev->mc_io, 0, mc_dev->mc_handle, now); err = dprtc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
if (err) DPRTC_IRQ_INDEX, mask);
dev_err(dev, "dprtc_set_time err %d\n", err); if (err < 0) {
return err; dev_err(dev, "dprtc_set_irq_mask(): %d\n", err);
}
static int ptp_dpaa2_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
struct ptp_dpaa2_priv *ptp_dpaa2 =
container_of(ptp, struct ptp_dpaa2_priv, caps);
struct fsl_mc_device *mc_dev = ptp_dpaa2->ptp_mc_dev;
struct device *dev = &mc_dev->dev;
u64 ns;
u32 remainder;
int err = 0;
err = dprtc_get_time(mc_dev->mc_io, 0, mc_dev->mc_handle, &ns);
if (err) {
dev_err(dev, "dprtc_get_time err %d\n", err);
return err; return err;
} }
ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); return 0;
ts->tv_nsec = remainder;
return err;
}
static int ptp_dpaa2_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts)
{
struct ptp_dpaa2_priv *ptp_dpaa2 =
container_of(ptp, struct ptp_dpaa2_priv, caps);
struct fsl_mc_device *mc_dev = ptp_dpaa2->ptp_mc_dev;
struct device *dev = &mc_dev->dev;
u64 ns;
int err = 0;
ns = ts->tv_sec * 1000000000ULL;
ns += ts->tv_nsec;
err = dprtc_set_time(mc_dev->mc_io, 0, mc_dev->mc_handle, ns);
if (err)
dev_err(dev, "dprtc_set_time err %d\n", err);
return err;
} }
static const struct ptp_clock_info ptp_dpaa2_caps = { static const struct ptp_clock_info dpaa2_ptp_caps = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "DPAA2 PTP Clock", .name = "DPAA2 PTP Clock",
.max_adj = 512000, .max_adj = 512000,
...@@ -121,21 +65,58 @@ static const struct ptp_clock_info ptp_dpaa2_caps = { ...@@ -121,21 +65,58 @@ static const struct ptp_clock_info ptp_dpaa2_caps = {
.n_per_out = 3, .n_per_out = 3,
.n_pins = 0, .n_pins = 0,
.pps = 1, .pps = 1,
.adjfreq = ptp_dpaa2_adjfreq, .adjfine = ptp_qoriq_adjfine,
.adjtime = ptp_dpaa2_adjtime, .adjtime = ptp_qoriq_adjtime,
.gettime64 = ptp_dpaa2_gettime, .gettime64 = ptp_qoriq_gettime,
.settime64 = ptp_dpaa2_settime, .settime64 = ptp_qoriq_settime,
.enable = dpaa2_ptp_enable,
}; };
static irqreturn_t dpaa2_ptp_irq_handler_thread(int irq, void *priv)
{
struct ptp_qoriq *ptp_qoriq = priv;
struct ptp_clock_event event;
struct fsl_mc_device *mc_dev;
struct device *dev;
u32 status = 0;
int err;
dev = ptp_qoriq->dev;
mc_dev = to_fsl_mc_device(dev);
err = dprtc_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
DPRTC_IRQ_INDEX, &status);
if (unlikely(err)) {
dev_err(dev, "dprtc_get_irq_status err %d\n", err);
return IRQ_NONE;
}
if (status & DPRTC_EVENT_PPS) {
event.type = PTP_CLOCK_PPS;
ptp_clock_event(ptp_qoriq->clock, &event);
}
err = dprtc_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
DPRTC_IRQ_INDEX, status);
if (unlikely(err)) {
dev_err(dev, "dprtc_clear_irq_status err %d\n", err);
return IRQ_NONE;
}
return IRQ_HANDLED;
}
static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev) static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
{ {
struct device *dev = &mc_dev->dev; struct device *dev = &mc_dev->dev;
struct ptp_dpaa2_priv *ptp_dpaa2; struct fsl_mc_device_irq *irq;
u32 tmr_add = 0; struct ptp_qoriq *ptp_qoriq;
struct device_node *node;
void __iomem *base;
int err; int err;
ptp_dpaa2 = devm_kzalloc(dev, sizeof(*ptp_dpaa2), GFP_KERNEL); ptp_qoriq = devm_kzalloc(dev, sizeof(*ptp_qoriq), GFP_KERNEL);
if (!ptp_dpaa2) if (!ptp_qoriq)
return -ENOMEM; return -ENOMEM;
err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io); err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
...@@ -154,30 +135,60 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev) ...@@ -154,30 +135,60 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
goto err_free_mcp; goto err_free_mcp;
} }
ptp_dpaa2->ptp_mc_dev = mc_dev; ptp_qoriq->dev = dev;
err = dprtc_get_freq_compensation(mc_dev->mc_io, 0, node = of_find_compatible_node(NULL, NULL, "fsl,dpaa2-ptp");
mc_dev->mc_handle, &tmr_add); if (!node) {
if (err) { err = -ENODEV;
dev_err(dev, "dprtc_get_freq_compensation err %d\n", err);
goto err_close; goto err_close;
} }
ptp_dpaa2->freq_comp = tmr_add; dev->of_node = node;
ptp_dpaa2->caps = ptp_dpaa2_caps;
ptp_dpaa2->clock = ptp_clock_register(&ptp_dpaa2->caps, dev); base = of_iomap(node, 0);
if (IS_ERR(ptp_dpaa2->clock)) { if (!base) {
err = PTR_ERR(ptp_dpaa2->clock); err = -ENOMEM;
goto err_close; goto err_close;
} }
dpaa2_phc_index = ptp_clock_index(ptp_dpaa2->clock); err = fsl_mc_allocate_irqs(mc_dev);
if (err) {
dev_err(dev, "MC irqs allocation failed\n");
goto err_unmap;
}
irq = mc_dev->irqs[0];
ptp_qoriq->irq = irq->msi_desc->irq;
dev_set_drvdata(dev, ptp_dpaa2); err = devm_request_threaded_irq(dev, ptp_qoriq->irq, NULL,
dpaa2_ptp_irq_handler_thread,
IRQF_NO_SUSPEND | IRQF_ONESHOT,
dev_name(dev), ptp_qoriq);
if (err < 0) {
dev_err(dev, "devm_request_threaded_irq(): %d\n", err);
goto err_free_mc_irq;
}
err = dprtc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
DPRTC_IRQ_INDEX, 1);
if (err < 0) {
dev_err(dev, "dprtc_set_irq_enable(): %d\n", err);
goto err_free_mc_irq;
}
err = ptp_qoriq_init(ptp_qoriq, base, &dpaa2_ptp_caps);
if (err)
goto err_free_mc_irq;
dpaa2_phc_index = ptp_qoriq->phc_index;
dev_set_drvdata(dev, ptp_qoriq);
return 0; return 0;
err_free_mc_irq:
fsl_mc_free_irqs(mc_dev);
err_unmap:
iounmap(base);
err_close: err_close:
dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
err_free_mcp: err_free_mcp:
...@@ -188,12 +199,15 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev) ...@@ -188,12 +199,15 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev) static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
{ {
struct ptp_dpaa2_priv *ptp_dpaa2;
struct device *dev = &mc_dev->dev; struct device *dev = &mc_dev->dev;
struct ptp_qoriq *ptp_qoriq;
ptp_qoriq = dev_get_drvdata(dev);
ptp_dpaa2 = dev_get_drvdata(dev); dpaa2_phc_index = -1;
ptp_clock_unregister(ptp_dpaa2->clock); ptp_qoriq_free(ptp_qoriq);
fsl_mc_free_irqs(mc_dev);
dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
fsl_mc_portal_free(mc_dev->mc_io); fsl_mc_portal_free(mc_dev->mc_io);
......
...@@ -17,22 +17,54 @@ ...@@ -17,22 +17,54 @@
#define DPRTC_CMDID_CLOSE DPRTC_CMD(0x800) #define DPRTC_CMDID_CLOSE DPRTC_CMD(0x800)
#define DPRTC_CMDID_OPEN DPRTC_CMD(0x810) #define DPRTC_CMDID_OPEN DPRTC_CMD(0x810)
#define DPRTC_CMDID_SET_FREQ_COMPENSATION DPRTC_CMD(0x1d1) #define DPRTC_CMDID_SET_IRQ_ENABLE DPRTC_CMD(0x012)
#define DPRTC_CMDID_GET_FREQ_COMPENSATION DPRTC_CMD(0x1d2) #define DPRTC_CMDID_GET_IRQ_ENABLE DPRTC_CMD(0x013)
#define DPRTC_CMDID_GET_TIME DPRTC_CMD(0x1d3) #define DPRTC_CMDID_SET_IRQ_MASK DPRTC_CMD(0x014)
#define DPRTC_CMDID_SET_TIME DPRTC_CMD(0x1d4) #define DPRTC_CMDID_GET_IRQ_MASK DPRTC_CMD(0x015)
#define DPRTC_CMDID_GET_IRQ_STATUS DPRTC_CMD(0x016)
#define DPRTC_CMDID_CLEAR_IRQ_STATUS DPRTC_CMD(0x017)
#pragma pack(push, 1) #pragma pack(push, 1)
struct dprtc_cmd_open { struct dprtc_cmd_open {
__le32 dprtc_id; __le32 dprtc_id;
}; };
struct dprtc_get_freq_compensation { struct dprtc_cmd_get_irq {
__le32 freq_compensation; __le32 pad;
u8 irq_index;
}; };
struct dprtc_time { struct dprtc_cmd_set_irq_enable {
__le64 time; u8 en;
u8 pad[3];
u8 irq_index;
};
struct dprtc_rsp_get_irq_enable {
u8 en;
};
struct dprtc_cmd_set_irq_mask {
__le32 mask;
u8 irq_index;
};
struct dprtc_rsp_get_irq_mask {
__le32 mask;
};
struct dprtc_cmd_get_irq_status {
__le32 status;
u8 irq_index;
};
struct dprtc_rsp_get_irq_status {
__le32 status;
};
struct dprtc_cmd_clear_irq_status {
__le32 status;
u8 irq_index;
}; };
#pragma pack(pop) #pragma pack(pop)
......
...@@ -74,121 +74,220 @@ int dprtc_close(struct fsl_mc_io *mc_io, ...@@ -74,121 +74,220 @@ int dprtc_close(struct fsl_mc_io *mc_io,
} }
/** /**
* dprtc_set_freq_compensation() - Sets a new frequency compensation value. * dprtc_set_irq_enable() - Set overall interrupt state.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPRTC object
* @irq_index: The interrupt index to configure
* @en: Interrupt state - enable = 1, disable = 0
* *
* @mc_io: Pointer to MC portal's I/O object * Allows GPP software to control when interrupts are generated.
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * Each interrupt can have up to 32 causes. The enable/disable control's the
* @token: Token of DPRTC object * overall interrupt state. if the interrupt is disabled no causes will cause
* @freq_compensation: The new frequency compensation value to set. * an interrupt.
* *
* Return: '0' on Success; Error code otherwise. * Return: '0' on Success; Error code otherwise.
*/ */
int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io, int dprtc_set_irq_enable(struct fsl_mc_io *mc_io,
u32 cmd_flags, u32 cmd_flags,
u16 token, u16 token,
u32 freq_compensation) u8 irq_index,
u8 en)
{ {
struct dprtc_get_freq_compensation *cmd_params; struct dprtc_cmd_set_irq_enable *cmd_params;
struct fsl_mc_command cmd = { 0 }; struct fsl_mc_command cmd = { 0 };
cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_FREQ_COMPENSATION, cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_ENABLE,
cmd_flags, cmd_flags,
token); token);
cmd_params = (struct dprtc_get_freq_compensation *)cmd.params; cmd_params = (struct dprtc_cmd_set_irq_enable *)cmd.params;
cmd_params->freq_compensation = cpu_to_le32(freq_compensation); cmd_params->irq_index = irq_index;
cmd_params->en = en;
return mc_send_command(mc_io, &cmd); return mc_send_command(mc_io, &cmd);
} }
/** /**
* dprtc_get_freq_compensation() - Retrieves the frequency compensation value * dprtc_get_irq_enable() - Get overall interrupt state
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPRTC object
* @irq_index: The interrupt index to configure
* @en: Returned interrupt state - enable = 1, disable = 0
*
* Return: '0' on Success; Error code otherwise.
*/
int dprtc_get_irq_enable(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
u8 irq_index,
u8 *en)
{
struct dprtc_rsp_get_irq_enable *rsp_params;
struct dprtc_cmd_get_irq *cmd_params;
struct fsl_mc_command cmd = { 0 };
int err;
cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_ENABLE,
cmd_flags,
token);
cmd_params = (struct dprtc_cmd_get_irq *)cmd.params;
cmd_params->irq_index = irq_index;
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
rsp_params = (struct dprtc_rsp_get_irq_enable *)cmd.params;
*en = rsp_params->en;
return 0;
}
/**
* dprtc_set_irq_mask() - Set interrupt mask.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPRTC object
* @irq_index: The interrupt index to configure
* @mask: Event mask to trigger interrupt;
* each bit:
* 0 = ignore event
* 1 = consider event for asserting IRQ
*
* Every interrupt can have up to 32 causes and the interrupt model supports
* masking/unmasking each cause independently
*
* Return: '0' on Success; Error code otherwise.
*/
int dprtc_set_irq_mask(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
u8 irq_index,
u32 mask)
{
struct dprtc_cmd_set_irq_mask *cmd_params;
struct fsl_mc_command cmd = { 0 };
cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_MASK,
cmd_flags,
token);
cmd_params = (struct dprtc_cmd_set_irq_mask *)cmd.params;
cmd_params->mask = cpu_to_le32(mask);
cmd_params->irq_index = irq_index;
return mc_send_command(mc_io, &cmd);
}
/**
* dprtc_get_irq_mask() - Get interrupt mask.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPRTC object
* @irq_index: The interrupt index to configure
* @mask: Returned event mask to trigger interrupt
* *
* @mc_io: Pointer to MC portal's I/O object * Every interrupt can have up to 32 causes and the interrupt model supports
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * masking/unmasking each cause independently
* @token: Token of DPRTC object
* @freq_compensation: Frequency compensation value
* *
* Return: '0' on Success; Error code otherwise. * Return: '0' on Success; Error code otherwise.
*/ */
int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io, int dprtc_get_irq_mask(struct fsl_mc_io *mc_io,
u32 cmd_flags, u32 cmd_flags,
u16 token, u16 token,
u32 *freq_compensation) u8 irq_index,
u32 *mask)
{ {
struct dprtc_get_freq_compensation *rsp_params; struct dprtc_rsp_get_irq_mask *rsp_params;
struct dprtc_cmd_get_irq *cmd_params;
struct fsl_mc_command cmd = { 0 }; struct fsl_mc_command cmd = { 0 };
int err; int err;
cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_FREQ_COMPENSATION, cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_MASK,
cmd_flags, cmd_flags,
token); token);
cmd_params = (struct dprtc_cmd_get_irq *)cmd.params;
cmd_params->irq_index = irq_index;
err = mc_send_command(mc_io, &cmd); err = mc_send_command(mc_io, &cmd);
if (err) if (err)
return err; return err;
rsp_params = (struct dprtc_get_freq_compensation *)cmd.params; rsp_params = (struct dprtc_rsp_get_irq_mask *)cmd.params;
*freq_compensation = le32_to_cpu(rsp_params->freq_compensation); *mask = le32_to_cpu(rsp_params->mask);
return 0; return 0;
} }
/** /**
* dprtc_get_time() - Returns the current RTC time. * dprtc_get_irq_status() - Get the current status of any pending interrupts.
* *
* @mc_io: Pointer to MC portal's I/O object * @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPRTC object * @token: Token of DPRTC object
* @time: Current RTC time. * @irq_index: The interrupt index to configure
* @status: Returned interrupts status - one bit per cause:
* 0 = no interrupt pending
* 1 = interrupt pending
* *
* Return: '0' on Success; Error code otherwise. * Return: '0' on Success; Error code otherwise.
*/ */
int dprtc_get_time(struct fsl_mc_io *mc_io, int dprtc_get_irq_status(struct fsl_mc_io *mc_io,
u32 cmd_flags, u32 cmd_flags,
u16 token, u16 token,
uint64_t *time) u8 irq_index,
u32 *status)
{ {
struct dprtc_time *rsp_params; struct dprtc_cmd_get_irq_status *cmd_params;
struct dprtc_rsp_get_irq_status *rsp_params;
struct fsl_mc_command cmd = { 0 }; struct fsl_mc_command cmd = { 0 };
int err; int err;
cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_TIME, cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_STATUS,
cmd_flags, cmd_flags,
token); token);
cmd_params = (struct dprtc_cmd_get_irq_status *)cmd.params;
cmd_params->status = cpu_to_le32(*status);
cmd_params->irq_index = irq_index;
err = mc_send_command(mc_io, &cmd); err = mc_send_command(mc_io, &cmd);
if (err) if (err)
return err; return err;
rsp_params = (struct dprtc_time *)cmd.params; rsp_params = (struct dprtc_rsp_get_irq_status *)cmd.params;
*time = le64_to_cpu(rsp_params->time); *status = le32_to_cpu(rsp_params->status);
return 0; return 0;
} }
/** /**
* dprtc_set_time() - Updates current RTC time. * dprtc_clear_irq_status() - Clear a pending interrupt's status
* *
* @mc_io: Pointer to MC portal's I/O object * @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPRTC object * @token: Token of DPRTC object
* @time: New RTC time. * @irq_index: The interrupt index to configure
* @status: Bits to clear (W1C) - one bit per cause:
* 0 = don't change
* 1 = clear status bit
* *
* Return: '0' on Success; Error code otherwise. * Return: '0' on Success; Error code otherwise.
*/ */
int dprtc_set_time(struct fsl_mc_io *mc_io, int dprtc_clear_irq_status(struct fsl_mc_io *mc_io,
u32 cmd_flags, u32 cmd_flags,
u16 token, u16 token,
uint64_t time) u8 irq_index,
u32 status)
{ {
struct dprtc_time *cmd_params; struct dprtc_cmd_clear_irq_status *cmd_params;
struct fsl_mc_command cmd = { 0 }; struct fsl_mc_command cmd = { 0 };
cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_TIME, cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLEAR_IRQ_STATUS,
cmd_flags, cmd_flags,
token); token);
cmd_params = (struct dprtc_time *)cmd.params; cmd_params = (struct dprtc_cmd_clear_irq_status *)cmd.params;
cmd_params->time = cpu_to_le64(time); cmd_params->irq_index = irq_index;
cmd_params->status = cpu_to_le32(status);
return mc_send_command(mc_io, &cmd); return mc_send_command(mc_io, &cmd);
} }
...@@ -13,6 +13,14 @@ ...@@ -13,6 +13,14 @@
struct fsl_mc_io; struct fsl_mc_io;
/**
* Number of irq's
*/
#define DPRTC_MAX_IRQ_NUM 1
#define DPRTC_IRQ_INDEX 0
#define DPRTC_EVENT_PPS 0x08000000
int dprtc_open(struct fsl_mc_io *mc_io, int dprtc_open(struct fsl_mc_io *mc_io,
u32 cmd_flags, u32 cmd_flags,
int dprtc_id, int dprtc_id,
...@@ -22,24 +30,40 @@ int dprtc_close(struct fsl_mc_io *mc_io, ...@@ -22,24 +30,40 @@ int dprtc_close(struct fsl_mc_io *mc_io,
u32 cmd_flags, u32 cmd_flags,
u16 token); u16 token);
int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io, int dprtc_set_irq_enable(struct fsl_mc_io *mc_io,
u32 cmd_flags, u32 cmd_flags,
u16 token, u16 token,
u32 freq_compensation); u8 irq_index,
u8 en);
int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io,
u32 cmd_flags, int dprtc_get_irq_enable(struct fsl_mc_io *mc_io,
u16 token, u32 cmd_flags,
u32 *freq_compensation); u16 token,
u8 irq_index,
int dprtc_get_time(struct fsl_mc_io *mc_io, u8 *en);
u32 cmd_flags,
u16 token, int dprtc_set_irq_mask(struct fsl_mc_io *mc_io,
uint64_t *time); u32 cmd_flags,
u16 token,
int dprtc_set_time(struct fsl_mc_io *mc_io, u8 irq_index,
u32 cmd_flags, u32 mask);
u16 token,
uint64_t time); int dprtc_get_irq_mask(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
u8 irq_index,
u32 *mask);
int dprtc_get_irq_status(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
u8 irq_index,
u32 *status);
int dprtc_clear_irq_status(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
u8 irq_index,
u32 status);
#endif /* __FSL_DPRTC_H */ #endif /* __FSL_DPRTC_H */
...@@ -44,7 +44,7 @@ config PTP_1588_CLOCK_DTE ...@@ -44,7 +44,7 @@ config PTP_1588_CLOCK_DTE
config PTP_1588_CLOCK_QORIQ config PTP_1588_CLOCK_QORIQ
tristate "Freescale QorIQ 1588 timer as PTP clock" tristate "Freescale QorIQ 1588 timer as PTP clock"
depends on GIANFAR || FSL_DPAA_ETH || FSL_ENETC || FSL_ENETC_VF depends on GIANFAR || FSL_DPAA_ETH || FSL_DPAA2_ETH || FSL_ENETC || FSL_ENETC_VF || COMPILE_TEST
depends on PTP_1588_CLOCK depends on PTP_1588_CLOCK
default y default y
help help
......
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