0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <linux/fpga/fpga-bridge.h>
0027 #include <linux/kernel.h>
0028 #include <linux/mfd/syscon.h>
0029 #include <linux/module.h>
0030 #include <linux/of_platform.h>
0031 #include <linux/regmap.h>
0032
0033 #define ALT_SDR_CTL_FPGAPORTRST_OFST 0x80
0034 #define ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK 0x00003fff
0035 #define ALT_SDR_CTL_FPGAPORTRST_RD_SHIFT 0
0036 #define ALT_SDR_CTL_FPGAPORTRST_WR_SHIFT 4
0037 #define ALT_SDR_CTL_FPGAPORTRST_CTRL_SHIFT 8
0038
0039
0040
0041
0042
0043
0044
0045
0046 #define SYSMGR_ISWGRP_HANDOFF3 (0x8C)
0047
0048 #define F2S_BRIDGE_NAME "fpga2sdram"
0049
0050 struct alt_fpga2sdram_data {
0051 struct device *dev;
0052 struct regmap *sdrctl;
0053 int mask;
0054 };
0055
0056 static int alt_fpga2sdram_enable_show(struct fpga_bridge *bridge)
0057 {
0058 struct alt_fpga2sdram_data *priv = bridge->priv;
0059 int value;
0060
0061 regmap_read(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST, &value);
0062
0063 return (value & priv->mask) == priv->mask;
0064 }
0065
0066 static inline int _alt_fpga2sdram_enable_set(struct alt_fpga2sdram_data *priv,
0067 bool enable)
0068 {
0069 return regmap_update_bits(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST,
0070 priv->mask, enable ? priv->mask : 0);
0071 }
0072
0073 static int alt_fpga2sdram_enable_set(struct fpga_bridge *bridge, bool enable)
0074 {
0075 return _alt_fpga2sdram_enable_set(bridge->priv, enable);
0076 }
0077
0078 struct prop_map {
0079 char *prop_name;
0080 u32 *prop_value;
0081 u32 prop_max;
0082 };
0083
0084 static const struct fpga_bridge_ops altera_fpga2sdram_br_ops = {
0085 .enable_set = alt_fpga2sdram_enable_set,
0086 .enable_show = alt_fpga2sdram_enable_show,
0087 };
0088
0089 static const struct of_device_id altera_fpga_of_match[] = {
0090 { .compatible = "altr,socfpga-fpga2sdram-bridge" },
0091 {},
0092 };
0093
0094 static int alt_fpga_bridge_probe(struct platform_device *pdev)
0095 {
0096 struct device *dev = &pdev->dev;
0097 struct alt_fpga2sdram_data *priv;
0098 struct fpga_bridge *br;
0099 u32 enable;
0100 struct regmap *sysmgr;
0101 int ret = 0;
0102
0103 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0104 if (!priv)
0105 return -ENOMEM;
0106
0107 priv->dev = dev;
0108
0109 priv->sdrctl = syscon_regmap_lookup_by_compatible("altr,sdr-ctl");
0110 if (IS_ERR(priv->sdrctl)) {
0111 dev_err(dev, "regmap for altr,sdr-ctl lookup failed.\n");
0112 return PTR_ERR(priv->sdrctl);
0113 }
0114
0115 sysmgr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
0116 if (IS_ERR(sysmgr)) {
0117 dev_err(dev, "regmap for altr,sys-mgr lookup failed.\n");
0118 return PTR_ERR(sysmgr);
0119 }
0120
0121
0122 regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
0123
0124 br = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
0125 &altera_fpga2sdram_br_ops, priv);
0126 if (IS_ERR(br))
0127 return PTR_ERR(br);
0128
0129 platform_set_drvdata(pdev, br);
0130
0131 dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
0132
0133 if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
0134 if (enable > 1) {
0135 dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
0136 } else {
0137 dev_info(dev, "%s bridge\n",
0138 (enable ? "enabling" : "disabling"));
0139 ret = _alt_fpga2sdram_enable_set(priv, enable);
0140 if (ret) {
0141 fpga_bridge_unregister(br);
0142 return ret;
0143 }
0144 }
0145 }
0146
0147 return ret;
0148 }
0149
0150 static int alt_fpga_bridge_remove(struct platform_device *pdev)
0151 {
0152 struct fpga_bridge *br = platform_get_drvdata(pdev);
0153
0154 fpga_bridge_unregister(br);
0155
0156 return 0;
0157 }
0158
0159 MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
0160
0161 static struct platform_driver altera_fpga_driver = {
0162 .probe = alt_fpga_bridge_probe,
0163 .remove = alt_fpga_bridge_remove,
0164 .driver = {
0165 .name = "altera_fpga2sdram_bridge",
0166 .of_match_table = of_match_ptr(altera_fpga_of_match),
0167 },
0168 };
0169
0170 module_platform_driver(altera_fpga_driver);
0171
0172 MODULE_DESCRIPTION("Altera SoCFPGA FPGA to SDRAM Bridge");
0173 MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
0174 MODULE_LICENSE("GPL v2");