Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 332675
b: refs/heads/master
c: ff50617
h: refs/heads/master
i:
  332673: 141d233
  332671: 98c4c07
v: v3
  • Loading branch information
Huang Shijie authored and David Woodhouse committed Sep 29, 2012
1 parent 8fee1aa commit be7c8c1
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 894824f9731a805b70b553220ae58e5475ff6ff1
refs/heads/master: ff506172a30080963853dc0d259566c82fe8626c
45 changes: 37 additions & 8 deletions trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,42 @@ static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
return -ETIMEDOUT;
}

static int __gpmi_enable_clk(struct gpmi_nand_data *this, bool v)
{
struct clk *clk;
int ret;
int i;

for (i = 0; i < GPMI_CLK_MAX; i++) {
clk = this->resources.clock[i];
if (!clk)
break;

if (v) {
ret = clk_prepare_enable(clk);
if (ret)
goto err_clk;
} else {
clk_disable_unprepare(clk);
}
}
return 0;

err_clk:
for (; i > 0; i--)
clk_disable_unprepare(this->resources.clock[i - 1]);
return ret;
}

#define gpmi_enable_clk(x) __gpmi_enable_clk(x, true)
#define gpmi_disable_clk(x) __gpmi_enable_clk(x, false)

int gpmi_init(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;
int ret;

ret = clk_prepare_enable(r->clock);
ret = gpmi_enable_clk(this);
if (ret)
goto err_out;
ret = gpmi_reset_block(r->gpmi_regs, false);
Expand All @@ -149,7 +179,7 @@ int gpmi_init(struct gpmi_nand_data *this)
/* Select BCH ECC. */
writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);

clk_disable_unprepare(r->clock);
gpmi_disable_clk(this);
return 0;
err_out:
return ret;
Expand Down Expand Up @@ -205,7 +235,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
ecc_strength = bch_geo->ecc_strength >> 1;
page_size = bch_geo->page_size;

ret = clk_prepare_enable(r->clock);
ret = gpmi_enable_clk(this);
if (ret)
goto err_out;

Expand Down Expand Up @@ -240,7 +270,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
r->bch_regs + HW_BCH_CTRL_SET);

clk_disable_unprepare(r->clock);
gpmi_disable_clk(this);
return 0;
err_out:
return ret;
Expand Down Expand Up @@ -716,7 +746,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
int ret;

/* Enable the clock. */
ret = clk_prepare_enable(r->clock);
ret = gpmi_enable_clk(this);
if (ret) {
pr_err("We failed in enable the clk\n");
goto err_out;
Expand All @@ -727,7 +757,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
gpmi_regs + HW_GPMI_TIMING1);

/* Get the timing information we need. */
nfc->clock_frequency_in_hz = clk_get_rate(r->clock);
nfc->clock_frequency_in_hz = clk_get_rate(r->clock[0]);
clock_period_in_ns = 1000000000 / nfc->clock_frequency_in_hz;

gpmi_nfc_compute_hardware_timing(this, &hw);
Expand Down Expand Up @@ -784,8 +814,7 @@ void gpmi_begin(struct gpmi_nand_data *this)

void gpmi_end(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;
clk_disable_unprepare(r->clock);
gpmi_disable_clk(this);
}

/* Clears a BCH interrupt. */
Expand Down
82 changes: 73 additions & 9 deletions trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,9 +465,78 @@ static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
return -EINVAL;
}

static void gpmi_put_clks(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;
struct clk *clk;
int i;

for (i = 0; i < GPMI_CLK_MAX; i++) {
clk = r->clock[i];
if (clk) {
clk_put(clk);
r->clock[i] = NULL;
}
}
}

static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
"gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
};

static int __devinit gpmi_get_clks(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;
char **extra_clks = NULL;
struct clk *clk;
int i;

/* The main clock is stored in the first. */
r->clock[0] = clk_get(this->dev, "gpmi_io");
if (IS_ERR(r->clock[0]))
goto err_clock;

/* Get extra clocks */
if (GPMI_IS_MX6Q(this))
extra_clks = extra_clks_for_mx6q;
if (!extra_clks)
return 0;

for (i = 1; i < GPMI_CLK_MAX; i++) {
if (extra_clks[i - 1] == NULL)
break;

clk = clk_get(this->dev, extra_clks[i - 1]);
if (IS_ERR(clk))
goto err_clock;

r->clock[i] = clk;
}

if (GPMI_IS_MX6Q(this)) {
/*
* Set the default values for the clocks in mx6q:
* The main clock(enfc) : 22MHz
* The others : 44.5MHz
*
* These are just the default values. If you want to use
* the ONFI nand which is in the Synchronous Mode, you should
* change the clocks's frequencies as you need.
*/
clk_set_rate(r->clock[0], 22000000);
for (i = 1; i < GPMI_CLK_MAX && r->clock[i]; i++)
clk_set_rate(r->clock[i], 44500000);
}
return 0;

err_clock:
dev_dbg(this->dev, "failed in finding the clocks.\n");
gpmi_put_clks(this);
return -ENOMEM;
}

static int __devinit acquire_resources(struct gpmi_nand_data *this)
{
struct resources *res = &this->resources;
struct pinctrl *pinctrl;
int ret;

Expand All @@ -493,12 +562,9 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this)
goto exit_pin;
}

res->clock = clk_get(&this->pdev->dev, NULL);
if (IS_ERR(res->clock)) {
pr_err("can not get the clock\n");
ret = -ENOENT;
ret = gpmi_get_clks(this);
if (ret)
goto exit_clock;
}
return 0;

exit_clock:
Expand All @@ -513,9 +579,7 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this)

static void release_resources(struct gpmi_nand_data *this)
{
struct resources *r = &this->resources;

clk_put(r->clock);
gpmi_put_clks(this);
release_register_block(this);
release_bch_irq(this);
release_dma_channels(this);
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@
#include <linux/dma-mapping.h>
#include <linux/fsl/mxs-dma.h>

#define GPMI_CLK_MAX 5 /* MX6Q needs five clocks */
struct resources {
void *gpmi_regs;
void *bch_regs;
unsigned int bch_low_interrupt;
unsigned int bch_high_interrupt;
unsigned int dma_low_channel;
unsigned int dma_high_channel;
struct clk *clock;
struct clk *clock[GPMI_CLK_MAX];
};

/**
Expand Down

0 comments on commit be7c8c1

Please sign in to comment.