0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/clk.h>
0023 #include <linux/fpga/fpga-bridge.h>
0024 #include <linux/kernel.h>
0025 #include <linux/mfd/syscon.h>
0026 #include <linux/module.h>
0027 #include <linux/of_platform.h>
0028 #include <linux/regmap.h>
0029 #include <linux/reset.h>
0030 #include <linux/spinlock.h>
0031
0032 #define ALT_L3_REMAP_OFST 0x0
0033 #define ALT_L3_REMAP_MPUZERO_MSK 0x00000001
0034 #define ALT_L3_REMAP_H2F_MSK 0x00000008
0035 #define ALT_L3_REMAP_LWH2F_MSK 0x00000010
0036
0037 #define HPS2FPGA_BRIDGE_NAME "hps2fpga"
0038 #define LWHPS2FPGA_BRIDGE_NAME "lwhps2fpga"
0039 #define FPGA2HPS_BRIDGE_NAME "fpga2hps"
0040
0041 struct altera_hps2fpga_data {
0042 const char *name;
0043 struct reset_control *bridge_reset;
0044 struct regmap *l3reg;
0045 unsigned int remap_mask;
0046 struct clk *clk;
0047 };
0048
0049 static int alt_hps2fpga_enable_show(struct fpga_bridge *bridge)
0050 {
0051 struct altera_hps2fpga_data *priv = bridge->priv;
0052
0053 return reset_control_status(priv->bridge_reset);
0054 }
0055
0056
0057 static unsigned int l3_remap_shadow;
0058 static DEFINE_SPINLOCK(l3_remap_lock);
0059
0060 static int _alt_hps2fpga_enable_set(struct altera_hps2fpga_data *priv,
0061 bool enable)
0062 {
0063 unsigned long flags;
0064 int ret;
0065
0066
0067 if (enable)
0068 ret = reset_control_deassert(priv->bridge_reset);
0069 else
0070 ret = reset_control_assert(priv->bridge_reset);
0071 if (ret)
0072 return ret;
0073
0074
0075 if (priv->remap_mask) {
0076 spin_lock_irqsave(&l3_remap_lock, flags);
0077 l3_remap_shadow |= ALT_L3_REMAP_MPUZERO_MSK;
0078
0079 if (enable)
0080 l3_remap_shadow |= priv->remap_mask;
0081 else
0082 l3_remap_shadow &= ~priv->remap_mask;
0083
0084 ret = regmap_write(priv->l3reg, ALT_L3_REMAP_OFST,
0085 l3_remap_shadow);
0086 spin_unlock_irqrestore(&l3_remap_lock, flags);
0087 }
0088
0089 return ret;
0090 }
0091
0092 static int alt_hps2fpga_enable_set(struct fpga_bridge *bridge, bool enable)
0093 {
0094 return _alt_hps2fpga_enable_set(bridge->priv, enable);
0095 }
0096
0097 static const struct fpga_bridge_ops altera_hps2fpga_br_ops = {
0098 .enable_set = alt_hps2fpga_enable_set,
0099 .enable_show = alt_hps2fpga_enable_show,
0100 };
0101
0102 static struct altera_hps2fpga_data hps2fpga_data = {
0103 .name = HPS2FPGA_BRIDGE_NAME,
0104 .remap_mask = ALT_L3_REMAP_H2F_MSK,
0105 };
0106
0107 static struct altera_hps2fpga_data lwhps2fpga_data = {
0108 .name = LWHPS2FPGA_BRIDGE_NAME,
0109 .remap_mask = ALT_L3_REMAP_LWH2F_MSK,
0110 };
0111
0112 static struct altera_hps2fpga_data fpga2hps_data = {
0113 .name = FPGA2HPS_BRIDGE_NAME,
0114 };
0115
0116 static const struct of_device_id altera_fpga_of_match[] = {
0117 { .compatible = "altr,socfpga-hps2fpga-bridge",
0118 .data = &hps2fpga_data },
0119 { .compatible = "altr,socfpga-lwhps2fpga-bridge",
0120 .data = &lwhps2fpga_data },
0121 { .compatible = "altr,socfpga-fpga2hps-bridge",
0122 .data = &fpga2hps_data },
0123 {},
0124 };
0125
0126 static int alt_fpga_bridge_probe(struct platform_device *pdev)
0127 {
0128 struct device *dev = &pdev->dev;
0129 struct altera_hps2fpga_data *priv;
0130 const struct of_device_id *of_id;
0131 struct fpga_bridge *br;
0132 u32 enable;
0133 int ret;
0134
0135 of_id = of_match_device(altera_fpga_of_match, dev);
0136 if (!of_id) {
0137 dev_err(dev, "failed to match device\n");
0138 return -ENODEV;
0139 }
0140
0141 priv = (struct altera_hps2fpga_data *)of_id->data;
0142
0143 priv->bridge_reset = of_reset_control_get_exclusive_by_index(dev->of_node,
0144 0);
0145 if (IS_ERR(priv->bridge_reset)) {
0146 dev_err(dev, "Could not get %s reset control\n", priv->name);
0147 return PTR_ERR(priv->bridge_reset);
0148 }
0149
0150 if (priv->remap_mask) {
0151 priv->l3reg = syscon_regmap_lookup_by_compatible("altr,l3regs");
0152 if (IS_ERR(priv->l3reg)) {
0153 dev_err(dev, "regmap for altr,l3regs lookup failed\n");
0154 return PTR_ERR(priv->l3reg);
0155 }
0156 }
0157
0158 priv->clk = devm_clk_get(dev, NULL);
0159 if (IS_ERR(priv->clk)) {
0160 dev_err(dev, "no clock specified\n");
0161 return PTR_ERR(priv->clk);
0162 }
0163
0164 ret = clk_prepare_enable(priv->clk);
0165 if (ret) {
0166 dev_err(dev, "could not enable clock\n");
0167 return -EBUSY;
0168 }
0169
0170 if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
0171 if (enable > 1) {
0172 dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
0173 } else {
0174 dev_info(dev, "%s bridge\n",
0175 (enable ? "enabling" : "disabling"));
0176
0177 ret = _alt_hps2fpga_enable_set(priv, enable);
0178 if (ret)
0179 goto err;
0180 }
0181 }
0182
0183 br = fpga_bridge_register(dev, priv->name,
0184 &altera_hps2fpga_br_ops, priv);
0185 if (IS_ERR(br)) {
0186 ret = PTR_ERR(br);
0187 goto err;
0188 }
0189
0190 platform_set_drvdata(pdev, br);
0191
0192 return 0;
0193
0194 err:
0195 clk_disable_unprepare(priv->clk);
0196
0197 return ret;
0198 }
0199
0200 static int alt_fpga_bridge_remove(struct platform_device *pdev)
0201 {
0202 struct fpga_bridge *bridge = platform_get_drvdata(pdev);
0203 struct altera_hps2fpga_data *priv = bridge->priv;
0204
0205 fpga_bridge_unregister(bridge);
0206
0207 clk_disable_unprepare(priv->clk);
0208
0209 return 0;
0210 }
0211
0212 MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
0213
0214 static struct platform_driver alt_fpga_bridge_driver = {
0215 .probe = alt_fpga_bridge_probe,
0216 .remove = alt_fpga_bridge_remove,
0217 .driver = {
0218 .name = "altera_hps2fpga_bridge",
0219 .of_match_table = of_match_ptr(altera_fpga_of_match),
0220 },
0221 };
0222
0223 module_platform_driver(alt_fpga_bridge_driver);
0224
0225 MODULE_DESCRIPTION("Altera SoCFPGA HPS to FPGA Bridge");
0226 MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
0227 MODULE_LICENSE("GPL v2");