Commit 86feb64f authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'omap-for-v3.10/gpmc-signed' of...

Merge tag 'omap-for-v3.10/gpmc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers

From Tony Lindgren <tony@atomide.com>:

GPMC updates from Jon Hunter <jon-hunter@ti.com>:

Adds GPMC (General Purpose Memory Controller) DT support for
NOR flash and Ethernet and includes various GPMC cleans-up
and fixes.

This series is dependent on commit 71856843 (ARM: OMAP: use
consistent error checking) from RMK's clean-up branch and commit
31d9adca (ARM: OMAP2+: Fix broken gpmc support).

* tag 'omap-for-v3.10/gpmc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (29 commits)
  ARM: OMAP2+: Add GPMC DT support for Ethernet child nodes
  ARM: OMAP2+: rename gpmc_probe_nor_child() to gpmc_probe_generic_child()
  ARM: OMAP2+: return -ENODEV if GPMC child device creation fails
  ARM: OMAP2+: Allow GPMC probe to complete even if CS mapping fails
  ARM: OMAP2+: Remove unnecesssary GPMC definitions and variable
  ARM: OMAP2+: Detect incorrectly aligned GPMC base address
  ARM: OMAP2+: Convert ONENAND to retrieve GPMC settings from DT
  ARM: OMAP2+: Convert NAND to retrieve GPMC settings from DT
  ARM: OMAP2+: Add device-tree support for NOR flash
  ARM: OMAP2+: Add additional GPMC timing parameters
  ARM: OMAP2+: Add function to read GPMC settings from device-tree
  ARM: OMAP2+: Don't configure of chip-select options in gpmc_cs_configure()
  ARM: OMAP2+: Convert TUSB to use gpmc_cs_program_settings()
  ARM: OMAP2+: Convert SMC91x to use gpmc_cs_program_settings()
  ARM: OMAP2+: Convert NAND to use gpmc_cs_program_settings()
  ARM: OMAP2+: Convert ONENAND to use gpmc_cs_program_settings()
  ARM: OMAP2+: Add function for configuring GPMC settings
  ARM: OMAP2+: Add structure for storing GPMC settings
  ARM: OMAP2+: Add variable to store number of GPMC waitpins
  ARM: OMAP2+: Simplify code configuring ONENAND devices
  ...
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents dc2d3db8 aecb65a3
......@@ -35,36 +35,83 @@ Required properties:
Timing properties for child nodes. All are optional and default to 0.
- gpmc,sync-clk: Minimum clock period for synchronous mode, in picoseconds
Chip-select signal timings corresponding to GPMC_CONFIG2:
- gpmc,cs-on: Assertion time
- gpmc,cs-rd-off: Read deassertion time
- gpmc,cs-wr-off: Write deassertion time
ADV signal timings corresponding to GPMC_CONFIG3:
- gpmc,adv-on: Assertion time
- gpmc,adv-rd-off: Read deassertion time
- gpmc,adv-wr-off: Write deassertion time
WE signals timings corresponding to GPMC_CONFIG4:
- gpmc,we-on: Assertion time
- gpmc,we-off: Deassertion time
OE signals timings corresponding to GPMC_CONFIG4:
- gpmc,oe-on: Assertion time
- gpmc,oe-off: Deassertion time
Access time and cycle time timings corresponding to GPMC_CONFIG5:
- gpmc,page-burst-access: Multiple access word delay
- gpmc,access: Start-cycle to first data valid delay
- gpmc,rd-cycle: Total read cycle time
- gpmc,wr-cycle: Total write cycle time
- gpmc,sync-clk-ps: Minimum clock period for synchronous mode, in picoseconds
Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
- gpmc,cs-on-ns: Assertion time
- gpmc,cs-rd-off-ns: Read deassertion time
- gpmc,cs-wr-off-ns: Write deassertion time
ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
- gpmc,adv-on-ns: Assertion time
- gpmc,adv-rd-off-ns: Read deassertion time
- gpmc,adv-wr-off-ns: Write deassertion time
WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
- gpmc,we-on-ns Assertion time
- gpmc,we-off-ns: Deassertion time
OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
- gpmc,oe-on-ns: Assertion time
- gpmc,oe-off-ns: Deassertion time
Access time and cycle time timings (in nanoseconds) corresponding to
GPMC_CONFIG5:
- gpmc,page-burst-access-ns: Multiple access word delay
- gpmc,access-ns: Start-cycle to first data valid delay
- gpmc,rd-cycle-ns: Total read cycle time
- gpmc,wr-cycle-ns: Total write cycle time
- gpmc,bus-turnaround-ns: Turn-around time between successive accesses
- gpmc,cycle2cycle-delay-ns: Delay between chip-select pulses
- gpmc,clk-activation-ns: GPMC clock activation time
- gpmc,wait-monitoring-ns: Start of wait monitoring with regard to valid
data
Boolean timing parameters. If property is present parameter enabled and
disabled if omitted:
- gpmc,adv-extra-delay: ADV signal is delayed by half GPMC clock
- gpmc,cs-extra-delay: CS signal is delayed by half GPMC clock
- gpmc,cycle2cycle-diffcsen: Add "cycle2cycle-delay" between successive
accesses to a different CS
- gpmc,cycle2cycle-samecsen: Add "cycle2cycle-delay" between successive
accesses to the same CS
- gpmc,oe-extra-delay: OE signal is delayed by half GPMC clock
- gpmc,we-extra-delay: WE signal is delayed by half GPMC clock
- gpmc,time-para-granularity: Multiply all access times by 2
The following are only applicable to OMAP3+ and AM335x:
- gpmc,wr-access
- gpmc,wr-data-mux-bus
- gpmc,wr-access-ns: In synchronous write mode, for single or
burst accesses, defines the number of
GPMC_FCLK cycles from start access time
to the GPMC_CLK rising edge used by the
memory device for the first data capture.
- gpmc,wr-data-mux-bus-ns: In address-data multiplex mode, specifies
the time when the first data is driven on
the address-data bus.
GPMC chip-select settings properties for child nodes. All are optional.
- gpmc,burst-length Page/burst length. Must be 4, 8 or 16.
- gpmc,burst-wrap Enables wrap bursting
- gpmc,burst-read Enables read page/burst mode
- gpmc,burst-write Enables write page/burst mode
- gpmc,device-nand Device is NAND
- gpmc,device-width Total width of device(s) connected to a GPMC
chip-select in bytes. The GPMC supports 8-bit
and 16-bit devices and so this property must be
1 or 2.
- gpmc,mux-add-data Address and data multiplexing configuration.
Valid values are 1 for address-address-data
multiplexing mode and 2 for address-data
multiplexing mode.
- gpmc,sync-read Enables synchronous read. Defaults to asynchronous
is this is not set.
- gpmc,sync-write Enables synchronous writes. Defaults to asynchronous
is this is not set.
- gpmc,wait-pin Wait-pin used by client. Must be less than
"gpmc,num-waitpins".
- gpmc,wait-on-read Enables wait monitoring on reads.
- gpmc,wait-on-write Enables wait monitoring on writes.
Example for an AM33xx board:
......
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>;
};
};
};
......@@ -10,6 +10,8 @@ Documentation/devicetree/bindings/bus/ti-gpmc.txt
Required properties:
- reg: The CS line the peripheral is connected to
- gpmc,device-width Width of the ONENAND device connected to the GPMC
in bytes. Must be 1 or 2.
Optional properties:
......@@ -34,6 +36,7 @@ Example for an OMAP3430 board:
onenand@0 {
reg = <0 0 0>; /* CS0, offset 0 */
gpmc,device-width = <2>;
#address-cells = <1>;
#size-cells = <1>;
......
Device tree bindings for Ethernet chip connected to TI GPMC
Besides being used to interface with external memory devices, the
General-Purpose Memory Controller can be used to connect Pseudo-SRAM devices
such as ethernet controllers to processors using the TI GPMC as a data bus.
Ethernet controllers connected to TI GPMC are represented as child nodes of
the GPMC controller with an "ethernet" name.
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
For the properties relevant to the ethernet controller connected to the GPMC
refer to the binding documentation of the device. For example, the documentation
for the SMSC 911x is Documentation/devicetree/bindings/net/smsc911x.txt
Child nodes need to specify the GPMC bus address width using the "bank-width"
property but is possible that an ethernet controller also has a property to
specify the I/O registers address width. Even when the GPMC has a maximum 16-bit
address width, it supports devices with 32-bit word registers.
For example with an SMSC LAN911x/912x controller connected to the TI GPMC on an
OMAP2+ board, "bank-width = <2>;" and "reg-io-width = <4>;".
Required properties:
- bank-width: Address width of the device in bytes. GPMC supports 8-bit
and 16-bit devices and so must be either 1 or 2 bytes.
- compatible: Compatible string property for the ethernet child device.
- gpmc,cs-on: Chip-select assertion time
- gpmc,cs-rd-off: Chip-select de-assertion time for reads
- gpmc,cs-wr-off: Chip-select de-assertion time for writes
- gpmc,oe-on: Output-enable assertion time
- gpmc,oe-off Output-enable de-assertion time
- gpmc,we-on: Write-enable assertion time
- gpmc,we-off: Write-enable de-assertion time
- gpmc,access: Start cycle to first data capture (read access)
- gpmc,rd-cycle: Total read cycle time
- gpmc,wr-cycle: Total write cycle time
- reg: Chip-select, base address (relative to chip-select)
and size of the memory mapped for the device.
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
Example:
gpmc: gpmc@6e000000 {
compatible = "ti,omap3430-gpmc";
ti,hwmods = "gpmc";
reg = <0x6e000000 0x1000>;
interrupts = <20>;
gpmc,num-cs = <8>;
gpmc,num-waitpins = <4>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <5 0 0x2c000000 0x1000000>;
ethernet@5,0 {
compatible = "smsc,lan9221", "smsc,lan9115";
reg = <5 0 0xff>;
bank-width = <2>;
gpmc,mux-add-data;
gpmc,cs-on = <0>;
gpmc,cs-rd-off = <186>;
gpmc,cs-wr-off = <186>;
gpmc,adv-on = <12>;
gpmc,adv-rd-off = <48>;
gpmc,adv-wr-off = <48>;
gpmc,oe-on = <54>;
gpmc,oe-off = <168>;
gpmc,we-on = <54>;
gpmc,we-off = <168>;
gpmc,rd-cycle = <186>;
gpmc,wr-cycle = <186>;
gpmc,access = <114>;
gpmc,page-burst-access = <6>;
gpmc,bus-turnaround = <12>;
gpmc,cycle2cycle-delay = <18>;
gpmc,wr-data-mux-bus = <90>;
gpmc,wr-access = <186>;
gpmc,cycle2cycle-samecsen;
gpmc,cycle2cycle-diffcsen;
interrupt-parent = <&gpio6>;
interrupts = <16>;
vmmc-supply = <&vddvario>;
vmmc_aux-supply = <&vdd33a>;
reg-io-width = <4>;
smsc,save-mac-address;
};
};
......@@ -74,14 +74,6 @@ static int omap2_nand_gpmc_retime(
t.cs_wr_off = gpmc_t->cs_wr_off;
t.wr_cycle = gpmc_t->wr_cycle;
/* Configure GPMC */
if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
else
gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
gpmc_cs_configure(gpmc_nand_data->cs,
GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
if (err)
return err;
......@@ -115,14 +107,18 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
struct gpmc_timings *gpmc_t)
{
int err = 0;
struct gpmc_settings s;
struct device *dev = &gpmc_nand_device.dev;
memset(&s, 0, sizeof(struct gpmc_settings));
gpmc_nand_device.dev.platform_data = gpmc_nand_data;
err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
(unsigned long *)&gpmc_nand_resource[0].start);
if (err < 0) {
dev_err(dev, "Cannot request GPMC CS\n");
dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
gpmc_nand_data->cs, err);
return err;
}
......@@ -140,11 +136,31 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
dev_err(dev, "Unable to set gpmc timings: %d\n", err);
return err;
}
}
/* Enable RD PIN Monitoring Reg */
if (gpmc_nand_data->dev_ready) {
gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
if (gpmc_nand_data->of_node) {
gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
} else {
s.device_nand = true;
/* Enable RD PIN Monitoring Reg */
if (gpmc_nand_data->dev_ready) {
s.wait_on_read = true;
s.wait_on_write = true;
}
}
if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
s.device_width = GPMC_DEVWIDTH_16BIT;
else
s.device_width = GPMC_DEVWIDTH_8BIT;
err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
if (err < 0)
goto out_free_cs;
err = gpmc_configure(GPMC_CONFIG_WP, 0);
if (err < 0)
goto out_free_cs;
}
gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
......
......@@ -47,11 +47,23 @@ static struct platform_device gpmc_onenand_device = {
.resource = &gpmc_onenand_resource,
};
static struct gpmc_timings omap2_onenand_calc_async_timings(void)
static struct gpmc_settings onenand_async = {
.device_width = GPMC_DEVWIDTH_16BIT,
.mux_add_data = GPMC_MUX_AD,
};
static struct gpmc_settings onenand_sync = {
.burst_read = true,
.burst_wrap = true,
.burst_len = GPMC_BURST_16,
.device_width = GPMC_DEVWIDTH_16BIT,
.mux_add_data = GPMC_MUX_AD,
.wait_pin = 0,
};
static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
{
struct gpmc_device_timings dev_t;
struct gpmc_timings t;
const int t_cer = 15;
const int t_avdp = 12;
const int t_aavdh = 7;
......@@ -64,7 +76,6 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
dev_t.t_avdp_w = dev_t.t_avdp_r;
dev_t.t_aavdh = t_aavdh * 1000;
......@@ -76,19 +87,7 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
dev_t.t_wpl = t_wpl * 1000;
dev_t.t_wph = t_wph * 1000;
gpmc_calc_timings(&t, &dev_t);
return t;
}
static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
{
/* Configure GPMC for asynchronous read */
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
GPMC_CONFIG1_DEVICESIZE_16 |
GPMC_CONFIG1_MUXADDDATA);
return gpmc_cs_set_timings(cs, t);
gpmc_calc_timings(t, &onenand_async, &dev_t);
}
static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
......@@ -158,12 +157,11 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
return freq;
}
static struct gpmc_timings
omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
int freq)
static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
unsigned int flags,
int freq)
{
struct gpmc_device_timings dev_t;
struct gpmc_timings t;
const int t_cer = 15;
const int t_avdp = 12;
const int t_cez = 20; /* max of t_cez, t_oez */
......@@ -172,9 +170,9 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
int div, gpmc_clk_ns;
if (cfg->flags & ONENAND_SYNC_READ)
if (flags & ONENAND_SYNC_READ)
onenand_flags = ONENAND_FLAG_SYNCREAD;
else if (cfg->flags & ONENAND_SYNC_READWRITE)
else if (flags & ONENAND_SYNC_READWRITE)
onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
switch (freq) {
......@@ -239,10 +237,11 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
/* Set synchronous read timings */
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.sync_read = true;
if (onenand_flags & ONENAND_FLAG_SYNCREAD)
onenand_sync.sync_read = true;
if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
dev_t.sync_write = true;
onenand_sync.sync_write = true;
onenand_sync.burst_write = true;
} else {
dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
dev_t.t_wpl = t_wpl * 1000;
......@@ -265,32 +264,7 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
dev_t.cyc_aavdh_oe = 1;
dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
gpmc_calc_timings(&t, &dev_t);
return t;
}
static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
{
unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD;
unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE;
/* Configure GPMC for synchronous read */
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
GPMC_CONFIG1_WRAPBURST_SUPP |
GPMC_CONFIG1_READMULTIPLE_SUPP |
(sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
(sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
(sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
GPMC_CONFIG1_PAGE_LEN(2) |
(cpu_is_omap34xx() ? 0 :
(GPMC_CONFIG1_WAIT_READ_MON |
GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
GPMC_CONFIG1_DEVICESIZE_16 |
GPMC_CONFIG1_DEVICETYPE_NOR |
GPMC_CONFIG1_MUXADDDATA);
return gpmc_cs_set_timings(cs, t);
gpmc_calc_timings(t, &onenand_sync, &dev_t);
}
static int omap2_onenand_setup_async(void __iomem *onenand_base)
......@@ -298,11 +272,19 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
struct gpmc_timings t;
int ret;
if (gpmc_onenand_data->of_node)
gpmc_read_settings_dt(gpmc_onenand_data->of_node,
&onenand_async);
omap2_onenand_set_async_mode(onenand_base);
t = omap2_onenand_calc_async_timings();
omap2_onenand_calc_async_timings(&t);
ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
if (ret < 0)
return ret;
ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
if (ret < 0)
return ret;
......@@ -322,9 +304,25 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
set_onenand_cfg(onenand_base);
}
t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
if (gpmc_onenand_data->of_node) {
gpmc_read_settings_dt(gpmc_onenand_data->of_node,
&onenand_sync);
} else {
/*
* FIXME: Appears to be legacy code from initial ONENAND commit.
* Unclear what boards this is for and if this can be removed.
*/
if (!cpu_is_omap34xx())
onenand_sync.wait_on_read = true;
}
ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_sync);
if (ret < 0)
return ret;
ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
if (ret < 0)
return ret;
......@@ -359,6 +357,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
{
int err;
struct device *dev = &gpmc_onenand_device.dev;
gpmc_onenand_data = _onenand_data;
gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
......@@ -366,7 +365,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
if (cpu_is_omap24xx() &&
(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
dev_warn(dev, "OneNAND using only SYNC_READ on 24xx\n");
gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
}
......@@ -379,7 +378,8 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
(unsigned long *)&gpmc_onenand_resource.start);
if (err < 0) {
pr_err("%s: Cannot request GPMC CS\n", __func__);
dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
gpmc_onenand_data->cs, err);
return;
}
......@@ -387,7 +387,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
ONENAND_IO_SIZE - 1;
if (platform_device_register(&gpmc_onenand_device) < 0) {
pr_err("%s: Unable to register OneNAND device\n", __func__);
dev_err(dev, "Unable to register OneNAND device\n");
gpmc_cs_free(gpmc_onenand_data->cs);
return;
}
......
......@@ -49,6 +49,10 @@ static struct platform_device gpmc_smc91x_device = {
.resource = gpmc_smc91x_resources,
};
static struct gpmc_settings smc91x_settings = {
.device_width = GPMC_DEVWIDTH_16BIT,
};
/*
* Set the gpmc timings for smc91c96. The timings are taken
* from the data sheet available at:
......@@ -67,18 +71,6 @@ static int smc91c96_gpmc_retime(void)
const int t7 = 5; /* Figure 12.4 write */
const int t8 = 5; /* Figure 12.4 write */
const int t20 = 185; /* Figure 12.2 read and 12.4 write */
u32 l;
l = GPMC_CONFIG1_DEVICESIZE_16;
if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
l |= GPMC_CONFIG1_MUXADDDATA;
if (gpmc_cfg->flags & GPMC_READ_MON)
l |= GPMC_CONFIG1_WAIT_READ_MON;
if (gpmc_cfg->flags & GPMC_WRITE_MON)
l |= GPMC_CONFIG1_WAIT_WRITE_MON;
if (gpmc_cfg->wait_pin)
l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
/*
* FIXME: Calculate the address and data bus muxed timings.
......@@ -104,7 +96,7 @@ static int smc91c96_gpmc_retime(void)
dev_t.t_cez_w = t4_w * 1000;
dev_t.t_wr_cycle = (t20 - t3) * 1000;
gpmc_calc_timings(&t, &dev_t);
gpmc_calc_timings(&t, &smc91x_settings, &dev_t);
return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
}
......@@ -133,6 +125,18 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
smc91x_settings.mux_add_data = GPMC_MUX_AD;
if (gpmc_cfg->flags & GPMC_READ_MON)
smc91x_settings.wait_on_read = true;
if (gpmc_cfg->flags & GPMC_WRITE_MON)
smc91x_settings.wait_on_write = true;
if (gpmc_cfg->wait_pin)
smc91x_settings.wait_pin = gpmc_cfg->wait_pin;
ret = gpmc_cs_program_settings(gpmc_cfg->cs, &smc91x_settings);
if (ret < 0)
goto free1;
if (gpmc_cfg->retime) {
ret = gpmc_cfg->retime();
if (ret != 0)
......
This diff is collapsed.
......@@ -58,7 +58,7 @@
#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
#define GPMC_CONFIG1_MUXADDDATA (1 << 9)
#define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8)
#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1))
......@@ -73,6 +73,13 @@
#define GPMC_IRQ_FIFOEVENTENABLE 0x01
#define GPMC_IRQ_COUNT_EVENT 0x02
#define GPMC_BURST_4 4 /* 4 word burst */
#define GPMC_BURST_8 8 /* 8 word burst */
#define GPMC_BURST_16 16 /* 16 word burst */
#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */
#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */
#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
/* bool type time settings */
struct gpmc_bool_timings {
......@@ -178,10 +185,6 @@ struct gpmc_device_timings {
u8 cyc_wpl; /* write deassertion time in cycles */
u32 cyc_iaa; /* initial access time in cycles */
bool mux; /* address & data muxed */
bool sync_write;/* synchronous write */
bool sync_read; /* synchronous read */
/* extra delays */
bool ce_xdelay;
bool avd_xdelay;
......@@ -189,28 +192,40 @@ struct gpmc_device_timings {
bool we_xdelay;
};
struct gpmc_settings {
bool burst_wrap; /* enables wrap bursting */
bool burst_read; /* enables read page/burst mode */
bool burst_write; /* enables write page/burst mode */
bool device_nand; /* device is NAND */
bool sync_read; /* enables synchronous reads */
bool sync_write; /* enables synchronous writes */
bool wait_on_read; /* monitor wait on reads */
bool wait_on_write; /* monitor wait on writes */
u32 burst_len; /* page/burst length */
u32 device_width; /* device bus width (8 or 16 bit) */
u32 mux_add_data; /* multiplex address & data */
u32 wait_pin; /* wait-pin to be used */
};
extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t);
struct gpmc_settings *gpmc_s,
struct gpmc_device_timings *dev_t);
extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
extern int gpmc_get_client_irq(unsigned irq_config);
extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
extern unsigned long gpmc_get_fclk_period(void);
extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
extern u32 gpmc_cs_read_reg(int cs, int idx);
extern int gpmc_calc_divider(unsigned int sync_clk);
extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p);
extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
extern void gpmc_cs_free(int cs);
extern int gpmc_cs_set_reserved(int cs, int reserved);
extern int gpmc_cs_reserved(int cs);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern int gpmc_cs_configure(int cs, int cmd, int wval);
extern int gpmc_configure(int cmd, int wval);
extern void gpmc_read_settings_dt(struct device_node *np,
struct gpmc_settings *p);
#endif
......@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/errno.h>
......@@ -26,6 +27,24 @@
static u8 async_cs, sync_cs;
static unsigned refclk_psec;
static struct gpmc_settings tusb_async = {
.wait_on_read = true,
.wait_on_write = true,
.device_width = GPMC_DEVWIDTH_16BIT,
.mux_add_data = GPMC_MUX_AD,
};
static struct gpmc_settings tusb_sync = {
.burst_read = true,
.burst_write = true,
.sync_read = true,
.sync_write = true,
.wait_on_read = true,
.wait_on_write = true,
.burst_len = GPMC_BURST_16,
.device_width = GPMC_DEVWIDTH_16BIT,
.mux_add_data = GPMC_MUX_AD,
};
/* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
......@@ -37,8 +56,6 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.t_ceasu = 8 * 1000;
dev_t.t_avdasu = t_acsnh_advnh - 7000;
dev_t.t_ce_avd = 1000;
......@@ -52,7 +69,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
dev_t.t_wpl = 300;
dev_t.cyc_aavdh_we = 1;
gpmc_calc_timings(&t, &dev_t);
gpmc_calc_timings(&t, &tusb_async, &dev_t);
return gpmc_cs_set_timings(async_cs, &t);
}
......@@ -65,10 +82,6 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.sync_read = true;
dev_t.sync_write = true;
dev_t.clk = 11100;
dev_t.t_bacc = 1000;
dev_t.t_ces = 1000;
......@@ -84,7 +97,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
dev_t.cyc_wpl = 6;
dev_t.t_ce_rdyz = 7000;
gpmc_calc_timings(&t, &dev_t);
gpmc_calc_timings(&t, &tusb_sync, &dev_t);
return gpmc_cs_set_timings(sync_cs, &t);
}
......@@ -165,18 +178,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
return status;
}
tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
tusb_async.wait_pin = waitpin;
async_cs = async;
gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
GPMC_CONFIG1_PAGE_LEN(2)
| GPMC_CONFIG1_WAIT_READ_MON
| GPMC_CONFIG1_WAIT_WRITE_MON
| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
| GPMC_CONFIG1_READTYPE_ASYNC
| GPMC_CONFIG1_WRITETYPE_ASYNC
| GPMC_CONFIG1_DEVICESIZE_16
| GPMC_CONFIG1_DEVICETYPE_NOR
| GPMC_CONFIG1_MUXADDDATA);
status = gpmc_cs_program_settings(async_cs, &tusb_async);
if (status < 0)
return status;
/* SYNC region, primarily for DMA */
status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
......@@ -186,21 +193,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
return status;
}
tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
tusb_sync.wait_pin = waitpin;
sync_cs = sync;
gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
GPMC_CONFIG1_READMULTIPLE_SUPP
| GPMC_CONFIG1_READTYPE_SYNC
| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
| GPMC_CONFIG1_WRITETYPE_SYNC
| GPMC_CONFIG1_PAGE_LEN(2)
| GPMC_CONFIG1_WAIT_READ_MON
| GPMC_CONFIG1_WAIT_WRITE_MON
| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
| GPMC_CONFIG1_DEVICESIZE_16
| GPMC_CONFIG1_DEVICETYPE_NOR
| GPMC_CONFIG1_MUXADDDATA
/* fclk divider gets set later */
);
status = gpmc_cs_program_settings(sync_cs, &tusb_sync);
if (status < 0)
return status;
/* IRQ */
status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment