1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4 */
5
6 /* PPE platform device probe, DTSI parser and PPE clock initializations. */
7
8 #include <linux/clk.h>
9 #include <linux/interconnect.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/platform_device.h>
14 #include <linux/regmap.h>
15 #include <linux/reset.h>
16
17 #include "ppe.h"
18 #include "ppe_config.h"
19 #include "ppe_debugfs.h"
20
21 #define PPE_PORT_MAX 8
22 #define PPE_CLK_RATE 353000000
23
24 /* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0
25 * will be updated by the clock rate of PPE.
26 */
27 static const struct icc_bulk_data ppe_icc_data[] = {
28 {
29 .name = "ppe",
30 .avg_bw = 0,
31 .peak_bw = 0,
32 },
33 {
34 .name = "ppe_cfg",
35 .avg_bw = 0,
36 .peak_bw = 0,
37 },
38 {
39 .name = "qos_gen",
40 .avg_bw = 6000,
41 .peak_bw = 6000,
42 },
43 {
44 .name = "timeout_ref",
45 .avg_bw = 6000,
46 .peak_bw = 6000,
47 },
48 {
49 .name = "nssnoc_memnoc",
50 .avg_bw = 533333,
51 .peak_bw = 533333,
52 },
53 {
54 .name = "memnoc_nssnoc",
55 .avg_bw = 533333,
56 .peak_bw = 533333,
57 },
58 {
59 .name = "memnoc_nssnoc_1",
60 .avg_bw = 533333,
61 .peak_bw = 533333,
62 },
63 };
64
65 static const struct regmap_range ppe_readable_ranges[] = {
66 regmap_reg_range(0x0, 0x1ff), /* Global */
67 regmap_reg_range(0x400, 0x5ff), /* LPI CSR */
68 regmap_reg_range(0x1000, 0x11ff), /* GMAC0 */
69 regmap_reg_range(0x1200, 0x13ff), /* GMAC1 */
70 regmap_reg_range(0x1400, 0x15ff), /* GMAC2 */
71 regmap_reg_range(0x1600, 0x17ff), /* GMAC3 */
72 regmap_reg_range(0x1800, 0x19ff), /* GMAC4 */
73 regmap_reg_range(0x1a00, 0x1bff), /* GMAC5 */
74 regmap_reg_range(0xb000, 0xefff), /* PRX CSR */
75 regmap_reg_range(0xf000, 0x1efff), /* IPE */
76 regmap_reg_range(0x20000, 0x5ffff), /* PTX CSR */
77 regmap_reg_range(0x60000, 0x9ffff), /* IPE L2 CSR */
78 regmap_reg_range(0xb0000, 0xeffff), /* IPO CSR */
79 regmap_reg_range(0x100000, 0x17ffff), /* IPE PC */
80 regmap_reg_range(0x180000, 0x1bffff), /* PRE IPO CSR */
81 regmap_reg_range(0x1d0000, 0x1dffff), /* Tunnel parser */
82 regmap_reg_range(0x1e0000, 0x1effff), /* Ingress parse */
83 regmap_reg_range(0x200000, 0x2fffff), /* IPE L3 */
84 regmap_reg_range(0x300000, 0x3fffff), /* IPE tunnel */
85 regmap_reg_range(0x400000, 0x4fffff), /* Scheduler */
86 regmap_reg_range(0x500000, 0x503fff), /* XGMAC0 */
87 regmap_reg_range(0x504000, 0x507fff), /* XGMAC1 */
88 regmap_reg_range(0x508000, 0x50bfff), /* XGMAC2 */
89 regmap_reg_range(0x50c000, 0x50ffff), /* XGMAC3 */
90 regmap_reg_range(0x510000, 0x513fff), /* XGMAC4 */
91 regmap_reg_range(0x514000, 0x517fff), /* XGMAC5 */
92 regmap_reg_range(0x600000, 0x6fffff), /* BM */
93 regmap_reg_range(0x800000, 0x9fffff), /* QM */
94 regmap_reg_range(0xb00000, 0xbef800), /* EDMA */
95 };
96
97 static const struct regmap_access_table ppe_reg_table = {
98 .yes_ranges = ppe_readable_ranges,
99 .n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
100 };
101
102 static const struct regmap_config regmap_config_ipq9574 = {
103 .reg_bits = 32,
104 .reg_stride = 4,
105 .val_bits = 32,
106 .rd_table = &ppe_reg_table,
107 .wr_table = &ppe_reg_table,
108 .max_register = 0xbef800,
109 };
110
ppe_clock_init_and_reset(struct ppe_device * ppe_dev)111 static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
112 {
113 unsigned long ppe_rate = ppe_dev->clk_rate;
114 struct device *dev = ppe_dev->dev;
115 struct reset_control *rstc;
116 struct clk_bulk_data *clks;
117 struct clk *clk;
118 int ret, i;
119
120 for (i = 0; i < ppe_dev->num_icc_paths; i++) {
121 ppe_dev->icc_paths[i].name = ppe_icc_data[i].name;
122 ppe_dev->icc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? :
123 Bps_to_icc(ppe_rate);
124
125 /* PPE does not have an explicit peak bandwidth requirement,
126 * so set the peak bandwidth to be equal to the average
127 * bandwidth.
128 */
129 ppe_dev->icc_paths[i].peak_bw = ppe_icc_data[i].peak_bw ? :
130 Bps_to_icc(ppe_rate);
131 }
132
133 ret = devm_of_icc_bulk_get(dev, ppe_dev->num_icc_paths,
134 ppe_dev->icc_paths);
135 if (ret)
136 return ret;
137
138 ret = icc_bulk_set_bw(ppe_dev->num_icc_paths, ppe_dev->icc_paths);
139 if (ret)
140 return ret;
141
142 /* The PPE clocks have a common parent clock. Setting the clock
143 * rate of "ppe" ensures the clock rate of all PPE clocks is
144 * configured to the same rate.
145 */
146 clk = devm_clk_get(dev, "ppe");
147 if (IS_ERR(clk))
148 return PTR_ERR(clk);
149
150 ret = clk_set_rate(clk, ppe_rate);
151 if (ret)
152 return ret;
153
154 ret = devm_clk_bulk_get_all_enabled(dev, &clks);
155 if (ret < 0)
156 return ret;
157
158 /* Reset the PPE. */
159 rstc = devm_reset_control_get_exclusive(dev, NULL);
160 if (IS_ERR(rstc))
161 return PTR_ERR(rstc);
162
163 ret = reset_control_assert(rstc);
164 if (ret)
165 return ret;
166
167 /* The delay 10 ms of assert is necessary for resetting PPE. */
168 usleep_range(10000, 11000);
169
170 return reset_control_deassert(rstc);
171 }
172
qcom_ppe_probe(struct platform_device * pdev)173 static int qcom_ppe_probe(struct platform_device *pdev)
174 {
175 struct device *dev = &pdev->dev;
176 struct ppe_device *ppe_dev;
177 void __iomem *base;
178 int ret, num_icc;
179
180 num_icc = ARRAY_SIZE(ppe_icc_data);
181 ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),
182 GFP_KERNEL);
183 if (!ppe_dev)
184 return -ENOMEM;
185
186 base = devm_platform_ioremap_resource(pdev, 0);
187 if (IS_ERR(base))
188 return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n");
189
190 ppe_dev->regmap = devm_regmap_init_mmio(dev, base, ®map_config_ipq9574);
191 if (IS_ERR(ppe_dev->regmap))
192 return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap),
193 "PPE initialize regmap failed\n");
194 ppe_dev->dev = dev;
195 ppe_dev->clk_rate = PPE_CLK_RATE;
196 ppe_dev->num_ports = PPE_PORT_MAX;
197 ppe_dev->num_icc_paths = num_icc;
198
199 ret = ppe_clock_init_and_reset(ppe_dev);
200 if (ret)
201 return dev_err_probe(dev, ret, "PPE clock config failed\n");
202
203 ret = ppe_hw_config(ppe_dev);
204 if (ret)
205 return dev_err_probe(dev, ret, "PPE HW config failed\n");
206
207 ppe_debugfs_setup(ppe_dev);
208 platform_set_drvdata(pdev, ppe_dev);
209
210 return 0;
211 }
212
qcom_ppe_remove(struct platform_device * pdev)213 static void qcom_ppe_remove(struct platform_device *pdev)
214 {
215 struct ppe_device *ppe_dev;
216
217 ppe_dev = platform_get_drvdata(pdev);
218 ppe_debugfs_teardown(ppe_dev);
219 }
220
221 static const struct of_device_id qcom_ppe_of_match[] = {
222 { .compatible = "qcom,ipq9574-ppe" },
223 {}
224 };
225 MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
226
227 static struct platform_driver qcom_ppe_driver = {
228 .driver = {
229 .name = "qcom_ppe",
230 .of_match_table = qcom_ppe_of_match,
231 },
232 .probe = qcom_ppe_probe,
233 .remove = qcom_ppe_remove,
234 };
235 module_platform_driver(qcom_ppe_driver);
236
237 MODULE_LICENSE("GPL");
238 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ PPE driver");
239