linux/drivers/clk/bcm/clk-bcm63xx-gate.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <linux/clk-provider.h>
   4#include <linux/init.h>
   5#include <linux/of.h>
   6#include <linux/of_device.h>
   7#include <linux/platform_device.h>
   8
   9#include <dt-bindings/clock/bcm3368-clock.h>
  10#include <dt-bindings/clock/bcm6318-clock.h>
  11#include <dt-bindings/clock/bcm6328-clock.h>
  12#include <dt-bindings/clock/bcm6358-clock.h>
  13#include <dt-bindings/clock/bcm6362-clock.h>
  14#include <dt-bindings/clock/bcm6368-clock.h>
  15#include <dt-bindings/clock/bcm63268-clock.h>
  16
  17struct clk_bcm63xx_table_entry {
  18        const char * const name;
  19        u8 bit;
  20        unsigned long flags;
  21};
  22
  23struct clk_bcm63xx_hw {
  24        void __iomem *regs;
  25        spinlock_t lock;
  26
  27        struct clk_hw_onecell_data data;
  28};
  29
  30static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = {
  31        {
  32                .name = "mac",
  33                .bit = BCM3368_CLK_MAC,
  34        }, {
  35                .name = "tc",
  36                .bit = BCM3368_CLK_TC,
  37        }, {
  38                .name = "us_top",
  39                .bit = BCM3368_CLK_US_TOP,
  40        }, {
  41                .name = "ds_top",
  42                .bit = BCM3368_CLK_DS_TOP,
  43        }, {
  44                .name = "acm",
  45                .bit = BCM3368_CLK_ACM,
  46        }, {
  47                .name = "spi",
  48                .bit = BCM3368_CLK_SPI,
  49        }, {
  50                .name = "usbs",
  51                .bit = BCM3368_CLK_USBS,
  52        }, {
  53                .name = "bmu",
  54                .bit = BCM3368_CLK_BMU,
  55        }, {
  56                .name = "pcm",
  57                .bit = BCM3368_CLK_PCM,
  58        }, {
  59                .name = "ntp",
  60                .bit = BCM3368_CLK_NTP,
  61        }, {
  62                .name = "acp_b",
  63                .bit = BCM3368_CLK_ACP_B,
  64        }, {
  65                .name = "acp_a",
  66                .bit = BCM3368_CLK_ACP_A,
  67        }, {
  68                .name = "emusb",
  69                .bit = BCM3368_CLK_EMUSB,
  70        }, {
  71                .name = "enet0",
  72                .bit = BCM3368_CLK_ENET0,
  73        }, {
  74                .name = "enet1",
  75                .bit = BCM3368_CLK_ENET1,
  76        }, {
  77                .name = "usbsu",
  78                .bit = BCM3368_CLK_USBSU,
  79        }, {
  80                .name = "ephy",
  81                .bit = BCM3368_CLK_EPHY,
  82        }, {
  83                /* sentinel */
  84        },
  85};
  86
  87static const struct clk_bcm63xx_table_entry bcm6318_clocks[] = {
  88        {
  89                .name = "adsl_asb",
  90                .bit = BCM6318_CLK_ADSL_ASB,
  91        }, {
  92                .name = "usb_asb",
  93                .bit = BCM6318_CLK_USB_ASB,
  94        }, {
  95                .name = "mips_asb",
  96                .bit = BCM6318_CLK_MIPS_ASB,
  97        }, {
  98                .name = "pcie_asb",
  99                .bit = BCM6318_CLK_PCIE_ASB,
 100        }, {
 101                .name = "phymips_asb",
 102                .bit = BCM6318_CLK_PHYMIPS_ASB,
 103        }, {
 104                .name = "robosw_asb",
 105                .bit = BCM6318_CLK_ROBOSW_ASB,
 106        }, {
 107                .name = "sar_asb",
 108                .bit = BCM6318_CLK_SAR_ASB,
 109        }, {
 110                .name = "sdr_asb",
 111                .bit = BCM6318_CLK_SDR_ASB,
 112        }, {
 113                .name = "swreg_asb",
 114                .bit = BCM6318_CLK_SWREG_ASB,
 115        }, {
 116                .name = "periph_asb",
 117                .bit = BCM6318_CLK_PERIPH_ASB,
 118        }, {
 119                .name = "cpubus160",
 120                .bit = BCM6318_CLK_CPUBUS160,
 121        }, {
 122                .name = "adsl",
 123                .bit = BCM6318_CLK_ADSL,
 124        }, {
 125                .name = "sar125",
 126                .bit = BCM6318_CLK_SAR125,
 127        }, {
 128                .name = "mips",
 129                .bit = BCM6318_CLK_MIPS,
 130                .flags = CLK_IS_CRITICAL,
 131        }, {
 132                .name = "pcie",
 133                .bit = BCM6318_CLK_PCIE,
 134        }, {
 135                .name = "robosw250",
 136                .bit = BCM6318_CLK_ROBOSW250,
 137        }, {
 138                .name = "robosw025",
 139                .bit = BCM6318_CLK_ROBOSW025,
 140        }, {
 141                .name = "sdr",
 142                .bit = BCM6318_CLK_SDR,
 143                .flags = CLK_IS_CRITICAL,
 144        }, {
 145                .name = "usbd",
 146                .bit = BCM6318_CLK_USBD,
 147        }, {
 148                .name = "hsspi",
 149                .bit = BCM6318_CLK_HSSPI,
 150        }, {
 151                .name = "pcie25",
 152                .bit = BCM6318_CLK_PCIE25,
 153        }, {
 154                .name = "phymips",
 155                .bit = BCM6318_CLK_PHYMIPS,
 156        }, {
 157                .name = "afe",
 158                .bit = BCM6318_CLK_AFE,
 159        }, {
 160                .name = "qproc",
 161                .bit = BCM6318_CLK_QPROC,
 162        }, {
 163                /* sentinel */
 164        },
 165};
 166
 167static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks[] = {
 168        {
 169                .name = "adsl-ubus",
 170                .bit = BCM6318_UCLK_ADSL,
 171        }, {
 172                .name = "arb-ubus",
 173                .bit = BCM6318_UCLK_ARB,
 174                .flags = CLK_IS_CRITICAL,
 175        }, {
 176                .name = "mips-ubus",
 177                .bit = BCM6318_UCLK_MIPS,
 178                .flags = CLK_IS_CRITICAL,
 179        }, {
 180                .name = "pcie-ubus",
 181                .bit = BCM6318_UCLK_PCIE,
 182        }, {
 183                .name = "periph-ubus",
 184                .bit = BCM6318_UCLK_PERIPH,
 185                .flags = CLK_IS_CRITICAL,
 186        }, {
 187                .name = "phymips-ubus",
 188                .bit = BCM6318_UCLK_PHYMIPS,
 189        }, {
 190                .name = "robosw-ubus",
 191                .bit = BCM6318_UCLK_ROBOSW,
 192        }, {
 193                .name = "sar-ubus",
 194                .bit = BCM6318_UCLK_SAR,
 195        }, {
 196                .name = "sdr-ubus",
 197                .bit = BCM6318_UCLK_SDR,
 198        }, {
 199                .name = "usb-ubus",
 200                .bit = BCM6318_UCLK_USB,
 201        }, {
 202                /* sentinel */
 203        },
 204};
 205
 206static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = {
 207        {
 208                .name = "phy_mips",
 209                .bit = BCM6328_CLK_PHYMIPS,
 210        }, {
 211                .name = "adsl_qproc",
 212                .bit = BCM6328_CLK_ADSL_QPROC,
 213        }, {
 214                .name = "adsl_afe",
 215                .bit = BCM6328_CLK_ADSL_AFE,
 216        }, {
 217                .name = "adsl",
 218                .bit = BCM6328_CLK_ADSL,
 219        }, {
 220                .name = "mips",
 221                .bit = BCM6328_CLK_MIPS,
 222                .flags = CLK_IS_CRITICAL,
 223        }, {
 224                .name = "sar",
 225                .bit = BCM6328_CLK_SAR,
 226        }, {
 227                .name = "pcm",
 228                .bit = BCM6328_CLK_PCM,
 229        }, {
 230                .name = "usbd",
 231                .bit = BCM6328_CLK_USBD,
 232        }, {
 233                .name = "usbh",
 234                .bit = BCM6328_CLK_USBH,
 235        }, {
 236                .name = "hsspi",
 237                .bit = BCM6328_CLK_HSSPI,
 238        }, {
 239                .name = "pcie",
 240                .bit = BCM6328_CLK_PCIE,
 241        }, {
 242                .name = "robosw",
 243                .bit = BCM6328_CLK_ROBOSW,
 244        }, {
 245                /* sentinel */
 246        },
 247};
 248
 249static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = {
 250        {
 251                .name = "enet",
 252                .bit = BCM6358_CLK_ENET,
 253        }, {
 254                .name = "adslphy",
 255                .bit = BCM6358_CLK_ADSLPHY,
 256        }, {
 257                .name = "pcm",
 258                .bit = BCM6358_CLK_PCM,
 259        }, {
 260                .name = "spi",
 261                .bit = BCM6358_CLK_SPI,
 262        }, {
 263                .name = "usbs",
 264                .bit = BCM6358_CLK_USBS,
 265        }, {
 266                .name = "sar",
 267                .bit = BCM6358_CLK_SAR,
 268        }, {
 269                .name = "emusb",
 270                .bit = BCM6358_CLK_EMUSB,
 271        }, {
 272                .name = "enet0",
 273                .bit = BCM6358_CLK_ENET0,
 274        }, {
 275                .name = "enet1",
 276                .bit = BCM6358_CLK_ENET1,
 277        }, {
 278                .name = "usbsu",
 279                .bit = BCM6358_CLK_USBSU,
 280        }, {
 281                .name = "ephy",
 282                .bit = BCM6358_CLK_EPHY,
 283        }, {
 284                /* sentinel */
 285        },
 286};
 287
 288static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = {
 289        {
 290                .name = "adsl_qproc",
 291                .bit = BCM6362_CLK_ADSL_QPROC,
 292        }, {
 293                .name = "adsl_afe",
 294                .bit = BCM6362_CLK_ADSL_AFE,
 295        }, {
 296                .name = "adsl",
 297                .bit = BCM6362_CLK_ADSL,
 298        }, {
 299                .name = "mips",
 300                .bit = BCM6362_CLK_MIPS,
 301                .flags = CLK_IS_CRITICAL,
 302        }, {
 303                .name = "wlan_ocp",
 304                .bit = BCM6362_CLK_WLAN_OCP,
 305        }, {
 306                .name = "swpkt_usb",
 307                .bit = BCM6362_CLK_SWPKT_USB,
 308        }, {
 309                .name = "swpkt_sar",
 310                .bit = BCM6362_CLK_SWPKT_SAR,
 311        }, {
 312                .name = "sar",
 313                .bit = BCM6362_CLK_SAR,
 314        }, {
 315                .name = "robosw",
 316                .bit = BCM6362_CLK_ROBOSW,
 317        }, {
 318                .name = "pcm",
 319                .bit = BCM6362_CLK_PCM,
 320        }, {
 321                .name = "usbd",
 322                .bit = BCM6362_CLK_USBD,
 323        }, {
 324                .name = "usbh",
 325                .bit = BCM6362_CLK_USBH,
 326        }, {
 327                .name = "ipsec",
 328                .bit = BCM6362_CLK_IPSEC,
 329        }, {
 330                .name = "spi",
 331                .bit = BCM6362_CLK_SPI,
 332        }, {
 333                .name = "hsspi",
 334                .bit = BCM6362_CLK_HSSPI,
 335        }, {
 336                .name = "pcie",
 337                .bit = BCM6362_CLK_PCIE,
 338        }, {
 339                .name = "fap",
 340                .bit = BCM6362_CLK_FAP,
 341        }, {
 342                .name = "phymips",
 343                .bit = BCM6362_CLK_PHYMIPS,
 344        }, {
 345                .name = "nand",
 346                .bit = BCM6362_CLK_NAND,
 347        }, {
 348                /* sentinel */
 349        },
 350};
 351
 352static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = {
 353        {
 354                .name = "vdsl_qproc",
 355                .bit = BCM6368_CLK_VDSL_QPROC,
 356        }, {
 357                .name = "vdsl_afe",
 358                .bit = BCM6368_CLK_VDSL_AFE,
 359        }, {
 360                .name = "vdsl_bonding",
 361                .bit = BCM6368_CLK_VDSL_BONDING,
 362        }, {
 363                .name = "vdsl",
 364                .bit = BCM6368_CLK_VDSL,
 365        }, {
 366                .name = "phymips",
 367                .bit = BCM6368_CLK_PHYMIPS,
 368        }, {
 369                .name = "swpkt_usb",
 370                .bit = BCM6368_CLK_SWPKT_USB,
 371        }, {
 372                .name = "swpkt_sar",
 373                .bit = BCM6368_CLK_SWPKT_SAR,
 374        }, {
 375                .name = "spi",
 376                .bit = BCM6368_CLK_SPI,
 377        }, {
 378                .name = "usbd",
 379                .bit = BCM6368_CLK_USBD,
 380        }, {
 381                .name = "sar",
 382                .bit = BCM6368_CLK_SAR,
 383        }, {
 384                .name = "robosw",
 385                .bit = BCM6368_CLK_ROBOSW,
 386        }, {
 387                .name = "utopia",
 388                .bit = BCM6368_CLK_UTOPIA,
 389        }, {
 390                .name = "pcm",
 391                .bit = BCM6368_CLK_PCM,
 392        }, {
 393                .name = "usbh",
 394                .bit = BCM6368_CLK_USBH,
 395        }, {
 396                .name = "disable_gless",
 397                .bit = BCM6368_CLK_DIS_GLESS,
 398        }, {
 399                .name = "nand",
 400                .bit = BCM6368_CLK_NAND,
 401        }, {
 402                .name = "ipsec",
 403                .bit = BCM6368_CLK_IPSEC,
 404        }, {
 405                /* sentinel */
 406        },
 407};
 408
 409static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = {
 410        {
 411                .name = "disable_gless",
 412                .bit = BCM63268_CLK_DIS_GLESS,
 413        }, {
 414                .name = "vdsl_qproc",
 415                .bit = BCM63268_CLK_VDSL_QPROC,
 416        }, {
 417                .name = "vdsl_afe",
 418                .bit = BCM63268_CLK_VDSL_AFE,
 419        }, {
 420                .name = "vdsl",
 421                .bit = BCM63268_CLK_VDSL,
 422        }, {
 423                .name = "mips",
 424                .bit = BCM63268_CLK_MIPS,
 425                .flags = CLK_IS_CRITICAL,
 426        }, {
 427                .name = "wlan_ocp",
 428                .bit = BCM63268_CLK_WLAN_OCP,
 429        }, {
 430                .name = "dect",
 431                .bit = BCM63268_CLK_DECT,
 432        }, {
 433                .name = "fap0",
 434                .bit = BCM63268_CLK_FAP0,
 435        }, {
 436                .name = "fap1",
 437                .bit = BCM63268_CLK_FAP1,
 438        }, {
 439                .name = "sar",
 440                .bit = BCM63268_CLK_SAR,
 441        }, {
 442                .name = "robosw",
 443                .bit = BCM63268_CLK_ROBOSW,
 444        }, {
 445                .name = "pcm",
 446                .bit = BCM63268_CLK_PCM,
 447        }, {
 448                .name = "usbd",
 449                .bit = BCM63268_CLK_USBD,
 450        }, {
 451                .name = "usbh",
 452                .bit = BCM63268_CLK_USBH,
 453        }, {
 454                .name = "ipsec",
 455                .bit = BCM63268_CLK_IPSEC,
 456        }, {
 457                .name = "spi",
 458                .bit = BCM63268_CLK_SPI,
 459        }, {
 460                .name = "hsspi",
 461                .bit = BCM63268_CLK_HSSPI,
 462        }, {
 463                .name = "pcie",
 464                .bit = BCM63268_CLK_PCIE,
 465        }, {
 466                .name = "phymips",
 467                .bit = BCM63268_CLK_PHYMIPS,
 468        }, {
 469                .name = "gmac",
 470                .bit = BCM63268_CLK_GMAC,
 471        }, {
 472                .name = "nand",
 473                .bit = BCM63268_CLK_NAND,
 474        }, {
 475                .name = "tbus",
 476                .bit = BCM63268_CLK_TBUS,
 477        }, {
 478                .name = "robosw250",
 479                .bit = BCM63268_CLK_ROBOSW250,
 480        }, {
 481                /* sentinel */
 482        },
 483};
 484
 485static int clk_bcm63xx_probe(struct platform_device *pdev)
 486{
 487        const struct clk_bcm63xx_table_entry *entry, *table;
 488        struct clk_bcm63xx_hw *hw;
 489        u8 maxbit = 0;
 490        int i, ret;
 491
 492        table = of_device_get_match_data(&pdev->dev);
 493        if (!table)
 494                return -EINVAL;
 495
 496        for (entry = table; entry->name; entry++)
 497                maxbit = max_t(u8, maxbit, entry->bit);
 498        maxbit++;
 499
 500        hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
 501                          GFP_KERNEL);
 502        if (!hw)
 503                return -ENOMEM;
 504
 505        platform_set_drvdata(pdev, hw);
 506
 507        spin_lock_init(&hw->lock);
 508
 509        hw->data.num = maxbit;
 510        for (i = 0; i < maxbit; i++)
 511                hw->data.hws[i] = ERR_PTR(-ENODEV);
 512
 513        hw->regs = devm_platform_ioremap_resource(pdev, 0);
 514        if (IS_ERR(hw->regs))
 515                return PTR_ERR(hw->regs);
 516
 517        for (entry = table; entry->name; entry++) {
 518                struct clk_hw *clk;
 519
 520                clk = clk_hw_register_gate(&pdev->dev, entry->name, NULL,
 521                                           entry->flags, hw->regs, entry->bit,
 522                                           CLK_GATE_BIG_ENDIAN, &hw->lock);
 523                if (IS_ERR(clk)) {
 524                        ret = PTR_ERR(clk);
 525                        goto out_err;
 526                }
 527
 528                hw->data.hws[entry->bit] = clk;
 529        }
 530
 531        ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
 532                                     &hw->data);
 533        if (!ret)
 534                return 0;
 535out_err:
 536        for (i = 0; i < hw->data.num; i++) {
 537                if (!IS_ERR(hw->data.hws[i]))
 538                        clk_hw_unregister_gate(hw->data.hws[i]);
 539        }
 540
 541        return ret;
 542}
 543
 544static int clk_bcm63xx_remove(struct platform_device *pdev)
 545{
 546        struct clk_bcm63xx_hw *hw = platform_get_drvdata(pdev);
 547        int i;
 548
 549        of_clk_del_provider(pdev->dev.of_node);
 550
 551        for (i = 0; i < hw->data.num; i++) {
 552                if (!IS_ERR(hw->data.hws[i]))
 553                        clk_hw_unregister_gate(hw->data.hws[i]);
 554        }
 555
 556        return 0;
 557}
 558
 559static const struct of_device_id clk_bcm63xx_dt_ids[] = {
 560        { .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, },
 561        { .compatible = "brcm,bcm6318-clocks", .data = &bcm6318_clocks, },
 562        { .compatible = "brcm,bcm6318-ubus-clocks", .data = &bcm6318_ubus_clocks, },
 563        { .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, },
 564        { .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, },
 565        { .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, },
 566        { .compatible = "brcm,bcm6368-clocks", .data = &bcm6368_clocks, },
 567        { .compatible = "brcm,bcm63268-clocks", .data = &bcm63268_clocks, },
 568        { }
 569};
 570
 571static struct platform_driver clk_bcm63xx = {
 572        .probe = clk_bcm63xx_probe,
 573        .remove = clk_bcm63xx_remove,
 574        .driver = {
 575                .name = "bcm63xx-clock",
 576                .of_match_table = clk_bcm63xx_dt_ids,
 577        },
 578};
 579builtin_platform_driver(clk_bcm63xx);
 580