1e7300d04SMaxime Bizon /* 2e7300d04SMaxime Bizon * This file is subject to the terms and conditions of the GNU General Public 3e7300d04SMaxime Bizon * License. See the file "COPYING" in the main directory of this archive 4e7300d04SMaxime Bizon * for more details. 5e7300d04SMaxime Bizon * 6e7300d04SMaxime Bizon * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 7e7300d04SMaxime Bizon */ 8e7300d04SMaxime Bizon 926dd3e4fSPaul Gortmaker #include <linux/init.h> 1026dd3e4fSPaul Gortmaker #include <linux/export.h> 11e7300d04SMaxime Bizon #include <linux/mutex.h> 12e7300d04SMaxime Bizon #include <linux/err.h> 13e7300d04SMaxime Bizon #include <linux/clk.h> 14c5af3c2dSJonas Gorski #include <linux/clkdev.h> 1504712f3fSMaxime Bizon #include <linux/delay.h> 16e7300d04SMaxime Bizon #include <bcm63xx_cpu.h> 17e7300d04SMaxime Bizon #include <bcm63xx_io.h> 18e7300d04SMaxime Bizon #include <bcm63xx_regs.h> 19ba00e2e5SJonas Gorski #include <bcm63xx_reset.h> 20042df4faSJonas Gorski 21042df4faSJonas Gorski struct clk { 22042df4faSJonas Gorski void (*set)(struct clk *, int); 23042df4faSJonas Gorski unsigned int rate; 24042df4faSJonas Gorski unsigned int usage; 25042df4faSJonas Gorski int id; 26042df4faSJonas Gorski }; 27e7300d04SMaxime Bizon 28e7300d04SMaxime Bizon static DEFINE_MUTEX(clocks_mutex); 29e7300d04SMaxime Bizon 30e7300d04SMaxime Bizon 31e7300d04SMaxime Bizon static void clk_enable_unlocked(struct clk *clk) 32e7300d04SMaxime Bizon { 33e7300d04SMaxime Bizon if (clk->set && (clk->usage++) == 0) 34e7300d04SMaxime Bizon clk->set(clk, 1); 35e7300d04SMaxime Bizon } 36e7300d04SMaxime Bizon 37e7300d04SMaxime Bizon static void clk_disable_unlocked(struct clk *clk) 38e7300d04SMaxime Bizon { 39e7300d04SMaxime Bizon if (clk->set && (--clk->usage) == 0) 40e7300d04SMaxime Bizon clk->set(clk, 0); 41e7300d04SMaxime Bizon } 42e7300d04SMaxime Bizon 43e7300d04SMaxime Bizon static void bcm_hwclock_set(u32 mask, int enable) 44e7300d04SMaxime Bizon { 45e7300d04SMaxime Bizon u32 reg; 46e7300d04SMaxime Bizon 47e7300d04SMaxime Bizon reg = bcm_perf_readl(PERF_CKCTL_REG); 48e7300d04SMaxime Bizon if (enable) 49e7300d04SMaxime Bizon reg |= mask; 50e7300d04SMaxime Bizon else 51e7300d04SMaxime Bizon reg &= ~mask; 52e7300d04SMaxime Bizon bcm_perf_writel(reg, PERF_CKCTL_REG); 53e7300d04SMaxime Bizon } 54e7300d04SMaxime Bizon 55e7300d04SMaxime Bizon /* 56e7300d04SMaxime Bizon * Ethernet MAC "misc" clock: dma clocks and main clock on 6348 57e7300d04SMaxime Bizon */ 58e7300d04SMaxime Bizon static void enet_misc_set(struct clk *clk, int enable) 59e7300d04SMaxime Bizon { 60e7300d04SMaxime Bizon u32 mask; 61e7300d04SMaxime Bizon 62e7300d04SMaxime Bizon if (BCMCPU_IS_6338()) 63e7300d04SMaxime Bizon mask = CKCTL_6338_ENET_EN; 64e7300d04SMaxime Bizon else if (BCMCPU_IS_6345()) 65e7300d04SMaxime Bizon mask = CKCTL_6345_ENET_EN; 66e7300d04SMaxime Bizon else if (BCMCPU_IS_6348()) 67e7300d04SMaxime Bizon mask = CKCTL_6348_ENET_EN; 68e7300d04SMaxime Bizon else 69e7300d04SMaxime Bizon /* BCMCPU_IS_6358 */ 70e7300d04SMaxime Bizon mask = CKCTL_6358_EMUSB_EN; 71e7300d04SMaxime Bizon bcm_hwclock_set(mask, enable); 72e7300d04SMaxime Bizon } 73e7300d04SMaxime Bizon 74e7300d04SMaxime Bizon static struct clk clk_enet_misc = { 75e7300d04SMaxime Bizon .set = enet_misc_set, 76e7300d04SMaxime Bizon }; 77e7300d04SMaxime Bizon 78e7300d04SMaxime Bizon /* 79*c024e8f6SBhaskar Chowdhury * Ethernet MAC clocks: only relevant on 6358, silently enable misc 80e7300d04SMaxime Bizon * clocks 81e7300d04SMaxime Bizon */ 82e7300d04SMaxime Bizon static void enetx_set(struct clk *clk, int enable) 83e7300d04SMaxime Bizon { 84e7300d04SMaxime Bizon if (enable) 85e7300d04SMaxime Bizon clk_enable_unlocked(&clk_enet_misc); 86e7300d04SMaxime Bizon else 87e7300d04SMaxime Bizon clk_disable_unlocked(&clk_enet_misc); 88e7300d04SMaxime Bizon 897b933421SFlorian Fainelli if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) { 90e7300d04SMaxime Bizon u32 mask; 91e7300d04SMaxime Bizon 92e7300d04SMaxime Bizon if (clk->id == 0) 93e7300d04SMaxime Bizon mask = CKCTL_6358_ENET0_EN; 94e7300d04SMaxime Bizon else 95e7300d04SMaxime Bizon mask = CKCTL_6358_ENET1_EN; 96e7300d04SMaxime Bizon bcm_hwclock_set(mask, enable); 97e7300d04SMaxime Bizon } 98e7300d04SMaxime Bizon } 99e7300d04SMaxime Bizon 100e7300d04SMaxime Bizon static struct clk clk_enet0 = { 101e7300d04SMaxime Bizon .id = 0, 102e7300d04SMaxime Bizon .set = enetx_set, 103e7300d04SMaxime Bizon }; 104e7300d04SMaxime Bizon 105e7300d04SMaxime Bizon static struct clk clk_enet1 = { 106e7300d04SMaxime Bizon .id = 1, 107e7300d04SMaxime Bizon .set = enetx_set, 108e7300d04SMaxime Bizon }; 109e7300d04SMaxime Bizon 110e7300d04SMaxime Bizon /* 111e7300d04SMaxime Bizon * Ethernet PHY clock 112e7300d04SMaxime Bizon */ 113e7300d04SMaxime Bizon static void ephy_set(struct clk *clk, int enable) 114e7300d04SMaxime Bizon { 1157b933421SFlorian Fainelli if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) 116e7300d04SMaxime Bizon bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable); 117e7300d04SMaxime Bizon } 118e7300d04SMaxime Bizon 119e7300d04SMaxime Bizon 120e7300d04SMaxime Bizon static struct clk clk_ephy = { 121e7300d04SMaxime Bizon .set = ephy_set, 122e7300d04SMaxime Bizon }; 123e7300d04SMaxime Bizon 124e7300d04SMaxime Bizon /* 125072916f5SJonas Gorski * Ethernet switch SAR clock 126072916f5SJonas Gorski */ 127072916f5SJonas Gorski static void swpkt_sar_set(struct clk *clk, int enable) 128072916f5SJonas Gorski { 129072916f5SJonas Gorski if (BCMCPU_IS_6368()) 130072916f5SJonas Gorski bcm_hwclock_set(CKCTL_6368_SWPKT_SAR_EN, enable); 131072916f5SJonas Gorski else 132072916f5SJonas Gorski return; 133072916f5SJonas Gorski } 134072916f5SJonas Gorski 135072916f5SJonas Gorski static struct clk clk_swpkt_sar = { 136072916f5SJonas Gorski .set = swpkt_sar_set, 137072916f5SJonas Gorski }; 138072916f5SJonas Gorski 139072916f5SJonas Gorski /* 140072916f5SJonas Gorski * Ethernet switch USB clock 141072916f5SJonas Gorski */ 142072916f5SJonas Gorski static void swpkt_usb_set(struct clk *clk, int enable) 143072916f5SJonas Gorski { 144072916f5SJonas Gorski if (BCMCPU_IS_6368()) 145072916f5SJonas Gorski bcm_hwclock_set(CKCTL_6368_SWPKT_USB_EN, enable); 146072916f5SJonas Gorski else 147072916f5SJonas Gorski return; 148072916f5SJonas Gorski } 149072916f5SJonas Gorski 150072916f5SJonas Gorski static struct clk clk_swpkt_usb = { 151072916f5SJonas Gorski .set = swpkt_usb_set, 152072916f5SJonas Gorski }; 153072916f5SJonas Gorski 154072916f5SJonas Gorski /* 15504712f3fSMaxime Bizon * Ethernet switch clock 15604712f3fSMaxime Bizon */ 15704712f3fSMaxime Bizon static void enetsw_set(struct clk *clk, int enable) 15804712f3fSMaxime Bizon { 159072916f5SJonas Gorski if (BCMCPU_IS_6328()) { 1601cd1c049SJonas Gorski bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable); 161072916f5SJonas Gorski } else if (BCMCPU_IS_6362()) { 1621cd1c049SJonas Gorski bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable); 163072916f5SJonas Gorski } else if (BCMCPU_IS_6368()) { 164072916f5SJonas Gorski if (enable) { 165072916f5SJonas Gorski clk_enable_unlocked(&clk_swpkt_sar); 166072916f5SJonas Gorski clk_enable_unlocked(&clk_swpkt_usb); 167072916f5SJonas Gorski } else { 168072916f5SJonas Gorski clk_disable_unlocked(&clk_swpkt_usb); 169072916f5SJonas Gorski clk_disable_unlocked(&clk_swpkt_sar); 170072916f5SJonas Gorski } 171072916f5SJonas Gorski bcm_hwclock_set(CKCTL_6368_ROBOSW_EN, enable); 172072916f5SJonas Gorski } else { 1731cd1c049SJonas Gorski return; 174072916f5SJonas Gorski } 1751cd1c049SJonas Gorski 17604712f3fSMaxime Bizon if (enable) { 17704712f3fSMaxime Bizon /* reset switch core afer clock change */ 178ba00e2e5SJonas Gorski bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1); 17904712f3fSMaxime Bizon msleep(10); 180ba00e2e5SJonas Gorski bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0); 18104712f3fSMaxime Bizon msleep(10); 18204712f3fSMaxime Bizon } 18304712f3fSMaxime Bizon } 18404712f3fSMaxime Bizon 18504712f3fSMaxime Bizon static struct clk clk_enetsw = { 18604712f3fSMaxime Bizon .set = enetsw_set, 18704712f3fSMaxime Bizon }; 18804712f3fSMaxime Bizon 18904712f3fSMaxime Bizon /* 190e7300d04SMaxime Bizon * PCM clock 191e7300d04SMaxime Bizon */ 192e7300d04SMaxime Bizon static void pcm_set(struct clk *clk, int enable) 193e7300d04SMaxime Bizon { 1947b933421SFlorian Fainelli if (BCMCPU_IS_3368()) 1957b933421SFlorian Fainelli bcm_hwclock_set(CKCTL_3368_PCM_EN, enable); 1967b933421SFlorian Fainelli if (BCMCPU_IS_6358()) 197e7300d04SMaxime Bizon bcm_hwclock_set(CKCTL_6358_PCM_EN, enable); 198e7300d04SMaxime Bizon } 199e7300d04SMaxime Bizon 200e7300d04SMaxime Bizon static struct clk clk_pcm = { 201e7300d04SMaxime Bizon .set = pcm_set, 202e7300d04SMaxime Bizon }; 203e7300d04SMaxime Bizon 204e7300d04SMaxime Bizon /* 205e7300d04SMaxime Bizon * USB host clock 206e7300d04SMaxime Bizon */ 207e7300d04SMaxime Bizon static void usbh_set(struct clk *clk, int enable) 208e7300d04SMaxime Bizon { 209dd89d60cSKevin Cernekee if (BCMCPU_IS_6328()) 210dd89d60cSKevin Cernekee bcm_hwclock_set(CKCTL_6328_USBH_EN, enable); 211dd89d60cSKevin Cernekee else if (BCMCPU_IS_6348()) 212e7300d04SMaxime Bizon bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); 2131cd1c049SJonas Gorski else if (BCMCPU_IS_6362()) 2141cd1c049SJonas Gorski bcm_hwclock_set(CKCTL_6362_USBH_EN, enable); 21504712f3fSMaxime Bizon else if (BCMCPU_IS_6368()) 216d9831a41SFlorian Fainelli bcm_hwclock_set(CKCTL_6368_USBH_EN, enable); 217e7300d04SMaxime Bizon } 218e7300d04SMaxime Bizon 219e7300d04SMaxime Bizon static struct clk clk_usbh = { 220e7300d04SMaxime Bizon .set = usbh_set, 221e7300d04SMaxime Bizon }; 222e7300d04SMaxime Bizon 223e7300d04SMaxime Bizon /* 224dd89d60cSKevin Cernekee * USB device clock 225dd89d60cSKevin Cernekee */ 226dd89d60cSKevin Cernekee static void usbd_set(struct clk *clk, int enable) 227dd89d60cSKevin Cernekee { 228dd89d60cSKevin Cernekee if (BCMCPU_IS_6328()) 229dd89d60cSKevin Cernekee bcm_hwclock_set(CKCTL_6328_USBD_EN, enable); 2301cd1c049SJonas Gorski else if (BCMCPU_IS_6362()) 2311cd1c049SJonas Gorski bcm_hwclock_set(CKCTL_6362_USBD_EN, enable); 232dd89d60cSKevin Cernekee else if (BCMCPU_IS_6368()) 233dd89d60cSKevin Cernekee bcm_hwclock_set(CKCTL_6368_USBD_EN, enable); 234dd89d60cSKevin Cernekee } 235dd89d60cSKevin Cernekee 236dd89d60cSKevin Cernekee static struct clk clk_usbd = { 237dd89d60cSKevin Cernekee .set = usbd_set, 238dd89d60cSKevin Cernekee }; 239dd89d60cSKevin Cernekee 240dd89d60cSKevin Cernekee /* 241e7300d04SMaxime Bizon * SPI clock 242e7300d04SMaxime Bizon */ 243e7300d04SMaxime Bizon static void spi_set(struct clk *clk, int enable) 244e7300d04SMaxime Bizon { 245e7300d04SMaxime Bizon u32 mask; 246e7300d04SMaxime Bizon 247e7300d04SMaxime Bizon if (BCMCPU_IS_6338()) 248e7300d04SMaxime Bizon mask = CKCTL_6338_SPI_EN; 249e7300d04SMaxime Bizon else if (BCMCPU_IS_6348()) 250e7300d04SMaxime Bizon mask = CKCTL_6348_SPI_EN; 2517b933421SFlorian Fainelli else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) 252e7300d04SMaxime Bizon mask = CKCTL_6358_SPI_EN; 25308a41d12SJonas Gorski else if (BCMCPU_IS_6362()) 25408a41d12SJonas Gorski mask = CKCTL_6362_SPI_EN; 25519372b24SFlorian Fainelli else 25619372b24SFlorian Fainelli /* BCMCPU_IS_6368 */ 25719372b24SFlorian Fainelli mask = CKCTL_6368_SPI_EN; 258e7300d04SMaxime Bizon bcm_hwclock_set(mask, enable); 259e7300d04SMaxime Bizon } 260e7300d04SMaxime Bizon 261e7300d04SMaxime Bizon static struct clk clk_spi = { 262e7300d04SMaxime Bizon .set = spi_set, 263e7300d04SMaxime Bizon }; 264e7300d04SMaxime Bizon 265e7300d04SMaxime Bizon /* 2660ebe8aaeSJonas Gorski * HSSPI clock 2670ebe8aaeSJonas Gorski */ 2680ebe8aaeSJonas Gorski static void hsspi_set(struct clk *clk, int enable) 2690ebe8aaeSJonas Gorski { 2700ebe8aaeSJonas Gorski u32 mask; 2710ebe8aaeSJonas Gorski 2720ebe8aaeSJonas Gorski if (BCMCPU_IS_6328()) 2730ebe8aaeSJonas Gorski mask = CKCTL_6328_HSSPI_EN; 2740ebe8aaeSJonas Gorski else if (BCMCPU_IS_6362()) 2750ebe8aaeSJonas Gorski mask = CKCTL_6362_HSSPI_EN; 2760ebe8aaeSJonas Gorski else 2770ebe8aaeSJonas Gorski return; 2780ebe8aaeSJonas Gorski 2790ebe8aaeSJonas Gorski bcm_hwclock_set(mask, enable); 2800ebe8aaeSJonas Gorski } 2810ebe8aaeSJonas Gorski 2820ebe8aaeSJonas Gorski static struct clk clk_hsspi = { 2830ebe8aaeSJonas Gorski .set = hsspi_set, 2840ebe8aaeSJonas Gorski }; 2850ebe8aaeSJonas Gorski 2865d691036SJonas Gorski /* 2875d691036SJonas Gorski * HSSPI PLL 2885d691036SJonas Gorski */ 2895d691036SJonas Gorski static struct clk clk_hsspi_pll; 2900ebe8aaeSJonas Gorski 2910ebe8aaeSJonas Gorski /* 29204712f3fSMaxime Bizon * XTM clock 29304712f3fSMaxime Bizon */ 29404712f3fSMaxime Bizon static void xtm_set(struct clk *clk, int enable) 29504712f3fSMaxime Bizon { 29604712f3fSMaxime Bizon if (!BCMCPU_IS_6368()) 29704712f3fSMaxime Bizon return; 29804712f3fSMaxime Bizon 299072916f5SJonas Gorski if (enable) 300072916f5SJonas Gorski clk_enable_unlocked(&clk_swpkt_sar); 301072916f5SJonas Gorski else 302072916f5SJonas Gorski clk_disable_unlocked(&clk_swpkt_sar); 303072916f5SJonas Gorski 304072916f5SJonas Gorski bcm_hwclock_set(CKCTL_6368_SAR_EN, enable); 30504712f3fSMaxime Bizon 30604712f3fSMaxime Bizon if (enable) { 30704712f3fSMaxime Bizon /* reset sar core afer clock change */ 308ba00e2e5SJonas Gorski bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1); 30904712f3fSMaxime Bizon mdelay(1); 310ba00e2e5SJonas Gorski bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0); 31104712f3fSMaxime Bizon mdelay(1); 31204712f3fSMaxime Bizon } 31304712f3fSMaxime Bizon } 31404712f3fSMaxime Bizon 31504712f3fSMaxime Bizon 31604712f3fSMaxime Bizon static struct clk clk_xtm = { 31704712f3fSMaxime Bizon .set = xtm_set, 31804712f3fSMaxime Bizon }; 31904712f3fSMaxime Bizon 32004712f3fSMaxime Bizon /* 3210b55561bSFlorian Fainelli * IPsec clock 3220b55561bSFlorian Fainelli */ 3230b55561bSFlorian Fainelli static void ipsec_set(struct clk *clk, int enable) 3240b55561bSFlorian Fainelli { 3251cd1c049SJonas Gorski if (BCMCPU_IS_6362()) 3261cd1c049SJonas Gorski bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable); 3271cd1c049SJonas Gorski else if (BCMCPU_IS_6368()) 3280b55561bSFlorian Fainelli bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable); 3290b55561bSFlorian Fainelli } 3300b55561bSFlorian Fainelli 3310b55561bSFlorian Fainelli static struct clk clk_ipsec = { 3320b55561bSFlorian Fainelli .set = ipsec_set, 3330b55561bSFlorian Fainelli }; 3340b55561bSFlorian Fainelli 3350b55561bSFlorian Fainelli /* 336f2d1035eSJonas Gorski * PCIe clock 337f2d1035eSJonas Gorski */ 338f2d1035eSJonas Gorski 339f2d1035eSJonas Gorski static void pcie_set(struct clk *clk, int enable) 340f2d1035eSJonas Gorski { 3411cd1c049SJonas Gorski if (BCMCPU_IS_6328()) 342f2d1035eSJonas Gorski bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable); 3431cd1c049SJonas Gorski else if (BCMCPU_IS_6362()) 3441cd1c049SJonas Gorski bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable); 345f2d1035eSJonas Gorski } 346f2d1035eSJonas Gorski 347f2d1035eSJonas Gorski static struct clk clk_pcie = { 348f2d1035eSJonas Gorski .set = pcie_set, 349f2d1035eSJonas Gorski }; 350f2d1035eSJonas Gorski 351f2d1035eSJonas Gorski /* 352e7300d04SMaxime Bizon * Internal peripheral clock 353e7300d04SMaxime Bizon */ 354e7300d04SMaxime Bizon static struct clk clk_periph = { 355e7300d04SMaxime Bizon .rate = (50 * 1000 * 1000), 356e7300d04SMaxime Bizon }; 357e7300d04SMaxime Bizon 358e7300d04SMaxime Bizon 359e7300d04SMaxime Bizon /* 360e7300d04SMaxime Bizon * Linux clock API implementation 361e7300d04SMaxime Bizon */ 362e7300d04SMaxime Bizon int clk_enable(struct clk *clk) 363e7300d04SMaxime Bizon { 364e7300d04SMaxime Bizon mutex_lock(&clocks_mutex); 365e7300d04SMaxime Bizon clk_enable_unlocked(clk); 366e7300d04SMaxime Bizon mutex_unlock(&clocks_mutex); 367e7300d04SMaxime Bizon return 0; 368e7300d04SMaxime Bizon } 369e7300d04SMaxime Bizon 370e7300d04SMaxime Bizon EXPORT_SYMBOL(clk_enable); 371e7300d04SMaxime Bizon 372e7300d04SMaxime Bizon void clk_disable(struct clk *clk) 373e7300d04SMaxime Bizon { 37400ca0250SMasahiro Yamada if (!clk) 37500ca0250SMasahiro Yamada return; 37600ca0250SMasahiro Yamada 377e7300d04SMaxime Bizon mutex_lock(&clocks_mutex); 378e7300d04SMaxime Bizon clk_disable_unlocked(clk); 379e7300d04SMaxime Bizon mutex_unlock(&clocks_mutex); 380e7300d04SMaxime Bizon } 381e7300d04SMaxime Bizon 382e7300d04SMaxime Bizon EXPORT_SYMBOL(clk_disable); 383e7300d04SMaxime Bizon 384e7300d04SMaxime Bizon unsigned long clk_get_rate(struct clk *clk) 385e7300d04SMaxime Bizon { 3861b495faeSJonas Gorski if (!clk) 3871b495faeSJonas Gorski return 0; 3881b495faeSJonas Gorski 389e7300d04SMaxime Bizon return clk->rate; 390e7300d04SMaxime Bizon } 391e7300d04SMaxime Bizon 392e7300d04SMaxime Bizon EXPORT_SYMBOL(clk_get_rate); 393e7300d04SMaxime Bizon 3947aa2d052SMarkos Chandras int clk_set_rate(struct clk *clk, unsigned long rate) 3957aa2d052SMarkos Chandras { 3967aa2d052SMarkos Chandras return 0; 3977aa2d052SMarkos Chandras } 3987aa2d052SMarkos Chandras EXPORT_SYMBOL_GPL(clk_set_rate); 3997aa2d052SMarkos Chandras 4007aa2d052SMarkos Chandras long clk_round_rate(struct clk *clk, unsigned long rate) 4017aa2d052SMarkos Chandras { 4027aa2d052SMarkos Chandras return 0; 4037aa2d052SMarkos Chandras } 4047aa2d052SMarkos Chandras EXPORT_SYMBOL_GPL(clk_round_rate); 4057aa2d052SMarkos Chandras 406c5af3c2dSJonas Gorski static struct clk_lookup bcm3368_clks[] = { 407c5af3c2dSJonas Gorski /* fixed rate clocks */ 408c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 409243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 410243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph), 411c5af3c2dSJonas Gorski /* gated clocks */ 412c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet0", &clk_enet0), 413c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet1", &clk_enet1), 414c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "ephy", &clk_ephy), 415c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 416c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 417c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "spi", &clk_spi), 418c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "pcm", &clk_pcm), 419ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0), 420ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1), 421c5af3c2dSJonas Gorski }; 422e7300d04SMaxime Bizon 423c5af3c2dSJonas Gorski static struct clk_lookup bcm6328_clks[] = { 424c5af3c2dSJonas Gorski /* fixed rate clocks */ 425c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 426243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 427243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph), 4285d691036SJonas Gorski CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll), 429c5af3c2dSJonas Gorski /* gated clocks */ 430c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enetsw", &clk_enetsw), 431c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 432c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 433c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "hsspi", &clk_hsspi), 434c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "pcie", &clk_pcie), 435c5af3c2dSJonas Gorski }; 436e7300d04SMaxime Bizon 437c5af3c2dSJonas Gorski static struct clk_lookup bcm6338_clks[] = { 438c5af3c2dSJonas Gorski /* fixed rate clocks */ 439c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 440243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 441c5af3c2dSJonas Gorski /* gated clocks */ 442c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet0", &clk_enet0), 443c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet1", &clk_enet1), 444c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "ephy", &clk_ephy), 445c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 446c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 447c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "spi", &clk_spi), 448ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc), 449c5af3c2dSJonas Gorski }; 450e7300d04SMaxime Bizon 451c5af3c2dSJonas Gorski static struct clk_lookup bcm6345_clks[] = { 452c5af3c2dSJonas Gorski /* fixed rate clocks */ 453c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 454243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 455c5af3c2dSJonas Gorski /* gated clocks */ 456c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet0", &clk_enet0), 457c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet1", &clk_enet1), 458c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "ephy", &clk_ephy), 459c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 460c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 461c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "spi", &clk_spi), 462ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc), 463c5af3c2dSJonas Gorski }; 464c5af3c2dSJonas Gorski 465c5af3c2dSJonas Gorski static struct clk_lookup bcm6348_clks[] = { 466c5af3c2dSJonas Gorski /* fixed rate clocks */ 467c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 468243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 469c5af3c2dSJonas Gorski /* gated clocks */ 470c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet0", &clk_enet0), 471c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet1", &clk_enet1), 472c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "ephy", &clk_ephy), 473c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 474c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 475c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "spi", &clk_spi), 476ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc), 477ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc), 478c5af3c2dSJonas Gorski }; 479c5af3c2dSJonas Gorski 480c5af3c2dSJonas Gorski static struct clk_lookup bcm6358_clks[] = { 481c5af3c2dSJonas Gorski /* fixed rate clocks */ 482c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 483243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 484243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph), 485c5af3c2dSJonas Gorski /* gated clocks */ 486c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet0", &clk_enet0), 487c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enet1", &clk_enet1), 488c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "ephy", &clk_ephy), 489c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 490c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 491c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "spi", &clk_spi), 492c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "pcm", &clk_pcm), 493072916f5SJonas Gorski CLKDEV_INIT(NULL, "swpkt_sar", &clk_swpkt_sar), 494072916f5SJonas Gorski CLKDEV_INIT(NULL, "swpkt_usb", &clk_swpkt_usb), 495ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0), 496ef423515SJonas Gorski CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1), 497c5af3c2dSJonas Gorski }; 498c5af3c2dSJonas Gorski 499c5af3c2dSJonas Gorski static struct clk_lookup bcm6362_clks[] = { 500c5af3c2dSJonas Gorski /* fixed rate clocks */ 501c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 502243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 503243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph), 5045d691036SJonas Gorski CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll), 505c5af3c2dSJonas Gorski /* gated clocks */ 506c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enetsw", &clk_enetsw), 507c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 508c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 509c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "spi", &clk_spi), 510c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "hsspi", &clk_hsspi), 511c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "pcie", &clk_pcie), 512c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "ipsec", &clk_ipsec), 513c5af3c2dSJonas Gorski }; 514c5af3c2dSJonas Gorski 515c5af3c2dSJonas Gorski static struct clk_lookup bcm6368_clks[] = { 516c5af3c2dSJonas Gorski /* fixed rate clocks */ 517c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "periph", &clk_periph), 518243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph), 519243fa279SJonas Gorski CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph), 520c5af3c2dSJonas Gorski /* gated clocks */ 521c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "enetsw", &clk_enetsw), 522c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbh", &clk_usbh), 523c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "usbd", &clk_usbd), 524c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "spi", &clk_spi), 525c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "xtm", &clk_xtm), 526c5af3c2dSJonas Gorski CLKDEV_INIT(NULL, "ipsec", &clk_ipsec), 527c5af3c2dSJonas Gorski }; 52826b8c07fSJonas Gorski 52926b8c07fSJonas Gorski #define HSSPI_PLL_HZ_6328 133333333 53026b8c07fSJonas Gorski #define HSSPI_PLL_HZ_6362 400000000 53126b8c07fSJonas Gorski 53226b8c07fSJonas Gorski static int __init bcm63xx_clk_init(void) 53326b8c07fSJonas Gorski { 53426b8c07fSJonas Gorski switch (bcm63xx_get_cpu_id()) { 535c5af3c2dSJonas Gorski case BCM3368_CPU_ID: 536c5af3c2dSJonas Gorski clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks)); 537c5af3c2dSJonas Gorski break; 53826b8c07fSJonas Gorski case BCM6328_CPU_ID: 5395d691036SJonas Gorski clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328; 540c5af3c2dSJonas Gorski clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks)); 541c5af3c2dSJonas Gorski break; 542c5af3c2dSJonas Gorski case BCM6338_CPU_ID: 543c5af3c2dSJonas Gorski clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks)); 544c5af3c2dSJonas Gorski break; 545c5af3c2dSJonas Gorski case BCM6345_CPU_ID: 546c5af3c2dSJonas Gorski clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks)); 547c5af3c2dSJonas Gorski break; 548c5af3c2dSJonas Gorski case BCM6348_CPU_ID: 549c5af3c2dSJonas Gorski clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks)); 550c5af3c2dSJonas Gorski break; 551c5af3c2dSJonas Gorski case BCM6358_CPU_ID: 552c5af3c2dSJonas Gorski clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks)); 55326b8c07fSJonas Gorski break; 55426b8c07fSJonas Gorski case BCM6362_CPU_ID: 5555d691036SJonas Gorski clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362; 556c5af3c2dSJonas Gorski clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks)); 557c5af3c2dSJonas Gorski break; 558c5af3c2dSJonas Gorski case BCM6368_CPU_ID: 559c5af3c2dSJonas Gorski clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks)); 56026b8c07fSJonas Gorski break; 56126b8c07fSJonas Gorski } 56226b8c07fSJonas Gorski 56326b8c07fSJonas Gorski return 0; 56426b8c07fSJonas Gorski } 56526b8c07fSJonas Gorski arch_initcall(bcm63xx_clk_init); 566