[PATCH V4] mtd: nand: add Loongson1 NAND driver

2016-11-01 Thread Keguang Zhang
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);
+   

[PATCH V4] mtd: nand: add Loongson1 NAND driver

2016-11-01 Thread Keguang Zhang
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

2016-09-18 Thread Keguang Zhang
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, 

[PATCH V1 3/3] clk: Loongson1: Make use of GENMASK

2016-09-18 Thread Keguang Zhang
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

2016-09-18 Thread Keguang Zhang
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 3/3] clk: Loongson1: Make use of GENMASK

2016-09-18 Thread Keguang Zhang
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

2016-09-18 Thread Keguang Zhang
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

2016-09-18 Thread Keguang Zhang
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

2016-09-18 Thread Keguang Zhang
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 V1 0/3] Refactor Loongson1 clock

2016-09-18 Thread Keguang Zhang
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

2016-08-12 Thread Keguang Zhang
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] MIPS: Loongson1B: Change the OSC clock name

2016-08-12 Thread Keguang Zhang
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

2016-08-12 Thread Keguang Zhang
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

2016-08-12 Thread Keguang Zhang
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 0/3] Refactor Loongson1 clock

2016-08-12 Thread Keguang Zhang
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

2016-08-12 Thread Keguang Zhang
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

2016-08-12 Thread Keguang Zhang
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
--- 

[PATCH 2/3] clk: Loongson1: Update clocks of Loongson1B

2016-08-12 Thread Keguang Zhang
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 2/3] clk: Loongson1: Update clocks of Loongson1B

2016-08-12 Thread Keguang Zhang
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

2016-08-12 Thread Keguang Zhang
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

2016-08-09 Thread Keguang Zhang
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: Loongson1B: Modify DEFAULT_MEMSIZE

2016-08-09 Thread Keguang Zhang
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

2016-08-09 Thread Keguang Zhang
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] MIPS: Loongson1C: Remove ARCH_WANT_OPTIONAL_GPIOLIB

2016-08-09 Thread Keguang Zhang
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

2016-08-09 Thread Keguang Zhang
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 V1] MIPS: Loongson1B: Provide DMA filter callbacks via platform data

2016-08-09 Thread Keguang Zhang
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

2016-05-28 Thread Keguang Zhang
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 == 

[PATCH V3] mtd: nand: add Loongson1 NAND driver

2016-05-28 Thread Keguang Zhang
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

2016-05-28 Thread Keguang Zhang
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

2016-05-28 Thread Keguang Zhang
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] MIPS: Loongson1B: Provide DMA filter callbacks via platform data

2016-05-28 Thread Keguang Zhang
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

2016-05-28 Thread Keguang Zhang
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

2016-05-28 Thread Keguang Zhang
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;
+   

[PATCH V3] dmaengine: Loongson1: add Loongson1 dmaengine driver

2016-05-28 Thread Keguang Zhang
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

2016-04-12 Thread Keguang Zhang
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 3/5] cpufreq: Loongson1: Use dev_get_platdata() to get platform_data

2016-04-12 Thread Keguang Zhang
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

2016-04-12 Thread Keguang Zhang
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)) {
-   

[PATCH V1 4/5] cpufreq: Loongson1: Use devm_kzalloc() instead of global structure

2016-04-12 Thread Keguang Zhang
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()

2016-04-12 Thread Keguang Zhang
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

2016-04-12 Thread Keguang Zhang
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()

2016-04-12 Thread Keguang Zhang
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 V1 5/5] cpufreq: Loongson1: Replace goto out with return in ls1x_cpufreq_probe()

2016-04-12 Thread Keguang Zhang
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

2016-04-12 Thread Keguang Zhang
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()

2016-04-12 Thread Keguang Zhang
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()

2016-04-11 Thread Keguang Zhang
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()

2016-04-11 Thread Keguang Zhang
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 5/5] cpufreq: Loongson1: Replace goto out with return in ls1x_cpufreq_probe()

2016-04-11 Thread Keguang Zhang
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()

2016-04-11 Thread Keguang Zhang
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

2016-04-11 Thread Keguang Zhang
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

2016-04-11 Thread Keguang Zhang
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)) {
-   

[PATCH 1/5] cpufreq: Loongson1: Rename the file to loongson1-cpufreq.c

2016-04-11 Thread Keguang Zhang
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

2016-04-11 Thread Keguang Zhang
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

2016-04-11 Thread Keguang Zhang
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 3/5] cpufreq: Loongson1: Use dev_get_platdata() to get platform_data

2016-04-11 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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 5/7] gpio: Loongson1: add Loongson1 GPIO driver

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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 

[PATCH 0/7] MIPS: Loongson1B: add NAND, DMA and GPIO support

2016-04-06 Thread Keguang Zhang
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 1/7] clk: Loongson1: Update clocks of Loongson1B

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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 

[PATCH 7/7] MAINTAINERS: add Loongson1 architecture entry

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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

2016-04-06 Thread Keguang Zhang
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,
+