cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk.c (12956B)


      1/*
      2 * This file is subject to the terms and conditions of the GNU General Public
      3 * License.  See the file "COPYING" in the main directory of this archive
      4 * for more details.
      5 *
      6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
      7 */
      8
      9#include <linux/init.h>
     10#include <linux/export.h>
     11#include <linux/mutex.h>
     12#include <linux/err.h>
     13#include <linux/clk.h>
     14#include <linux/clkdev.h>
     15#include <linux/delay.h>
     16#include <bcm63xx_cpu.h>
     17#include <bcm63xx_io.h>
     18#include <bcm63xx_regs.h>
     19#include <bcm63xx_reset.h>
     20
     21struct clk {
     22	void		(*set)(struct clk *, int);
     23	unsigned int	rate;
     24	unsigned int	usage;
     25	int		id;
     26};
     27
     28static DEFINE_MUTEX(clocks_mutex);
     29
     30
     31static void clk_enable_unlocked(struct clk *clk)
     32{
     33	if (clk->set && (clk->usage++) == 0)
     34		clk->set(clk, 1);
     35}
     36
     37static void clk_disable_unlocked(struct clk *clk)
     38{
     39	if (clk->set && (--clk->usage) == 0)
     40		clk->set(clk, 0);
     41}
     42
     43static void bcm_hwclock_set(u32 mask, int enable)
     44{
     45	u32 reg;
     46
     47	reg = bcm_perf_readl(PERF_CKCTL_REG);
     48	if (enable)
     49		reg |= mask;
     50	else
     51		reg &= ~mask;
     52	bcm_perf_writel(reg, PERF_CKCTL_REG);
     53}
     54
     55/*
     56 * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
     57 */
     58static void enet_misc_set(struct clk *clk, int enable)
     59{
     60	u32 mask;
     61
     62	if (BCMCPU_IS_6338())
     63		mask = CKCTL_6338_ENET_EN;
     64	else if (BCMCPU_IS_6345())
     65		mask = CKCTL_6345_ENET_EN;
     66	else if (BCMCPU_IS_6348())
     67		mask = CKCTL_6348_ENET_EN;
     68	else
     69		/* BCMCPU_IS_6358 */
     70		mask = CKCTL_6358_EMUSB_EN;
     71	bcm_hwclock_set(mask, enable);
     72}
     73
     74static struct clk clk_enet_misc = {
     75	.set	= enet_misc_set,
     76};
     77
     78/*
     79 * Ethernet MAC clocks: only relevant on 6358, silently enable misc
     80 * clocks
     81 */
     82static void enetx_set(struct clk *clk, int enable)
     83{
     84	if (enable)
     85		clk_enable_unlocked(&clk_enet_misc);
     86	else
     87		clk_disable_unlocked(&clk_enet_misc);
     88
     89	if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
     90		u32 mask;
     91
     92		if (clk->id == 0)
     93			mask = CKCTL_6358_ENET0_EN;
     94		else
     95			mask = CKCTL_6358_ENET1_EN;
     96		bcm_hwclock_set(mask, enable);
     97	}
     98}
     99
    100static struct clk clk_enet0 = {
    101	.id	= 0,
    102	.set	= enetx_set,
    103};
    104
    105static struct clk clk_enet1 = {
    106	.id	= 1,
    107	.set	= enetx_set,
    108};
    109
    110/*
    111 * Ethernet PHY clock
    112 */
    113static void ephy_set(struct clk *clk, int enable)
    114{
    115	if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
    116		bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
    117}
    118
    119
    120static struct clk clk_ephy = {
    121	.set	= ephy_set,
    122};
    123
    124/*
    125 * Ethernet switch SAR clock
    126 */
    127static void swpkt_sar_set(struct clk *clk, int enable)
    128{
    129	if (BCMCPU_IS_6368())
    130		bcm_hwclock_set(CKCTL_6368_SWPKT_SAR_EN, enable);
    131	else
    132		return;
    133}
    134
    135static struct clk clk_swpkt_sar = {
    136	.set	= swpkt_sar_set,
    137};
    138
    139/*
    140 * Ethernet switch USB clock
    141 */
    142static void swpkt_usb_set(struct clk *clk, int enable)
    143{
    144	if (BCMCPU_IS_6368())
    145		bcm_hwclock_set(CKCTL_6368_SWPKT_USB_EN, enable);
    146	else
    147		return;
    148}
    149
    150static struct clk clk_swpkt_usb = {
    151	.set	= swpkt_usb_set,
    152};
    153
    154/*
    155 * Ethernet switch clock
    156 */
    157static void enetsw_set(struct clk *clk, int enable)
    158{
    159	if (BCMCPU_IS_6328()) {
    160		bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
    161	} else if (BCMCPU_IS_6362()) {
    162		bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
    163	} else if (BCMCPU_IS_6368()) {
    164		if (enable) {
    165			clk_enable_unlocked(&clk_swpkt_sar);
    166			clk_enable_unlocked(&clk_swpkt_usb);
    167		} else {
    168			clk_disable_unlocked(&clk_swpkt_usb);
    169			clk_disable_unlocked(&clk_swpkt_sar);
    170		}
    171		bcm_hwclock_set(CKCTL_6368_ROBOSW_EN, enable);
    172	} else {
    173		return;
    174	}
    175
    176	if (enable) {
    177		/* reset switch core afer clock change */
    178		bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
    179		msleep(10);
    180		bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
    181		msleep(10);
    182	}
    183}
    184
    185static struct clk clk_enetsw = {
    186	.set	= enetsw_set,
    187};
    188
    189/*
    190 * PCM clock
    191 */
    192static void pcm_set(struct clk *clk, int enable)
    193{
    194	if (BCMCPU_IS_3368())
    195		bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
    196	if (BCMCPU_IS_6358())
    197		bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
    198}
    199
    200static struct clk clk_pcm = {
    201	.set	= pcm_set,
    202};
    203
    204/*
    205 * USB host clock
    206 */
    207static void usbh_set(struct clk *clk, int enable)
    208{
    209	if (BCMCPU_IS_6328())
    210		bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
    211	else if (BCMCPU_IS_6348())
    212		bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
    213	else if (BCMCPU_IS_6362())
    214		bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
    215	else if (BCMCPU_IS_6368())
    216		bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
    217}
    218
    219static struct clk clk_usbh = {
    220	.set	= usbh_set,
    221};
    222
    223/*
    224 * USB device clock
    225 */
    226static void usbd_set(struct clk *clk, int enable)
    227{
    228	if (BCMCPU_IS_6328())
    229		bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
    230	else if (BCMCPU_IS_6362())
    231		bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
    232	else if (BCMCPU_IS_6368())
    233		bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
    234}
    235
    236static struct clk clk_usbd = {
    237	.set	= usbd_set,
    238};
    239
    240/*
    241 * SPI clock
    242 */
    243static void spi_set(struct clk *clk, int enable)
    244{
    245	u32 mask;
    246
    247	if (BCMCPU_IS_6338())
    248		mask = CKCTL_6338_SPI_EN;
    249	else if (BCMCPU_IS_6348())
    250		mask = CKCTL_6348_SPI_EN;
    251	else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
    252		mask = CKCTL_6358_SPI_EN;
    253	else if (BCMCPU_IS_6362())
    254		mask = CKCTL_6362_SPI_EN;
    255	else
    256		/* BCMCPU_IS_6368 */
    257		mask = CKCTL_6368_SPI_EN;
    258	bcm_hwclock_set(mask, enable);
    259}
    260
    261static struct clk clk_spi = {
    262	.set	= spi_set,
    263};
    264
    265/*
    266 * HSSPI clock
    267 */
    268static void hsspi_set(struct clk *clk, int enable)
    269{
    270	u32 mask;
    271
    272	if (BCMCPU_IS_6328())
    273		mask = CKCTL_6328_HSSPI_EN;
    274	else if (BCMCPU_IS_6362())
    275		mask = CKCTL_6362_HSSPI_EN;
    276	else
    277		return;
    278
    279	bcm_hwclock_set(mask, enable);
    280}
    281
    282static struct clk clk_hsspi = {
    283	.set	= hsspi_set,
    284};
    285
    286/*
    287 * HSSPI PLL
    288 */
    289static struct clk clk_hsspi_pll;
    290
    291/*
    292 * XTM clock
    293 */
    294static void xtm_set(struct clk *clk, int enable)
    295{
    296	if (!BCMCPU_IS_6368())
    297		return;
    298
    299	if (enable)
    300		clk_enable_unlocked(&clk_swpkt_sar);
    301	else
    302		clk_disable_unlocked(&clk_swpkt_sar);
    303
    304	bcm_hwclock_set(CKCTL_6368_SAR_EN, enable);
    305
    306	if (enable) {
    307		/* reset sar core afer clock change */
    308		bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
    309		mdelay(1);
    310		bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
    311		mdelay(1);
    312	}
    313}
    314
    315
    316static struct clk clk_xtm = {
    317	.set	= xtm_set,
    318};
    319
    320/*
    321 * IPsec clock
    322 */
    323static void ipsec_set(struct clk *clk, int enable)
    324{
    325	if (BCMCPU_IS_6362())
    326		bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
    327	else if (BCMCPU_IS_6368())
    328		bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
    329}
    330
    331static struct clk clk_ipsec = {
    332	.set	= ipsec_set,
    333};
    334
    335/*
    336 * PCIe clock
    337 */
    338
    339static void pcie_set(struct clk *clk, int enable)
    340{
    341	if (BCMCPU_IS_6328())
    342		bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
    343	else if (BCMCPU_IS_6362())
    344		bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
    345}
    346
    347static struct clk clk_pcie = {
    348	.set	= pcie_set,
    349};
    350
    351/*
    352 * Internal peripheral clock
    353 */
    354static struct clk clk_periph = {
    355	.rate	= (50 * 1000 * 1000),
    356};
    357
    358
    359/*
    360 * Linux clock API implementation
    361 */
    362int clk_enable(struct clk *clk)
    363{
    364	mutex_lock(&clocks_mutex);
    365	clk_enable_unlocked(clk);
    366	mutex_unlock(&clocks_mutex);
    367	return 0;
    368}
    369
    370EXPORT_SYMBOL(clk_enable);
    371
    372void clk_disable(struct clk *clk)
    373{
    374	if (!clk)
    375		return;
    376
    377	mutex_lock(&clocks_mutex);
    378	clk_disable_unlocked(clk);
    379	mutex_unlock(&clocks_mutex);
    380}
    381
    382EXPORT_SYMBOL(clk_disable);
    383
    384struct clk *clk_get_parent(struct clk *clk)
    385{
    386	return NULL;
    387}
    388EXPORT_SYMBOL(clk_get_parent);
    389
    390int clk_set_parent(struct clk *clk, struct clk *parent)
    391{
    392	return 0;
    393}
    394EXPORT_SYMBOL(clk_set_parent);
    395
    396unsigned long clk_get_rate(struct clk *clk)
    397{
    398	if (!clk)
    399		return 0;
    400
    401	return clk->rate;
    402}
    403
    404EXPORT_SYMBOL(clk_get_rate);
    405
    406int clk_set_rate(struct clk *clk, unsigned long rate)
    407{
    408	return 0;
    409}
    410EXPORT_SYMBOL_GPL(clk_set_rate);
    411
    412long clk_round_rate(struct clk *clk, unsigned long rate)
    413{
    414	return 0;
    415}
    416EXPORT_SYMBOL_GPL(clk_round_rate);
    417
    418static struct clk_lookup bcm3368_clks[] = {
    419	/* fixed rate clocks */
    420	CLKDEV_INIT(NULL, "periph", &clk_periph),
    421	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    422	CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
    423	/* gated clocks */
    424	CLKDEV_INIT(NULL, "enet0", &clk_enet0),
    425	CLKDEV_INIT(NULL, "enet1", &clk_enet1),
    426	CLKDEV_INIT(NULL, "ephy", &clk_ephy),
    427	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    428	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    429	CLKDEV_INIT(NULL, "spi", &clk_spi),
    430	CLKDEV_INIT(NULL, "pcm", &clk_pcm),
    431	CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
    432	CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
    433};
    434
    435static struct clk_lookup bcm6328_clks[] = {
    436	/* fixed rate clocks */
    437	CLKDEV_INIT(NULL, "periph", &clk_periph),
    438	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    439	CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
    440	CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
    441	/* gated clocks */
    442	CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
    443	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    444	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    445	CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
    446	CLKDEV_INIT(NULL, "pcie", &clk_pcie),
    447};
    448
    449static struct clk_lookup bcm6338_clks[] = {
    450	/* fixed rate clocks */
    451	CLKDEV_INIT(NULL, "periph", &clk_periph),
    452	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    453	/* gated clocks */
    454	CLKDEV_INIT(NULL, "enet0", &clk_enet0),
    455	CLKDEV_INIT(NULL, "enet1", &clk_enet1),
    456	CLKDEV_INIT(NULL, "ephy", &clk_ephy),
    457	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    458	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    459	CLKDEV_INIT(NULL, "spi", &clk_spi),
    460	CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
    461};
    462
    463static struct clk_lookup bcm6345_clks[] = {
    464	/* fixed rate clocks */
    465	CLKDEV_INIT(NULL, "periph", &clk_periph),
    466	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    467	/* gated clocks */
    468	CLKDEV_INIT(NULL, "enet0", &clk_enet0),
    469	CLKDEV_INIT(NULL, "enet1", &clk_enet1),
    470	CLKDEV_INIT(NULL, "ephy", &clk_ephy),
    471	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    472	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    473	CLKDEV_INIT(NULL, "spi", &clk_spi),
    474	CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
    475};
    476
    477static struct clk_lookup bcm6348_clks[] = {
    478	/* fixed rate clocks */
    479	CLKDEV_INIT(NULL, "periph", &clk_periph),
    480	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    481	/* gated clocks */
    482	CLKDEV_INIT(NULL, "enet0", &clk_enet0),
    483	CLKDEV_INIT(NULL, "enet1", &clk_enet1),
    484	CLKDEV_INIT(NULL, "ephy", &clk_ephy),
    485	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    486	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    487	CLKDEV_INIT(NULL, "spi", &clk_spi),
    488	CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
    489	CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc),
    490};
    491
    492static struct clk_lookup bcm6358_clks[] = {
    493	/* fixed rate clocks */
    494	CLKDEV_INIT(NULL, "periph", &clk_periph),
    495	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    496	CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
    497	/* gated clocks */
    498	CLKDEV_INIT(NULL, "enet0", &clk_enet0),
    499	CLKDEV_INIT(NULL, "enet1", &clk_enet1),
    500	CLKDEV_INIT(NULL, "ephy", &clk_ephy),
    501	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    502	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    503	CLKDEV_INIT(NULL, "spi", &clk_spi),
    504	CLKDEV_INIT(NULL, "pcm", &clk_pcm),
    505	CLKDEV_INIT(NULL, "swpkt_sar", &clk_swpkt_sar),
    506	CLKDEV_INIT(NULL, "swpkt_usb", &clk_swpkt_usb),
    507	CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
    508	CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
    509};
    510
    511static struct clk_lookup bcm6362_clks[] = {
    512	/* fixed rate clocks */
    513	CLKDEV_INIT(NULL, "periph", &clk_periph),
    514	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    515	CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
    516	CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
    517	/* gated clocks */
    518	CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
    519	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    520	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    521	CLKDEV_INIT(NULL, "spi", &clk_spi),
    522	CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
    523	CLKDEV_INIT(NULL, "pcie", &clk_pcie),
    524	CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
    525};
    526
    527static struct clk_lookup bcm6368_clks[] = {
    528	/* fixed rate clocks */
    529	CLKDEV_INIT(NULL, "periph", &clk_periph),
    530	CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
    531	CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
    532	/* gated clocks */
    533	CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
    534	CLKDEV_INIT(NULL, "usbh", &clk_usbh),
    535	CLKDEV_INIT(NULL, "usbd", &clk_usbd),
    536	CLKDEV_INIT(NULL, "spi", &clk_spi),
    537	CLKDEV_INIT(NULL, "xtm", &clk_xtm),
    538	CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
    539};
    540
    541#define HSSPI_PLL_HZ_6328	133333333
    542#define HSSPI_PLL_HZ_6362	400000000
    543
    544static int __init bcm63xx_clk_init(void)
    545{
    546	switch (bcm63xx_get_cpu_id()) {
    547	case BCM3368_CPU_ID:
    548		clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
    549		break;
    550	case BCM6328_CPU_ID:
    551		clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328;
    552		clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
    553		break;
    554	case BCM6338_CPU_ID:
    555		clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
    556		break;
    557	case BCM6345_CPU_ID:
    558		clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
    559		break;
    560	case BCM6348_CPU_ID:
    561		clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
    562		break;
    563	case BCM6358_CPU_ID:
    564		clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
    565		break;
    566	case BCM6362_CPU_ID:
    567		clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362;
    568		clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
    569		break;
    570	case BCM6368_CPU_ID:
    571		clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
    572		break;
    573	}
    574
    575	return 0;
    576}
    577arch_initcall(bcm63xx_clk_init);