^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * FPGA Freeze Bridge Controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016 Altera Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/fpga/fpga-bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define FREEZE_CSR_STATUS_OFFSET 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define FREEZE_CSR_CTRL_OFFSET 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define FREEZE_CSR_ILLEGAL_REQ_OFFSET 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define FREEZE_CSR_REG_VERSION 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define FREEZE_CSR_SUPPORTED_VERSION 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define FREEZE_CSR_OFFICIAL_VERSION 0xad000003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define FREEZE_CSR_STATUS_FREEZE_REQ_DONE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define FREEZE_CSR_CTRL_FREEZE_REQ BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define FREEZE_CSR_CTRL_RESET_REQ BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define FREEZE_CSR_CTRL_UNFREEZE_REQ BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define FREEZE_BRIDGE_NAME "freeze"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct altera_freeze_br_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) void __iomem *base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) bool enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * Poll status until status bit is set or we have a timeout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int altera_freeze_br_req_ack(struct altera_freeze_br_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 timeout, u32 req_ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct device *dev = priv->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) void __iomem *csr_illegal_req_addr = priv->base_addr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) FREEZE_CSR_ILLEGAL_REQ_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u32 status, illegal, ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) illegal = readl(csr_illegal_req_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (illegal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) dev_err(dev, "illegal request detected 0x%x", illegal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) writel(1, csr_illegal_req_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) illegal = readl(csr_illegal_req_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (illegal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) dev_err(dev, "illegal request not cleared 0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) illegal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) dev_dbg(dev, "%s %x %x\n", __func__, status, req_ack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) status &= req_ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ctrl = readl(priv->base_addr + FREEZE_CSR_CTRL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dev_dbg(dev, "%s request %x acknowledged %x %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) __func__, req_ack, status, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) } while (timeout--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (ret == -ETIMEDOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dev_err(dev, "%s timeout waiting for 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) __func__, req_ack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int altera_freeze_br_do_freeze(struct altera_freeze_br_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u32 timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct device *dev = priv->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) void __iomem *csr_ctrl_addr = priv->base_addr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) FREEZE_CSR_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) dev_dbg(dev, "%s bridge already disabled %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) } else if (!(status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dev_err(dev, "%s bridge not enabled %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) writel(FREEZE_CSR_CTRL_FREEZE_REQ, csr_ctrl_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = altera_freeze_br_req_ack(priv, timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) FREEZE_CSR_STATUS_FREEZE_REQ_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) writel(0, csr_ctrl_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) writel(FREEZE_CSR_CTRL_RESET_REQ, csr_ctrl_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int altera_freeze_br_do_unfreeze(struct altera_freeze_br_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u32 timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct device *dev = priv->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) void __iomem *csr_ctrl_addr = priv->base_addr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) FREEZE_CSR_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) writel(0, csr_ctrl_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dev_dbg(dev, "%s bridge already enabled %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) } else if (!(status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_err(dev, "%s bridge not frozen %d\n", __func__, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) writel(FREEZE_CSR_CTRL_UNFREEZE_REQ, csr_ctrl_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ret = altera_freeze_br_req_ack(priv, timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) writel(0, csr_ctrl_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * enable = 1 : allow traffic through the bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * enable = 0 : disable traffic through the bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int altera_freeze_br_enable_set(struct fpga_bridge *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct altera_freeze_br_data *priv = bridge->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct fpga_image_info *info = bridge->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) u32 timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) timeout = info->enable_timeout_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = altera_freeze_br_do_unfreeze(bridge->priv, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) timeout = info->disable_timeout_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret = altera_freeze_br_do_freeze(bridge->priv, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) priv->enable = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int altera_freeze_br_enable_show(struct fpga_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct altera_freeze_br_data *priv = bridge->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return priv->enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static const struct fpga_bridge_ops altera_freeze_br_br_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .enable_set = altera_freeze_br_enable_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .enable_show = altera_freeze_br_enable_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static const struct of_device_id altera_freeze_br_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { .compatible = "altr,freeze-bridge-controller", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) MODULE_DEVICE_TABLE(of, altera_freeze_br_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int altera_freeze_br_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) void __iomem *base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct altera_freeze_br_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct fpga_bridge *br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) u32 status, revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) base_addr = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (IS_ERR(base_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return PTR_ERR(base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) revision = readl(base_addr + FREEZE_CSR_REG_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if ((revision != FREEZE_CSR_SUPPORTED_VERSION) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) (revision != FREEZE_CSR_OFFICIAL_VERSION)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "%s unexpected revision 0x%x != 0x%x != 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) __func__, revision, FREEZE_CSR_SUPPORTED_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) FREEZE_CSR_OFFICIAL_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) priv->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) status = readl(base_addr + FREEZE_CSR_STATUS_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) priv->enable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) priv->base_addr = base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) &altera_freeze_br_br_ops, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!br)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) platform_set_drvdata(pdev, br);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return fpga_bridge_register(br);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int altera_freeze_br_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct fpga_bridge *br = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) fpga_bridge_unregister(br);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static struct platform_driver altera_freeze_br_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .probe = altera_freeze_br_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .remove = altera_freeze_br_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .name = "altera_freeze_br",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .of_match_table = of_match_ptr(altera_freeze_br_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) module_platform_driver(altera_freeze_br_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) MODULE_DESCRIPTION("Altera Freeze Bridge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) MODULE_LICENSE("GPL v2");