Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");