This patch is to update linux 4.9 patches to LSDK-18.06 release and to adjust config-4.9 accordingly. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>master
parent
ad1dbc0ca3
commit
a83eae385a
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,542 @@ |
||||
From 2887442bd13bc8be687afc7172cb01c2b7f0dd3b Mon Sep 17 00:00:00 2001
|
||||
From: Yangbo Lu <yangbo.lu@nxp.com>
|
||||
Date: Thu, 5 Jul 2018 17:41:14 +0800
|
||||
Subject: [PATCH 31/32] flexcan: support layerscape
|
||||
|
||||
This is an integrated patch for layerscape flexcan support.
|
||||
|
||||
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
|
||||
Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
|
||||
Signed-off-by: Sakar Arora <Sakar.Arora@freescale.com>
|
||||
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
|
||||
---
|
||||
drivers/net/can/flexcan.c | 212 ++++++++++++++++++++++----------------
|
||||
1 file changed, 123 insertions(+), 89 deletions(-)
|
||||
|
||||
--- a/drivers/net/can/flexcan.c
|
||||
+++ b/drivers/net/can/flexcan.c
|
||||
@@ -184,6 +184,7 @@
|
||||
* MX53 FlexCAN2 03.00.00.00 yes no no no
|
||||
* MX6s FlexCAN3 10.00.12.00 yes yes no yes
|
||||
* VF610 FlexCAN3 ? no yes yes yes?
|
||||
+ * LS1021A FlexCAN2 03.00.04.00 no yes no yes
|
||||
*
|
||||
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
|
||||
*/
|
||||
@@ -260,6 +261,10 @@ struct flexcan_priv {
|
||||
struct flexcan_platform_data *pdata;
|
||||
const struct flexcan_devtype_data *devtype_data;
|
||||
struct regulator *reg_xceiver;
|
||||
+
|
||||
+ /* Read and Write APIs */
|
||||
+ u32 (*read)(void __iomem *addr);
|
||||
+ void (*write)(u32 val, void __iomem *addr);
|
||||
};
|
||||
|
||||
static struct flexcan_devtype_data fsl_p1010_devtype_data = {
|
||||
@@ -276,6 +281,10 @@ static struct flexcan_devtype_data fsl_v
|
||||
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR,
|
||||
};
|
||||
|
||||
+static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = {
|
||||
+ .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR,
|
||||
+};
|
||||
+
|
||||
static const struct can_bittiming_const flexcan_bittiming_const = {
|
||||
.name = DRV_NAME,
|
||||
.tseg1_min = 4,
|
||||
@@ -288,32 +297,38 @@ static const struct can_bittiming_const
|
||||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
-/* Abstract off the read/write for arm versus ppc. This
|
||||
- * assumes that PPC uses big-endian registers and everything
|
||||
- * else uses little-endian registers, independent of CPU
|
||||
- * endianness.
|
||||
+/* FlexCAN module is essentially modelled as a little-endian IP in most
|
||||
+ * SoCs, i.e the registers as well as the message buffer areas are
|
||||
+ * implemented in a little-endian fashion.
|
||||
+ *
|
||||
+ * However there are some SoCs (e.g. LS1021A) which implement the FlexCAN
|
||||
+ * module in a big-endian fashion (i.e the registers as well as the
|
||||
+ * message buffer areas are implemented in a big-endian way).
|
||||
+ *
|
||||
+ * In addition, the FlexCAN module can be found on SoCs having ARM or
|
||||
+ * PPC cores. So, we need to abstract off the register read/write
|
||||
+ * functions, ensuring that these cater to all the combinations of module
|
||||
+ * endianness and underlying CPU endianness.
|
||||
*/
|
||||
-#if defined(CONFIG_PPC)
|
||||
-static inline u32 flexcan_read(void __iomem *addr)
|
||||
+static inline u32 flexcan_read_be(void __iomem *addr)
|
||||
{
|
||||
- return in_be32(addr);
|
||||
+ return ioread32be(addr);
|
||||
}
|
||||
|
||||
-static inline void flexcan_write(u32 val, void __iomem *addr)
|
||||
+static inline void flexcan_write_be(u32 val, void __iomem *addr)
|
||||
{
|
||||
- out_be32(addr, val);
|
||||
+ iowrite32be(val, addr);
|
||||
}
|
||||
-#else
|
||||
-static inline u32 flexcan_read(void __iomem *addr)
|
||||
+
|
||||
+static inline u32 flexcan_read_le(void __iomem *addr)
|
||||
{
|
||||
- return readl(addr);
|
||||
+ return ioread32(addr);
|
||||
}
|
||||
|
||||
-static inline void flexcan_write(u32 val, void __iomem *addr)
|
||||
+static inline void flexcan_write_le(u32 val, void __iomem *addr)
|
||||
{
|
||||
- writel(val, addr);
|
||||
+ iowrite32(val, addr);
|
||||
}
|
||||
-#endif
|
||||
|
||||
static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
|
||||
{
|
||||
@@ -344,14 +359,14 @@ static int flexcan_chip_enable(struct fl
|
||||
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
|
||||
u32 reg;
|
||||
|
||||
- reg = flexcan_read(®s->mcr);
|
||||
+ reg = priv->read(®s->mcr);
|
||||
reg &= ~FLEXCAN_MCR_MDIS;
|
||||
- flexcan_write(reg, ®s->mcr);
|
||||
+ priv->write(reg, ®s->mcr);
|
||||
|
||||
- while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
|
||||
+ while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
|
||||
udelay(10);
|
||||
|
||||
- if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)
|
||||
+ if (priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
@@ -363,14 +378,14 @@ static int flexcan_chip_disable(struct f
|
||||
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
|
||||
u32 reg;
|
||||
|
||||
- reg = flexcan_read(®s->mcr);
|
||||
+ reg = priv->read(®s->mcr);
|
||||
reg |= FLEXCAN_MCR_MDIS;
|
||||
- flexcan_write(reg, ®s->mcr);
|
||||
+ priv->write(reg, ®s->mcr);
|
||||
|
||||
- while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
|
||||
+ while (timeout-- && !(priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
|
||||
udelay(10);
|
||||
|
||||
- if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
|
||||
+ if (!(priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
@@ -382,14 +397,14 @@ static int flexcan_chip_freeze(struct fl
|
||||
unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
|
||||
u32 reg;
|
||||
|
||||
- reg = flexcan_read(®s->mcr);
|
||||
+ reg = priv->read(®s->mcr);
|
||||
reg |= FLEXCAN_MCR_HALT;
|
||||
- flexcan_write(reg, ®s->mcr);
|
||||
+ priv->write(reg, ®s->mcr);
|
||||
|
||||
- while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
|
||||
+ while (timeout-- && !(priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
|
||||
udelay(100);
|
||||
|
||||
- if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
|
||||
+ if (!(priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
@@ -401,14 +416,14 @@ static int flexcan_chip_unfreeze(struct
|
||||
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
|
||||
u32 reg;
|
||||
|
||||
- reg = flexcan_read(®s->mcr);
|
||||
+ reg = priv->read(®s->mcr);
|
||||
reg &= ~FLEXCAN_MCR_HALT;
|
||||
- flexcan_write(reg, ®s->mcr);
|
||||
+ priv->write(reg, ®s->mcr);
|
||||
|
||||
- while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
|
||||
+ while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
|
||||
udelay(10);
|
||||
|
||||
- if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)
|
||||
+ if (priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
@@ -419,11 +434,11 @@ static int flexcan_chip_softreset(struct
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
|
||||
|
||||
- flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr);
|
||||
- while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST))
|
||||
+ priv->write(FLEXCAN_MCR_SOFTRST, ®s->mcr);
|
||||
+ while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_SOFTRST))
|
||||
udelay(10);
|
||||
|
||||
- if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)
|
||||
+ if (priv->read(®s->mcr) & FLEXCAN_MCR_SOFTRST)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
@@ -434,7 +449,7 @@ static int __flexcan_get_berr_counter(co
|
||||
{
|
||||
const struct flexcan_priv *priv = netdev_priv(dev);
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
- u32 reg = flexcan_read(®s->ecr);
|
||||
+ u32 reg = priv->read(®s->ecr);
|
||||
|
||||
bec->txerr = (reg >> 0) & 0xff;
|
||||
bec->rxerr = (reg >> 8) & 0xff;
|
||||
@@ -491,24 +506,24 @@ static int flexcan_start_xmit(struct sk_
|
||||
|
||||
if (cf->can_dlc > 0) {
|
||||
data = be32_to_cpup((__be32 *)&cf->data[0]);
|
||||
- flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[0]);
|
||||
+ priv->write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[0]);
|
||||
}
|
||||
if (cf->can_dlc > 4) {
|
||||
data = be32_to_cpup((__be32 *)&cf->data[4]);
|
||||
- flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[1]);
|
||||
+ priv->write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[1]);
|
||||
}
|
||||
|
||||
can_put_echo_skb(skb, dev, 0);
|
||||
|
||||
- flexcan_write(can_id, ®s->mb[FLEXCAN_TX_BUF_ID].can_id);
|
||||
- flexcan_write(ctrl, ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
|
||||
+ priv->write(can_id, ®s->mb[FLEXCAN_TX_BUF_ID].can_id);
|
||||
+ priv->write(ctrl, ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
|
||||
|
||||
/* Errata ERR005829 step8:
|
||||
* Write twice INACTIVE(0x8) code to first MB.
|
||||
*/
|
||||
- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
+ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
|
||||
- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
+ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@@ -632,8 +647,8 @@ static void flexcan_read_fifo(const stru
|
||||
struct flexcan_mb __iomem *mb = ®s->mb[0];
|
||||
u32 reg_ctrl, reg_id;
|
||||
|
||||
- reg_ctrl = flexcan_read(&mb->can_ctrl);
|
||||
- reg_id = flexcan_read(&mb->can_id);
|
||||
+ reg_ctrl = priv->read(&mb->can_ctrl);
|
||||
+ reg_id = priv->read(&mb->can_id);
|
||||
if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
|
||||
cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
|
||||
else
|
||||
@@ -643,12 +658,12 @@ static void flexcan_read_fifo(const stru
|
||||
cf->can_id |= CAN_RTR_FLAG;
|
||||
cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
|
||||
|
||||
- *(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0]));
|
||||
- *(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1]));
|
||||
+ *(__be32 *)(cf->data + 0) = cpu_to_be32(priv->read(&mb->data[0]));
|
||||
+ *(__be32 *)(cf->data + 4) = cpu_to_be32(priv->read(&mb->data[1]));
|
||||
|
||||
/* mark as read */
|
||||
- flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1);
|
||||
- flexcan_read(®s->timer);
|
||||
+ priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1);
|
||||
+ priv->read(®s->timer);
|
||||
}
|
||||
|
||||
static int flexcan_read_frame(struct net_device *dev)
|
||||
@@ -685,17 +700,17 @@ static int flexcan_poll(struct napi_stru
|
||||
/* The error bits are cleared on read,
|
||||
* use saved value from irq handler.
|
||||
*/
|
||||
- reg_esr = flexcan_read(®s->esr) | priv->reg_esr;
|
||||
+ reg_esr = priv->read(®s->esr) | priv->reg_esr;
|
||||
|
||||
/* handle state changes */
|
||||
work_done += flexcan_poll_state(dev, reg_esr);
|
||||
|
||||
/* handle RX-FIFO */
|
||||
- reg_iflag1 = flexcan_read(®s->iflag1);
|
||||
+ reg_iflag1 = priv->read(®s->iflag1);
|
||||
while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
|
||||
work_done < quota) {
|
||||
work_done += flexcan_read_frame(dev);
|
||||
- reg_iflag1 = flexcan_read(®s->iflag1);
|
||||
+ reg_iflag1 = priv->read(®s->iflag1);
|
||||
}
|
||||
|
||||
/* report bus errors */
|
||||
@@ -705,8 +720,8 @@ static int flexcan_poll(struct napi_stru
|
||||
if (work_done < quota) {
|
||||
napi_complete_done(napi, work_done);
|
||||
/* enable IRQs */
|
||||
- flexcan_write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1);
|
||||
- flexcan_write(priv->reg_ctrl_default, ®s->ctrl);
|
||||
+ priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1);
|
||||
+ priv->write(priv->reg_ctrl_default, ®s->ctrl);
|
||||
}
|
||||
|
||||
return work_done;
|
||||
@@ -720,12 +735,12 @@ static irqreturn_t flexcan_irq(int irq,
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
u32 reg_iflag1, reg_esr;
|
||||
|
||||
- reg_iflag1 = flexcan_read(®s->iflag1);
|
||||
- reg_esr = flexcan_read(®s->esr);
|
||||
+ reg_iflag1 = priv->read(®s->iflag1);
|
||||
+ reg_esr = priv->read(®s->esr);
|
||||
|
||||
/* ACK all bus error and state change IRQ sources */
|
||||
if (reg_esr & FLEXCAN_ESR_ALL_INT)
|
||||
- flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr);
|
||||
+ priv->write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr);
|
||||
|
||||
/* schedule NAPI in case of:
|
||||
* - rx IRQ
|
||||
@@ -739,16 +754,16 @@ static irqreturn_t flexcan_irq(int irq,
|
||||
* save them for later use.
|
||||
*/
|
||||
priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
|
||||
- flexcan_write(FLEXCAN_IFLAG_DEFAULT &
|
||||
+ priv->write(FLEXCAN_IFLAG_DEFAULT &
|
||||
~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->imask1);
|
||||
- flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
|
||||
+ priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
|
||||
®s->ctrl);
|
||||
napi_schedule(&priv->napi);
|
||||
}
|
||||
|
||||
/* FIFO overflow */
|
||||
if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
|
||||
- flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1);
|
||||
+ priv->write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1);
|
||||
dev->stats.rx_over_errors++;
|
||||
dev->stats.rx_errors++;
|
||||
}
|
||||
@@ -760,9 +775,9 @@ static irqreturn_t flexcan_irq(int irq,
|
||||
can_led_event(dev, CAN_LED_EVENT_TX);
|
||||
|
||||
/* after sending a RTR frame MB is in RX mode */
|
||||
- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
+ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
|
||||
- flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
|
||||
+ priv->write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
@@ -776,7 +791,7 @@ static void flexcan_set_bittiming(struct
|
||||
struct flexcan_regs __iomem *regs = priv->regs;
|
||||
u32 reg;
|
||||
|
||||
- reg = flexcan_read(®s->ctrl);
|
||||
+ reg = priv->read(®s->ctrl);
|
||||
reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
|
||||
FLEXCAN_CTRL_RJW(0x3) |
|
||||
FLEXCAN_CTRL_PSEG1(0x7) |
|
||||
@@ -800,11 +815,11 @@ static void flexcan_set_bittiming(struct
|
||||
reg |= FLEXCAN_CTRL_SMP;
|
||||
|
||||
netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
|
||||
- flexcan_write(reg, ®s->ctrl);
|
||||
+ priv->write(reg, ®s->ctrl);
|
||||
|
||||
/* print chip status */
|
||||
netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
|
||||
- flexcan_read(®s->mcr), flexcan_read(®s->ctrl));
|
||||
+ priv->read(®s->mcr), priv->read(®s->ctrl));
|
||||
}
|
||||
|
||||
/* flexcan_chip_start
|
||||
@@ -842,13 +857,13 @@ static int flexcan_chip_start(struct net
|
||||
* choose format C
|
||||
* set max mailbox number
|
||||
*/
|
||||
- reg_mcr = flexcan_read(®s->mcr);
|
||||
+ reg_mcr = priv->read(®s->mcr);
|
||||
reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
|
||||
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
|
||||
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS |
|
||||
FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
|
||||
netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
|
||||
- flexcan_write(reg_mcr, ®s->mcr);
|
||||
+ priv->write(reg_mcr, ®s->mcr);
|
||||
|
||||
/* CTRL
|
||||
*
|
||||
@@ -861,7 +876,7 @@ static int flexcan_chip_start(struct net
|
||||
* enable bus off interrupt
|
||||
* (== FLEXCAN_CTRL_ERR_STATE)
|
||||
*/
|
||||
- reg_ctrl = flexcan_read(®s->ctrl);
|
||||
+ reg_ctrl = priv->read(®s->ctrl);
|
||||
reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
|
||||
reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
|
||||
FLEXCAN_CTRL_ERR_STATE;
|
||||
@@ -881,29 +896,29 @@ static int flexcan_chip_start(struct net
|
||||
/* leave interrupts disabled for now */
|
||||
reg_ctrl &= ~FLEXCAN_CTRL_ERR_ALL;
|
||||
netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
|
||||
- flexcan_write(reg_ctrl, ®s->ctrl);
|
||||
+ priv->write(reg_ctrl, ®s->ctrl);
|
||||
|
||||
/* clear and invalidate all mailboxes first */
|
||||
for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) {
|
||||
- flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
|
||||
+ priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
|
||||
®s->mb[i].can_ctrl);
|
||||
}
|
||||
|
||||
/* Errata ERR005829: mark first TX mailbox as INACTIVE */
|
||||
- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
+ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
|
||||
|
||||
/* mark TX mailbox as INACTIVE */
|
||||
- flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
+ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
|
||||
®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
|
||||
|
||||
/* acceptance mask/acceptance code (accept everything) */
|
||||
- flexcan_write(0x0, ®s->rxgmask);
|
||||
- flexcan_write(0x0, ®s->rx14mask);
|
||||
- flexcan_write(0x0, ®s->rx15mask);
|
||||
+ priv->write(0x0, ®s->rxgmask);
|
||||
+ priv->write(0x0, ®s->rx14mask);
|
||||
+ priv->write(0x0, ®s->rx15mask);
|
||||
|
||||
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
|
||||
- flexcan_write(0x0, ®s->rxfgmask);
|
||||
+ priv->write(0x0, ®s->rxfgmask);
|
||||
|
||||
/* On Vybrid, disable memory error detection interrupts
|
||||
* and freeze mode.
|
||||
@@ -916,16 +931,16 @@ static int flexcan_chip_start(struct net
|
||||
* and Correction of Memory Errors" to write to
|
||||
* MECR register
|
||||
*/
|
||||
- reg_ctrl2 = flexcan_read(®s->ctrl2);
|
||||
+ reg_ctrl2 = priv->read(®s->ctrl2);
|
||||
reg_ctrl2 |= FLEXCAN_CTRL2_ECRWRE;
|
||||
- flexcan_write(reg_ctrl2, ®s->ctrl2);
|
||||
+ priv->write(reg_ctrl2, ®s->ctrl2);
|
||||
|
||||
- reg_mecr = flexcan_read(®s->mecr);
|
||||
+ reg_mecr = priv->read(®s->mecr);
|
||||
reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS;
|
||||
- flexcan_write(reg_mecr, ®s->mecr);
|
||||
+ priv->write(reg_mecr, ®s->mecr);
|
||||
reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
|
||||
FLEXCAN_MECR_FANCEI_MSK);
|
||||
- flexcan_write(reg_mecr, ®s->mecr);
|
||||
+ priv->write(reg_mecr, ®s->mecr);
|
||||
}
|
||||
|
||||
err = flexcan_transceiver_enable(priv);
|
||||
@@ -941,13 +956,13 @@ static int flexcan_chip_start(struct net
|
||||
|
||||
/* enable interrupts atomically */
|
||||
disable_irq(dev->irq);
|
||||
- flexcan_write(priv->reg_ctrl_default, ®s->ctrl);
|
||||
- flexcan_write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1);
|
||||
+ priv->write(priv->reg_ctrl_default, ®s->ctrl);
|
||||
+ priv->write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1);
|
||||
enable_irq(dev->irq);
|
||||
|
||||
/* print chip status */
|
||||
netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__,
|
||||
- flexcan_read(®s->mcr), flexcan_read(®s->ctrl));
|
||||
+ priv->read(®s->mcr), priv->read(®s->ctrl));
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -972,8 +987,8 @@ static void flexcan_chip_stop(struct net
|
||||
flexcan_chip_disable(priv);
|
||||
|
||||
/* Disable all interrupts */
|
||||
- flexcan_write(0, ®s->imask1);
|
||||
- flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
|
||||
+ priv->write(0, ®s->imask1);
|
||||
+ priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
|
||||
®s->ctrl);
|
||||
|
||||
flexcan_transceiver_disable(priv);
|
||||
@@ -1089,25 +1104,25 @@ static int register_flexcandev(struct ne
|
||||
err = flexcan_chip_disable(priv);
|
||||
if (err)
|
||||
goto out_disable_per;
|
||||
- reg = flexcan_read(®s->ctrl);
|
||||
+ reg = priv->read(®s->ctrl);
|
||||
reg |= FLEXCAN_CTRL_CLK_SRC;
|
||||
- flexcan_write(reg, ®s->ctrl);
|
||||
+ priv->write(reg, ®s->ctrl);
|
||||
|
||||
err = flexcan_chip_enable(priv);
|
||||
if (err)
|
||||
goto out_chip_disable;
|
||||
|
||||
/* set freeze, halt and activate FIFO, restrict register access */
|
||||
- reg = flexcan_read(®s->mcr);
|
||||
+ reg = priv->read(®s->mcr);
|
||||
reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
|
||||
FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
|
||||
- flexcan_write(reg, ®s->mcr);
|
||||
+ priv->write(reg, ®s->mcr);
|
||||
|
||||
/* Currently we only support newer versions of this core
|
||||
* featuring a RX FIFO. Older cores found on some Coldfire
|
||||
* derivates are not yet supported.
|
||||
*/
|
||||
- reg = flexcan_read(®s->mcr);
|
||||
+ reg = priv->read(®s->mcr);
|
||||
if (!(reg & FLEXCAN_MCR_FEN)) {
|
||||
netdev_err(dev, "Could not enable RX FIFO, unsupported core\n");
|
||||
err = -ENODEV;
|
||||
@@ -1135,8 +1150,12 @@ static void unregister_flexcandev(struct
|
||||
static const struct of_device_id flexcan_of_match[] = {
|
||||
{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
|
||||
{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
|
||||
+ { .compatible = "fsl,imx53-flexcan", .data = &fsl_p1010_devtype_data, },
|
||||
+ { .compatible = "fsl,imx35-flexcan", .data = &fsl_p1010_devtype_data, },
|
||||
+ { .compatible = "fsl,imx25-flexcan", .data = &fsl_p1010_devtype_data, },
|
||||
{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
|
||||
{ .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
|
||||
+ { .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, flexcan_of_match);
|
||||
@@ -1213,6 +1232,21 @@ static int flexcan_probe(struct platform
|
||||
dev->flags |= IFF_ECHO;
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
+
|
||||
+ if (of_property_read_bool(pdev->dev.of_node, "big-endian")) {
|
||||
+ priv->read = flexcan_read_be;
|
||||
+ priv->write = flexcan_write_be;
|
||||
+ } else {
|
||||
+ if (of_device_is_compatible(pdev->dev.of_node,
|
||||
+ "fsl,p1010-flexcan")) {
|
||||
+ priv->read = flexcan_read_be;
|
||||
+ priv->write = flexcan_write_be;
|
||||
+ } else {
|
||||
+ priv->read = flexcan_read_le;
|
||||
+ priv->write = flexcan_write_le;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
priv->can.clock.freq = clock_freq;
|
||||
priv->can.bittiming_const = &flexcan_bittiming_const;
|
||||
priv->can.do_set_mode = flexcan_set_mode;
|
@ -0,0 +1,239 @@ |
||||
From fe22151c95c02c6bb145ea6c3685941e8fb09d60 Mon Sep 17 00:00:00 2001
|
||||
From: Yangbo Lu <yangbo.lu@nxp.com>
|
||||
Date: Thu, 5 Jul 2018 17:43:16 +0800
|
||||
Subject: [PATCH 32/32] kvm: support layerscape
|
||||
|
||||
This is an integrated patch for layerscape kvm support.
|
||||
|
||||
Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
|
||||
Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
|
||||
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
|
||||
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
|
||||
---
|
||||
arch/arm/include/asm/kvm_mmu.h | 3 +-
|
||||
arch/arm/kvm/mmu.c | 56 ++++++++++++++++++++++++++++++--
|
||||
arch/arm64/include/asm/kvm_mmu.h | 14 ++++++--
|
||||
virt/kvm/arm/vgic/vgic-its.c | 24 +++++++++++---
|
||||
virt/kvm/arm/vgic/vgic-v2.c | 3 +-
|
||||
5 files changed, 88 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/arch/arm/include/asm/kvm_mmu.h
|
||||
+++ b/arch/arm/include/asm/kvm_mmu.h
|
||||
@@ -55,7 +55,8 @@ void stage2_unmap_vm(struct kvm *kvm);
|
||||
int kvm_alloc_stage2_pgd(struct kvm *kvm);
|
||||
void kvm_free_stage2_pgd(struct kvm *kvm);
|
||||
int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
|
||||
- phys_addr_t pa, unsigned long size, bool writable);
|
||||
+ phys_addr_t pa, unsigned long size, bool writable,
|
||||
+ pgprot_t prot);
|
||||
|
||||
int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run);
|
||||
|
||||
--- a/arch/arm/kvm/mmu.c
|
||||
+++ b/arch/arm/kvm/mmu.c
|
||||
@@ -1020,9 +1020,11 @@ static int stage2_pmdp_test_and_clear_yo
|
||||
* @guest_ipa: The IPA at which to insert the mapping
|
||||
* @pa: The physical address of the device
|
||||
* @size: The size of the mapping
|
||||
+ * @prot: S2 page translation bits
|
||||
*/
|
||||
int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
|
||||
- phys_addr_t pa, unsigned long size, bool writable)
|
||||
+ phys_addr_t pa, unsigned long size, bool writable,
|
||||
+ pgprot_t prot)
|
||||
{
|
||||
phys_addr_t addr, end;
|
||||
int ret = 0;
|
||||
@@ -1033,7 +1035,7 @@ int kvm_phys_addr_ioremap(struct kvm *kv
|
||||
pfn = __phys_to_pfn(pa);
|
||||
|
||||
for (addr = guest_ipa; addr < end; addr += PAGE_SIZE) {
|
||||
- pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE);
|
||||
+ pte_t pte = pfn_pte(pfn, prot);
|
||||
|
||||
if (writable)
|
||||
pte = kvm_s2pte_mkwrite(pte);
|
||||
@@ -1057,6 +1059,30 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_ARM64
|
||||
+static pgprot_t stage1_to_stage2_pgprot(pgprot_t prot)
|
||||
+{
|
||||
+ switch (pgprot_val(prot) & PTE_ATTRINDX_MASK) {
|
||||
+ case PTE_ATTRINDX(MT_DEVICE_nGnRE):
|
||||
+ case PTE_ATTRINDX(MT_DEVICE_nGnRnE):
|
||||
+ case PTE_ATTRINDX(MT_DEVICE_GRE):
|
||||
+ return PAGE_S2_DEVICE;
|
||||
+ case PTE_ATTRINDX(MT_NORMAL_NC):
|
||||
+ case PTE_ATTRINDX(MT_NORMAL):
|
||||
+ return (pgprot_val(prot) & PTE_SHARED)
|
||||
+ ? PAGE_S2
|
||||
+ : PAGE_S2_NS;
|
||||
+ }
|
||||
+
|
||||
+ return PAGE_S2_DEVICE;
|
||||
+}
|
||||
+#else
|
||||
+static pgprot_t stage1_to_stage2_pgprot(pgprot_t prot)
|
||||
+{
|
||||
+ return PAGE_S2_DEVICE;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap)
|
||||
{
|
||||
kvm_pfn_t pfn = *pfnp;
|
||||
@@ -1308,6 +1334,19 @@ static int user_mem_abort(struct kvm_vcp
|
||||
hugetlb = true;
|
||||
gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT;
|
||||
} else {
|
||||
+ if (!is_vm_hugetlb_page(vma)) {
|
||||
+ pte_t *pte;
|
||||
+ spinlock_t *ptl;
|
||||
+ pgprot_t prot;
|
||||
+
|
||||
+ pte = get_locked_pte(current->mm, memslot->userspace_addr, &ptl);
|
||||
+ prot = stage1_to_stage2_pgprot(__pgprot(pte_val(*pte)));
|
||||
+ pte_unmap_unlock(pte, ptl);
|
||||
+#ifdef CONFIG_ARM64
|
||||
+ if (pgprot_val(prot) == pgprot_val(PAGE_S2_NS))
|
||||
+ mem_type = PAGE_S2_NS;
|
||||
+#endif
|
||||
+ }
|
||||
/*
|
||||
* Pages belonging to memslots that don't have the same
|
||||
* alignment for userspace and IPA cannot be mapped using
|
||||
@@ -1345,6 +1384,11 @@ static int user_mem_abort(struct kvm_vcp
|
||||
if (is_error_noslot_pfn(pfn))
|
||||
return -EFAULT;
|
||||
|
||||
+#ifdef CONFIG_ARM64
|
||||
+ if (pgprot_val(mem_type) == pgprot_val(PAGE_S2_NS)) {
|
||||
+ flags |= KVM_S2PTE_FLAG_IS_IOMAP;
|
||||
+ } else
|
||||
+#endif
|
||||
if (kvm_is_device_pfn(pfn)) {
|
||||
mem_type = PAGE_S2_DEVICE;
|
||||
flags |= KVM_S2PTE_FLAG_IS_IOMAP;
|
||||
@@ -1882,6 +1926,9 @@ int kvm_arch_prepare_memory_region(struc
|
||||
gpa_t gpa = mem->guest_phys_addr +
|
||||
(vm_start - mem->userspace_addr);
|
||||
phys_addr_t pa;
|
||||
+ pgprot_t prot;
|
||||
+ pte_t *pte;
|
||||
+ spinlock_t *ptl;
|
||||
|
||||
pa = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
|
||||
pa += vm_start - vma->vm_start;
|
||||
@@ -1891,10 +1938,13 @@ int kvm_arch_prepare_memory_region(struc
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
+ pte = get_locked_pte(current->mm, mem->userspace_addr, &ptl);
|
||||
+ prot = stage1_to_stage2_pgprot(__pgprot(pte_val(*pte)));
|
||||
+ pte_unmap_unlock(pte, ptl);
|
||||
|
||||
ret = kvm_phys_addr_ioremap(kvm, gpa, pa,
|
||||
vm_end - vm_start,
|
||||
- writable);
|
||||
+ writable, prot);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
--- a/arch/arm64/include/asm/kvm_mmu.h
|
||||
+++ b/arch/arm64/include/asm/kvm_mmu.h
|
||||
@@ -167,7 +167,8 @@ void stage2_unmap_vm(struct kvm *kvm);
|
||||
int kvm_alloc_stage2_pgd(struct kvm *kvm);
|
||||
void kvm_free_stage2_pgd(struct kvm *kvm);
|
||||
int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
|
||||
- phys_addr_t pa, unsigned long size, bool writable);
|
||||
+ phys_addr_t pa, unsigned long size, bool writable,
|
||||
+ pgprot_t prot);
|
||||
|
||||
int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run);
|
||||
|
||||
@@ -274,8 +275,15 @@ static inline void __coherent_cache_gues
|
||||
|
||||
static inline void __kvm_flush_dcache_pte(pte_t pte)
|
||||
{
|
||||
- struct page *page = pte_page(pte);
|
||||
- kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE);
|
||||
+ if (pfn_valid(pte_pfn(pte))) {
|
||||
+ struct page *page = pte_page(pte);
|
||||
+ kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE);
|
||||
+ } else {
|
||||
+ void __iomem *va = ioremap_cache_ns(pte_pfn(pte) << PAGE_SHIFT, PAGE_SIZE);
|
||||
+
|
||||
+ kvm_flush_dcache_to_poc(va, PAGE_SIZE);
|
||||
+ iounmap(va);
|
||||
+ }
|
||||
}
|
||||
|
||||
static inline void __kvm_flush_dcache_pmd(pmd_t pmd)
|
||||
--- a/virt/kvm/arm/vgic/vgic-its.c
|
||||
+++ b/virt/kvm/arm/vgic/vgic-its.c
|
||||
@@ -176,6 +176,8 @@ static struct its_itte *find_itte(struct
|
||||
|
||||
#define GIC_LPI_OFFSET 8192
|
||||
|
||||
+#define VITS_TYPER_DEVBITS 17
|
||||
+
|
||||
/*
|
||||
* Finds and returns a collection in the ITS collection table.
|
||||
* Must be called with the its_lock mutex held.
|
||||
@@ -375,7 +377,7 @@ static unsigned long vgic_mmio_read_its_
|
||||
* To avoid memory waste in the guest, we keep the number of IDBits and
|
||||
* DevBits low - as least for the time being.
|
||||
*/
|
||||
- reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
|
||||
+ reg |= GIC_ENCODE_SZ(VITS_TYPER_DEVBITS, 5) << GITS_TYPER_DEVBITS_SHIFT;
|
||||
reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
|
||||
|
||||
return extract_bytes(reg, addr & 7, len);
|
||||
@@ -601,16 +603,30 @@ static int vgic_its_cmd_handle_movi(stru
|
||||
* Check whether an ID can be stored into the corresponding guest table.
|
||||
* For a direct table this is pretty easy, but gets a bit nasty for
|
||||
* indirect tables. We check whether the resulting guest physical address
|
||||
- * is actually valid (covered by a memslot and guest accessbible).
|
||||
+ * is actually valid (covered by a memslot and guest accessible).
|
||||
* For this we have to read the respective first level entry.
|
||||
*/
|
||||
-static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
|
||||
+static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
|
||||
{
|
||||
int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
|
||||
+ u64 indirect_ptr, type = GITS_BASER_TYPE(baser);
|
||||
int index;
|
||||
- u64 indirect_ptr;
|
||||
gfn_t gfn;
|
||||
|
||||
+ switch (type) {
|
||||
+ case GITS_BASER_TYPE_DEVICE:
|
||||
+ if (id >= BIT_ULL(VITS_TYPER_DEVBITS))
|
||||
+ return false;
|
||||
+ break;
|
||||
+ case GITS_BASER_TYPE_COLLECTION:
|
||||
+ /* as GITS_TYPER.CIL == 0, ITS supports 16-bit collection ID */
|
||||
+ if (id >= BIT_ULL(16))
|
||||
+ return false;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
if (!(baser & GITS_BASER_INDIRECT)) {
|
||||
phys_addr_t addr;
|
||||
|
||||
--- a/virt/kvm/arm/vgic/vgic-v2.c
|
||||
+++ b/virt/kvm/arm/vgic/vgic-v2.c
|
||||
@@ -290,7 +290,8 @@ int vgic_v2_map_resources(struct kvm *kv
|
||||
if (!static_branch_unlikely(&vgic_v2_cpuif_trap)) {
|
||||
ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
|
||||
kvm_vgic_global_state.vcpu_base,
|
||||
- KVM_VGIC_V2_CPU_SIZE, true);
|
||||
+ KVM_VGIC_V2_CPU_SIZE, true,
|
||||
+ PAGE_S2_DEVICE);
|
||||
if (ret) {
|
||||
kvm_err("Unable to remap VGIC CPU to VCPU\n");
|
||||
goto out;
|
Loading…
Reference in new issue