Merge branch 'omap-gpmc-for-v3.10-take2' of git://github.com/jonhunter/linux into...
authorTony Lindgren <tony@atomide.com>
Thu, 4 Apr 2013 18:22:33 +0000 (11:22 -0700)
committerTony Lindgren <tony@atomide.com>
Thu, 4 Apr 2013 18:22:33 +0000 (11:22 -0700)
Documentation/devicetree/bindings/bus/ti-gpmc.txt
Documentation/devicetree/bindings/mtd/gpmc-nor.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
Documentation/devicetree/bindings/net/gpmc-eth.txt [new file with mode: 0644]
arch/arm/mach-omap2/gpmc-nand.c
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/gpmc-smc91x.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/gpmc.h
arch/arm/mach-omap2/usb-tusb6010.c

index 5ddb2e9efaaacf020a75b1d6b5c6b05908b6cd2a..4b87ea1194e3128e6adba331931cc3616f8e10df 100644 (file)
@@ -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:
 
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
new file mode 100644 (file)
index 0000000..420b3ab
--- /dev/null
@@ -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>;
+               };
+       };
+};
index deec9da224a2aec46c09a878202599e82d1fbece..b7529424ac88e0a6304aea730ff364be78ec84dd 100644 (file)
@@ -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>;
diff --git a/Documentation/devicetree/bindings/net/gpmc-eth.txt b/Documentation/devicetree/bindings/net/gpmc-eth.txt
new file mode 100644 (file)
index 0000000..24cb4e4
--- /dev/null
@@ -0,0 +1,97 @@
+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;
+       };
+};
index afc1e8c32d6ccf8ced2372f6131300a8407ed1d7..d9c27195caf0ffa2d9ee38b17cc23067954d6a21 100644 (file)
@@ -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);
index 0d75889c0a6f57d13f9362cd10bc6c137b023fdb..64b5a83469822ad53693c2ae8ffdd3b227fa2a7b 100644 (file)
@@ -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;
        }
index 11d0b756f09897be435075302392131a35aa686b..61a063595e66fb1c2d01bca46c561873aa2fd643 100644 (file)
@@ -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)
index 6de31739b45c474c63e68acec36171a05bbe0c8b..ed946df5ad8a6acd75bb9010843eac90b3d4480c 100644 (file)
@@ -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>
@@ -91,9 +92,7 @@
 #define GPMC_CS_SIZE           0x30
 #define        GPMC_BCH_SIZE           0x10
 
-#define GPMC_MEM_START         0x00000000
 #define GPMC_MEM_END           0x3FFFFFFF
-#define BOOT_ROM_SPACE         0x100000        /* 1MB */
 
 #define GPMC_CHUNK_SHIFT       24              /* 16 MB */
 #define GPMC_SECTION_SHIFT     28              /* 128 MB */
 
 #define        GPMC_HAS_WR_ACCESS              0x1
 #define        GPMC_HAS_WR_DATA_MUX_BUS        0x2
+#define        GPMC_HAS_MUX_AAD                0x4
+
+#define GPMC_NR_WAITPINS               4
 
 /* XXX: Only NAND irq has been considered,currently these are the only ones used
  */
@@ -153,6 +155,7 @@ static struct resource      gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
 /* Define chip-selects as reserved by default until probe completes */
 static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
+static unsigned int gpmc_nr_waitpins;
 static struct device *gpmc_dev;
 static int gpmc_irq;
 static resource_size_t phys_base, mem_size;
@@ -181,7 +184,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
        __raw_writel(val, reg_addr);
 }
 
-u32 gpmc_cs_read_reg(int cs, int idx)
+static u32 gpmc_cs_read_reg(int cs, int idx)
 {
        void __iomem *reg_addr;
 
@@ -190,7 +193,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
 }
 
 /* TODO: Add support for gpmc_fck to clock framework and use it */
-unsigned long gpmc_get_fclk_period(void)
+static unsigned long gpmc_get_fclk_period(void)
 {
        unsigned long rate = clk_get_rate(gpmc_l3_clk);
 
@@ -205,7 +208,7 @@ unsigned long gpmc_get_fclk_period(void)
        return rate;
 }
 
-unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
 {
        unsigned long tick_ps;
 
@@ -215,7 +218,7 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
        return (time_ns * 1000 + tick_ps - 1) / tick_ps;
 }
 
-unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
+static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
 {
        unsigned long tick_ps;
 
@@ -230,13 +233,6 @@ unsigned int gpmc_ticks_to_ns(unsigned int ticks)
        return ticks * gpmc_get_fclk_period() / 1000;
 }
 
-unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
-{
-       unsigned long ticks = gpmc_ns_to_ticks(time_ns);
-
-       return ticks * gpmc_get_fclk_period() / 1000;
-}
-
 static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
 {
        return ticks * gpmc_get_fclk_period();
@@ -405,11 +401,18 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
        return 0;
 }
 
-static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
+static int gpmc_cs_enable_mem(int cs, u32 base, u32 size)
 {
        u32 l;
        u32 mask;
 
+       /*
+        * Ensure that base address is aligned on a
+        * boundary equal to or greater than size.
+        */
+       if (base & (size - 1))
+               return -EINVAL;
+
        mask = (1 << GPMC_SECTION_SHIFT) - size;
        l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
        l &= ~0x3f;
@@ -418,6 +421,8 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
        l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
        l |= GPMC_CONFIG7_CSVALID;
        gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+
+       return 0;
 }
 
 static void gpmc_cs_disable_mem(int cs)
@@ -448,22 +453,14 @@ static int gpmc_cs_mem_enabled(int cs)
        return l & GPMC_CONFIG7_CSVALID;
 }
 
-int gpmc_cs_set_reserved(int cs, int reserved)
+static void gpmc_cs_set_reserved(int cs, int reserved)
 {
-       if (cs > GPMC_CS_NUM)
-               return -ENODEV;
-
        gpmc_cs_map &= ~(1 << cs);
        gpmc_cs_map |= (reserved ? 1 : 0) << cs;
-
-       return 0;
 }
 
-int gpmc_cs_reserved(int cs)
+static bool gpmc_cs_reserved(int cs)
 {
-       if (cs > GPMC_CS_NUM)
-               return -ENODEV;
-
        return gpmc_cs_map & (1 << cs);
 }
 
@@ -510,6 +507,39 @@ 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;
+       ret = gpmc_cs_enable_mem(cs, base, size);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
        struct resource *res = &gpmc_cs_mem[cs];
@@ -535,7 +565,12 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
        if (r < 0)
                goto out;
 
-       gpmc_cs_enable_mem(cs, res->start, resource_size(res));
+       r = gpmc_cs_enable_mem(cs, res->start, resource_size(res));
+       if (r < 0) {
+               release_resource(res);
+               goto out;
+       }
+
        *base = res->start;
        gpmc_cs_set_reserved(cs, 1);
 out:
@@ -561,16 +596,14 @@ void gpmc_cs_free(int cs)
 EXPORT_SYMBOL(gpmc_cs_free);
 
 /**
- * gpmc_cs_configure - write request to configure gpmc
- * @cs: chip select number
+ * gpmc_configure - write request to configure gpmc
  * @cmd: command type
  * @wval: value to write
  * @return status of the operation
  */
-int gpmc_cs_configure(int cs, int cmd, int wval)
+int gpmc_configure(int cmd, int wval)
 {
-       int err = 0;
-       u32 regval = 0;
+       u32 regval;
 
        switch (cmd) {
        case GPMC_ENABLE_IRQ:
@@ -590,43 +623,14 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
                gpmc_write_reg(GPMC_CONFIG, regval);
                break;
 
-       case GPMC_CONFIG_RDY_BSY:
-               regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-               if (wval)
-                       regval |= WR_RD_PIN_MONITORING;
-               else
-                       regval &= ~WR_RD_PIN_MONITORING;
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-               break;
-
-       case GPMC_CONFIG_DEV_SIZE:
-               regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-               /* clear 2 target bits */
-               regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
-
-               /* set the proper value */
-               regval |= GPMC_CONFIG1_DEVICESIZE(wval);
-
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-               break;
-
-       case GPMC_CONFIG_DEV_TYPE:
-               regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-               regval |= GPMC_CONFIG1_DEVICETYPE(wval);
-               if (wval == GPMC_DEVICETYPE_NOR)
-                       regval |= GPMC_CONFIG1_MUXADDDATA;
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-               break;
-
        default:
-               printk(KERN_ERR "gpmc_configure_cs: Not supported\n");
-               err = -EINVAL;
+               pr_err("%s: command not supported\n", __func__);
+               return -EINVAL;
        }
 
-       return err;
+       return 0;
 }
-EXPORT_SYMBOL(gpmc_cs_configure);
+EXPORT_SYMBOL(gpmc_configure);
 
 void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 {
@@ -781,16 +785,16 @@ static void gpmc_mem_exit(void)
 
 }
 
-static int gpmc_mem_init(void)
+static void gpmc_mem_init(void)
 {
-       int cs, rc;
-       unsigned long boot_rom_space = 0;
+       int cs;
 
-       /* never allocate the first page, to facilitate bug detection;
-        * even if we didn't boot from ROM.
+       /*
+        * The first 1MB of GPMC address space is typically mapped to
+        * the internal ROM. Never allocate the first page, to
+        * facilitate bug detection; even if we didn't boot from ROM.
         */
-       boot_rom_space = BOOT_ROM_SPACE;
-       gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
+       gpmc_mem_root.start = SZ_1M;
        gpmc_mem_root.end = GPMC_MEM_END;
 
        /* Reserve all regions that has been set up by bootloader */
@@ -800,16 +804,12 @@ static int gpmc_mem_init(void)
                if (!gpmc_cs_mem_enabled(cs))
                        continue;
                gpmc_cs_get_memconf(cs, &base, &size);
-               rc = gpmc_cs_insert_mem(cs, base, size);
-               if (rc < 0) {
-                       while (--cs >= 0)
-                               if (gpmc_cs_mem_enabled(cs))
-                                       gpmc_cs_delete_mem(cs);
-                       return rc;
+               if (gpmc_cs_insert_mem(cs, base, size)) {
+                       pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n",
+                               __func__, cs, base, base + size);
+                       gpmc_cs_disable_mem(cs);
                }
        }
-
-       return 0;
 }
 
 static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
@@ -825,9 +825,9 @@ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
 
 /* XXX: can the cycles be avoided ? */
 static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                      struct gpmc_device_timings *dev_t,
+                                      bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_rd_off */
@@ -880,9 +880,9 @@ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                       struct gpmc_device_timings *dev_t,
+                                       bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_wr_off */
@@ -942,9 +942,9 @@ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                       struct gpmc_device_timings *dev_t,
+                                       bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_rd_off */
@@ -982,9 +982,9 @@ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                        struct gpmc_device_timings *dev_t,
+                                        bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_wr_off */
@@ -1054,7 +1054,8 @@ static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
-                       struct gpmc_device_timings *dev_t)
+                                   struct gpmc_device_timings *dev_t,
+                                   bool sync)
 {
        u32 temp;
 
@@ -1068,7 +1069,7 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
                                gpmc_t->cs_on + dev_t->t_ce_avd);
        gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
 
-       if (dev_t->sync_write || dev_t->sync_read)
+       if (sync)
                gpmc_calc_sync_common_timings(gpmc_t, dev_t);
 
        return 0;
@@ -1103,21 +1104,29 @@ static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
 }
 
 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)
 {
+       bool mux = false, sync = false;
+
+       if (gpmc_s) {
+               mux = gpmc_s->mux_add_data ? true : false;
+               sync = (gpmc_s->sync_read || gpmc_s->sync_write);
+       }
+
        memset(gpmc_t, 0, sizeof(*gpmc_t));
 
-       gpmc_calc_common_timings(gpmc_t, dev_t);
+       gpmc_calc_common_timings(gpmc_t, dev_t, sync);
 
-       if (dev_t->sync_read)
-               gpmc_calc_sync_read_timings(gpmc_t, dev_t);
+       if (gpmc_s && gpmc_s->sync_read)
+               gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux);
        else
-               gpmc_calc_async_read_timings(gpmc_t, dev_t);
+               gpmc_calc_async_read_timings(gpmc_t, dev_t, mux);
 
-       if (dev_t->sync_write)
-               gpmc_calc_sync_write_timings(gpmc_t, dev_t);
+       if (gpmc_s && gpmc_s->sync_write)
+               gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux);
        else
-               gpmc_calc_async_write_timings(gpmc_t, dev_t);
+               gpmc_calc_async_write_timings(gpmc_t, dev_t, mux);
 
        /* TODO: remove, see function definition */
        gpmc_convert_ps_to_ns(gpmc_t);
@@ -1125,6 +1134,90 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
        return 0;
 }
 
+/**
+ * gpmc_cs_program_settings - programs non-timing related settings
+ * @cs:                GPMC chip-select to program
+ * @p:         pointer to GPMC settings structure
+ *
+ * Programs non-timing related settings for a GPMC chip-select, such as
+ * bus-width, burst configuration, etc. Function should be called once
+ * for each chip-select that is being used and must be called before
+ * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
+ * register will be initialised to zero by this function. Returns 0 on
+ * success and appropriate negative error code on failure.
+ */
+int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
+{
+       u32 config1;
+
+       if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) {
+               pr_err("%s: invalid width %d!", __func__, p->device_width);
+               return -EINVAL;
+       }
+
+       /* Address-data multiplexing not supported for NAND devices */
+       if (p->device_nand && p->mux_add_data) {
+               pr_err("%s: invalid configuration!\n", __func__);
+               return -EINVAL;
+       }
+
+       if ((p->mux_add_data > GPMC_MUX_AD) ||
+           ((p->mux_add_data == GPMC_MUX_AAD) &&
+            !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
+               pr_err("%s: invalid multiplex configuration!\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+       if (p->burst_read || p->burst_write) {
+               switch (p->burst_len) {
+               case GPMC_BURST_4:
+               case GPMC_BURST_8:
+               case GPMC_BURST_16:
+                       break;
+               default:
+                       pr_err("%s: invalid page/burst-length (%d)\n",
+                              __func__, p->burst_len);
+                       return -EINVAL;
+               }
+       }
+
+       if ((p->wait_on_read || p->wait_on_write) &&
+           (p->wait_pin > gpmc_nr_waitpins)) {
+               pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+               return -EINVAL;
+       }
+
+       config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+       if (p->sync_read)
+               config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+       if (p->sync_write)
+               config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+       if (p->wait_on_read)
+               config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+       if (p->wait_on_write)
+               config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+       if (p->wait_on_read || p->wait_on_write)
+               config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+       if (p->device_nand)
+               config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+       if (p->mux_add_data)
+               config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+       if (p->burst_read)
+               config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+       if (p->burst_write)
+               config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+       if (p->burst_read || p->burst_write) {
+               config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+               config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+       }
+
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
+
+       return 0;
+}
+
 #ifdef CONFIG_OF
 static struct of_device_id gpmc_dt_ids[] = {
        { .compatible = "ti,omap2420-gpmc" },
@@ -1136,70 +1229,110 @@ static struct of_device_id gpmc_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
 
+/**
+ * gpmc_read_settings_dt - read gpmc settings from device-tree
+ * @np:                pointer to device-tree node for a gpmc child device
+ * @p:         pointer to gpmc settings structure
+ *
+ * Reads the GPMC settings for a GPMC child device from device-tree and
+ * stores them in the GPMC settings structure passed. The GPMC settings
+ * structure is initialised to zero by this function and so any
+ * previously stored settings will be cleared.
+ */
+void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
+{
+       memset(p, 0, sizeof(struct gpmc_settings));
+
+       p->sync_read = of_property_read_bool(np, "gpmc,sync-read");
+       p->sync_write = of_property_read_bool(np, "gpmc,sync-write");
+       p->device_nand = of_property_read_bool(np, "gpmc,device-nand");
+       of_property_read_u32(np, "gpmc,device-width", &p->device_width);
+       of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
+
+       if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
+               p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap");
+               p->burst_read = of_property_read_bool(np, "gpmc,burst-read");
+               p->burst_write = of_property_read_bool(np, "gpmc,burst-write");
+               if (!p->burst_read && !p->burst_write)
+                       pr_warn("%s: page/burst-length set but not used!\n",
+                               __func__);
+       }
+
+       if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
+               p->wait_on_read = of_property_read_bool(np,
+                                                       "gpmc,wait-on-read");
+               p->wait_on_write = of_property_read_bool(np,
+                                                        "gpmc,wait-on-write");
+               if (!p->wait_on_read && !p->wait_on_write)
+                       pr_warn("%s: read/write wait monitoring not enabled!\n",
+                               __func__);
+       }
+}
+
 static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
                                                struct gpmc_timings *gpmc_t)
 {
-       u32 val;
+       struct gpmc_bool_timings *p;
+
+       if (!np || !gpmc_t)
+               return;
 
        memset(gpmc_t, 0, sizeof(*gpmc_t));
 
        /* minimum clock period for syncronous mode */
-       if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
-               gpmc_t->sync_clk = val;
+       of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk);
 
        /* chip select timtings */
-       if (!of_property_read_u32(np, "gpmc,cs-on", &val))
-               gpmc_t->cs_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
-               gpmc_t->cs_rd_off = val;
-
-       if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
-               gpmc_t->cs_wr_off = val;
+       of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on);
+       of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off);
+       of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off);
 
        /* ADV signal timings */
-       if (!of_property_read_u32(np, "gpmc,adv-on", &val))
-               gpmc_t->adv_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
-               gpmc_t->adv_rd_off = val;
-
-       if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
-               gpmc_t->adv_wr_off = val;
+       of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on);
+       of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off);
+       of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off);
 
        /* WE signal timings */
-       if (!of_property_read_u32(np, "gpmc,we-on", &val))
-               gpmc_t->we_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,we-off", &val))
-               gpmc_t->we_off = val;
+       of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on);
+       of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off);
 
        /* OE signal timings */
-       if (!of_property_read_u32(np, "gpmc,oe-on", &val))
-               gpmc_t->oe_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,oe-off", &val))
-               gpmc_t->oe_off = val;
+       of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on);
+       of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off);
 
        /* access and cycle timings */
-       if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
-               gpmc_t->page_burst_access = val;
-
-       if (!of_property_read_u32(np, "gpmc,access", &val))
-               gpmc_t->access = val;
-
-       if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
-               gpmc_t->rd_cycle = val;
-
-       if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
-               gpmc_t->wr_cycle = val;
-
-       /* only for OMAP3430 */
-       if (!of_property_read_u32(np, "gpmc,wr-access", &val))
-               gpmc_t->wr_access = val;
-
-       if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
-               gpmc_t->wr_data_mux_bus = val;
+       of_property_read_u32(np, "gpmc,page-burst-access-ns",
+                            &gpmc_t->page_burst_access);
+       of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access);
+       of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle);
+       of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle);
+       of_property_read_u32(np, "gpmc,bus-turnaround-ns",
+                            &gpmc_t->bus_turnaround);
+       of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns",
+                            &gpmc_t->cycle2cycle_delay);
+       of_property_read_u32(np, "gpmc,wait-monitoring-ns",
+                            &gpmc_t->wait_monitoring);
+       of_property_read_u32(np, "gpmc,clk-activation-ns",
+                            &gpmc_t->clk_activation);
+
+       /* only applicable to OMAP3+ */
+       of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access);
+       of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns",
+                            &gpmc_t->wr_data_mux_bus);
+
+       /* bool timing parameters */
+       p = &gpmc_t->bool_timings;
+
+       p->cycle2cyclediffcsen =
+               of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen");
+       p->cycle2cyclesamecsen =
+               of_property_read_bool(np, "gpmc,cycle2cycle-samecsen");
+       p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay");
+       p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay");
+       p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay");
+       p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay");
+       p->time_para_granularity =
+               of_property_read_bool(np, "gpmc,time-para-granularity");
 }
 
 #ifdef CONFIG_MTD_NAND
@@ -1295,6 +1428,81 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
 }
 #endif
 
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev:      pointer to gpmc platform device
+ * @child:     pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_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);
+       ret = -ENODEV;
+
+err:
+       gpmc_cs_free(cs);
+
+       return ret;
+}
+
 static int gpmc_probe_dt(struct platform_device *pdev)
 {
        int ret;
@@ -1305,6 +1513,13 @@ static int gpmc_probe_dt(struct platform_device *pdev)
        if (!of_id)
                return 0;
 
+       ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
+                                  &gpmc_nr_waitpins);
+       if (ret < 0) {
+               pr_err("%s: number of wait pins not found!\n", __func__);
+               return ret;
+       }
+
        for_each_node_by_name(child, "nand") {
                ret = gpmc_probe_nand_child(pdev, child);
                if (ret < 0) {
@@ -1320,6 +1535,23 @@ static int gpmc_probe_dt(struct platform_device *pdev)
                        return ret;
                }
        }
+
+       for_each_node_by_name(child, "nor") {
+               ret = gpmc_probe_generic_child(pdev, child);
+               if (ret < 0) {
+                       of_node_put(child);
+                       return ret;
+               }
+       }
+
+       for_each_node_by_name(child, "ethernet") {
+               ret = gpmc_probe_generic_child(pdev, child);
+               if (ret < 0) {
+                       of_node_put(child);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 #else
@@ -1364,18 +1596,27 @@ static int gpmc_probe(struct platform_device *pdev)
        gpmc_dev = &pdev->dev;
 
        l = gpmc_read_reg(GPMC_REVISION);
+
+       /*
+        * FIXME: Once device-tree migration is complete the below flags
+        * should be populated based upon the device-tree compatible
+        * string. For now just use the IP revision. OMAP3+ devices have
+        * the wr_access and wr_data_mux_bus register fields. OMAP4+
+        * devices support the addr-addr-data multiplex protocol.
+        *
+        * GPMC IP revisions:
+        * - OMAP24xx                   = 2.0
+        * - OMAP3xxx                   = 5.0
+        * - OMAP44xx/54xx/AM335x       = 6.0
+        */
        if (GPMC_REVISION_MAJOR(l) > 0x4)
                gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
+       if (GPMC_REVISION_MAJOR(l) > 0x5)
+               gpmc_capability |= GPMC_HAS_MUX_AAD;
        dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
                 GPMC_REVISION_MINOR(l));
 
-       rc = gpmc_mem_init();
-       if (rc < 0) {
-               clk_disable_unprepare(gpmc_l3_clk);
-               clk_put(gpmc_l3_clk);
-               dev_err(gpmc_dev, "failed to reserve memory\n");
-               return rc;
-       }
+       gpmc_mem_init();
 
        if (gpmc_setup_irq() < 0)
                dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
@@ -1383,6 +1624,9 @@ static int gpmc_probe(struct platform_device *pdev)
        /* Now the GPMC is initialised, unreserve the chip-selects */
        gpmc_cs_map = 0;
 
+       if (!pdev->dev.of_node)
+               gpmc_nr_waitpins = GPMC_NR_WAITPINS;
+
        rc = gpmc_probe_dt(pdev);
        if (rc < 0) {
                clk_disable_unprepare(gpmc_l3_clk);
index fe0a844d5007a7775cadf78e357b541bbb80b153..707f6d58edd53d300a1b266cc229b3f9c1edd8f3 100644 (file)
@@ -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))
 #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
index c5a3c6f9504e79c8085e12e0aac10904a5177ab3..e832bc7b8e2dd77042ef323d68185d8f9a7dd135 100644 (file)
@@ -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>
 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");
This page took 0.08383 seconds and 5 git commands to generate.