Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 287e3f3f authored by John Crispin's avatar John Crispin Committed by Ralf Baechle
Browse files

MIPS: lantiq: implement support for clkdev api



This patch unifies all clock generation and gating code into one file.
All drivers will now be able to request their clocks via their device.
This patch also adds support for the clockout feature, which allows
clock generation on external pins.

Support for COMMON_CLK will be provided in the next series.

Signed-off-by: default avatarJohn Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3804/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent bd51db7f
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -228,7 +228,8 @@ config LANTIQ
	select ARCH_REQUIRE_GPIOLIB
	select ARCH_REQUIRE_GPIOLIB
	select SWAP_IO_SPACE
	select SWAP_IO_SPACE
	select BOOT_RAW
	select BOOT_RAW
	select HAVE_CLK
	select HAVE_MACH_CLKDEV
	select CLKDEV_LOOKUP
	select USE_OF
	select USE_OF


config LASAT
config LASAT
+12 −15
Original line number Original line Diff line number Diff line
@@ -9,6 +9,8 @@
#define _LANTIQ_H__
#define _LANTIQ_H__


#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <linux/clk.h>


/* generic reg access functions */
/* generic reg access functions */
#define ltq_r32(reg)		__raw_readl(reg)
#define ltq_r32(reg)		__raw_readl(reg)
@@ -21,26 +23,13 @@
/* register access macros for EBU and CGU */
/* register access macros for EBU and CGU */
#define ltq_ebu_w32(x, y)	ltq_w32((x), ltq_ebu_membase + (y))
#define ltq_ebu_w32(x, y)	ltq_w32((x), ltq_ebu_membase + (y))
#define ltq_ebu_r32(x)		ltq_r32(ltq_ebu_membase + (x))
#define ltq_ebu_r32(x)		ltq_r32(ltq_ebu_membase + (x))
#define ltq_cgu_w32(x, y)	ltq_w32((x), ltq_cgu_membase + (y))
#define ltq_ebu_w32_mask(x, y, z) \
#define ltq_cgu_r32(x)		ltq_r32(ltq_cgu_membase + (x))
	ltq_w32_mask(x, y, ltq_ebu_membase + (z))

extern __iomem void *ltq_ebu_membase;
extern __iomem void *ltq_ebu_membase;
extern __iomem void *ltq_cgu_membase;


extern unsigned int ltq_get_cpu_ver(void);
extern unsigned int ltq_get_cpu_ver(void);
extern unsigned int ltq_get_soc_type(void);
extern unsigned int ltq_get_soc_type(void);


/* clock speeds */
#define CLOCK_60M	60000000
#define CLOCK_83M	83333333
#define CLOCK_111M	111111111
#define CLOCK_133M	133333333
#define CLOCK_167M	166666667
#define CLOCK_200M	200000000
#define CLOCK_266M	266666666
#define CLOCK_333M	333333333
#define CLOCK_400M	400000000

/* spinlock all ebu i/o */
/* spinlock all ebu i/o */
extern spinlock_t ebu_lock;
extern spinlock_t ebu_lock;


@@ -48,6 +37,14 @@ extern spinlock_t ebu_lock;
extern void ltq_disable_irq(struct irq_data *data);
extern void ltq_disable_irq(struct irq_data *data);
extern void ltq_mask_and_ack_irq(struct irq_data *data);
extern void ltq_mask_and_ack_irq(struct irq_data *data);
extern void ltq_enable_irq(struct irq_data *data);
extern void ltq_enable_irq(struct irq_data *data);

/* clock handling */
extern int clk_activate(struct clk *clk);
extern void clk_deactivate(struct clk *clk);
extern struct clk *clk_get_cpu(void);
extern struct clk *clk_get_fpi(void);
extern struct clk *clk_get_io(void);

/* find out what bootsource we have */
/* find out what bootsource we have */
extern unsigned char ltq_boot_select(void);
extern unsigned char ltq_boot_select(void);
/* find out what caused the last cpu reset */
/* find out what caused the last cpu reset */
+5 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,11 @@
#define BS_NAND			0x6
#define BS_NAND			0x6
#define BS_RMII0		0x7
#define BS_RMII0		0x7


/* helpers used to access the cgu */
#define ltq_cgu_w32(x, y)	ltq_w32((x), ltq_cgu_membase + (y))
#define ltq_cgu_r32(x)		ltq_r32(ltq_cgu_membase + (x))
extern __iomem void *ltq_cgu_membase;

/*
/*
 * during early_printk no ioremap is possible
 * during early_printk no ioremap is possible
 * lets use KSEG1 instead
 * lets use KSEG1 instead
+79 −67
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/list.h>


@@ -22,44 +23,32 @@
#include <lantiq_soc.h>
#include <lantiq_soc.h>


#include "clk.h"
#include "clk.h"
#include "prom.h"


struct clk {
/* lantiq socs have 3 static clocks */
	const char *name;
static struct clk cpu_clk_generic[3];
	unsigned long rate;
	unsigned long (*get_rate) (void);
};


static struct clk *cpu_clk;
void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io)
static int cpu_clk_cnt;
{
	cpu_clk_generic[0].rate = cpu;
	cpu_clk_generic[1].rate = fpi;
	cpu_clk_generic[2].rate = io;
}


/* lantiq socs have 3 static clocks */
struct clk *clk_get_cpu(void)
static struct clk cpu_clk_generic[] = {
{
{
		.name = "cpu",
	return &cpu_clk_generic[0];
		.get_rate = ltq_get_cpu_hz,
}
	}, {

		.name = "fpi",
struct clk *clk_get_fpi(void)
		.get_rate = ltq_get_fpi_hz,
{
	}, {
	return &cpu_clk_generic[1];
		.name = "io",
}
		.get_rate = ltq_get_io_region_clock,
EXPORT_SYMBOL_GPL(clk_get_fpi);
	},

};
struct clk *clk_get_io(void)

static struct resource ltq_cgu_resource = {
	.name	= "cgu",
	.start	= LTQ_CGU_BASE_ADDR,
	.end	= LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
	.flags	= IORESOURCE_MEM,
};

/* remapped clock register range */
void __iomem *ltq_cgu_membase;

void clk_init(void)
{
{
	cpu_clk = cpu_clk_generic;
	return &cpu_clk_generic[2];
	cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
}
}


static inline int clk_good(struct clk *clk)
static inline int clk_good(struct clk *clk)
@@ -82,38 +71,71 @@ unsigned long clk_get_rate(struct clk *clk)
}
}
EXPORT_SYMBOL(clk_get_rate);
EXPORT_SYMBOL(clk_get_rate);


struct clk *clk_get(struct device *dev, const char *id)
int clk_set_rate(struct clk *clk, unsigned long rate)
{
{
	int i;
	if (unlikely(!clk_good(clk)))

		return 0;
	for (i = 0; i < cpu_clk_cnt; i++)
	if (clk->rates && *clk->rates) {
		if (!strcmp(id, cpu_clk[i].name))
		unsigned long *r = clk->rates;
			return &cpu_clk[i];

	BUG();
		while (*r && (*r != rate))
	return ERR_PTR(-ENOENT);
			r++;
		if (!*r) {
			pr_err("clk %s.%s: trying to set invalid rate %ld\n",
				clk->cl.dev_id, clk->cl.con_id, rate);
			return -1;
		}
		}
EXPORT_SYMBOL(clk_get);

void clk_put(struct clk *clk)
{
	/* not used */
	}
	}
EXPORT_SYMBOL(clk_put);
	clk->rate = rate;
	return 0;
}
EXPORT_SYMBOL(clk_set_rate);


int clk_enable(struct clk *clk)
int clk_enable(struct clk *clk)
{
{
	/* not used */
	if (unlikely(!clk_good(clk)))
	return 0;
		return -1;

	if (clk->enable)
		return clk->enable(clk);

	return -1;
}
}
EXPORT_SYMBOL(clk_enable);
EXPORT_SYMBOL(clk_enable);


void clk_disable(struct clk *clk)
void clk_disable(struct clk *clk)
{
{
	/* not used */
	if (unlikely(!clk_good(clk)))
		return;

	if (clk->disable)
		clk->disable(clk);
}
}
EXPORT_SYMBOL(clk_disable);
EXPORT_SYMBOL(clk_disable);


static inline u32 ltq_get_counter_resolution(void)
int clk_activate(struct clk *clk)
{
	if (unlikely(!clk_good(clk)))
		return -1;

	if (clk->activate)
		return clk->activate(clk);

	return -1;
}
EXPORT_SYMBOL(clk_activate);

void clk_deactivate(struct clk *clk)
{
	if (unlikely(!clk_good(clk)))
		return;

	if (clk->deactivate)
		clk->deactivate(clk);
}
EXPORT_SYMBOL(clk_deactivate);

static inline u32 get_counter_resolution(void)
{
{
	u32 res;
	u32 res;


@@ -133,21 +155,11 @@ void __init plat_time_init(void)
{
{
	struct clk *clk;
	struct clk *clk;


	if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
	ltq_soc_init();
		panic("Failed to insert cgu memory");


	if (request_mem_region(ltq_cgu_resource.start,
	clk = clk_get_cpu();
			resource_size(&ltq_cgu_resource), "cgu") < 0)
	mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
		panic("Failed to request cgu memory");

	ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
				resource_size(&ltq_cgu_resource));
	if (!ltq_cgu_membase) {
		pr_err("Failed to remap cgu memory\n");
		unreachable();
	}
	clk = clk_get(0, "cpu");
	mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
	write_c0_compare(read_c0_count());
	write_c0_compare(read_c0_count());
	pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
	clk_put(clk);
	clk_put(clk);
}
}
+64 −4
Original line number Original line Diff line number Diff line
@@ -9,10 +9,70 @@
#ifndef _LTQ_CLK_H__
#ifndef _LTQ_CLK_H__
#define _LTQ_CLK_H__
#define _LTQ_CLK_H__


extern void clk_init(void);
#include <linux/clkdev.h>


extern unsigned long ltq_get_cpu_hz(void);
/* clock speeds */
extern unsigned long ltq_get_fpi_hz(void);
#define CLOCK_33M	33333333
extern unsigned long ltq_get_io_region_clock(void);
#define CLOCK_60M	60000000
#define CLOCK_62_5M	62500000
#define CLOCK_83M	83333333
#define CLOCK_83_5M	83500000
#define CLOCK_98_304M	98304000
#define CLOCK_100M	100000000
#define CLOCK_111M	111111111
#define CLOCK_125M	125000000
#define CLOCK_133M	133333333
#define CLOCK_150M	150000000
#define CLOCK_166M	166666666
#define CLOCK_167M	166666667
#define CLOCK_196_608M	196608000
#define CLOCK_200M	200000000
#define CLOCK_250M	250000000
#define CLOCK_266M	266666666
#define CLOCK_300M	300000000
#define CLOCK_333M	333333333
#define CLOCK_393M	393215332
#define CLOCK_400M	400000000
#define CLOCK_500M	500000000
#define CLOCK_600M	600000000

/* clock out speeds */
#define CLOCK_32_768K	32768
#define CLOCK_1_536M	1536000
#define CLOCK_2_5M	2500000
#define CLOCK_12M	12000000
#define CLOCK_24M	24000000
#define CLOCK_25M	25000000
#define CLOCK_30M	30000000
#define CLOCK_40M	40000000
#define CLOCK_48M	48000000
#define CLOCK_50M	50000000
#define CLOCK_60M	60000000

struct clk {
	struct clk_lookup cl;
	unsigned long rate;
	unsigned long *rates;
	unsigned int module;
	unsigned int bits;
	unsigned long (*get_rate) (void);
	int (*enable) (struct clk *clk);
	void (*disable) (struct clk *clk);
	int (*activate) (struct clk *clk);
	void (*deactivate) (struct clk *clk);
	void (*reboot) (struct clk *clk);
};

extern void clkdev_add_static(unsigned long cpu, unsigned long fpi,
				unsigned long io);

extern unsigned long ltq_danube_cpu_hz(void);
extern unsigned long ltq_danube_fpi_hz(void);

extern unsigned long ltq_ar9_cpu_hz(void);
extern unsigned long ltq_ar9_fpi_hz(void);

extern unsigned long ltq_vr9_cpu_hz(void);
extern unsigned long ltq_vr9_fpi_hz(void);


#endif
#endif
Loading