0001
0002
0003
0004
0005
0006 #include <linux/bitfield.h>
0007 #include <linux/clk.h>
0008 #include <linux/interconnect-provider.h>
0009 #include <linux/io.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/of_device.h>
0013 #include <linux/platform_device.h>
0014
0015 #include <dt-bindings/interconnect/qcom,osm-l3.h>
0016
0017 #include "sc7180.h"
0018 #include "sc7280.h"
0019 #include "sc8180x.h"
0020 #include "sdm845.h"
0021 #include "sm8150.h"
0022 #include "sm8250.h"
0023
0024 #define LUT_MAX_ENTRIES 40U
0025 #define LUT_SRC GENMASK(31, 30)
0026 #define LUT_L_VAL GENMASK(7, 0)
0027 #define CLK_HW_DIV 2
0028
0029
0030 #define REG_ENABLE 0x0
0031 #define OSM_LUT_ROW_SIZE 32
0032 #define OSM_REG_FREQ_LUT 0x110
0033 #define OSM_REG_PERF_STATE 0x920
0034
0035
0036 #define EPSS_LUT_ROW_SIZE 4
0037 #define EPSS_REG_FREQ_LUT 0x100
0038 #define EPSS_REG_PERF_STATE 0x320
0039
0040 #define OSM_L3_MAX_LINKS 1
0041
0042 #define to_osm_l3_provider(_provider) \
0043 container_of(_provider, struct qcom_osm_l3_icc_provider, provider)
0044
0045 struct qcom_osm_l3_icc_provider {
0046 void __iomem *base;
0047 unsigned int max_state;
0048 unsigned int reg_perf_state;
0049 unsigned long lut_tables[LUT_MAX_ENTRIES];
0050 struct icc_provider provider;
0051 };
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 struct qcom_osm_l3_node {
0062 const char *name;
0063 u16 links[OSM_L3_MAX_LINKS];
0064 u16 id;
0065 u16 num_links;
0066 u16 buswidth;
0067 };
0068
0069 struct qcom_osm_l3_desc {
0070 const struct qcom_osm_l3_node * const *nodes;
0071 size_t num_nodes;
0072 unsigned int lut_row_size;
0073 unsigned int reg_freq_lut;
0074 unsigned int reg_perf_state;
0075 };
0076
0077 #define DEFINE_QNODE(_name, _id, _buswidth, ...) \
0078 static const struct qcom_osm_l3_node _name = { \
0079 .name = #_name, \
0080 .id = _id, \
0081 .buswidth = _buswidth, \
0082 .num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \
0083 .links = { __VA_ARGS__ }, \
0084 }
0085
0086 DEFINE_QNODE(sdm845_osm_apps_l3, SDM845_MASTER_OSM_L3_APPS, 16, SDM845_SLAVE_OSM_L3);
0087 DEFINE_QNODE(sdm845_osm_l3, SDM845_SLAVE_OSM_L3, 16);
0088
0089 static const struct qcom_osm_l3_node * const sdm845_osm_l3_nodes[] = {
0090 [MASTER_OSM_L3_APPS] = &sdm845_osm_apps_l3,
0091 [SLAVE_OSM_L3] = &sdm845_osm_l3,
0092 };
0093
0094 static const struct qcom_osm_l3_desc sdm845_icc_osm_l3 = {
0095 .nodes = sdm845_osm_l3_nodes,
0096 .num_nodes = ARRAY_SIZE(sdm845_osm_l3_nodes),
0097 .lut_row_size = OSM_LUT_ROW_SIZE,
0098 .reg_freq_lut = OSM_REG_FREQ_LUT,
0099 .reg_perf_state = OSM_REG_PERF_STATE,
0100 };
0101
0102 DEFINE_QNODE(sc7180_osm_apps_l3, SC7180_MASTER_OSM_L3_APPS, 16, SC7180_SLAVE_OSM_L3);
0103 DEFINE_QNODE(sc7180_osm_l3, SC7180_SLAVE_OSM_L3, 16);
0104
0105 static const struct qcom_osm_l3_node * const sc7180_osm_l3_nodes[] = {
0106 [MASTER_OSM_L3_APPS] = &sc7180_osm_apps_l3,
0107 [SLAVE_OSM_L3] = &sc7180_osm_l3,
0108 };
0109
0110 static const struct qcom_osm_l3_desc sc7180_icc_osm_l3 = {
0111 .nodes = sc7180_osm_l3_nodes,
0112 .num_nodes = ARRAY_SIZE(sc7180_osm_l3_nodes),
0113 .lut_row_size = OSM_LUT_ROW_SIZE,
0114 .reg_freq_lut = OSM_REG_FREQ_LUT,
0115 .reg_perf_state = OSM_REG_PERF_STATE,
0116 };
0117
0118 DEFINE_QNODE(sc7280_epss_apps_l3, SC7280_MASTER_EPSS_L3_APPS, 32, SC7280_SLAVE_EPSS_L3);
0119 DEFINE_QNODE(sc7280_epss_l3, SC7280_SLAVE_EPSS_L3, 32);
0120
0121 static const struct qcom_osm_l3_node * const sc7280_epss_l3_nodes[] = {
0122 [MASTER_EPSS_L3_APPS] = &sc7280_epss_apps_l3,
0123 [SLAVE_EPSS_L3_SHARED] = &sc7280_epss_l3,
0124 };
0125
0126 static const struct qcom_osm_l3_desc sc7280_icc_epss_l3 = {
0127 .nodes = sc7280_epss_l3_nodes,
0128 .num_nodes = ARRAY_SIZE(sc7280_epss_l3_nodes),
0129 .lut_row_size = EPSS_LUT_ROW_SIZE,
0130 .reg_freq_lut = EPSS_REG_FREQ_LUT,
0131 .reg_perf_state = EPSS_REG_PERF_STATE,
0132 };
0133
0134 DEFINE_QNODE(sc8180x_osm_apps_l3, SC8180X_MASTER_OSM_L3_APPS, 32, SC8180X_SLAVE_OSM_L3);
0135 DEFINE_QNODE(sc8180x_osm_l3, SC8180X_SLAVE_OSM_L3, 32);
0136
0137 static const struct qcom_osm_l3_node * const sc8180x_osm_l3_nodes[] = {
0138 [MASTER_OSM_L3_APPS] = &sc8180x_osm_apps_l3,
0139 [SLAVE_OSM_L3] = &sc8180x_osm_l3,
0140 };
0141
0142 static const struct qcom_osm_l3_desc sc8180x_icc_osm_l3 = {
0143 .nodes = sc8180x_osm_l3_nodes,
0144 .num_nodes = ARRAY_SIZE(sc8180x_osm_l3_nodes),
0145 .lut_row_size = OSM_LUT_ROW_SIZE,
0146 .reg_freq_lut = OSM_REG_FREQ_LUT,
0147 .reg_perf_state = OSM_REG_PERF_STATE,
0148 };
0149
0150 DEFINE_QNODE(sm8150_osm_apps_l3, SM8150_MASTER_OSM_L3_APPS, 32, SM8150_SLAVE_OSM_L3);
0151 DEFINE_QNODE(sm8150_osm_l3, SM8150_SLAVE_OSM_L3, 32);
0152
0153 static const struct qcom_osm_l3_node * const sm8150_osm_l3_nodes[] = {
0154 [MASTER_OSM_L3_APPS] = &sm8150_osm_apps_l3,
0155 [SLAVE_OSM_L3] = &sm8150_osm_l3,
0156 };
0157
0158 static const struct qcom_osm_l3_desc sm8150_icc_osm_l3 = {
0159 .nodes = sm8150_osm_l3_nodes,
0160 .num_nodes = ARRAY_SIZE(sm8150_osm_l3_nodes),
0161 .lut_row_size = OSM_LUT_ROW_SIZE,
0162 .reg_freq_lut = OSM_REG_FREQ_LUT,
0163 .reg_perf_state = OSM_REG_PERF_STATE,
0164 };
0165
0166 DEFINE_QNODE(sm8250_epss_apps_l3, SM8250_MASTER_EPSS_L3_APPS, 32, SM8250_SLAVE_EPSS_L3);
0167 DEFINE_QNODE(sm8250_epss_l3, SM8250_SLAVE_EPSS_L3, 32);
0168
0169 static const struct qcom_osm_l3_node * const sm8250_epss_l3_nodes[] = {
0170 [MASTER_EPSS_L3_APPS] = &sm8250_epss_apps_l3,
0171 [SLAVE_EPSS_L3_SHARED] = &sm8250_epss_l3,
0172 };
0173
0174 static const struct qcom_osm_l3_desc sm8250_icc_epss_l3 = {
0175 .nodes = sm8250_epss_l3_nodes,
0176 .num_nodes = ARRAY_SIZE(sm8250_epss_l3_nodes),
0177 .lut_row_size = EPSS_LUT_ROW_SIZE,
0178 .reg_freq_lut = EPSS_REG_FREQ_LUT,
0179 .reg_perf_state = EPSS_REG_PERF_STATE,
0180 };
0181
0182 static int qcom_osm_l3_set(struct icc_node *src, struct icc_node *dst)
0183 {
0184 struct qcom_osm_l3_icc_provider *qp;
0185 struct icc_provider *provider;
0186 const struct qcom_osm_l3_node *qn;
0187 struct icc_node *n;
0188 unsigned int index;
0189 u32 agg_peak = 0;
0190 u32 agg_avg = 0;
0191 u64 rate;
0192
0193 qn = src->data;
0194 provider = src->provider;
0195 qp = to_osm_l3_provider(provider);
0196
0197 list_for_each_entry(n, &provider->nodes, node_list)
0198 provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
0199 &agg_avg, &agg_peak);
0200
0201 rate = max(agg_avg, agg_peak);
0202 rate = icc_units_to_bps(rate);
0203 do_div(rate, qn->buswidth);
0204
0205 for (index = 0; index < qp->max_state - 1; index++) {
0206 if (qp->lut_tables[index] >= rate)
0207 break;
0208 }
0209
0210 writel_relaxed(index, qp->base + qp->reg_perf_state);
0211
0212 return 0;
0213 }
0214
0215 static int qcom_osm_l3_remove(struct platform_device *pdev)
0216 {
0217 struct qcom_osm_l3_icc_provider *qp = platform_get_drvdata(pdev);
0218
0219 icc_nodes_remove(&qp->provider);
0220 return icc_provider_del(&qp->provider);
0221 }
0222
0223 static int qcom_osm_l3_probe(struct platform_device *pdev)
0224 {
0225 u32 info, src, lval, i, prev_freq = 0, freq;
0226 static unsigned long hw_rate, xo_rate;
0227 struct qcom_osm_l3_icc_provider *qp;
0228 const struct qcom_osm_l3_desc *desc;
0229 struct icc_onecell_data *data;
0230 struct icc_provider *provider;
0231 const struct qcom_osm_l3_node * const *qnodes;
0232 struct icc_node *node;
0233 size_t num_nodes;
0234 struct clk *clk;
0235 int ret;
0236
0237 clk = clk_get(&pdev->dev, "xo");
0238 if (IS_ERR(clk))
0239 return PTR_ERR(clk);
0240
0241 xo_rate = clk_get_rate(clk);
0242 clk_put(clk);
0243
0244 clk = clk_get(&pdev->dev, "alternate");
0245 if (IS_ERR(clk))
0246 return PTR_ERR(clk);
0247
0248 hw_rate = clk_get_rate(clk) / CLK_HW_DIV;
0249 clk_put(clk);
0250
0251 qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
0252 if (!qp)
0253 return -ENOMEM;
0254
0255 qp->base = devm_platform_ioremap_resource(pdev, 0);
0256 if (IS_ERR(qp->base))
0257 return PTR_ERR(qp->base);
0258
0259
0260 if (!(readl_relaxed(qp->base + REG_ENABLE) & 0x1)) {
0261 dev_err(&pdev->dev, "error hardware not enabled\n");
0262 return -ENODEV;
0263 }
0264
0265 desc = device_get_match_data(&pdev->dev);
0266 if (!desc)
0267 return -EINVAL;
0268
0269 qp->reg_perf_state = desc->reg_perf_state;
0270
0271 for (i = 0; i < LUT_MAX_ENTRIES; i++) {
0272 info = readl_relaxed(qp->base + desc->reg_freq_lut +
0273 i * desc->lut_row_size);
0274 src = FIELD_GET(LUT_SRC, info);
0275 lval = FIELD_GET(LUT_L_VAL, info);
0276 if (src)
0277 freq = xo_rate * lval;
0278 else
0279 freq = hw_rate;
0280
0281
0282 if (i > 0 && prev_freq == freq)
0283 break;
0284
0285 dev_dbg(&pdev->dev, "index=%d freq=%d\n", i, freq);
0286
0287 qp->lut_tables[i] = freq;
0288 prev_freq = freq;
0289 }
0290 qp->max_state = i;
0291
0292 qnodes = desc->nodes;
0293 num_nodes = desc->num_nodes;
0294
0295 data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
0296 if (!data)
0297 return -ENOMEM;
0298
0299 provider = &qp->provider;
0300 provider->dev = &pdev->dev;
0301 provider->set = qcom_osm_l3_set;
0302 provider->aggregate = icc_std_aggregate;
0303 provider->xlate = of_icc_xlate_onecell;
0304 INIT_LIST_HEAD(&provider->nodes);
0305 provider->data = data;
0306
0307 ret = icc_provider_add(provider);
0308 if (ret) {
0309 dev_err(&pdev->dev, "error adding interconnect provider\n");
0310 return ret;
0311 }
0312
0313 for (i = 0; i < num_nodes; i++) {
0314 size_t j;
0315
0316 node = icc_node_create(qnodes[i]->id);
0317 if (IS_ERR(node)) {
0318 ret = PTR_ERR(node);
0319 goto err;
0320 }
0321
0322 node->name = qnodes[i]->name;
0323
0324 node->data = (void *)qnodes[i];
0325 icc_node_add(node, provider);
0326
0327 for (j = 0; j < qnodes[i]->num_links; j++)
0328 icc_link_create(node, qnodes[i]->links[j]);
0329
0330 data->nodes[i] = node;
0331 }
0332 data->num_nodes = num_nodes;
0333
0334 platform_set_drvdata(pdev, qp);
0335
0336 return 0;
0337 err:
0338 icc_nodes_remove(provider);
0339 icc_provider_del(provider);
0340
0341 return ret;
0342 }
0343
0344 static const struct of_device_id osm_l3_of_match[] = {
0345 { .compatible = "qcom,sc7180-osm-l3", .data = &sc7180_icc_osm_l3 },
0346 { .compatible = "qcom,sc7280-epss-l3", .data = &sc7280_icc_epss_l3 },
0347 { .compatible = "qcom,sdm845-osm-l3", .data = &sdm845_icc_osm_l3 },
0348 { .compatible = "qcom,sm8150-osm-l3", .data = &sm8150_icc_osm_l3 },
0349 { .compatible = "qcom,sc8180x-osm-l3", .data = &sc8180x_icc_osm_l3 },
0350 { .compatible = "qcom,sm8250-epss-l3", .data = &sm8250_icc_epss_l3 },
0351 { }
0352 };
0353 MODULE_DEVICE_TABLE(of, osm_l3_of_match);
0354
0355 static struct platform_driver osm_l3_driver = {
0356 .probe = qcom_osm_l3_probe,
0357 .remove = qcom_osm_l3_remove,
0358 .driver = {
0359 .name = "osm-l3",
0360 .of_match_table = osm_l3_of_match,
0361 .sync_state = icc_sync_state,
0362 },
0363 };
0364 module_platform_driver(osm_l3_driver);
0365
0366 MODULE_DESCRIPTION("Qualcomm OSM L3 interconnect driver");
0367 MODULE_LICENSE("GPL v2");