diff options
Diffstat (limited to 'kernel/arch/mips/jz4740')
-rw-r--r-- | kernel/arch/mips/jz4740/Kconfig | 17 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/Makefile | 8 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/Platform | 8 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/board-qi_lb60.c | 21 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/clock-debugfs.c | 108 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/clock.c | 924 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/clock.h | 76 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/gpio.c | 34 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/irq.c | 162 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/irq.h | 23 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/platform.c | 38 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/pm.c | 2 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/prom.c | 13 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/reset.c | 13 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/serial.c | 33 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/serial.h | 23 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/setup.c | 36 | ||||
-rw-r--r-- | kernel/arch/mips/jz4740/time.c | 65 |
18 files changed, 140 insertions, 1464 deletions
diff --git a/kernel/arch/mips/jz4740/Kconfig b/kernel/arch/mips/jz4740/Kconfig index 468903053..36f820176 100644 --- a/kernel/arch/mips/jz4740/Kconfig +++ b/kernel/arch/mips/jz4740/Kconfig @@ -1,9 +1,24 @@ choice prompt "Machine type" - depends on MACH_JZ4740 + depends on MACH_INGENIC default JZ4740_QI_LB60 config JZ4740_QI_LB60 bool "Qi Hardware Ben NanoNote" + select MACH_JZ4740 + +config JZ4780_CI20 + bool "MIPS Creator CI20" + select MACH_JZ4780 endchoice + +config MACH_JZ4740 + bool + select SYS_HAS_CPU_MIPS32_R1 + +config MACH_JZ4780 + bool + select MIPS_CPU_SCACHE + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_HIGHMEM diff --git a/kernel/arch/mips/jz4740/Makefile b/kernel/arch/mips/jz4740/Makefile index 28e5535df..39d70bde8 100644 --- a/kernel/arch/mips/jz4740/Makefile +++ b/kernel/arch/mips/jz4740/Makefile @@ -4,10 +4,12 @@ # Object file lists. -obj-y += prom.o irq.o time.o reset.o setup.o \ - gpio.o clock.o platform.o timer.o serial.o +obj-y += prom.o time.o reset.o setup.o \ + platform.o timer.o -obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o +obj-$(CONFIG_MACH_JZ4740) += gpio.o + +CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt # board specific support diff --git a/kernel/arch/mips/jz4740/Platform b/kernel/arch/mips/jz4740/Platform index c41d30080..28448d358 100644 --- a/kernel/arch/mips/jz4740/Platform +++ b/kernel/arch/mips/jz4740/Platform @@ -1,4 +1,4 @@ -platform-$(CONFIG_MACH_JZ4740) += jz4740/ -cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 -load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 -zload-$(CONFIG_MACH_JZ4740) += 0xffffffff80600000 +platform-$(CONFIG_MACH_INGENIC) += jz4740/ +cflags-$(CONFIG_MACH_INGENIC) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 +load-$(CONFIG_MACH_INGENIC) += 0xffffffff80010000 +zload-$(CONFIG_MACH_INGENIC) += 0xffffffff80600000 diff --git a/kernel/arch/mips/jz4740/board-qi_lb60.c b/kernel/arch/mips/jz4740/board-qi_lb60.c index 9dd051edb..934b15b5b 100644 --- a/kernel/arch/mips/jz4740/board-qi_lb60.c +++ b/kernel/arch/mips/jz4740/board-qi_lb60.c @@ -25,7 +25,9 @@ #include <linux/power_supply.h> #include <linux/power/jz4740-battery.h> #include <linux/power/gpio-charger.h> +#include <linux/pwm.h> +#include <asm/mach-jz4740/gpio.h> #include <asm/mach-jz4740/jz4740_fb.h> #include <asm/mach-jz4740/jz4740_mmc.h> #include <asm/mach-jz4740/jz4740_nand.h> @@ -33,8 +35,6 @@ #include <linux/regulator/fixed.h> #include <linux/regulator/machine.h> -#include <linux/leds_pwm.h> - #include <asm/mach-jz4740/platform.h> #include "clock.h" @@ -398,13 +398,15 @@ static struct platform_device avt2_usb_regulator_device = { } }; +static struct pwm_lookup qi_lb60_pwm_lookup[] = { + PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0, + PWM_POLARITY_NORMAL), +}; + /* beeper */ static struct platform_device qi_lb60_pwm_beeper = { .name = "pwm-beeper", .id = -1, - .dev = { - .platform_data = (void *)4, - }, }; /* charger */ @@ -482,8 +484,6 @@ static int __init qi_lb60_init_platform_devices(void) gpiod_add_lookup_table(&qi_lb60_audio_gpio_table); gpiod_add_lookup_table(&qi_lb60_nand_gpio_table); - jz4740_serial_device_register(); - spi_register_board_info(qi_lb60_spi_board_info, ARRAY_SIZE(qi_lb60_spi_board_info)); @@ -492,16 +492,13 @@ static int __init qi_lb60_init_platform_devices(void) platform_device_register(&jz4740_usb_ohci_device); } + pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup)); + return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices)); } -struct jz4740_clock_board_data jz4740_clock_bdata = { - .ext_rate = 12000000, - .rtc_rate = 32768, -}; - static __init int board_avt2(char *str) { qi_lb60_mmc_pdata.card_detect_active_low = 1; diff --git a/kernel/arch/mips/jz4740/clock-debugfs.c b/kernel/arch/mips/jz4740/clock-debugfs.c deleted file mode 100644 index 325422d0d..000000000 --- a/kernel/arch/mips/jz4740/clock-debugfs.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 SoC clock support debugfs entries - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/clk.h> -#include <linux/err.h> - -#include <linux/debugfs.h> -#include <linux/uaccess.h> - -#include <asm/mach-jz4740/clock.h> -#include "clock.h" - -static struct dentry *jz4740_clock_debugfs; - -static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value) -{ - struct clk *clk = data; - *value = clk_is_enabled(clk); - - return 0; -} - -static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value) -{ - struct clk *clk = data; - - if (value) - return clk_enable(clk); - else - clk_disable(clk); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled, - jz4740_clock_debugfs_show_enabled, - jz4740_clock_debugfs_set_enabled, - "%llu\n"); - -static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value) -{ - struct clk *clk = data; - *value = clk_get_rate(clk); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate, - jz4740_clock_debugfs_show_rate, - NULL, - "%llu\n"); - -void jz4740_clock_debugfs_add_clk(struct clk *clk) -{ - if (!jz4740_clock_debugfs) - return; - - clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs); - debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk, - &jz4740_clock_debugfs_ops_rate); - debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk, - &jz4740_clock_debugfs_ops_enabled); - - if (clk->parent) { - char parent_path[100]; - snprintf(parent_path, 100, "../%s", clk->parent->name); - clk->debugfs_parent_entry = debugfs_create_symlink("parent", - clk->debugfs_entry, - parent_path); - } -} - -/* TODO: Locking */ -void jz4740_clock_debugfs_update_parent(struct clk *clk) -{ - debugfs_remove(clk->debugfs_parent_entry); - - if (clk->parent) { - char parent_path[100]; - snprintf(parent_path, 100, "../%s", clk->parent->name); - clk->debugfs_parent_entry = debugfs_create_symlink("parent", - clk->debugfs_entry, - parent_path); - } else { - clk->debugfs_parent_entry = NULL; - } -} - -void jz4740_clock_debugfs_init(void) -{ - jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL); - if (IS_ERR(jz4740_clock_debugfs)) - jz4740_clock_debugfs = NULL; -} diff --git a/kernel/arch/mips/jz4740/clock.c b/kernel/arch/mips/jz4740/clock.c deleted file mode 100644 index 1b5f55426..000000000 --- a/kernel/arch/mips/jz4740/clock.c +++ /dev/null @@ -1,924 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 SoC clock support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/clk.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/list.h> -#include <linux/err.h> - -#include <asm/mach-jz4740/clock.h> -#include <asm/mach-jz4740/base.h> - -#include "clock.h" - -#define JZ_REG_CLOCK_CTRL 0x00 -#define JZ_REG_CLOCK_LOW_POWER 0x04 -#define JZ_REG_CLOCK_PLL 0x10 -#define JZ_REG_CLOCK_GATE 0x20 -#define JZ_REG_CLOCK_SLEEP_CTRL 0x24 -#define JZ_REG_CLOCK_I2S 0x60 -#define JZ_REG_CLOCK_LCD 0x64 -#define JZ_REG_CLOCK_MMC 0x68 -#define JZ_REG_CLOCK_UHC 0x6C -#define JZ_REG_CLOCK_SPI 0x74 - -#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31) -#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30) -#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29) -#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000 -#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22) -#define JZ_CLOCK_CTRL_PLL_HALF BIT(21) -#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000 -#define JZ_CLOCK_CTRL_UDIV_OFFSET 23 -#define JZ_CLOCK_CTRL_LDIV_OFFSET 16 -#define JZ_CLOCK_CTRL_MDIV_OFFSET 12 -#define JZ_CLOCK_CTRL_PDIV_OFFSET 8 -#define JZ_CLOCK_CTRL_HDIV_OFFSET 4 -#define JZ_CLOCK_CTRL_CDIV_OFFSET 0 - -#define JZ_CLOCK_GATE_UART0 BIT(0) -#define JZ_CLOCK_GATE_TCU BIT(1) -#define JZ_CLOCK_GATE_RTC BIT(2) -#define JZ_CLOCK_GATE_I2C BIT(3) -#define JZ_CLOCK_GATE_SPI BIT(4) -#define JZ_CLOCK_GATE_AIC BIT(5) -#define JZ_CLOCK_GATE_I2S BIT(6) -#define JZ_CLOCK_GATE_MMC BIT(7) -#define JZ_CLOCK_GATE_ADC BIT(8) -#define JZ_CLOCK_GATE_CIM BIT(9) -#define JZ_CLOCK_GATE_LCD BIT(10) -#define JZ_CLOCK_GATE_UDC BIT(11) -#define JZ_CLOCK_GATE_DMAC BIT(12) -#define JZ_CLOCK_GATE_IPU BIT(13) -#define JZ_CLOCK_GATE_UHC BIT(14) -#define JZ_CLOCK_GATE_UART1 BIT(15) - -#define JZ_CLOCK_I2S_DIV_MASK 0x01ff - -#define JZ_CLOCK_LCD_DIV_MASK 0x01ff - -#define JZ_CLOCK_MMC_DIV_MASK 0x001f - -#define JZ_CLOCK_UHC_DIV_MASK 0x000f - -#define JZ_CLOCK_SPI_SRC_PLL BIT(31) -#define JZ_CLOCK_SPI_DIV_MASK 0x000f - -#define JZ_CLOCK_PLL_M_MASK 0x01ff -#define JZ_CLOCK_PLL_N_MASK 0x001f -#define JZ_CLOCK_PLL_OD_MASK 0x0003 -#define JZ_CLOCK_PLL_STABLE BIT(10) -#define JZ_CLOCK_PLL_BYPASS BIT(9) -#define JZ_CLOCK_PLL_ENABLED BIT(8) -#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f -#define JZ_CLOCK_PLL_M_OFFSET 23 -#define JZ_CLOCK_PLL_N_OFFSET 18 -#define JZ_CLOCK_PLL_OD_OFFSET 16 - -#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2) -#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0) - -#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7) -#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6) - -static void __iomem *jz_clock_base; -static spinlock_t jz_clock_lock; -static LIST_HEAD(jz_clocks); - -struct main_clk { - struct clk clk; - uint32_t div_offset; -}; - -struct divided_clk { - struct clk clk; - uint32_t reg; - uint32_t mask; -}; - -struct static_clk { - struct clk clk; - unsigned long rate; -}; - -static uint32_t jz_clk_reg_read(int reg) -{ - return readl(jz_clock_base + reg); -} - -static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask) -{ - uint32_t val2; - - spin_lock(&jz_clock_lock); - val2 = readl(jz_clock_base + reg); - val2 &= ~mask; - val2 |= val; - writel(val2, jz_clock_base + reg); - spin_unlock(&jz_clock_lock); -} - -static void jz_clk_reg_set_bits(int reg, uint32_t mask) -{ - uint32_t val; - - spin_lock(&jz_clock_lock); - val = readl(jz_clock_base + reg); - val |= mask; - writel(val, jz_clock_base + reg); - spin_unlock(&jz_clock_lock); -} - -static void jz_clk_reg_clear_bits(int reg, uint32_t mask) -{ - uint32_t val; - - spin_lock(&jz_clock_lock); - val = readl(jz_clock_base + reg); - val &= ~mask; - writel(val, jz_clock_base + reg); - spin_unlock(&jz_clock_lock); -} - -static int jz_clk_enable_gating(struct clk *clk) -{ - if (clk->gate_bit == JZ4740_CLK_NOT_GATED) - return -EINVAL; - - jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); - return 0; -} - -static int jz_clk_disable_gating(struct clk *clk) -{ - if (clk->gate_bit == JZ4740_CLK_NOT_GATED) - return -EINVAL; - - jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); - return 0; -} - -static int jz_clk_is_enabled_gating(struct clk *clk) -{ - if (clk->gate_bit == JZ4740_CLK_NOT_GATED) - return 1; - - return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit); -} - -static unsigned long jz_clk_static_get_rate(struct clk *clk) -{ - return ((struct static_clk *)clk)->rate; -} - -static int jz_clk_ko_enable(struct clk *clk) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); - return 0; -} - -static int jz_clk_ko_disable(struct clk *clk) -{ - jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); - return 0; -} - -static int jz_clk_ko_is_enabled(struct clk *clk) -{ - return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE); -} - -static const int pllno[] = {1, 2, 2, 4}; - -static unsigned long jz_clk_pll_get_rate(struct clk *clk) -{ - uint32_t val; - int m; - int n; - int od; - - val = jz_clk_reg_read(JZ_REG_CLOCK_PLL); - - if (val & JZ_CLOCK_PLL_BYPASS) - return clk_get_rate(clk->parent); - - m = ((val >> 23) & 0x1ff) + 2; - n = ((val >> 18) & 0x1f) + 2; - od = (val >> 16) & 0x3; - - return ((clk_get_rate(clk->parent) / n) * m) / pllno[od]; -} - -static unsigned long jz_clk_pll_half_get_rate(struct clk *clk) -{ - uint32_t reg; - - reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); - if (reg & JZ_CLOCK_CTRL_PLL_HALF) - return jz_clk_pll_get_rate(clk->parent); - return jz_clk_pll_get_rate(clk->parent) >> 1; -} - -static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; - -static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); - int div; - - div = parent_rate / rate; - if (div > 32) - return parent_rate / 32; - else if (div < 1) - return parent_rate; - - div &= (0x3 << (ffs(div) - 1)); - - return parent_rate / div; -} - -static unsigned long jz_clk_main_get_rate(struct clk *clk) -{ - struct main_clk *mclk = (struct main_clk *)clk; - uint32_t div; - - div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); - - div >>= mclk->div_offset; - div &= 0xf; - - if (div >= ARRAY_SIZE(jz_clk_main_divs)) - div = ARRAY_SIZE(jz_clk_main_divs) - 1; - - return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div]; -} - -static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate) -{ - struct main_clk *mclk = (struct main_clk *)clk; - int i; - int div; - unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); - - rate = jz_clk_main_round_rate(clk, rate); - - div = parent_rate / rate; - - i = (ffs(div) - 1) << 1; - if (i > 0 && !(div & BIT(i-1))) - i -= 1; - - jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset, - 0xf << mclk->div_offset); - - return 0; -} - -static struct clk_ops jz_clk_static_ops = { - .get_rate = jz_clk_static_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct static_clk jz_clk_ext = { - .clk = { - .name = "ext", - .gate_bit = JZ4740_CLK_NOT_GATED, - .ops = &jz_clk_static_ops, - }, -}; - -static struct clk_ops jz_clk_pll_ops = { - .get_rate = jz_clk_pll_get_rate, -}; - -static struct clk jz_clk_pll = { - .name = "pll", - .parent = &jz_clk_ext.clk, - .ops = &jz_clk_pll_ops, -}; - -static struct clk_ops jz_clk_pll_half_ops = { - .get_rate = jz_clk_pll_half_get_rate, -}; - -static struct clk jz_clk_pll_half = { - .name = "pll half", - .parent = &jz_clk_pll, - .ops = &jz_clk_pll_half_ops, -}; - -static const struct clk_ops jz_clk_main_ops = { - .get_rate = jz_clk_main_get_rate, - .set_rate = jz_clk_main_set_rate, - .round_rate = jz_clk_main_round_rate, -}; - -static struct main_clk jz_clk_cpu = { - .clk = { - .name = "cclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET, -}; - -static struct main_clk jz_clk_memory = { - .clk = { - .name = "mclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET, -}; - -static struct main_clk jz_clk_high_speed_peripheral = { - .clk = { - .name = "hclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET, -}; - - -static struct main_clk jz_clk_low_speed_peripheral = { - .clk = { - .name = "pclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET, -}; - -static const struct clk_ops jz_clk_ko_ops = { - .enable = jz_clk_ko_enable, - .disable = jz_clk_ko_disable, - .is_enabled = jz_clk_ko_is_enabled, -}; - -static struct clk jz_clk_ko = { - .name = "cko", - .parent = &jz_clk_memory.clk, - .ops = &jz_clk_ko_ops, -}; - -static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent) -{ - if (parent == &jz_clk_pll) - jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); - else if (parent == &jz_clk_ext.clk) - jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); - else - return -EINVAL; - - clk->parent = parent; - - return 0; -} - -static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent) -{ - if (parent == &jz_clk_pll_half) - jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); - else if (parent == &jz_clk_ext.clk) - jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); - else - return -EINVAL; - - clk->parent = parent; - - return 0; -} - -static int jz_clk_udc_enable(struct clk *clk) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL, - JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); - - return 0; -} - -static int jz_clk_udc_disable(struct clk *clk) -{ - jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL, - JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); - - return 0; -} - -static int jz_clk_udc_is_enabled(struct clk *clk) -{ - return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) & - JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); -} - -static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent) -{ - if (parent == &jz_clk_pll_half) - jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); - else if (parent == &jz_clk_ext.clk) - jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); - else - return -EINVAL; - - clk->parent = parent; - - return 0; -} - -static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate) -{ - int div; - - if (clk->parent == &jz_clk_ext.clk) - return -EINVAL; - - div = clk_get_rate(clk->parent) / rate - 1; - - if (div < 0) - div = 0; - else if (div > 63) - div = 63; - - jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET, - JZ_CLOCK_CTRL_UDIV_MASK); - return 0; -} - -static unsigned long jz_clk_udc_get_rate(struct clk *clk) -{ - int div; - - if (clk->parent == &jz_clk_ext.clk) - return clk_get_rate(clk->parent); - - div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK); - div >>= JZ_CLOCK_CTRL_UDIV_OFFSET; - div += 1; - - return clk_get_rate(clk->parent) / div; -} - -static unsigned long jz_clk_divided_get_rate(struct clk *clk) -{ - struct divided_clk *dclk = (struct divided_clk *)clk; - int div; - - if (clk->parent == &jz_clk_ext.clk) - return clk_get_rate(clk->parent); - - div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1; - - return clk_get_rate(clk->parent) / div; -} - -static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate) -{ - struct divided_clk *dclk = (struct divided_clk *)clk; - int div; - - if (clk->parent == &jz_clk_ext.clk) - return -EINVAL; - - div = clk_get_rate(clk->parent) / rate - 1; - - if (div < 0) - div = 0; - else if (div > dclk->mask) - div = dclk->mask; - - jz_clk_reg_write_mask(dclk->reg, div, dclk->mask); - - return 0; -} - -static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate) -{ - int div; - unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent); - - if (rate > 150000000) - return 150000000; - - div = parent_rate / rate; - if (div < 1) - div = 1; - else if (div > 32) - div = 32; - - return parent_rate / div; -} - -static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate) -{ - int div; - - if (rate > 150000000) - return -EINVAL; - - div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1; - if (div < 0) - div = 0; - else if (div > 31) - div = 31; - - jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET, - JZ_CLOCK_CTRL_LDIV_MASK); - - return 0; -} - -static unsigned long jz_clk_ldclk_get_rate(struct clk *clk) -{ - int div; - - div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK; - div >>= JZ_CLOCK_CTRL_LDIV_OFFSET; - - return jz_clk_pll_half_get_rate(clk->parent) / (div + 1); -} - -static const struct clk_ops jz_clk_ops_ld = { - .set_rate = jz_clk_ldclk_set_rate, - .get_rate = jz_clk_ldclk_get_rate, - .round_rate = jz_clk_ldclk_round_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct clk jz_clk_ld = { - .name = "lcd", - .gate_bit = JZ_CLOCK_GATE_LCD, - .parent = &jz_clk_pll_half, - .ops = &jz_clk_ops_ld, -}; - -static const struct clk_ops jz_clk_i2s_ops = { - .set_rate = jz_clk_divided_set_rate, - .get_rate = jz_clk_divided_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, - .set_parent = jz_clk_i2s_set_parent, -}; - -static const struct clk_ops jz_clk_spi_ops = { - .set_rate = jz_clk_divided_set_rate, - .get_rate = jz_clk_divided_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, - .set_parent = jz_clk_spi_set_parent, -}; - -static const struct clk_ops jz_clk_divided_ops = { - .set_rate = jz_clk_divided_set_rate, - .get_rate = jz_clk_divided_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct divided_clk jz4740_clock_divided_clks[] = { - [0] = { - .clk = { - .name = "i2s", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_I2S, - .ops = &jz_clk_i2s_ops, - }, - .reg = JZ_REG_CLOCK_I2S, - .mask = JZ_CLOCK_I2S_DIV_MASK, - }, - [1] = { - .clk = { - .name = "spi", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_SPI, - .ops = &jz_clk_spi_ops, - }, - .reg = JZ_REG_CLOCK_SPI, - .mask = JZ_CLOCK_SPI_DIV_MASK, - }, - [2] = { - .clk = { - .name = "lcd_pclk", - .parent = &jz_clk_pll_half, - .gate_bit = JZ4740_CLK_NOT_GATED, - .ops = &jz_clk_divided_ops, - }, - .reg = JZ_REG_CLOCK_LCD, - .mask = JZ_CLOCK_LCD_DIV_MASK, - }, - [3] = { - .clk = { - .name = "mmc", - .parent = &jz_clk_pll_half, - .gate_bit = JZ_CLOCK_GATE_MMC, - .ops = &jz_clk_divided_ops, - }, - .reg = JZ_REG_CLOCK_MMC, - .mask = JZ_CLOCK_MMC_DIV_MASK, - }, - [4] = { - .clk = { - .name = "uhc", - .parent = &jz_clk_pll_half, - .gate_bit = JZ_CLOCK_GATE_UHC, - .ops = &jz_clk_divided_ops, - }, - .reg = JZ_REG_CLOCK_UHC, - .mask = JZ_CLOCK_UHC_DIV_MASK, - }, -}; - -static const struct clk_ops jz_clk_udc_ops = { - .set_parent = jz_clk_udc_set_parent, - .set_rate = jz_clk_udc_set_rate, - .get_rate = jz_clk_udc_get_rate, - .enable = jz_clk_udc_enable, - .disable = jz_clk_udc_disable, - .is_enabled = jz_clk_udc_is_enabled, -}; - -static const struct clk_ops jz_clk_simple_ops = { - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct clk jz4740_clock_simple_clks[] = { - [0] = { - .name = "udc", - .parent = &jz_clk_ext.clk, - .ops = &jz_clk_udc_ops, - }, - [1] = { - .name = "uart0", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_UART0, - .ops = &jz_clk_simple_ops, - }, - [2] = { - .name = "uart1", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_UART1, - .ops = &jz_clk_simple_ops, - }, - [3] = { - .name = "dma", - .parent = &jz_clk_high_speed_peripheral.clk, - .gate_bit = JZ_CLOCK_GATE_DMAC, - .ops = &jz_clk_simple_ops, - }, - [4] = { - .name = "ipu", - .parent = &jz_clk_high_speed_peripheral.clk, - .gate_bit = JZ_CLOCK_GATE_IPU, - .ops = &jz_clk_simple_ops, - }, - [5] = { - .name = "adc", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_ADC, - .ops = &jz_clk_simple_ops, - }, - [6] = { - .name = "i2c", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_I2C, - .ops = &jz_clk_simple_ops, - }, - [7] = { - .name = "aic", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_AIC, - .ops = &jz_clk_simple_ops, - }, -}; - -static struct static_clk jz_clk_rtc = { - .clk = { - .name = "rtc", - .gate_bit = JZ_CLOCK_GATE_RTC, - .ops = &jz_clk_static_ops, - }, - .rate = 32768, -}; - -int clk_enable(struct clk *clk) -{ - if (!clk->ops->enable) - return -EINVAL; - - return clk->ops->enable(clk); -} -EXPORT_SYMBOL_GPL(clk_enable); - -void clk_disable(struct clk *clk) -{ - if (clk->ops->disable) - clk->ops->disable(clk); -} -EXPORT_SYMBOL_GPL(clk_disable); - -int clk_is_enabled(struct clk *clk) -{ - if (clk->ops->is_enabled) - return clk->ops->is_enabled(clk); - - return 1; -} - -unsigned long clk_get_rate(struct clk *clk) -{ - if (clk->ops->get_rate) - return clk->ops->get_rate(clk); - if (clk->parent) - return clk_get_rate(clk->parent); - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - if (!clk->ops->set_rate) - return -EINVAL; - return clk->ops->set_rate(clk, rate); -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (clk->ops->round_rate) - return clk->ops->round_rate(clk, rate); - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - int ret; - int enabled; - - if (!clk->ops->set_parent) - return -EINVAL; - - enabled = clk_is_enabled(clk); - if (enabled) - clk_disable(clk); - ret = clk->ops->set_parent(clk, parent); - if (enabled) - clk_enable(clk); - - jz4740_clock_debugfs_update_parent(clk); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -struct clk *clk_get(struct device *dev, const char *name) -{ - struct clk *clk; - - list_for_each_entry(clk, &jz_clocks, list) { - if (strcmp(clk->name, name) == 0) - return clk; - } - return ERR_PTR(-ENXIO); -} -EXPORT_SYMBOL_GPL(clk_get); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL_GPL(clk_put); - -static inline void clk_add(struct clk *clk) -{ - list_add_tail(&clk->list, &jz_clocks); - - jz4740_clock_debugfs_add_clk(clk); -} - -static void clk_register_clks(void) -{ - size_t i; - - clk_add(&jz_clk_ext.clk); - clk_add(&jz_clk_pll); - clk_add(&jz_clk_pll_half); - clk_add(&jz_clk_cpu.clk); - clk_add(&jz_clk_high_speed_peripheral.clk); - clk_add(&jz_clk_low_speed_peripheral.clk); - clk_add(&jz_clk_ko); - clk_add(&jz_clk_ld); - clk_add(&jz_clk_rtc.clk); - - for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i) - clk_add(&jz4740_clock_divided_clks[i].clk); - - for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i) - clk_add(&jz4740_clock_simple_clks[i]); -} - -void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode) -{ - switch (mode) { - case JZ4740_WAIT_MODE_IDLE: - jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); - break; - case JZ4740_WAIT_MODE_SLEEP: - jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); - break; - } -} - -void jz4740_clock_udc_disable_auto_suspend(void) -{ - jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); -} -EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend); - -void jz4740_clock_udc_enable_auto_suspend(void) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); -} -EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); - -void jz4740_clock_suspend(void) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, - JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); - - jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); -} - -void jz4740_clock_resume(void) -{ - uint32_t pll; - - jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); - - do { - pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL); - } while (!(pll & JZ_CLOCK_PLL_STABLE)); - - jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, - JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); -} - -static int jz4740_clock_init(void) -{ - uint32_t val; - - jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100); - if (!jz_clock_base) - return -EBUSY; - - spin_lock_init(&jz_clock_lock); - - jz_clk_ext.rate = jz4740_clock_bdata.ext_rate; - jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate; - - val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); - - if (val & JZ_CLOCK_SPI_SRC_PLL) - jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half; - - val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); - - if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) - jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half; - - if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) - jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half; - - jz4740_clock_debugfs_init(); - - clk_register_clks(); - - return 0; -} -arch_initcall(jz4740_clock_init); diff --git a/kernel/arch/mips/jz4740/clock.h b/kernel/arch/mips/jz4740/clock.h deleted file mode 100644 index 5d07499d7..000000000 --- a/kernel/arch/mips/jz4740/clock.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 SoC clock support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __MIPS_JZ4740_CLOCK_H__ -#define __MIPS_JZ4740_CLOCK_H__ - -#include <linux/list.h> - -struct jz4740_clock_board_data { - unsigned long ext_rate; - unsigned long rtc_rate; -}; - -extern struct jz4740_clock_board_data jz4740_clock_bdata; - -void jz4740_clock_suspend(void); -void jz4740_clock_resume(void); - -struct clk; - -struct clk_ops { - unsigned long (*get_rate)(struct clk *clk); - unsigned long (*round_rate)(struct clk *clk, unsigned long rate); - int (*set_rate)(struct clk *clk, unsigned long rate); - int (*enable)(struct clk *clk); - int (*disable)(struct clk *clk); - int (*is_enabled)(struct clk *clk); - - int (*set_parent)(struct clk *clk, struct clk *parent); - -}; - -struct clk { - const char *name; - struct clk *parent; - - uint32_t gate_bit; - - const struct clk_ops *ops; - - struct list_head list; - -#ifdef CONFIG_DEBUG_FS - struct dentry *debugfs_entry; - struct dentry *debugfs_parent_entry; -#endif - -}; - -#define JZ4740_CLK_NOT_GATED ((uint32_t)-1) - -int clk_is_enabled(struct clk *clk); - -#ifdef CONFIG_DEBUG_FS -void jz4740_clock_debugfs_init(void); -void jz4740_clock_debugfs_add_clk(struct clk *clk); -void jz4740_clock_debugfs_update_parent(struct clk *clk); -#else -static inline void jz4740_clock_debugfs_init(void) {}; -static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {}; -static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {}; -#endif - -#endif diff --git a/kernel/arch/mips/jz4740/gpio.c b/kernel/arch/mips/jz4740/gpio.c index 00b798d2f..8c6d76c9b 100644 --- a/kernel/arch/mips/jz4740/gpio.c +++ b/kernel/arch/mips/jz4740/gpio.c @@ -21,14 +21,14 @@ #include <linux/gpio.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/irqchip/ingenic.h> #include <linux/bitops.h> #include <linux/debugfs.h> #include <linux/seq_file.h> #include <asm/mach-jz4740/base.h> - -#include "irq.h" +#include <asm/mach-jz4740/gpio.h> #define JZ4740_GPIO_BASE_A (32*0) #define JZ4740_GPIO_BASE_B (32*1) @@ -232,6 +232,13 @@ static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) return 0; } +static int jz_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ + struct jz_gpio_chip *jz_gpio = gpio_chip_to_jz_gpio_chip(chip); + + return jz_gpio->irq_base + gpio; +} + int jz_gpio_port_direction_input(int port, uint32_t mask) { writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR)); @@ -263,18 +270,6 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask) } EXPORT_SYMBOL(jz_gpio_port_get_value); -int gpio_to_irq(unsigned gpio) -{ - return JZ4740_IRQ_GPIO(0) + gpio; -} -EXPORT_SYMBOL_GPL(gpio_to_irq); - -int irq_to_gpio(unsigned irq) -{ - return irq - JZ4740_IRQ_GPIO(0); -} -EXPORT_SYMBOL_GPL(irq_to_gpio); - #define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f) static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq) @@ -297,7 +292,7 @@ static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int i writel(mask, reg); } -static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc) +static void jz_gpio_irq_demux_handler(struct irq_desc *desc) { uint32_t flag; unsigned int gpio_irq; @@ -404,6 +399,7 @@ static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on) .get = jz_gpio_get_value, \ .direction_output = jz_gpio_direction_output, \ .direction_input = jz_gpio_direction_input, \ + .to_irq = jz_gpio_to_irq, \ .base = JZ4740_GPIO_BASE_ ## _bank, \ .ngpio = JZ4740_GPIO_NUM_ ## _bank, \ }, \ @@ -424,8 +420,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); chip->irq = JZ4740_IRQ_INTC_GPIO(id); - irq_set_handler_data(chip->irq, chip); - irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler); + irq_set_chained_handler_and_data(chip->irq, + jz_gpio_irq_demux_handler, chip); gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base, chip->base, handle_level_irq); @@ -442,8 +438,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) ct->chip.irq_mask = irq_gc_mask_disable_reg; ct->chip.irq_unmask = jz_gpio_irq_unmask; ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_suspend = jz4740_irq_suspend; - ct->chip.irq_resume = jz4740_irq_resume; + ct->chip.irq_suspend = ingenic_intc_irq_suspend; + ct->chip.irq_resume = ingenic_intc_irq_resume; ct->chip.irq_startup = jz_gpio_irq_startup; ct->chip.irq_shutdown = jz_gpio_irq_shutdown; ct->chip.irq_set_type = jz_gpio_irq_set_type; diff --git a/kernel/arch/mips/jz4740/irq.c b/kernel/arch/mips/jz4740/irq.c deleted file mode 100644 index 97206b3de..000000000 --- a/kernel/arch/mips/jz4740/irq.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 platform IRQ support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/delay.h> - -#include <linux/debugfs.h> -#include <linux/seq_file.h> - -#include <asm/io.h> -#include <asm/mipsregs.h> -#include <asm/irq_cpu.h> - -#include <asm/mach-jz4740/base.h> -#include <asm/mach-jz4740/irq.h> - -#include "irq.h" - -static void __iomem *jz_intc_base; - -#define JZ_REG_INTC_STATUS 0x00 -#define JZ_REG_INTC_MASK 0x04 -#define JZ_REG_INTC_SET_MASK 0x08 -#define JZ_REG_INTC_CLEAR_MASK 0x0c -#define JZ_REG_INTC_PENDING 0x10 - -static irqreturn_t jz4740_cascade(int irq, void *data) -{ - uint32_t irq_reg; - - irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING); - - if (irq_reg) - generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE); - - return IRQ_HANDLED; -} - -static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask) -{ - struct irq_chip_regs *regs = &gc->chip_types->regs; - - writel(mask, gc->reg_base + regs->enable); - writel(~mask, gc->reg_base + regs->disable); -} - -void jz4740_irq_suspend(struct irq_data *data) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); - jz4740_irq_set_mask(gc, gc->wake_active); -} - -void jz4740_irq_resume(struct irq_data *data) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); - jz4740_irq_set_mask(gc, gc->mask_cache); -} - -static struct irqaction jz4740_cascade_action = { - .handler = jz4740_cascade, - .name = "JZ4740 cascade interrupt", -}; - -void __init arch_init_irq(void) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - mips_cpu_irq_init(); - - jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14); - - /* Mask all irqs */ - writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK); - - gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base, - handle_level_irq); - - gc->wake_enabled = IRQ_MSK(32); - - ct = gc->chip_types; - ct->regs.enable = JZ_REG_INTC_CLEAR_MASK; - ct->regs.disable = JZ_REG_INTC_SET_MASK; - ct->chip.irq_unmask = irq_gc_unmask_enable_reg; - ct->chip.irq_mask = irq_gc_mask_disable_reg; - ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; - ct->chip.irq_set_wake = irq_gc_set_wake; - ct->chip.irq_suspend = jz4740_irq_suspend; - ct->chip.irq_resume = jz4740_irq_resume; - - irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL); - - setup_irq(2, &jz4740_cascade_action); -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; - if (pending & STATUSF_IP2) - do_IRQ(2); - else if (pending & STATUSF_IP3) - do_IRQ(3); - else - spurious_interrupt(); -} - -#ifdef CONFIG_DEBUG_FS - -static inline void intc_seq_reg(struct seq_file *s, const char *name, - unsigned int reg) -{ - seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg)); -} - -static int intc_regs_show(struct seq_file *s, void *unused) -{ - intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS); - intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK); - intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING); - - return 0; -} - -static int intc_regs_open(struct inode *inode, struct file *file) -{ - return single_open(file, intc_regs_show, NULL); -} - -static const struct file_operations intc_regs_operations = { - .open = intc_regs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init intc_debugfs_init(void) -{ - (void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO, - NULL, NULL, &intc_regs_operations); - return 0; -} -subsys_initcall(intc_debugfs_init); - -#endif diff --git a/kernel/arch/mips/jz4740/irq.h b/kernel/arch/mips/jz4740/irq.h deleted file mode 100644 index 0f48720b5..000000000 --- a/kernel/arch/mips/jz4740/irq.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __MIPS_JZ4740_IRQ_H__ -#define __MIPS_JZ4740_IRQ_H__ - -#include <linux/irq.h> - -extern void jz4740_irq_suspend(struct irq_data *data); -extern void jz4740_irq_resume(struct irq_data *data); - -#endif diff --git a/kernel/arch/mips/jz4740/platform.c b/kernel/arch/mips/jz4740/platform.c index 0b12f273c..e8a463b9b 100644 --- a/kernel/arch/mips/jz4740/platform.c +++ b/kernel/arch/mips/jz4740/platform.c @@ -13,6 +13,7 @@ * */ +#include <linux/clk.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/platform_device.h> @@ -29,7 +30,6 @@ #include <linux/serial_core.h> #include <linux/serial_8250.h> -#include "serial.h" #include "clock.h" /* OHCI controller */ @@ -279,42 +279,6 @@ struct platform_device jz4740_adc_device = { .resource = jz4740_adc_resources, }; -/* Serial */ -#define JZ4740_UART_DATA(_id) \ - { \ - .flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \ - .iotype = UPIO_MEM, \ - .regshift = 2, \ - .serial_out = jz4740_serial_out, \ - .type = PORT_16550, \ - .mapbase = JZ4740_UART ## _id ## _BASE_ADDR, \ - .irq = JZ4740_IRQ_UART ## _id, \ - } - -static struct plat_serial8250_port jz4740_uart_data[] = { - JZ4740_UART_DATA(0), - JZ4740_UART_DATA(1), - {}, -}; - -static struct platform_device jz4740_uart_device = { - .name = "serial8250", - .id = 0, - .dev = { - .platform_data = jz4740_uart_data, - }, -}; - -void jz4740_serial_device_register(void) -{ - struct plat_serial8250_port *p; - - for (p = jz4740_uart_data; p->flags != 0; ++p) - p->uartclk = jz4740_clock_bdata.ext_rate; - - platform_device_register(&jz4740_uart_device); -} - /* Watchdog */ static struct resource jz4740_wdt_resources[] = { { diff --git a/kernel/arch/mips/jz4740/pm.c b/kernel/arch/mips/jz4740/pm.c index d8e213010..2d8653f2f 100644 --- a/kernel/arch/mips/jz4740/pm.c +++ b/kernel/arch/mips/jz4740/pm.c @@ -20,8 +20,6 @@ #include <asm/mach-jz4740/clock.h> -#include "clock.h" - static int jz4740_pm_enter(suspend_state_t state) { jz4740_clock_suspend(); diff --git a/kernel/arch/mips/jz4740/prom.c b/kernel/arch/mips/jz4740/prom.c index 5a93f3815..6984683c9 100644 --- a/kernel/arch/mips/jz4740/prom.c +++ b/kernel/arch/mips/jz4740/prom.c @@ -53,16 +53,3 @@ void __init prom_init(void) void __init prom_free_prom_memory(void) { } - -#define UART_REG(_reg) ((void __iomem *)CKSEG1ADDR(JZ4740_UART0_BASE_ADDR + (_reg << 2))) - -void prom_putchar(char c) -{ - uint8_t lsr; - - do { - lsr = readb(UART_REG(UART_LSR)); - } while ((lsr & UART_LSR_TEMT) == 0); - - writeb(c, UART_REG(UART_TX)); -} diff --git a/kernel/arch/mips/jz4740/reset.c b/kernel/arch/mips/jz4740/reset.c index b6c6343d2..954e669c9 100644 --- a/kernel/arch/mips/jz4740/reset.c +++ b/kernel/arch/mips/jz4740/reset.c @@ -12,6 +12,7 @@ * */ +#include <linux/clk.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/pm.h> @@ -79,12 +80,20 @@ static void jz4740_power_off(void) void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38); unsigned long wakeup_filter_ticks; unsigned long reset_counter_ticks; + struct clk *rtc_clk; + unsigned long rtc_rate; + + rtc_clk = clk_get(NULL, "rtc"); + if (IS_ERR(rtc_clk)) + panic("unable to get RTC clock"); + rtc_rate = clk_get_rate(rtc_clk); + clk_put(rtc_clk); /* * Set minimum wakeup pin assertion time: 100 ms. * Range is 0 to 2 sec if RTC is clocked at 32 kHz. */ - wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000; + wakeup_filter_ticks = (100 * rtc_rate) / 1000; if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK) wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; else @@ -96,7 +105,7 @@ static void jz4740_power_off(void) * Set reset pin low-level assertion time after wakeup: 60 ms. * Range is 0 to 125 ms if RTC is clocked at 32 kHz. */ - reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000; + reset_counter_ticks = (60 * rtc_rate) / 1000; if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK) reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK; else diff --git a/kernel/arch/mips/jz4740/serial.c b/kernel/arch/mips/jz4740/serial.c deleted file mode 100644 index d23de4582..000000000 --- a/kernel/arch/mips/jz4740/serial.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 serial support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/io.h> -#include <linux/serial_core.h> -#include <linux/serial_reg.h> - -void jz4740_serial_out(struct uart_port *p, int offset, int value) -{ - switch (offset) { - case UART_FCR: - value |= 0x10; /* Enable uart module */ - break; - case UART_IER: - value |= (value & 0x4) << 2; - break; - default: - break; - } - writeb(value, p->membase + (offset << p->regshift)); -} diff --git a/kernel/arch/mips/jz4740/serial.h b/kernel/arch/mips/jz4740/serial.h deleted file mode 100644 index 8eb715bb1..000000000 --- a/kernel/arch/mips/jz4740/serial.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 serial support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __MIPS_JZ4740_SERIAL_H__ -#define __MIPS_JZ4740_SERIAL_H__ - -struct uart_port; - -void jz4740_serial_out(struct uart_port *p, int offset, int value); - -#endif diff --git a/kernel/arch/mips/jz4740/setup.c b/kernel/arch/mips/jz4740/setup.c index ef796f97b..510fc0d96 100644 --- a/kernel/arch/mips/jz4740/setup.c +++ b/kernel/arch/mips/jz4740/setup.c @@ -16,9 +16,14 @@ #include <linux/init.h> #include <linux/io.h> +#include <linux/irqchip.h> #include <linux/kernel.h> +#include <linux/libfdt.h> +#include <linux/of_fdt.h> +#include <linux/of_platform.h> #include <asm/bootinfo.h> +#include <asm/prom.h> #include <asm/mach-jz4740/base.h> @@ -51,11 +56,40 @@ static void __init jz4740_detect_mem(void) void __init plat_mem_setup(void) { + int offset; + jz4740_reset_init(); - jz4740_detect_mem(); + __dt_setup_arch(__dtb_start); + + offset = fdt_path_offset(__dtb_start, "/memory"); + if (offset < 0) + jz4740_detect_mem(); } +void __init device_tree_init(void) +{ + if (!initial_boot_params) + return; + + unflatten_and_copy_device_tree(); +} + +static int __init populate_machine(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + return 0; +} +arch_initcall(populate_machine); + const char *get_system_type(void) { + if (config_enabled(CONFIG_MACH_JZ4780)) + return "JZ4780"; + return "JZ4740"; } + +void __init arch_init_irq(void) +{ + irqchip_init(); +} diff --git a/kernel/arch/mips/jz4740/time.c b/kernel/arch/mips/jz4740/time.c index 72b0cecbc..1f7ca2c9f 100644 --- a/kernel/arch/mips/jz4740/time.c +++ b/kernel/arch/mips/jz4740/time.c @@ -13,6 +13,8 @@ * */ +#include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/time.h> @@ -20,6 +22,7 @@ #include <linux/clockchips.h> #include <linux/sched_clock.h> +#include <asm/mach-jz4740/clock.h> #include <asm/mach-jz4740/irq.h> #include <asm/mach-jz4740/timer.h> #include <asm/time.h> @@ -55,7 +58,7 @@ static irqreturn_t jz4740_clockevent_irq(int irq, void *devid) jz4740_timer_ack_full(TIMER_CLOCKEVENT); - if (cd->mode != CLOCK_EVT_MODE_PERIODIC) + if (!clockevent_state_periodic(cd)) jz4740_timer_disable(TIMER_CLOCKEVENT); cd->event_handler(cd); @@ -63,24 +66,29 @@ static irqreturn_t jz4740_clockevent_irq(int irq, void *devid) return IRQ_HANDLED; } -static void jz4740_clockevent_set_mode(enum clock_event_mode mode, - struct clock_event_device *cd) +static int jz4740_clockevent_set_periodic(struct clock_event_device *evt) { - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); - jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); - case CLOCK_EVT_MODE_RESUME: - jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); - jz4740_timer_enable(TIMER_CLOCKEVENT); - break; - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_SHUTDOWN: - jz4740_timer_disable(TIMER_CLOCKEVENT); - break; - default: - break; - } + jz4740_timer_set_count(TIMER_CLOCKEVENT, 0); + jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick); + jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); + jz4740_timer_enable(TIMER_CLOCKEVENT); + + return 0; +} + +static int jz4740_clockevent_resume(struct clock_event_device *evt) +{ + jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT); + jz4740_timer_enable(TIMER_CLOCKEVENT); + + return 0; +} + +static int jz4740_clockevent_shutdown(struct clock_event_device *evt) +{ + jz4740_timer_disable(TIMER_CLOCKEVENT); + + return 0; } static int jz4740_clockevent_set_next(unsigned long evt, @@ -97,9 +105,17 @@ static struct clock_event_device jz4740_clockevent = { .name = "jz4740-timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = jz4740_clockevent_set_next, - .set_mode = jz4740_clockevent_set_mode, + .set_state_shutdown = jz4740_clockevent_shutdown, + .set_state_periodic = jz4740_clockevent_set_periodic, + .set_state_oneshot = jz4740_clockevent_shutdown, + .tick_resume = jz4740_clockevent_resume, .rating = 200, +#ifdef CONFIG_MACH_JZ4740 .irq = JZ4740_IRQ_TCU0, +#endif +#ifdef CONFIG_MACH_JZ4780 + .irq = JZ4780_IRQ_TCU2, +#endif }; static struct irqaction timer_irqaction = { @@ -114,10 +130,17 @@ void __init plat_time_init(void) int ret; uint32_t clk_rate; uint16_t ctrl; + struct clk *ext_clk; + of_clk_init(NULL); jz4740_timer_init(); - clk_rate = jz4740_clock_bdata.ext_rate >> 4; + ext_clk = clk_get(NULL, "ext"); + if (IS_ERR(ext_clk)) + panic("unable to get ext clock"); + clk_rate = clk_get_rate(ext_clk) >> 4; + clk_put(ext_clk); + jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ); clockevent_set_clock(&jz4740_clockevent, clk_rate); @@ -134,7 +157,7 @@ void __init plat_time_init(void) sched_clock_register(jz4740_read_sched_clock, 16, clk_rate); - setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction); + setup_irq(jz4740_clockevent.irq, &timer_irqaction); ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT; |