Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 372349
b: refs/heads/master
c: cdd6928
h: refs/heads/master
i:
  372347: 96fcae0
v: v3
  • Loading branch information
Jon Hunter committed Apr 4, 2013
1 parent b7a67a9 commit 570c3dd
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d36b4cd46d23dd3c283c2e11de540e4cb875255d
refs/heads/master: cdd6928c589a2dcf084bd62fa5a2b7db1516187b
98 changes: 98 additions & 0 deletions trunk/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
Device tree bindings for NOR flash connect to TI GPMC

NOR flash connected to the TI GPMC (found on OMAP boards) are represented as
child nodes of the GPMC controller with a name of "nor".

All timing relevant properties as well as generic GPMC child properties are
explained in a separate documents. Please refer to
Documentation/devicetree/bindings/bus/ti-gpmc.txt

Required properties:
- bank-width: Width of NOR flash in bytes. GPMC supports 8-bit and
16-bit devices and so must be either 1 or 2 bytes.
- compatible: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
- gpmc,cs-on-ns: Chip-select assertion time
- gpmc,cs-rd-off-ns: Chip-select de-assertion time for reads
- gpmc,cs-wr-off-ns: Chip-select de-assertion time for writes
- gpmc,oe-on-ns: Output-enable assertion time
- gpmc,oe-off-ns: Output-enable de-assertion time
- gpmc,we-on-ns Write-enable assertion time
- gpmc,we-off-ns: Write-enable de-assertion time
- gpmc,access-ns: Start cycle to first data capture (read access)
- gpmc,rd-cycle-ns: Total read cycle time
- gpmc,wr-cycle-ns: Total write cycle time
- linux,mtd-name: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
- reg: Chip-select, base address (relative to chip-select)
and size of NOR flash. Note that base address will be
typically 0 as this is the start of the chip-select.

Optional properties:
- gpmc,XXX Additional GPMC timings and settings parameters. See
Documentation/devicetree/bindings/bus/ti-gpmc.txt

Optional properties for partiton table parsing:
- #address-cells: should be set to 1
- #size-cells: should be set to 1

Example:

gpmc: gpmc@6e000000 {
compatible = "ti,omap3430-gpmc", "simple-bus";
ti,hwmods = "gpmc";
reg = <0x6e000000 0x1000>;
interrupts = <20>;
gpmc,num-cs = <8>;
gpmc,num-waitpins = <4>;
#address-cells = <2>;
#size-cells = <1>;

ranges = <0 0 0x10000000 0x08000000>;

nor@0,0 {
compatible = "cfi-flash";
linux,mtd-name= "intel,pf48f6000m0y1be";
#address-cells = <1>;
#size-cells = <1>;
reg = <0 0 0x08000000>;
bank-width = <2>;

gpmc,mux-add-data;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <186>;
gpmc,cs-wr-off-ns = <186>;
gpmc,adv-on-ns = <12>;
gpmc,adv-rd-off-ns = <48>;
gpmc,adv-wr-off-ns = <48>;
gpmc,oe-on-ns = <54>;
gpmc,oe-off-ns = <168>;
gpmc,we-on-ns = <54>;
gpmc,we-off-ns = <168>;
gpmc,rd-cycle-ns = <186>;
gpmc,wr-cycle-ns = <186>;
gpmc,access-ns = <114>;
gpmc,page-burst-access-ns = <6>;
gpmc,bus-turnaround-ns = <12>;
gpmc,cycle2cycle-delay-ns = <18>;
gpmc,wr-data-mux-bus-ns = <90>;
gpmc,wr-access-ns = <186>;
gpmc,cycle2cycle-samecsen;
gpmc,cycle2cycle-diffcsen;

partition@0 {
label = "bootloader-nor";
reg = <0 0x40000>;
};
partition@0x40000 {
label = "params-nor";
reg = <0x40000 0x40000>;
};
partition@0x80000 {
label = "kernel-nor";
reg = <0x80000 0x200000>;
};
partition@0x280000 {
label = "filesystem-nor";
reg = <0x240000 0x7d80000>;
};
};
};
115 changes: 115 additions & 0 deletions trunk/arch/arm/mach-omap2/gpmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_mtd.h>
#include <linux/of_device.h>
#include <linux/mtd/nand.h>
Expand Down Expand Up @@ -499,6 +500,37 @@ static int gpmc_cs_delete_mem(int cs)
return r;
}

/**
* gpmc_cs_remap - remaps a chip-select physical base address
* @cs: chip-select to remap
* @base: physical base address to re-map chip-select to
*
* Re-maps a chip-select to a new physical base address specified by
* "base". Returns 0 on success and appropriate negative error code
* on failure.
*/
static int gpmc_cs_remap(int cs, u32 base)
{
int ret;
u32 old_base, size;

if (cs > GPMC_CS_NUM)
return -ENODEV;
gpmc_cs_get_memconf(cs, &old_base, &size);
if (base == old_base)
return 0;
gpmc_cs_disable_mem(cs);
ret = gpmc_cs_delete_mem(cs);
if (ret < 0)
return ret;
ret = gpmc_cs_insert_mem(cs, base, size);
if (ret < 0)
return ret;
gpmc_cs_enable_mem(cs, base, size);

return 0;
}

int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
{
struct resource *res = &gpmc_cs_mem[cs];
Expand Down Expand Up @@ -1386,6 +1418,80 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
}
#endif

/**
* gpmc_probe_nor_child - configures the gpmc for a nor device
* @pdev: pointer to gpmc platform device
* @child: pointer to device-tree node for nor device
*
* Allocates and configures a GPMC chip-select for a NOR flash device.
* Returns 0 on success and appropriate negative error code on failure.
*/
static int gpmc_probe_nor_child(struct platform_device *pdev,
struct device_node *child)
{
struct gpmc_settings gpmc_s;
struct gpmc_timings gpmc_t;
struct resource res;
unsigned long base;
int ret, cs;

if (of_property_read_u32(child, "reg", &cs) < 0) {
dev_err(&pdev->dev, "%s has no 'reg' property\n",
child->full_name);
return -ENODEV;
}

if (of_address_to_resource(child, 0, &res) < 0) {
dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
child->full_name);
return -ENODEV;
}

ret = gpmc_cs_request(cs, resource_size(&res), &base);
if (ret < 0) {
dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
return ret;
}

/*
* FIXME: gpmc_cs_request() will map the CS to an arbitary
* location in the gpmc address space. When booting with
* device-tree we want the NOR flash to be mapped to the
* location specified in the device-tree blob. So remap the
* CS to this location. Once DT migration is complete should
* just make gpmc_cs_request() map a specific address.
*/
ret = gpmc_cs_remap(cs, res.start);
if (ret < 0) {
dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
cs, res.start);
goto err;
}

gpmc_read_settings_dt(child, &gpmc_s);

ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
if (ret < 0)
goto err;

ret = gpmc_cs_program_settings(cs, &gpmc_s);
if (ret < 0)
goto err;

gpmc_read_timings_dt(child, &gpmc_t);
gpmc_cs_set_timings(cs, &gpmc_t);

if (of_platform_device_create(child, NULL, &pdev->dev))
return 0;

dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);

err:
gpmc_cs_free(cs);

return ret;
}

static int gpmc_probe_dt(struct platform_device *pdev)
{
int ret;
Expand Down Expand Up @@ -1418,6 +1524,15 @@ static int gpmc_probe_dt(struct platform_device *pdev)
return ret;
}
}

for_each_node_by_name(child, "nor") {
ret = gpmc_probe_nor_child(pdev, child);
if (ret < 0) {
of_node_put(child);
return ret;
}
}

return 0;
}
#else
Expand Down

0 comments on commit 570c3dd

Please sign in to comment.