summary refs log tree commit diff
path: root/arch/mips/lantiq
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2013-02-21 12:51:33 +0100
committerRalf Baechle <ralf@linux-mips.org>2013-02-21 12:51:33 +0100
commit8bfc245f9ad7bd4e461179e4e7852ef99b8b6144 (patch)
tree0ad091f645fbc8318634599d278966a53d3922ee /arch/mips/lantiq
parent612663a974065c3445e641d046769fe4c55a6438 (diff)
parent535237cecab2b078114be712c67e89a0db61965f (diff)
downloadlinux-8bfc245f9ad7bd4e461179e4e7852ef99b8b6144.tar.gz
Merge branch 'mips-next-3.9' of git://git.linux-mips.org/pub/scm/john/linux-john into mips-for-linux-next
Diffstat (limited to 'arch/mips/lantiq')
-rw-r--r--arch/mips/lantiq/clk.c12
-rw-r--r--arch/mips/lantiq/clk.h7
-rw-r--r--arch/mips/lantiq/falcon/sysctrl.c4
-rw-r--r--arch/mips/lantiq/irq.c105
-rw-r--r--arch/mips/lantiq/xway/clk.c43
-rw-r--r--arch/mips/lantiq/xway/reset.c9
-rw-r--r--arch/mips/lantiq/xway/sysctrl.c15
7 files changed, 152 insertions, 43 deletions
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index 186fd3e44242..3fc2e6d70c77 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -26,13 +26,15 @@
 #include "prom.h"
 
 /* lantiq socs have 3 static clocks */
-static struct clk cpu_clk_generic[3];
+static struct clk cpu_clk_generic[4];
 
-void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io)
+void clkdev_add_static(unsigned long cpu, unsigned long fpi,
+			unsigned long io, unsigned long ppe)
 {
 	cpu_clk_generic[0].rate = cpu;
 	cpu_clk_generic[1].rate = fpi;
 	cpu_clk_generic[2].rate = io;
+	cpu_clk_generic[3].rate = ppe;
 }
 
 struct clk *clk_get_cpu(void)
@@ -51,6 +53,12 @@ struct clk *clk_get_io(void)
 	return &cpu_clk_generic[2];
 }
 
+struct clk *clk_get_ppe(void)
+{
+	return &cpu_clk_generic[3];
+}
+EXPORT_SYMBOL_GPL(clk_get_ppe);
+
 static inline int clk_good(struct clk *clk)
 {
 	return clk && !IS_ERR(clk);
diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
index fa670602b91b..77e4bdb1fe8c 100644
--- a/arch/mips/lantiq/clk.h
+++ b/arch/mips/lantiq/clk.h
@@ -27,12 +27,15 @@
 #define CLOCK_167M	166666667
 #define CLOCK_196_608M	196608000
 #define CLOCK_200M	200000000
+#define CLOCK_222M	222000000
+#define CLOCK_240M	240000000
 #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_450M	450000000
 #define CLOCK_500M	500000000
 #define CLOCK_600M	600000000
 
@@ -64,15 +67,17 @@ struct clk {
 };
 
 extern void clkdev_add_static(unsigned long cpu, unsigned long fpi,
-				unsigned long io);
+				unsigned long io, unsigned long ppe);
 
 extern unsigned long ltq_danube_cpu_hz(void);
 extern unsigned long ltq_danube_fpi_hz(void);
+extern unsigned long ltq_danube_pp32_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);
+extern unsigned long ltq_vr9_pp32_hz(void);
 
 #endif
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
index 2d4ced332b37..ff4894a833ee 100644
--- a/arch/mips/lantiq/falcon/sysctrl.c
+++ b/arch/mips/lantiq/falcon/sysctrl.c
@@ -241,9 +241,9 @@ void __init ltq_soc_init(void)
 
 	/* get our 3 static rates for cpu, fpi and io clocks */
 	if (ltq_sys1_r32(SYS1_CPU0CC) & CPU0CC_CPUDIV)
-		clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M);
+		clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M, 0);
 	else
-		clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M);
+		clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M, 0);
 
 	/* add our clock domains */
 	clkdev_add_sys("1d810000.gpio", SYSCTL_SYSETH, ACTS_P0);
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 5323308aab3f..51194875f158 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -33,17 +33,10 @@
 /* register definitions - external irqs */
 #define LTQ_EIU_EXIN_C		0x0000
 #define LTQ_EIU_EXIN_INIC	0x0004
+#define LTQ_EIU_EXIN_INC	0x0008
 #define LTQ_EIU_EXIN_INEN	0x000C
 
-/* irq numbers used by the external interrupt unit (EIU) */
-#define LTQ_EIU_IR0		(INT_NUM_IM4_IRL0 + 30)
-#define LTQ_EIU_IR1		(INT_NUM_IM3_IRL0 + 31)
-#define LTQ_EIU_IR2		(INT_NUM_IM1_IRL0 + 26)
-#define LTQ_EIU_IR3		INT_NUM_IM1_IRL0
-#define LTQ_EIU_IR4		(INT_NUM_IM1_IRL0 + 1)
-#define LTQ_EIU_IR5		(INT_NUM_IM1_IRL0 + 2)
-#define LTQ_EIU_IR6		(INT_NUM_IM2_IRL0 + 30)
-#define XWAY_EXIN_COUNT		3
+/* number of external interrupts */
 #define MAX_EIU			6
 
 /* the performance counter */
@@ -72,20 +65,19 @@
 int gic_present;
 #endif
 
-static unsigned short ltq_eiu_irq[MAX_EIU] = {
-	LTQ_EIU_IR0,
-	LTQ_EIU_IR1,
-	LTQ_EIU_IR2,
-	LTQ_EIU_IR3,
-	LTQ_EIU_IR4,
-	LTQ_EIU_IR5,
-};
-
 static int exin_avail;
+static struct resource ltq_eiu_irq[MAX_EIU];
 static void __iomem *ltq_icu_membase[MAX_IM];
 static void __iomem *ltq_eiu_membase;
 static struct irq_domain *ltq_domain;
 
+int ltq_eiu_get_irq(int exin)
+{
+	if (exin < exin_avail)
+		return ltq_eiu_irq[exin].start;
+	return -1;
+}
+
 void ltq_disable_irq(struct irq_data *d)
 {
 	u32 ier = LTQ_ICU_IM0_IER;
@@ -128,19 +120,65 @@ void ltq_enable_irq(struct irq_data *d)
 	ltq_icu_w32(im, ltq_icu_r32(im, ier) | BIT(offset), ier);
 }
 
+static int ltq_eiu_settype(struct irq_data *d, unsigned int type)
+{
+	int i;
+
+	for (i = 0; i < MAX_EIU; i++) {
+		if (d->hwirq == ltq_eiu_irq[i].start) {
+			int val = 0;
+			int edge = 0;
+
+			switch (type) {
+			case IRQF_TRIGGER_NONE:
+				break;
+			case IRQF_TRIGGER_RISING:
+				val = 1;
+				edge = 1;
+				break;
+			case IRQF_TRIGGER_FALLING:
+				val = 2;
+				edge = 1;
+				break;
+			case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING:
+				val = 3;
+				edge = 1;
+				break;
+			case IRQF_TRIGGER_HIGH:
+				val = 5;
+				break;
+			case IRQF_TRIGGER_LOW:
+				val = 6;
+				break;
+			default:
+				pr_err("invalid type %d for irq %ld\n",
+					type, d->hwirq);
+				return -EINVAL;
+			}
+
+			if (edge)
+				irq_set_handler(d->hwirq, handle_edge_irq);
+
+			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
+				(val << (i * 4)), LTQ_EIU_EXIN_C);
+		}
+	}
+
+	return 0;
+}
+
 static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
 {
 	int i;
 
 	ltq_enable_irq(d);
 	for (i = 0; i < MAX_EIU; i++) {
-		if (d->hwirq == ltq_eiu_irq[i]) {
-			/* low level - we should really handle set_type */
-			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
-				(0x6 << (i * 4)), LTQ_EIU_EXIN_C);
+		if (d->hwirq == ltq_eiu_irq[i].start) {
+			/* by default we are low level triggered */
+			ltq_eiu_settype(d, IRQF_TRIGGER_LOW);
 			/* clear all pending */
-			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~BIT(i),
-				LTQ_EIU_EXIN_INIC);
+			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INC) & ~BIT(i),
+				LTQ_EIU_EXIN_INC);
 			/* enable */
 			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | BIT(i),
 				LTQ_EIU_EXIN_INEN);
@@ -157,7 +195,7 @@ static void ltq_shutdown_eiu_irq(struct irq_data *d)
 
 	ltq_disable_irq(d);
 	for (i = 0; i < MAX_EIU; i++) {
-		if (d->hwirq == ltq_eiu_irq[i]) {
+		if (d->hwirq == ltq_eiu_irq[i].start) {
 			/* disable */
 			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~BIT(i),
 				LTQ_EIU_EXIN_INEN);
@@ -186,6 +224,7 @@ static struct irq_chip ltq_eiu_type = {
 	.irq_ack = ltq_ack_irq,
 	.irq_mask = ltq_disable_irq,
 	.irq_mask_ack = ltq_mask_and_ack_irq,
+	.irq_set_type = ltq_eiu_settype,
 };
 
 static void ltq_hw_irqdispatch(int module)
@@ -301,7 +340,7 @@ static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 		return 0;
 
 	for (i = 0; i < exin_avail; i++)
-		if (hw == ltq_eiu_irq[i])
+		if (hw == ltq_eiu_irq[i].start)
 			chip = &ltq_eiu_type;
 
 	irq_set_chip_and_handler(hw, chip, handle_level_irq);
@@ -323,7 +362,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
 {
 	struct device_node *eiu_node;
 	struct resource res;
-	int i;
+	int i, ret;
 
 	for (i = 0; i < MAX_IM; i++) {
 		if (of_address_to_resource(node, i, &res))
@@ -340,17 +379,19 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
 	}
 
 	/* the external interrupts are optional and xway only */
-	eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu");
+	eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
 	if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
 		/* find out how many external irq sources we have */
-		const __be32 *count = of_get_property(node,
-							"lantiq,count", NULL);
+		exin_avail = of_irq_count(eiu_node);
 
-		if (count)
-			exin_avail = *count;
 		if (exin_avail > MAX_EIU)
 			exin_avail = MAX_EIU;
 
+		ret = of_irq_to_resource_table(eiu_node,
+						ltq_eiu_irq, exin_avail);
+		if (ret != exin_avail)
+			panic("failed to load external irq resources\n");
+
 		if (request_mem_region(res.start, resource_size(&res),
 							res.name) < 0)
 			pr_err("Failed to request eiu memory");
diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
index 9aa17f79a742..1ab576dc9bd1 100644
--- a/arch/mips/lantiq/xway/clk.c
+++ b/arch/mips/lantiq/xway/clk.c
@@ -53,6 +53,29 @@ unsigned long ltq_danube_cpu_hz(void)
 	}
 }
 
+unsigned long ltq_danube_pp32_hz(void)
+{
+	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 7) & 3;
+	unsigned long clk;
+
+	switch (clksys) {
+	case 1:
+		clk = CLOCK_240M;
+		break;
+	case 2:
+		clk = CLOCK_222M;
+		break;
+	case 3:
+		clk = CLOCK_133M;
+		break;
+	default:
+		clk = CLOCK_266M;
+		break;
+	}
+
+	return clk;
+}
+
 unsigned long ltq_ar9_sys_hz(void)
 {
 	if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2)
@@ -149,3 +172,23 @@ unsigned long ltq_vr9_fpi_hz(void)
 
 	return clk;
 }
+
+unsigned long ltq_vr9_pp32_hz(void)
+{
+	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3;
+	unsigned long clk;
+
+	switch (clksys) {
+	case 1:
+		clk = CLOCK_450M;
+		break;
+	case 2:
+		clk = CLOCK_300M;
+		break;
+	default:
+		clk = CLOCK_500M;
+		break;
+	}
+
+	return clk;
+}
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 544dbb7fb421..1fa0f175357e 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -78,10 +78,19 @@ static struct ltq_xrx200_gphy_reset {
 /* reset and boot a gphy. these phys only exist on xrx200 SoC */
 int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
 {
+	struct clk *clk;
+
 	if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
 		dev_err(dev, "this SoC has no GPHY\n");
 		return -EINVAL;
 	}
+
+	clk = clk_get_sys("1f203000.rcu", "gphy");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	clk_enable(clk);
+
 	if (id > 1) {
 		dev_err(dev, "%u is an invalid gphy id\n", id);
 		return -EINVAL;
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 3925e6609acc..c24924fe087d 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -305,7 +305,7 @@ void __init ltq_soc_init(void)
 
 	/* check if all the core register ranges are available */
 	if (!np_pmu || !np_cgu || !np_ebu)
-		panic("Failed to load core nodess from devicetree");
+		panic("Failed to load core nodes from devicetree");
 
 	if (of_address_to_resource(np_pmu, 0, &res_pmu) ||
 			of_address_to_resource(np_cgu, 0, &res_cgu) ||
@@ -356,14 +356,16 @@ void __init ltq_soc_init(void)
 
 	if (of_machine_is_compatible("lantiq,ase")) {
 		if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
-			clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
+			clkdev_add_static(CLOCK_266M, CLOCK_133M,
+						CLOCK_133M, CLOCK_266M);
 		else
-			clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
+			clkdev_add_static(CLOCK_133M, CLOCK_133M,
+						CLOCK_133M, CLOCK_133M);
 		clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
 		clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
 	} else if (of_machine_is_compatible("lantiq,vr9")) {
 		clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
-				ltq_vr9_fpi_hz());
+				ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz());
 		clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
 		clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
 		clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
@@ -374,12 +376,13 @@ void __init ltq_soc_init(void)
 				PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
 				PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
 				PMU_PPE_QSB | PMU_PPE_TOP);
+		clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY);
 	} else if (of_machine_is_compatible("lantiq,ar9")) {
 		clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
-				ltq_ar9_fpi_hz());
+				ltq_ar9_fpi_hz(), CLOCK_250M);
 		clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
 	} else {
 		clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
-				ltq_danube_fpi_hz());
+				ltq_danube_fpi_hz(), ltq_danube_pp32_hz());
 	}
 }