diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 13:59:11 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 13:59:11 -0500 |
| commit | 698d601224824bc1a5bf17f3d86be902e2aabff0 (patch) | |
| tree | 10262bd1f83fd26f874cbd898818e5925844a2ef | |
| parent | a11da7df6543b5f71a150b47c0d08ecf0799a0f3 (diff) | |
| parent | 4aa7cf79b1f760b5751d1686329351c2e060791b (diff) | |
Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver specific changes from Olof Johansson:
"A collection of mostly SoC-specific driver updates:
- a handful of pincontrol and setup changes
- new drivers for hwmon and reset controller for vexpress
- timing support updates for OMAP (gpmc and other interfaces)
- plus a collection of smaller cleanups"
* tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (21 commits)
ARM: ux500: fix pin warning
ARM: OMAP2+: tusb6010: generic timing calculation
ARM: OMAP2+: smc91x: generic timing calculation
ARM: OMAP2+: onenand: generic timing calculation
ARM: OMAP2+: gpmc: generic timing calculation
ARM: OMAP2+: gpmc: handle additional timings
ARM: OMAP2+: nand: remove redundant rounding
gpio: samsung: use pr_* instead of printk
ARM: ux500: fixup magnetometer pins
ARM: ux500: add STM pin configuration
ARM: ux500: 8500: add pinctrl support for uart1 and uart2
ARM: ux500: cosmetic fixups for uart0
gpio: samsung: Fix input mode setting function for GPIO int
ARM: SAMSUNG: Insert bitmap_gpio_int member in samsung_gpio_chip
ARM: ux500: 8500: define SDI sleep states
ARM: vexpress: Reset driver
ARM: ux500: 8500: update SKE keypad pinctrl table
hwmon: Versatile Express hwmon driver
ARM: ux500: delete duplicate macro
ARM: ux500: 8500: add IDLE pin configuration for SPI
...
| -rw-r--r-- | Documentation/bus-devices/ti-gpmc.txt | 122 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/hwmon/vexpress.txt | 23 | ||||
| -rw-r--r-- | Documentation/hwmon/vexpress | 34 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/gpmc-nand.c | 26 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/gpmc-onenand.c | 143 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/gpmc-smc91x.c | 43 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 373 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/gpmc.h | 113 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/usb-tusb6010.c | 181 | ||||
| -rw-r--r-- | arch/arm/mach-ux500/board-mop500-pins.c | 425 | ||||
| -rw-r--r-- | arch/arm/mach-vexpress/reset.c | 141 | ||||
| -rw-r--r-- | arch/arm/plat-samsung/include/plat/gpio-core.h | 2 | ||||
| -rw-r--r-- | arch/arm/plat-samsung/s5p-irq-gpioint.c | 8 | ||||
| -rw-r--r-- | drivers/gpio/gpio-samsung.c | 25 | ||||
| -rw-r--r-- | drivers/hwmon/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
| -rw-r--r-- | drivers/hwmon/vexpress.c | 229 |
17 files changed, 1525 insertions, 372 deletions
diff --git a/Documentation/bus-devices/ti-gpmc.txt b/Documentation/bus-devices/ti-gpmc.txt new file mode 100644 index 000000000000..cc9ce57e0a26 --- /dev/null +++ b/Documentation/bus-devices/ti-gpmc.txt | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | GPMC (General Purpose Memory Controller): | ||
| 2 | ========================================= | ||
| 3 | |||
| 4 | GPMC is an unified memory controller dedicated to interfacing external | ||
| 5 | memory devices like | ||
| 6 | * Asynchronous SRAM like memories and application specific integrated | ||
| 7 | circuit devices. | ||
| 8 | * Asynchronous, synchronous, and page mode burst NOR flash devices | ||
| 9 | NAND flash | ||
| 10 | * Pseudo-SRAM devices | ||
| 11 | |||
| 12 | GPMC is found on Texas Instruments SoC's (OMAP based) | ||
| 13 | IP details: http://www.ti.com/lit/pdf/spruh73 section 7.1 | ||
| 14 | |||
| 15 | |||
| 16 | GPMC generic timing calculation: | ||
| 17 | ================================ | ||
| 18 | |||
| 19 | GPMC has certain timings that has to be programmed for proper | ||
| 20 | functioning of the peripheral, while peripheral has another set of | ||
| 21 | timings. To have peripheral work with gpmc, peripheral timings has to | ||
| 22 | be translated to the form gpmc can understand. The way it has to be | ||
| 23 | translated depends on the connected peripheral. Also there is a | ||
| 24 | dependency for certain gpmc timings on gpmc clock frequency. Hence a | ||
| 25 | generic timing routine was developed to achieve above requirements. | ||
| 26 | |||
| 27 | Generic routine provides a generic method to calculate gpmc timings | ||
| 28 | from gpmc peripheral timings. struct gpmc_device_timings fields has to | ||
| 29 | be updated with timings from the datasheet of the peripheral that is | ||
| 30 | connected to gpmc. A few of the peripheral timings can be fed either | ||
| 31 | in time or in cycles, provision to handle this scenario has been | ||
| 32 | provided (refer struct gpmc_device_timings definition). It may so | ||
| 33 | happen that timing as specified by peripheral datasheet is not present | ||
| 34 | in timing structure, in this scenario, try to correlate peripheral | ||
| 35 | timing to the one available. If that doesn't work, try to add a new | ||
| 36 | field as required by peripheral, educate generic timing routine to | ||
| 37 | handle it, make sure that it does not break any of the existing. | ||
| 38 | Then there may be cases where peripheral datasheet doesn't mention | ||
| 39 | certain fields of struct gpmc_device_timings, zero those entries. | ||
| 40 | |||
| 41 | Generic timing routine has been verified to work properly on | ||
| 42 | multiple onenand's and tusb6010 peripherals. | ||
| 43 | |||
| 44 | A word of caution: generic timing routine has been developed based | ||
| 45 | on understanding of gpmc timings, peripheral timings, available | ||
| 46 | custom timing routines, a kind of reverse engineering without | ||
| 47 | most of the datasheets & hardware (to be exact none of those supported | ||
| 48 | in mainline having custom timing routine) and by simulation. | ||
| 49 | |||
| 50 | gpmc timing dependency on peripheral timings: | ||
| 51 | [<gpmc_timing>: <peripheral timing1>, <peripheral timing2> ...] | ||
| 52 | |||
| 53 | 1. common | ||
| 54 | cs_on: t_ceasu | ||
| 55 | adv_on: t_avdasu, t_ceavd | ||
| 56 | |||
| 57 | 2. sync common | ||
| 58 | sync_clk: clk | ||
| 59 | page_burst_access: t_bacc | ||
| 60 | clk_activation: t_ces, t_avds | ||
| 61 | |||
| 62 | 3. read async muxed | ||
| 63 | adv_rd_off: t_avdp_r | ||
| 64 | oe_on: t_oeasu, t_aavdh | ||
| 65 | access: t_iaa, t_oe, t_ce, t_aa | ||
| 66 | rd_cycle: t_rd_cycle, t_cez_r, t_oez | ||
| 67 | |||
| 68 | 4. read async non-muxed | ||
| 69 | adv_rd_off: t_avdp_r | ||
| 70 | oe_on: t_oeasu | ||
| 71 | access: t_iaa, t_oe, t_ce, t_aa | ||
| 72 | rd_cycle: t_rd_cycle, t_cez_r, t_oez | ||
| 73 | |||
| 74 | 5. read sync muxed | ||
| 75 | adv_rd_off: t_avdp_r, t_avdh | ||
| 76 | oe_on: t_oeasu, t_ach, cyc_aavdh_oe | ||
| 77 | access: t_iaa, cyc_iaa, cyc_oe | ||
| 78 | rd_cycle: t_cez_r, t_oez, t_ce_rdyz | ||
| 79 | |||
| 80 | 6. read sync non-muxed | ||
| 81 | adv_rd_off: t_avdp_r | ||
| 82 | oe_on: t_oeasu | ||
| 83 | access: t_iaa, cyc_iaa, cyc_oe | ||
| 84 | rd_cycle: t_cez_r, t_oez, t_ce_rdyz | ||
| 85 | |||
| 86 | 7. write async muxed | ||
| 87 | adv_wr_off: t_avdp_w | ||
| 88 | we_on, wr_data_mux_bus: t_weasu, t_aavdh, cyc_aavhd_we | ||
| 89 | we_off: t_wpl | ||
| 90 | cs_wr_off: t_wph | ||
| 91 | wr_cycle: t_cez_w, t_wr_cycle | ||
| 92 | |||
| 93 | 8. write async non-muxed | ||
| 94 | adv_wr_off: t_avdp_w | ||
| 95 | we_on, wr_data_mux_bus: t_weasu | ||
| 96 | we_off: t_wpl | ||
| 97 | cs_wr_off: t_wph | ||
| 98 | wr_cycle: t_cez_w, t_wr_cycle | ||
| 99 | |||
| 100 | 9. write sync muxed | ||
| 101 | adv_wr_off: t_avdp_w, t_avdh | ||
| 102 | we_on, wr_data_mux_bus: t_weasu, t_rdyo, t_aavdh, cyc_aavhd_we | ||
| 103 | we_off: t_wpl, cyc_wpl | ||
| 104 | cs_wr_off: t_wph | ||
| 105 | wr_cycle: t_cez_w, t_ce_rdyz | ||
| 106 | |||
| 107 | 10. write sync non-muxed | ||
| 108 | adv_wr_off: t_avdp_w | ||
| 109 | we_on, wr_data_mux_bus: t_weasu, t_rdyo | ||
| 110 | we_off: t_wpl, cyc_wpl | ||
| 111 | cs_wr_off: t_wph | ||
| 112 | wr_cycle: t_cez_w, t_ce_rdyz | ||
| 113 | |||
| 114 | |||
| 115 | Note: Many of gpmc timings are dependent on other gpmc timings (a few | ||
| 116 | gpmc timings purely dependent on other gpmc timings, a reason that | ||
| 117 | some of the gpmc timings are missing above), and it will result in | ||
| 118 | indirect dependency of peripheral timings to gpmc timings other than | ||
| 119 | mentioned above, refer timing routine for more details. To know what | ||
| 120 | these peripheral timings correspond to, please see explanations in | ||
| 121 | struct gpmc_device_timings definition. And for gpmc timings refer | ||
| 122 | IP details (link above). | ||
diff --git a/Documentation/devicetree/bindings/hwmon/vexpress.txt b/Documentation/devicetree/bindings/hwmon/vexpress.txt new file mode 100644 index 000000000000..9c27ed694bbb --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/vexpress.txt | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | Versatile Express hwmon sensors | ||
| 2 | ------------------------------- | ||
| 3 | |||
| 4 | Requires node properties: | ||
| 5 | - "compatible" value : one of | ||
| 6 | "arm,vexpress-volt" | ||
| 7 | "arm,vexpress-amp" | ||
| 8 | "arm,vexpress-temp" | ||
| 9 | "arm,vexpress-power" | ||
| 10 | "arm,vexpress-energy" | ||
| 11 | - "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg | ||
| 12 | (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt | ||
| 13 | for more details) | ||
| 14 | |||
| 15 | Optional node properties: | ||
| 16 | - label : string describing the monitored value | ||
| 17 | |||
| 18 | Example: | ||
| 19 | energy@0 { | ||
| 20 | compatible = "arm,vexpress-energy"; | ||
| 21 | arm,vexpress-sysreg,func = <13 0>; | ||
| 22 | label = "A15 Jcore"; | ||
| 23 | }; | ||
diff --git a/Documentation/hwmon/vexpress b/Documentation/hwmon/vexpress new file mode 100644 index 000000000000..557d6d5ad90d --- /dev/null +++ b/Documentation/hwmon/vexpress | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | Kernel driver vexpress | ||
| 2 | ====================== | ||
| 3 | |||
| 4 | Supported systems: | ||
| 5 | * ARM Ltd. Versatile Express platform | ||
| 6 | Prefix: 'vexpress' | ||
| 7 | Datasheets: | ||
| 8 | * "Hardware Description" sections of the Technical Reference Manuals | ||
| 9 | for the Versatile Express boards: | ||
| 10 | http://infocenter.arm.com/help/topic/com.arm.doc.subset.boards.express/index.html | ||
| 11 | * Section "4.4.14. System Configuration registers" of the V2M-P1 TRM: | ||
| 12 | http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0447-/index.html | ||
| 13 | |||
| 14 | Author: Pawel Moll | ||
| 15 | |||
| 16 | Description | ||
| 17 | ----------- | ||
| 18 | |||
| 19 | Versatile Express platform (http://www.arm.com/versatileexpress/) is a | ||
| 20 | reference & prototyping system for ARM Ltd. processors. It can be set up | ||
| 21 | from a wide range of boards, each of them containing (apart of the main | ||
| 22 | chip/FPGA) a number of microcontrollers responsible for platform | ||
| 23 | configuration and control. Theses microcontrollers can also monitor the | ||
| 24 | board and its environment by a number of internal and external sensors, | ||
| 25 | providing information about power lines voltages and currents, board | ||
| 26 | temperature and power usage. Some of them also calculate consumed energy | ||
| 27 | and provide a cumulative use counter. | ||
| 28 | |||
| 29 | The configuration devices are _not_ memory mapped and must be accessed | ||
| 30 | via a custom interface, abstracted by the "vexpress_config" API. | ||
| 31 | |||
| 32 | As these devices are non-discoverable, they must be described in a Device | ||
| 33 | Tree passed to the kernel. Details of the DT binding for them can be found | ||
| 34 | in Documentation/devicetree/bindings/hwmon/vexpress.txt. | ||
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 8607735b3ab3..db969a5c4998 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c | |||
| @@ -52,27 +52,27 @@ static int omap2_nand_gpmc_retime( | |||
| 52 | 52 | ||
| 53 | memset(&t, 0, sizeof(t)); | 53 | memset(&t, 0, sizeof(t)); |
| 54 | t.sync_clk = gpmc_t->sync_clk; | 54 | t.sync_clk = gpmc_t->sync_clk; |
| 55 | t.cs_on = gpmc_round_ns_to_ticks(gpmc_t->cs_on); | 55 | t.cs_on = gpmc_t->cs_on; |
| 56 | t.adv_on = gpmc_round_ns_to_ticks(gpmc_t->adv_on); | 56 | t.adv_on = gpmc_t->adv_on; |
| 57 | 57 | ||
| 58 | /* Read */ | 58 | /* Read */ |
| 59 | t.adv_rd_off = gpmc_round_ns_to_ticks(gpmc_t->adv_rd_off); | 59 | t.adv_rd_off = gpmc_t->adv_rd_off; |
| 60 | t.oe_on = t.adv_on; | 60 | t.oe_on = t.adv_on; |
| 61 | t.access = gpmc_round_ns_to_ticks(gpmc_t->access); | 61 | t.access = gpmc_t->access; |
| 62 | t.oe_off = gpmc_round_ns_to_ticks(gpmc_t->oe_off); | 62 | t.oe_off = gpmc_t->oe_off; |
| 63 | t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_t->cs_rd_off); | 63 | t.cs_rd_off = gpmc_t->cs_rd_off; |
| 64 | t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_t->rd_cycle); | 64 | t.rd_cycle = gpmc_t->rd_cycle; |
| 65 | 65 | ||
| 66 | /* Write */ | 66 | /* Write */ |
| 67 | t.adv_wr_off = gpmc_round_ns_to_ticks(gpmc_t->adv_wr_off); | 67 | t.adv_wr_off = gpmc_t->adv_wr_off; |
| 68 | t.we_on = t.oe_on; | 68 | t.we_on = t.oe_on; |
| 69 | if (cpu_is_omap34xx()) { | 69 | if (cpu_is_omap34xx()) { |
| 70 | t.wr_data_mux_bus = gpmc_round_ns_to_ticks(gpmc_t->wr_data_mux_bus); | 70 | t.wr_data_mux_bus = gpmc_t->wr_data_mux_bus; |
| 71 | t.wr_access = gpmc_round_ns_to_ticks(gpmc_t->wr_access); | 71 | t.wr_access = gpmc_t->wr_access; |
| 72 | } | 72 | } |
| 73 | t.we_off = gpmc_round_ns_to_ticks(gpmc_t->we_off); | 73 | t.we_off = gpmc_t->we_off; |
| 74 | t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_t->cs_wr_off); | 74 | t.cs_wr_off = gpmc_t->cs_wr_off; |
| 75 | t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_t->wr_cycle); | 75 | t.wr_cycle = gpmc_t->wr_cycle; |
| 76 | 76 | ||
| 77 | /* Configure GPMC */ | 77 | /* Configure GPMC */ |
| 78 | if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) | 78 | if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) |
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index d102183ed9a5..94a349e4dc96 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | 33 | ||
| 34 | static unsigned onenand_flags; | 34 | static unsigned onenand_flags; |
| 35 | static unsigned latency; | 35 | static unsigned latency; |
| 36 | static int fclk_offset; | ||
| 37 | 36 | ||
| 38 | static struct omap_onenand_platform_data *gpmc_onenand_data; | 37 | static struct omap_onenand_platform_data *gpmc_onenand_data; |
| 39 | 38 | ||
| @@ -50,6 +49,7 @@ static struct platform_device gpmc_onenand_device = { | |||
| 50 | 49 | ||
| 51 | static struct gpmc_timings omap2_onenand_calc_async_timings(void) | 50 | static struct gpmc_timings omap2_onenand_calc_async_timings(void) |
| 52 | { | 51 | { |
| 52 | struct gpmc_device_timings dev_t; | ||
| 53 | struct gpmc_timings t; | 53 | struct gpmc_timings t; |
| 54 | 54 | ||
| 55 | const int t_cer = 15; | 55 | const int t_cer = 15; |
| @@ -59,35 +59,24 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void) | |||
| 59 | const int t_aa = 76; | 59 | const int t_aa = 76; |
| 60 | const int t_oe = 20; | 60 | const int t_oe = 20; |
| 61 | const int t_cez = 20; /* max of t_cez, t_oez */ | 61 | const int t_cez = 20; /* max of t_cez, t_oez */ |
| 62 | const int t_ds = 30; | ||
| 63 | const int t_wpl = 40; | 62 | const int t_wpl = 40; |
| 64 | const int t_wph = 30; | 63 | const int t_wph = 30; |
| 65 | 64 | ||
| 66 | memset(&t, 0, sizeof(t)); | 65 | memset(&dev_t, 0, sizeof(dev_t)); |
| 67 | t.sync_clk = 0; | 66 | |
| 68 | t.cs_on = 0; | 67 | dev_t.mux = true; |
| 69 | t.adv_on = 0; | 68 | dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000; |
| 70 | 69 | dev_t.t_avdp_w = dev_t.t_avdp_r; | |
| 71 | /* Read */ | 70 | dev_t.t_aavdh = t_aavdh * 1000; |
| 72 | t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer)); | 71 | dev_t.t_aa = t_aa * 1000; |
| 73 | t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh); | 72 | dev_t.t_ce = t_ce * 1000; |
| 74 | t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa); | 73 | dev_t.t_oe = t_oe * 1000; |
| 75 | t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce)); | 74 | dev_t.t_cez_r = t_cez * 1000; |
| 76 | t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe)); | 75 | dev_t.t_cez_w = dev_t.t_cez_r; |
| 77 | t.oe_off = t.access + gpmc_round_ns_to_ticks(1); | 76 | dev_t.t_wpl = t_wpl * 1000; |
| 78 | t.cs_rd_off = t.oe_off; | 77 | dev_t.t_wph = t_wph * 1000; |
| 79 | t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez); | 78 | |
| 80 | 79 | gpmc_calc_timings(&t, &dev_t); | |
| 81 | /* Write */ | ||
| 82 | t.adv_wr_off = t.adv_rd_off; | ||
| 83 | t.we_on = t.oe_on; | ||
| 84 | if (cpu_is_omap34xx()) { | ||
| 85 | t.wr_data_mux_bus = t.we_on; | ||
| 86 | t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); | ||
| 87 | } | ||
| 88 | t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); | ||
| 89 | t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); | ||
| 90 | t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); | ||
| 91 | 80 | ||
| 92 | return t; | 81 | return t; |
| 93 | } | 82 | } |
| @@ -173,18 +162,15 @@ static struct gpmc_timings | |||
| 173 | omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, | 162 | omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, |
| 174 | int freq) | 163 | int freq) |
| 175 | { | 164 | { |
| 165 | struct gpmc_device_timings dev_t; | ||
| 176 | struct gpmc_timings t; | 166 | struct gpmc_timings t; |
| 177 | const int t_cer = 15; | 167 | const int t_cer = 15; |
| 178 | const int t_avdp = 12; | 168 | const int t_avdp = 12; |
| 179 | const int t_cez = 20; /* max of t_cez, t_oez */ | 169 | const int t_cez = 20; /* max of t_cez, t_oez */ |
| 180 | const int t_ds = 30; | ||
| 181 | const int t_wpl = 40; | 170 | const int t_wpl = 40; |
| 182 | const int t_wph = 30; | 171 | const int t_wph = 30; |
| 183 | int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; | 172 | int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; |
| 184 | u32 reg; | 173 | int div, gpmc_clk_ns; |
| 185 | int div, fclk_offset_ns, gpmc_clk_ns; | ||
| 186 | int ticks_cez; | ||
| 187 | int cs = cfg->cs; | ||
| 188 | 174 | ||
| 189 | if (cfg->flags & ONENAND_SYNC_READ) | 175 | if (cfg->flags & ONENAND_SYNC_READ) |
| 190 | onenand_flags = ONENAND_FLAG_SYNCREAD; | 176 | onenand_flags = ONENAND_FLAG_SYNCREAD; |
| @@ -251,77 +237,35 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, | |||
| 251 | latency = 4; | 237 | latency = 4; |
| 252 | 238 | ||
| 253 | /* Set synchronous read timings */ | 239 | /* Set synchronous read timings */ |
| 254 | memset(&t, 0, sizeof(t)); | 240 | memset(&dev_t, 0, sizeof(dev_t)); |
| 255 | |||
| 256 | if (div == 1) { | ||
| 257 | reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); | ||
| 258 | reg |= (1 << 7); | ||
| 259 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); | ||
| 260 | reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); | ||
| 261 | reg |= (1 << 7); | ||
| 262 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); | ||
| 263 | reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); | ||
| 264 | reg |= (1 << 7); | ||
| 265 | reg |= (1 << 23); | ||
| 266 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); | ||
| 267 | } else { | ||
| 268 | reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); | ||
| 269 | reg &= ~(1 << 7); | ||
| 270 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); | ||
| 271 | reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); | ||
| 272 | reg &= ~(1 << 7); | ||
| 273 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); | ||
| 274 | reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); | ||
| 275 | reg &= ~(1 << 7); | ||
| 276 | reg &= ~(1 << 23); | ||
| 277 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); | ||
| 278 | } | ||
| 279 | 241 | ||
| 280 | t.sync_clk = min_gpmc_clk_period; | 242 | dev_t.mux = true; |
| 281 | t.cs_on = 0; | 243 | dev_t.sync_read = true; |
| 282 | t.adv_on = 0; | ||
| 283 | fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds)); | ||
| 284 | fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns); | ||
| 285 | t.page_burst_access = gpmc_clk_ns; | ||
| 286 | |||
| 287 | /* Read */ | ||
| 288 | t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh)); | ||
| 289 | t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach)); | ||
| 290 | /* Force at least 1 clk between AVD High to OE Low */ | ||
| 291 | if (t.oe_on <= t.adv_rd_off) | ||
| 292 | t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1); | ||
| 293 | t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div); | ||
| 294 | t.oe_off = t.access + gpmc_round_ns_to_ticks(1); | ||
| 295 | t.cs_rd_off = t.oe_off; | ||
| 296 | ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div; | ||
| 297 | t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + | ||
| 298 | ticks_cez); | ||
| 299 | |||
| 300 | /* Write */ | ||
| 301 | if (onenand_flags & ONENAND_FLAG_SYNCWRITE) { | 244 | if (onenand_flags & ONENAND_FLAG_SYNCWRITE) { |
| 302 | t.adv_wr_off = t.adv_rd_off; | 245 | dev_t.sync_write = true; |
| 303 | t.we_on = 0; | ||
| 304 | t.we_off = t.cs_rd_off; | ||
| 305 | t.cs_wr_off = t.cs_rd_off; | ||
| 306 | t.wr_cycle = t.rd_cycle; | ||
| 307 | if (cpu_is_omap34xx()) { | ||
| 308 | t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset + | ||
| 309 | gpmc_ps_to_ticks(min_gpmc_clk_period + | ||
| 310 | t_rdyo * 1000)); | ||
| 311 | t.wr_access = t.access; | ||
| 312 | } | ||
| 313 | } else { | 246 | } else { |
| 314 | t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int, | 247 | dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000; |
| 315 | t_avdp, t_cer)); | 248 | dev_t.t_wpl = t_wpl * 1000; |
| 316 | t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh); | 249 | dev_t.t_wph = t_wph * 1000; |
| 317 | t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); | 250 | dev_t.t_aavdh = t_aavdh * 1000; |
| 318 | t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); | ||
| 319 | t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); | ||
| 320 | if (cpu_is_omap34xx()) { | ||
| 321 | t.wr_data_mux_bus = t.we_on; | ||
| 322 | t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); | ||
| 323 | } | ||
| 324 | } | 251 | } |
| 252 | dev_t.ce_xdelay = true; | ||
| 253 | dev_t.avd_xdelay = true; | ||
| 254 | dev_t.oe_xdelay = true; | ||
| 255 | dev_t.we_xdelay = true; | ||
| 256 | dev_t.clk = min_gpmc_clk_period; | ||
| 257 | dev_t.t_bacc = dev_t.clk; | ||
| 258 | dev_t.t_ces = t_ces * 1000; | ||
| 259 | dev_t.t_avds = t_avds * 1000; | ||
| 260 | dev_t.t_avdh = t_avdh * 1000; | ||
| 261 | dev_t.t_ach = t_ach * 1000; | ||
| 262 | dev_t.cyc_iaa = (latency + 1); | ||
| 263 | dev_t.t_cez_r = t_cez * 1000; | ||
| 264 | dev_t.t_cez_w = dev_t.t_cez_r; | ||
| 265 | dev_t.cyc_aavdh_oe = 1; | ||
| 266 | dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period; | ||
| 267 | |||
| 268 | gpmc_calc_timings(&t, &dev_t); | ||
| 325 | 269 | ||
| 326 | return t; | 270 | return t; |
| 327 | } | 271 | } |
| @@ -338,7 +282,6 @@ static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t) | |||
| 338 | (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | | 282 | (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | |
| 339 | (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | | 283 | (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | |
| 340 | (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | | 284 | (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | |
| 341 | GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | | ||
| 342 | GPMC_CONFIG1_PAGE_LEN(2) | | 285 | GPMC_CONFIG1_PAGE_LEN(2) | |
| 343 | (cpu_is_omap34xx() ? 0 : | 286 | (cpu_is_omap34xx() ? 0 : |
| 344 | (GPMC_CONFIG1_WAIT_READ_MON | | 287 | (GPMC_CONFIG1_WAIT_READ_MON | |
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c index 6eed907d594c..11d0b756f098 100644 --- a/arch/arm/mach-omap2/gpmc-smc91x.c +++ b/arch/arm/mach-omap2/gpmc-smc91x.c | |||
| @@ -58,6 +58,7 @@ static struct platform_device gpmc_smc91x_device = { | |||
| 58 | static int smc91c96_gpmc_retime(void) | 58 | static int smc91c96_gpmc_retime(void) |
| 59 | { | 59 | { |
| 60 | struct gpmc_timings t; | 60 | struct gpmc_timings t; |
| 61 | struct gpmc_device_timings dev_t; | ||
| 61 | const int t3 = 10; /* Figure 12.2 read and 12.4 write */ | 62 | const int t3 = 10; /* Figure 12.2 read and 12.4 write */ |
| 62 | const int t4_r = 20; /* Figure 12.2 read */ | 63 | const int t4_r = 20; /* Figure 12.2 read */ |
| 63 | const int t4_w = 5; /* Figure 12.4 write */ | 64 | const int t4_w = 5; /* Figure 12.4 write */ |
| @@ -68,32 +69,6 @@ static int smc91c96_gpmc_retime(void) | |||
| 68 | const int t20 = 185; /* Figure 12.2 read and 12.4 write */ | 69 | const int t20 = 185; /* Figure 12.2 read and 12.4 write */ |
| 69 | u32 l; | 70 | u32 l; |
| 70 | 71 | ||
| 71 | memset(&t, 0, sizeof(t)); | ||
| 72 | |||
| 73 | /* Read timings */ | ||
| 74 | t.cs_on = 0; | ||
| 75 | t.adv_on = t.cs_on; | ||
| 76 | t.oe_on = t.adv_on + t3; | ||
| 77 | t.access = t.oe_on + t5; | ||
| 78 | t.oe_off = t.access; | ||
| 79 | t.adv_rd_off = t.oe_off + max(t4_r, t6); | ||
| 80 | t.cs_rd_off = t.oe_off; | ||
| 81 | t.rd_cycle = t20 - t.oe_on; | ||
| 82 | |||
| 83 | /* Write timings */ | ||
| 84 | t.we_on = t.adv_on + t3; | ||
| 85 | |||
| 86 | if (cpu_is_omap34xx() && (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)) { | ||
| 87 | t.wr_data_mux_bus = t.we_on; | ||
| 88 | t.we_off = t.wr_data_mux_bus + t7; | ||
| 89 | } else | ||
| 90 | t.we_off = t.we_on + t7; | ||
| 91 | if (cpu_is_omap34xx()) | ||
| 92 | t.wr_access = t.we_off; | ||
| 93 | t.adv_wr_off = t.we_off + max(t4_w, t8); | ||
| 94 | t.cs_wr_off = t.we_off + t4_w; | ||
| 95 | t.wr_cycle = t20 - t.we_on; | ||
| 96 | |||
| 97 | l = GPMC_CONFIG1_DEVICESIZE_16; | 72 | l = GPMC_CONFIG1_DEVICESIZE_16; |
| 98 | if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) | 73 | if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) |
| 99 | l |= GPMC_CONFIG1_MUXADDDATA; | 74 | l |= GPMC_CONFIG1_MUXADDDATA; |
| @@ -115,6 +90,22 @@ static int smc91c96_gpmc_retime(void) | |||
| 115 | if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) | 90 | if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) |
| 116 | return 0; | 91 | return 0; |
| 117 | 92 | ||
| 93 | memset(&dev_t, 0, sizeof(dev_t)); | ||
| 94 | |||
| 95 | dev_t.t_oeasu = t3 * 1000; | ||
| 96 | dev_t.t_oe = t5 * 1000; | ||
| 97 | dev_t.t_cez_r = t4_r * 1000; | ||
| 98 | dev_t.t_oez = t6 * 1000; | ||
| 99 | dev_t.t_rd_cycle = (t20 - t3) * 1000; | ||
| 100 | |||
| 101 | dev_t.t_weasu = t3 * 1000; | ||
| 102 | dev_t.t_wpl = t7 * 1000; | ||
| 103 | dev_t.t_wph = t8 * 1000; | ||
| 104 | dev_t.t_cez_w = t4_w * 1000; | ||
| 105 | dev_t.t_wr_cycle = (t20 - t3) * 1000; | ||
| 106 | |||
| 107 | gpmc_calc_timings(&t, &dev_t); | ||
| 108 | |||
| 118 | return gpmc_cs_set_timings(gpmc_cfg->cs, &t); | 109 | return gpmc_cs_set_timings(gpmc_cfg->cs, &t); |
| 119 | } | 110 | } |
| 120 | 111 | ||
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index bf6117c32f4b..65468f6d7f0e 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
| @@ -74,6 +74,13 @@ | |||
| 74 | #define GPMC_ECC_CTRL_ECCREG8 0x008 | 74 | #define GPMC_ECC_CTRL_ECCREG8 0x008 |
| 75 | #define GPMC_ECC_CTRL_ECCREG9 0x009 | 75 | #define GPMC_ECC_CTRL_ECCREG9 0x009 |
| 76 | 76 | ||
| 77 | #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) | ||
| 78 | #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) | ||
| 79 | #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) | ||
| 80 | #define GPMC_CONFIG4_WEEXTRADELAY BIT(23) | ||
| 81 | #define GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN BIT(6) | ||
| 82 | #define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN BIT(7) | ||
| 83 | |||
| 77 | #define GPMC_CS0_OFFSET 0x60 | 84 | #define GPMC_CS0_OFFSET 0x60 |
| 78 | #define GPMC_CS_SIZE 0x30 | 85 | #define GPMC_CS_SIZE 0x30 |
| 79 | #define GPMC_BCH_SIZE 0x10 | 86 | #define GPMC_BCH_SIZE 0x10 |
| @@ -223,6 +230,51 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) | |||
| 223 | return ticks * gpmc_get_fclk_period() / 1000; | 230 | return ticks * gpmc_get_fclk_period() / 1000; |
| 224 | } | 231 | } |
| 225 | 232 | ||
| 233 | static unsigned int gpmc_ticks_to_ps(unsigned int ticks) | ||
| 234 | { | ||
| 235 | return ticks * gpmc_get_fclk_period(); | ||
| 236 | } | ||
| 237 | |||
| 238 | static unsigned int gpmc_round_ps_to_ticks(unsigned int time_ps) | ||
| 239 | { | ||
| 240 | unsigned long ticks = gpmc_ps_to_ticks(time_ps); | ||
| 241 | |||
| 242 | return ticks * gpmc_get_fclk_period(); | ||
| 243 | } | ||
| 244 | |||
| 245 | static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value) | ||
| 246 | { | ||
| 247 | u32 l; | ||
| 248 | |||
| 249 | l = gpmc_cs_read_reg(cs, reg); | ||
| 250 | if (value) | ||
| 251 | l |= mask; | ||
| 252 | else | ||
| 253 | l &= ~mask; | ||
| 254 | gpmc_cs_write_reg(cs, reg, l); | ||
| 255 | } | ||
| 256 | |||
| 257 | static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) | ||
| 258 | { | ||
| 259 | gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1, | ||
| 260 | GPMC_CONFIG1_TIME_PARA_GRAN, | ||
| 261 | p->time_para_granularity); | ||
| 262 | gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2, | ||
| 263 | GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay); | ||
| 264 | gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3, | ||
| 265 | GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay); | ||
| 266 | gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, | ||
| 267 | GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay); | ||
| 268 | gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, | ||
| 269 | GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay); | ||
| 270 | gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, | ||
| 271 | GPMC_CONFIG6_CYCLE2CYCLESAMECSEN, | ||
| 272 | p->cycle2cyclesamecsen); | ||
| 273 | gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, | ||
| 274 | GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN, | ||
| 275 | p->cycle2cyclediffcsen); | ||
| 276 | } | ||
| 277 | |||
| 226 | #ifdef DEBUG | 278 | #ifdef DEBUG |
| 227 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | 279 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, |
| 228 | int time, const char *name) | 280 | int time, const char *name) |
| @@ -316,6 +368,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) | |||
| 316 | 368 | ||
| 317 | GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); | 369 | GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); |
| 318 | 370 | ||
| 371 | GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround); | ||
| 372 | GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay); | ||
| 373 | |||
| 374 | GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring); | ||
| 375 | GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); | ||
| 376 | |||
| 319 | if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) | 377 | if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) |
| 320 | GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); | 378 | GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); |
| 321 | if (gpmc_capability & GPMC_HAS_WR_ACCESS) | 379 | if (gpmc_capability & GPMC_HAS_WR_ACCESS) |
| @@ -335,6 +393,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) | |||
| 335 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); | 393 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); |
| 336 | } | 394 | } |
| 337 | 395 | ||
| 396 | gpmc_cs_bool_timings(cs, &t->bool_timings); | ||
| 397 | |||
| 338 | return 0; | 398 | return 0; |
| 339 | } | 399 | } |
| 340 | 400 | ||
| @@ -748,6 +808,319 @@ static int __devinit gpmc_mem_init(void) | |||
| 748 | return 0; | 808 | return 0; |
| 749 | } | 809 | } |
| 750 | 810 | ||
| 811 | static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk) | ||
| 812 | { | ||
| 813 | u32 temp; | ||
| 814 | int div; | ||
| 815 | |||
| 816 | div = gpmc_calc_divider(sync_clk); | ||
| 817 | temp = gpmc_ps_to_ticks(time_ps); | ||
| 818 | temp = (temp + div - 1) / div; | ||
| 819 | return gpmc_ticks_to_ps(temp * div); | ||
| 820 | } | ||
| 821 | |||
| 822 | /* XXX: can the cycles be avoided ? */ | ||
| 823 | static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t, | ||
| 824 | struct gpmc_device_timings *dev_t) | ||
| 825 | { | ||
| 826 | bool mux = dev_t->mux; | ||
| 827 | u32 temp; | ||
| 828 | |||
| 829 | /* adv_rd_off */ | ||
| 830 | temp = dev_t->t_avdp_r; | ||
| 831 | /* XXX: mux check required ? */ | ||
| 832 | if (mux) { | ||
| 833 | /* XXX: t_avdp not to be required for sync, only added for tusb | ||
| 834 | * this indirectly necessitates requirement of t_avdp_r and | ||
| 835 | * t_avdp_w instead of having a single t_avdp | ||
| 836 | */ | ||
| 837 | temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_avdh); | ||
| 838 | temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp); | ||
| 839 | } | ||
| 840 | gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp); | ||
| 841 | |||
| 842 | /* oe_on */ | ||
| 843 | temp = dev_t->t_oeasu; /* XXX: remove this ? */ | ||
| 844 | if (mux) { | ||
| 845 | temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_ach); | ||
| 846 | temp = max_t(u32, temp, gpmc_t->adv_rd_off + | ||
| 847 | gpmc_ticks_to_ps(dev_t->cyc_aavdh_oe)); | ||
| 848 | } | ||
| 849 | gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp); | ||
| 850 | |||
| 851 | /* access */ | ||
| 852 | /* XXX: any scope for improvement ?, by combining oe_on | ||
| 853 | * and clk_activation, need to check whether | ||
| 854 | * access = clk_activation + round to sync clk ? | ||
| 855 | */ | ||
| 856 | temp = max_t(u32, dev_t->t_iaa, dev_t->cyc_iaa * gpmc_t->sync_clk); | ||
| 857 | temp += gpmc_t->clk_activation; | ||
| 858 | if (dev_t->cyc_oe) | ||
| 859 | temp = max_t(u32, temp, gpmc_t->oe_on + | ||
| 860 | gpmc_ticks_to_ps(dev_t->cyc_oe)); | ||
| 861 | gpmc_t->access = gpmc_round_ps_to_ticks(temp); | ||
| 862 | |||
| 863 | gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1); | ||
| 864 | gpmc_t->cs_rd_off = gpmc_t->oe_off; | ||
| 865 | |||
| 866 | /* rd_cycle */ | ||
| 867 | temp = max_t(u32, dev_t->t_cez_r, dev_t->t_oez); | ||
| 868 | temp = gpmc_round_ps_to_sync_clk(temp, gpmc_t->sync_clk) + | ||
| 869 | gpmc_t->access; | ||
| 870 | /* XXX: barter t_ce_rdyz with t_cez_r ? */ | ||
| 871 | if (dev_t->t_ce_rdyz) | ||
| 872 | temp = max_t(u32, temp, gpmc_t->cs_rd_off + dev_t->t_ce_rdyz); | ||
| 873 | gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp); | ||
| 874 | |||
| 875 | return 0; | ||
| 876 | } | ||
| 877 | |||
| 878 | static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t, | ||
| 879 | struct gpmc_device_timings *dev_t) | ||
| 880 | { | ||
| 881 | bool mux = dev_t->mux; | ||
| 882 | u32 temp; | ||
| 883 | |||
| 884 | /* adv_wr_off */ | ||
| 885 | temp = dev_t->t_avdp_w; | ||
| 886 | if (mux) { | ||
| 887 | temp = max_t(u32, temp, | ||
| 888 | gpmc_t->clk_activation + dev_t->t_avdh); | ||
| 889 | temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp); | ||
| 890 | } | ||
| 891 | gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp); | ||
| 892 | |||
| 893 | /* wr_data_mux_bus */ | ||
| 894 | temp = max_t(u32, dev_t->t_weasu, | ||
| 895 | gpmc_t->clk_activation + dev_t->t_rdyo); | ||
| 896 | /* XXX: shouldn't mux be kept as a whole for wr_data_mux_bus ?, | ||
| 897 | * and in that case remember to handle we_on properly | ||
| 898 | */ | ||
| 899 | if (mux) { | ||
| 900 | temp = max_t(u32, temp, | ||
| 901 | gpmc_t->adv_wr_off + dev_t->t_aavdh); | ||
| 902 | temp = max_t(u32, temp, gpmc_t->adv_wr_off + | ||
| 903 | gpmc_ticks_to_ps(dev_t->cyc_aavdh_we)); | ||
| 904 | } | ||
| 905 | gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp); | ||
| 906 | |||
| 907 | /* we_on */ | ||
| 908 | if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) | ||
| 909 | gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu); | ||
| 910 | else | ||
| 911 | gpmc_t->we_on = gpmc_t->wr_data_mux_bus; | ||
| 912 | |||
| 913 | /* wr_access */ | ||
| 914 | /* XXX: gpmc_capability check reqd ? , even if not, will not harm */ | ||
| 915 | gpmc_t->wr_access = gpmc_t->access; | ||
| 916 | |||
| 917 | /* we_off */ | ||
| 918 | temp = gpmc_t->we_on + dev_t->t_wpl; | ||
| 919 | temp = max_t(u32, temp, | ||
| 920 | gpmc_t->wr_access + gpmc_ticks_to_ps(1)); | ||
| 921 | temp = max_t(u32, temp, | ||
| 922 | gpmc_t->we_on + gpmc_ticks_to_ps(dev_t->cyc_wpl)); | ||
| 923 | gpmc_t->we_off = gpmc_round_ps_to_ticks(temp); | ||
| 924 | |||
| 925 | gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off + | ||
| 926 | dev_t->t_wph); | ||
| 927 | |||
| 928 | /* wr_cycle */ | ||
| 929 | temp = gpmc_round_ps_to_sync_clk(dev_t->t_cez_w, gpmc_t->sync_clk); | ||
| 930 | temp += gpmc_t->wr_access; | ||
| 931 | /* XXX: barter t_ce_rdyz with t_cez_w ? */ | ||
| 932 | if (dev_t->t_ce_rdyz) | ||
| 933 | temp = max_t(u32, temp, | ||
| 934 | gpmc_t->cs_wr_off + dev_t->t_ce_rdyz); | ||
| 935 | gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp); | ||
| 936 | |||
| 937 | return 0; | ||
| 938 | } | ||
| 939 | |||
| 940 | static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t, | ||
| 941 | struct gpmc_device_timings *dev_t) | ||
| 942 | { | ||
| 943 | bool mux = dev_t->mux; | ||
| 944 | u32 temp; | ||
| 945 | |||
| 946 | /* adv_rd_off */ | ||
| 947 | temp = dev_t->t_avdp_r; | ||
| 948 | if (mux) | ||
| 949 | temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp); | ||
| 950 | gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp); | ||
| 951 | |||
| 952 | /* oe_on */ | ||
| 953 | temp = dev_t->t_oeasu; | ||
| 954 | if (mux) | ||
| 955 | temp = max_t(u32, temp, | ||
| 956 | gpmc_t->adv_rd_off + dev_t->t_aavdh); | ||
| 957 | gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp); | ||
| 958 | |||
| 959 | /* access */ | ||
| 960 | temp = max_t(u32, dev_t->t_iaa, /* XXX: remove t_iaa in async ? */ | ||
| 961 | gpmc_t->oe_on + dev_t->t_oe); | ||
| 962 | temp = max_t(u32, temp, | ||
| 963 | gpmc_t->cs_on + dev_t->t_ce); | ||
| 964 | temp = max_t(u32, temp, | ||
| 965 | gpmc_t->adv_on + dev_t->t_aa); | ||
| 966 | gpmc_t->access = gpmc_round_ps_to_ticks(temp); | ||
| 967 | |||
| 968 | gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1); | ||
| 969 | gpmc_t->cs_rd_off = gpmc_t->oe_off; | ||
| 970 | |||
| 971 | /* rd_cycle */ | ||
| 972 | temp = max_t(u32, dev_t->t_rd_cycle, | ||
| 973 | gpmc_t->cs_rd_off + dev_t->t_cez_r); | ||
| 974 | temp = max_t(u32, temp, gpmc_t->oe_off + dev_t->t_oez); | ||
| 975 | gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp); | ||
| 976 | |||
| 977 | return 0; | ||
| 978 | } | ||
| 979 | |||
| 980 | static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t, | ||
| 981 | struct gpmc_device_timings *dev_t) | ||
| 982 | { | ||
| 983 | bool mux = dev_t->mux; | ||
| 984 | u32 temp; | ||
| 985 | |||
| 986 | /* adv_wr_off */ | ||
| 987 | temp = dev_t->t_avdp_w; | ||
| 988 | if (mux) | ||
| 989 | temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp); | ||
| 990 | gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp); | ||
| 991 | |||
| 992 | /* wr_data_mux_bus */ | ||
| 993 | temp = dev_t->t_weasu; | ||
| 994 | if (mux) { | ||
| 995 | temp = max_t(u32, temp, gpmc_t->adv_wr_off + dev_t->t_aavdh); | ||
| 996 | temp = max_t(u32, temp, gpmc_t->adv_wr_off + | ||
| 997 | gpmc_ticks_to_ps(dev_t->cyc_aavdh_we)); | ||
| 998 | } | ||
| 999 | gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp); | ||
| 1000 | |||
| 1001 | /* we_on */ | ||
| 1002 | if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) | ||
| 1003 | gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu); | ||
| 1004 | else | ||
| 1005 | gpmc_t->we_on = gpmc_t->wr_data_mux_bus; | ||
| 1006 | |||
| 1007 | /* we_off */ | ||
| 1008 | temp = gpmc_t->we_on + dev_t->t_wpl; | ||
| 1009 | gpmc_t->we_off = gpmc_round_ps_to_ticks(temp); | ||
| 1010 | |||
| 1011 | gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off + | ||
| 1012 | dev_t->t_wph); | ||
| 1013 | |||
| 1014 | /* wr_cycle */ | ||
| 1015 | temp = max_t(u32, dev_t->t_wr_cycle, | ||
| 1016 | gpmc_t->cs_wr_off + dev_t->t_cez_w); | ||
| 1017 | gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp); | ||
| 1018 | |||
| 1019 | return 0; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t, | ||
| 1023 | struct gpmc_device_timings *dev_t) | ||
| 1024 | { | ||
| 1025 | u32 temp; | ||
| 1026 | |||
| 1027 | gpmc_t->sync_clk = gpmc_calc_divider(dev_t->clk) * | ||
| 1028 | gpmc_get_fclk_period(); | ||
| 1029 | |||
| 1030 | gpmc_t->page_burst_access = gpmc_round_ps_to_sync_clk( | ||
| 1031 | dev_t->t_bacc, | ||
| 1032 | gpmc_t->sync_clk); | ||
| 1033 | |||
| 1034 | temp = max_t(u32, dev_t->t_ces, dev_t->t_avds); | ||
| 1035 | gpmc_t->clk_activation = gpmc_round_ps_to_ticks(temp); | ||
| 1036 | |||
| 1037 | if (gpmc_calc_divider(gpmc_t->sync_clk) != 1) | ||
| 1038 | return 0; | ||
| 1039 | |||
| 1040 | if (dev_t->ce_xdelay) | ||
| 1041 | gpmc_t->bool_timings.cs_extra_delay = true; | ||
| 1042 | if (dev_t->avd_xdelay) | ||
| 1043 | gpmc_t->bool_timings.adv_extra_delay = true; | ||
| 1044 | if (dev_t->oe_xdelay) | ||
| 1045 | gpmc_t->bool_timings.oe_extra_delay = true; | ||
| 1046 | if (dev_t->we_xdelay) | ||
| 1047 | gpmc_t->bool_timings.we_extra_delay = true; | ||
| 1048 | |||
| 1049 | return 0; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t, | ||
| 1053 | struct gpmc_device_timings *dev_t) | ||
| 1054 | { | ||
| 1055 | u32 temp; | ||
| 1056 | |||
| 1057 | /* cs_on */ | ||
| 1058 | gpmc_t->cs_on = gpmc_round_ps_to_ticks(dev_t->t_ceasu); | ||
| 1059 | |||
| 1060 | /* adv_on */ | ||
| 1061 | temp = dev_t->t_avdasu; | ||
| 1062 | if (dev_t->t_ce_avd) | ||
| 1063 | temp = max_t(u32, temp, | ||
| 1064 | gpmc_t->cs_on + dev_t->t_ce_avd); | ||
| 1065 | gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp); | ||
| 1066 | |||
| 1067 | if (dev_t->sync_write || dev_t->sync_read) | ||
| 1068 | gpmc_calc_sync_common_timings(gpmc_t, dev_t); | ||
| 1069 | |||
| 1070 | return 0; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | /* TODO: remove this function once all peripherals are confirmed to | ||
| 1074 | * work with generic timing. Simultaneously gpmc_cs_set_timings() | ||
| 1075 | * has to be modified to handle timings in ps instead of ns | ||
| 1076 | */ | ||
| 1077 | static void gpmc_convert_ps_to_ns(struct gpmc_timings *t) | ||
| 1078 | { | ||
| 1079 | t->cs_on /= 1000; | ||
| 1080 | t->cs_rd_off /= 1000; | ||
| 1081 | t->cs_wr_off /= 1000; | ||
| 1082 | t->adv_on /= 1000; | ||
| 1083 | t->adv_rd_off /= 1000; | ||
| 1084 | t->adv_wr_off /= 1000; | ||
| 1085 | t->we_on /= 1000; | ||
| 1086 | t->we_off /= 1000; | ||
| 1087 | t->oe_on /= 1000; | ||
| 1088 | t->oe_off /= 1000; | ||
| 1089 | t->page_burst_access /= 1000; | ||
| 1090 | t->access /= 1000; | ||
| 1091 | t->rd_cycle /= 1000; | ||
| 1092 | t->wr_cycle /= 1000; | ||
| 1093 | t->bus_turnaround /= 1000; | ||
| 1094 | t->cycle2cycle_delay /= 1000; | ||
| 1095 | t->wait_monitoring /= 1000; | ||
| 1096 | t->clk_activation /= 1000; | ||
| 1097 | t->wr_access /= 1000; | ||
| 1098 | t->wr_data_mux_bus /= 1000; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | int gpmc_calc_timings(struct gpmc_timings *gpmc_t, | ||
| 1102 | struct gpmc_device_timings *dev_t) | ||
| 1103 | { | ||
| 1104 | memset(gpmc_t, 0, sizeof(*gpmc_t)); | ||
| 1105 | |||
| 1106 | gpmc_calc_common_timings(gpmc_t, dev_t); | ||
| 1107 | |||
| 1108 | if (dev_t->sync_read) | ||
| 1109 | gpmc_calc_sync_read_timings(gpmc_t, dev_t); | ||
| 1110 | else | ||
| 1111 | gpmc_calc_async_read_timings(gpmc_t, dev_t); | ||
| 1112 | |||
| 1113 | if (dev_t->sync_write) | ||
| 1114 | gpmc_calc_sync_write_timings(gpmc_t, dev_t); | ||
| 1115 | else | ||
| 1116 | gpmc_calc_async_write_timings(gpmc_t, dev_t); | ||
| 1117 | |||
| 1118 | /* TODO: remove, see function definition */ | ||
| 1119 | gpmc_convert_ps_to_ns(gpmc_t); | ||
| 1120 | |||
| 1121 | return 0; | ||
| 1122 | } | ||
| 1123 | |||
| 751 | static __devinit int gpmc_probe(struct platform_device *pdev) | 1124 | static __devinit int gpmc_probe(struct platform_device *pdev) |
| 752 | { | 1125 | { |
| 753 | int rc; | 1126 | int rc; |
diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h index 79f4dfc2adb3..fe0a844d5007 100644 --- a/arch/arm/mach-omap2/gpmc.h +++ b/arch/arm/mach-omap2/gpmc.h | |||
| @@ -74,6 +74,17 @@ | |||
| 74 | #define GPMC_IRQ_COUNT_EVENT 0x02 | 74 | #define GPMC_IRQ_COUNT_EVENT 0x02 |
| 75 | 75 | ||
| 76 | 76 | ||
| 77 | /* bool type time settings */ | ||
| 78 | struct gpmc_bool_timings { | ||
| 79 | bool cycle2cyclediffcsen; | ||
| 80 | bool cycle2cyclesamecsen; | ||
| 81 | bool we_extra_delay; | ||
| 82 | bool oe_extra_delay; | ||
| 83 | bool adv_extra_delay; | ||
| 84 | bool cs_extra_delay; | ||
| 85 | bool time_para_granularity; | ||
| 86 | }; | ||
| 87 | |||
| 77 | /* | 88 | /* |
| 78 | * Note that all values in this struct are in nanoseconds except sync_clk | 89 | * Note that all values in this struct are in nanoseconds except sync_clk |
| 79 | * (which is in picoseconds), while the register values are in gpmc_fck cycles. | 90 | * (which is in picoseconds), while the register values are in gpmc_fck cycles. |
| @@ -83,34 +94,104 @@ struct gpmc_timings { | |||
| 83 | u32 sync_clk; | 94 | u32 sync_clk; |
| 84 | 95 | ||
| 85 | /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ | 96 | /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ |
| 86 | u16 cs_on; /* Assertion time */ | 97 | u32 cs_on; /* Assertion time */ |
| 87 | u16 cs_rd_off; /* Read deassertion time */ | 98 | u32 cs_rd_off; /* Read deassertion time */ |
| 88 | u16 cs_wr_off; /* Write deassertion time */ | 99 | u32 cs_wr_off; /* Write deassertion time */ |
| 89 | 100 | ||
| 90 | /* ADV signal timings corresponding to GPMC_CONFIG3 */ | 101 | /* ADV signal timings corresponding to GPMC_CONFIG3 */ |
| 91 | u16 adv_on; /* Assertion time */ | 102 | u32 adv_on; /* Assertion time */ |
| 92 | u16 adv_rd_off; /* Read deassertion time */ | 103 | u32 adv_rd_off; /* Read deassertion time */ |
| 93 | u16 adv_wr_off; /* Write deassertion time */ | 104 | u32 adv_wr_off; /* Write deassertion time */ |
| 94 | 105 | ||
| 95 | /* WE signals timings corresponding to GPMC_CONFIG4 */ | 106 | /* WE signals timings corresponding to GPMC_CONFIG4 */ |
| 96 | u16 we_on; /* WE assertion time */ | 107 | u32 we_on; /* WE assertion time */ |
| 97 | u16 we_off; /* WE deassertion time */ | 108 | u32 we_off; /* WE deassertion time */ |
| 98 | 109 | ||
| 99 | /* OE signals timings corresponding to GPMC_CONFIG4 */ | 110 | /* OE signals timings corresponding to GPMC_CONFIG4 */ |
| 100 | u16 oe_on; /* OE assertion time */ | 111 | u32 oe_on; /* OE assertion time */ |
| 101 | u16 oe_off; /* OE deassertion time */ | 112 | u32 oe_off; /* OE deassertion time */ |
| 102 | 113 | ||
| 103 | /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ | 114 | /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ |
| 104 | u16 page_burst_access; /* Multiple access word delay */ | 115 | u32 page_burst_access; /* Multiple access word delay */ |
| 105 | u16 access; /* Start-cycle to first data valid delay */ | 116 | u32 access; /* Start-cycle to first data valid delay */ |
| 106 | u16 rd_cycle; /* Total read cycle time */ | 117 | u32 rd_cycle; /* Total read cycle time */ |
| 107 | u16 wr_cycle; /* Total write cycle time */ | 118 | u32 wr_cycle; /* Total write cycle time */ |
| 119 | |||
| 120 | u32 bus_turnaround; | ||
| 121 | u32 cycle2cycle_delay; | ||
| 122 | |||
| 123 | u32 wait_monitoring; | ||
| 124 | u32 clk_activation; | ||
| 108 | 125 | ||
| 109 | /* The following are only on OMAP3430 */ | 126 | /* The following are only on OMAP3430 */ |
| 110 | u16 wr_access; /* WRACCESSTIME */ | 127 | u32 wr_access; /* WRACCESSTIME */ |
| 111 | u16 wr_data_mux_bus; /* WRDATAONADMUXBUS */ | 128 | u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ |
| 129 | |||
| 130 | struct gpmc_bool_timings bool_timings; | ||
| 131 | }; | ||
| 132 | |||
| 133 | /* Device timings in picoseconds */ | ||
| 134 | struct gpmc_device_timings { | ||
| 135 | u32 t_ceasu; /* address setup to CS valid */ | ||
| 136 | u32 t_avdasu; /* address setup to ADV valid */ | ||
| 137 | /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is | ||
| 138 | * of tusb using these timings even for sync whilst | ||
| 139 | * ideally for adv_rd/(wr)_off it should have considered | ||
| 140 | * t_avdh instead. This indirectly necessitates r/w | ||
| 141 | * variations of t_avdp as it is possible to have one | ||
| 142 | * sync & other async | ||
| 143 | */ | ||
| 144 | u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ | ||
| 145 | u32 t_avdp_w; | ||
| 146 | u32 t_aavdh; /* address hold time */ | ||
| 147 | u32 t_oeasu; /* address setup to OE valid */ | ||
| 148 | u32 t_aa; /* access time from ADV assertion */ | ||
| 149 | u32 t_iaa; /* initial access time */ | ||
| 150 | u32 t_oe; /* access time from OE assertion */ | ||
| 151 | u32 t_ce; /* access time from CS asertion */ | ||
| 152 | u32 t_rd_cycle; /* read cycle time */ | ||
| 153 | u32 t_cez_r; /* read CS deassertion to high Z */ | ||
| 154 | u32 t_cez_w; /* write CS deassertion to high Z */ | ||
| 155 | u32 t_oez; /* OE deassertion to high Z */ | ||
| 156 | u32 t_weasu; /* address setup to WE valid */ | ||
| 157 | u32 t_wpl; /* write assertion time */ | ||
| 158 | u32 t_wph; /* write deassertion time */ | ||
| 159 | u32 t_wr_cycle; /* write cycle time */ | ||
| 160 | |||
| 161 | u32 clk; | ||
| 162 | u32 t_bacc; /* burst access valid clock to output delay */ | ||
| 163 | u32 t_ces; /* CS setup time to clk */ | ||
| 164 | u32 t_avds; /* ADV setup time to clk */ | ||
| 165 | u32 t_avdh; /* ADV hold time from clk */ | ||
| 166 | u32 t_ach; /* address hold time from clk */ | ||
| 167 | u32 t_rdyo; /* clk to ready valid */ | ||
| 168 | |||
| 169 | u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ | ||
| 170 | u32 t_ce_avd; /* CS on to ADV on delay */ | ||
| 171 | |||
| 172 | /* XXX: check the possibility of combining | ||
| 173 | * cyc_aavhd_oe & cyc_aavdh_we | ||
| 174 | */ | ||
| 175 | u8 cyc_aavdh_oe;/* read address hold time in cycles */ | ||
| 176 | u8 cyc_aavdh_we;/* write address hold time in cycles */ | ||
| 177 | u8 cyc_oe; /* access time from OE assertion in cycles */ | ||
| 178 | u8 cyc_wpl; /* write deassertion time in cycles */ | ||
| 179 | u32 cyc_iaa; /* initial access time in cycles */ | ||
| 180 | |||
| 181 | bool mux; /* address & data muxed */ | ||
| 182 | bool sync_write;/* synchronous write */ | ||
| 183 | bool sync_read; /* synchronous read */ | ||
| 184 | |||
| 185 | /* extra delays */ | ||
| 186 | bool ce_xdelay; | ||
| 187 | bool avd_xdelay; | ||
| 188 | bool oe_xdelay; | ||
| 189 | bool we_xdelay; | ||
| 112 | }; | 190 | }; |
| 113 | 191 | ||
| 192 | extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, | ||
| 193 | struct gpmc_device_timings *dev_t); | ||
| 194 | |||
| 114 | extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); | 195 | extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); |
| 115 | extern int gpmc_get_client_irq(unsigned irq_config); | 196 | extern int gpmc_get_client_irq(unsigned irq_config); |
| 116 | 197 | ||
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index a8795ff19e6d..c5a3c6f9504e 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c | |||
| @@ -27,180 +27,88 @@ static u8 async_cs, sync_cs; | |||
| 27 | static unsigned refclk_psec; | 27 | static unsigned refclk_psec; |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | /* t2_ps, when quantized to fclk units, must happen no earlier than | ||
| 31 | * the clock after after t1_NS. | ||
| 32 | * | ||
| 33 | * Return a possibly updated value of t2_ps, converted to nsec. | ||
| 34 | */ | ||
| 35 | static unsigned | ||
| 36 | next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps) | ||
| 37 | { | ||
| 38 | unsigned t1_ps = t1_NS * 1000; | ||
| 39 | unsigned t1_f, t2_f; | ||
| 40 | |||
| 41 | if ((t1_ps + fclk_ps) < t2_ps) | ||
| 42 | return t2_ps / 1000; | ||
| 43 | |||
| 44 | t1_f = (t1_ps + fclk_ps - 1) / fclk_ps; | ||
| 45 | t2_f = (t2_ps + fclk_ps - 1) / fclk_ps; | ||
| 46 | |||
| 47 | if (t1_f >= t2_f) | ||
| 48 | t2_f = t1_f + 1; | ||
| 49 | |||
| 50 | return (t2_f * fclk_ps) / 1000; | ||
| 51 | } | ||
| 52 | |||
| 53 | /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ | 30 | /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ |
| 54 | 31 | ||
| 55 | static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps) | 32 | static int tusb_set_async_mode(unsigned sysclk_ps) |
| 56 | { | 33 | { |
| 34 | struct gpmc_device_timings dev_t; | ||
| 57 | struct gpmc_timings t; | 35 | struct gpmc_timings t; |
| 58 | unsigned t_acsnh_advnh = sysclk_ps + 3000; | 36 | unsigned t_acsnh_advnh = sysclk_ps + 3000; |
| 59 | unsigned tmp; | ||
| 60 | |||
| 61 | memset(&t, 0, sizeof(t)); | ||
| 62 | |||
| 63 | /* CS_ON = t_acsnh_acsnl */ | ||
| 64 | t.cs_on = 8; | ||
| 65 | /* ADV_ON = t_acsnh_advnh - t_advn */ | ||
| 66 | t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * READ ... from omap2420 TRM fig 12-13 | ||
| 70 | */ | ||
| 71 | |||
| 72 | /* ADV_RD_OFF = t_acsnh_advnh */ | ||
| 73 | t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps); | ||
| 74 | |||
| 75 | /* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */ | ||
| 76 | t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps); | ||
| 77 | |||
| 78 | /* ACCESS = counters continue only after nRDY */ | ||
| 79 | tmp = t.oe_on * 1000 + 300; | ||
| 80 | t.access = next_clk(t.oe_on, tmp, fclk_ps); | ||
| 81 | |||
| 82 | /* OE_OFF = after data gets sampled */ | ||
| 83 | tmp = t.access * 1000; | ||
| 84 | t.oe_off = next_clk(t.access, tmp, fclk_ps); | ||
| 85 | |||
| 86 | t.cs_rd_off = t.oe_off; | ||
| 87 | |||
| 88 | tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */; | ||
| 89 | t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps); | ||
| 90 | |||
| 91 | /* | ||
| 92 | * WRITE ... from omap2420 TRM fig 12-15 | ||
| 93 | */ | ||
| 94 | |||
| 95 | /* ADV_WR_OFF = t_acsnh_advnh */ | ||
| 96 | t.adv_wr_off = t.adv_rd_off; | ||
| 97 | 37 | ||
| 98 | /* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */ | 38 | memset(&dev_t, 0, sizeof(dev_t)); |
| 99 | t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps); | ||
| 100 | 39 | ||
| 101 | /* WE_OFF = after data gets sampled */ | 40 | dev_t.mux = true; |
| 102 | tmp = t.we_on * 1000 + 300; | ||
| 103 | t.we_off = next_clk(t.we_on, tmp, fclk_ps); | ||
| 104 | 41 | ||
| 105 | t.cs_wr_off = t.we_off; | 42 | dev_t.t_ceasu = 8 * 1000; |
| 43 | dev_t.t_avdasu = t_acsnh_advnh - 7000; | ||
| 44 | dev_t.t_ce_avd = 1000; | ||
| 45 | dev_t.t_avdp_r = t_acsnh_advnh; | ||
| 46 | dev_t.t_oeasu = t_acsnh_advnh + 1000; | ||
| 47 | dev_t.t_oe = 300; | ||
| 48 | dev_t.t_cez_r = 7000; | ||
| 49 | dev_t.t_cez_w = dev_t.t_cez_r; | ||
| 50 | dev_t.t_avdp_w = t_acsnh_advnh; | ||
| 51 | dev_t.t_weasu = t_acsnh_advnh + 1000; | ||
| 52 | dev_t.t_wpl = 300; | ||
| 53 | dev_t.cyc_aavdh_we = 1; | ||
| 106 | 54 | ||
| 107 | tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */; | 55 | gpmc_calc_timings(&t, &dev_t); |
| 108 | t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); | ||
| 109 | 56 | ||
| 110 | return gpmc_cs_set_timings(async_cs, &t); | 57 | return gpmc_cs_set_timings(async_cs, &t); |
| 111 | } | 58 | } |
| 112 | 59 | ||
| 113 | static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) | 60 | static int tusb_set_sync_mode(unsigned sysclk_ps) |
| 114 | { | 61 | { |
| 62 | struct gpmc_device_timings dev_t; | ||
| 115 | struct gpmc_timings t; | 63 | struct gpmc_timings t; |
| 116 | unsigned t_scsnh_advnh = sysclk_ps + 3000; | 64 | unsigned t_scsnh_advnh = sysclk_ps + 3000; |
| 117 | unsigned tmp; | ||
| 118 | |||
| 119 | memset(&t, 0, sizeof(t)); | ||
| 120 | t.cs_on = 8; | ||
| 121 | |||
| 122 | /* ADV_ON = t_acsnh_advnh - t_advn */ | ||
| 123 | t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps); | ||
| 124 | |||
| 125 | /* GPMC_CLK rate = fclk rate / div */ | ||
| 126 | t.sync_clk = 11100 /* 11.1 nsec */; | ||
| 127 | tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps; | ||
| 128 | if (tmp > 4) | ||
| 129 | return -ERANGE; | ||
| 130 | if (tmp == 0) | ||
| 131 | tmp = 1; | ||
| 132 | t.page_burst_access = (fclk_ps * tmp) / 1000; | ||
| 133 | |||
| 134 | /* | ||
| 135 | * READ ... based on omap2420 TRM fig 12-19, 12-20 | ||
| 136 | */ | ||
| 137 | |||
| 138 | /* ADV_RD_OFF = t_scsnh_advnh */ | ||
| 139 | t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps); | ||
| 140 | |||
| 141 | /* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */ | ||
| 142 | tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps); | ||
| 143 | t.oe_on = next_clk(t.adv_on, tmp, fclk_ps); | ||
| 144 | |||
| 145 | /* ACCESS = number of clock cycles after t_adv_eon */ | ||
| 146 | tmp = (t.oe_on * 1000) + (5 * fclk_ps); | ||
| 147 | t.access = next_clk(t.oe_on, tmp, fclk_ps); | ||
| 148 | 65 | ||
| 149 | /* OE_OFF = after data gets sampled */ | 66 | memset(&dev_t, 0, sizeof(dev_t)); |
| 150 | tmp = (t.access * 1000) + (1 * fclk_ps); | 67 | |
| 151 | t.oe_off = next_clk(t.access, tmp, fclk_ps); | 68 | dev_t.mux = true; |
| 152 | 69 | dev_t.sync_read = true; | |
| 153 | t.cs_rd_off = t.oe_off; | 70 | dev_t.sync_write = true; |
| 154 | 71 | ||
| 155 | tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */; | 72 | dev_t.clk = 11100; |
| 156 | t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps); | 73 | dev_t.t_bacc = 1000; |
| 157 | 74 | dev_t.t_ces = 1000; | |
| 158 | /* | 75 | dev_t.t_ceasu = 8 * 1000; |
| 159 | * WRITE ... based on omap2420 TRM fig 12-21 | 76 | dev_t.t_avdasu = t_scsnh_advnh - 7000; |
| 160 | */ | 77 | dev_t.t_ce_avd = 1000; |
| 161 | 78 | dev_t.t_avdp_r = t_scsnh_advnh; | |
| 162 | /* ADV_WR_OFF = t_scsnh_advnh */ | 79 | dev_t.cyc_aavdh_oe = 3; |
| 163 | t.adv_wr_off = t.adv_rd_off; | 80 | dev_t.cyc_oe = 5; |
| 164 | 81 | dev_t.t_ce_rdyz = 7000; | |
| 165 | /* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */ | 82 | dev_t.t_avdp_w = t_scsnh_advnh; |
| 166 | tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps); | 83 | dev_t.cyc_aavdh_we = 3; |
| 167 | t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps); | 84 | dev_t.cyc_wpl = 6; |
| 168 | 85 | dev_t.t_ce_rdyz = 7000; | |
| 169 | /* WE_OFF = number of clock cycles after t_adv_wen */ | 86 | |
| 170 | tmp = (t.we_on * 1000) + (6 * fclk_ps); | 87 | gpmc_calc_timings(&t, &dev_t); |
| 171 | t.we_off = next_clk(t.we_on, tmp, fclk_ps); | ||
| 172 | |||
| 173 | t.cs_wr_off = t.we_off; | ||
| 174 | |||
| 175 | tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */; | ||
| 176 | t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); | ||
| 177 | 88 | ||
| 178 | return gpmc_cs_set_timings(sync_cs, &t); | 89 | return gpmc_cs_set_timings(sync_cs, &t); |
| 179 | } | 90 | } |
| 180 | 91 | ||
| 181 | extern unsigned long gpmc_get_fclk_period(void); | ||
| 182 | |||
| 183 | /* tusb driver calls this when it changes the chip's clocking */ | 92 | /* tusb driver calls this when it changes the chip's clocking */ |
| 184 | int tusb6010_platform_retime(unsigned is_refclk) | 93 | int tusb6010_platform_retime(unsigned is_refclk) |
| 185 | { | 94 | { |
| 186 | static const char error[] = | 95 | static const char error[] = |
| 187 | KERN_ERR "tusb6010 %s retime error %d\n"; | 96 | KERN_ERR "tusb6010 %s retime error %d\n"; |
| 188 | 97 | ||
| 189 | unsigned fclk_ps = gpmc_get_fclk_period(); | ||
| 190 | unsigned sysclk_ps; | 98 | unsigned sysclk_ps; |
| 191 | int status; | 99 | int status; |
| 192 | 100 | ||
| 193 | if (!refclk_psec || fclk_ps == 0) | 101 | if (!refclk_psec) |
| 194 | return -ENODEV; | 102 | return -ENODEV; |
| 195 | 103 | ||
| 196 | sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; | 104 | sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; |
| 197 | 105 | ||
| 198 | status = tusb_set_async_mode(sysclk_ps, fclk_ps); | 106 | status = tusb_set_async_mode(sysclk_ps); |
| 199 | if (status < 0) { | 107 | if (status < 0) { |
| 200 | printk(error, "async", status); | 108 | printk(error, "async", status); |
| 201 | goto done; | 109 | goto done; |
| 202 | } | 110 | } |
| 203 | status = tusb_set_sync_mode(sysclk_ps, fclk_ps); | 111 | status = tusb_set_sync_mode(sysclk_ps); |
| 204 | if (status < 0) | 112 | if (status < 0) |
| 205 | printk(error, "sync", status); | 113 | printk(error, "sync", status); |
| 206 | done: | 114 | done: |
| @@ -284,7 +192,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, | |||
| 284 | | GPMC_CONFIG1_READTYPE_SYNC | 192 | | GPMC_CONFIG1_READTYPE_SYNC |
| 285 | | GPMC_CONFIG1_WRITEMULTIPLE_SUPP | 193 | | GPMC_CONFIG1_WRITEMULTIPLE_SUPP |
| 286 | | GPMC_CONFIG1_WRITETYPE_SYNC | 194 | | GPMC_CONFIG1_WRITETYPE_SYNC |
| 287 | | GPMC_CONFIG1_CLKACTIVATIONTIME(1) | ||
| 288 | | GPMC_CONFIG1_PAGE_LEN(2) | 195 | | GPMC_CONFIG1_PAGE_LEN(2) |
| 289 | | GPMC_CONFIG1_WAIT_READ_MON | 196 | | GPMC_CONFIG1_WAIT_READ_MON |
| 290 | | GPMC_CONFIG1_WAIT_WRITE_MON | 197 | | GPMC_CONFIG1_WAIT_WRITE_MON |
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index c34d4efd0d5c..0a3f30df1eb8 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c | |||
| @@ -33,8 +33,6 @@ BIAS(in_nopull, PIN_INPUT_NOPULL); | |||
| 33 | BIAS(in_nopull_slpm_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE); | 33 | BIAS(in_nopull_slpm_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE); |
| 34 | BIAS(in_pu, PIN_INPUT_PULLUP); | 34 | BIAS(in_pu, PIN_INPUT_PULLUP); |
| 35 | BIAS(in_pd, PIN_INPUT_PULLDOWN); | 35 | BIAS(in_pd, PIN_INPUT_PULLDOWN); |
| 36 | BIAS(in_pd_slpm_in_pu, PIN_INPUT_PULLDOWN|PIN_SLPM_INPUT_PULLUP); | ||
| 37 | BIAS(in_pu_slpm_out_lo, PIN_INPUT_PULLUP|PIN_SLPM_OUTPUT_LOW); | ||
| 38 | BIAS(out_hi, PIN_OUTPUT_HIGH); | 36 | BIAS(out_hi, PIN_OUTPUT_HIGH); |
| 39 | BIAS(out_lo, PIN_OUTPUT_LOW); | 37 | BIAS(out_lo, PIN_OUTPUT_LOW); |
| 40 | BIAS(out_lo_slpm_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE); | 38 | BIAS(out_lo_slpm_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE); |
| @@ -46,14 +44,34 @@ BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SL | |||
| 46 | BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED); | 44 | BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED); |
| 47 | BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED); | 45 | BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED); |
| 48 | /* Sleep modes */ | 46 | /* Sleep modes */ |
| 49 | BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | 47 | BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED| |
| 50 | BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE); | 48 | PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE); |
| 51 | BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | 49 | BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED| |
| 52 | BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | 50 | PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); |
| 53 | BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | 51 | BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED| |
| 54 | BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE); | 52 | PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); |
| 55 | BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | 53 | BIAS(slpm_out_lo_pdis, PIN_SLEEPMODE_ENABLED| |
| 56 | BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | 54 | PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE|PIN_SLPM_PDIS_DISABLED); |
| 55 | BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED| | ||
| 56 | PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE); | ||
| 57 | BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED| | ||
| 58 | PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | ||
| 59 | BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH| | ||
| 60 | PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | ||
| 61 | BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED| | ||
| 62 | PIN_SLPM_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | ||
| 63 | BIAS(slpm_in_pu_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_PULLUP| | ||
| 64 | PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED); | ||
| 65 | BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED| | ||
| 66 | PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | ||
| 67 | BIAS(out_lo_wkup_pdis, PIN_SLPM_OUTPUT_LOW| | ||
| 68 | PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED); | ||
| 69 | BIAS(in_wkup_pdis_en, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE| | ||
| 70 | PIN_SLPM_PDIS_ENABLED); | ||
| 71 | BIAS(in_wkup_pdis, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE| | ||
| 72 | PIN_SLPM_PDIS_DISABLED); | ||
| 73 | BIAS(out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE| | ||
| 74 | PIN_SLPM_PDIS_DISABLED); | ||
| 57 | 75 | ||
| 58 | /* We use these to define hog settings that are always done on boot */ | 76 | /* We use these to define hog settings that are always done on boot */ |
| 59 | #define DB8500_MUX_HOG(group,func) \ | 77 | #define DB8500_MUX_HOG(group,func) \ |
| @@ -69,13 +87,16 @@ BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_NOPULL|PIN_S | |||
| 69 | PIN_MAP_MUX_GROUP_DEFAULT(dev, "pinctrl-db8500", group, func) | 87 | PIN_MAP_MUX_GROUP_DEFAULT(dev, "pinctrl-db8500", group, func) |
| 70 | #define DB8500_PIN(pin,conf,dev) \ | 88 | #define DB8500_PIN(pin,conf,dev) \ |
| 71 | PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf) | 89 | PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf) |
| 72 | #define DB8500_PIN_SLEEP(pin, conf, dev) \ | 90 | #define DB8500_PIN_IDLE(pin, conf, dev) \ |
| 73 | PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \ | 91 | PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_IDLE, "pinctrl-db8500", \ |
| 74 | pin, conf) | 92 | pin, conf) |
| 75 | 93 | #define DB8500_PIN_SLEEP(pin, conf, dev) \ | |
| 76 | #define DB8500_PIN_SLEEP(pin,conf,dev) \ | ||
| 77 | PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \ | 94 | PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \ |
| 78 | pin, conf) | 95 | pin, conf) |
| 96 | #define DB8500_MUX_STATE(group, func, dev, state) \ | ||
| 97 | PIN_MAP_MUX_GROUP(dev, state, "pinctrl-db8500", group, func) | ||
| 98 | #define DB8500_PIN_STATE(pin, conf, dev, state) \ | ||
| 99 | PIN_MAP_CONFIGS_PIN(dev, state, "pinctrl-db8500", pin, conf) | ||
| 79 | 100 | ||
| 80 | /* Pin control settings */ | 101 | /* Pin control settings */ |
| 81 | static struct pinctrl_map __initdata mop500_family_pinmap[] = { | 102 | static struct pinctrl_map __initdata mop500_family_pinmap[] = { |
| @@ -112,7 +133,7 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 112 | * UART0, we do not mux in u0 here. | 133 | * UART0, we do not mux in u0 here. |
| 113 | * uart-0 pins gpio configuration should be kept intact to prevent | 134 | * uart-0 pins gpio configuration should be kept intact to prevent |
| 114 | * a glitch in tx line when the tty dev is opened. Later these pins | 135 | * a glitch in tx line when the tty dev is opened. Later these pins |
| 115 | * are configured to uart mop500_pins_uart0 | 136 | * are configured by uart driver |
| 116 | */ | 137 | */ |
| 117 | DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */ | 138 | DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */ |
| 118 | DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */ | 139 | DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */ |
| @@ -123,12 +144,13 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 123 | * TODO: is this used on U8500 variants and Snowball really? | 144 | * TODO: is this used on U8500 variants and Snowball really? |
| 124 | * The setting on GPIO31 conflicts with magnetometer use on hrefv60 | 145 | * The setting on GPIO31 conflicts with magnetometer use on hrefv60 |
| 125 | */ | 146 | */ |
| 126 | DB8500_MUX_HOG("u2rxtx_c_1", "u2"), | 147 | /* default state for UART2 */ |
| 127 | DB8500_MUX_HOG("u2ctsrts_c_1", "u2"), | 148 | DB8500_MUX("u2rxtx_c_1", "u2", "uart2"), |
| 128 | DB8500_PIN_HOG("GPIO29_W2", in_pu), /* RXD */ | 149 | DB8500_PIN("GPIO29_W2", in_pu, "uart2"), /* RXD */ |
| 129 | DB8500_PIN_HOG("GPIO30_W3", out_hi), /* TXD */ | 150 | DB8500_PIN("GPIO30_W3", out_hi, "uart2"), /* TXD */ |
| 130 | DB8500_PIN_HOG("GPIO31_V3", in_pu), /* CTS */ | 151 | /* Sleep state for UART2 */ |
| 131 | DB8500_PIN_HOG("GPIO32_V2", out_hi), /* RTS */ | 152 | DB8500_PIN_SLEEP("GPIO29_W2", in_wkup_pdis, "uart2"), |
| 153 | DB8500_PIN_SLEEP("GPIO30_W3", out_wkup_pdis, "uart2"), | ||
| 132 | /* | 154 | /* |
| 133 | * The following pin sets were known as "runtime pins" before being | 155 | * The following pin sets were known as "runtime pins" before being |
| 134 | * converted to the pinctrl model. Here we model them as "default" | 156 | * converted to the pinctrl model. Here we model them as "default" |
| @@ -140,11 +162,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 140 | DB8500_PIN("GPIO1_AJ3", out_hi, "uart0"), /* RTS */ | 162 | DB8500_PIN("GPIO1_AJ3", out_hi, "uart0"), /* RTS */ |
| 141 | DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */ | 163 | DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */ |
| 142 | DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */ | 164 | DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */ |
| 143 | /* UART0 sleep state */ | 165 | /* Sleep state for UART0 */ |
| 144 | DB8500_PIN_SLEEP("GPIO0_AJ5", slpm_in_wkup_pdis, "uart0"), | 166 | DB8500_PIN_SLEEP("GPIO0_AJ5", slpm_in_wkup_pdis, "uart0"), |
| 145 | DB8500_PIN_SLEEP("GPIO1_AJ3", slpm_out_hi_wkup_pdis, "uart0"), | 167 | DB8500_PIN_SLEEP("GPIO1_AJ3", slpm_out_hi_wkup_pdis, "uart0"), |
| 146 | DB8500_PIN_SLEEP("GPIO2_AH4", slpm_in_wkup_pdis, "uart0"), | 168 | DB8500_PIN_SLEEP("GPIO2_AH4", slpm_in_wkup_pdis, "uart0"), |
| 147 | DB8500_PIN_SLEEP("GPIO3_AH3", slpm_out_wkup_pdis, "uart0"), | 169 | DB8500_PIN_SLEEP("GPIO3_AH3", slpm_out_wkup_pdis, "uart0"), |
| 170 | /* Mux in UART1 after initialization */ | ||
| 171 | DB8500_MUX("u1rxtx_a_1", "u1", "uart1"), | ||
| 172 | DB8500_PIN("GPIO4_AH6", in_pu, "uart1"), /* RXD */ | ||
| 173 | DB8500_PIN("GPIO5_AG6", out_hi, "uart1"), /* TXD */ | ||
| 174 | /* Sleep state for UART1 */ | ||
| 175 | DB8500_PIN_SLEEP("GPIO4_AH6", slpm_in_wkup_pdis, "uart1"), | ||
| 176 | DB8500_PIN_SLEEP("GPIO5_AG6", slpm_out_wkup_pdis, "uart1"), | ||
| 148 | /* MSP1 for ALSA codec */ | 177 | /* MSP1 for ALSA codec */ |
| 149 | DB8500_MUX("msp1txrx_a_1", "msp1", "ux500-msp-i2s.1"), | 178 | DB8500_MUX("msp1txrx_a_1", "msp1", "ux500-msp-i2s.1"), |
| 150 | DB8500_MUX("msp1_a_1", "msp1", "ux500-msp-i2s.1"), | 179 | DB8500_MUX("msp1_a_1", "msp1", "ux500-msp-i2s.1"), |
| @@ -161,7 +190,10 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 161 | DB8500_MUX("lcd_d8_d11_a_1", "lcd", "mcde-tvout"), | 190 | DB8500_MUX("lcd_d8_d11_a_1", "lcd", "mcde-tvout"), |
| 162 | DB8500_MUX("lcdaclk_b_1", "lcda", "mcde-tvout"), | 191 | DB8500_MUX("lcdaclk_b_1", "lcda", "mcde-tvout"), |
| 163 | /* Mux in LCD VSI1 and pull it up for MCDE HDMI output */ | 192 | /* Mux in LCD VSI1 and pull it up for MCDE HDMI output */ |
| 164 | DB8500_MUX("lcdvsi1_a_1", "lcd", "av8100-hdmi"), | 193 | DB8500_MUX("lcdvsi1_a_1", "lcd", "0-0070"), |
| 194 | DB8500_PIN("GPIO69_E2", in_pu, "0-0070"), | ||
| 195 | /* LCD VSI1 sleep state */ | ||
| 196 | DB8500_PIN_SLEEP("GPIO69_E2", slpm_in_wkup_pdis, "0-0070"), | ||
| 165 | /* Mux in i2c0 block, default state */ | 197 | /* Mux in i2c0 block, default state */ |
| 166 | DB8500_MUX("i2c0_a_1", "i2c0", "nmk-i2c.0"), | 198 | DB8500_MUX("i2c0_a_1", "i2c0", "nmk-i2c.0"), |
| 167 | /* i2c0 sleep state */ | 199 | /* i2c0 sleep state */ |
| @@ -194,6 +226,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 194 | DB8500_PIN("GPIO26_Y2", in_pu, "sdi0"), /* DAT1 */ | 226 | DB8500_PIN("GPIO26_Y2", in_pu, "sdi0"), /* DAT1 */ |
| 195 | DB8500_PIN("GPIO27_AA2", in_pu, "sdi0"), /* DAT2 */ | 227 | DB8500_PIN("GPIO27_AA2", in_pu, "sdi0"), /* DAT2 */ |
| 196 | DB8500_PIN("GPIO28_AA1", in_pu, "sdi0"), /* DAT3 */ | 228 | DB8500_PIN("GPIO28_AA1", in_pu, "sdi0"), /* DAT3 */ |
| 229 | /* SDI0 sleep state */ | ||
| 230 | DB8500_PIN_SLEEP("GPIO18_AC2", slpm_out_hi_wkup_pdis, "sdi0"), | ||
| 231 | DB8500_PIN_SLEEP("GPIO19_AC1", slpm_out_hi_wkup_pdis, "sdi0"), | ||
| 232 | DB8500_PIN_SLEEP("GPIO20_AB4", slpm_out_hi_wkup_pdis, "sdi0"), | ||
| 233 | DB8500_PIN_SLEEP("GPIO22_AA3", slpm_in_wkup_pdis, "sdi0"), | ||
| 234 | DB8500_PIN_SLEEP("GPIO23_AA4", slpm_out_lo_wkup_pdis, "sdi0"), | ||
| 235 | DB8500_PIN_SLEEP("GPIO24_AB2", slpm_in_wkup_pdis, "sdi0"), | ||
| 236 | DB8500_PIN_SLEEP("GPIO25_Y4", slpm_in_wkup_pdis, "sdi0"), | ||
| 237 | DB8500_PIN_SLEEP("GPIO26_Y2", slpm_in_wkup_pdis, "sdi0"), | ||
| 238 | DB8500_PIN_SLEEP("GPIO27_AA2", slpm_in_wkup_pdis, "sdi0"), | ||
| 239 | DB8500_PIN_SLEEP("GPIO28_AA1", slpm_in_wkup_pdis, "sdi0"), | ||
| 240 | |||
| 197 | /* Mux in SDI1 (here called MC1) used for SDIO for CW1200 WLAN */ | 241 | /* Mux in SDI1 (here called MC1) used for SDIO for CW1200 WLAN */ |
| 198 | DB8500_MUX("mc1_a_1", "mc1", "sdi1"), | 242 | DB8500_MUX("mc1_a_1", "mc1", "sdi1"), |
| 199 | DB8500_PIN("GPIO208_AH16", out_lo, "sdi1"), /* CLK */ | 243 | DB8500_PIN("GPIO208_AH16", out_lo, "sdi1"), /* CLK */ |
| @@ -203,6 +247,15 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 203 | DB8500_PIN("GPIO212_AF13", in_pu, "sdi1"), /* DAT1 */ | 247 | DB8500_PIN("GPIO212_AF13", in_pu, "sdi1"), /* DAT1 */ |
| 204 | DB8500_PIN("GPIO213_AG13", in_pu, "sdi1"), /* DAT2 */ | 248 | DB8500_PIN("GPIO213_AG13", in_pu, "sdi1"), /* DAT2 */ |
| 205 | DB8500_PIN("GPIO214_AH15", in_pu, "sdi1"), /* DAT3 */ | 249 | DB8500_PIN("GPIO214_AH15", in_pu, "sdi1"), /* DAT3 */ |
| 250 | /* SDI1 sleep state */ | ||
| 251 | DB8500_PIN_SLEEP("GPIO208_AH16", slpm_out_lo_wkup_pdis, "sdi1"), /* CLK */ | ||
| 252 | DB8500_PIN_SLEEP("GPIO209_AG15", slpm_in_wkup_pdis, "sdi1"), /* FBCLK */ | ||
| 253 | DB8500_PIN_SLEEP("GPIO210_AJ15", slpm_in_wkup_pdis, "sdi1"), /* CMD */ | ||
| 254 | DB8500_PIN_SLEEP("GPIO211_AG14", slpm_in_wkup_pdis, "sdi1"), /* DAT0 */ | ||
| 255 | DB8500_PIN_SLEEP("GPIO212_AF13", slpm_in_wkup_pdis, "sdi1"), /* DAT1 */ | ||
| 256 | DB8500_PIN_SLEEP("GPIO213_AG13", slpm_in_wkup_pdis, "sdi1"), /* DAT2 */ | ||
| 257 | DB8500_PIN_SLEEP("GPIO214_AH15", slpm_in_wkup_pdis, "sdi1"), /* DAT3 */ | ||
| 258 | |||
| 206 | /* Mux in SDI2 (here called MC2) used for for PoP eMMC */ | 259 | /* Mux in SDI2 (here called MC2) used for for PoP eMMC */ |
| 207 | DB8500_MUX("mc2_a_1", "mc2", "sdi2"), | 260 | DB8500_MUX("mc2_a_1", "mc2", "sdi2"), |
| 208 | DB8500_PIN("GPIO128_A5", out_lo, "sdi2"), /* CLK */ | 261 | DB8500_PIN("GPIO128_A5", out_lo, "sdi2"), /* CLK */ |
| @@ -216,6 +269,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 216 | DB8500_PIN("GPIO136_C7", in_pu, "sdi2"), /* DAT5 */ | 269 | DB8500_PIN("GPIO136_C7", in_pu, "sdi2"), /* DAT5 */ |
| 217 | DB8500_PIN("GPIO137_A7", in_pu, "sdi2"), /* DAT6 */ | 270 | DB8500_PIN("GPIO137_A7", in_pu, "sdi2"), /* DAT6 */ |
| 218 | DB8500_PIN("GPIO138_C5", in_pu, "sdi2"), /* DAT7 */ | 271 | DB8500_PIN("GPIO138_C5", in_pu, "sdi2"), /* DAT7 */ |
| 272 | /* SDI2 sleep state */ | ||
| 273 | DB8500_PIN_SLEEP("GPIO128_A5", out_lo_wkup_pdis, "sdi2"), /* CLK */ | ||
| 274 | DB8500_PIN_SLEEP("GPIO129_B4", in_wkup_pdis_en, "sdi2"), /* CMD */ | ||
| 275 | DB8500_PIN_SLEEP("GPIO130_C8", in_wkup_pdis_en, "sdi2"), /* FBCLK */ | ||
| 276 | DB8500_PIN_SLEEP("GPIO131_A12", in_wkup_pdis, "sdi2"), /* DAT0 */ | ||
| 277 | DB8500_PIN_SLEEP("GPIO132_C10", in_wkup_pdis, "sdi2"), /* DAT1 */ | ||
| 278 | DB8500_PIN_SLEEP("GPIO133_B10", in_wkup_pdis, "sdi2"), /* DAT2 */ | ||
| 279 | DB8500_PIN_SLEEP("GPIO134_B9", in_wkup_pdis, "sdi2"), /* DAT3 */ | ||
| 280 | DB8500_PIN_SLEEP("GPIO135_A9", in_wkup_pdis, "sdi2"), /* DAT4 */ | ||
| 281 | DB8500_PIN_SLEEP("GPIO136_C7", in_wkup_pdis, "sdi2"), /* DAT5 */ | ||
| 282 | DB8500_PIN_SLEEP("GPIO137_A7", in_wkup_pdis, "sdi2"), /* DAT6 */ | ||
| 283 | DB8500_PIN_SLEEP("GPIO138_C5", in_wkup_pdis, "sdi2"), /* DAT7 */ | ||
| 284 | |||
| 219 | /* Mux in SDI4 (here called MC4) used for for PCB-mounted eMMC */ | 285 | /* Mux in SDI4 (here called MC4) used for for PCB-mounted eMMC */ |
| 220 | DB8500_MUX("mc4_a_1", "mc4", "sdi4"), | 286 | DB8500_MUX("mc4_a_1", "mc4", "sdi4"), |
| 221 | DB8500_PIN("GPIO197_AH24", in_pu, "sdi4"), /* DAT3 */ | 287 | DB8500_PIN("GPIO197_AH24", in_pu, "sdi4"), /* DAT3 */ |
| @@ -229,6 +295,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 229 | DB8500_PIN("GPIO205_AG23", in_pu, "sdi4"), /* DAT6 */ | 295 | DB8500_PIN("GPIO205_AG23", in_pu, "sdi4"), /* DAT6 */ |
| 230 | DB8500_PIN("GPIO206_AG24", in_pu, "sdi4"), /* DAT5 */ | 296 | DB8500_PIN("GPIO206_AG24", in_pu, "sdi4"), /* DAT5 */ |
| 231 | DB8500_PIN("GPIO207_AJ23", in_pu, "sdi4"), /* DAT4 */ | 297 | DB8500_PIN("GPIO207_AJ23", in_pu, "sdi4"), /* DAT4 */ |
| 298 | /*SDI4 sleep state */ | ||
| 299 | DB8500_PIN_SLEEP("GPIO197_AH24", slpm_in_wkup_pdis, "sdi4"), /* DAT3 */ | ||
| 300 | DB8500_PIN_SLEEP("GPIO198_AG25", slpm_in_wkup_pdis, "sdi4"), /* DAT2 */ | ||
| 301 | DB8500_PIN_SLEEP("GPIO199_AH23", slpm_in_wkup_pdis, "sdi4"), /* DAT1 */ | ||
| 302 | DB8500_PIN_SLEEP("GPIO200_AH26", slpm_in_wkup_pdis, "sdi4"), /* DAT0 */ | ||
| 303 | DB8500_PIN_SLEEP("GPIO201_AF24", slpm_in_wkup_pdis, "sdi4"), /* CMD */ | ||
| 304 | DB8500_PIN_SLEEP("GPIO202_AF25", slpm_in_wkup_pdis, "sdi4"), /* FBCLK */ | ||
| 305 | DB8500_PIN_SLEEP("GPIO203_AE23", slpm_out_lo_wkup_pdis, "sdi4"), /* CLK */ | ||
| 306 | DB8500_PIN_SLEEP("GPIO204_AF23", slpm_in_wkup_pdis, "sdi4"), /* DAT7 */ | ||
| 307 | DB8500_PIN_SLEEP("GPIO205_AG23", slpm_in_wkup_pdis, "sdi4"), /* DAT6 */ | ||
| 308 | DB8500_PIN_SLEEP("GPIO206_AG24", slpm_in_wkup_pdis, "sdi4"), /* DAT5 */ | ||
| 309 | DB8500_PIN_SLEEP("GPIO207_AJ23", slpm_in_wkup_pdis, "sdi4"), /* DAT4 */ | ||
| 310 | |||
| 232 | /* Mux in USB pins, drive STP high */ | 311 | /* Mux in USB pins, drive STP high */ |
| 233 | DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"), | 312 | DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"), |
| 234 | DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */ | 313 | DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */ |
| @@ -238,10 +317,232 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = { | |||
| 238 | DB8500_PIN("GPIO218_AH11", in_pd, "spi2"), /* RXD */ | 317 | DB8500_PIN("GPIO218_AH11", in_pd, "spi2"), /* RXD */ |
| 239 | DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */ | 318 | DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */ |
| 240 | DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */ | 319 | DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */ |
| 320 | /* SPI2 idle state */ | ||
| 321 | DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */ | ||
| 322 | DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */ | ||
| 323 | DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */ | ||
| 241 | /* SPI2 sleep state */ | 324 | /* SPI2 sleep state */ |
| 325 | DB8500_PIN_SLEEP("GPIO216_AG12", slpm_in_wkup_pdis, "spi2"), /* FRM */ | ||
| 242 | DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */ | 326 | DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */ |
| 243 | DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */ | 327 | DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */ |
| 244 | DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */ | 328 | DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */ |
| 329 | |||
| 330 | /* ske default state */ | ||
| 331 | DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"), | ||
| 332 | DB8500_PIN("GPIO153_B17", in_pd, "nmk-ske-keypad"), /* I7 */ | ||
| 333 | DB8500_PIN("GPIO154_C16", in_pd, "nmk-ske-keypad"), /* I6 */ | ||
| 334 | DB8500_PIN("GPIO155_C19", in_pd, "nmk-ske-keypad"), /* I5 */ | ||
| 335 | DB8500_PIN("GPIO156_C17", in_pd, "nmk-ske-keypad"), /* I4 */ | ||
| 336 | DB8500_PIN("GPIO161_D21", in_pd, "nmk-ske-keypad"), /* I3 */ | ||
| 337 | DB8500_PIN("GPIO162_D20", in_pd, "nmk-ske-keypad"), /* I2 */ | ||
| 338 | DB8500_PIN("GPIO163_C20", in_pd, "nmk-ske-keypad"), /* I1 */ | ||
| 339 | DB8500_PIN("GPIO164_B21", in_pd, "nmk-ske-keypad"), /* I0 */ | ||
| 340 | DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */ | ||
| 341 | DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */ | ||
| 342 | DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */ | ||
| 343 | DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */ | ||
| 344 | DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */ | ||
| 345 | DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */ | ||
| 346 | DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */ | ||
| 347 | DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */ | ||
| 348 | /* ske sleep state */ | ||
| 349 | DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */ | ||
| 350 | DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */ | ||
| 351 | DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */ | ||
| 352 | DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */ | ||
| 353 | DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */ | ||
| 354 | DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */ | ||
| 355 | DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */ | ||
| 356 | DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */ | ||
| 357 | DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */ | ||
| 358 | DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */ | ||
| 359 | DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */ | ||
| 360 | DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */ | ||
| 361 | DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */ | ||
| 362 | DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */ | ||
| 363 | DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */ | ||
| 364 | DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */ | ||
| 365 | |||
| 366 | /* STM APE pins states */ | ||
| 367 | DB8500_MUX_STATE("stmape_c_1", "stmape", | ||
| 368 | "stm", "ape_mipi34"), | ||
| 369 | DB8500_PIN_STATE("GPIO70_G5", in_nopull, | ||
| 370 | "stm", "ape_mipi34"), /* clk */ | ||
| 371 | DB8500_PIN_STATE("GPIO71_G4", in_nopull, | ||
| 372 | "stm", "ape_mipi34"), /* dat3 */ | ||
| 373 | DB8500_PIN_STATE("GPIO72_H4", in_nopull, | ||
| 374 | "stm", "ape_mipi34"), /* dat2 */ | ||
| 375 | DB8500_PIN_STATE("GPIO73_H3", in_nopull, | ||
| 376 | "stm", "ape_mipi34"), /* dat1 */ | ||
| 377 | DB8500_PIN_STATE("GPIO74_J3", in_nopull, | ||
| 378 | "stm", "ape_mipi34"), /* dat0 */ | ||
| 379 | |||
| 380 | DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis, | ||
| 381 | "stm", "ape_mipi34_sleep"), /* clk */ | ||
| 382 | DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis, | ||
| 383 | "stm", "ape_mipi34_sleep"), /* dat3 */ | ||
| 384 | DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis, | ||
| 385 | "stm", "ape_mipi34_sleep"), /* dat2 */ | ||
| 386 | DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis, | ||
| 387 | "stm", "ape_mipi34_sleep"), /* dat1 */ | ||
| 388 | DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis, | ||
| 389 | "stm", "ape_mipi34_sleep"), /* dat0 */ | ||
| 390 | |||
| 391 | DB8500_MUX_STATE("stmape_oc1_1", "stmape", | ||
| 392 | "stm", "ape_microsd"), | ||
| 393 | DB8500_PIN_STATE("GPIO23_AA4", in_nopull, | ||
| 394 | "stm", "ape_microsd"), /* clk */ | ||
| 395 | DB8500_PIN_STATE("GPIO25_Y4", in_nopull, | ||
| 396 | "stm", "ape_microsd"), /* dat0 */ | ||
| 397 | DB8500_PIN_STATE("GPIO26_Y2", in_nopull, | ||
| 398 | "stm", "ape_microsd"), /* dat1 */ | ||
| 399 | DB8500_PIN_STATE("GPIO27_AA2", in_nopull, | ||
| 400 | "stm", "ape_microsd"), /* dat2 */ | ||
| 401 | DB8500_PIN_STATE("GPIO28_AA1", in_nopull, | ||
| 402 | "stm", "ape_microsd"), /* dat3 */ | ||
| 403 | |||
| 404 | DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis, | ||
| 405 | "stm", "ape_microsd_sleep"), /* clk */ | ||
| 406 | DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis, | ||
| 407 | "stm", "ape_microsd_sleep"), /* dat0 */ | ||
| 408 | DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis, | ||
| 409 | "stm", "ape_microsd_sleep"), /* dat1 */ | ||
| 410 | DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis, | ||
| 411 | "stm", "ape_microsd_sleep"), /* dat2 */ | ||
| 412 | DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis, | ||
| 413 | "stm", "ape_microsd_sleep"), /* dat3 */ | ||
| 414 | |||
| 415 | /* STM Modem pins states */ | ||
| 416 | DB8500_MUX_STATE("stmmod_oc3_2", "stmmod", | ||
| 417 | "stm", "mod_mipi34"), | ||
| 418 | DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod", | ||
| 419 | "stm", "mod_mipi34"), | ||
| 420 | DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod", | ||
| 421 | "stm", "mod_mipi34"), | ||
| 422 | DB8500_PIN_STATE("GPIO70_G5", in_nopull, | ||
| 423 | "stm", "mod_mipi34"), /* clk */ | ||
| 424 | DB8500_PIN_STATE("GPIO71_G4", in_nopull, | ||
| 425 | "stm", "mod_mipi34"), /* dat3 */ | ||
| 426 | DB8500_PIN_STATE("GPIO72_H4", in_nopull, | ||
| 427 | "stm", "mod_mipi34"), /* dat2 */ | ||
| 428 | DB8500_PIN_STATE("GPIO73_H3", in_nopull, | ||
| 429 | "stm", "mod_mipi34"), /* dat1 */ | ||
| 430 | DB8500_PIN_STATE("GPIO74_J3", in_nopull, | ||
| 431 | "stm", "mod_mipi34"), /* dat0 */ | ||
| 432 | DB8500_PIN_STATE("GPIO75_H2", in_pu, | ||
| 433 | "stm", "mod_mipi34"), /* uartmod rx */ | ||
| 434 | DB8500_PIN_STATE("GPIO76_J2", out_lo, | ||
| 435 | "stm", "mod_mipi34"), /* uartmod tx */ | ||
| 436 | |||
| 437 | DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis, | ||
| 438 | "stm", "mod_mipi34_sleep"), /* clk */ | ||
| 439 | DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis, | ||
| 440 | "stm", "mod_mipi34_sleep"), /* dat3 */ | ||
| 441 | DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis, | ||
| 442 | "stm", "mod_mipi34_sleep"), /* dat2 */ | ||
| 443 | DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis, | ||
| 444 | "stm", "mod_mipi34_sleep"), /* dat1 */ | ||
| 445 | DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis, | ||
| 446 | "stm", "mod_mipi34_sleep"), /* dat0 */ | ||
| 447 | DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis, | ||
| 448 | "stm", "mod_mipi34_sleep"), /* uartmod rx */ | ||
| 449 | DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis, | ||
| 450 | "stm", "mod_mipi34_sleep"), /* uartmod tx */ | ||
| 451 | |||
| 452 | DB8500_MUX_STATE("stmmod_b_1", "stmmod", | ||
| 453 | "stm", "mod_microsd"), | ||
| 454 | DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod", | ||
| 455 | "stm", "mod_microsd"), | ||
| 456 | DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod", | ||
| 457 | "stm", "mod_microsd"), | ||
| 458 | DB8500_PIN_STATE("GPIO23_AA4", in_nopull, | ||
| 459 | "stm", "mod_microsd"), /* clk */ | ||
| 460 | DB8500_PIN_STATE("GPIO25_Y4", in_nopull, | ||
| 461 | "stm", "mod_microsd"), /* dat0 */ | ||
| 462 | DB8500_PIN_STATE("GPIO26_Y2", in_nopull, | ||
| 463 | "stm", "mod_microsd"), /* dat1 */ | ||
| 464 | DB8500_PIN_STATE("GPIO27_AA2", in_nopull, | ||
| 465 | "stm", "mod_microsd"), /* dat2 */ | ||
| 466 | DB8500_PIN_STATE("GPIO28_AA1", in_nopull, | ||
| 467 | "stm", "mod_microsd"), /* dat3 */ | ||
| 468 | DB8500_PIN_STATE("GPIO75_H2", in_pu, | ||
| 469 | "stm", "mod_microsd"), /* uartmod rx */ | ||
| 470 | DB8500_PIN_STATE("GPIO76_J2", out_lo, | ||
| 471 | "stm", "mod_microsd"), /* uartmod tx */ | ||
| 472 | |||
| 473 | DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis, | ||
| 474 | "stm", "mod_microsd_sleep"), /* clk */ | ||
| 475 | DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis, | ||
| 476 | "stm", "mod_microsd_sleep"), /* dat0 */ | ||
| 477 | DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis, | ||
| 478 | "stm", "mod_microsd_sleep"), /* dat1 */ | ||
| 479 | DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis, | ||
| 480 | "stm", "mod_microsd_sleep"), /* dat2 */ | ||
| 481 | DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis, | ||
| 482 | "stm", "mod_microsd_sleep"), /* dat3 */ | ||
| 483 | DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis, | ||
| 484 | "stm", "mod_microsd_sleep"), /* uartmod rx */ | ||
| 485 | DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis, | ||
| 486 | "stm", "mod_microsd_sleep"), /* uartmod tx */ | ||
| 487 | |||
| 488 | /* STM dual Modem/APE pins state */ | ||
| 489 | DB8500_MUX_STATE("stmmod_oc3_2", "stmmod", | ||
| 490 | "stm", "mod_mipi34_ape_mipi60"), | ||
| 491 | DB8500_MUX_STATE("stmape_c_2", "stmape", | ||
| 492 | "stm", "mod_mipi34_ape_mipi60"), | ||
| 493 | DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod", | ||
| 494 | "stm", "mod_mipi34_ape_mipi60"), | ||
| 495 | DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod", | ||
| 496 | "stm", "mod_mipi34_ape_mipi60"), | ||
| 497 | DB8500_PIN_STATE("GPIO70_G5", in_nopull, | ||
| 498 | "stm", "mod_mipi34_ape_mipi60"), /* clk */ | ||
| 499 | DB8500_PIN_STATE("GPIO71_G4", in_nopull, | ||
| 500 | "stm", "mod_mipi34_ape_mipi60"), /* dat3 */ | ||
| 501 | DB8500_PIN_STATE("GPIO72_H4", in_nopull, | ||
| 502 | "stm", "mod_mipi34_ape_mipi60"), /* dat2 */ | ||
| 503 | DB8500_PIN_STATE("GPIO73_H3", in_nopull, | ||
| 504 | "stm", "mod_mipi34_ape_mipi60"), /* dat1 */ | ||
| 505 | DB8500_PIN_STATE("GPIO74_J3", in_nopull, | ||
| 506 | "stm", "mod_mipi34_ape_mipi60"), /* dat0 */ | ||
| 507 | DB8500_PIN_STATE("GPIO75_H2", in_pu, | ||
| 508 | "stm", "mod_mipi34_ape_mipi60"), /* uartmod rx */ | ||
| 509 | DB8500_PIN_STATE("GPIO76_J2", out_lo, | ||
| 510 | "stm", "mod_mipi34_ape_mipi60"), /* uartmod tx */ | ||
| 511 | DB8500_PIN_STATE("GPIO155_C19", in_nopull, | ||
| 512 | "stm", "mod_mipi34_ape_mipi60"), /* clk */ | ||
| 513 | DB8500_PIN_STATE("GPIO156_C17", in_nopull, | ||
| 514 | "stm", "mod_mipi34_ape_mipi60"), /* dat3 */ | ||
| 515 | DB8500_PIN_STATE("GPIO157_A18", in_nopull, | ||
| 516 | "stm", "mod_mipi34_ape_mipi60"), /* dat2 */ | ||
| 517 | DB8500_PIN_STATE("GPIO158_C18", in_nopull, | ||
| 518 | "stm", "mod_mipi34_ape_mipi60"), /* dat1 */ | ||
| 519 | DB8500_PIN_STATE("GPIO159_B19", in_nopull, | ||
| 520 | "stm", "mod_mipi34_ape_mipi60"), /* dat0 */ | ||
| 521 | |||
| 522 | DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis, | ||
| 523 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */ | ||
| 524 | DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis, | ||
| 525 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */ | ||
| 526 | DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis, | ||
| 527 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */ | ||
| 528 | DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis, | ||
| 529 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */ | ||
| 530 | DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis, | ||
| 531 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */ | ||
| 532 | DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis, | ||
| 533 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod rx */ | ||
| 534 | DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis, | ||
| 535 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod tx */ | ||
| 536 | DB8500_PIN_STATE("GPIO155_C19", slpm_in_wkup_pdis, | ||
| 537 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */ | ||
| 538 | DB8500_PIN_STATE("GPIO156_C17", slpm_in_wkup_pdis, | ||
| 539 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */ | ||
| 540 | DB8500_PIN_STATE("GPIO157_A18", slpm_in_wkup_pdis, | ||
| 541 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */ | ||
| 542 | DB8500_PIN_STATE("GPIO158_C18", slpm_in_wkup_pdis, | ||
| 543 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */ | ||
| 544 | DB8500_PIN_STATE("GPIO159_B19", slpm_in_wkup_pdis, | ||
| 545 | "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */ | ||
| 245 | }; | 546 | }; |
| 246 | 547 | ||
| 247 | /* | 548 | /* |
| @@ -267,32 +568,48 @@ static struct pinctrl_map __initdata mop500_pinmap[] = { | |||
| 267 | DB8500_PIN_HOG("GPIO217_AH12", gpio_in_pu), | 568 | DB8500_PIN_HOG("GPIO217_AH12", gpio_in_pu), |
| 268 | /* Mux in UART1 and set the pull-ups */ | 569 | /* Mux in UART1 and set the pull-ups */ |
| 269 | DB8500_MUX_HOG("u1rxtx_a_1", "u1"), | 570 | DB8500_MUX_HOG("u1rxtx_a_1", "u1"), |
| 270 | DB8500_MUX_HOG("u1ctsrts_a_1", "u1"), | ||
| 271 | DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */ | 571 | DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */ |
| 272 | DB8500_PIN_HOG("GPIO5_AG6", out_hi), /* TXD */ | 572 | DB8500_PIN_HOG("GPIO5_AG6", out_hi), /* TXD */ |
| 273 | DB8500_PIN_HOG("GPIO6_AF6", in_pu), /* CTS */ | ||
| 274 | DB8500_PIN_HOG("GPIO7_AG5", out_hi), /* RTS */ | ||
| 275 | /* | 573 | /* |
| 276 | * Runtime stuff: make it possible to mux in the SKE keypad | 574 | * Runtime stuff: make it possible to mux in the SKE keypad |
| 277 | * and bias the pins | 575 | * and bias the pins |
| 278 | */ | 576 | */ |
| 279 | DB8500_MUX("kp_a_2", "kp", "ske"), | 577 | /* ske default state */ |
| 280 | DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */ | 578 | DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"), |
| 281 | DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */ | 579 | DB8500_PIN("GPIO153_B17", in_pu, "nmk-ske-keypad"), /* I7 */ |
| 282 | DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */ | 580 | DB8500_PIN("GPIO154_C16", in_pu, "nmk-ske-keypad"), /* I6 */ |
| 283 | DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */ | 581 | DB8500_PIN("GPIO155_C19", in_pu, "nmk-ske-keypad"), /* I5 */ |
| 284 | DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */ | 582 | DB8500_PIN("GPIO156_C17", in_pu, "nmk-ske-keypad"), /* I4 */ |
| 285 | DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */ | 583 | DB8500_PIN("GPIO161_D21", in_pu, "nmk-ske-keypad"), /* I3 */ |
| 286 | DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */ | 584 | DB8500_PIN("GPIO162_D20", in_pu, "nmk-ske-keypad"), /* I2 */ |
| 287 | DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */ | 585 | DB8500_PIN("GPIO163_C20", in_pu, "nmk-ske-keypad"), /* I1 */ |
| 288 | DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */ | 586 | DB8500_PIN("GPIO164_B21", in_pu, "nmk-ske-keypad"), /* I0 */ |
| 289 | DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */ | 587 | DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */ |
| 290 | DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */ | 588 | DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */ |
| 291 | DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */ | 589 | DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */ |
| 292 | DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */ | 590 | DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */ |
| 293 | DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */ | 591 | DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */ |
| 294 | DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */ | 592 | DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */ |
| 295 | DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */ | 593 | DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */ |
| 594 | DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */ | ||
| 595 | /* ske sleep state */ | ||
| 596 | DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */ | ||
| 597 | DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */ | ||
| 598 | DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */ | ||
| 599 | DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */ | ||
| 600 | DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */ | ||
| 601 | DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */ | ||
| 602 | DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */ | ||
| 603 | DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */ | ||
| 604 | DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */ | ||
| 605 | DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */ | ||
| 606 | DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */ | ||
| 607 | DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */ | ||
| 608 | DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */ | ||
| 609 | DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */ | ||
| 610 | DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */ | ||
| 611 | DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */ | ||
| 612 | |||
| 296 | /* Mux in and drive the SDI0 DAT31DIR line high at runtime */ | 613 | /* Mux in and drive the SDI0 DAT31DIR line high at runtime */ |
| 297 | DB8500_MUX("mc0dat31dir_a_1", "mc0", "sdi0"), | 614 | DB8500_MUX("mc0dat31dir_a_1", "mc0", "sdi0"), |
| 298 | DB8500_PIN("GPIO21_AB3", out_hi, "sdi0"), | 615 | DB8500_PIN("GPIO21_AB3", out_hi, "sdi0"), |
| @@ -395,28 +712,6 @@ static struct pinctrl_map __initdata hrefv60_pinmap[] = { | |||
| 395 | DB8500_PIN("GPIO217_AH12", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"), | 712 | DB8500_PIN("GPIO217_AH12", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"), |
| 396 | DB8500_PIN("GPIO145_C13", gpio_in_pd_slpm_gpio_nopull, "gpio-keys.0"), | 713 | DB8500_PIN("GPIO145_C13", gpio_in_pd_slpm_gpio_nopull, "gpio-keys.0"), |
| 397 | DB8500_PIN("GPIO139_C9", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"), | 714 | DB8500_PIN("GPIO139_C9", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"), |
| 398 | /* | ||
| 399 | * Make it possible to mux in the SKE keypad and bias the pins | ||
| 400 | * FIXME: what's the point with this on HREFv60? KP/SKE is already | ||
| 401 | * muxed in at another place! Enabling this will bork. | ||
| 402 | */ | ||
| 403 | DB8500_MUX("kp_a_2", "kp", "ske"), | ||
| 404 | DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */ | ||
| 405 | DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */ | ||
| 406 | DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */ | ||
| 407 | DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */ | ||
| 408 | DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */ | ||
| 409 | DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */ | ||
| 410 | DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */ | ||
| 411 | DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */ | ||
| 412 | DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */ | ||
| 413 | DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */ | ||
| 414 | DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */ | ||
| 415 | DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */ | ||
| 416 | DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */ | ||
| 417 | DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */ | ||
| 418 | DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */ | ||
| 419 | DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */ | ||
| 420 | }; | 715 | }; |
| 421 | 716 | ||
| 422 | static struct pinctrl_map __initdata u9500_pinmap[] = { | 717 | static struct pinctrl_map __initdata u9500_pinmap[] = { |
diff --git a/arch/arm/mach-vexpress/reset.c b/arch/arm/mach-vexpress/reset.c new file mode 100644 index 000000000000..465923aa3819 --- /dev/null +++ b/arch/arm/mach-vexpress/reset.c | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License version 2 as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * Copyright (C) 2012 ARM Limited | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/jiffies.h> | ||
| 15 | #include <linux/of.h> | ||
| 16 | #include <linux/of_device.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/stat.h> | ||
| 19 | #include <linux/vexpress.h> | ||
| 20 | |||
| 21 | static void vexpress_reset_do(struct device *dev, const char *what) | ||
| 22 | { | ||
| 23 | int err = -ENOENT; | ||
| 24 | struct vexpress_config_func *func = | ||
| 25 | vexpress_config_func_get_by_dev(dev); | ||
| 26 | |||
| 27 | if (func) { | ||
| 28 | unsigned long timeout; | ||
| 29 | |||
| 30 | err = vexpress_config_write(func, 0, 0); | ||
| 31 | |||
| 32 | timeout = jiffies + HZ; | ||
| 33 | while (time_before(jiffies, timeout)) | ||
| 34 | cpu_relax(); | ||
| 35 | } | ||
| 36 | |||
| 37 | dev_emerg(dev, "Unable to %s (%d)\n", what, err); | ||
| 38 | } | ||
| 39 | |||
| 40 | static struct device *vexpress_power_off_device; | ||
| 41 | |||
| 42 | void vexpress_power_off(void) | ||
| 43 | { | ||
| 44 | vexpress_reset_do(vexpress_power_off_device, "power off"); | ||
| 45 | } | ||
| 46 | |||
| 47 | static struct device *vexpress_restart_device; | ||
| 48 | |||
| 49 | void vexpress_restart(char str, const char *cmd) | ||
| 50 | { | ||
| 51 | vexpress_reset_do(vexpress_restart_device, "restart"); | ||
| 52 | } | ||
| 53 | |||
| 54 | static ssize_t vexpress_reset_active_show(struct device *dev, | ||
| 55 | struct device_attribute *attr, char *buf) | ||
| 56 | { | ||
| 57 | return sprintf(buf, "%d\n", vexpress_restart_device == dev); | ||
| 58 | } | ||
| 59 | |||
| 60 | static ssize_t vexpress_reset_active_store(struct device *dev, | ||
| 61 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 62 | { | ||
| 63 | long value; | ||
| 64 | int err = kstrtol(buf, 0, &value); | ||
| 65 | |||
| 66 | if (!err && value) | ||
| 67 | vexpress_restart_device = dev; | ||
| 68 | |||
| 69 | return err ? err : count; | ||
| 70 | } | ||
| 71 | |||
| 72 | DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show, | ||
| 73 | vexpress_reset_active_store); | ||
| 74 | |||
| 75 | |||
| 76 | enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT }; | ||
| 77 | |||
| 78 | static struct of_device_id vexpress_reset_of_match[] = { | ||
| 79 | { | ||
| 80 | .compatible = "arm,vexpress-reset", | ||
| 81 | .data = (void *)FUNC_RESET, | ||
| 82 | }, { | ||
| 83 | .compatible = "arm,vexpress-shutdown", | ||
| 84 | .data = (void *)FUNC_SHUTDOWN | ||
| 85 | }, { | ||
| 86 | .compatible = "arm,vexpress-reboot", | ||
| 87 | .data = (void *)FUNC_REBOOT | ||
| 88 | }, | ||
| 89 | {} | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int vexpress_reset_probe(struct platform_device *pdev) | ||
| 93 | { | ||
| 94 | enum vexpress_reset_func func; | ||
| 95 | const struct of_device_id *match = | ||
| 96 | of_match_device(vexpress_reset_of_match, &pdev->dev); | ||
| 97 | |||
| 98 | if (match) | ||
| 99 | func = (enum vexpress_reset_func)match->data; | ||
| 100 | else | ||
| 101 | func = pdev->id_entry->driver_data; | ||
| 102 | |||
| 103 | switch (func) { | ||
| 104 | case FUNC_SHUTDOWN: | ||
| 105 | vexpress_power_off_device = &pdev->dev; | ||
| 106 | break; | ||
| 107 | case FUNC_RESET: | ||
| 108 | if (!vexpress_restart_device) | ||
| 109 | vexpress_restart_device = &pdev->dev; | ||
| 110 | device_create_file(&pdev->dev, &dev_attr_active); | ||
| 111 | break; | ||
| 112 | case FUNC_REBOOT: | ||
| 113 | vexpress_restart_device = &pdev->dev; | ||
| 114 | device_create_file(&pdev->dev, &dev_attr_active); | ||
| 115 | break; | ||
| 116 | }; | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static const struct platform_device_id vexpress_reset_id_table[] = { | ||
| 122 | { .name = "vexpress-reset", .driver_data = FUNC_RESET, }, | ||
| 123 | { .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, }, | ||
| 124 | { .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, }, | ||
| 125 | {} | ||
| 126 | }; | ||
| 127 | |||
| 128 | static struct platform_driver vexpress_reset_driver = { | ||
| 129 | .probe = vexpress_reset_probe, | ||
| 130 | .driver = { | ||
| 131 | .name = "vexpress-reset", | ||
| 132 | .of_match_table = vexpress_reset_of_match, | ||
| 133 | }, | ||
| 134 | .id_table = vexpress_reset_id_table, | ||
| 135 | }; | ||
| 136 | |||
| 137 | static int __init vexpress_reset_init(void) | ||
| 138 | { | ||
| 139 | return platform_driver_register(&vexpress_reset_driver); | ||
| 140 | } | ||
| 141 | device_initcall(vexpress_reset_init); | ||
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index 1fe6917f6a2a..dfd8b7af8c7a 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h | |||
| @@ -48,6 +48,7 @@ struct samsung_gpio_cfg; | |||
| 48 | * @config: special function and pull-resistor control information. | 48 | * @config: special function and pull-resistor control information. |
| 49 | * @lock: Lock for exclusive access to this gpio bank. | 49 | * @lock: Lock for exclusive access to this gpio bank. |
| 50 | * @pm_save: Save information for suspend/resume support. | 50 | * @pm_save: Save information for suspend/resume support. |
| 51 | * @bitmap_gpio_int: Bitmap for representing GPIO interrupt or not. | ||
| 51 | * | 52 | * |
| 52 | * This wrapper provides the necessary information for the Samsung | 53 | * This wrapper provides the necessary information for the Samsung |
| 53 | * specific gpios being registered with gpiolib. | 54 | * specific gpios being registered with gpiolib. |
| @@ -71,6 +72,7 @@ struct samsung_gpio_chip { | |||
| 71 | #ifdef CONFIG_PM | 72 | #ifdef CONFIG_PM |
| 72 | u32 pm_save[4]; | 73 | u32 pm_save[4]; |
| 73 | #endif | 74 | #endif |
| 75 | u32 bitmap_gpio_int; | ||
| 74 | }; | 76 | }; |
| 75 | 77 | ||
| 76 | static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc) | 78 | static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc) |
diff --git a/arch/arm/plat-samsung/s5p-irq-gpioint.c b/arch/arm/plat-samsung/s5p-irq-gpioint.c index 23557d30e44c..bae56131a50a 100644 --- a/arch/arm/plat-samsung/s5p-irq-gpioint.c +++ b/arch/arm/plat-samsung/s5p-irq-gpioint.c | |||
| @@ -185,7 +185,7 @@ int __init s5p_register_gpio_interrupt(int pin) | |||
| 185 | 185 | ||
| 186 | /* check if the group has been already registered */ | 186 | /* check if the group has been already registered */ |
| 187 | if (my_chip->irq_base) | 187 | if (my_chip->irq_base) |
| 188 | return my_chip->irq_base + offset; | 188 | goto success; |
| 189 | 189 | ||
| 190 | /* register gpio group */ | 190 | /* register gpio group */ |
| 191 | ret = s5p_gpioint_add(my_chip); | 191 | ret = s5p_gpioint_add(my_chip); |
| @@ -193,9 +193,13 @@ int __init s5p_register_gpio_interrupt(int pin) | |||
| 193 | my_chip->chip.to_irq = samsung_gpiolib_to_irq; | 193 | my_chip->chip.to_irq = samsung_gpiolib_to_irq; |
| 194 | printk(KERN_INFO "Registered interrupt support for gpio group %d.\n", | 194 | printk(KERN_INFO "Registered interrupt support for gpio group %d.\n", |
| 195 | group); | 195 | group); |
| 196 | return my_chip->irq_base + offset; | 196 | goto success; |
| 197 | } | 197 | } |
| 198 | return ret; | 198 | return ret; |
| 199 | success: | ||
| 200 | my_chip->bitmap_gpio_int |= BIT(offset); | ||
| 201 | |||
| 202 | return my_chip->irq_base + offset; | ||
| 199 | } | 203 | } |
| 200 | 204 | ||
| 201 | int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups) | 205 | int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups) |
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 88f41e51565b..01f7fe955590 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c | |||
| @@ -42,12 +42,6 @@ | |||
| 42 | #include <plat/gpio-fns.h> | 42 | #include <plat/gpio-fns.h> |
| 43 | #include <plat/pm.h> | 43 | #include <plat/pm.h> |
| 44 | 44 | ||
| 45 | #ifndef DEBUG_GPIO | ||
| 46 | #define gpio_dbg(x...) do { } while (0) | ||
| 47 | #else | ||
| 48 | #define gpio_dbg(x...) printk(KERN_DEBUG x) | ||
| 49 | #endif | ||
| 50 | |||
| 51 | int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip, | 45 | int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip, |
| 52 | unsigned int off, samsung_gpio_pull_t pull) | 46 | unsigned int off, samsung_gpio_pull_t pull) |
| 53 | { | 47 | { |
| @@ -596,10 +590,13 @@ static int samsung_gpiolib_4bit_input(struct gpio_chip *chip, | |||
| 596 | unsigned long con; | 590 | unsigned long con; |
| 597 | 591 | ||
| 598 | con = __raw_readl(base + GPIOCON_OFF); | 592 | con = __raw_readl(base + GPIOCON_OFF); |
| 599 | con &= ~(0xf << con_4bit_shift(offset)); | 593 | if (ourchip->bitmap_gpio_int & BIT(offset)) |
| 594 | con |= 0xf << con_4bit_shift(offset); | ||
| 595 | else | ||
| 596 | con &= ~(0xf << con_4bit_shift(offset)); | ||
| 600 | __raw_writel(con, base + GPIOCON_OFF); | 597 | __raw_writel(con, base + GPIOCON_OFF); |
| 601 | 598 | ||
| 602 | gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con); | 599 | pr_debug("%s: %p: CON now %08lx\n", __func__, base, con); |
| 603 | 600 | ||
| 604 | return 0; | 601 | return 0; |
| 605 | } | 602 | } |
| @@ -627,7 +624,7 @@ static int samsung_gpiolib_4bit_output(struct gpio_chip *chip, | |||
| 627 | __raw_writel(con, base + GPIOCON_OFF); | 624 | __raw_writel(con, base + GPIOCON_OFF); |
| 628 | __raw_writel(dat, base + GPIODAT_OFF); | 625 | __raw_writel(dat, base + GPIODAT_OFF); |
| 629 | 626 | ||
| 630 | gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); | 627 | pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); |
| 631 | 628 | ||
| 632 | return 0; | 629 | return 0; |
| 633 | } | 630 | } |
| @@ -671,7 +668,7 @@ static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip, | |||
| 671 | con &= ~(0xf << con_4bit_shift(offset)); | 668 | con &= ~(0xf << con_4bit_shift(offset)); |
| 672 | __raw_writel(con, regcon); | 669 | __raw_writel(con, regcon); |
| 673 | 670 | ||
| 674 | gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con); | 671 | pr_debug("%s: %p: CON %08lx\n", __func__, base, con); |
| 675 | 672 | ||
| 676 | return 0; | 673 | return 0; |
| 677 | } | 674 | } |
| @@ -706,7 +703,7 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip, | |||
| 706 | __raw_writel(con, regcon); | 703 | __raw_writel(con, regcon); |
| 707 | __raw_writel(dat, base + GPIODAT_OFF); | 704 | __raw_writel(dat, base + GPIODAT_OFF); |
| 708 | 705 | ||
| 709 | gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); | 706 | pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); |
| 710 | 707 | ||
| 711 | return 0; | 708 | return 0; |
| 712 | } | 709 | } |
| @@ -926,10 +923,10 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip) | |||
| 926 | #ifdef CONFIG_PM | 923 | #ifdef CONFIG_PM |
| 927 | if (chip->pm != NULL) { | 924 | if (chip->pm != NULL) { |
| 928 | if (!chip->pm->save || !chip->pm->resume) | 925 | if (!chip->pm->save || !chip->pm->resume) |
| 929 | printk(KERN_ERR "gpio: %s has missing PM functions\n", | 926 | pr_err("gpio: %s has missing PM functions\n", |
| 930 | gc->label); | 927 | gc->label); |
| 931 | } else | 928 | } else |
| 932 | printk(KERN_ERR "gpio: %s has no PM function\n", gc->label); | 929 | pr_err("gpio: %s has no PM function\n", gc->label); |
| 933 | #endif | 930 | #endif |
| 934 | 931 | ||
| 935 | /* gpiochip_add() prints own failure message on error. */ | 932 | /* gpiochip_add() prints own failure message on error. */ |
| @@ -1081,6 +1078,8 @@ static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip | |||
| 1081 | if ((base != NULL) && (chip->base == NULL)) | 1078 | if ((base != NULL) && (chip->base == NULL)) |
| 1082 | chip->base = base + ((i) * 0x20); | 1079 | chip->base = base + ((i) * 0x20); |
| 1083 | 1080 | ||
| 1081 | chip->bitmap_gpio_int = 0; | ||
| 1082 | |||
| 1084 | samsung_gpiolib_add(chip); | 1083 | samsung_gpiolib_add(chip); |
| 1085 | } | 1084 | } |
| 1086 | } | 1085 | } |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 4800d4c2a7b7..32f238f3caea 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -1208,6 +1208,14 @@ config SENSORS_TWL4030_MADC | |||
| 1208 | This driver can also be built as a module. If so it will be called | 1208 | This driver can also be built as a module. If so it will be called |
| 1209 | twl4030-madc-hwmon. | 1209 | twl4030-madc-hwmon. |
| 1210 | 1210 | ||
| 1211 | config SENSORS_VEXPRESS | ||
| 1212 | tristate "Versatile Express" | ||
| 1213 | depends on VEXPRESS_CONFIG | ||
| 1214 | help | ||
| 1215 | This driver provides support for hardware sensors available on | ||
| 1216 | the ARM Ltd's Versatile Express platform. It can provide wide | ||
| 1217 | range of information like temperature, power, energy. | ||
| 1218 | |||
| 1211 | config SENSORS_VIA_CPUTEMP | 1219 | config SENSORS_VIA_CPUTEMP |
| 1212 | tristate "VIA CPU temperature sensor" | 1220 | tristate "VIA CPU temperature sensor" |
| 1213 | depends on X86 | 1221 | depends on X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index a930f0997d25..5da287443f6c 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
| @@ -122,6 +122,7 @@ obj-$(CONFIG_SENSORS_TMP102) += tmp102.o | |||
| 122 | obj-$(CONFIG_SENSORS_TMP401) += tmp401.o | 122 | obj-$(CONFIG_SENSORS_TMP401) += tmp401.o |
| 123 | obj-$(CONFIG_SENSORS_TMP421) += tmp421.o | 123 | obj-$(CONFIG_SENSORS_TMP421) += tmp421.o |
| 124 | obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o | 124 | obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o |
| 125 | obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o | ||
| 125 | obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o | 126 | obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o |
| 126 | obj-$(CONFIG_SENSORS_VIA686A) += via686a.o | 127 | obj-$(CONFIG_SENSORS_VIA686A) += via686a.o |
| 127 | obj-$(CONFIG_SENSORS_VT1211) += vt1211.o | 128 | obj-$(CONFIG_SENSORS_VT1211) += vt1211.o |
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c new file mode 100644 index 000000000000..59fd1268e58a --- /dev/null +++ b/drivers/hwmon/vexpress.c | |||
| @@ -0,0 +1,229 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License version 2 as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * Copyright (C) 2012 ARM Limited | ||
| 12 | */ | ||
| 13 | |||
| 14 | #define DRVNAME "vexpress-hwmon" | ||
| 15 | #define pr_fmt(fmt) DRVNAME ": " fmt | ||
| 16 | |||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/err.h> | ||
| 19 | #include <linux/hwmon.h> | ||
| 20 | #include <linux/hwmon-sysfs.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/of_device.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/vexpress.h> | ||
| 25 | |||
| 26 | struct vexpress_hwmon_data { | ||
| 27 | struct device *hwmon_dev; | ||
| 28 | struct vexpress_config_func *func; | ||
| 29 | }; | ||
| 30 | |||
| 31 | static ssize_t vexpress_hwmon_name_show(struct device *dev, | ||
| 32 | struct device_attribute *dev_attr, char *buffer) | ||
| 33 | { | ||
| 34 | const char *compatible = of_get_property(dev->of_node, "compatible", | ||
| 35 | NULL); | ||
| 36 | |||
| 37 | return sprintf(buffer, "%s\n", compatible); | ||
| 38 | } | ||
| 39 | |||
| 40 | static ssize_t vexpress_hwmon_label_show(struct device *dev, | ||
| 41 | struct device_attribute *dev_attr, char *buffer) | ||
| 42 | { | ||
| 43 | const char *label = of_get_property(dev->of_node, "label", NULL); | ||
| 44 | |||
| 45 | if (!label) | ||
| 46 | return -ENOENT; | ||
| 47 | |||
| 48 | return snprintf(buffer, PAGE_SIZE, "%s\n", label); | ||
| 49 | } | ||
| 50 | |||
| 51 | static ssize_t vexpress_hwmon_u32_show(struct device *dev, | ||
| 52 | struct device_attribute *dev_attr, char *buffer) | ||
| 53 | { | ||
| 54 | struct vexpress_hwmon_data *data = dev_get_drvdata(dev); | ||
| 55 | int err; | ||
| 56 | u32 value; | ||
| 57 | |||
| 58 | err = vexpress_config_read(data->func, 0, &value); | ||
| 59 | if (err) | ||
| 60 | return err; | ||
| 61 | |||
| 62 | return snprintf(buffer, PAGE_SIZE, "%u\n", value / | ||
| 63 | to_sensor_dev_attr(dev_attr)->index); | ||
| 64 | } | ||
| 65 | |||
| 66 | static ssize_t vexpress_hwmon_u64_show(struct device *dev, | ||
| 67 | struct device_attribute *dev_attr, char *buffer) | ||
| 68 | { | ||
| 69 | struct vexpress_hwmon_data *data = dev_get_drvdata(dev); | ||
| 70 | int err; | ||
| 71 | u32 value_hi, value_lo; | ||
| 72 | |||
| 73 | err = vexpress_config_read(data->func, 0, &value_lo); | ||
| 74 | if (err) | ||
| 75 | return err; | ||
| 76 | |||
| 77 | err = vexpress_config_read(data->func, 1, &value_hi); | ||
| 78 | if (err) | ||
| 79 | return err; | ||
| 80 | |||
| 81 | return snprintf(buffer, PAGE_SIZE, "%llu\n", | ||
| 82 | div_u64(((u64)value_hi << 32) | value_lo, | ||
| 83 | to_sensor_dev_attr(dev_attr)->index)); | ||
| 84 | } | ||
| 85 | |||
| 86 | static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL); | ||
| 87 | |||
| 88 | #define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \ | ||
| 89 | struct attribute *vexpress_hwmon_attrs_##_name[] = { \ | ||
| 90 | &dev_attr_name.attr, \ | ||
| 91 | &dev_attr_##_label_attr.attr, \ | ||
| 92 | &sensor_dev_attr_##_input_attr.dev_attr.attr, \ | ||
| 93 | NULL \ | ||
| 94 | } | ||
| 95 | |||
| 96 | #if !defined(CONFIG_REGULATOR_VEXPRESS) | ||
| 97 | static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | ||
| 98 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show, | ||
| 99 | NULL, 1000); | ||
| 100 | static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input); | ||
| 101 | static struct attribute_group vexpress_hwmon_group_volt = { | ||
| 102 | .attrs = vexpress_hwmon_attrs_volt, | ||
| 103 | }; | ||
| 104 | #endif | ||
| 105 | |||
| 106 | static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | ||
| 107 | static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show, | ||
| 108 | NULL, 1000); | ||
| 109 | static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input); | ||
| 110 | static struct attribute_group vexpress_hwmon_group_amp = { | ||
| 111 | .attrs = vexpress_hwmon_attrs_amp, | ||
| 112 | }; | ||
| 113 | |||
| 114 | static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | ||
| 115 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show, | ||
| 116 | NULL, 1000); | ||
| 117 | static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input); | ||
| 118 | static struct attribute_group vexpress_hwmon_group_temp = { | ||
| 119 | .attrs = vexpress_hwmon_attrs_temp, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | ||
| 123 | static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show, | ||
| 124 | NULL, 1); | ||
| 125 | static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input); | ||
| 126 | static struct attribute_group vexpress_hwmon_group_power = { | ||
| 127 | .attrs = vexpress_hwmon_attrs_power, | ||
| 128 | }; | ||
| 129 | |||
| 130 | static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | ||
| 131 | static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show, | ||
| 132 | NULL, 1); | ||
| 133 | static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input); | ||
| 134 | static struct attribute_group vexpress_hwmon_group_energy = { | ||
| 135 | .attrs = vexpress_hwmon_attrs_energy, | ||
| 136 | }; | ||
| 137 | |||
| 138 | static struct of_device_id vexpress_hwmon_of_match[] = { | ||
| 139 | #if !defined(CONFIG_REGULATOR_VEXPRESS) | ||
| 140 | { | ||
| 141 | .compatible = "arm,vexpress-volt", | ||
| 142 | .data = &vexpress_hwmon_group_volt, | ||
| 143 | }, | ||
| 144 | #endif | ||
| 145 | { | ||
| 146 | .compatible = "arm,vexpress-amp", | ||
| 147 | .data = &vexpress_hwmon_group_amp, | ||
| 148 | }, { | ||
| 149 | .compatible = "arm,vexpress-temp", | ||
| 150 | .data = &vexpress_hwmon_group_temp, | ||
| 151 | }, { | ||
| 152 | .compatible = "arm,vexpress-power", | ||
| 153 | .data = &vexpress_hwmon_group_power, | ||
| 154 | }, { | ||
| 155 | .compatible = "arm,vexpress-energy", | ||
| 156 | .data = &vexpress_hwmon_group_energy, | ||
| 157 | }, | ||
| 158 | {} | ||
| 159 | }; | ||
| 160 | MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match); | ||
| 161 | |||
| 162 | static int vexpress_hwmon_probe(struct platform_device *pdev) | ||
| 163 | { | ||
| 164 | int err; | ||
| 165 | const struct of_device_id *match; | ||
| 166 | struct vexpress_hwmon_data *data; | ||
| 167 | |||
| 168 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
| 169 | if (!data) | ||
| 170 | return -ENOMEM; | ||
| 171 | platform_set_drvdata(pdev, data); | ||
| 172 | |||
| 173 | match = of_match_device(vexpress_hwmon_of_match, &pdev->dev); | ||
| 174 | if (!match) | ||
| 175 | return -ENODEV; | ||
| 176 | |||
| 177 | data->func = vexpress_config_func_get_by_dev(&pdev->dev); | ||
| 178 | if (!data->func) | ||
| 179 | return -ENODEV; | ||
| 180 | |||
| 181 | err = sysfs_create_group(&pdev->dev.kobj, match->data); | ||
| 182 | if (err) | ||
| 183 | goto error; | ||
| 184 | |||
| 185 | data->hwmon_dev = hwmon_device_register(&pdev->dev); | ||
| 186 | if (IS_ERR(data->hwmon_dev)) { | ||
| 187 | err = PTR_ERR(data->hwmon_dev); | ||
| 188 | goto error; | ||
| 189 | } | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | |||
| 193 | error: | ||
| 194 | sysfs_remove_group(&pdev->dev.kobj, match->data); | ||
| 195 | vexpress_config_func_put(data->func); | ||
| 196 | return err; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int __devexit vexpress_hwmon_remove(struct platform_device *pdev) | ||
| 200 | { | ||
| 201 | struct vexpress_hwmon_data *data = platform_get_drvdata(pdev); | ||
| 202 | const struct of_device_id *match; | ||
| 203 | |||
| 204 | hwmon_device_unregister(data->hwmon_dev); | ||
| 205 | |||
| 206 | match = of_match_device(vexpress_hwmon_of_match, &pdev->dev); | ||
| 207 | sysfs_remove_group(&pdev->dev.kobj, match->data); | ||
| 208 | |||
| 209 | vexpress_config_func_put(data->func); | ||
| 210 | |||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static struct platform_driver vexpress_hwmon_driver = { | ||
| 215 | .probe = vexpress_hwmon_probe, | ||
| 216 | .remove = __devexit_p(vexpress_hwmon_remove), | ||
| 217 | .driver = { | ||
| 218 | .name = DRVNAME, | ||
| 219 | .owner = THIS_MODULE, | ||
| 220 | .of_match_table = vexpress_hwmon_of_match, | ||
| 221 | }, | ||
| 222 | }; | ||
| 223 | |||
| 224 | module_platform_driver(vexpress_hwmon_driver); | ||
| 225 | |||
| 226 | MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>"); | ||
| 227 | MODULE_DESCRIPTION("Versatile Express hwmon sensors driver"); | ||
| 228 | MODULE_LICENSE("GPL"); | ||
| 229 | MODULE_ALIAS("platform:vexpress-hwmon"); | ||
