Merge branch 'clk-next' of git://git.linaro.org/people/mturquette/linux into next/clock

* 'clk-next' of git://git.linaro.org/people/mturquette/linux:
  clk: Fix CLK_SET_RATE_GATE flag validation in clk_set_rate().
  clk: Provide dummy clk_unregister()
  ARM: Kirkwood: Replace clock gating
  ARM: Orion: Audio: Add clk/clkdev support
  ARM: Orion: PCIE: Add support for clk
  ARM: Orion: XOR: Add support for clk
  ARM: Orion: CESA: Add support for clk
  ARM: Orion: SDIO: Add support for clk.
  ARM: Orion: NAND: Add support for clk, if there is one.
  ARM: Orion: EHCI: Add support for enabling clocks
  ARM: Orion: SATA: Add per channel clk/clkdev support.
  ARM: Orion: UART: Get the clock rate via clk_get_rate().
  ARM: Orion: WDT: Add clk/clkdev support
  ARM: Orion: Eth: Add clk/clkdev support.
  ARM: Orion: SPI: Add clk/clkdev support.
  ARM: Orion: Add clocks using the generic clk infrastructure.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2012-05-16 16:35:25 +02:00
commit 3c0dec5f58
36 changed files with 585 additions and 264 deletions

View File

@ -1142,6 +1142,7 @@ config PLAT_ORION
bool
select CLKSRC_MMIO
select GENERIC_IRQ_CHIP
select COMMON_CLK
config PLAT_PXA
bool

View File

@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/ata_platform.h>
#include <linux/gpio.h>
#include <asm/page.h>
@ -67,6 +67,19 @@ void __init dove_map_io(void)
iotable_init(dove_io_desc, ARRAY_SIZE(dove_io_desc));
}
/*****************************************************************************
* CLK tree
****************************************************************************/
static struct clk *tclk;
static void __init clk_init(void)
{
tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
get_tclk());
orion_clkdev_init(tclk);
}
/*****************************************************************************
* EHCI0
****************************************************************************/
@ -89,8 +102,7 @@ void __init dove_ehci1_init(void)
void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data,
DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM,
0, get_tclk());
DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM, 0);
}
/*****************************************************************************
@ -116,7 +128,7 @@ void __init dove_sata_init(struct mv_sata_platform_data *sata_data)
void __init dove_uart0_init(void)
{
orion_uart0_init(DOVE_UART0_VIRT_BASE, DOVE_UART0_PHYS_BASE,
IRQ_DOVE_UART_0, get_tclk());
IRQ_DOVE_UART_0, tclk);
}
/*****************************************************************************
@ -125,7 +137,7 @@ void __init dove_uart0_init(void)
void __init dove_uart1_init(void)
{
orion_uart1_init(DOVE_UART1_VIRT_BASE, DOVE_UART1_PHYS_BASE,
IRQ_DOVE_UART_1, get_tclk());
IRQ_DOVE_UART_1, tclk);
}
/*****************************************************************************
@ -134,7 +146,7 @@ void __init dove_uart1_init(void)
void __init dove_uart2_init(void)
{
orion_uart2_init(DOVE_UART2_VIRT_BASE, DOVE_UART2_PHYS_BASE,
IRQ_DOVE_UART_2, get_tclk());
IRQ_DOVE_UART_2, tclk);
}
/*****************************************************************************
@ -143,7 +155,7 @@ void __init dove_uart2_init(void)
void __init dove_uart3_init(void)
{
orion_uart3_init(DOVE_UART3_VIRT_BASE, DOVE_UART3_PHYS_BASE,
IRQ_DOVE_UART_3, get_tclk());
IRQ_DOVE_UART_3, tclk);
}
/*****************************************************************************
@ -151,12 +163,12 @@ void __init dove_uart3_init(void)
****************************************************************************/
void __init dove_spi0_init(void)
{
orion_spi_init(DOVE_SPI0_PHYS_BASE, get_tclk());
orion_spi_init(DOVE_SPI0_PHYS_BASE);
}
void __init dove_spi1_init(void)
{
orion_spi_1_init(DOVE_SPI1_PHYS_BASE, get_tclk());
orion_spi_1_init(DOVE_SPI1_PHYS_BASE);
}
/*****************************************************************************
@ -272,18 +284,17 @@ void __init dove_sdio1_init(void)
void __init dove_init(void)
{
int tclk;
tclk = get_tclk();
printk(KERN_INFO "Dove 88AP510 SoC, ");
printk(KERN_INFO "TCLK = %dMHz\n", (tclk + 499999) / 1000000);
printk(KERN_INFO "TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
#ifdef CONFIG_CACHE_TAUROS2
tauros2_init();
#endif
dove_setup_cpu_mbus();
/* Setup root of clk tree */
clk_init();
/* internal devices that every board has */
dove_rtc_init();
dove_xor0_init();

View File

@ -20,7 +20,6 @@
#include <linux/i2c.h>
#include <linux/pci.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/spi/flash.h>
#include <linux/gpio.h>
#include <asm/mach-types.h>

View File

@ -27,7 +27,6 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>

View File

@ -42,6 +42,9 @@ static void __init kirkwood_dt_init(void)
kirkwood_l2_init();
#endif
/* Setup root of clk tree */
kirkwood_clk_init();
/* internal devices that every board has */
kirkwood_wdt_init();
kirkwood_xor0_init();

View File

@ -15,6 +15,8 @@
#include <linux/ata_platform.h>
#include <linux/mtd/nand.h>
#include <linux/dma-mapping.h>
#include <linux/clk-provider.h>
#include <linux/spinlock.h>
#include <net/dsa.h>
#include <asm/page.h>
#include <asm/timex.h>
@ -31,6 +33,7 @@
#include <plat/common.h>
#include <plat/time.h>
#include <plat/addr-map.h>
#include <plat/mv_xor.h>
#include "common.h"
/*****************************************************************************
@ -60,20 +63,188 @@ void __init kirkwood_map_io(void)
iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
}
/*
* Default clock control bits. Any bit _not_ set in this variable
* will be cleared from the hardware after platform devices have been
* registered. Some reserved bits must be set to 1.
*/
unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED;
/*****************************************************************************
* CLK tree
****************************************************************************/
static void disable_sata0(void)
{
/* Disable PLL and IVREF */
writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
}
static void disable_sata1(void)
{
/* Disable PLL and IVREF */
writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
}
static void disable_pcie0(void)
{
writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
while (1)
if (readl(PCIE_STATUS) & 0x1)
break;
writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
}
static void disable_pcie1(void)
{
u32 dev, rev;
kirkwood_pcie_id(&dev, &rev);
if (dev == MV88F6282_DEV_ID) {
writel(readl(PCIE1_LINK_CTRL) | 0x10, PCIE1_LINK_CTRL);
while (1)
if (readl(PCIE1_STATUS) & 0x1)
break;
writel(readl(PCIE1_LINK_CTRL) & ~0x10, PCIE1_LINK_CTRL);
}
}
/* An extended version of the gated clk. This calls fn() before
* disabling the clock. We use this to turn off PHYs etc. */
struct clk_gate_fn {
struct clk_gate gate;
void (*fn)(void);
};
#define to_clk_gate_fn(_gate) container_of(_gate, struct clk_gate_fn, gate)
#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
static void clk_gate_fn_disable(struct clk_hw *hw)
{
struct clk_gate *gate = to_clk_gate(hw);
struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
if (gate_fn->fn)
gate_fn->fn();
clk_gate_ops.disable(hw);
}
static struct clk_ops clk_gate_fn_ops;
static struct clk __init *clk_register_gate_fn(struct device *dev,
const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock,
void (*fn)(void))
{
struct clk_gate_fn *gate_fn;
struct clk *clk;
struct clk_init_data init;
gate_fn = kzalloc(sizeof(struct clk_gate_fn), GFP_KERNEL);
if (!gate_fn) {
pr_err("%s: could not allocate gated clk\n", __func__);
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clk_gate_fn_ops;
init.flags = flags;
init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0);
/* struct clk_gate assignments */
gate_fn->gate.reg = reg;
gate_fn->gate.bit_idx = bit_idx;
gate_fn->gate.flags = clk_gate_flags;
gate_fn->gate.lock = lock;
gate_fn->gate.hw.init = &init;
/* ops is the gate ops, but with our disable function */
if (clk_gate_fn_ops.disable != clk_gate_fn_disable) {
clk_gate_fn_ops = clk_gate_ops;
clk_gate_fn_ops.disable = clk_gate_fn_disable;
}
clk = clk_register(dev, &gate_fn->gate.hw);
if (IS_ERR(clk))
kfree(gate_fn);
return clk;
}
static DEFINE_SPINLOCK(gating_lock);
static struct clk *tclk;
static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
{
return clk_register_gate(NULL, name, "tclk", 0,
(void __iomem *)CLOCK_GATING_CTRL,
bit_idx, 0, &gating_lock);
}
static struct clk __init *kirkwood_register_gate_fn(const char *name,
u8 bit_idx,
void (*fn)(void))
{
return clk_register_gate_fn(NULL, name, "tclk", 0,
(void __iomem *)CLOCK_GATING_CTRL,
bit_idx, 0, &gating_lock, fn);
}
void __init kirkwood_clk_init(void)
{
struct clk *runit, *ge0, *ge1, *sata0, *sata1, *usb0, *sdio;
struct clk *crypto, *xor0, *xor1, *pex0, *pex1, *audio;
tclk = clk_register_fixed_rate(NULL, "tclk", NULL,
CLK_IS_ROOT, kirkwood_tclk);
runit = kirkwood_register_gate("runit", CGC_BIT_RUNIT);
ge0 = kirkwood_register_gate("ge0", CGC_BIT_GE0);
ge1 = kirkwood_register_gate("ge1", CGC_BIT_GE1);
sata0 = kirkwood_register_gate_fn("sata0", CGC_BIT_SATA0,
disable_sata0);
sata1 = kirkwood_register_gate_fn("sata1", CGC_BIT_SATA1,
disable_sata1);
usb0 = kirkwood_register_gate("usb0", CGC_BIT_USB0);
sdio = kirkwood_register_gate("sdio", CGC_BIT_SDIO);
crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO);
xor0 = kirkwood_register_gate("xor0", CGC_BIT_XOR0);
xor1 = kirkwood_register_gate("xor1", CGC_BIT_XOR1);
pex0 = kirkwood_register_gate_fn("pex0", CGC_BIT_PEX0,
disable_pcie0);
pex1 = kirkwood_register_gate_fn("pex1", CGC_BIT_PEX1,
disable_pcie1);
audio = kirkwood_register_gate("audio", CGC_BIT_AUDIO);
kirkwood_register_gate("tdm", CGC_BIT_TDM);
kirkwood_register_gate("tsu", CGC_BIT_TSU);
/* clkdev entries, mapping clks to devices */
orion_clkdev_add(NULL, "orion_spi.0", runit);
orion_clkdev_add(NULL, "orion_spi.1", runit);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", ge0);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", ge1);
orion_clkdev_add(NULL, "orion_wdt", tclk);
orion_clkdev_add("0", "sata_mv.0", sata0);
orion_clkdev_add("1", "sata_mv.0", sata1);
orion_clkdev_add(NULL, "orion-ehci.0", usb0);
orion_clkdev_add(NULL, "orion_nand", runit);
orion_clkdev_add(NULL, "mvsdio", sdio);
orion_clkdev_add(NULL, "mv_crypto", crypto);
orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".0", xor0);
orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".1", xor1);
orion_clkdev_add("0", "pcie", pex0);
orion_clkdev_add("1", "pcie", pex1);
orion_clkdev_add(NULL, "kirkwood-i2s", audio);
}
/*****************************************************************************
* EHCI0
****************************************************************************/
void __init kirkwood_ehci_init(void)
{
kirkwood_clk_ctrl |= CGC_USB0;
orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB, EHCI_PHY_NA);
}
@ -83,11 +254,9 @@ void __init kirkwood_ehci_init(void)
****************************************************************************/
void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
kirkwood_clk_ctrl |= CGC_GE0;
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
IRQ_KIRKWOOD_GE00_ERR, kirkwood_tclk);
IRQ_KIRKWOOD_GE00_ERR);
}
@ -96,12 +265,9 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
****************************************************************************/
void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
{
kirkwood_clk_ctrl |= CGC_GE1;
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
IRQ_KIRKWOOD_GE01_ERR, kirkwood_tclk);
IRQ_KIRKWOOD_GE01_ERR);
}
@ -143,7 +309,6 @@ static struct platform_device kirkwood_nand_flash = {
void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
int chip_delay)
{
kirkwood_clk_ctrl |= CGC_RUNIT;
kirkwood_nand_data.parts = parts;
kirkwood_nand_data.nr_parts = nr_parts;
kirkwood_nand_data.chip_delay = chip_delay;
@ -153,7 +318,6 @@ void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
void __init kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
int (*dev_ready)(struct mtd_info *))
{
kirkwood_clk_ctrl |= CGC_RUNIT;
kirkwood_nand_data.parts = parts;
kirkwood_nand_data.nr_parts = nr_parts;
kirkwood_nand_data.dev_ready = dev_ready;
@ -174,10 +338,6 @@ static void __init kirkwood_rtc_init(void)
****************************************************************************/
void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data)
{
kirkwood_clk_ctrl |= CGC_SATA0;
if (sata_data->n_ports > 1)
kirkwood_clk_ctrl |= CGC_SATA1;
orion_sata_init(sata_data, SATA_PHYS_BASE, IRQ_KIRKWOOD_SATA);
}
@ -220,7 +380,6 @@ void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
mvsdio_data->clock = 100000000;
else
mvsdio_data->clock = 200000000;
kirkwood_clk_ctrl |= CGC_SDIO;
kirkwood_sdio.dev.platform_data = mvsdio_data;
platform_device_register(&kirkwood_sdio);
}
@ -231,8 +390,7 @@ void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
****************************************************************************/
void __init kirkwood_spi_init()
{
kirkwood_clk_ctrl |= CGC_RUNIT;
orion_spi_init(SPI_PHYS_BASE, kirkwood_tclk);
orion_spi_init(SPI_PHYS_BASE);
}
@ -252,7 +410,7 @@ void __init kirkwood_i2c_init(void)
void __init kirkwood_uart0_init(void)
{
orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
IRQ_KIRKWOOD_UART_0, kirkwood_tclk);
IRQ_KIRKWOOD_UART_0, tclk);
}
@ -262,7 +420,7 @@ void __init kirkwood_uart0_init(void)
void __init kirkwood_uart1_init(void)
{
orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
IRQ_KIRKWOOD_UART_1, kirkwood_tclk);
IRQ_KIRKWOOD_UART_1, tclk);
}
/*****************************************************************************
@ -270,7 +428,6 @@ void __init kirkwood_uart1_init(void)
****************************************************************************/
void __init kirkwood_crypto_init(void)
{
kirkwood_clk_ctrl |= CGC_CRYPTO;
orion_crypto_init(CRYPTO_PHYS_BASE, KIRKWOOD_SRAM_PHYS_BASE,
KIRKWOOD_SRAM_SIZE, IRQ_KIRKWOOD_CRYPTO);
}
@ -281,8 +438,6 @@ void __init kirkwood_crypto_init(void)
****************************************************************************/
void __init kirkwood_xor0_init(void)
{
kirkwood_clk_ctrl |= CGC_XOR0;
orion_xor0_init(XOR0_PHYS_BASE, XOR0_HIGH_PHYS_BASE,
IRQ_KIRKWOOD_XOR_00, IRQ_KIRKWOOD_XOR_01);
}
@ -293,8 +448,6 @@ void __init kirkwood_xor0_init(void)
****************************************************************************/
void __init kirkwood_xor1_init(void)
{
kirkwood_clk_ctrl |= CGC_XOR1;
orion_xor1_init(XOR1_PHYS_BASE, XOR1_HIGH_PHYS_BASE,
IRQ_KIRKWOOD_XOR_10, IRQ_KIRKWOOD_XOR_11);
}
@ -305,7 +458,7 @@ void __init kirkwood_xor1_init(void)
****************************************************************************/
void __init kirkwood_wdt_init(void)
{
orion_wdt_init(kirkwood_tclk);
orion_wdt_init();
}
@ -381,7 +534,6 @@ static struct platform_device kirkwood_pcm_device = {
void __init kirkwood_audio_init(void)
{
kirkwood_clk_ctrl |= CGC_AUDIO;
platform_device_register(&kirkwood_i2s_device);
platform_device_register(&kirkwood_pcm_device);
}
@ -465,6 +617,9 @@ void __init kirkwood_init(void)
kirkwood_l2_init();
#endif
/* Setup root of clk tree */
kirkwood_clk_init();
/* internal devices that every board has */
kirkwood_rtc_init();
kirkwood_wdt_init();
@ -477,61 +632,6 @@ void __init kirkwood_init(void)
#endif
}
static int __init kirkwood_clock_gate(void)
{
unsigned int curr = readl(CLOCK_GATING_CTRL);
u32 dev, rev;
kirkwood_pcie_id(&dev, &rev);
printk(KERN_DEBUG "Gating clock of unused units\n");
printk(KERN_DEBUG "before: 0x%08x\n", curr);
/* Make sure those units are accessible */
writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0 | CGC_PEX1, CLOCK_GATING_CTRL);
/* For SATA: first shutdown the phy */
if (!(kirkwood_clk_ctrl & CGC_SATA0)) {
/* Disable PLL and IVREF */
writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
}
if (!(kirkwood_clk_ctrl & CGC_SATA1)) {
/* Disable PLL and IVREF */
writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
/* Disable PHY */
writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
}
/* For PCIe: first shutdown the phy */
if (!(kirkwood_clk_ctrl & CGC_PEX0)) {
writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
while (1)
if (readl(PCIE_STATUS) & 0x1)
break;
writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
}
/* For PCIe 1: first shutdown the phy */
if (dev == MV88F6282_DEV_ID) {
if (!(kirkwood_clk_ctrl & CGC_PEX1)) {
writel(readl(PCIE1_LINK_CTRL) | 0x10, PCIE1_LINK_CTRL);
while (1)
if (readl(PCIE1_STATUS) & 0x1)
break;
writel(readl(PCIE1_LINK_CTRL) & ~0x10, PCIE1_LINK_CTRL);
}
} else /* keep this bit set for devices that don't have PCIe1 */
kirkwood_clk_ctrl |= CGC_PEX1;
/* Now gate clock the required units */
writel(kirkwood_clk_ctrl, CLOCK_GATING_CTRL);
printk(KERN_DEBUG " after: 0x%08x\n", readl(CLOCK_GATING_CTRL));
return 0;
}
late_initcall(kirkwood_clock_gate);
void kirkwood_restart(char mode, const char *cmd)
{
/*

View File

@ -50,6 +50,7 @@ void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev_ready)(struct mtd_info *));
void kirkwood_audio_init(void);
void kirkwood_restart(char, const char *);
void kirkwood_clk_init(void);
/* board init functions for boards not fully converted to fdt */
#ifdef CONFIG_MACH_DREAMPLUG_DT

View File

@ -43,6 +43,22 @@
#define L2_WRITETHROUGH 0x00000010
#define CLOCK_GATING_CTRL (BRIDGE_VIRT_BASE | 0x11c)
#define CGC_BIT_GE0 (0)
#define CGC_BIT_PEX0 (2)
#define CGC_BIT_USB0 (3)
#define CGC_BIT_SDIO (4)
#define CGC_BIT_TSU (5)
#define CGC_BIT_DUNIT (6)
#define CGC_BIT_RUNIT (7)
#define CGC_BIT_XOR0 (8)
#define CGC_BIT_AUDIO (9)
#define CGC_BIT_SATA0 (14)
#define CGC_BIT_SATA1 (15)
#define CGC_BIT_XOR1 (16)
#define CGC_BIT_CRYPTO (17)
#define CGC_BIT_PEX1 (18)
#define CGC_BIT_GE1 (19)
#define CGC_BIT_TDM (20)
#define CGC_GE0 (1 << 0)
#define CGC_PEX0 (1 << 2)
#define CGC_USB0 (1 << 3)

View File

@ -23,7 +23,6 @@
#include <linux/gpio_keys.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <net/dsa.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>

View File

@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <video/vga.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
@ -19,6 +20,23 @@
#include <plat/addr-map.h>
#include "common.h"
static void kirkwood_enable_pcie_clk(const char *port)
{
struct clk *clk;
clk = clk_get_sys("pcie", port);
if (IS_ERR(clk)) {
printk(KERN_ERR "PCIE clock %s missing\n", port);
return;
}
clk_prepare_enable(clk);
clk_put(clk);
}
/* This function is called very early in the boot when probing the
hardware to determine what we actually are, and what rate tclk is
ticking at. Hence calling kirkwood_enable_pcie_clk() is not
possible since the clk tree has not been created yet. */
void kirkwood_enable_pcie(void)
{
u32 curr = readl(CLOCK_GATING_CTRL);
@ -26,7 +44,7 @@ void kirkwood_enable_pcie(void)
writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
}
void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
void kirkwood_pcie_id(u32 *dev, u32 *rev)
{
kirkwood_enable_pcie();
*dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
@ -163,7 +181,6 @@ static void __init pcie1_ioresources_init(struct pcie_port *pp)
static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
{
extern unsigned int kirkwood_clk_ctrl;
struct pcie_port *pp;
int index;
@ -182,11 +199,11 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
switch (index) {
case 0:
kirkwood_clk_ctrl |= CGC_PEX0;
kirkwood_enable_pcie_clk("0");
pcie0_ioresources_init(pp);
break;
case 1:
kirkwood_clk_ctrl |= CGC_PEX1;
kirkwood_enable_pcie_clk("1");
pcie1_ioresources_init(pp);
break;
default:

View File

@ -16,7 +16,6 @@
#include <linux/gpio.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>

View File

@ -16,7 +16,6 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/i2c.h>
#include <linux/mv643xx_eth.h>
#include <linux/ata_platform.h>

View File

@ -4,7 +4,6 @@
#include <linux/mtd/physmap.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/serial_reg.h>
#include <mach/kirkwood.h>
#include "common.h"

View File

@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/ata_platform.h>
#include <linux/clk-provider.h>
#include <linux/ethtool.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
@ -103,24 +104,24 @@ static void get_pclk_l2clk(int hclk, int core_index, int *pclk, int *l2clk)
static int get_tclk(void)
{
int tclk;
int tclk_freq;
/*
* TCLK tick rate is configured by DEV_A[2:0] strap pins.
*/
switch ((readl(SAMPLE_AT_RESET_HIGH) >> 6) & 7) {
case 1:
tclk = 166666667;
tclk_freq = 166666667;
break;
case 3:
tclk = 200000000;
tclk_freq = 200000000;
break;
default:
panic("unknown TCLK PLL setting: %.8x\n",
readl(SAMPLE_AT_RESET_HIGH));
}
return tclk;
return tclk_freq;
}
@ -165,6 +166,19 @@ void __init mv78xx0_map_io(void)
}
/*****************************************************************************
* CLK tree
****************************************************************************/
static struct clk *tclk;
static void __init clk_init(void)
{
tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
get_tclk());
orion_clkdev_init(tclk);
}
/*****************************************************************************
* EHCI
****************************************************************************/
@ -199,7 +213,7 @@ void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data,
GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
IRQ_MV78XX0_GE_ERR, get_tclk());
IRQ_MV78XX0_GE_ERR);
}
@ -210,7 +224,7 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge01_init(eth_data,
GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
NO_IRQ, get_tclk());
NO_IRQ);
}
@ -234,7 +248,7 @@ void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
orion_ge10_init(eth_data,
GE10_PHYS_BASE, IRQ_MV78XX0_GE10_SUM,
NO_IRQ, get_tclk());
NO_IRQ);
}
@ -258,7 +272,7 @@ void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
orion_ge11_init(eth_data,
GE11_PHYS_BASE, IRQ_MV78XX0_GE11_SUM,
NO_IRQ, get_tclk());
NO_IRQ);
}
/*****************************************************************************
@ -285,7 +299,7 @@ void __init mv78xx0_sata_init(struct mv_sata_platform_data *sata_data)
void __init mv78xx0_uart0_init(void)
{
orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
IRQ_MV78XX0_UART_0, get_tclk());
IRQ_MV78XX0_UART_0, tclk);
}
@ -295,7 +309,7 @@ void __init mv78xx0_uart0_init(void)
void __init mv78xx0_uart1_init(void)
{
orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
IRQ_MV78XX0_UART_1, get_tclk());
IRQ_MV78XX0_UART_1, tclk);
}
@ -305,7 +319,7 @@ void __init mv78xx0_uart1_init(void)
void __init mv78xx0_uart2_init(void)
{
orion_uart2_init(UART2_VIRT_BASE, UART2_PHYS_BASE,
IRQ_MV78XX0_UART_2, get_tclk());
IRQ_MV78XX0_UART_2, tclk);
}
/*****************************************************************************
@ -314,7 +328,7 @@ void __init mv78xx0_uart2_init(void)
void __init mv78xx0_uart3_init(void)
{
orion_uart3_init(UART3_VIRT_BASE, UART3_PHYS_BASE,
IRQ_MV78XX0_UART_3, get_tclk());
IRQ_MV78XX0_UART_3, tclk);
}
/*****************************************************************************
@ -378,25 +392,26 @@ void __init mv78xx0_init(void)
int hclk;
int pclk;
int l2clk;
int tclk;
core_index = mv78xx0_core_index();
hclk = get_hclk();
get_pclk_l2clk(hclk, core_index, &pclk, &l2clk);
tclk = get_tclk();
printk(KERN_INFO "%s ", mv78xx0_id());
printk("core #%d, ", core_index);
printk("PCLK = %dMHz, ", (pclk + 499999) / 1000000);
printk("L2 = %dMHz, ", (l2clk + 499999) / 1000000);
printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000);
printk("TCLK = %dMHz\n", (tclk + 499999) / 1000000);
printk("TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
mv78xx0_setup_cpu_mbus();
#ifdef CONFIG_CACHE_FEROCEON_L2
feroceon_l2_init(is_l2_writethrough());
#endif
/* Setup root of clk tree */
clk_init();
}
void mv78xx0_restart(char mode, const char *cmd)

View File

@ -18,6 +18,7 @@
#include <linux/mv643xx_i2c.h>
#include <linux/ata_platform.h>
#include <linux/delay.h>
#include <linux/clk-provider.h>
#include <net/dsa.h>
#include <asm/page.h>
#include <asm/setup.h>
@ -69,6 +70,19 @@ void __init orion5x_map_io(void)
}
/*****************************************************************************
* CLK tree
****************************************************************************/
static struct clk *tclk;
static void __init clk_init(void)
{
tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
orion5x_tclk);
orion_clkdev_init(tclk);
}
/*****************************************************************************
* EHCI0
****************************************************************************/
@ -95,7 +109,7 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
{
orion_ge00_init(eth_data,
ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
IRQ_ORION5X_ETH_ERR, orion5x_tclk);
IRQ_ORION5X_ETH_ERR);
}
@ -132,7 +146,7 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
****************************************************************************/
void __init orion5x_spi_init()
{
orion_spi_init(SPI_PHYS_BASE, orion5x_tclk);
orion_spi_init(SPI_PHYS_BASE);
}
@ -142,7 +156,7 @@ void __init orion5x_spi_init()
void __init orion5x_uart0_init(void)
{
orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
IRQ_ORION5X_UART0, orion5x_tclk);
IRQ_ORION5X_UART0, tclk);
}
/*****************************************************************************
@ -151,7 +165,7 @@ void __init orion5x_uart0_init(void)
void __init orion5x_uart1_init(void)
{
orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
IRQ_ORION5X_UART1, orion5x_tclk);
IRQ_ORION5X_UART1, tclk);
}
/*****************************************************************************
@ -179,7 +193,7 @@ static void __init orion5x_crypto_init(void)
****************************************************************************/
void __init orion5x_wdt_init(void)
{
orion_wdt_init(orion5x_tclk);
orion_wdt_init();
}
@ -276,6 +290,9 @@ void __init orion5x_init(void)
*/
orion5x_setup_cpu_mbus_bridge();
/* Setup root of clk tree */
clk_init();
/*
* Don't issue "Wait for Interrupt" instruction if we are
* running on D0 5281 silicon.

View File

@ -16,7 +16,6 @@
#include <linux/mtd/physmap.h>
#include <linux/mv643xx_eth.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/spi/flash.h>
#include <linux/ethtool.h>
#include <net/dsa.h>

View File

@ -14,15 +14,41 @@
#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
#include <linux/ata_platform.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/mv643xx_eth.h>
#include <linux/mv643xx_i2c.h>
#include <net/dsa.h>
#include <linux/spi/orion_spi.h>
#include <plat/orion_wdt.h>
#include <plat/mv_xor.h>
#include <plat/ehci-orion.h>
#include <mach/bridge-regs.h>
/* Create a clkdev entry for a given device/clk */
void __init orion_clkdev_add(const char *con_id, const char *dev_id,
struct clk *clk)
{
struct clk_lookup *cl;
cl = clkdev_alloc(clk, con_id, dev_id);
if (cl)
clkdev_add(cl);
}
/* Create clkdev entries for all orion platforms except kirkwood.
Kirkwood has gated clocks for some of its peripherals, so creates
its own clkdev entries. For all the other orion devices, create
clkdev entries to the tclk. */
void __init orion_clkdev_init(struct clk *tclk)
{
orion_clkdev_add(NULL, "orion_spi.0", tclk);
orion_clkdev_add(NULL, "orion_spi.1", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".2", tclk);
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".3", tclk);
orion_clkdev_add(NULL, "orion_wdt", tclk);
}
/* Fill in the resources structure and link it into the platform
device structure. There is always a memory region, and nearly
always an interrupt.*/
@ -49,6 +75,12 @@ static void fill_resources(struct platform_device *device,
/*****************************************************************************
* UART
****************************************************************************/
static unsigned long __init uart_get_clk_rate(struct clk *clk)
{
clk_prepare_enable(clk);
return clk_get_rate(clk);
}
static void __init uart_complete(
struct platform_device *orion_uart,
struct plat_serial8250_port *data,
@ -56,12 +88,12 @@ static void __init uart_complete(
unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
data->mapbase = mapbase;
data->membase = (void __iomem *)membase;
data->irq = irq;
data->uartclk = uartclk;
data->uartclk = uart_get_clk_rate(clk);
orion_uart->dev.platform_data = data;
fill_resources(orion_uart, resources, mapbase, 0xff, irq);
@ -90,10 +122,10 @@ static struct platform_device orion_uart0 = {
void __init orion_uart0_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart0, orion_uart0_data, orion_uart0_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -118,10 +150,10 @@ static struct platform_device orion_uart1 = {
void __init orion_uart1_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart1, orion_uart1_data, orion_uart1_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -146,10 +178,10 @@ static struct platform_device orion_uart2 = {
void __init orion_uart2_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart2, orion_uart2_data, orion_uart2_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -174,10 +206,10 @@ static struct platform_device orion_uart3 = {
void __init orion_uart3_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk)
struct clk *clk)
{
uart_complete(&orion_uart3, orion_uart3_data, orion_uart3_resources,
membase, mapbase, irq, uartclk);
membase, mapbase, irq, clk);
}
/*****************************************************************************
@ -203,13 +235,11 @@ void __init orion_rtc_init(unsigned long mapbase,
****************************************************************************/
static __init void ge_complete(
struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
int tclk,
struct resource *orion_ge_resource, unsigned long irq,
struct platform_device *orion_ge_shared,
struct mv643xx_eth_platform_data *eth_data,
struct platform_device *orion_ge)
{
orion_ge_shared_data->t_clk = tclk;
orion_ge_resource->start = irq;
orion_ge_resource->end = irq;
eth_data->shared = orion_ge_shared;
@ -260,12 +290,11 @@ static struct platform_device orion_ge00 = {
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge00_shared_data, tclk,
ge_complete(&orion_ge00_shared_data,
orion_ge00_resources, irq, &orion_ge00_shared,
eth_data, &orion_ge00);
}
@ -313,12 +342,11 @@ static struct platform_device orion_ge01 = {
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge01_shared_data, tclk,
ge_complete(&orion_ge01_shared_data,
orion_ge01_resources, irq, &orion_ge01_shared,
eth_data, &orion_ge01);
}
@ -366,12 +394,11 @@ static struct platform_device orion_ge10 = {
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge10_shared_data, tclk,
ge_complete(&orion_ge10_shared_data,
orion_ge10_resources, irq, &orion_ge10_shared,
eth_data, &orion_ge10);
}
@ -419,12 +446,11 @@ static struct platform_device orion_ge11 = {
void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk)
unsigned long irq_err)
{
fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
mapbase + 0x2000, SZ_16K - 1, irq_err);
ge_complete(&orion_ge11_shared_data, tclk,
ge_complete(&orion_ge11_shared_data,
orion_ge11_resources, irq, &orion_ge11_shared,
eth_data, &orion_ge11);
}
@ -521,44 +547,32 @@ void __init orion_i2c_1_init(unsigned long mapbase,
/*****************************************************************************
* SPI
****************************************************************************/
static struct orion_spi_info orion_spi_plat_data;
static struct resource orion_spi_resources;
static struct platform_device orion_spi = {
.name = "orion_spi",
.id = 0,
.dev = {
.platform_data = &orion_spi_plat_data,
},
};
static struct orion_spi_info orion_spi_1_plat_data;
static struct resource orion_spi_1_resources;
static struct platform_device orion_spi_1 = {
.name = "orion_spi",
.id = 1,
.dev = {
.platform_data = &orion_spi_1_plat_data,
},
};
/* Note: The SPI silicon core does have interrupts. However the
* current Linux software driver does not use interrupts. */
void __init orion_spi_init(unsigned long mapbase,
unsigned long tclk)
void __init orion_spi_init(unsigned long mapbase)
{
orion_spi_plat_data.tclk = tclk;
fill_resources(&orion_spi, &orion_spi_resources,
mapbase, SZ_512 - 1, NO_IRQ);
platform_device_register(&orion_spi);
}
void __init orion_spi_1_init(unsigned long mapbase,
unsigned long tclk)
void __init orion_spi_1_init(unsigned long mapbase)
{
orion_spi_1_plat_data.tclk = tclk;
fill_resources(&orion_spi_1, &orion_spi_1_resources,
mapbase, SZ_512 - 1, NO_IRQ);
platform_device_register(&orion_spi_1);
@ -567,24 +581,18 @@ void __init orion_spi_1_init(unsigned long mapbase,
/*****************************************************************************
* Watchdog
****************************************************************************/
static struct orion_wdt_platform_data orion_wdt_data;
static struct resource orion_wdt_resource =
DEFINE_RES_MEM(TIMER_VIRT_BASE, 0x28);
static struct platform_device orion_wdt_device = {
.name = "orion_wdt",
.id = -1,
.dev = {
.platform_data = &orion_wdt_data,
},
.resource = &orion_wdt_resource,
.num_resources = 1,
.resource = &orion_wdt_resource,
};
void __init orion_wdt_init(unsigned long tclk)
void __init orion_wdt_init(void)
{
orion_wdt_data.tclk = tclk;
platform_device_register(&orion_wdt_device);
}

View File

@ -16,22 +16,22 @@ struct dsa_platform_data;
void __init orion_uart0_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_uart1_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_uart2_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_uart3_init(unsigned int membase,
resource_size_t mapbase,
unsigned int irq,
unsigned int uartclk);
struct clk *clk);
void __init orion_rtc_init(unsigned long mapbase,
unsigned long irq);
@ -39,29 +39,26 @@ void __init orion_rtc_init(unsigned long mapbase,
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq,
unsigned long irq_err,
int tclk);
unsigned long irq_err);
void __init orion_ge00_switch_init(struct dsa_platform_data *d,
int irq);
void __init orion_i2c_init(unsigned long mapbase,
unsigned long irq,
unsigned long freq_m);
@ -70,13 +67,11 @@ void __init orion_i2c_1_init(unsigned long mapbase,
unsigned long irq,
unsigned long freq_m);
void __init orion_spi_init(unsigned long mapbase,
unsigned long tclk);
void __init orion_spi_init(unsigned long mapbase);
void __init orion_spi_1_init(unsigned long mapbase,
unsigned long tclk);
void __init orion_spi_1_init(unsigned long mapbase);
void __init orion_wdt_init(unsigned long tclk);
void __init orion_wdt_init(void);
void __init orion_xor0_init(unsigned long mapbase_low,
unsigned long mapbase_high,
@ -106,4 +101,9 @@ void __init orion_crypto_init(unsigned long mapbase,
unsigned long srambase,
unsigned long sram_size,
unsigned long irq);
void __init orion_clkdev_add(const char *con_id, const char *dev_id,
struct clk *clk);
void __init orion_clkdev_init(struct clk *tclk);
#endif

View File

@ -1,18 +0,0 @@
/*
* arch/arm/plat-orion/include/plat/orion_wdt.h
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PLAT_ORION_WDT_H
#define __PLAT_ORION_WDT_H
struct orion_wdt_platform_data {
u32 tclk; /* no <linux/clk.h> support yet */
};
#endif

View File

@ -52,12 +52,12 @@
#define PCIE_DEBUG_SOFT_RESET (1<<20)
u32 __init orion_pcie_dev_id(void __iomem *base)
u32 orion_pcie_dev_id(void __iomem *base)
{
return readl(base + PCIE_DEV_ID_OFF) >> 16;
}
u32 __init orion_pcie_rev(void __iomem *base)
u32 orion_pcie_rev(void __iomem *base)
{
return readl(base + PCIE_DEV_REV_OFF) & 0xff;
}

View File

@ -553,6 +553,7 @@ struct mv_host_priv {
#if defined(CONFIG_HAVE_CLK)
struct clk *clk;
struct clk **port_clks;
#endif
/*
* These consistent DMA memory pools give us guaranteed
@ -4027,6 +4028,9 @@ static int mv_platform_probe(struct platform_device *pdev)
struct resource *res;
int n_ports = 0;
int rc;
#if defined(CONFIG_HAVE_CLK)
int port;
#endif
ata_print_version_once(&pdev->dev, DRV_VERSION);
@ -4054,6 +4058,13 @@ static int mv_platform_probe(struct platform_device *pdev)
if (!host || !hpriv)
return -ENOMEM;
#if defined(CONFIG_HAVE_CLK)
hpriv->port_clks = devm_kzalloc(&pdev->dev,
sizeof(struct clk *) * n_ports,
GFP_KERNEL);
if (!hpriv->port_clks)
return -ENOMEM;
#endif
host->private_data = hpriv;
hpriv->n_ports = n_ports;
hpriv->board_idx = chip_soc;
@ -4066,9 +4077,17 @@ static int mv_platform_probe(struct platform_device *pdev)
#if defined(CONFIG_HAVE_CLK)
hpriv->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(hpriv->clk))
dev_notice(&pdev->dev, "cannot get clkdev\n");
dev_notice(&pdev->dev, "cannot get optional clkdev\n");
else
clk_enable(hpriv->clk);
clk_prepare_enable(hpriv->clk);
for (port = 0; port < n_ports; port++) {
char port_number[16];
sprintf(port_number, "%d", port);
hpriv->port_clks[port] = clk_get(&pdev->dev, port_number);
if (!IS_ERR(hpriv->port_clks[port]))
clk_prepare_enable(hpriv->port_clks[port]);
}
#endif
/*
@ -4098,9 +4117,15 @@ static int mv_platform_probe(struct platform_device *pdev)
err:
#if defined(CONFIG_HAVE_CLK)
if (!IS_ERR(hpriv->clk)) {
clk_disable(hpriv->clk);
clk_disable_unprepare(hpriv->clk);
clk_put(hpriv->clk);
}
for (port = 0; port < n_ports; port++) {
if (!IS_ERR(hpriv->port_clks[port])) {
clk_disable_unprepare(hpriv->port_clks[port]);
clk_put(hpriv->port_clks[port]);
}
}
#endif
return rc;
@ -4119,14 +4144,21 @@ static int __devexit mv_platform_remove(struct platform_device *pdev)
struct ata_host *host = platform_get_drvdata(pdev);
#if defined(CONFIG_HAVE_CLK)
struct mv_host_priv *hpriv = host->private_data;
int port;
#endif
ata_host_detach(host);
#if defined(CONFIG_HAVE_CLK)
if (!IS_ERR(hpriv->clk)) {
clk_disable(hpriv->clk);
clk_disable_unprepare(hpriv->clk);
clk_put(hpriv->clk);
}
for (port = 0; port < host->n_ports; port++) {
if (!IS_ERR(hpriv->port_clks[port])) {
clk_disable_unprepare(hpriv->port_clks[port]);
clk_put(hpriv->port_clks[port]);
}
}
#endif
return 0;
}

View File

@ -903,7 +903,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (rate == clk->rate)
goto out;
if ((clk->flags & CLK_SET_RATE_GATE) && __clk_is_enabled(clk)) {
if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
ret = -EBUSY;
goto out;
}
@ -1420,6 +1420,15 @@ fail_out:
}
EXPORT_SYMBOL_GPL(clk_register);
/**
* clk_unregister - unregister a currently registered clock
* @clk: clock to unregister
*
* Currently unimplemented.
*/
void clk_unregister(struct clk *clk) {}
EXPORT_SYMBOL_GPL(clk_unregister);
/*** clk rate change notifiers ***/
/**

View File

@ -16,6 +16,7 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <crypto/internal/hash.h>
#include <crypto/sha.h>
@ -79,6 +80,7 @@ struct crypto_priv {
void __iomem *reg;
void __iomem *sram;
int irq;
struct clk *clk;
struct task_struct *queue_th;
/* the lock protects queue and eng_st */
@ -1053,6 +1055,12 @@ static int mv_probe(struct platform_device *pdev)
if (ret)
goto err_thread;
/* Not all platforms can gate the clock, so it is not
an error if the clock does not exists. */
cp->clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(cp->clk))
clk_prepare_enable(cp->clk);
writel(SEC_INT_ACCEL0_DONE, cpg->reg + SEC_ACCEL_INT_MASK);
writel(SEC_CFG_STOP_DIG_ERR, cpg->reg + SEC_ACCEL_CFG);
writel(SRAM_CONFIG, cpg->reg + SEC_ACCEL_DESC_P0);
@ -1118,6 +1126,12 @@ static int mv_remove(struct platform_device *pdev)
memset(cp->sram, 0, cp->sram_size);
iounmap(cp->sram);
iounmap(cp->reg);
if (!IS_ERR(cp->clk)) {
clk_disable_unprepare(cp->clk);
clk_put(cp->clk);
}
kfree(cp);
cpg = NULL;
return 0;

View File

@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/memory.h>
#include <linux/clk.h>
#include <plat/mv_xor.h>
#include "dmaengine.h"
@ -1307,11 +1308,25 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
if (dram)
mv_xor_conf_mbus_windows(msp, dram);
/* Not all platforms can gate the clock, so it is not
* an error if the clock does not exists.
*/
msp->clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(msp->clk))
clk_prepare_enable(msp->clk);
return 0;
}
static int mv_xor_shared_remove(struct platform_device *pdev)
{
struct mv_xor_shared_private *msp = platform_get_drvdata(pdev);
if (!IS_ERR(msp->clk)) {
clk_disable_unprepare(msp->clk);
clk_put(msp->clk);
}
return 0;
}

View File

@ -55,6 +55,7 @@
struct mv_xor_shared_private {
void __iomem *xor_base;
void __iomem *xor_high_base;
struct clk *clk;
};

View File

@ -19,6 +19,7 @@
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/mmc/host.h>
@ -51,6 +52,7 @@ struct mvsd_host {
struct device *dev;
struct resource *res;
int irq;
struct clk *clk;
int gpio_card_detect;
int gpio_write_protect;
};
@ -770,6 +772,13 @@ static int __init mvsd_probe(struct platform_device *pdev)
} else
host->irq = irq;
/* Not all platforms can gate the clock, so it is not
an error if the clock does not exists. */
host->clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(host->clk)) {
clk_prepare_enable(host->clk);
}
if (mvsd_data->gpio_card_detect) {
ret = gpio_request(mvsd_data->gpio_card_detect,
DRIVER_NAME " cd");
@ -854,6 +863,11 @@ static int __exit mvsd_remove(struct platform_device *pdev)
mvsd_power_down(host);
iounmap(host->base);
release_resource(host->res);
if (!IS_ERR(host->clk)) {
clk_disable_unprepare(host->clk);
clk_put(host->clk);
}
mmc_free_host(mmc);
}
platform_set_drvdata(pdev, NULL);

View File

@ -16,6 +16,8 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <mach/hardware.h>
@ -77,6 +79,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
struct nand_chip *nc;
struct orion_nand_data *board;
struct resource *res;
struct clk *clk;
void __iomem *io_base;
int ret = 0;
@ -123,6 +126,14 @@ static int __init orion_nand_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mtd);
/* Not all platforms can gate the clock, so it is not
an error if the clock does not exists. */
clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(clk)) {
clk_prepare_enable(clk);
clk_put(clk);
}
if (nand_scan(mtd, 1)) {
ret = -ENXIO;
goto no_dev;
@ -151,6 +162,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev)
{
struct mtd_info *mtd = platform_get_drvdata(pdev);
struct nand_chip *nc = mtd->priv;
struct clk *clk;
nand_release(mtd);
@ -158,6 +170,12 @@ static int __devexit orion_nand_remove(struct platform_device *pdev)
kfree(nc);
clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(clk)) {
clk_disable_unprepare(clk);
clk_put(clk);
}
return 0;
}

View File

@ -57,6 +57,7 @@
#include <linux/types.h>
#include <linux/inet_lro.h>
#include <linux/slab.h>
#include <linux/clk.h>
static char mv643xx_eth_driver_name[] = "mv643xx_eth";
static char mv643xx_eth_driver_version[] = "1.4";
@ -289,10 +290,10 @@ struct mv643xx_eth_shared_private {
/*
* Hardware-specific parameters.
*/
unsigned int t_clk;
int extended_rx_coal_limit;
int tx_bw_control;
int tx_csum_limit;
};
#define TX_BW_CONTROL_ABSENT 0
@ -431,6 +432,12 @@ struct mv643xx_eth_private {
int tx_desc_sram_size;
int txq_count;
struct tx_queue txq[8];
/*
* Hardware-specific parameters.
*/
struct clk *clk;
unsigned int t_clk;
};
@ -1010,7 +1017,7 @@ static void tx_set_rate(struct mv643xx_eth_private *mp, int rate, int burst)
int mtu;
int bucket_size;
token_rate = ((rate / 1000) * 64) / (mp->shared->t_clk / 1000);
token_rate = ((rate / 1000) * 64) / (mp->t_clk / 1000);
if (token_rate > 1023)
token_rate = 1023;
@ -1042,7 +1049,7 @@ static void txq_set_rate(struct tx_queue *txq, int rate, int burst)
int token_rate;
int bucket_size;
token_rate = ((rate / 1000) * 64) / (mp->shared->t_clk / 1000);
token_rate = ((rate / 1000) * 64) / (mp->t_clk / 1000);
if (token_rate > 1023)
token_rate = 1023;
@ -1309,7 +1316,7 @@ static unsigned int get_rx_coal(struct mv643xx_eth_private *mp)
temp = (val & 0x003fff00) >> 8;
temp *= 64000000;
do_div(temp, mp->shared->t_clk);
do_div(temp, mp->t_clk);
return (unsigned int)temp;
}
@ -1319,7 +1326,7 @@ static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int usec)
u64 temp;
u32 val;
temp = (u64)usec * mp->shared->t_clk;
temp = (u64)usec * mp->t_clk;
temp += 31999999;
do_div(temp, 64000000);
@ -1345,7 +1352,7 @@ static unsigned int get_tx_coal(struct mv643xx_eth_private *mp)
temp = (rdlp(mp, TX_FIFO_URGENT_THRESHOLD) & 0x3fff0) >> 4;
temp *= 64000000;
do_div(temp, mp->shared->t_clk);
do_div(temp, mp->t_clk);
return (unsigned int)temp;
}
@ -1354,7 +1361,7 @@ static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int usec)
{
u64 temp;
temp = (u64)usec * mp->shared->t_clk;
temp = (u64)usec * mp->t_clk;
temp += 31999999;
do_div(temp, 64000000);
@ -2662,10 +2669,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
if (dram)
mv643xx_eth_conf_mbus_windows(msp, dram);
/*
* Detect hardware parameters.
*/
msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000;
msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
pd->tx_csum_limit : 9 * 1024;
infer_hw_params(msp);
@ -2890,6 +2893,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
mp->dev = dev;
/*
* Get the clk rate, if there is one, otherwise use the default.
*/
mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0"));
if (!IS_ERR(mp->clk)) {
clk_prepare_enable(mp->clk);
mp->t_clk = clk_get_rate(mp->clk);
} else {
mp->t_clk = 133000000;
printk(KERN_WARNING "Unable to get clock");
}
set_params(mp, pd);
netif_set_real_num_tx_queues(dev, mp->txq_count);
netif_set_real_num_rx_queues(dev, mp->rxq_count);
@ -2978,6 +2993,11 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
if (mp->phy != NULL)
phy_detach(mp->phy);
cancel_work_sync(&mp->tx_timeout_task);
if (!IS_ERR(mp->clk)) {
clk_disable_unprepare(mp->clk);
clk_put(mp->clk);
}
free_netdev(mp->dev);
platform_set_drvdata(pdev, NULL);

View File

@ -16,8 +16,8 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/spi/spi.h>
#include <linux/spi/orion_spi.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <asm/unaligned.h>
#define DRIVER_NAME "orion_spi"
@ -46,6 +46,7 @@ struct orion_spi {
unsigned int max_speed;
unsigned int min_speed;
struct orion_spi_info *spi_info;
struct clk *clk;
};
static struct workqueue_struct *orion_spi_wq;
@ -104,7 +105,7 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
orion_spi = spi_master_get_devdata(spi->master);
tclk_hz = orion_spi->spi_info->tclk;
tclk_hz = clk_get_rate(orion_spi->clk);
/*
* the supported rates are: 4,6,8...30
@ -450,6 +451,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
struct orion_spi *spi;
struct resource *r;
struct orion_spi_info *spi_info;
unsigned long tclk_hz;
int status = 0;
spi_info = pdev->dev.platform_data;
@ -476,19 +478,28 @@ static int __init orion_spi_probe(struct platform_device *pdev)
spi->master = master;
spi->spi_info = spi_info;
spi->max_speed = DIV_ROUND_UP(spi_info->tclk, 4);
spi->min_speed = DIV_ROUND_UP(spi_info->tclk, 30);
spi->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(spi->clk)) {
status = PTR_ERR(spi->clk);
goto out;
}
clk_prepare(spi->clk);
clk_enable(spi->clk);
tclk_hz = clk_get_rate(spi->clk);
spi->max_speed = DIV_ROUND_UP(tclk_hz, 4);
spi->min_speed = DIV_ROUND_UP(tclk_hz, 30);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
status = -ENODEV;
goto out;
goto out_rel_clk;
}
if (!request_mem_region(r->start, resource_size(r),
dev_name(&pdev->dev))) {
status = -EBUSY;
goto out;
goto out_rel_clk;
}
spi->base = ioremap(r->start, SZ_1K);
@ -508,7 +519,9 @@ static int __init orion_spi_probe(struct platform_device *pdev)
out_rel_mem:
release_mem_region(r->start, resource_size(r));
out_rel_clk:
clk_disable_unprepare(spi->clk);
clk_put(spi->clk);
out:
spi_master_put(master);
return status;
@ -526,6 +539,9 @@ static int __exit orion_spi_remove(struct platform_device *pdev)
cancel_work_sync(&spi->work);
clk_disable_unprepare(spi->clk);
clk_put(spi->clk);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(r->start, resource_size(r));

View File

@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mbus.h>
#include <linux/clk.h>
#include <plat/ehci-orion.h>
#define rdl(off) __raw_readl(hcd->regs + (off))
@ -198,6 +199,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
struct resource *res;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct clk *clk;
void __iomem *regs;
int irq, err;
@ -238,6 +240,14 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
goto err2;
}
/* Not all platforms can gate the clock, so it is not
an error if the clock does not exists. */
clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(clk)) {
clk_prepare_enable(clk);
clk_put(clk);
}
hcd = usb_create_hcd(&ehci_orion_hc_driver,
&pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
@ -301,12 +311,18 @@ err1:
static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct clk *clk;
usb_remove_hcd(hcd);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
clk = clk_get(&pdev->dev, NULL);
if (!IS_ERR(clk)) {
clk_disable_unprepare(clk);
clk_put(clk);
}
return 0;
}

View File

@ -24,8 +24,8 @@
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/clk.h>
#include <mach/bridge-regs.h>
#include <plat/orion_wdt.h>
/*
* Watchdog timer block registers.
@ -41,6 +41,7 @@
static bool nowayout = WATCHDOG_NOWAYOUT;
static int heartbeat = -1; /* module parameter (seconds) */
static unsigned int wdt_max_duration; /* (seconds) */
static struct clk *clk;
static unsigned int wdt_tclk;
static void __iomem *wdt_reg;
static unsigned long wdt_status;
@ -237,16 +238,16 @@ static struct miscdevice orion_wdt_miscdev = {
static int __devinit orion_wdt_probe(struct platform_device *pdev)
{
struct orion_wdt_platform_data *pdata = pdev->dev.platform_data;
struct resource *res;
int ret;
if (pdata) {
wdt_tclk = pdata->tclk;
} else {
pr_err("misses platform data\n");
clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
printk(KERN_ERR "Orion Watchdog missing clock\n");
return -ENODEV;
}
clk_prepare_enable(clk);
wdt_tclk = clk_get_rate(clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -282,6 +283,9 @@ static int __devexit orion_wdt_remove(struct platform_device *pdev)
if (!ret)
orion_wdt_miscdev.parent = NULL;
clk_disable_unprepare(clk);
clk_put(clk);
return ret;
}

View File

@ -312,6 +312,8 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
*/
struct clk *clk_register(struct device *dev, struct clk_hw *hw);
void clk_unregister(struct clk *clk);
/* helper functions */
const char *__clk_get_name(struct clk *clk);
struct clk_hw *__clk_get_hw(struct clk *clk);

View File

@ -18,7 +18,6 @@
struct mv643xx_eth_shared_platform_data {
struct mbus_dram_target_info *dram;
struct platform_device *shared_smi;
unsigned int t_clk;
/*
* Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
* limit of 9KiB will be used.

View File

@ -1,17 +0,0 @@
/*
* orion_spi.h
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __LINUX_SPI_ORION_SPI_H
#define __LINUX_SPI_ORION_SPI_H
struct orion_spi_info {
u32 tclk; /* no <linux/clk.h> support yet */
};
#endif

View File

@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/mbus.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@ -449,6 +450,14 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
priv->burst = data->burst;
priv->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "no clock\n");
err = PTR_ERR(priv->clk);
goto err_ioremap;
}
clk_prepare_enable(priv->clk);
return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);
err_ioremap:
@ -466,6 +475,10 @@ static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
clk_disable_unprepare(priv->clk);
clk_put(priv->clk);
iounmap(priv->io);
release_mem_region(priv->mem->start, SZ_16K);
kfree(priv);

View File

@ -123,6 +123,7 @@ struct kirkwood_dma_data {
void __iomem *io;
int irq;
int burst;
struct clk *clk;
};
#endif