Message ID | 20220728111905.12427-8-Sergey.Semin@baikalelectronics.ru |
---|---|
State | New |
Headers | show |
Series | ata: ahci: Add DWC/Baikal-T1 AHCI SATA support | expand |
Hi Serge, I love your patch! Yet something to improve: [auto build test ERROR on robh/for-next] [also build test ERROR on axboe-block/for-next linus/master v5.19-rc8 next-20220728] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Serge-Semin/ata-ahci-Add-DWC-Baikal-T1-AHCI-SATA-support/20220728-192315 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next config: m68k-randconfig-s052-20220729 (https://download.01.org/0day-ci/archive/20220730/202207300343.gBqrivXn-lkp@intel.com/config) compiler: m68k-linux-gcc (GCC) 12.1.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.4-39-gce1a6720-dirty # https://github.com/intel-lab-lkp/linux/commit/a84e837dd293db69f2510f3036f2c83ce8b0167c git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Serge-Semin/ata-ahci-Add-DWC-Baikal-T1-AHCI-SATA-support/20220728-192315 git checkout a84e837dd293db69f2510f3036f2c83ce8b0167c # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=m68k SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): m68k-linux-ld: drivers/ata/libahci_platform.o: in function `ahci_platform_get_resources': >> drivers/ata/libahci_platform.c:428: undefined reference to `__clk_get_name' vim +428 drivers/ata/libahci_platform.c 347 348 /** 349 * ahci_platform_get_resources - Get platform resources 350 * @pdev: platform device to get resources for 351 * @flags: bitmap representing the resource to get 352 * 353 * This function allocates an ahci_host_priv struct, and gets the following 354 * resources, storing a reference to them inside the returned struct: 355 * 356 * 1) mmio registers (IORESOURCE_MEM 0, mandatory) 357 * 2) regulator for controlling the targets power (optional) 358 * regulator for controlling the AHCI controller (optional) 359 * 3) all clocks specified in the devicetree node, or a single 360 * clock for non-OF platforms (optional) 361 * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional) 362 * 5) phys (optional) 363 * 364 * RETURNS: 365 * The allocated ahci_host_priv on success, otherwise an ERR_PTR value 366 */ 367 struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, 368 unsigned int flags) 369 { 370 int child_nodes, rc = -ENOMEM, enabled_ports = 0; 371 struct device *dev = &pdev->dev; 372 struct ahci_host_priv *hpriv; 373 struct device_node *child; 374 u32 mask_port_map = 0; 375 376 if (!devres_open_group(dev, NULL, GFP_KERNEL)) 377 return ERR_PTR(-ENOMEM); 378 379 hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), 380 GFP_KERNEL); 381 if (!hpriv) 382 goto err_out; 383 384 devres_add(dev, hpriv); 385 386 /* 387 * If the DT provided an "ahci" named resource, use it. Otherwise, 388 * fallback to using the default first resource for the device node. 389 */ 390 if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci")) 391 hpriv->mmio = devm_platform_ioremap_resource_byname(pdev, "ahci"); 392 else 393 hpriv->mmio = devm_platform_ioremap_resource(pdev, 0); 394 if (IS_ERR(hpriv->mmio)) { 395 rc = PTR_ERR(hpriv->mmio); 396 goto err_out; 397 } 398 399 /* 400 * Bulk clocks getting procedure can fail to find any clock due to 401 * running on a non-OF platform or due to the clocks being defined in 402 * bypass of the DT firmware (like da850, spear13xx). In that case we 403 * fallback to getting a single clock source right from the dev clocks 404 * list. 405 */ 406 rc = devm_clk_bulk_get_all(dev, &hpriv->clks); 407 if (rc < 0) 408 goto err_out; 409 410 if (rc > 0) { 411 /* Got clocks in bulk */ 412 hpriv->n_clks = rc; 413 } else { 414 /* 415 * No clock bulk found: fallback to manually getting 416 * the optional clock. 417 */ 418 hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL); 419 if (!hpriv->clks) { 420 rc = -ENOMEM; 421 goto err_out; 422 } 423 hpriv->clks->clk = devm_clk_get_optional(dev, NULL); 424 if (IS_ERR(hpriv->clks->clk)) { 425 rc = PTR_ERR(hpriv->clks->clk); 426 goto err_out; 427 } else if (hpriv->clks->clk) { > 428 hpriv->clks->id = __clk_get_name(hpriv->clks->clk); 429 hpriv->n_clks = 1; 430 } 431 } 432 433 hpriv->ahci_regulator = devm_regulator_get(dev, "ahci"); 434 if (IS_ERR(hpriv->ahci_regulator)) { 435 rc = PTR_ERR(hpriv->ahci_regulator); 436 if (rc != 0) 437 goto err_out; 438 } 439 440 hpriv->phy_regulator = devm_regulator_get(dev, "phy"); 441 if (IS_ERR(hpriv->phy_regulator)) { 442 rc = PTR_ERR(hpriv->phy_regulator); 443 goto err_out; 444 } 445 446 if (flags & AHCI_PLATFORM_GET_RESETS) { 447 hpriv->rsts = devm_reset_control_array_get_optional_shared(dev); 448 if (IS_ERR(hpriv->rsts)) { 449 rc = PTR_ERR(hpriv->rsts); 450 goto err_out; 451 } 452 } 453 454 hpriv->nports = child_nodes = of_get_child_count(dev->of_node); 455 456 /* 457 * If no sub-node was found, we still need to set nports to 458 * one in order to be able to use the 459 * ahci_platform_[en|dis]able_[phys|regulators] functions. 460 */ 461 if (!child_nodes) 462 hpriv->nports = 1; 463 464 hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL); 465 if (!hpriv->phys) { 466 rc = -ENOMEM; 467 goto err_out; 468 } 469 /* 470 * We cannot use devm_ here, since ahci_platform_put_resources() uses 471 * target_pwrs after devm_ have freed memory 472 */ 473 hpriv->target_pwrs = kcalloc(hpriv->nports, sizeof(*hpriv->target_pwrs), GFP_KERNEL); 474 if (!hpriv->target_pwrs) { 475 rc = -ENOMEM; 476 goto err_out; 477 } 478 479 if (child_nodes) { 480 for_each_child_of_node(dev->of_node, child) { 481 u32 port; 482 struct platform_device *port_dev __maybe_unused; 483 484 if (!of_device_is_available(child)) 485 continue; 486 487 if (of_property_read_u32(child, "reg", &port)) { 488 rc = -EINVAL; 489 of_node_put(child); 490 goto err_out; 491 } 492 493 if (port >= hpriv->nports) { 494 dev_warn(dev, "invalid port number %d\n", port); 495 continue; 496 } 497 mask_port_map |= BIT(port); 498
Hi Serge, I love your patch! Yet something to improve: [auto build test ERROR on robh/for-next] [also build test ERROR on axboe-block/for-next linus/master v5.19-rc8 next-20220728] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Serge-Semin/ata-ahci-Add-DWC-Baikal-T1-AHCI-SATA-support/20220728-192315 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next config: csky-randconfig-r023-20220729 (https://download.01.org/0day-ci/archive/20220730/202207300915.8DDz66ju-lkp@intel.com/config) compiler: csky-linux-gcc (GCC) 12.1.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/a84e837dd293db69f2510f3036f2c83ce8b0167c git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Serge-Semin/ata-ahci-Add-DWC-Baikal-T1-AHCI-SATA-support/20220728-192315 git checkout a84e837dd293db69f2510f3036f2c83ce8b0167c # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=csky SHELL=/bin/bash drivers/ata/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): drivers/ata/ahci_da850.c: In function 'ahci_da850_probe': >> drivers/ata/ahci_da850.c:181:13: error: wrong type argument to unary exclamation mark 181 | if (!hpriv->clks[0]) { | ^ >> drivers/ata/ahci_da850.c:186:34: error: incompatible types when assigning to type 'struct clk_bulk_data' from type 'struct clk *' 186 | hpriv->clks[0] = clk; | ^~~ drivers/ata/ahci_da850.c:194:13: error: wrong type argument to unary exclamation mark 194 | if (!hpriv->clks[1]) { | ^ drivers/ata/ahci_da850.c:201:34: error: incompatible types when assigning to type 'struct clk_bulk_data' from type 'struct clk *' 201 | hpriv->clks[1] = clk; | ^~~ >> drivers/ata/ahci_da850.c:204:64: error: incompatible type for argument 1 of 'clk_get_rate' 204 | mpy = ahci_da850_calculate_mpy(clk_get_rate(hpriv->clks[1])); | ~~~~~~~~~~~^~~ | | | struct clk_bulk_data In file included from drivers/ata/ahci.h:23, from drivers/ata/ahci_da850.c:13: include/linux/clk.h:584:40: note: expected 'struct clk *' but argument is of type 'struct clk_bulk_data' 584 | unsigned long clk_get_rate(struct clk *clk); | ~~~~~~~~~~~~^~~ -- drivers/ata/ahci_dm816.c: In function 'ahci_dm816_phy_init': >> drivers/ata/ahci_dm816.c:72:13: error: wrong type argument to unary exclamation mark 72 | if (!hpriv->clks[1]) { | ^ >> drivers/ata/ahci_dm816.c:77:47: error: incompatible type for argument 1 of 'clk_get_rate' 77 | refclk_rate = clk_get_rate(hpriv->clks[1]); | ~~~~~~~~~~~^~~ | | | struct clk_bulk_data In file included from drivers/ata/ahci.h:23, from drivers/ata/ahci_dm816.c:16: include/linux/clk.h:584:40: note: expected 'struct clk *' but argument is of type 'struct clk_bulk_data' 584 | unsigned long clk_get_rate(struct clk *clk); | ~~~~~~~~~~~~^~~ vim +186 drivers/ata/ahci_da850.c 018d5ef2048fcab Akinobu Mita 2015-01-29 159 ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 160 static int ahci_da850_probe(struct platform_device *pdev) ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 161 { ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 162 struct device *dev = &pdev->dev; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 163 struct ahci_host_priv *hpriv; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 164 void __iomem *pwrdn_reg; cdf0ead3747200d Bartosz Golaszewski 2017-01-30 165 struct resource *res; 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 166 struct clk *clk; cdf0ead3747200d Bartosz Golaszewski 2017-01-30 167 u32 mpy; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 168 int rc; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 169 16af2d65842d343 Kunihiko Hayashi 2018-08-22 170 hpriv = ahci_platform_get_resources(pdev, 0); ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 171 if (IS_ERR(hpriv)) ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 172 return PTR_ERR(hpriv); ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 173 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 174 /* 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 175 * Internally ahci_platform_get_resources() calls clk_get(dev, NULL) 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 176 * when trying to obtain the functional clock. This SATA controller 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 177 * uses two clocks for which we specify two connection ids. If we don't 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 178 * have the functional clock at this point - call clk_get() again with 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 179 * con_id = "fck". 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 180 */ 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 @181 if (!hpriv->clks[0]) { 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 182 clk = clk_get(dev, "fck"); 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 183 if (IS_ERR(clk)) 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 184 return PTR_ERR(clk); 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 185 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 @186 hpriv->clks[0] = clk; 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 187 } 82dbe1a68fd65a4 Bartosz Golaszewski 2017-01-30 188 cdf0ead3747200d Bartosz Golaszewski 2017-01-30 189 /* cdf0ead3747200d Bartosz Golaszewski 2017-01-30 190 * The second clock used by ahci-da850 is the external REFCLK. If we cdf0ead3747200d Bartosz Golaszewski 2017-01-30 191 * didn't get it from ahci_platform_get_resources(), let's try to cdf0ead3747200d Bartosz Golaszewski 2017-01-30 192 * specify the con_id in clk_get(). cdf0ead3747200d Bartosz Golaszewski 2017-01-30 193 */ cdf0ead3747200d Bartosz Golaszewski 2017-01-30 194 if (!hpriv->clks[1]) { cdf0ead3747200d Bartosz Golaszewski 2017-01-30 195 clk = clk_get(dev, "refclk"); cdf0ead3747200d Bartosz Golaszewski 2017-01-30 196 if (IS_ERR(clk)) { cdf0ead3747200d Bartosz Golaszewski 2017-01-30 197 dev_err(dev, "unable to obtain the reference clock"); cdf0ead3747200d Bartosz Golaszewski 2017-01-30 198 return -ENODEV; cdf0ead3747200d Bartosz Golaszewski 2017-01-30 199 } cdf0ead3747200d Bartosz Golaszewski 2017-01-30 200 cdf0ead3747200d Bartosz Golaszewski 2017-01-30 201 hpriv->clks[1] = clk; cdf0ead3747200d Bartosz Golaszewski 2017-01-30 202 } cdf0ead3747200d Bartosz Golaszewski 2017-01-30 203 cdf0ead3747200d Bartosz Golaszewski 2017-01-30 @204 mpy = ahci_da850_calculate_mpy(clk_get_rate(hpriv->clks[1])); cdf0ead3747200d Bartosz Golaszewski 2017-01-30 205 if (mpy == 0) { cdf0ead3747200d Bartosz Golaszewski 2017-01-30 206 dev_err(dev, "invalid REFCLK multiplier value: 0x%x", mpy); cdf0ead3747200d Bartosz Golaszewski 2017-01-30 207 return -EINVAL; cdf0ead3747200d Bartosz Golaszewski 2017-01-30 208 } cdf0ead3747200d Bartosz Golaszewski 2017-01-30 209 ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 210 rc = ahci_platform_enable_resources(hpriv); ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 211 if (rc) ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 212 return rc; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 213 ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 214 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); c88c094985ad38c Christophe JAILLET 2017-08-16 215 if (!res) { c88c094985ad38c Christophe JAILLET 2017-08-16 216 rc = -ENODEV; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 217 goto disable_resources; c88c094985ad38c Christophe JAILLET 2017-08-16 218 } ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 219 ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 220 pwrdn_reg = devm_ioremap(dev, res->start, resource_size(res)); c88c094985ad38c Christophe JAILLET 2017-08-16 221 if (!pwrdn_reg) { c88c094985ad38c Christophe JAILLET 2017-08-16 222 rc = -ENOMEM; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 223 goto disable_resources; c88c094985ad38c Christophe JAILLET 2017-08-16 224 } ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 225 cdf0ead3747200d Bartosz Golaszewski 2017-01-30 226 da850_sata_init(dev, pwrdn_reg, hpriv->mmio, mpy); ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 227 018d5ef2048fcab Akinobu Mita 2015-01-29 228 rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, 018d5ef2048fcab Akinobu Mita 2015-01-29 229 &ahci_platform_sht); ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 230 if (rc) ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 231 goto disable_resources; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 232 ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 233 return 0; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 234 disable_resources: ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 235 ahci_platform_disable_resources(hpriv); ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 236 return rc; ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 237 } ae8723f8a9c8e80 Bartlomiej Zolnierkiewicz 2014-03-25 238
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index ad11a4c52fbe..c3770a19781b 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -38,7 +38,6 @@ enum { AHCI_MAX_PORTS = 32, - AHCI_MAX_CLKS = 5, AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_MAX_CMDS = 32, @@ -339,7 +338,8 @@ struct ahci_host_priv { u32 em_msg_type; /* EM message type */ u32 remapped_nvme; /* NVMe remapped device count */ bool got_runtime_pm; /* Did we do pm_runtime_get? */ - struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + unsigned int n_clks; + struct clk_bulk_data *clks; /* Optional */ struct reset_control *rsts; /* Optional */ struct regulator **target_pwrs; /* Optional */ struct regulator *ahci_regulator;/* Optional */ diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 1e9e825d6cc5..814804582d1d 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -8,6 +8,7 @@ * Anton Vorontsov <avorontsov@ru.mvista.com> */ +#include <linux/clk-provider.h> #include <linux/clk.h> #include <linux/kernel.h> #include <linux/gfp.h> @@ -97,28 +98,14 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_phys); * ahci_platform_enable_clks - Enable platform clocks * @hpriv: host private area to store config values * - * This function enables all the clks found in hpriv->clks, starting at - * index 0. If any clk fails to enable it disables all the clks already - * enabled in reverse order, and then returns an error. + * This function enables all the clks found for the AHCI device. * * RETURNS: * 0 on success otherwise a negative error code */ int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) { - int c, rc; - - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { - rc = clk_prepare_enable(hpriv->clks[c]); - if (rc) - goto disable_unprepare_clk; - } - return 0; - -disable_unprepare_clk: - while (--c >= 0) - clk_disable_unprepare(hpriv->clks[c]); - return rc; + return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks); } EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); @@ -126,16 +113,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); * ahci_platform_disable_clks - Disable platform clocks * @hpriv: host private area to store config values * - * This function disables all the clks found in hpriv->clks, in reverse - * order of ahci_platform_enable_clks (starting at the end of the array). + * This function disables all the clocks enabled before + * (bulk-clocks-disable function is supposed to do that in reverse + * from the enabling procedure order). */ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) { - int c; - - for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) - if (hpriv->clks[c]) - clk_disable_unprepare(hpriv->clks[c]); + clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks); } EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); @@ -292,8 +276,6 @@ static void ahci_platform_put_resources(struct device *dev, void *res) pm_runtime_disable(dev); } - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) - clk_put(hpriv->clks[c]); /* * The regulators are tied to child node device and not to the * SATA device itself. So we can't use devm for automatically @@ -374,8 +356,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, * 1) mmio registers (IORESOURCE_MEM 0, mandatory) * 2) regulator for controlling the targets power (optional) * regulator for controlling the AHCI controller (optional) - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, - * or for non devicetree enabled platforms a single clock + * 3) all clocks specified in the devicetree node, or a single + * clock for non-OF platforms (optional) * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional) * 5) phys (optional) * @@ -385,11 +367,10 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, unsigned int flags) { + int child_nodes, rc = -ENOMEM, enabled_ports = 0; struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; - struct clk *clk; struct device_node *child; - int i, enabled_ports = 0, rc = -ENOMEM, child_nodes; u32 mask_port_map = 0; if (!devres_open_group(dev, NULL, GFP_KERNEL)) @@ -415,25 +396,38 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, goto err_out; } - for (i = 0; i < AHCI_MAX_CLKS; i++) { + /* + * Bulk clocks getting procedure can fail to find any clock due to + * running on a non-OF platform or due to the clocks being defined in + * bypass of the DT firmware (like da850, spear13xx). In that case we + * fallback to getting a single clock source right from the dev clocks + * list. + */ + rc = devm_clk_bulk_get_all(dev, &hpriv->clks); + if (rc < 0) + goto err_out; + + if (rc > 0) { + /* Got clocks in bulk */ + hpriv->n_clks = rc; + } else { /* - * For now we must use clk_get(dev, NULL) for the first clock, - * because some platforms (da850, spear13xx) are not yet - * converted to use devicetree for clocks. For new platforms - * this is equivalent to of_clk_get(dev->of_node, 0). + * No clock bulk found: fallback to manually getting + * the optional clock. */ - if (i == 0) - clk = clk_get(dev, NULL); - else - clk = of_clk_get(dev->of_node, i); - - if (IS_ERR(clk)) { - rc = PTR_ERR(clk); - if (rc == -EPROBE_DEFER) - goto err_out; - break; + hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL); + if (!hpriv->clks) { + rc = -ENOMEM; + goto err_out; + } + hpriv->clks->clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(hpriv->clks->clk)) { + rc = PTR_ERR(hpriv->clks->clk); + goto err_out; + } else if (hpriv->clks->clk) { + hpriv->clks->id = __clk_get_name(hpriv->clks->clk); + hpriv->n_clks = 1; } - hpriv->clks[i] = clk; } hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");