| .. | .. |
|---|
| 206 | 206 | } |
|---|
| 207 | 207 | EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk); |
|---|
| 208 | 208 | |
|---|
| 209 | +/* Drop 'protected-clocks' from the list of clocks to register */ |
|---|
| 210 | +static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc) |
|---|
| 211 | +{ |
|---|
| 212 | + struct device_node *np = dev->of_node; |
|---|
| 213 | + struct property *prop; |
|---|
| 214 | + const __be32 *p; |
|---|
| 215 | + u32 i; |
|---|
| 216 | + |
|---|
| 217 | + of_property_for_each_u32(np, "protected-clocks", prop, p, i) { |
|---|
| 218 | + if (i >= cc->num_rclks) |
|---|
| 219 | + continue; |
|---|
| 220 | + |
|---|
| 221 | + cc->rclks[i] = NULL; |
|---|
| 222 | + } |
|---|
| 223 | +} |
|---|
| 224 | + |
|---|
| 209 | 225 | static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec, |
|---|
| 210 | 226 | void *data) |
|---|
| 211 | 227 | { |
|---|
| .. | .. |
|---|
| 217 | 233 | return ERR_PTR(-EINVAL); |
|---|
| 218 | 234 | } |
|---|
| 219 | 235 | |
|---|
| 220 | | - return cc->rclks[idx] ? &cc->rclks[idx]->hw : ERR_PTR(-ENOENT); |
|---|
| 236 | + return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL; |
|---|
| 221 | 237 | } |
|---|
| 222 | 238 | |
|---|
| 223 | 239 | int qcom_cc_really_probe(struct platform_device *pdev, |
|---|
| .. | .. |
|---|
| 230 | 246 | struct gdsc_desc *scd; |
|---|
| 231 | 247 | size_t num_clks = desc->num_clks; |
|---|
| 232 | 248 | struct clk_regmap **rclks = desc->clks; |
|---|
| 249 | + size_t num_clk_hws = desc->num_clk_hws; |
|---|
| 250 | + struct clk_hw **clk_hws = desc->clk_hws; |
|---|
| 233 | 251 | |
|---|
| 234 | 252 | cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL); |
|---|
| 235 | 253 | if (!cc) |
|---|
| .. | .. |
|---|
| 266 | 284 | cc->rclks = rclks; |
|---|
| 267 | 285 | cc->num_rclks = num_clks; |
|---|
| 268 | 286 | |
|---|
| 287 | + qcom_cc_drop_protected(dev, cc); |
|---|
| 288 | + |
|---|
| 289 | + for (i = 0; i < num_clk_hws; i++) { |
|---|
| 290 | + ret = devm_clk_hw_register(dev, clk_hws[i]); |
|---|
| 291 | + if (ret) |
|---|
| 292 | + return ret; |
|---|
| 293 | + } |
|---|
| 294 | + |
|---|
| 269 | 295 | for (i = 0; i < num_clks; i++) { |
|---|
| 270 | 296 | if (!rclks[i]) |
|---|
| 271 | 297 | continue; |
|---|
| .. | .. |
|---|
| 295 | 321 | } |
|---|
| 296 | 322 | EXPORT_SYMBOL_GPL(qcom_cc_probe); |
|---|
| 297 | 323 | |
|---|
| 324 | +int qcom_cc_probe_by_index(struct platform_device *pdev, int index, |
|---|
| 325 | + const struct qcom_cc_desc *desc) |
|---|
| 326 | +{ |
|---|
| 327 | + struct regmap *regmap; |
|---|
| 328 | + struct resource *res; |
|---|
| 329 | + void __iomem *base; |
|---|
| 330 | + |
|---|
| 331 | + res = platform_get_resource(pdev, IORESOURCE_MEM, index); |
|---|
| 332 | + base = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 333 | + if (IS_ERR(base)) |
|---|
| 334 | + return -ENOMEM; |
|---|
| 335 | + |
|---|
| 336 | + regmap = devm_regmap_init_mmio(&pdev->dev, base, desc->config); |
|---|
| 337 | + if (IS_ERR(regmap)) |
|---|
| 338 | + return PTR_ERR(regmap); |
|---|
| 339 | + |
|---|
| 340 | + return qcom_cc_really_probe(pdev, desc, regmap); |
|---|
| 341 | +} |
|---|
| 342 | +EXPORT_SYMBOL_GPL(qcom_cc_probe_by_index); |
|---|
| 343 | + |
|---|
| 298 | 344 | MODULE_LICENSE("GPL v2"); |
|---|