xref: /linux/drivers/net/ethernet/qualcomm/ppe/ppe.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1353a0f1dSLuo Jie // SPDX-License-Identifier: GPL-2.0-only
2353a0f1dSLuo Jie /*
3353a0f1dSLuo Jie  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4353a0f1dSLuo Jie  */
5353a0f1dSLuo Jie 
6353a0f1dSLuo Jie /* PPE platform device probe, DTSI parser and PPE clock initializations. */
7353a0f1dSLuo Jie 
8353a0f1dSLuo Jie #include <linux/clk.h>
9353a0f1dSLuo Jie #include <linux/interconnect.h>
10353a0f1dSLuo Jie #include <linux/kernel.h>
11353a0f1dSLuo Jie #include <linux/module.h>
12353a0f1dSLuo Jie #include <linux/of.h>
13353a0f1dSLuo Jie #include <linux/platform_device.h>
14353a0f1dSLuo Jie #include <linux/regmap.h>
15353a0f1dSLuo Jie #include <linux/reset.h>
16353a0f1dSLuo Jie 
17353a0f1dSLuo Jie #include "ppe.h"
188a971df9SLuo Jie #include "ppe_config.h"
19*a2a7221dSLuo Jie #include "ppe_debugfs.h"
20353a0f1dSLuo Jie 
21353a0f1dSLuo Jie #define PPE_PORT_MAX		8
22353a0f1dSLuo Jie #define PPE_CLK_RATE		353000000
23353a0f1dSLuo Jie 
24353a0f1dSLuo Jie /* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0
25353a0f1dSLuo Jie  * will be updated by the clock rate of PPE.
26353a0f1dSLuo Jie  */
27353a0f1dSLuo Jie static const struct icc_bulk_data ppe_icc_data[] = {
28353a0f1dSLuo Jie 	{
29353a0f1dSLuo Jie 		.name = "ppe",
30353a0f1dSLuo Jie 		.avg_bw = 0,
31353a0f1dSLuo Jie 		.peak_bw = 0,
32353a0f1dSLuo Jie 	},
33353a0f1dSLuo Jie 	{
34353a0f1dSLuo Jie 		.name = "ppe_cfg",
35353a0f1dSLuo Jie 		.avg_bw = 0,
36353a0f1dSLuo Jie 		.peak_bw = 0,
37353a0f1dSLuo Jie 	},
38353a0f1dSLuo Jie 	{
39353a0f1dSLuo Jie 		.name = "qos_gen",
40353a0f1dSLuo Jie 		.avg_bw = 6000,
41353a0f1dSLuo Jie 		.peak_bw = 6000,
42353a0f1dSLuo Jie 	},
43353a0f1dSLuo Jie 	{
44353a0f1dSLuo Jie 		.name = "timeout_ref",
45353a0f1dSLuo Jie 		.avg_bw = 6000,
46353a0f1dSLuo Jie 		.peak_bw = 6000,
47353a0f1dSLuo Jie 	},
48353a0f1dSLuo Jie 	{
49353a0f1dSLuo Jie 		.name = "nssnoc_memnoc",
50353a0f1dSLuo Jie 		.avg_bw = 533333,
51353a0f1dSLuo Jie 		.peak_bw = 533333,
52353a0f1dSLuo Jie 	},
53353a0f1dSLuo Jie 	{
54353a0f1dSLuo Jie 		.name = "memnoc_nssnoc",
55353a0f1dSLuo Jie 		.avg_bw = 533333,
56353a0f1dSLuo Jie 		.peak_bw = 533333,
57353a0f1dSLuo Jie 	},
58353a0f1dSLuo Jie 	{
59353a0f1dSLuo Jie 		.name = "memnoc_nssnoc_1",
60353a0f1dSLuo Jie 		.avg_bw = 533333,
61353a0f1dSLuo Jie 		.peak_bw = 533333,
62353a0f1dSLuo Jie 	},
63353a0f1dSLuo Jie };
64353a0f1dSLuo Jie 
65353a0f1dSLuo Jie static const struct regmap_range ppe_readable_ranges[] = {
66353a0f1dSLuo Jie 	regmap_reg_range(0x0, 0x1ff),		/* Global */
67353a0f1dSLuo Jie 	regmap_reg_range(0x400, 0x5ff),		/* LPI CSR */
68353a0f1dSLuo Jie 	regmap_reg_range(0x1000, 0x11ff),	/* GMAC0 */
69353a0f1dSLuo Jie 	regmap_reg_range(0x1200, 0x13ff),	/* GMAC1 */
70353a0f1dSLuo Jie 	regmap_reg_range(0x1400, 0x15ff),	/* GMAC2 */
71353a0f1dSLuo Jie 	regmap_reg_range(0x1600, 0x17ff),	/* GMAC3 */
72353a0f1dSLuo Jie 	regmap_reg_range(0x1800, 0x19ff),	/* GMAC4 */
73353a0f1dSLuo Jie 	regmap_reg_range(0x1a00, 0x1bff),	/* GMAC5 */
74353a0f1dSLuo Jie 	regmap_reg_range(0xb000, 0xefff),	/* PRX CSR */
75353a0f1dSLuo Jie 	regmap_reg_range(0xf000, 0x1efff),	/* IPE */
76353a0f1dSLuo Jie 	regmap_reg_range(0x20000, 0x5ffff),	/* PTX CSR */
77353a0f1dSLuo Jie 	regmap_reg_range(0x60000, 0x9ffff),	/* IPE L2 CSR */
78353a0f1dSLuo Jie 	regmap_reg_range(0xb0000, 0xeffff),	/* IPO CSR */
79353a0f1dSLuo Jie 	regmap_reg_range(0x100000, 0x17ffff),	/* IPE PC */
80353a0f1dSLuo Jie 	regmap_reg_range(0x180000, 0x1bffff),	/* PRE IPO CSR */
81353a0f1dSLuo Jie 	regmap_reg_range(0x1d0000, 0x1dffff),	/* Tunnel parser */
82353a0f1dSLuo Jie 	regmap_reg_range(0x1e0000, 0x1effff),	/* Ingress parse */
83353a0f1dSLuo Jie 	regmap_reg_range(0x200000, 0x2fffff),	/* IPE L3 */
84353a0f1dSLuo Jie 	regmap_reg_range(0x300000, 0x3fffff),	/* IPE tunnel */
85353a0f1dSLuo Jie 	regmap_reg_range(0x400000, 0x4fffff),	/* Scheduler */
86353a0f1dSLuo Jie 	regmap_reg_range(0x500000, 0x503fff),	/* XGMAC0 */
87353a0f1dSLuo Jie 	regmap_reg_range(0x504000, 0x507fff),	/* XGMAC1 */
88353a0f1dSLuo Jie 	regmap_reg_range(0x508000, 0x50bfff),	/* XGMAC2 */
89353a0f1dSLuo Jie 	regmap_reg_range(0x50c000, 0x50ffff),	/* XGMAC3 */
90353a0f1dSLuo Jie 	regmap_reg_range(0x510000, 0x513fff),	/* XGMAC4 */
91353a0f1dSLuo Jie 	regmap_reg_range(0x514000, 0x517fff),	/* XGMAC5 */
92353a0f1dSLuo Jie 	regmap_reg_range(0x600000, 0x6fffff),	/* BM */
93353a0f1dSLuo Jie 	regmap_reg_range(0x800000, 0x9fffff),	/* QM */
94353a0f1dSLuo Jie 	regmap_reg_range(0xb00000, 0xbef800),	/* EDMA */
95353a0f1dSLuo Jie };
96353a0f1dSLuo Jie 
97353a0f1dSLuo Jie static const struct regmap_access_table ppe_reg_table = {
98353a0f1dSLuo Jie 	.yes_ranges = ppe_readable_ranges,
99353a0f1dSLuo Jie 	.n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
100353a0f1dSLuo Jie };
101353a0f1dSLuo Jie 
102353a0f1dSLuo Jie static const struct regmap_config regmap_config_ipq9574 = {
103353a0f1dSLuo Jie 	.reg_bits = 32,
104353a0f1dSLuo Jie 	.reg_stride = 4,
105353a0f1dSLuo Jie 	.val_bits = 32,
106353a0f1dSLuo Jie 	.rd_table = &ppe_reg_table,
107353a0f1dSLuo Jie 	.wr_table = &ppe_reg_table,
108353a0f1dSLuo Jie 	.max_register = 0xbef800,
109353a0f1dSLuo Jie 	.fast_io = true,
110353a0f1dSLuo Jie };
111353a0f1dSLuo Jie 
112353a0f1dSLuo Jie static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
113353a0f1dSLuo Jie {
114353a0f1dSLuo Jie 	unsigned long ppe_rate = ppe_dev->clk_rate;
115353a0f1dSLuo Jie 	struct device *dev = ppe_dev->dev;
116353a0f1dSLuo Jie 	struct reset_control *rstc;
117353a0f1dSLuo Jie 	struct clk_bulk_data *clks;
118353a0f1dSLuo Jie 	struct clk *clk;
119353a0f1dSLuo Jie 	int ret, i;
120353a0f1dSLuo Jie 
121353a0f1dSLuo Jie 	for (i = 0; i < ppe_dev->num_icc_paths; i++) {
122353a0f1dSLuo Jie 		ppe_dev->icc_paths[i].name = ppe_icc_data[i].name;
123353a0f1dSLuo Jie 		ppe_dev->icc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? :
124353a0f1dSLuo Jie 					       Bps_to_icc(ppe_rate);
125353a0f1dSLuo Jie 
126353a0f1dSLuo Jie 		/* PPE does not have an explicit peak bandwidth requirement,
127353a0f1dSLuo Jie 		 * so set the peak bandwidth to be equal to the average
128353a0f1dSLuo Jie 		 * bandwidth.
129353a0f1dSLuo Jie 		 */
130353a0f1dSLuo Jie 		ppe_dev->icc_paths[i].peak_bw = ppe_icc_data[i].peak_bw ? :
131353a0f1dSLuo Jie 						Bps_to_icc(ppe_rate);
132353a0f1dSLuo Jie 	}
133353a0f1dSLuo Jie 
134353a0f1dSLuo Jie 	ret = devm_of_icc_bulk_get(dev, ppe_dev->num_icc_paths,
135353a0f1dSLuo Jie 				   ppe_dev->icc_paths);
136353a0f1dSLuo Jie 	if (ret)
137353a0f1dSLuo Jie 		return ret;
138353a0f1dSLuo Jie 
139353a0f1dSLuo Jie 	ret = icc_bulk_set_bw(ppe_dev->num_icc_paths, ppe_dev->icc_paths);
140353a0f1dSLuo Jie 	if (ret)
141353a0f1dSLuo Jie 		return ret;
142353a0f1dSLuo Jie 
143353a0f1dSLuo Jie 	/* The PPE clocks have a common parent clock. Setting the clock
144353a0f1dSLuo Jie 	 * rate of "ppe" ensures the clock rate of all PPE clocks is
145353a0f1dSLuo Jie 	 * configured to the same rate.
146353a0f1dSLuo Jie 	 */
147353a0f1dSLuo Jie 	clk = devm_clk_get(dev, "ppe");
148353a0f1dSLuo Jie 	if (IS_ERR(clk))
149353a0f1dSLuo Jie 		return PTR_ERR(clk);
150353a0f1dSLuo Jie 
151353a0f1dSLuo Jie 	ret = clk_set_rate(clk, ppe_rate);
152353a0f1dSLuo Jie 	if (ret)
153353a0f1dSLuo Jie 		return ret;
154353a0f1dSLuo Jie 
155353a0f1dSLuo Jie 	ret = devm_clk_bulk_get_all_enabled(dev, &clks);
156353a0f1dSLuo Jie 	if (ret < 0)
157353a0f1dSLuo Jie 		return ret;
158353a0f1dSLuo Jie 
159353a0f1dSLuo Jie 	/* Reset the PPE. */
160353a0f1dSLuo Jie 	rstc = devm_reset_control_get_exclusive(dev, NULL);
161353a0f1dSLuo Jie 	if (IS_ERR(rstc))
162353a0f1dSLuo Jie 		return PTR_ERR(rstc);
163353a0f1dSLuo Jie 
164353a0f1dSLuo Jie 	ret = reset_control_assert(rstc);
165353a0f1dSLuo Jie 	if (ret)
166353a0f1dSLuo Jie 		return ret;
167353a0f1dSLuo Jie 
168353a0f1dSLuo Jie 	/* The delay 10 ms of assert is necessary for resetting PPE. */
169353a0f1dSLuo Jie 	usleep_range(10000, 11000);
170353a0f1dSLuo Jie 
171353a0f1dSLuo Jie 	return reset_control_deassert(rstc);
172353a0f1dSLuo Jie }
173353a0f1dSLuo Jie 
174353a0f1dSLuo Jie static int qcom_ppe_probe(struct platform_device *pdev)
175353a0f1dSLuo Jie {
176353a0f1dSLuo Jie 	struct device *dev = &pdev->dev;
177353a0f1dSLuo Jie 	struct ppe_device *ppe_dev;
178353a0f1dSLuo Jie 	void __iomem *base;
179353a0f1dSLuo Jie 	int ret, num_icc;
180353a0f1dSLuo Jie 
181353a0f1dSLuo Jie 	num_icc = ARRAY_SIZE(ppe_icc_data);
182353a0f1dSLuo Jie 	ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),
183353a0f1dSLuo Jie 			       GFP_KERNEL);
184353a0f1dSLuo Jie 	if (!ppe_dev)
185353a0f1dSLuo Jie 		return -ENOMEM;
186353a0f1dSLuo Jie 
187353a0f1dSLuo Jie 	base = devm_platform_ioremap_resource(pdev, 0);
188353a0f1dSLuo Jie 	if (IS_ERR(base))
189353a0f1dSLuo Jie 		return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n");
190353a0f1dSLuo Jie 
191353a0f1dSLuo Jie 	ppe_dev->regmap = devm_regmap_init_mmio(dev, base, &regmap_config_ipq9574);
192353a0f1dSLuo Jie 	if (IS_ERR(ppe_dev->regmap))
193353a0f1dSLuo Jie 		return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap),
194353a0f1dSLuo Jie 				     "PPE initialize regmap failed\n");
195353a0f1dSLuo Jie 	ppe_dev->dev = dev;
196353a0f1dSLuo Jie 	ppe_dev->clk_rate = PPE_CLK_RATE;
197353a0f1dSLuo Jie 	ppe_dev->num_ports = PPE_PORT_MAX;
198353a0f1dSLuo Jie 	ppe_dev->num_icc_paths = num_icc;
199353a0f1dSLuo Jie 
200353a0f1dSLuo Jie 	ret = ppe_clock_init_and_reset(ppe_dev);
201353a0f1dSLuo Jie 	if (ret)
202353a0f1dSLuo Jie 		return dev_err_probe(dev, ret, "PPE clock config failed\n");
203353a0f1dSLuo Jie 
2048a971df9SLuo Jie 	ret = ppe_hw_config(ppe_dev);
2058a971df9SLuo Jie 	if (ret)
2068a971df9SLuo Jie 		return dev_err_probe(dev, ret, "PPE HW config failed\n");
2078a971df9SLuo Jie 
208*a2a7221dSLuo Jie 	ppe_debugfs_setup(ppe_dev);
209353a0f1dSLuo Jie 	platform_set_drvdata(pdev, ppe_dev);
210353a0f1dSLuo Jie 
211353a0f1dSLuo Jie 	return 0;
212353a0f1dSLuo Jie }
213353a0f1dSLuo Jie 
214*a2a7221dSLuo Jie static void qcom_ppe_remove(struct platform_device *pdev)
215*a2a7221dSLuo Jie {
216*a2a7221dSLuo Jie 	struct ppe_device *ppe_dev;
217*a2a7221dSLuo Jie 
218*a2a7221dSLuo Jie 	ppe_dev = platform_get_drvdata(pdev);
219*a2a7221dSLuo Jie 	ppe_debugfs_teardown(ppe_dev);
220*a2a7221dSLuo Jie }
221*a2a7221dSLuo Jie 
222353a0f1dSLuo Jie static const struct of_device_id qcom_ppe_of_match[] = {
223353a0f1dSLuo Jie 	{ .compatible = "qcom,ipq9574-ppe" },
224353a0f1dSLuo Jie 	{}
225353a0f1dSLuo Jie };
226353a0f1dSLuo Jie MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
227353a0f1dSLuo Jie 
228353a0f1dSLuo Jie static struct platform_driver qcom_ppe_driver = {
229353a0f1dSLuo Jie 	.driver = {
230353a0f1dSLuo Jie 		.name = "qcom_ppe",
231353a0f1dSLuo Jie 		.of_match_table = qcom_ppe_of_match,
232353a0f1dSLuo Jie 	},
233353a0f1dSLuo Jie 	.probe	= qcom_ppe_probe,
234*a2a7221dSLuo Jie 	.remove = qcom_ppe_remove,
235353a0f1dSLuo Jie };
236353a0f1dSLuo Jie module_platform_driver(qcom_ppe_driver);
237353a0f1dSLuo Jie 
238353a0f1dSLuo Jie MODULE_LICENSE("GPL");
239353a0f1dSLuo Jie MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ PPE driver");
240