[PATCH V4] mtd: nand: add Loongson1 NAND driver
From: Kelvin CheungThis patch adds NAND driver for Loongson1B. Signed-off-by: Kelvin Cheung --- v4: Retrieve the controller from nand_hw_control. v3: Replace __raw_readl/__raw_writel with readl/writel. Split ls1x_nand into two structures: ls1x_nand_chip and ls1x_nand_controller. V2: Modify the dependency in Kconfig due to the changes of DMA module. --- drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 571 ++ 3 files changed, 580 insertions(+) create mode 100644 drivers/mtd/nand/loongson1_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 7b7a887..2a815c7 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -569,4 +569,12 @@ config MTD_NAND_MTK Enables support for NAND controller on MTK SoCs. This controller is found on mt27xx, mt81xx, mt65xx SoCs. +config MTD_NAND_LOONGSON1 + tristate "Support for Loongson1 SoC NAND controller" + depends on MACH_LOONGSON32 + select DMADEVICES + select LOONGSON1_DMA + help + Enables support for NAND Flash on Loongson1 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index cafde6f..04f65a6 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -58,5 +58,6 @@ obj-$(CONFIG_MTD_NAND_HISI504)+= hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o +obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1_nand.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/drivers/mtd/nand/loongson1_nand.c b/drivers/mtd/nand/loongson1_nand.c new file mode 100644 index 000..e3999ea --- /dev/null +++ b/drivers/mtd/nand/loongson1_nand.c @@ -0,0 +1,571 @@ +/* + * NAND Flash Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Loongson 1 NAND Register Definitions */ +#define NAND_CMD 0x0 +#define NAND_ADDRL 0x4 +#define NAND_ADDRH 0x8 +#define NAND_TIMING0xc +#define NAND_IDL 0x10 +#define NAND_IDH 0x14 +#define NAND_STATUS0x14 +#define NAND_PARAM 0x18 +#define NAND_OP_NUM0x1c +#define NAND_CS_RDY0x20 + +#define NAND_DMA_ADDR 0x40 + +/* NAND Command Register Bits */ +#define NAND_RDY BIT(10) +#define OP_SPARE BIT(9) +#define OP_MAINBIT(8) +#define CMD_STATUS BIT(7) +#define CMD_RESET BIT(6) +#define CMD_READID BIT(5) +#define BLOCKS_ERASE BIT(4) +#define CMD_ERASE BIT(3) +#define CMD_WRITE BIT(2) +#define CMD_READ BIT(1) +#define CMD_VALID BIT(0) + +#defineLS1X_NAND_TIMEOUT 20 + +/* macros for registers read/write */ +#define nand_readl(nandc, off) \ + readl((nandc)->reg_base + (off)) + +#define nand_writel(nandc, off, val) \ + writel((val), (nandc)->reg_base + (off)) + +#define set_cmd(nandc, ctrl) \ + nand_writel(nandc, NAND_CMD, ctrl) + +#define start_nand(nandc) \ + nand_writel(nandc, NAND_CMD, nand_readl(nandc, NAND_CMD) | CMD_VALID) + +struct ls1x_nand_chip { + struct nand_chip chip; + struct plat_ls1x_nand *pdata; +}; + +struct ls1x_nand_controller { + struct nand_hw_control controller; + struct clk *clk; + void __iomem *reg_base; + + int cmd_ctrl; + char datareg[8]; + char *data_ptr; + + /* DMA stuff */ + unsigned char *dma_buf; + unsigned int buf_off; + unsigned int buf_len; + + /* DMA Engine stuff */ + unsigned int dma_chan_id; + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; + struct completion dma_complete; + void __iomem *dma_desc; +}; + +static inline struct ls1x_nand_chip *to_ls1x_nand_chip(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct ls1x_nand_chip, chip); +} + +static struct ls1x_nand_controller * +to_ls1x_nand_controller(struct nand_hw_control *ctrl) +{ + return container_of(ctrl, struct ls1x_nand_controller, controller); +} + +static void dma_callback(void *data) +{ + struct mtd_info *mtd = (struct mtd_info *)data; + struct nand_chip *chip = mtd_to_nand(mtd); +
[PATCH V4] mtd: nand: add Loongson1 NAND driver
From: Kelvin Cheung This patch adds NAND driver for Loongson1B. Signed-off-by: Kelvin Cheung --- v4: Retrieve the controller from nand_hw_control. v3: Replace __raw_readl/__raw_writel with readl/writel. Split ls1x_nand into two structures: ls1x_nand_chip and ls1x_nand_controller. V2: Modify the dependency in Kconfig due to the changes of DMA module. --- drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 571 ++ 3 files changed, 580 insertions(+) create mode 100644 drivers/mtd/nand/loongson1_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 7b7a887..2a815c7 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -569,4 +569,12 @@ config MTD_NAND_MTK Enables support for NAND controller on MTK SoCs. This controller is found on mt27xx, mt81xx, mt65xx SoCs. +config MTD_NAND_LOONGSON1 + tristate "Support for Loongson1 SoC NAND controller" + depends on MACH_LOONGSON32 + select DMADEVICES + select LOONGSON1_DMA + help + Enables support for NAND Flash on Loongson1 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index cafde6f..04f65a6 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -58,5 +58,6 @@ obj-$(CONFIG_MTD_NAND_HISI504)+= hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o +obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1_nand.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/drivers/mtd/nand/loongson1_nand.c b/drivers/mtd/nand/loongson1_nand.c new file mode 100644 index 000..e3999ea --- /dev/null +++ b/drivers/mtd/nand/loongson1_nand.c @@ -0,0 +1,571 @@ +/* + * NAND Flash Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Loongson 1 NAND Register Definitions */ +#define NAND_CMD 0x0 +#define NAND_ADDRL 0x4 +#define NAND_ADDRH 0x8 +#define NAND_TIMING0xc +#define NAND_IDL 0x10 +#define NAND_IDH 0x14 +#define NAND_STATUS0x14 +#define NAND_PARAM 0x18 +#define NAND_OP_NUM0x1c +#define NAND_CS_RDY0x20 + +#define NAND_DMA_ADDR 0x40 + +/* NAND Command Register Bits */ +#define NAND_RDY BIT(10) +#define OP_SPARE BIT(9) +#define OP_MAINBIT(8) +#define CMD_STATUS BIT(7) +#define CMD_RESET BIT(6) +#define CMD_READID BIT(5) +#define BLOCKS_ERASE BIT(4) +#define CMD_ERASE BIT(3) +#define CMD_WRITE BIT(2) +#define CMD_READ BIT(1) +#define CMD_VALID BIT(0) + +#defineLS1X_NAND_TIMEOUT 20 + +/* macros for registers read/write */ +#define nand_readl(nandc, off) \ + readl((nandc)->reg_base + (off)) + +#define nand_writel(nandc, off, val) \ + writel((val), (nandc)->reg_base + (off)) + +#define set_cmd(nandc, ctrl) \ + nand_writel(nandc, NAND_CMD, ctrl) + +#define start_nand(nandc) \ + nand_writel(nandc, NAND_CMD, nand_readl(nandc, NAND_CMD) | CMD_VALID) + +struct ls1x_nand_chip { + struct nand_chip chip; + struct plat_ls1x_nand *pdata; +}; + +struct ls1x_nand_controller { + struct nand_hw_control controller; + struct clk *clk; + void __iomem *reg_base; + + int cmd_ctrl; + char datareg[8]; + char *data_ptr; + + /* DMA stuff */ + unsigned char *dma_buf; + unsigned int buf_off; + unsigned int buf_len; + + /* DMA Engine stuff */ + unsigned int dma_chan_id; + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; + struct completion dma_complete; + void __iomem *dma_desc; +}; + +static inline struct ls1x_nand_chip *to_ls1x_nand_chip(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct ls1x_nand_chip, chip); +} + +static struct ls1x_nand_controller * +to_ls1x_nand_controller(struct nand_hw_control *ctrl) +{ + return container_of(ctrl, struct ls1x_nand_controller, controller); +} + +static void dma_callback(void *data) +{ + struct mtd_info *mtd = (struct mtd_info *)data; + struct nand_chip *chip = mtd_to_nand(mtd); + struct ls1x_nand_controller *nandc = +
[PATCH V1 1/3] clk: Loongson1: Refactor Loongson1 clock
From: Kelvin CheungFactor out the common functions into loongson1/clk.c to support both Loongson1B and Loongson1C. And, put the rest into loongson1/clk-loongson1b.c. Signed-off-by: Kelvin Cheung --- v1: Rebase the patch on clk: ls1x: Migrate to clk_hw based OF and registration APIs. --- drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 51 ++ drivers/clk/loongson1/clk.c| 43 ++ drivers/clk/loongson1/clk.h| 19 5 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (78%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 8264d81..925081e 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK)+= clk-highbank.o -obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o @@ -61,6 +60,7 @@ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_ARCH_MXC) += imx/ obj-$(CONFIG_MACH_INGENIC) += ingenic/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ obj-$(CONFIG_ARCH_MEDIATEK)+= mediatek/ obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/ obj-$(CONFIG_MACH_PIC32) += microchip/ diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile new file mode 100644 index 000..5a162a1 --- /dev/null +++ b/drivers/clk/loongson1/Makefile @@ -0,0 +1,2 @@ +obj-y += clk.o +obj-$(CONFIG_LOONGSON1_LS1B) += clk-loongson1b.o diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/loongson1/clk-loongson1b.c similarity index 78% rename from drivers/clk/clk-ls1x.c rename to drivers/clk/loongson1/clk-loongson1b.c index 8430e45..5b6817e 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Zhang, Keguang + * Copyright (c) 2012-2016 Zhang, Keguang * * 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 @@ -10,25 +10,16 @@ #include #include #include -#include #include #include +#include "clk.h" #define OSC(33 * 100) #define DIV_APB2 static DEFINE_SPINLOCK(_lock); -static int ls1x_pll_clk_enable(struct clk_hw *hw) -{ - return 0; -} - -static void ls1x_pll_clk_disable(struct clk_hw *hw) -{ -} - static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -43,44 +34,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, } static const struct clk_ops ls1x_pll_clk_ops = { - .enable = ls1x_pll_clk_enable, - .disable = ls1x_pll_clk_disable, .recalc_rate = ls1x_pll_recalc_rate, }; -static struct clk_hw *__init clk_hw_register_pll(struct device *dev, -const char *name, -const char *parent_name, -unsigned long flags) -{ - int ret; - struct clk_hw *hw; - struct clk_init_data init; - - /* allocate the divider */ - hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL); - if (!hw) { - pr_err("%s: could not allocate clk_hw\n", __func__); - return ERR_PTR(-ENOMEM); - } - - init.name = name; - init.ops = _pll_clk_ops; - init.flags = flags | CLK_IS_BASIC; - init.parent_names = (parent_name ? _name : NULL); - init.num_parents = (parent_name ? 1 : 0); - hw->init = - - /* register the clock */ - ret = clk_hw_register(dev, hw); - if (ret) { - kfree(hw); - hw = ERR_PTR(ret); - } - - return hw; -} - static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; @@ -93,7 +49,8 @@ void __init ls1x_clk_init(void) clk_hw_register_clkdev(hw,
[PATCH V1 3/3] clk: Loongson1: Make use of GENMASK
From: Kelvin CheungMake use of GENMASK instead of open coding the equivalent operation, and update the PLL formula. Signed-off-by: Kelvin Cheung --- drivers/clk/loongson1/clk-loongson1b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 4b3d9d2..f36a97e 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -26,7 +26,7 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, u32 pll, rate; pll = __raw_readl(LS1X_CLK_PLL_FREQ); - rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10); + rate = 12 + (pll & GENMASK(5, 0)); rate *= OSC; rate >>= 1; -- 1.9.1
[PATCH V1 2/3] clk: Loongson1: Update clocks of Loongson1B
From: Kelvin CheungThis patch updates some clock names of Loongson1B, and adds AC97, DMA and NAND clock. Signed-off-by: Kelvin Cheung --- v1: Rebase the patch on clk: ls1x: Migrate to clk_hw based OF and registration APIs. --- drivers/clk/loongson1/clk-loongson1b.c | 23 +-- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 5b6817e..4b3d9d2 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -37,19 +37,19 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; -static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; -static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; +static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", }; +static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", }; +static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", }; void __init ls1x_clk_init(void) { struct clk_hw *hw; - hw = clk_hw_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); - clk_hw_register_clkdev(hw, "osc_33m_clk", NULL); + hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC); + clk_hw_register_clkdev(hw, "osc_clk", NULL); /* clock derived from 33 MHz OSC clk */ - hw = clk_hw_register_pll(NULL, "pll_clk", "osc_33m_clk", + hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk", _pll_clk_ops, 0); clk_hw_register_clkdev(hw, "pll_clk", NULL); @@ -104,6 +104,7 @@ void __init ls1x_clk_init(void) CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock); clk_hw_register_clkdev(hw, "ahb_clk", NULL); + clk_hw_register_clkdev(hw, "ls1x-dma", NULL); clk_hw_register_clkdev(hw, "stmmaceth", NULL); /* clock derived from AHB clk */ @@ -111,9 +112,11 @@ void __init ls1x_clk_init(void) hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, DIV_APB); clk_hw_register_clkdev(hw, "apb_clk", NULL); - clk_hw_register_clkdev(hw, "ls1x_i2c", NULL); - clk_hw_register_clkdev(hw, "ls1x_pwmtimer", NULL); - clk_hw_register_clkdev(hw, "ls1x_spi", NULL); - clk_hw_register_clkdev(hw, "ls1x_wdt", NULL); + clk_hw_register_clkdev(hw, "ls1x-ac97", NULL); + clk_hw_register_clkdev(hw, "ls1x-i2c", NULL); + clk_hw_register_clkdev(hw, "ls1x-nand", NULL); + clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL); + clk_hw_register_clkdev(hw, "ls1x-spi", NULL); + clk_hw_register_clkdev(hw, "ls1x-wdt", NULL); clk_hw_register_clkdev(hw, "serial8250", NULL); } -- 1.9.1
[PATCH V1 3/3] clk: Loongson1: Make use of GENMASK
From: Kelvin Cheung Make use of GENMASK instead of open coding the equivalent operation, and update the PLL formula. Signed-off-by: Kelvin Cheung --- drivers/clk/loongson1/clk-loongson1b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 4b3d9d2..f36a97e 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -26,7 +26,7 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, u32 pll, rate; pll = __raw_readl(LS1X_CLK_PLL_FREQ); - rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10); + rate = 12 + (pll & GENMASK(5, 0)); rate *= OSC; rate >>= 1; -- 1.9.1
[PATCH V1 2/3] clk: Loongson1: Update clocks of Loongson1B
From: Kelvin Cheung This patch updates some clock names of Loongson1B, and adds AC97, DMA and NAND clock. Signed-off-by: Kelvin Cheung --- v1: Rebase the patch on clk: ls1x: Migrate to clk_hw based OF and registration APIs. --- drivers/clk/loongson1/clk-loongson1b.c | 23 +-- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 5b6817e..4b3d9d2 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -37,19 +37,19 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; -static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; -static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; +static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", }; +static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", }; +static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", }; void __init ls1x_clk_init(void) { struct clk_hw *hw; - hw = clk_hw_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); - clk_hw_register_clkdev(hw, "osc_33m_clk", NULL); + hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC); + clk_hw_register_clkdev(hw, "osc_clk", NULL); /* clock derived from 33 MHz OSC clk */ - hw = clk_hw_register_pll(NULL, "pll_clk", "osc_33m_clk", + hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk", _pll_clk_ops, 0); clk_hw_register_clkdev(hw, "pll_clk", NULL); @@ -104,6 +104,7 @@ void __init ls1x_clk_init(void) CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock); clk_hw_register_clkdev(hw, "ahb_clk", NULL); + clk_hw_register_clkdev(hw, "ls1x-dma", NULL); clk_hw_register_clkdev(hw, "stmmaceth", NULL); /* clock derived from AHB clk */ @@ -111,9 +112,11 @@ void __init ls1x_clk_init(void) hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, DIV_APB); clk_hw_register_clkdev(hw, "apb_clk", NULL); - clk_hw_register_clkdev(hw, "ls1x_i2c", NULL); - clk_hw_register_clkdev(hw, "ls1x_pwmtimer", NULL); - clk_hw_register_clkdev(hw, "ls1x_spi", NULL); - clk_hw_register_clkdev(hw, "ls1x_wdt", NULL); + clk_hw_register_clkdev(hw, "ls1x-ac97", NULL); + clk_hw_register_clkdev(hw, "ls1x-i2c", NULL); + clk_hw_register_clkdev(hw, "ls1x-nand", NULL); + clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL); + clk_hw_register_clkdev(hw, "ls1x-spi", NULL); + clk_hw_register_clkdev(hw, "ls1x-wdt", NULL); clk_hw_register_clkdev(hw, "serial8250", NULL); } -- 1.9.1
[PATCH V1 1/3] clk: Loongson1: Refactor Loongson1 clock
From: Kelvin Cheung Factor out the common functions into loongson1/clk.c to support both Loongson1B and Loongson1C. And, put the rest into loongson1/clk-loongson1b.c. Signed-off-by: Kelvin Cheung --- v1: Rebase the patch on clk: ls1x: Migrate to clk_hw based OF and registration APIs. --- drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 51 ++ drivers/clk/loongson1/clk.c| 43 ++ drivers/clk/loongson1/clk.h| 19 5 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (78%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 8264d81..925081e 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK)+= clk-highbank.o -obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o @@ -61,6 +60,7 @@ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_ARCH_MXC) += imx/ obj-$(CONFIG_MACH_INGENIC) += ingenic/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ obj-$(CONFIG_ARCH_MEDIATEK)+= mediatek/ obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/ obj-$(CONFIG_MACH_PIC32) += microchip/ diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile new file mode 100644 index 000..5a162a1 --- /dev/null +++ b/drivers/clk/loongson1/Makefile @@ -0,0 +1,2 @@ +obj-y += clk.o +obj-$(CONFIG_LOONGSON1_LS1B) += clk-loongson1b.o diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/loongson1/clk-loongson1b.c similarity index 78% rename from drivers/clk/clk-ls1x.c rename to drivers/clk/loongson1/clk-loongson1b.c index 8430e45..5b6817e 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Zhang, Keguang + * Copyright (c) 2012-2016 Zhang, Keguang * * 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 @@ -10,25 +10,16 @@ #include #include #include -#include #include #include +#include "clk.h" #define OSC(33 * 100) #define DIV_APB2 static DEFINE_SPINLOCK(_lock); -static int ls1x_pll_clk_enable(struct clk_hw *hw) -{ - return 0; -} - -static void ls1x_pll_clk_disable(struct clk_hw *hw) -{ -} - static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -43,44 +34,9 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, } static const struct clk_ops ls1x_pll_clk_ops = { - .enable = ls1x_pll_clk_enable, - .disable = ls1x_pll_clk_disable, .recalc_rate = ls1x_pll_recalc_rate, }; -static struct clk_hw *__init clk_hw_register_pll(struct device *dev, -const char *name, -const char *parent_name, -unsigned long flags) -{ - int ret; - struct clk_hw *hw; - struct clk_init_data init; - - /* allocate the divider */ - hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL); - if (!hw) { - pr_err("%s: could not allocate clk_hw\n", __func__); - return ERR_PTR(-ENOMEM); - } - - init.name = name; - init.ops = _pll_clk_ops; - init.flags = flags | CLK_IS_BASIC; - init.parent_names = (parent_name ? _name : NULL); - init.num_parents = (parent_name ? 1 : 0); - hw->init = - - /* register the clock */ - ret = clk_hw_register(dev, hw); - if (ret) { - kfree(hw); - hw = ERR_PTR(ret); - } - - return hw; -} - static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; @@ -93,7 +49,8 @@ void __init ls1x_clk_init(void) clk_hw_register_clkdev(hw, "osc_33m_clk", NULL); /* clock derived from 33 MHz OSC clk */ - hw = clk_hw_register_pll(NULL,
[PATCH V1 0/3] Refactor Loongson1 clock
From: Kelvin CheungThis patchset is to refactor Loongson1 clock, and update Loongson1B clocks. This applies on top of clk-next. Thanks! Changelog: v1: Rebase the patch on clk: ls1x: Migrate to clk_hw based OF and registration APIs. Kelvin Cheung (3): clk: Loongson1: Refactor Loongson1 clock clk: Loongson1: Update clocks of Loongson1B clk: Loongson1: Make use of GENMASK drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 74 +- drivers/clk/loongson1/clk.c| 43 + drivers/clk/loongson1/clk.h| 19 ++ 5 files changed, 82 insertions(+), 58 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (67%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h -- 1.9.1
[PATCH V1 0/3] Refactor Loongson1 clock
From: Kelvin Cheung This patchset is to refactor Loongson1 clock, and update Loongson1B clocks. This applies on top of clk-next. Thanks! Changelog: v1: Rebase the patch on clk: ls1x: Migrate to clk_hw based OF and registration APIs. Kelvin Cheung (3): clk: Loongson1: Refactor Loongson1 clock clk: Loongson1: Update clocks of Loongson1B clk: Loongson1: Make use of GENMASK drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 74 +- drivers/clk/loongson1/clk.c| 43 + drivers/clk/loongson1/clk.h| 19 ++ 5 files changed, 82 insertions(+), 58 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (67%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h -- 1.9.1
[PATCH] MIPS: Loongson1B: Change the OSC clock name
From: Kelvin CheungThis patch changes the OSC clock name to "osc_clk". Signed-off-by: Kelvin Cheung --- arch/mips/loongson32/common/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/loongson32/common/platform.c b/arch/mips/loongson32/common/platform.c index 4d12e36..fb60602 100644 --- a/arch/mips/loongson32/common/platform.c +++ b/arch/mips/loongson32/common/platform.c @@ -69,7 +69,7 @@ void __init ls1x_serial_set_uartclk(struct platform_device *pdev) /* CPUFreq */ static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = { .clk_name = "cpu_clk", - .osc_clk_name = "osc_33m_clk", + .osc_clk_name = "osc_clk", .max_freq = 266 * 1000, .min_freq = 33 * 1000, }; -- 1.9.1
[PATCH] MIPS: Loongson1B: Change the OSC clock name
From: Kelvin Cheung This patch changes the OSC clock name to "osc_clk". Signed-off-by: Kelvin Cheung --- arch/mips/loongson32/common/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/loongson32/common/platform.c b/arch/mips/loongson32/common/platform.c index 4d12e36..fb60602 100644 --- a/arch/mips/loongson32/common/platform.c +++ b/arch/mips/loongson32/common/platform.c @@ -69,7 +69,7 @@ void __init ls1x_serial_set_uartclk(struct platform_device *pdev) /* CPUFreq */ static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = { .clk_name = "cpu_clk", - .osc_clk_name = "osc_33m_clk", + .osc_clk_name = "osc_clk", .max_freq = 266 * 1000, .min_freq = 33 * 1000, }; -- 1.9.1
[PATCH 0/3] Refactor Loongson1 clock
From: Keguang Zhang <keguang.zh...@spreadtrum.com> This patchset is to refactor Loongson1 clock, and update Loongson1B clocks. This applies on top of clk-next. Thanks! Kelvin Cheung (3): clk: Loongson1: Refactor Loongson1 clock clk: Loongson1: Update clocks of Loongson1B clk: Loongson1: Make use of GENMASK drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 71 ++ drivers/clk/loongson1/clk.c| 52 drivers/clk/loongson1/clk.h| 21 +++ 5 files changed, 93 insertions(+), 55 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (68%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h -- 1.9.1
[PATCH 3/3] clk: Loongson1: Make use of GENMASK
From: Kelvin CheungMake use of GENMASK instead of open coding the equivalent operation, and update the PLL formula. Signed-off-by: Kelvin Cheung --- drivers/clk/loongson1/clk-loongson1b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 2302ee5..5cedb28 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -26,7 +26,7 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, u32 pll, rate; pll = __raw_readl(LS1X_CLK_PLL_FREQ); - rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10); + rate = 12 + (pll & GENMASK(5, 0)); rate *= OSC; rate >>= 1; -- 1.9.1
[PATCH 0/3] Refactor Loongson1 clock
From: Keguang Zhang This patchset is to refactor Loongson1 clock, and update Loongson1B clocks. This applies on top of clk-next. Thanks! Kelvin Cheung (3): clk: Loongson1: Refactor Loongson1 clock clk: Loongson1: Update clocks of Loongson1B clk: Loongson1: Make use of GENMASK drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 71 ++ drivers/clk/loongson1/clk.c| 52 drivers/clk/loongson1/clk.h| 21 +++ 5 files changed, 93 insertions(+), 55 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (68%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h -- 1.9.1
[PATCH 3/3] clk: Loongson1: Make use of GENMASK
From: Kelvin Cheung Make use of GENMASK instead of open coding the equivalent operation, and update the PLL formula. Signed-off-by: Kelvin Cheung --- drivers/clk/loongson1/clk-loongson1b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 2302ee5..5cedb28 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -26,7 +26,7 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, u32 pll, rate; pll = __raw_readl(LS1X_CLK_PLL_FREQ); - rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10); + rate = 12 + (pll & GENMASK(5, 0)); rate *= OSC; rate >>= 1; -- 1.9.1
[PATCH 1/3] clk: Loongson1: Refactor Loongson1 clock
From: Kelvin CheungFactor out the common functions into loongson1/clk.c to support both Loongson1B and Loongson1C. And, put the rest into loongson1/clk-loongson1b.c. Signed-off-by: Kelvin Cheung --- drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 48 ++-- drivers/clk/loongson1/clk.c| 52 ++ drivers/clk/loongson1/clk.h| 21 + 5 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (80%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 3b6f9cf..a508375 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK)+= clk-highbank.o -obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o @@ -91,3 +90,4 @@ obj-$(CONFIG_COMMON_CLK_VERSATILE)+= versatile/ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_ARCH_ZX) += zte/ obj-$(CONFIG_ARCH_ZYNQ)+= zynq/ +obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile new file mode 100644 index 000..5a162a1 --- /dev/null +++ b/drivers/clk/loongson1/Makefile @@ -0,0 +1,2 @@ +obj-y += clk.o +obj-$(CONFIG_LOONGSON1_LS1B) += clk-loongson1b.o diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/loongson1/clk-loongson1b.c similarity index 80% rename from drivers/clk/clk-ls1x.c rename to drivers/clk/loongson1/clk-loongson1b.c index 5097831..336ff95 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Zhang, Keguang + * Copyright (c) 2012-2016 Zhang, Keguang * * 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 @@ -10,25 +10,16 @@ #include #include #include -#include #include #include +#include "clk.h" #define OSC(33 * 100) #define DIV_APB2 static DEFINE_SPINLOCK(_lock); -static int ls1x_pll_clk_enable(struct clk_hw *hw) -{ - return 0; -} - -static void ls1x_pll_clk_disable(struct clk_hw *hw) -{ -} - static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -48,38 +39,6 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static struct clk *__init clk_register_pll(struct device *dev, - const char *name, - const char *parent_name, - unsigned long flags) -{ - struct clk_hw *hw; - struct clk *clk; - struct clk_init_data init; - - /* allocate the divider */ - hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL); - if (!hw) { - pr_err("%s: could not allocate clk_hw\n", __func__); - return ERR_PTR(-ENOMEM); - } - - init.name = name; - init.ops = _pll_clk_ops; - init.flags = flags | CLK_IS_BASIC; - init.parent_names = (parent_name ? _name : NULL); - init.num_parents = (parent_name ? 1 : 0); - hw->init = - - /* register the clock */ - clk = clk_register(dev, hw); - - if (IS_ERR(clk)) - kfree(hw); - - return clk; -} - static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; @@ -92,7 +51,8 @@ void __init ls1x_clk_init(void) clk_register_clkdev(clk, "osc_33m_clk", NULL); /* clock derived from 33 MHz OSC clk */ - clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0); + clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", + _pll_clk_ops, 0); clk_register_clkdev(clk, "pll_clk", NULL); /* clock derived from PLL clk */ diff --git a/drivers/clk/loongson1/clk.c b/drivers/clk/loongson1/clk.c new file mode 100644 index 000..367b84a ---
[PATCH 2/3] clk: Loongson1: Update clocks of Loongson1B
From: Kelvin CheungThis patch updates some clock names of Loongson1B, and adds AC97, DMA and NAND clock. Signed-off-by: Kelvin Cheung --- drivers/clk/loongson1/clk-loongson1b.c | 23 +-- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 336ff95..2302ee5 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -39,19 +39,19 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; -static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; -static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; +static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", }; +static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", }; +static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", }; void __init ls1x_clk_init(void) { struct clk *clk; - clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); - clk_register_clkdev(clk, "osc_33m_clk", NULL); + clk = clk_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC); + clk_register_clkdev(clk, "osc_clk", NULL); /* clock derived from 33 MHz OSC clk */ - clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", + clk = clk_register_pll(NULL, "pll_clk", "osc_clk", _pll_clk_ops, 0); clk_register_clkdev(clk, "pll_clk", NULL); @@ -106,6 +106,7 @@ void __init ls1x_clk_init(void) CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock); clk_register_clkdev(clk, "ahb_clk", NULL); + clk_register_clkdev(clk, "ls1x-dma", NULL); clk_register_clkdev(clk, "stmmaceth", NULL); /* clock derived from AHB clk */ @@ -113,9 +114,11 @@ void __init ls1x_clk_init(void) clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, DIV_APB); clk_register_clkdev(clk, "apb_clk", NULL); - clk_register_clkdev(clk, "ls1x_i2c", NULL); - clk_register_clkdev(clk, "ls1x_pwmtimer", NULL); - clk_register_clkdev(clk, "ls1x_spi", NULL); - clk_register_clkdev(clk, "ls1x_wdt", NULL); + clk_register_clkdev(clk, "ls1x-ac97", NULL); + clk_register_clkdev(clk, "ls1x-i2c", NULL); + clk_register_clkdev(clk, "ls1x-nand", NULL); + clk_register_clkdev(clk, "ls1x-pwmtimer", NULL); + clk_register_clkdev(clk, "ls1x-spi", NULL); + clk_register_clkdev(clk, "ls1x-wdt", NULL); clk_register_clkdev(clk, "serial8250", NULL); } -- 1.9.1
[PATCH 2/3] clk: Loongson1: Update clocks of Loongson1B
From: Kelvin Cheung This patch updates some clock names of Loongson1B, and adds AC97, DMA and NAND clock. Signed-off-by: Kelvin Cheung --- drivers/clk/loongson1/clk-loongson1b.c | 23 +-- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/clk/loongson1/clk-loongson1b.c b/drivers/clk/loongson1/clk-loongson1b.c index 336ff95..2302ee5 100644 --- a/drivers/clk/loongson1/clk-loongson1b.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -39,19 +39,19 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; -static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; -static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; +static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", }; +static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", }; +static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", }; void __init ls1x_clk_init(void) { struct clk *clk; - clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); - clk_register_clkdev(clk, "osc_33m_clk", NULL); + clk = clk_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC); + clk_register_clkdev(clk, "osc_clk", NULL); /* clock derived from 33 MHz OSC clk */ - clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", + clk = clk_register_pll(NULL, "pll_clk", "osc_clk", _pll_clk_ops, 0); clk_register_clkdev(clk, "pll_clk", NULL); @@ -106,6 +106,7 @@ void __init ls1x_clk_init(void) CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock); clk_register_clkdev(clk, "ahb_clk", NULL); + clk_register_clkdev(clk, "ls1x-dma", NULL); clk_register_clkdev(clk, "stmmaceth", NULL); /* clock derived from AHB clk */ @@ -113,9 +114,11 @@ void __init ls1x_clk_init(void) clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, DIV_APB); clk_register_clkdev(clk, "apb_clk", NULL); - clk_register_clkdev(clk, "ls1x_i2c", NULL); - clk_register_clkdev(clk, "ls1x_pwmtimer", NULL); - clk_register_clkdev(clk, "ls1x_spi", NULL); - clk_register_clkdev(clk, "ls1x_wdt", NULL); + clk_register_clkdev(clk, "ls1x-ac97", NULL); + clk_register_clkdev(clk, "ls1x-i2c", NULL); + clk_register_clkdev(clk, "ls1x-nand", NULL); + clk_register_clkdev(clk, "ls1x-pwmtimer", NULL); + clk_register_clkdev(clk, "ls1x-spi", NULL); + clk_register_clkdev(clk, "ls1x-wdt", NULL); clk_register_clkdev(clk, "serial8250", NULL); } -- 1.9.1
[PATCH 1/3] clk: Loongson1: Refactor Loongson1 clock
From: Kelvin Cheung Factor out the common functions into loongson1/clk.c to support both Loongson1B and Loongson1C. And, put the rest into loongson1/clk-loongson1b.c. Signed-off-by: Kelvin Cheung --- drivers/clk/Makefile | 2 +- drivers/clk/loongson1/Makefile | 2 + .../clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} | 48 ++-- drivers/clk/loongson1/clk.c| 52 ++ drivers/clk/loongson1/clk.h| 21 + 5 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 drivers/clk/loongson1/Makefile rename drivers/clk/{clk-ls1x.c => loongson1/clk-loongson1b.c} (80%) create mode 100644 drivers/clk/loongson1/clk.c create mode 100644 drivers/clk/loongson1/clk.h diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 3b6f9cf..a508375 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK)+= clk-highbank.o -obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o @@ -91,3 +90,4 @@ obj-$(CONFIG_COMMON_CLK_VERSATILE)+= versatile/ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_ARCH_ZX) += zte/ obj-$(CONFIG_ARCH_ZYNQ)+= zynq/ +obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile new file mode 100644 index 000..5a162a1 --- /dev/null +++ b/drivers/clk/loongson1/Makefile @@ -0,0 +1,2 @@ +obj-y += clk.o +obj-$(CONFIG_LOONGSON1_LS1B) += clk-loongson1b.o diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/loongson1/clk-loongson1b.c similarity index 80% rename from drivers/clk/clk-ls1x.c rename to drivers/clk/loongson1/clk-loongson1b.c index 5097831..336ff95 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/loongson1/clk-loongson1b.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Zhang, Keguang + * Copyright (c) 2012-2016 Zhang, Keguang * * 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 @@ -10,25 +10,16 @@ #include #include #include -#include #include #include +#include "clk.h" #define OSC(33 * 100) #define DIV_APB2 static DEFINE_SPINLOCK(_lock); -static int ls1x_pll_clk_enable(struct clk_hw *hw) -{ - return 0; -} - -static void ls1x_pll_clk_disable(struct clk_hw *hw) -{ -} - static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -48,38 +39,6 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static struct clk *__init clk_register_pll(struct device *dev, - const char *name, - const char *parent_name, - unsigned long flags) -{ - struct clk_hw *hw; - struct clk *clk; - struct clk_init_data init; - - /* allocate the divider */ - hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL); - if (!hw) { - pr_err("%s: could not allocate clk_hw\n", __func__); - return ERR_PTR(-ENOMEM); - } - - init.name = name; - init.ops = _pll_clk_ops; - init.flags = flags | CLK_IS_BASIC; - init.parent_names = (parent_name ? _name : NULL); - init.num_parents = (parent_name ? 1 : 0); - hw->init = - - /* register the clock */ - clk = clk_register(dev, hw); - - if (IS_ERR(clk)) - kfree(hw); - - return clk; -} - static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; @@ -92,7 +51,8 @@ void __init ls1x_clk_init(void) clk_register_clkdev(clk, "osc_33m_clk", NULL); /* clock derived from 33 MHz OSC clk */ - clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0); + clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", + _pll_clk_ops, 0); clk_register_clkdev(clk, "pll_clk", NULL); /* clock derived from PLL clk */ diff --git a/drivers/clk/loongson1/clk.c b/drivers/clk/loongson1/clk.c new file mode 100644 index 000..367b84a --- /dev/null +++ b/drivers/clk/loongson1/clk.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012-2016 Zhang, Keguang
[PATCH] MIPS: Loongson1B: Modify DEFAULT_MEMSIZE
From: Kelvin CheungThis patch changes DEFAULT_MEMSIZE to 64MB which is the memory size of latest EVB. Signed-off-by: Kelvin Cheung --- arch/mips/include/asm/mach-loongson32/loongson1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h b/arch/mips/include/asm/mach-loongson32/loongson1.h index 3584c40..ec7efd0 100644 --- a/arch/mips/include/asm/mach-loongson32/loongson1.h +++ b/arch/mips/include/asm/mach-loongson32/loongson1.h @@ -13,7 +13,7 @@ #define __ASM_MACH_LOONGSON32_LOONGSON1_H #if defined(CONFIG_LOONGSON1_LS1B) -#define DEFAULT_MEMSIZE256 /* If no memsize provided */ +#define DEFAULT_MEMSIZE64 /* If no memsize provided */ #elif defined(CONFIG_LOONGSON1_LS1C) #define DEFAULT_MEMSIZE32 #endif -- 1.9.1
[PATCH] MIPS: Loongson1B: Modify DEFAULT_MEMSIZE
From: Kelvin Cheung This patch changes DEFAULT_MEMSIZE to 64MB which is the memory size of latest EVB. Signed-off-by: Kelvin Cheung --- arch/mips/include/asm/mach-loongson32/loongson1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h b/arch/mips/include/asm/mach-loongson32/loongson1.h index 3584c40..ec7efd0 100644 --- a/arch/mips/include/asm/mach-loongson32/loongson1.h +++ b/arch/mips/include/asm/mach-loongson32/loongson1.h @@ -13,7 +13,7 @@ #define __ASM_MACH_LOONGSON32_LOONGSON1_H #if defined(CONFIG_LOONGSON1_LS1B) -#define DEFAULT_MEMSIZE256 /* If no memsize provided */ +#define DEFAULT_MEMSIZE64 /* If no memsize provided */ #elif defined(CONFIG_LOONGSON1_LS1C) #define DEFAULT_MEMSIZE32 #endif -- 1.9.1
[PATCH] MIPS: Loongson1C: Remove ARCH_WANT_OPTIONAL_GPIOLIB
From: Kelvin CheungThis patch removes ARCH_WANT_OPTIONAL_GPIOLIB due to upstream changes. Signed-off-by: Kelvin Cheung --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 69df280..d0b9ad1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1405,7 +1405,6 @@ config CPU_LOONGSON1C bool "Loongson 1C" depends on SYS_HAS_CPU_LOONGSON1C select CPU_LOONGSON1 - select ARCH_WANT_OPTIONAL_GPIOLIB select LEDS_GPIO_REGISTER help The Loongson 1C is a 32-bit SoC, which implements the MIPS32 -- 1.9.1
[PATCH] MIPS: Loongson1C: Remove ARCH_WANT_OPTIONAL_GPIOLIB
From: Kelvin Cheung This patch removes ARCH_WANT_OPTIONAL_GPIOLIB due to upstream changes. Signed-off-by: Kelvin Cheung --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 69df280..d0b9ad1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1405,7 +1405,6 @@ config CPU_LOONGSON1C bool "Loongson 1C" depends on SYS_HAS_CPU_LOONGSON1C select CPU_LOONGSON1 - select ARCH_WANT_OPTIONAL_GPIOLIB select LEDS_GPIO_REGISTER help The Loongson 1C is a 32-bit SoC, which implements the MIPS32 -- 1.9.1
[PATCH V1] MIPS: Loongson1B: Provide DMA filter callbacks via platform data
From: Kelvin CheungThis patch provides DMA filter callbacks via platform data to make NAND driver independent of single DMA engine driver. Signed-off-by: Kelvin Cheung --- v1: Fix the build error --- arch/mips/include/asm/mach-loongson32/dma.h | 4 arch/mips/include/asm/mach-loongson32/nand.h | 3 +-- arch/mips/loongson32/ls1b/board.c| 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h index ad1dec7..d3ae391 100644 --- a/arch/mips/include/asm/mach-loongson32/dma.h +++ b/arch/mips/include/asm/mach-loongson32/dma.h @@ -12,6 +12,8 @@ #ifndef __ASM_MACH_LOONGSON32_DMA_H #define __ASM_MACH_LOONGSON32_DMA_H +#include + #define LS1X_DMA_CHANNEL0 0 #define LS1X_DMA_CHANNEL1 1 #define LS1X_DMA_CHANNEL2 2 @@ -22,4 +24,6 @@ struct plat_ls1x_dma { extern struct plat_ls1x_dma ls1b_dma_pdata; +bool ls1x_dma_filter(struct dma_chan *chan, void *param); + #endif /* __ASM_MACH_LOONGSON32_DMA_H */ diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h index e274912..a1f8704 100644 --- a/arch/mips/include/asm/mach-loongson32/nand.h +++ b/arch/mips/include/asm/mach-loongson32/nand.h @@ -21,10 +21,9 @@ struct plat_ls1x_nand { int hold_cycle; int wait_cycle; + bool (*dma_filter)(struct dma_chan *chan, void *param); }; extern struct plat_ls1x_nand ls1b_nand_pdata; -bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param); - #endif /* __ASM_MACH_LOONGSON32_NAND_H */ diff --git a/arch/mips/loongson32/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c index 38a1d40..dac1cbb 100644 --- a/arch/mips/loongson32/ls1b/board.c +++ b/arch/mips/loongson32/ls1b/board.c @@ -38,6 +38,9 @@ struct plat_ls1x_nand ls1x_nand_pdata = { .nr_parts = ARRAY_SIZE(ls1x_nand_parts), .hold_cycle = 0x2, .wait_cycle = 0xc, +#ifdef CONFIG_LOONGSON1_DMA + .dma_filter = ls1x_dma_filter, +#endif }; static const struct gpio_led ls1x_gpio_leds[] __initconst = { -- 1.9.1
[PATCH V1] MIPS: Loongson1B: Provide DMA filter callbacks via platform data
From: Kelvin Cheung This patch provides DMA filter callbacks via platform data to make NAND driver independent of single DMA engine driver. Signed-off-by: Kelvin Cheung --- v1: Fix the build error --- arch/mips/include/asm/mach-loongson32/dma.h | 4 arch/mips/include/asm/mach-loongson32/nand.h | 3 +-- arch/mips/loongson32/ls1b/board.c| 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h index ad1dec7..d3ae391 100644 --- a/arch/mips/include/asm/mach-loongson32/dma.h +++ b/arch/mips/include/asm/mach-loongson32/dma.h @@ -12,6 +12,8 @@ #ifndef __ASM_MACH_LOONGSON32_DMA_H #define __ASM_MACH_LOONGSON32_DMA_H +#include + #define LS1X_DMA_CHANNEL0 0 #define LS1X_DMA_CHANNEL1 1 #define LS1X_DMA_CHANNEL2 2 @@ -22,4 +24,6 @@ struct plat_ls1x_dma { extern struct plat_ls1x_dma ls1b_dma_pdata; +bool ls1x_dma_filter(struct dma_chan *chan, void *param); + #endif /* __ASM_MACH_LOONGSON32_DMA_H */ diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h index e274912..a1f8704 100644 --- a/arch/mips/include/asm/mach-loongson32/nand.h +++ b/arch/mips/include/asm/mach-loongson32/nand.h @@ -21,10 +21,9 @@ struct plat_ls1x_nand { int hold_cycle; int wait_cycle; + bool (*dma_filter)(struct dma_chan *chan, void *param); }; extern struct plat_ls1x_nand ls1b_nand_pdata; -bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param); - #endif /* __ASM_MACH_LOONGSON32_NAND_H */ diff --git a/arch/mips/loongson32/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c index 38a1d40..dac1cbb 100644 --- a/arch/mips/loongson32/ls1b/board.c +++ b/arch/mips/loongson32/ls1b/board.c @@ -38,6 +38,9 @@ struct plat_ls1x_nand ls1x_nand_pdata = { .nr_parts = ARRAY_SIZE(ls1x_nand_parts), .hold_cycle = 0x2, .wait_cycle = 0xc, +#ifdef CONFIG_LOONGSON1_DMA + .dma_filter = ls1x_dma_filter, +#endif }; static const struct gpio_led ls1x_gpio_leds[] __initconst = { -- 1.9.1
[PATCH V3] mtd: nand: add Loongson1 NAND driver
From: Kelvin CheungThis patch adds NAND driver for Loongson1B. Signed-off-by: Kelvin Cheung --- v3: Replace __raw_readl/__raw_writel with readl/writel. Split ls1x_nand into two structures: ls1x_nand_chip and ls1x_nand_controller. V2: Modify the dependency in Kconfig due to the changes of DMA module. --- drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 555 ++ 3 files changed, 564 insertions(+) create mode 100644 drivers/mtd/nand/loongson1_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index f05e0e9..be20fb8 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -563,4 +563,12 @@ config MTD_NAND_QCOM Enables support for NAND flash chips on SoCs containing the EBI2 NAND controller. This controller is found on IPQ806x SoC. +config MTD_NAND_LOONGSON1 + tristate "Support for Loongson1 SoC NAND controller" + depends on MACH_LOONGSON32 + select DMADEVICES + select LOONGSON1_DMA + help + Enables support for NAND Flash on Loongson1 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index f553353..0310c0b 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -57,5 +57,6 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o +obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1_nand.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/drivers/mtd/nand/loongson1_nand.c b/drivers/mtd/nand/loongson1_nand.c new file mode 100644 index 000..86831773 --- /dev/null +++ b/drivers/mtd/nand/loongson1_nand.c @@ -0,0 +1,555 @@ +/* + * NAND Flash Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Loongson 1 NAND Register Definitions */ +#define NAND_CMD 0x0 +#define NAND_ADDRL 0x4 +#define NAND_ADDRH 0x8 +#define NAND_TIMING0xc +#define NAND_IDL 0x10 +#define NAND_IDH 0x14 +#define NAND_STATUS0x14 +#define NAND_PARAM 0x18 +#define NAND_OP_NUM0x1c +#define NAND_CS_RDY0x20 + +#define NAND_DMA_ADDR 0x40 + +/* NAND Command Register Bits */ +#define OP_DONEBIT(10) +#define OP_SPARE BIT(9) +#define OP_MAINBIT(8) +#define CMD_STATUS BIT(7) +#define CMD_RESET BIT(6) +#define CMD_READID BIT(5) +#define BLOCKS_ERASE BIT(4) +#define CMD_ERASE BIT(3) +#define CMD_WRITE BIT(2) +#define CMD_READ BIT(1) +#define CMD_VALID BIT(0) + +#defineLS1X_NAND_TIMEOUT 20 + +/* macros for registers read/write */ +#define nand_readl(nandc, off) \ + readl((nandc)->reg_base + (off)) + +#define nand_writel(nandc, off, val) \ + writel((val), (nandc)->reg_base + (off)) + +#define set_cmd(nandc, ctrl) \ + nand_writel(nandc, NAND_CMD, ctrl) + +#define start_nand(nandc) \ + nand_writel(nandc, NAND_CMD, nand_readl(nandc, NAND_CMD) | CMD_VALID) + +struct ls1x_nand_chip { + struct nand_chip chip; + struct plat_ls1x_nand *pdata; +}; + +struct ls1x_nand_controller { + struct clk *clk; + void __iomem *reg_base; + + int cmd_ctrl; + char datareg[8]; + char *data_ptr; + + /* DMA stuff */ + unsigned char *dma_buf; + unsigned int buf_off; + unsigned int buf_len; + + /* DMA Engine stuff */ + unsigned int dma_chan_id; + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; + struct completion dma_complete; + void __iomem *dma_desc; +}; + +static inline struct ls1x_nand_chip *to_ls1x_nand_chip(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct ls1x_nand_chip, chip); +} + +static void dma_callback(void *data) +{ + struct mtd_info *mtd = (struct mtd_info *)data; + struct nand_chip *chip = mtd_to_nand(mtd); + struct ls1x_nand_controller *nandc = nand_get_controller_data(chip); + struct dma_tx_state state; + enum dma_status status; + + status = + dmaengine_tx_status(nandc->dma_chan, nandc->dma_cookie, ); + if (likely(status ==
[PATCH V3] mtd: nand: add Loongson1 NAND driver
From: Kelvin Cheung This patch adds NAND driver for Loongson1B. Signed-off-by: Kelvin Cheung --- v3: Replace __raw_readl/__raw_writel with readl/writel. Split ls1x_nand into two structures: ls1x_nand_chip and ls1x_nand_controller. V2: Modify the dependency in Kconfig due to the changes of DMA module. --- drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 555 ++ 3 files changed, 564 insertions(+) create mode 100644 drivers/mtd/nand/loongson1_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index f05e0e9..be20fb8 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -563,4 +563,12 @@ config MTD_NAND_QCOM Enables support for NAND flash chips on SoCs containing the EBI2 NAND controller. This controller is found on IPQ806x SoC. +config MTD_NAND_LOONGSON1 + tristate "Support for Loongson1 SoC NAND controller" + depends on MACH_LOONGSON32 + select DMADEVICES + select LOONGSON1_DMA + help + Enables support for NAND Flash on Loongson1 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index f553353..0310c0b 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -57,5 +57,6 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o +obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1_nand.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/drivers/mtd/nand/loongson1_nand.c b/drivers/mtd/nand/loongson1_nand.c new file mode 100644 index 000..86831773 --- /dev/null +++ b/drivers/mtd/nand/loongson1_nand.c @@ -0,0 +1,555 @@ +/* + * NAND Flash Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Loongson 1 NAND Register Definitions */ +#define NAND_CMD 0x0 +#define NAND_ADDRL 0x4 +#define NAND_ADDRH 0x8 +#define NAND_TIMING0xc +#define NAND_IDL 0x10 +#define NAND_IDH 0x14 +#define NAND_STATUS0x14 +#define NAND_PARAM 0x18 +#define NAND_OP_NUM0x1c +#define NAND_CS_RDY0x20 + +#define NAND_DMA_ADDR 0x40 + +/* NAND Command Register Bits */ +#define OP_DONEBIT(10) +#define OP_SPARE BIT(9) +#define OP_MAINBIT(8) +#define CMD_STATUS BIT(7) +#define CMD_RESET BIT(6) +#define CMD_READID BIT(5) +#define BLOCKS_ERASE BIT(4) +#define CMD_ERASE BIT(3) +#define CMD_WRITE BIT(2) +#define CMD_READ BIT(1) +#define CMD_VALID BIT(0) + +#defineLS1X_NAND_TIMEOUT 20 + +/* macros for registers read/write */ +#define nand_readl(nandc, off) \ + readl((nandc)->reg_base + (off)) + +#define nand_writel(nandc, off, val) \ + writel((val), (nandc)->reg_base + (off)) + +#define set_cmd(nandc, ctrl) \ + nand_writel(nandc, NAND_CMD, ctrl) + +#define start_nand(nandc) \ + nand_writel(nandc, NAND_CMD, nand_readl(nandc, NAND_CMD) | CMD_VALID) + +struct ls1x_nand_chip { + struct nand_chip chip; + struct plat_ls1x_nand *pdata; +}; + +struct ls1x_nand_controller { + struct clk *clk; + void __iomem *reg_base; + + int cmd_ctrl; + char datareg[8]; + char *data_ptr; + + /* DMA stuff */ + unsigned char *dma_buf; + unsigned int buf_off; + unsigned int buf_len; + + /* DMA Engine stuff */ + unsigned int dma_chan_id; + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; + struct completion dma_complete; + void __iomem *dma_desc; +}; + +static inline struct ls1x_nand_chip *to_ls1x_nand_chip(struct mtd_info *mtd) +{ + return container_of(mtd_to_nand(mtd), struct ls1x_nand_chip, chip); +} + +static void dma_callback(void *data) +{ + struct mtd_info *mtd = (struct mtd_info *)data; + struct nand_chip *chip = mtd_to_nand(mtd); + struct ls1x_nand_controller *nandc = nand_get_controller_data(chip); + struct dma_tx_state state; + enum dma_status status; + + status = + dmaengine_tx_status(nandc->dma_chan, nandc->dma_cookie, ); + if (likely(status == DMA_COMPLETE)) + dev_dbg(mtd->dev.parent, "DMA complete with cookie=%d\n",
[PATCH] MIPS: Loongson1B: Provide DMA filter callbacks via platform data
From: Kelvin CheungThis patch provides DMA filter callbacks via platform data to make NAND driver independent of single DMA engine driver. Signed-off-by: Kelvin Cheung --- arch/mips/include/asm/mach-loongson32/dma.h | 4 arch/mips/include/asm/mach-loongson32/nand.h | 3 +-- arch/mips/loongson32/ls1b/board.c| 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h index ad1dec7..d3ae391 100644 --- a/arch/mips/include/asm/mach-loongson32/dma.h +++ b/arch/mips/include/asm/mach-loongson32/dma.h @@ -12,6 +12,8 @@ #ifndef __ASM_MACH_LOONGSON32_DMA_H #define __ASM_MACH_LOONGSON32_DMA_H +#include + #define LS1X_DMA_CHANNEL0 0 #define LS1X_DMA_CHANNEL1 1 #define LS1X_DMA_CHANNEL2 2 @@ -22,4 +24,6 @@ struct plat_ls1x_dma { extern struct plat_ls1x_dma ls1b_dma_pdata; +bool ls1x_dma_filter(struct dma_chan *chan, void *param); + #endif /* __ASM_MACH_LOONGSON32_DMA_H */ diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h index e274912..a1f8704 100644 --- a/arch/mips/include/asm/mach-loongson32/nand.h +++ b/arch/mips/include/asm/mach-loongson32/nand.h @@ -21,10 +21,9 @@ struct plat_ls1x_nand { int hold_cycle; int wait_cycle; + bool (*dma_filter)(struct dma_chan *chan, void *param); }; extern struct plat_ls1x_nand ls1b_nand_pdata; -bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param); - #endif /* __ASM_MACH_LOONGSON32_NAND_H */ diff --git a/arch/mips/loongson32/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c index 38a1d40..0a57337 100644 --- a/arch/mips/loongson32/ls1b/board.c +++ b/arch/mips/loongson32/ls1b/board.c @@ -38,6 +38,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = { .nr_parts = ARRAY_SIZE(ls1x_nand_parts), .hold_cycle = 0x2, .wait_cycle = 0xc, + .dma_filter = ls1x_dma_filter, }; static const struct gpio_led ls1x_gpio_leds[] __initconst = { -- 1.9.1
[PATCH] MIPS: Loongson1B: Remove ARCH_WANT_OPTIONAL_GPIOLIB
From: Kelvin CheungThis patch removes ARCH_WANT_OPTIONAL_GPIOLIB due to upstream changes. Signed-off-by: Kelvin Cheung --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5663f41..34ed662 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1404,7 +1404,6 @@ config CPU_LOONGSON1B bool "Loongson 1B" depends on SYS_HAS_CPU_LOONGSON1B select CPU_LOONGSON1 - select ARCH_WANT_OPTIONAL_GPIOLIB select LEDS_GPIO_REGISTER help The Loongson 1B is a 32-bit SoC, which implements the MIPS32 -- 1.9.1
[PATCH] MIPS: Loongson1B: Provide DMA filter callbacks via platform data
From: Kelvin Cheung This patch provides DMA filter callbacks via platform data to make NAND driver independent of single DMA engine driver. Signed-off-by: Kelvin Cheung --- arch/mips/include/asm/mach-loongson32/dma.h | 4 arch/mips/include/asm/mach-loongson32/nand.h | 3 +-- arch/mips/loongson32/ls1b/board.c| 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h index ad1dec7..d3ae391 100644 --- a/arch/mips/include/asm/mach-loongson32/dma.h +++ b/arch/mips/include/asm/mach-loongson32/dma.h @@ -12,6 +12,8 @@ #ifndef __ASM_MACH_LOONGSON32_DMA_H #define __ASM_MACH_LOONGSON32_DMA_H +#include + #define LS1X_DMA_CHANNEL0 0 #define LS1X_DMA_CHANNEL1 1 #define LS1X_DMA_CHANNEL2 2 @@ -22,4 +24,6 @@ struct plat_ls1x_dma { extern struct plat_ls1x_dma ls1b_dma_pdata; +bool ls1x_dma_filter(struct dma_chan *chan, void *param); + #endif /* __ASM_MACH_LOONGSON32_DMA_H */ diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h index e274912..a1f8704 100644 --- a/arch/mips/include/asm/mach-loongson32/nand.h +++ b/arch/mips/include/asm/mach-loongson32/nand.h @@ -21,10 +21,9 @@ struct plat_ls1x_nand { int hold_cycle; int wait_cycle; + bool (*dma_filter)(struct dma_chan *chan, void *param); }; extern struct plat_ls1x_nand ls1b_nand_pdata; -bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param); - #endif /* __ASM_MACH_LOONGSON32_NAND_H */ diff --git a/arch/mips/loongson32/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c index 38a1d40..0a57337 100644 --- a/arch/mips/loongson32/ls1b/board.c +++ b/arch/mips/loongson32/ls1b/board.c @@ -38,6 +38,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = { .nr_parts = ARRAY_SIZE(ls1x_nand_parts), .hold_cycle = 0x2, .wait_cycle = 0xc, + .dma_filter = ls1x_dma_filter, }; static const struct gpio_led ls1x_gpio_leds[] __initconst = { -- 1.9.1
[PATCH] MIPS: Loongson1B: Remove ARCH_WANT_OPTIONAL_GPIOLIB
From: Kelvin Cheung This patch removes ARCH_WANT_OPTIONAL_GPIOLIB due to upstream changes. Signed-off-by: Kelvin Cheung --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5663f41..34ed662 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1404,7 +1404,6 @@ config CPU_LOONGSON1B bool "Loongson 1B" depends on SYS_HAS_CPU_LOONGSON1B select CPU_LOONGSON1 - select ARCH_WANT_OPTIONAL_GPIOLIB select LEDS_GPIO_REGISTER help The Loongson 1B is a 32-bit SoC, which implements the MIPS32 -- 1.9.1
[PATCH V3] dmaengine: Loongson1: add Loongson1 dmaengine driver
From: Kelvin CheungThis patch adds DMA Engine driver for Loongson1B. Signed-off-by: Kelvin Cheung --- V3: Rename ls1x_dma_filter_fn to ls1x_dma_filter. V2: Change the config from 'DMA_LOONGSON1' to 'LOONGSON1_DMA', and rearrange it in alphabetical order in Kconfig and Makefile. Fix comment style. --- drivers/dma/Kconfig | 9 + drivers/dma/Makefile| 1 + drivers/dma/loongson1-dma.c | 546 3 files changed, 556 insertions(+) create mode 100644 drivers/dma/loongson1-dma.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 8c98779..852a79e 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -286,6 +286,15 @@ config K3_DMA Support the DMA engine for Hisilicon K3 platform devices. +config LOONGSON1_DMA + tristate "Loongson1 DMA support" + depends on MACH_LOONGSON32 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + This selects support for the DMA controller in Loongson1 SoCs, + and is required by Loongson1 NAND Flash and AC97 support. + config LPC18XX_DMAMUX bool "NXP LPC18xx/43xx DMA MUX for PL080" depends on ARCH_LPC18XX || COMPILE_TEST diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 614f28b..955a5d8 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o +obj-$(CONFIG_LOONGSON1_DMA) += loongson1-dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o diff --git a/drivers/dma/loongson1-dma.c b/drivers/dma/loongson1-dma.c new file mode 100644 index 000..edef616 --- /dev/null +++ b/drivers/dma/loongson1-dma.c @@ -0,0 +1,546 @@ +/* + * DMA Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dmaengine.h" +#include "virt-dma.h" + +/* Loongson 1 DMA Register Definitions */ +#define DMA_CTRL 0x0 + +/* DMA Control Register Bits */ +#define DMA_STOP BIT(4) +#define DMA_START BIT(3) +#define ASK_VALID BIT(2) + +#define DMA_ADDR_MASK (0xffc0) + +/* DMA H/W Descriptor Bits */ +#define NEXT_ENBIT(0) + +/* DMA Command Register Bits */ +#define DMA_RAM2DEVBIT(12) +#define DMA_TRANS_OVER BIT(3) +#define DMA_SINGLE_TRANS_OVER BIT(2) +#define DMA_INTBIT(1) +#define DMA_INT_MASK BIT(0) + +struct ls1x_dma_hwdesc { + u32 next; /* next descriptor address */ + u32 saddr; /* memory DMA address */ + u32 daddr; /* device DMA address */ + u32 length; + u32 stride; + u32 cycles; + u32 cmd; + u32 phys; /* used by driver */ +} __aligned(64); + +struct ls1x_dma_desc { + struct virt_dma_desc vdesc; + struct ls1x_dma_chan *chan; + + enum dma_transfer_direction dir; + enum dma_transaction_type type; + + unsigned int nr_descs; /* number of descriptors */ + unsigned int nr_done; /* number of completed descriptors */ + struct ls1x_dma_hwdesc *desc[0];/* DMA coherent descriptors */ +}; + +struct ls1x_dma_chan { + struct virt_dma_chan vchan; + unsigned int id; + void __iomem *reg_base; + unsigned int irq; + struct dma_pool *desc_pool; + + struct dma_slave_config config; + + struct ls1x_dma_desc *dma_desc; + unsigned int curr_hwdesc; +}; + +struct ls1x_dma { + struct dma_device dma_dev; + struct clk *clk; + void __iomem *reg_base; + + unsigned int nr_dma_chans; + struct ls1x_dma_chan dma_chan[0]; +}; + +#define to_ls1x_dma_chan(chan) \ + container_of(chan, struct ls1x_dma_chan, vchan.chan) + +#define to_ls1x_dma_desc(vdesc)\ + container_of(vdesc, struct ls1x_dma_desc, vdesc) + +/* macros for registers read/write */ +#define chan_writel(chan, off, val)\ + __raw_writel((val), (chan)->reg_base + (off)) + +#define chan_readl(chan, off) \ + __raw_readl((chan)->reg_base + (off)) + +bool ls1x_dma_filter(struct dma_chan *chan, void *param) +{ + struct ls1x_dma_chan *dma_chan = to_ls1x_dma_chan(chan); + unsigned int chan_id = *(unsigned int *)param; + + if (chan_id == dma_chan->id) + return true; +
[PATCH V3] dmaengine: Loongson1: add Loongson1 dmaengine driver
From: Kelvin Cheung This patch adds DMA Engine driver for Loongson1B. Signed-off-by: Kelvin Cheung --- V3: Rename ls1x_dma_filter_fn to ls1x_dma_filter. V2: Change the config from 'DMA_LOONGSON1' to 'LOONGSON1_DMA', and rearrange it in alphabetical order in Kconfig and Makefile. Fix comment style. --- drivers/dma/Kconfig | 9 + drivers/dma/Makefile| 1 + drivers/dma/loongson1-dma.c | 546 3 files changed, 556 insertions(+) create mode 100644 drivers/dma/loongson1-dma.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 8c98779..852a79e 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -286,6 +286,15 @@ config K3_DMA Support the DMA engine for Hisilicon K3 platform devices. +config LOONGSON1_DMA + tristate "Loongson1 DMA support" + depends on MACH_LOONGSON32 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + This selects support for the DMA controller in Loongson1 SoCs, + and is required by Loongson1 NAND Flash and AC97 support. + config LPC18XX_DMAMUX bool "NXP LPC18xx/43xx DMA MUX for PL080" depends on ARCH_LPC18XX || COMPILE_TEST diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 614f28b..955a5d8 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o +obj-$(CONFIG_LOONGSON1_DMA) += loongson1-dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o diff --git a/drivers/dma/loongson1-dma.c b/drivers/dma/loongson1-dma.c new file mode 100644 index 000..edef616 --- /dev/null +++ b/drivers/dma/loongson1-dma.c @@ -0,0 +1,546 @@ +/* + * DMA Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dmaengine.h" +#include "virt-dma.h" + +/* Loongson 1 DMA Register Definitions */ +#define DMA_CTRL 0x0 + +/* DMA Control Register Bits */ +#define DMA_STOP BIT(4) +#define DMA_START BIT(3) +#define ASK_VALID BIT(2) + +#define DMA_ADDR_MASK (0xffc0) + +/* DMA H/W Descriptor Bits */ +#define NEXT_ENBIT(0) + +/* DMA Command Register Bits */ +#define DMA_RAM2DEVBIT(12) +#define DMA_TRANS_OVER BIT(3) +#define DMA_SINGLE_TRANS_OVER BIT(2) +#define DMA_INTBIT(1) +#define DMA_INT_MASK BIT(0) + +struct ls1x_dma_hwdesc { + u32 next; /* next descriptor address */ + u32 saddr; /* memory DMA address */ + u32 daddr; /* device DMA address */ + u32 length; + u32 stride; + u32 cycles; + u32 cmd; + u32 phys; /* used by driver */ +} __aligned(64); + +struct ls1x_dma_desc { + struct virt_dma_desc vdesc; + struct ls1x_dma_chan *chan; + + enum dma_transfer_direction dir; + enum dma_transaction_type type; + + unsigned int nr_descs; /* number of descriptors */ + unsigned int nr_done; /* number of completed descriptors */ + struct ls1x_dma_hwdesc *desc[0];/* DMA coherent descriptors */ +}; + +struct ls1x_dma_chan { + struct virt_dma_chan vchan; + unsigned int id; + void __iomem *reg_base; + unsigned int irq; + struct dma_pool *desc_pool; + + struct dma_slave_config config; + + struct ls1x_dma_desc *dma_desc; + unsigned int curr_hwdesc; +}; + +struct ls1x_dma { + struct dma_device dma_dev; + struct clk *clk; + void __iomem *reg_base; + + unsigned int nr_dma_chans; + struct ls1x_dma_chan dma_chan[0]; +}; + +#define to_ls1x_dma_chan(chan) \ + container_of(chan, struct ls1x_dma_chan, vchan.chan) + +#define to_ls1x_dma_desc(vdesc)\ + container_of(vdesc, struct ls1x_dma_desc, vdesc) + +/* macros for registers read/write */ +#define chan_writel(chan, off, val)\ + __raw_writel((val), (chan)->reg_base + (off)) + +#define chan_readl(chan, off) \ + __raw_readl((chan)->reg_base + (off)) + +bool ls1x_dma_filter(struct dma_chan *chan, void *param) +{ + struct ls1x_dma_chan *dma_chan = to_ls1x_dma_chan(chan); + unsigned int chan_id = *(unsigned int *)param; + + if (chan_id == dma_chan->id) + return true; + else + return false; +} + +static void
[PATCH V1 3/5] cpufreq: Loongson1: Use dev_get_platdata() to get platform_data
From: Kelvin CheungThis patch uses dev_get_platdata() to get the platform_data instead of referencing it directly. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 4c3087f..1b63b4a 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -134,7 +134,7 @@ static int ls1x_cpufreq_remove(struct platform_device *pdev) static int ls1x_cpufreq_probe(struct platform_device *pdev) { - struct plat_ls1x_cpufreq *pdata = pdev->dev.platform_data; + struct plat_ls1x_cpufreq *pdata = dev_get_platdata(>dev); struct clk *clk; int ret; -- 1.9.1
[PATCH V1 3/5] cpufreq: Loongson1: Use dev_get_platdata() to get platform_data
From: Kelvin Cheung This patch uses dev_get_platdata() to get the platform_data instead of referencing it directly. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 4c3087f..1b63b4a 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -134,7 +134,7 @@ static int ls1x_cpufreq_remove(struct platform_device *pdev) static int ls1x_cpufreq_probe(struct platform_device *pdev) { - struct plat_ls1x_cpufreq *pdata = pdev->dev.platform_data; + struct plat_ls1x_cpufreq *pdata = dev_get_platdata(>dev); struct clk *clk; int ret; -- 1.9.1
[PATCH V1 4/5] cpufreq: Loongson1: Use devm_kzalloc() instead of global structure
From: Kelvin CheungThis patch uses devm_kzalloc() instead of global structure. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 63 - 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 1b63b4a..f0d0156 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -20,7 +20,7 @@ #include #include -static struct { +struct ls1x_cpufreq { struct device *dev; struct clk *clk;/* CPU clk */ struct clk *mux_clk;/* MUX of CPU clk */ @@ -28,7 +28,9 @@ static struct { struct clk *osc_clk;/* OSC clk */ unsigned int max_freq; unsigned int min_freq; -} ls1x_cpufreq; +}; + +static struct ls1x_cpufreq *cpufreq; static int ls1x_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) @@ -46,6 +48,7 @@ static struct notifier_block ls1x_cpufreq_notifier_block = { static int ls1x_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { + struct device *cpu_dev = get_cpu_device(policy->cpu); unsigned int old_freq, new_freq; old_freq = policy->cur; @@ -60,25 +63,26 @@ static int ls1x_cpufreq_target(struct cpufreq_policy *policy, * - Reparent CPU clk back to CPU DIV clk */ - dev_dbg(ls1x_cpufreq.dev, "%u KHz --> %u KHz\n", old_freq, new_freq); - clk_set_parent(policy->clk, ls1x_cpufreq.osc_clk); + clk_set_parent(policy->clk, cpufreq->osc_clk); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU, LS1X_CLK_PLL_DIV); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU), LS1X_CLK_PLL_DIV); - clk_set_rate(ls1x_cpufreq.mux_clk, new_freq * 1000); - clk_set_parent(policy->clk, ls1x_cpufreq.mux_clk); + clk_set_rate(cpufreq->mux_clk, new_freq * 1000); + clk_set_parent(policy->clk, cpufreq->mux_clk); + dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq); return 0; } static int ls1x_cpufreq_init(struct cpufreq_policy *policy) { + struct device *cpu_dev = get_cpu_device(policy->cpu); struct cpufreq_frequency_table *freq_tbl; unsigned int pll_freq, freq; int steps, i, ret; - pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; + pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); @@ -87,18 +91,17 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); - if ((freq < ls1x_cpufreq.min_freq) || - (freq > ls1x_cpufreq.max_freq)) + if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq)) freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID; else freq_tbl[i].frequency = freq; - dev_dbg(ls1x_cpufreq.dev, + dev_dbg(cpu_dev, "cpufreq table: index %d: frequency %d\n", i, freq_tbl[i].frequency); } freq_tbl[i].frequency = CPUFREQ_TABLE_END; - policy->clk = ls1x_cpufreq.clk; + policy->clk = cpufreq->clk; ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); @@ -141,51 +144,56 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) return -EINVAL; - ls1x_cpufreq.dev = >dev; + cpufreq = + devm_kzalloc(>dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL); + if (!cpufreq) + return -ENOMEM; + + cpufreq->dev = >dev; clk = devm_clk_get(>dev, pdata->clk_name); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n", + dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.clk = clk; + cpufreq->clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n", - __clk_get_name(ls1x_cpufreq.clk)); + dev_err(>dev, "unable to get parent of %s clock\n", + __clk_get_name(cpufreq->clk)); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.mux_clk = clk; + cpufreq->mux_clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { -
[PATCH V1 4/5] cpufreq: Loongson1: Use devm_kzalloc() instead of global structure
From: Kelvin Cheung This patch uses devm_kzalloc() instead of global structure. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 63 - 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 1b63b4a..f0d0156 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -20,7 +20,7 @@ #include #include -static struct { +struct ls1x_cpufreq { struct device *dev; struct clk *clk;/* CPU clk */ struct clk *mux_clk;/* MUX of CPU clk */ @@ -28,7 +28,9 @@ static struct { struct clk *osc_clk;/* OSC clk */ unsigned int max_freq; unsigned int min_freq; -} ls1x_cpufreq; +}; + +static struct ls1x_cpufreq *cpufreq; static int ls1x_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) @@ -46,6 +48,7 @@ static struct notifier_block ls1x_cpufreq_notifier_block = { static int ls1x_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { + struct device *cpu_dev = get_cpu_device(policy->cpu); unsigned int old_freq, new_freq; old_freq = policy->cur; @@ -60,25 +63,26 @@ static int ls1x_cpufreq_target(struct cpufreq_policy *policy, * - Reparent CPU clk back to CPU DIV clk */ - dev_dbg(ls1x_cpufreq.dev, "%u KHz --> %u KHz\n", old_freq, new_freq); - clk_set_parent(policy->clk, ls1x_cpufreq.osc_clk); + clk_set_parent(policy->clk, cpufreq->osc_clk); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU, LS1X_CLK_PLL_DIV); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU), LS1X_CLK_PLL_DIV); - clk_set_rate(ls1x_cpufreq.mux_clk, new_freq * 1000); - clk_set_parent(policy->clk, ls1x_cpufreq.mux_clk); + clk_set_rate(cpufreq->mux_clk, new_freq * 1000); + clk_set_parent(policy->clk, cpufreq->mux_clk); + dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq); return 0; } static int ls1x_cpufreq_init(struct cpufreq_policy *policy) { + struct device *cpu_dev = get_cpu_device(policy->cpu); struct cpufreq_frequency_table *freq_tbl; unsigned int pll_freq, freq; int steps, i, ret; - pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; + pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); @@ -87,18 +91,17 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); - if ((freq < ls1x_cpufreq.min_freq) || - (freq > ls1x_cpufreq.max_freq)) + if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq)) freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID; else freq_tbl[i].frequency = freq; - dev_dbg(ls1x_cpufreq.dev, + dev_dbg(cpu_dev, "cpufreq table: index %d: frequency %d\n", i, freq_tbl[i].frequency); } freq_tbl[i].frequency = CPUFREQ_TABLE_END; - policy->clk = ls1x_cpufreq.clk; + policy->clk = cpufreq->clk; ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); @@ -141,51 +144,56 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) return -EINVAL; - ls1x_cpufreq.dev = >dev; + cpufreq = + devm_kzalloc(>dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL); + if (!cpufreq) + return -ENOMEM; + + cpufreq->dev = >dev; clk = devm_clk_get(>dev, pdata->clk_name); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n", + dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.clk = clk; + cpufreq->clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n", - __clk_get_name(ls1x_cpufreq.clk)); + dev_err(>dev, "unable to get parent of %s clock\n", + __clk_get_name(cpufreq->clk)); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.mux_clk = clk; + cpufreq->mux_clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get parent of %s
[PATCH V1 5/5] cpufreq: Loongson1: Replace goto out with return in ls1x_cpufreq_probe()
From: Kelvin CheungThis patch replaces goto out with return in ls1x_cpufreq_probe(). Signed-off-by: Kelvin Cheung --- V1: Move the minor updates into patch#1. Fix the brace problem in ls1x_cpufreq_probe(). --- drivers/cpufreq/loongson1-cpufreq.c | 29 + 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index f0d0156..be89416 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -141,8 +141,10 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) struct clk *clk; int ret; - if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) + if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) { + dev_err(>dev, "platform data missing\n"); return -EINVAL; + } cpufreq = devm_kzalloc(>dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL); @@ -155,8 +157,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->clk = clk; @@ -164,8 +165,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->mux_clk = clk; @@ -173,8 +173,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->mux_clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->pll_clk = clk; @@ -182,8 +181,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->osc_clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->osc_clk = clk; @@ -194,19 +192,18 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (ret) { dev_err(>dev, "failed to register CPUFreq driver: %d\n", ret); - goto out; + return ret; } ret = cpufreq_register_notifier(_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - if (!ret) - goto out; - - dev_err(>dev, "failed to register cpufreq notifier: %d\n", ret); + if (ret) { + dev_err(>dev, + "failed to register CPUFreq notifier: %d\n",ret); + cpufreq_unregister_driver(_cpufreq_driver); + } - cpufreq_unregister_driver(_cpufreq_driver); -out: return ret; } -- 1.9.1
[PATCH V1 1/5] cpufreq: Loongson1: Rename the file to loongson1-cpufreq.c
From: Kelvin CheungThis patch renames the file to loongson1-cpufreq.c, and also includes some minor updates. Signed-off-by: Kelvin Cheung --- V1: Merge the minor updates into this patch. --- drivers/cpufreq/Makefile| 2 +- drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} | 10 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} (96%) diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 9e63fb1..bebe9c8 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ)+= ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ)+= loongson2_cpufreq.o -obj-$(CONFIG_LOONGSON1_CPUFREQ)+= ls1x-cpufreq.o +obj-$(CONFIG_LOONGSON1_CPUFREQ)+= loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ)+= sparc-us3-cpufreq.o diff --git a/drivers/cpufreq/ls1x-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c similarity index 96% rename from drivers/cpufreq/ls1x-cpufreq.c rename to drivers/cpufreq/loongson1-cpufreq.c index 262581b..57fae9b 100644 --- a/drivers/cpufreq/ls1x-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -1,7 +1,7 @@ /* * CPU Frequency Scaling for Loongson 1 SoC * - * Copyright (C) 2014 Zhang, Keguang + * Copyright (C) 2014-2016 Zhang, Keguang * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -208,15 +208,15 @@ out: } static struct platform_driver ls1x_cpufreq_platdrv = { - .driver = { + .probe = ls1x_cpufreq_probe, + .remove = ls1x_cpufreq_remove, + .driver = { .name = "ls1x-cpufreq", }, - .probe = ls1x_cpufreq_probe, - .remove = ls1x_cpufreq_remove, }; module_platform_driver(ls1x_cpufreq_platdrv); MODULE_AUTHOR("Kelvin Cheung "); -MODULE_DESCRIPTION("Loongson 1 CPUFreq driver"); +MODULE_DESCRIPTION("Loongson1 CPUFreq driver"); MODULE_LICENSE("GPL"); -- 1.9.1
[PATCH V1 2/5] cpufreq: Loongson1: Replace kzalloc() with kcalloc()
From: Kelvin CheungThis patch replaces kzalloc() with kcalloc() when allocating frequency table, and remove unnecessary 'out of memory' message. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 57fae9b..4c3087f 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -81,13 +81,9 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; - freq_tbl = kzalloc(sizeof(*freq_tbl) * steps, GFP_KERNEL); - if (!freq_tbl) { - dev_err(ls1x_cpufreq.dev, - "failed to alloc cpufreq_frequency_table\n"); - ret = -ENOMEM; - goto out; - } + freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); + if (!freq_tbl) + return -ENOMEM; for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); @@ -106,7 +102,7 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); -out: + return ret; } -- 1.9.1
[PATCH V1 5/5] cpufreq: Loongson1: Replace goto out with return in ls1x_cpufreq_probe()
From: Kelvin Cheung This patch replaces goto out with return in ls1x_cpufreq_probe(). Signed-off-by: Kelvin Cheung --- V1: Move the minor updates into patch#1. Fix the brace problem in ls1x_cpufreq_probe(). --- drivers/cpufreq/loongson1-cpufreq.c | 29 + 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index f0d0156..be89416 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -141,8 +141,10 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) struct clk *clk; int ret; - if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) + if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) { + dev_err(>dev, "platform data missing\n"); return -EINVAL; + } cpufreq = devm_kzalloc(>dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL); @@ -155,8 +157,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->clk = clk; @@ -164,8 +165,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->mux_clk = clk; @@ -173,8 +173,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->mux_clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->pll_clk = clk; @@ -182,8 +181,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->osc_clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->osc_clk = clk; @@ -194,19 +192,18 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (ret) { dev_err(>dev, "failed to register CPUFreq driver: %d\n", ret); - goto out; + return ret; } ret = cpufreq_register_notifier(_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - if (!ret) - goto out; - - dev_err(>dev, "failed to register cpufreq notifier: %d\n", ret); + if (ret) { + dev_err(>dev, + "failed to register CPUFreq notifier: %d\n",ret); + cpufreq_unregister_driver(_cpufreq_driver); + } - cpufreq_unregister_driver(_cpufreq_driver); -out: return ret; } -- 1.9.1
[PATCH V1 1/5] cpufreq: Loongson1: Rename the file to loongson1-cpufreq.c
From: Kelvin Cheung This patch renames the file to loongson1-cpufreq.c, and also includes some minor updates. Signed-off-by: Kelvin Cheung --- V1: Merge the minor updates into this patch. --- drivers/cpufreq/Makefile| 2 +- drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} | 10 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} (96%) diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 9e63fb1..bebe9c8 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ)+= ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ)+= loongson2_cpufreq.o -obj-$(CONFIG_LOONGSON1_CPUFREQ)+= ls1x-cpufreq.o +obj-$(CONFIG_LOONGSON1_CPUFREQ)+= loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ)+= sparc-us3-cpufreq.o diff --git a/drivers/cpufreq/ls1x-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c similarity index 96% rename from drivers/cpufreq/ls1x-cpufreq.c rename to drivers/cpufreq/loongson1-cpufreq.c index 262581b..57fae9b 100644 --- a/drivers/cpufreq/ls1x-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -1,7 +1,7 @@ /* * CPU Frequency Scaling for Loongson 1 SoC * - * Copyright (C) 2014 Zhang, Keguang + * Copyright (C) 2014-2016 Zhang, Keguang * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -208,15 +208,15 @@ out: } static struct platform_driver ls1x_cpufreq_platdrv = { - .driver = { + .probe = ls1x_cpufreq_probe, + .remove = ls1x_cpufreq_remove, + .driver = { .name = "ls1x-cpufreq", }, - .probe = ls1x_cpufreq_probe, - .remove = ls1x_cpufreq_remove, }; module_platform_driver(ls1x_cpufreq_platdrv); MODULE_AUTHOR("Kelvin Cheung "); -MODULE_DESCRIPTION("Loongson 1 CPUFreq driver"); +MODULE_DESCRIPTION("Loongson1 CPUFreq driver"); MODULE_LICENSE("GPL"); -- 1.9.1
[PATCH V1 2/5] cpufreq: Loongson1: Replace kzalloc() with kcalloc()
From: Kelvin Cheung This patch replaces kzalloc() with kcalloc() when allocating frequency table, and remove unnecessary 'out of memory' message. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 57fae9b..4c3087f 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -81,13 +81,9 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; - freq_tbl = kzalloc(sizeof(*freq_tbl) * steps, GFP_KERNEL); - if (!freq_tbl) { - dev_err(ls1x_cpufreq.dev, - "failed to alloc cpufreq_frequency_table\n"); - ret = -ENOMEM; - goto out; - } + freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); + if (!freq_tbl) + return -ENOMEM; for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); @@ -106,7 +102,7 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); -out: + return ret; } -- 1.9.1
[PATCH 5/5] cpufreq: Loongson1: Replace goto out with return in ls1x_cpufreq_probe()
From: Kelvin CheungThis patch replaces goto out with return in ls1x_cpufreq_probe(), and also includes some minor fixes. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 37 - 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 5074f5e..1bc90af 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -1,7 +1,7 @@ /* * CPU Frequency Scaling for Loongson 1 SoC * - * Copyright (C) 2014 Zhang, Keguang + * Copyright (C) 2014-2016 Zhang, Keguang * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -141,7 +141,8 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) struct clk *clk; int ret; - if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) + if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) { + dev_err(>dev, "platform data missing\n"); return -EINVAL; cpufreq = @@ -155,8 +156,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->clk = clk; @@ -164,8 +164,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->mux_clk = clk; @@ -173,8 +172,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->mux_clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->pll_clk = clk; @@ -182,8 +180,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->osc_clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->osc_clk = clk; @@ -194,32 +191,30 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (ret) { dev_err(>dev, "failed to register CPUFreq driver: %d\n", ret); - goto out; + return ret; } ret = cpufreq_register_notifier(_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - if (!ret) - goto out; - - dev_err(>dev, "failed to register cpufreq notifier: %d\n", ret); + if (ret) { + dev_err(>dev, "failed to register CPUFreq notifier: %d\n", ret); + cpufreq_unregister_driver(_cpufreq_driver); + } - cpufreq_unregister_driver(_cpufreq_driver); -out: return ret; } static struct platform_driver ls1x_cpufreq_platdrv = { - .driver = { + .probe = ls1x_cpufreq_probe, + .remove = ls1x_cpufreq_remove, + .driver = { .name = "ls1x-cpufreq", }, - .probe = ls1x_cpufreq_probe, - .remove = ls1x_cpufreq_remove, }; module_platform_driver(ls1x_cpufreq_platdrv); MODULE_AUTHOR("Kelvin Cheung "); -MODULE_DESCRIPTION("Loongson 1 CPUFreq driver"); +MODULE_DESCRIPTION("Loongson1 CPUFreq driver"); MODULE_LICENSE("GPL"); -- 1.9.1
[PATCH 2/5] cpufreq: Loongson1: Replace kzalloc() with kcalloc()
From: Kelvin CheungThis patch replaces kzalloc() with kcalloc() when allocating frequency table, and remove unnecessary 'out of memory' message. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 262581b..2d83744 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -81,13 +81,9 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; - freq_tbl = kzalloc(sizeof(*freq_tbl) * steps, GFP_KERNEL); - if (!freq_tbl) { - dev_err(ls1x_cpufreq.dev, - "failed to alloc cpufreq_frequency_table\n"); - ret = -ENOMEM; - goto out; - } + freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); + if (!freq_tbl) + return -ENOMEM; for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); @@ -106,7 +102,7 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); -out: + return ret; } -- 1.9.1
[PATCH 5/5] cpufreq: Loongson1: Replace goto out with return in ls1x_cpufreq_probe()
From: Kelvin Cheung This patch replaces goto out with return in ls1x_cpufreq_probe(), and also includes some minor fixes. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 37 - 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 5074f5e..1bc90af 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -1,7 +1,7 @@ /* * CPU Frequency Scaling for Loongson 1 SoC * - * Copyright (C) 2014 Zhang, Keguang + * Copyright (C) 2014-2016 Zhang, Keguang * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -141,7 +141,8 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) struct clk *clk; int ret; - if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) + if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) { + dev_err(>dev, "platform data missing\n"); return -EINVAL; cpufreq = @@ -155,8 +156,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->clk = clk; @@ -164,8 +164,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->mux_clk = clk; @@ -173,8 +172,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get parent of %s clock\n", __clk_get_name(cpufreq->mux_clk)); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->pll_clk = clk; @@ -182,8 +180,7 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (IS_ERR(clk)) { dev_err(>dev, "unable to get %s clock\n", pdata->osc_clk_name); - ret = PTR_ERR(clk); - goto out; + return PTR_ERR(clk); } cpufreq->osc_clk = clk; @@ -194,32 +191,30 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (ret) { dev_err(>dev, "failed to register CPUFreq driver: %d\n", ret); - goto out; + return ret; } ret = cpufreq_register_notifier(_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - if (!ret) - goto out; - - dev_err(>dev, "failed to register cpufreq notifier: %d\n", ret); + if (ret) { + dev_err(>dev, "failed to register CPUFreq notifier: %d\n", ret); + cpufreq_unregister_driver(_cpufreq_driver); + } - cpufreq_unregister_driver(_cpufreq_driver); -out: return ret; } static struct platform_driver ls1x_cpufreq_platdrv = { - .driver = { + .probe = ls1x_cpufreq_probe, + .remove = ls1x_cpufreq_remove, + .driver = { .name = "ls1x-cpufreq", }, - .probe = ls1x_cpufreq_probe, - .remove = ls1x_cpufreq_remove, }; module_platform_driver(ls1x_cpufreq_platdrv); MODULE_AUTHOR("Kelvin Cheung "); -MODULE_DESCRIPTION("Loongson 1 CPUFreq driver"); +MODULE_DESCRIPTION("Loongson1 CPUFreq driver"); MODULE_LICENSE("GPL"); -- 1.9.1
[PATCH 2/5] cpufreq: Loongson1: Replace kzalloc() with kcalloc()
From: Kelvin Cheung This patch replaces kzalloc() with kcalloc() when allocating frequency table, and remove unnecessary 'out of memory' message. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 262581b..2d83744 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -81,13 +81,9 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; - freq_tbl = kzalloc(sizeof(*freq_tbl) * steps, GFP_KERNEL); - if (!freq_tbl) { - dev_err(ls1x_cpufreq.dev, - "failed to alloc cpufreq_frequency_table\n"); - ret = -ENOMEM; - goto out; - } + freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); + if (!freq_tbl) + return -ENOMEM; for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); @@ -106,7 +102,7 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); -out: + return ret; } -- 1.9.1
[PATCH 1/5] cpufreq: Loongson1: Rename the file to loongson1-cpufreq.c
From: Kelvin CheungThis patch renames the file to loongson1-cpufreq.c Signed-off-by: Kelvin Cheung --- drivers/cpufreq/Makefile| 2 +- drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} (100%) diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 9e63fb1..bebe9c8 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ)+= ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ)+= loongson2_cpufreq.o -obj-$(CONFIG_LOONGSON1_CPUFREQ)+= ls1x-cpufreq.o +obj-$(CONFIG_LOONGSON1_CPUFREQ)+= loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ)+= sparc-us3-cpufreq.o diff --git a/drivers/cpufreq/ls1x-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c similarity index 100% rename from drivers/cpufreq/ls1x-cpufreq.c rename to drivers/cpufreq/loongson1-cpufreq.c -- 1.9.1
[PATCH 4/5] cpufreq: Loongson1: Use devm_kzalloc() instead of global structure
From: Kelvin CheungThis patch uses devm_kzalloc() instead of global structure. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 63 - 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index f0d40fd..5074f5e 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -20,7 +20,7 @@ #include #include -static struct { +struct ls1x_cpufreq { struct device *dev; struct clk *clk;/* CPU clk */ struct clk *mux_clk;/* MUX of CPU clk */ @@ -28,7 +28,9 @@ static struct { struct clk *osc_clk;/* OSC clk */ unsigned int max_freq; unsigned int min_freq; -} ls1x_cpufreq; +}; + +static struct ls1x_cpufreq *cpufreq; static int ls1x_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) @@ -46,6 +48,7 @@ static struct notifier_block ls1x_cpufreq_notifier_block = { static int ls1x_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { + struct device *cpu_dev = get_cpu_device(policy->cpu); unsigned int old_freq, new_freq; old_freq = policy->cur; @@ -60,25 +63,26 @@ static int ls1x_cpufreq_target(struct cpufreq_policy *policy, * - Reparent CPU clk back to CPU DIV clk */ - dev_dbg(ls1x_cpufreq.dev, "%u KHz --> %u KHz\n", old_freq, new_freq); - clk_set_parent(policy->clk, ls1x_cpufreq.osc_clk); + clk_set_parent(policy->clk, cpufreq->osc_clk); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU, LS1X_CLK_PLL_DIV); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU), LS1X_CLK_PLL_DIV); - clk_set_rate(ls1x_cpufreq.mux_clk, new_freq * 1000); - clk_set_parent(policy->clk, ls1x_cpufreq.mux_clk); + clk_set_rate(cpufreq->mux_clk, new_freq * 1000); + clk_set_parent(policy->clk, cpufreq->mux_clk); + dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq); return 0; } static int ls1x_cpufreq_init(struct cpufreq_policy *policy) { + struct device *cpu_dev = get_cpu_device(policy->cpu); struct cpufreq_frequency_table *freq_tbl; unsigned int pll_freq, freq; int steps, i, ret; - pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; + pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); @@ -87,18 +91,17 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); - if ((freq < ls1x_cpufreq.min_freq) || - (freq > ls1x_cpufreq.max_freq)) + if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq)) freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID; else freq_tbl[i].frequency = freq; - dev_dbg(ls1x_cpufreq.dev, + dev_dbg(cpu_dev, "cpufreq table: index %d: frequency %d\n", i, freq_tbl[i].frequency); } freq_tbl[i].frequency = CPUFREQ_TABLE_END; - policy->clk = ls1x_cpufreq.clk; + policy->clk = cpufreq->clk; ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); @@ -141,51 +144,56 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) return -EINVAL; - ls1x_cpufreq.dev = >dev; + cpufreq = + devm_kzalloc(>dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL); + if (!cpufreq) + return -ENOMEM; + + cpufreq->dev = >dev; clk = devm_clk_get(>dev, pdata->clk_name); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n", + dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.clk = clk; + cpufreq->clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n", - __clk_get_name(ls1x_cpufreq.clk)); + dev_err(>dev, "unable to get parent of %s clock\n", + __clk_get_name(cpufreq->clk)); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.mux_clk = clk; + cpufreq->mux_clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { -
[PATCH 1/5] cpufreq: Loongson1: Rename the file to loongson1-cpufreq.c
From: Kelvin Cheung This patch renames the file to loongson1-cpufreq.c Signed-off-by: Kelvin Cheung --- drivers/cpufreq/Makefile| 2 +- drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/cpufreq/{ls1x-cpufreq.c => loongson1-cpufreq.c} (100%) diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 9e63fb1..bebe9c8 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ)+= ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ)+= loongson2_cpufreq.o -obj-$(CONFIG_LOONGSON1_CPUFREQ)+= ls1x-cpufreq.o +obj-$(CONFIG_LOONGSON1_CPUFREQ)+= loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ)+= sparc-us3-cpufreq.o diff --git a/drivers/cpufreq/ls1x-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c similarity index 100% rename from drivers/cpufreq/ls1x-cpufreq.c rename to drivers/cpufreq/loongson1-cpufreq.c -- 1.9.1
[PATCH 4/5] cpufreq: Loongson1: Use devm_kzalloc() instead of global structure
From: Kelvin Cheung This patch uses devm_kzalloc() instead of global structure. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 63 - 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index f0d40fd..5074f5e 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -20,7 +20,7 @@ #include #include -static struct { +struct ls1x_cpufreq { struct device *dev; struct clk *clk;/* CPU clk */ struct clk *mux_clk;/* MUX of CPU clk */ @@ -28,7 +28,9 @@ static struct { struct clk *osc_clk;/* OSC clk */ unsigned int max_freq; unsigned int min_freq; -} ls1x_cpufreq; +}; + +static struct ls1x_cpufreq *cpufreq; static int ls1x_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) @@ -46,6 +48,7 @@ static struct notifier_block ls1x_cpufreq_notifier_block = { static int ls1x_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { + struct device *cpu_dev = get_cpu_device(policy->cpu); unsigned int old_freq, new_freq; old_freq = policy->cur; @@ -60,25 +63,26 @@ static int ls1x_cpufreq_target(struct cpufreq_policy *policy, * - Reparent CPU clk back to CPU DIV clk */ - dev_dbg(ls1x_cpufreq.dev, "%u KHz --> %u KHz\n", old_freq, new_freq); - clk_set_parent(policy->clk, ls1x_cpufreq.osc_clk); + clk_set_parent(policy->clk, cpufreq->osc_clk); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU, LS1X_CLK_PLL_DIV); __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU), LS1X_CLK_PLL_DIV); - clk_set_rate(ls1x_cpufreq.mux_clk, new_freq * 1000); - clk_set_parent(policy->clk, ls1x_cpufreq.mux_clk); + clk_set_rate(cpufreq->mux_clk, new_freq * 1000); + clk_set_parent(policy->clk, cpufreq->mux_clk); + dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq); return 0; } static int ls1x_cpufreq_init(struct cpufreq_policy *policy) { + struct device *cpu_dev = get_cpu_device(policy->cpu); struct cpufreq_frequency_table *freq_tbl; unsigned int pll_freq, freq; int steps, i, ret; - pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000; + pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000; steps = 1 << DIV_CPU_WIDTH; freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); @@ -87,18 +91,17 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy) for (i = 0; i < (steps - 1); i++) { freq = pll_freq / (i + 1); - if ((freq < ls1x_cpufreq.min_freq) || - (freq > ls1x_cpufreq.max_freq)) + if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq)) freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID; else freq_tbl[i].frequency = freq; - dev_dbg(ls1x_cpufreq.dev, + dev_dbg(cpu_dev, "cpufreq table: index %d: frequency %d\n", i, freq_tbl[i].frequency); } freq_tbl[i].frequency = CPUFREQ_TABLE_END; - policy->clk = ls1x_cpufreq.clk; + policy->clk = cpufreq->clk; ret = cpufreq_generic_init(policy, freq_tbl, 0); if (ret) kfree(freq_tbl); @@ -141,51 +144,56 @@ static int ls1x_cpufreq_probe(struct platform_device *pdev) if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) return -EINVAL; - ls1x_cpufreq.dev = >dev; + cpufreq = + devm_kzalloc(>dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL); + if (!cpufreq) + return -ENOMEM; + + cpufreq->dev = >dev; clk = devm_clk_get(>dev, pdata->clk_name); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n", + dev_err(>dev, "unable to get %s clock\n", pdata->clk_name); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.clk = clk; + cpufreq->clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n", - __clk_get_name(ls1x_cpufreq.clk)); + dev_err(>dev, "unable to get parent of %s clock\n", + __clk_get_name(cpufreq->clk)); ret = PTR_ERR(clk); goto out; } - ls1x_cpufreq.mux_clk = clk; + cpufreq->mux_clk = clk; clk = clk_get_parent(clk); if (IS_ERR(clk)) { - dev_err(ls1x_cpufreq.dev, "unable to get parent of %s
[PATCH 3/5] cpufreq: Loongson1: Use dev_get_platdata() to get platform_data
From: Kelvin CheungThis patch uses dev_get_platdata() to get the platform_data instead of referencing it directly. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 2d83744..f0d40fd 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -134,7 +134,7 @@ static int ls1x_cpufreq_remove(struct platform_device *pdev) static int ls1x_cpufreq_probe(struct platform_device *pdev) { - struct plat_ls1x_cpufreq *pdata = pdev->dev.platform_data; + struct plat_ls1x_cpufreq *pdata = dev_get_platdata(>dev); struct clk *clk; int ret; -- 1.9.1
[PATCH 3/5] cpufreq: Loongson1: Use dev_get_platdata() to get platform_data
From: Kelvin Cheung This patch uses dev_get_platdata() to get the platform_data instead of referencing it directly. Signed-off-by: Kelvin Cheung --- drivers/cpufreq/loongson1-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index 2d83744..f0d40fd 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -134,7 +134,7 @@ static int ls1x_cpufreq_remove(struct platform_device *pdev) static int ls1x_cpufreq_probe(struct platform_device *pdev) { - struct plat_ls1x_cpufreq *pdata = pdev->dev.platform_data; + struct plat_ls1x_cpufreq *pdata = dev_get_platdata(>dev); struct clk *clk; int ret; -- 1.9.1
[PATCH 2/7] cpufreq: Loongson1: Update cpufreq of Loongson1B
From: Kelvin Cheung- Rename the file to loongson1-cpufreq.c - Use kcalloc() instead of kzalloc() - Use devm_kzalloc() instead of global structure - Use dev_get_platdata() to access the platform_data field instead of referencing it directly - Remove superfluous error messages Signed-off-by: Kelvin Cheung --- drivers/cpufreq/Makefile| 2 +- drivers/cpufreq/loongson1-cpufreq.c | 230 drivers/cpufreq/ls1x-cpufreq.c | 222 -- 3 files changed, 231 insertions(+), 223 deletions(-) create mode 100644 drivers/cpufreq/loongson1-cpufreq.c delete mode 100644 drivers/cpufreq/ls1x-cpufreq.c diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 9e63fb1..bebe9c8 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ)+= ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ)+= loongson2_cpufreq.o -obj-$(CONFIG_LOONGSON1_CPUFREQ)+= ls1x-cpufreq.o +obj-$(CONFIG_LOONGSON1_CPUFREQ)+= loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ)+= sparc-us3-cpufreq.o diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c new file mode 100644 index 000..d029211 --- /dev/null +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -0,0 +1,230 @@ +/* + * CPU Frequency Scaling for Loongson 1 SoC + * + * Copyright (C) 2014-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct ls1x_cpufreq { + struct device *dev; + struct clk *clk;/* CPU clk */ + struct clk *mux_clk;/* MUX of CPU clk */ + struct clk *pll_clk;/* PLL clk */ + struct clk *osc_clk;/* OSC clk */ + unsigned int max_freq; + unsigned int min_freq; +}; + +static struct ls1x_cpufreq *cpufreq; + +static int ls1x_cpufreq_notifier(struct notifier_block *nb, +unsigned long val, void *data) +{ + if (val == CPUFREQ_POSTCHANGE) + current_cpu_data.udelay_val = loops_per_jiffy; + + return NOTIFY_OK; +} + +static struct notifier_block ls1x_cpufreq_notifier_block = { + .notifier_call = ls1x_cpufreq_notifier +}; + +static int ls1x_cpufreq_target(struct cpufreq_policy *policy, + unsigned int index) +{ + struct device *cpu_dev = get_cpu_device(policy->cpu); + unsigned int old_freq, new_freq; + + old_freq = policy->cur; + new_freq = policy->freq_table[index].frequency; + + /* +* The procedure of reconfiguring CPU clk is as below. +* +* - Reparent CPU clk to OSC clk +* - Reset CPU clock (very important) +* - Reconfigure CPU DIV +* - Reparent CPU clk back to CPU DIV clk +*/ + + clk_set_parent(policy->clk, cpufreq->osc_clk); + __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU, +LS1X_CLK_PLL_DIV); + __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU), +LS1X_CLK_PLL_DIV); + clk_set_rate(cpufreq->mux_clk, new_freq * 1000); + clk_set_parent(policy->clk, cpufreq->mux_clk); + dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq); + + return 0; +} + +static int ls1x_cpufreq_init(struct cpufreq_policy *policy) +{ + struct device *cpu_dev = get_cpu_device(policy->cpu); + struct cpufreq_frequency_table *freq_tbl; + unsigned int pll_freq, freq; + int steps, i, ret; + + pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000; + + steps = 1 << DIV_CPU_WIDTH; + freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); + if (!freq_tbl) + return -ENOMEM; + + for (i = 0; i < (steps - 1); i++) { + freq = pll_freq / (i + 1); + if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq)) + freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID; + else + freq_tbl[i].frequency = freq; + dev_dbg(cpu_dev, + "cpufreq table: index %d: frequency %d\n", i, + freq_tbl[i].frequency); + } + freq_tbl[i].frequency = CPUFREQ_TABLE_END; + + policy->clk = cpufreq->clk; +
[PATCH 2/7] cpufreq: Loongson1: Update cpufreq of Loongson1B
From: Kelvin Cheung - Rename the file to loongson1-cpufreq.c - Use kcalloc() instead of kzalloc() - Use devm_kzalloc() instead of global structure - Use dev_get_platdata() to access the platform_data field instead of referencing it directly - Remove superfluous error messages Signed-off-by: Kelvin Cheung --- drivers/cpufreq/Makefile| 2 +- drivers/cpufreq/loongson1-cpufreq.c | 230 drivers/cpufreq/ls1x-cpufreq.c | 222 -- 3 files changed, 231 insertions(+), 223 deletions(-) create mode 100644 drivers/cpufreq/loongson1-cpufreq.c delete mode 100644 drivers/cpufreq/ls1x-cpufreq.c diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 9e63fb1..bebe9c8 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ)+= ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ)+= loongson2_cpufreq.o -obj-$(CONFIG_LOONGSON1_CPUFREQ)+= ls1x-cpufreq.o +obj-$(CONFIG_LOONGSON1_CPUFREQ)+= loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ)+= sparc-us3-cpufreq.o diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c new file mode 100644 index 000..d029211 --- /dev/null +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -0,0 +1,230 @@ +/* + * CPU Frequency Scaling for Loongson 1 SoC + * + * Copyright (C) 2014-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct ls1x_cpufreq { + struct device *dev; + struct clk *clk;/* CPU clk */ + struct clk *mux_clk;/* MUX of CPU clk */ + struct clk *pll_clk;/* PLL clk */ + struct clk *osc_clk;/* OSC clk */ + unsigned int max_freq; + unsigned int min_freq; +}; + +static struct ls1x_cpufreq *cpufreq; + +static int ls1x_cpufreq_notifier(struct notifier_block *nb, +unsigned long val, void *data) +{ + if (val == CPUFREQ_POSTCHANGE) + current_cpu_data.udelay_val = loops_per_jiffy; + + return NOTIFY_OK; +} + +static struct notifier_block ls1x_cpufreq_notifier_block = { + .notifier_call = ls1x_cpufreq_notifier +}; + +static int ls1x_cpufreq_target(struct cpufreq_policy *policy, + unsigned int index) +{ + struct device *cpu_dev = get_cpu_device(policy->cpu); + unsigned int old_freq, new_freq; + + old_freq = policy->cur; + new_freq = policy->freq_table[index].frequency; + + /* +* The procedure of reconfiguring CPU clk is as below. +* +* - Reparent CPU clk to OSC clk +* - Reset CPU clock (very important) +* - Reconfigure CPU DIV +* - Reparent CPU clk back to CPU DIV clk +*/ + + clk_set_parent(policy->clk, cpufreq->osc_clk); + __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU, +LS1X_CLK_PLL_DIV); + __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU), +LS1X_CLK_PLL_DIV); + clk_set_rate(cpufreq->mux_clk, new_freq * 1000); + clk_set_parent(policy->clk, cpufreq->mux_clk); + dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq); + + return 0; +} + +static int ls1x_cpufreq_init(struct cpufreq_policy *policy) +{ + struct device *cpu_dev = get_cpu_device(policy->cpu); + struct cpufreq_frequency_table *freq_tbl; + unsigned int pll_freq, freq; + int steps, i, ret; + + pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000; + + steps = 1 << DIV_CPU_WIDTH; + freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL); + if (!freq_tbl) + return -ENOMEM; + + for (i = 0; i < (steps - 1); i++) { + freq = pll_freq / (i + 1); + if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq)) + freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID; + else + freq_tbl[i].frequency = freq; + dev_dbg(cpu_dev, + "cpufreq table: index %d: frequency %d\n", i, + freq_tbl[i].frequency); + } + freq_tbl[i].frequency = CPUFREQ_TABLE_END; + + policy->clk = cpufreq->clk; + ret = cpufreq_generic_init(policy, freq_tbl, 0); + if (ret) +
[PATCH 5/7] gpio: Loongson1: add Loongson1 GPIO driver
From: Kelvin CheungThis patch adds GPIO driver for Loongson1B. Signed-off-by: Kelvin Cheung --- drivers/gpio/Kconfig | 7 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-loongson1.c | 102 ++ 3 files changed, 110 insertions(+) create mode 100644 drivers/gpio/gpio-loongson1.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5f3429f..373b8a7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -510,6 +510,13 @@ config GPIO_ZX help Say yes here to support the GPIO device on ZTE ZX SoCs. +config GPIO_LOONGSON1 + tristate "Loongson1 GPIO support" + depends on MACH_LOONGSON32 + select GPIO_GENERIC + help + Say Y or M here to support GPIO on Loongson1 SoCs. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1e0b74f..40ab913 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -127,3 +127,4 @@ obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ)+= gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o +obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c new file mode 100644 index 000..10c09bd --- /dev/null +++ b/drivers/gpio/gpio-loongson1.c @@ -0,0 +1,102 @@ +/* + * GPIO Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include + +/* Loongson 1 GPIO Register Definitions */ +#define GPIO_CFG 0x0 +#define GPIO_DIR 0x10 +#define GPIO_DATA 0x20 +#define GPIO_OUTPUT0x30 + +static void __iomem *gpio_reg_base; + +static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(>bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) | pinmask, +gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(>bgpio_lock, flags); + + return 0; +} + +static void ls1x_gpio_free(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(>bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) & ~pinmask, +gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(>bgpio_lock, flags); +} + +static int ls1x_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = >dev; + struct gpio_chip *gc; + struct resource *res; + int ret; + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to get I/O memory\n"); + return -EINVAL; + } + + gpio_reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(gpio_reg_base)) + return PTR_ERR(gpio_reg_base); + + ret = bgpio_init(gc, dev, 4, gpio_reg_base + GPIO_DATA, +gpio_reg_base + GPIO_OUTPUT, NULL, +NULL, gpio_reg_base + GPIO_DIR, 0); + if (ret) + goto err; + + gc->owner = THIS_MODULE; + gc->request = ls1x_gpio_request; + gc->free = ls1x_gpio_free; + gc->base = pdev->id * 32; + + ret = devm_gpiochip_add_data(dev, gc, NULL); + if (ret) + goto err; + + platform_set_drvdata(pdev, gc); + dev_info(dev, "Loongson1 GPIO driver registered\n"); + + return 0; +err: + dev_err(dev, "failed to register GPIO device\n"); + return ret; +} + +static struct platform_driver ls1x_gpio_driver = { + .probe = ls1x_gpio_probe, + .driver = { + .name = "ls1x-gpio", + }, +}; + +module_platform_driver(ls1x_gpio_driver); + +MODULE_AUTHOR("Kelvin Cheung "); +MODULE_DESCRIPTION("Loongson1 GPIO driver"); +MODULE_LICENSE("GPL"); -- 1.9.1
[PATCH 5/7] gpio: Loongson1: add Loongson1 GPIO driver
From: Kelvin Cheung This patch adds GPIO driver for Loongson1B. Signed-off-by: Kelvin Cheung --- drivers/gpio/Kconfig | 7 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-loongson1.c | 102 ++ 3 files changed, 110 insertions(+) create mode 100644 drivers/gpio/gpio-loongson1.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5f3429f..373b8a7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -510,6 +510,13 @@ config GPIO_ZX help Say yes here to support the GPIO device on ZTE ZX SoCs. +config GPIO_LOONGSON1 + tristate "Loongson1 GPIO support" + depends on MACH_LOONGSON32 + select GPIO_GENERIC + help + Say Y or M here to support GPIO on Loongson1 SoCs. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1e0b74f..40ab913 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -127,3 +127,4 @@ obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ)+= gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o +obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c new file mode 100644 index 000..10c09bd --- /dev/null +++ b/drivers/gpio/gpio-loongson1.c @@ -0,0 +1,102 @@ +/* + * GPIO Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include + +/* Loongson 1 GPIO Register Definitions */ +#define GPIO_CFG 0x0 +#define GPIO_DIR 0x10 +#define GPIO_DATA 0x20 +#define GPIO_OUTPUT0x30 + +static void __iomem *gpio_reg_base; + +static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(>bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) | pinmask, +gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(>bgpio_lock, flags); + + return 0; +} + +static void ls1x_gpio_free(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long pinmask = gc->pin2mask(gc, offset); + unsigned long flags; + + spin_lock_irqsave(>bgpio_lock, flags); + __raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) & ~pinmask, +gpio_reg_base + GPIO_CFG); + spin_unlock_irqrestore(>bgpio_lock, flags); +} + +static int ls1x_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = >dev; + struct gpio_chip *gc; + struct resource *res; + int ret; + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "failed to get I/O memory\n"); + return -EINVAL; + } + + gpio_reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(gpio_reg_base)) + return PTR_ERR(gpio_reg_base); + + ret = bgpio_init(gc, dev, 4, gpio_reg_base + GPIO_DATA, +gpio_reg_base + GPIO_OUTPUT, NULL, +NULL, gpio_reg_base + GPIO_DIR, 0); + if (ret) + goto err; + + gc->owner = THIS_MODULE; + gc->request = ls1x_gpio_request; + gc->free = ls1x_gpio_free; + gc->base = pdev->id * 32; + + ret = devm_gpiochip_add_data(dev, gc, NULL); + if (ret) + goto err; + + platform_set_drvdata(pdev, gc); + dev_info(dev, "Loongson1 GPIO driver registered\n"); + + return 0; +err: + dev_err(dev, "failed to register GPIO device\n"); + return ret; +} + +static struct platform_driver ls1x_gpio_driver = { + .probe = ls1x_gpio_probe, + .driver = { + .name = "ls1x-gpio", + }, +}; + +module_platform_driver(ls1x_gpio_driver); + +MODULE_AUTHOR("Kelvin Cheung "); +MODULE_DESCRIPTION("Loongson1 GPIO driver"); +MODULE_LICENSE("GPL"); -- 1.9.1
[PATCH 1/7] clk: Loongson1: Update clocks of Loongson1B
From: Kelvin Cheung- Rename the file to clk-loongson1.c - Add AC97, DMA and NAND clock - Update clock names - Remove superfluous error messages Signed-off-by: Kelvin Cheung --- drivers/clk/Makefile| 2 +- drivers/clk/clk-loongson1.c | 163 drivers/clk/clk-ls1x.c | 162 --- 3 files changed, 164 insertions(+), 163 deletions(-) create mode 100644 drivers/clk/clk-loongson1.c delete mode 100644 drivers/clk/clk-ls1x.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 46869d6..5845b2c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP)+= clk-cs2000-cp.o obj-$(CONFIG_ARCH_CLPS711X)+= clk-clps711x.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK)+= clk-highbank.o -obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o +obj-$(CONFIG_MACH_LOONGSON32) += clk-loongson1.o obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o diff --git a/drivers/clk/clk-loongson1.c b/drivers/clk/clk-loongson1.c new file mode 100644 index 000..ce2135c --- /dev/null +++ b/drivers/clk/clk-loongson1.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2012-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include + +#define OSC(33 * 100) +#define DIV_APB2 + +static DEFINE_SPINLOCK(_lock); + +static int ls1x_pll_clk_enable(struct clk_hw *hw) +{ + return 0; +} + +static void ls1x_pll_clk_disable(struct clk_hw *hw) +{ +} + +static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 pll, rate; + + pll = __raw_readl(LS1X_CLK_PLL_FREQ); + rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10); + rate *= OSC; + rate >>= 1; + + return rate; +} + +static const struct clk_ops ls1x_pll_clk_ops = { + .enable = ls1x_pll_clk_enable, + .disable = ls1x_pll_clk_disable, + .recalc_rate = ls1x_pll_recalc_rate, +}; + +static struct clk *__init clk_register_pll(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags) +{ + struct clk_hw *hw; + struct clk *clk; + struct clk_init_data init; + + /* allocate the divider */ + hw = kzalloc(sizeof(*hw), GFP_KERNEL); + if (!hw) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = _pll_clk_ops; + init.flags = flags | CLK_IS_BASIC; + init.parent_names = (parent_name ? _name : NULL); + init.num_parents = (parent_name ? 1 : 0); + hw->init = + + /* register the clock */ + clk = clk_register(dev, hw); + + if (IS_ERR(clk)) + kfree(hw); + + return clk; +} + +static const char *const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; +static const char *const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; +static const char *const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; + +void __init ls1x_clk_init(void) +{ + struct clk *clk; + + clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT, + OSC); + clk_register_clkdev(clk, "osc_33m_clk", NULL); + + /* clock derived from 33 MHz OSC clk */ + clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0); + clk_register_clkdev(clk, "pll_clk", NULL); + + /* clock derived from PLL clk */ + /* _ +* ___| | +* OSC ___/ | MUX |___ CPU CLK +*\___ PLL ___ CPU DIV ___| | +*|_| +*/ + clk = clk_register_divider(NULL, "cpu_clk_div", "pll_clk", + CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV, + DIV_CPU_SHIFT, DIV_CPU_WIDTH, + CLK_DIVIDER_ONE_BASED | + CLK_DIVIDER_ROUND_CLOSEST, &_lock); + clk_register_clkdev(clk, "cpu_clk_div", NULL); + clk = clk_register_mux(NULL, "cpu_clk", cpu_parents, + ARRAY_SIZE(cpu_parents), +
[PATCH 6/7] MIPS: Loongson1B: Some updates/fixes for LS1B
From: Kelvin Cheung- Add DMA device - Add NAND device - Add GPIO device - Add LED device - Update the defconfig and rename it to loongson1b_defconfig - Fix ioremap size - Other minor fixes Signed-off-by: Kelvin Cheung --- arch/mips/Kconfig | 2 + arch/mips/configs/loongson1b_defconfig| 125 ++ arch/mips/configs/ls1b_defconfig | 110 --- arch/mips/include/asm/mach-loongson32/cpufreq.h | 1 - arch/mips/include/asm/mach-loongson32/dma.h | 25 + arch/mips/include/asm/mach-loongson32/irq.h | 1 - arch/mips/include/asm/mach-loongson32/loongson1.h | 4 +- arch/mips/include/asm/mach-loongson32/nand.h | 30 ++ arch/mips/include/asm/mach-loongson32/platform.h | 14 ++- arch/mips/include/asm/mach-loongson32/regs-clk.h | 24 ++--- arch/mips/include/asm/mach-loongson32/regs-mux.h | 84 +++ arch/mips/include/asm/mach-loongson32/regs-pwm.h | 12 +-- arch/mips/loongson32/common/platform.c| 105 +- arch/mips/loongson32/common/reset.c | 13 +-- arch/mips/loongson32/common/time.c| 27 ++--- arch/mips/loongson32/ls1b/board.c | 67 +++- 16 files changed, 440 insertions(+), 204 deletions(-) create mode 100644 arch/mips/configs/loongson1b_defconfig delete mode 100644 arch/mips/configs/ls1b_defconfig create mode 100644 arch/mips/include/asm/mach-loongson32/dma.h create mode 100644 arch/mips/include/asm/mach-loongson32/nand.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 35d92a1..53b16e8 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1387,6 +1387,8 @@ config CPU_LOONGSON1B bool "Loongson 1B" depends on SYS_HAS_CPU_LOONGSON1B select CPU_LOONGSON1 + select ARCH_WANT_OPTIONAL_GPIOLIB + select LEDS_GPIO_REGISTER help The Loongson 1B is a 32-bit SoC, which implements the MIPS32 release 2 instruction set. diff --git a/arch/mips/configs/loongson1b_defconfig b/arch/mips/configs/loongson1b_defconfig new file mode 100644 index 000..c442f27 --- /dev/null +++ b/arch/mips/configs/loongson1b_defconfig @@ -0,0 +1,125 @@ +CONFIG_MACH_LOONGSON32=y +CONFIG_PREEMPT=y +# CONFIG_SECCOMP is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_XZ=y +CONFIG_SYSVIPC=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_NAMESPACES=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_LOONGSON1=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_SCSI=m +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=m +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_STMMAC_ETH=y +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_LOONGSON1=y +# CONFIG_HWMON is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_HID_GENERIC=m +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_STORAGE=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_LOONGSON1=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y
[PATCH 3/7] dmaengine: Loongson1: add Loongson1 dmaengine driver
From: Kelvin CheungThis patch adds DMA Engine driver for Loongson1B. Signed-off-by: Kelvin Cheung --- drivers/dma/Kconfig | 9 + drivers/dma/Makefile| 1 + drivers/dma/loongson1-dma.c | 546 3 files changed, 556 insertions(+) create mode 100644 drivers/dma/loongson1-dma.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index d96d87c..835d212 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -527,6 +527,15 @@ config ZX_DMA help Support the DMA engine for ZTE ZX296702 platform devices. +config DMA_LOONGSON1 + tristate "Loongson1 DMA support" + depends on MACH_LOONGSON32 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + This selects support for the DMA controller in Loongson1 SoCs, + and is required by Loongson1 NAND Flash and AC97 support. + # driver files source "drivers/dma/bestcomm/Kconfig" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 6084127..b0eceb0 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o obj-$(CONFIG_TI_EDMA) += edma.o obj-$(CONFIG_XGENE_DMA) += xgene-dma.o obj-$(CONFIG_ZX_DMA) += zx296702_dma.o +obj-$(CONFIG_DMA_LOONGSON1) += loongson1-dma.o obj-y += qcom/ obj-y += xilinx/ diff --git a/drivers/dma/loongson1-dma.c b/drivers/dma/loongson1-dma.c new file mode 100644 index 000..687eed7 --- /dev/null +++ b/drivers/dma/loongson1-dma.c @@ -0,0 +1,546 @@ +/* + * DMA Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dmaengine.h" +#include "virt-dma.h" + +/* Loongson 1 DMA Register Definitions */ +#define DMA_CTRL 0x0 + +/* DMA Control Register Bits */ +#define DMA_STOP BIT(4) +#define DMA_START BIT(3) +#define ASK_VALID BIT(2) + +#define DMA_ADDR_MASK (0xffc0) + +/* DMA H/W Descriptor Bits */ +#define NEXT_ENBIT(0) + +/* DMA Command Register Bits */ +#define DMA_RAM2DEVBIT(12) +#define DMA_TRANS_OVER BIT(3) +#define DMA_SINGLE_TRANS_OVER BIT(2) +#define DMA_INTBIT(1) +#define DMA_INT_MASK BIT(0) + +struct ls1x_dma_hwdesc { + u32 next; /* next descriptor address */ + u32 saddr; /* memory DMA address */ + u32 daddr; /* device DMA address */ + u32 length; + u32 stride; + u32 cycles; + u32 cmd; + u32 phys; /* used by driver */ +} __aligned(64); + +struct ls1x_dma_desc { + struct virt_dma_desc vdesc; + struct ls1x_dma_chan *chan; + + enum dma_transfer_direction dir; + enum dma_transaction_type type; + + unsigned int nr_descs; /* number of descriptors */ + unsigned int nr_done; /* number of completed descriptors */ + struct ls1x_dma_hwdesc *desc[0];/* DMA coherent descriptors */ +}; + +struct ls1x_dma_chan { + struct virt_dma_chan vchan; + unsigned int id; + void __iomem *reg_base; + unsigned int irq; + struct dma_pool *desc_pool; + + struct dma_slave_config config; + + struct ls1x_dma_desc *dma_desc; + unsigned int curr_hwdesc; +}; + +struct ls1x_dma { + struct dma_device dma_dev; + struct clk *clk; + void __iomem *reg_base; + + unsigned int nr_dma_chans; + struct ls1x_dma_chan dma_chan[0]; +}; + +#define to_ls1x_dma_chan(chan) \ + container_of(chan, struct ls1x_dma_chan, vchan.chan) + +#define to_ls1x_dma_desc(vdesc)\ + container_of(vdesc, struct ls1x_dma_desc, vdesc) + +/* macros for registers read/write */ +#define chan_writel(chan, off, val)\ + __raw_writel((val), (chan)->reg_base + (off)) + +#define chan_readl(chan, off) \ + __raw_readl((chan)->reg_base + (off)) + +bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param) +{ + struct ls1x_dma_chan *dma_chan = to_ls1x_dma_chan(chan); + unsigned int chan_id = *(unsigned int *)param; + + if (chan_id == dma_chan->id) + return true; + else + return false; +} + +static void ls1x_dma_free_chan_resources(struct dma_chan *chan) +{ + struct ls1x_dma_chan *dma_chan = to_ls1x_dma_chan(chan); + + vchan_free_chan_resources(_chan->vchan); + dma_pool_destroy(dma_chan->desc_pool); + dma_chan->desc_pool = NULL; +} + +static int ls1x_dma_alloc_chan_resources(struct
[PATCH 0/7] MIPS: Loongson1B: add NAND, DMA and GPIO support
From: Kelvin CheungThis patchset is to add NAND, DMA and GPIO support for Loongson1B, and moreover, include some updates/fixes. This applies on top of mips-for-linux-next. Thanks! Kelvin Cheung (7): clk: Loongson1: Update clocks of Loongson1B cpufreq: Loongson1: Update cpufreq of Loongson1B dmaengine: Loongson1: add Loongson1 dmaengine driver mtd: nand: add Loongson1 NAND driver gpio: Loongson1: add Loongson1 GPIO driver MIPS: Loongson1B: Some updates/fixes for LS1B MAINTAINERS: add Loongson1 architecture entry MAINTAINERS | 9 + arch/mips/Kconfig | 2 + arch/mips/configs/loongson1b_defconfig| 125 + arch/mips/configs/ls1b_defconfig | 110 - arch/mips/include/asm/mach-loongson32/cpufreq.h | 1 - arch/mips/include/asm/mach-loongson32/dma.h | 25 + arch/mips/include/asm/mach-loongson32/irq.h | 1 - arch/mips/include/asm/mach-loongson32/loongson1.h | 4 +- arch/mips/include/asm/mach-loongson32/nand.h | 30 ++ arch/mips/include/asm/mach-loongson32/platform.h | 14 +- arch/mips/include/asm/mach-loongson32/regs-clk.h | 24 +- arch/mips/include/asm/mach-loongson32/regs-mux.h | 84 ++-- arch/mips/include/asm/mach-loongson32/regs-pwm.h | 12 +- arch/mips/loongson32/common/platform.c| 105 - arch/mips/loongson32/common/reset.c | 13 +- arch/mips/loongson32/common/time.c| 27 +- arch/mips/loongson32/ls1b/board.c | 67 ++- drivers/clk/Makefile | 2 +- drivers/clk/clk-loongson1.c | 163 +++ drivers/clk/clk-ls1x.c| 162 --- drivers/cpufreq/Makefile | 2 +- drivers/cpufreq/loongson1-cpufreq.c | 230 + drivers/cpufreq/ls1x-cpufreq.c| 222 - drivers/dma/Kconfig | 9 + drivers/dma/Makefile | 1 + drivers/dma/loongson1-dma.c | 546 ++ drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-loongson1.c | 102 drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 522 + 32 files changed, 2041 insertions(+), 590 deletions(-) create mode 100644 arch/mips/configs/loongson1b_defconfig delete mode 100644 arch/mips/configs/ls1b_defconfig create mode 100644 arch/mips/include/asm/mach-loongson32/dma.h create mode 100644 arch/mips/include/asm/mach-loongson32/nand.h create mode 100644 drivers/clk/clk-loongson1.c delete mode 100644 drivers/clk/clk-ls1x.c create mode 100644 drivers/cpufreq/loongson1-cpufreq.c delete mode 100644 drivers/cpufreq/ls1x-cpufreq.c create mode 100644 drivers/dma/loongson1-dma.c create mode 100644 drivers/gpio/gpio-loongson1.c create mode 100644 drivers/mtd/nand/loongson1_nand.c -- 1.9.1
[PATCH 1/7] clk: Loongson1: Update clocks of Loongson1B
From: Kelvin Cheung - Rename the file to clk-loongson1.c - Add AC97, DMA and NAND clock - Update clock names - Remove superfluous error messages Signed-off-by: Kelvin Cheung --- drivers/clk/Makefile| 2 +- drivers/clk/clk-loongson1.c | 163 drivers/clk/clk-ls1x.c | 162 --- 3 files changed, 164 insertions(+), 163 deletions(-) create mode 100644 drivers/clk/clk-loongson1.c delete mode 100644 drivers/clk/clk-ls1x.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 46869d6..5845b2c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP)+= clk-cs2000-cp.o obj-$(CONFIG_ARCH_CLPS711X)+= clk-clps711x.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK)+= clk-highbank.o -obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o +obj-$(CONFIG_MACH_LOONGSON32) += clk-loongson1.o obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o diff --git a/drivers/clk/clk-loongson1.c b/drivers/clk/clk-loongson1.c new file mode 100644 index 000..ce2135c --- /dev/null +++ b/drivers/clk/clk-loongson1.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2012-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include + +#define OSC(33 * 100) +#define DIV_APB2 + +static DEFINE_SPINLOCK(_lock); + +static int ls1x_pll_clk_enable(struct clk_hw *hw) +{ + return 0; +} + +static void ls1x_pll_clk_disable(struct clk_hw *hw) +{ +} + +static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 pll, rate; + + pll = __raw_readl(LS1X_CLK_PLL_FREQ); + rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10); + rate *= OSC; + rate >>= 1; + + return rate; +} + +static const struct clk_ops ls1x_pll_clk_ops = { + .enable = ls1x_pll_clk_enable, + .disable = ls1x_pll_clk_disable, + .recalc_rate = ls1x_pll_recalc_rate, +}; + +static struct clk *__init clk_register_pll(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags) +{ + struct clk_hw *hw; + struct clk *clk; + struct clk_init_data init; + + /* allocate the divider */ + hw = kzalloc(sizeof(*hw), GFP_KERNEL); + if (!hw) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = _pll_clk_ops; + init.flags = flags | CLK_IS_BASIC; + init.parent_names = (parent_name ? _name : NULL); + init.num_parents = (parent_name ? 1 : 0); + hw->init = + + /* register the clock */ + clk = clk_register(dev, hw); + + if (IS_ERR(clk)) + kfree(hw); + + return clk; +} + +static const char *const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; +static const char *const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; +static const char *const dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; + +void __init ls1x_clk_init(void) +{ + struct clk *clk; + + clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT, + OSC); + clk_register_clkdev(clk, "osc_33m_clk", NULL); + + /* clock derived from 33 MHz OSC clk */ + clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0); + clk_register_clkdev(clk, "pll_clk", NULL); + + /* clock derived from PLL clk */ + /* _ +* ___| | +* OSC ___/ | MUX |___ CPU CLK +*\___ PLL ___ CPU DIV ___| | +*|_| +*/ + clk = clk_register_divider(NULL, "cpu_clk_div", "pll_clk", + CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV, + DIV_CPU_SHIFT, DIV_CPU_WIDTH, + CLK_DIVIDER_ONE_BASED | + CLK_DIVIDER_ROUND_CLOSEST, &_lock); + clk_register_clkdev(clk, "cpu_clk_div", NULL); + clk = clk_register_mux(NULL, "cpu_clk", cpu_parents, + ARRAY_SIZE(cpu_parents), + CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, +
[PATCH 6/7] MIPS: Loongson1B: Some updates/fixes for LS1B
From: Kelvin Cheung - Add DMA device - Add NAND device - Add GPIO device - Add LED device - Update the defconfig and rename it to loongson1b_defconfig - Fix ioremap size - Other minor fixes Signed-off-by: Kelvin Cheung --- arch/mips/Kconfig | 2 + arch/mips/configs/loongson1b_defconfig| 125 ++ arch/mips/configs/ls1b_defconfig | 110 --- arch/mips/include/asm/mach-loongson32/cpufreq.h | 1 - arch/mips/include/asm/mach-loongson32/dma.h | 25 + arch/mips/include/asm/mach-loongson32/irq.h | 1 - arch/mips/include/asm/mach-loongson32/loongson1.h | 4 +- arch/mips/include/asm/mach-loongson32/nand.h | 30 ++ arch/mips/include/asm/mach-loongson32/platform.h | 14 ++- arch/mips/include/asm/mach-loongson32/regs-clk.h | 24 ++--- arch/mips/include/asm/mach-loongson32/regs-mux.h | 84 +++ arch/mips/include/asm/mach-loongson32/regs-pwm.h | 12 +-- arch/mips/loongson32/common/platform.c| 105 +- arch/mips/loongson32/common/reset.c | 13 +-- arch/mips/loongson32/common/time.c| 27 ++--- arch/mips/loongson32/ls1b/board.c | 67 +++- 16 files changed, 440 insertions(+), 204 deletions(-) create mode 100644 arch/mips/configs/loongson1b_defconfig delete mode 100644 arch/mips/configs/ls1b_defconfig create mode 100644 arch/mips/include/asm/mach-loongson32/dma.h create mode 100644 arch/mips/include/asm/mach-loongson32/nand.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 35d92a1..53b16e8 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1387,6 +1387,8 @@ config CPU_LOONGSON1B bool "Loongson 1B" depends on SYS_HAS_CPU_LOONGSON1B select CPU_LOONGSON1 + select ARCH_WANT_OPTIONAL_GPIOLIB + select LEDS_GPIO_REGISTER help The Loongson 1B is a 32-bit SoC, which implements the MIPS32 release 2 instruction set. diff --git a/arch/mips/configs/loongson1b_defconfig b/arch/mips/configs/loongson1b_defconfig new file mode 100644 index 000..c442f27 --- /dev/null +++ b/arch/mips/configs/loongson1b_defconfig @@ -0,0 +1,125 @@ +CONFIG_MACH_LOONGSON32=y +CONFIG_PREEMPT=y +# CONFIG_SECCOMP is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_XZ=y +CONFIG_SYSVIPC=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_NAMESPACES=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_LOONGSON1=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_SCSI=m +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=m +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_STMMAC_ETH=y +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_LOONGSON1=y +# CONFIG_HWMON is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_HID_GENERIC=m +CONFIG_USB_HID=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_STORAGE=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_LOONGSON1=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +#
[PATCH 3/7] dmaengine: Loongson1: add Loongson1 dmaengine driver
From: Kelvin Cheung This patch adds DMA Engine driver for Loongson1B. Signed-off-by: Kelvin Cheung --- drivers/dma/Kconfig | 9 + drivers/dma/Makefile| 1 + drivers/dma/loongson1-dma.c | 546 3 files changed, 556 insertions(+) create mode 100644 drivers/dma/loongson1-dma.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index d96d87c..835d212 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -527,6 +527,15 @@ config ZX_DMA help Support the DMA engine for ZTE ZX296702 platform devices. +config DMA_LOONGSON1 + tristate "Loongson1 DMA support" + depends on MACH_LOONGSON32 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + This selects support for the DMA controller in Loongson1 SoCs, + and is required by Loongson1 NAND Flash and AC97 support. + # driver files source "drivers/dma/bestcomm/Kconfig" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 6084127..b0eceb0 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o obj-$(CONFIG_TI_EDMA) += edma.o obj-$(CONFIG_XGENE_DMA) += xgene-dma.o obj-$(CONFIG_ZX_DMA) += zx296702_dma.o +obj-$(CONFIG_DMA_LOONGSON1) += loongson1-dma.o obj-y += qcom/ obj-y += xilinx/ diff --git a/drivers/dma/loongson1-dma.c b/drivers/dma/loongson1-dma.c new file mode 100644 index 000..687eed7 --- /dev/null +++ b/drivers/dma/loongson1-dma.c @@ -0,0 +1,546 @@ +/* + * DMA Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dmaengine.h" +#include "virt-dma.h" + +/* Loongson 1 DMA Register Definitions */ +#define DMA_CTRL 0x0 + +/* DMA Control Register Bits */ +#define DMA_STOP BIT(4) +#define DMA_START BIT(3) +#define ASK_VALID BIT(2) + +#define DMA_ADDR_MASK (0xffc0) + +/* DMA H/W Descriptor Bits */ +#define NEXT_ENBIT(0) + +/* DMA Command Register Bits */ +#define DMA_RAM2DEVBIT(12) +#define DMA_TRANS_OVER BIT(3) +#define DMA_SINGLE_TRANS_OVER BIT(2) +#define DMA_INTBIT(1) +#define DMA_INT_MASK BIT(0) + +struct ls1x_dma_hwdesc { + u32 next; /* next descriptor address */ + u32 saddr; /* memory DMA address */ + u32 daddr; /* device DMA address */ + u32 length; + u32 stride; + u32 cycles; + u32 cmd; + u32 phys; /* used by driver */ +} __aligned(64); + +struct ls1x_dma_desc { + struct virt_dma_desc vdesc; + struct ls1x_dma_chan *chan; + + enum dma_transfer_direction dir; + enum dma_transaction_type type; + + unsigned int nr_descs; /* number of descriptors */ + unsigned int nr_done; /* number of completed descriptors */ + struct ls1x_dma_hwdesc *desc[0];/* DMA coherent descriptors */ +}; + +struct ls1x_dma_chan { + struct virt_dma_chan vchan; + unsigned int id; + void __iomem *reg_base; + unsigned int irq; + struct dma_pool *desc_pool; + + struct dma_slave_config config; + + struct ls1x_dma_desc *dma_desc; + unsigned int curr_hwdesc; +}; + +struct ls1x_dma { + struct dma_device dma_dev; + struct clk *clk; + void __iomem *reg_base; + + unsigned int nr_dma_chans; + struct ls1x_dma_chan dma_chan[0]; +}; + +#define to_ls1x_dma_chan(chan) \ + container_of(chan, struct ls1x_dma_chan, vchan.chan) + +#define to_ls1x_dma_desc(vdesc)\ + container_of(vdesc, struct ls1x_dma_desc, vdesc) + +/* macros for registers read/write */ +#define chan_writel(chan, off, val)\ + __raw_writel((val), (chan)->reg_base + (off)) + +#define chan_readl(chan, off) \ + __raw_readl((chan)->reg_base + (off)) + +bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param) +{ + struct ls1x_dma_chan *dma_chan = to_ls1x_dma_chan(chan); + unsigned int chan_id = *(unsigned int *)param; + + if (chan_id == dma_chan->id) + return true; + else + return false; +} + +static void ls1x_dma_free_chan_resources(struct dma_chan *chan) +{ + struct ls1x_dma_chan *dma_chan = to_ls1x_dma_chan(chan); + + vchan_free_chan_resources(_chan->vchan); + dma_pool_destroy(dma_chan->desc_pool); + dma_chan->desc_pool = NULL; +} + +static int ls1x_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct ls1x_dma_chan *dma_chan =
[PATCH 0/7] MIPS: Loongson1B: add NAND, DMA and GPIO support
From: Kelvin Cheung This patchset is to add NAND, DMA and GPIO support for Loongson1B, and moreover, include some updates/fixes. This applies on top of mips-for-linux-next. Thanks! Kelvin Cheung (7): clk: Loongson1: Update clocks of Loongson1B cpufreq: Loongson1: Update cpufreq of Loongson1B dmaengine: Loongson1: add Loongson1 dmaengine driver mtd: nand: add Loongson1 NAND driver gpio: Loongson1: add Loongson1 GPIO driver MIPS: Loongson1B: Some updates/fixes for LS1B MAINTAINERS: add Loongson1 architecture entry MAINTAINERS | 9 + arch/mips/Kconfig | 2 + arch/mips/configs/loongson1b_defconfig| 125 + arch/mips/configs/ls1b_defconfig | 110 - arch/mips/include/asm/mach-loongson32/cpufreq.h | 1 - arch/mips/include/asm/mach-loongson32/dma.h | 25 + arch/mips/include/asm/mach-loongson32/irq.h | 1 - arch/mips/include/asm/mach-loongson32/loongson1.h | 4 +- arch/mips/include/asm/mach-loongson32/nand.h | 30 ++ arch/mips/include/asm/mach-loongson32/platform.h | 14 +- arch/mips/include/asm/mach-loongson32/regs-clk.h | 24 +- arch/mips/include/asm/mach-loongson32/regs-mux.h | 84 ++-- arch/mips/include/asm/mach-loongson32/regs-pwm.h | 12 +- arch/mips/loongson32/common/platform.c| 105 - arch/mips/loongson32/common/reset.c | 13 +- arch/mips/loongson32/common/time.c| 27 +- arch/mips/loongson32/ls1b/board.c | 67 ++- drivers/clk/Makefile | 2 +- drivers/clk/clk-loongson1.c | 163 +++ drivers/clk/clk-ls1x.c| 162 --- drivers/cpufreq/Makefile | 2 +- drivers/cpufreq/loongson1-cpufreq.c | 230 + drivers/cpufreq/ls1x-cpufreq.c| 222 - drivers/dma/Kconfig | 9 + drivers/dma/Makefile | 1 + drivers/dma/loongson1-dma.c | 546 ++ drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-loongson1.c | 102 drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 522 + 32 files changed, 2041 insertions(+), 590 deletions(-) create mode 100644 arch/mips/configs/loongson1b_defconfig delete mode 100644 arch/mips/configs/ls1b_defconfig create mode 100644 arch/mips/include/asm/mach-loongson32/dma.h create mode 100644 arch/mips/include/asm/mach-loongson32/nand.h create mode 100644 drivers/clk/clk-loongson1.c delete mode 100644 drivers/clk/clk-ls1x.c create mode 100644 drivers/cpufreq/loongson1-cpufreq.c delete mode 100644 drivers/cpufreq/ls1x-cpufreq.c create mode 100644 drivers/dma/loongson1-dma.c create mode 100644 drivers/gpio/gpio-loongson1.c create mode 100644 drivers/mtd/nand/loongson1_nand.c -- 1.9.1
[PATCH 4/7] mtd: nand: add Loongson1 NAND driver
From: Kelvin CheungThis patch adds NAND driver for Loongson1B. Signed-off-by: Kelvin Cheung --- drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 522 ++ 3 files changed, 531 insertions(+) create mode 100644 drivers/mtd/nand/loongson1_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index f05e0e9..d90f545 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -563,4 +563,12 @@ config MTD_NAND_QCOM Enables support for NAND flash chips on SoCs containing the EBI2 NAND controller. This controller is found on IPQ806x SoC. +config MTD_NAND_LOONGSON1 + tristate "Support for Loongson1 SoC NAND controller" + depends on MACH_LOONGSON32 + select DMADEVICES + select DMA_LOONGSON1 + help + Enables support for NAND Flash on Loongson1 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index f553353..0310c0b 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -57,5 +57,6 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o +obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1_nand.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/drivers/mtd/nand/loongson1_nand.c b/drivers/mtd/nand/loongson1_nand.c new file mode 100644 index 000..68a0514 --- /dev/null +++ b/drivers/mtd/nand/loongson1_nand.c @@ -0,0 +1,522 @@ +/* + * NAND Flash Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Loongson 1 NAND Register Definitions */ +#define NAND_CMD 0x0 +#define NAND_ADDRL 0x4 +#define NAND_ADDRH 0x8 +#define NAND_TIMING0xc +#define NAND_IDL 0x10 +#define NAND_IDH 0x14 +#define NAND_STATUS0x14 +#define NAND_PARAM 0x18 +#define NAND_OP_NUM0x1c +#define NAND_CS_RDY0x20 + +#define NAND_DMA_ADDR 0x40 + +/* NAND Command Register Bits */ +#define OP_DONEBIT(10) +#define OP_SPARE BIT(9) +#define OP_MAINBIT(8) +#define CMD_STATUS BIT(7) +#define CMD_RESET BIT(6) +#define CMD_READID BIT(5) +#define BLOCKS_ERASE BIT(4) +#define CMD_ERASE BIT(3) +#define CMD_WRITE BIT(2) +#define CMD_READ BIT(1) +#define CMD_VALID BIT(0) + +#defineLS1X_NAND_TIMEOUT 20 + +/* macros for registers read/write */ +#define nand_readl(nand, off) \ + __raw_readl((nand)->reg_base + (off)) + +#define nand_writel(nand, off, val)\ + __raw_writel((val), (nand)->reg_base + (off)) + +#define set_cmd(nand, ctrl)\ + nand_writel(nand, NAND_CMD, ctrl) + +#define start_nand(nand) \ + nand_writel(nand, NAND_CMD, nand_readl(nand, NAND_CMD) | CMD_VALID) + +struct ls1x_nand { + struct platform_device *pdev; + struct nand_chip chip; + + struct clk *clk; + void __iomem *reg_base; + + int cmd_val; + + char datareg[8]; + char *data_ptr; + + /* DMA stuff */ + unsigned char *dma_buf; + unsigned int buf_off; + unsigned int buf_len; + + /* DMA Engine stuff */ + unsigned int dma_chan_id; + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; + struct completion dma_complete; + void __iomem *dma_desc; +}; + +static void dma_callback(void *data) +{ + struct ls1x_nand *nand = (struct ls1x_nand *)data; + struct mtd_info *mtd = nand_to_mtd(>chip); + struct dma_tx_state state; + enum dma_status status; + + status = dmaengine_tx_status(nand->dma_chan, nand->dma_cookie, ); + if (likely(status == DMA_COMPLETE)) + dev_dbg(mtd->dev.parent, "DMA complete with cookie=%d\n", + nand->dma_cookie); + else + dev_err(mtd->dev.parent, "DMA error with cookie=%d\n", + nand->dma_cookie); + + complete(>dma_complete); +} + +static int setup_dma(struct ls1x_nand *nand) +{ + struct mtd_info *mtd = nand_to_mtd(>chip); + struct dma_slave_config cfg; + dma_cap_mask_t mask; + int ret; + + /* allocate DMA buffer
[PATCH 7/7] MAINTAINERS: add Loongson1 architecture entry
From: Kelvin Cheung <keguang.zh...@gmail.com> This patch adds Loongson1 architecture entry. --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7..f6032a5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7271,6 +7271,15 @@ S: Supported F: Documentation/mips/ F: arch/mips/ +MIPS/LOONGSON1 ARCHITECTURE +M: Keguang Zhang <keguang.zh...@gmail.com> +L: linux-m...@linux-mips.org +S: Maintained +F: arch/mips/loongson32/ +F: arch/mips/include/asm/mach-loongson32/ +F: drivers/*/*loongson1* +F: drivers/*/*/*loongson1* + MIROSOUND PCM20 FM RADIO RECEIVER DRIVER M: Hans Verkuil <hverk...@xs4all.nl> L: linux-me...@vger.kernel.org -- 1.9.1
[PATCH 7/7] MAINTAINERS: add Loongson1 architecture entry
From: Kelvin Cheung This patch adds Loongson1 architecture entry. --- MAINTAINERS | 9 + 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7..f6032a5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7271,6 +7271,15 @@ S: Supported F: Documentation/mips/ F: arch/mips/ +MIPS/LOONGSON1 ARCHITECTURE +M: Keguang Zhang +L: linux-m...@linux-mips.org +S: Maintained +F: arch/mips/loongson32/ +F: arch/mips/include/asm/mach-loongson32/ +F: drivers/*/*loongson1* +F: drivers/*/*/*loongson1* + MIROSOUND PCM20 FM RADIO RECEIVER DRIVER M: Hans Verkuil L: linux-me...@vger.kernel.org -- 1.9.1
[PATCH 4/7] mtd: nand: add Loongson1 NAND driver
From: Kelvin Cheung This patch adds NAND driver for Loongson1B. Signed-off-by: Kelvin Cheung --- drivers/mtd/nand/Kconfig | 8 + drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/loongson1_nand.c | 522 ++ 3 files changed, 531 insertions(+) create mode 100644 drivers/mtd/nand/loongson1_nand.c diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index f05e0e9..d90f545 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -563,4 +563,12 @@ config MTD_NAND_QCOM Enables support for NAND flash chips on SoCs containing the EBI2 NAND controller. This controller is found on IPQ806x SoC. +config MTD_NAND_LOONGSON1 + tristate "Support for Loongson1 SoC NAND controller" + depends on MACH_LOONGSON32 + select DMADEVICES + select DMA_LOONGSON1 + help + Enables support for NAND Flash on Loongson1 SoC based boards. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index f553353..0310c0b 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -57,5 +57,6 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o +obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1_nand.o nand-objs := nand_base.o nand_bbt.o nand_timings.o diff --git a/drivers/mtd/nand/loongson1_nand.c b/drivers/mtd/nand/loongson1_nand.c new file mode 100644 index 000..68a0514 --- /dev/null +++ b/drivers/mtd/nand/loongson1_nand.c @@ -0,0 +1,522 @@ +/* + * NAND Flash Driver for Loongson 1 SoC + * + * Copyright (C) 2015-2016 Zhang, Keguang + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Loongson 1 NAND Register Definitions */ +#define NAND_CMD 0x0 +#define NAND_ADDRL 0x4 +#define NAND_ADDRH 0x8 +#define NAND_TIMING0xc +#define NAND_IDL 0x10 +#define NAND_IDH 0x14 +#define NAND_STATUS0x14 +#define NAND_PARAM 0x18 +#define NAND_OP_NUM0x1c +#define NAND_CS_RDY0x20 + +#define NAND_DMA_ADDR 0x40 + +/* NAND Command Register Bits */ +#define OP_DONEBIT(10) +#define OP_SPARE BIT(9) +#define OP_MAINBIT(8) +#define CMD_STATUS BIT(7) +#define CMD_RESET BIT(6) +#define CMD_READID BIT(5) +#define BLOCKS_ERASE BIT(4) +#define CMD_ERASE BIT(3) +#define CMD_WRITE BIT(2) +#define CMD_READ BIT(1) +#define CMD_VALID BIT(0) + +#defineLS1X_NAND_TIMEOUT 20 + +/* macros for registers read/write */ +#define nand_readl(nand, off) \ + __raw_readl((nand)->reg_base + (off)) + +#define nand_writel(nand, off, val)\ + __raw_writel((val), (nand)->reg_base + (off)) + +#define set_cmd(nand, ctrl)\ + nand_writel(nand, NAND_CMD, ctrl) + +#define start_nand(nand) \ + nand_writel(nand, NAND_CMD, nand_readl(nand, NAND_CMD) | CMD_VALID) + +struct ls1x_nand { + struct platform_device *pdev; + struct nand_chip chip; + + struct clk *clk; + void __iomem *reg_base; + + int cmd_val; + + char datareg[8]; + char *data_ptr; + + /* DMA stuff */ + unsigned char *dma_buf; + unsigned int buf_off; + unsigned int buf_len; + + /* DMA Engine stuff */ + unsigned int dma_chan_id; + struct dma_chan *dma_chan; + dma_cookie_t dma_cookie; + struct completion dma_complete; + void __iomem *dma_desc; +}; + +static void dma_callback(void *data) +{ + struct ls1x_nand *nand = (struct ls1x_nand *)data; + struct mtd_info *mtd = nand_to_mtd(>chip); + struct dma_tx_state state; + enum dma_status status; + + status = dmaengine_tx_status(nand->dma_chan, nand->dma_cookie, ); + if (likely(status == DMA_COMPLETE)) + dev_dbg(mtd->dev.parent, "DMA complete with cookie=%d\n", + nand->dma_cookie); + else + dev_err(mtd->dev.parent, "DMA error with cookie=%d\n", + nand->dma_cookie); + + complete(>dma_complete); +} + +static int setup_dma(struct ls1x_nand *nand) +{ + struct mtd_info *mtd = nand_to_mtd(>chip); + struct dma_slave_config cfg; + dma_cap_mask_t mask; + int ret; + + /* allocate DMA buffer */ + nand->dma_buf = devm_kzalloc(mtd->dev.parent, +